00001
00016
#include <stdio.h>
00017
#include <stdlib.h>
00018
#include <string.h>
00019
00020
#include "copyrigh.h"
00021
#include "wattcp.h"
00022
#include "wdpmi.h"
00023
#include "strings.h"
00024
#include "language.h"
00025
#include "sock_ini.h"
00026
#include "loopback.h"
00027
#include "cpumodel.h"
00028
#include "misc.h"
00029
#include "timer.h"
00030
#include "profile.h"
00031
#include "rs232.h"
00032
#include "split.h"
00033
#include "ip4_in.h"
00034
#include "ip6_in.h"
00035
#include "bsddbug.h"
00036
#include "pcmulti.h"
00037
#include "pcqueue.h"
00038
#include "pcconfig.h"
00039
#include "pcdbug.h"
00040
#include "pctcp.h"
00041
#include "pcstat.h"
00042
#include "pcpkt.h"
00043
#include "pcsed.h"
00044
#include "pppoe.h"
00045
00046
00047
00048
00049 mac_address
_eth_addr;
00050 mac_address
_eth_brdcast;
00051 mac_address
_eth_loop_addr;
00052 mac_address
_eth_real_addr;
00053 BYTE _eth_mac_len;
00054 BOOL
_eth_is_init = FALSE;
00055 BOOL
_ip_recursion = FALSE;
00056 BOOL
_eth_ndis3pkt = FALSE;
00057 BOOL
_eth_SwsVpkt = FALSE;
00058 BOOL
_eth_airpcap = FALSE;
00060
const char *_eth_not_init =
"Packet driver not initialised";
00061
00065 struct _eth_last_info
_eth_last;
00066
00088 void *(*_eth_recv_hook) (
WORD *type) = NULL;
00089 int (*_eth_recv_peek) (
void *mac_buf) = NULL;
00090 int (*_eth_xmit_hook) (
const void *mac_buf,
unsigned len) = NULL;
00091
00096 static void *(*mac_tx_format)(
void *mac_buf,
const void *mac_dest,
WORD type);
00097
static int (*mac_transmit) (
const void *mac_buf,
WORD len);
00098
00099
static WORD proto;
00100
static void *nw_pkt;
00101
00102
00112
#if (DOSX & (DOS4GW|X32VM))
00113
#define TX_BUF() ((union link_Packet*) pkt_tx_buf())
00114
00115
#elif (DOSX & DJGPP)
00116
static union link_Packet outbuf;
00117
00118
#define TX_BUF() (_pkt_inf && _pkt_inf->use_near_ptr ? \
00119
(union link_Packet*)pkt_tx_buf() : \
00120
(&outbuf))
00121
#else
00122
static union link_Packet outbuf;
00123
#define TX_BUF() (&outbuf)
00124
#endif
00125
00131 void *
_eth_formatpacket (
const void *mac_dest,
WORD eth_type)
00132 {
00133 SIO_TRACE ((
"_eth_formatpacket, type %04X", eth_type));
00134
00135 nw_pkt = (*mac_tx_format) (TX_BUF(), mac_dest, eth_type);
00136
return (nw_pkt);
00137 }
00138
00139
00140
#if defined(USE_LOOPBACK)
00141
00150 static int send_loopback (
link_Packet pkt, BOOL is_ip6,
unsigned *err_line)
00151 {
00152
struct pkt_ringbuf *q;
00153
const in_Header *ip;
00154
int ip_len;
00155
00156 SIO_TRACE ((
"send_loopback"));
00157
00158
if (!
_pkt_inf)
00159 {
00160 *err_line = __LINE__;
00161
goto drop_it;
00162 }
00163
00164
00165
00166 ip = (
in_Header*) ((
BYTE*)&pkt +
_pkt_ip_ofs);
00167 ip_len = loopback_device ((
in_Header*)ip);
00168
00169 q = &
_pkt_inf->
pkt_queue;
00170
00171
if (!q || ip_len > (
int)_mtu)
00172 {
00173 *err_line = __LINE__;
00174
goto drop_it;
00175 }
00176
00177
if (ip_len > 0)
00178 {
00179
#if defined(USE_FAST_PKT)
00180
00181
00182
00183
if (pkt_buffers_used() >=
_pkt_inf->
pkt_queue.
num_buf - 1)
00184 {
00185 *err_line = __LINE__;
00186
goto drop_it;
00187 }
00188 {
00189
char tx_buf [ETH_MAX];
00190
unsigned len = ip_len;
00191
00192
00193
00194
if (!
_pktserial)
00195 {
00196
void *data = (*mac_tx_format) (tx_buf,
_eth_addr,
00197 is_ip6 ? IP6_TYPE : IP4_TYPE);
00198 memcpy (MAC_SRC(data), &
_eth_loop_addr,
sizeof(mac_address));
00199 memcpy (data, ip, ip_len);
00200 len +=
_pkt_ip_ofs;
00201 }
00202
else
00203 memcpy (tx_buf, ip, ip_len);
00204
00205
if (!pkt_append_recv(tx_buf, len))
00206 {
00207 *err_line = __LINE__;
00208
goto drop_it;
00209 }
00210 }
00211
#elif defined(WIN32)
00212
struct pkt_rx_element *head;
00213
00214 ENTER_CRIT();
00215
if (pktq_in_index(q) == q->out_index)
00216 {
00217 q->num_drop++;
00218 LEAVE_CRIT();
00219 *err_line = __LINE__;
00220
goto drop_it;
00221 }
00222
00223 head = (
struct pkt_rx_element*) pktq_in_buf (q);
00224 head->rx_length =
_pkt_ip_ofs + ip_len;
00225 gettimeofday (&head->tstamp_put, NULL);
00226
00227
00228
00229
if (!
_pktserial)
00230 {
00231
void *data = (*mac_tx_format) (&head->rx_buf,
_eth_addr,
00232 is_ip6 ? IP6_TYPE : IP4_TYPE);
00233 memcpy (MAC_SRC(data), &
_eth_loop_addr,
sizeof(mac_address));
00234 memcpy (data, ip, ip_len);
00235 }
00236
else
00237 memcpy (head, ip, ip_len);
00238
00239
00240
00241 q->in_index = pktq_in_index (q);
00242
00243 LEAVE_CRIT();
00244
00245
#else
00246
union link_Packet *head;
00247
00248 DISABLE();
00249
if (pktq_in_index(q) == q->out_index)
00250 {
00251 q->num_drop++;
00252 ENABLE();
00253 *err_line = __LINE__;
00254
goto drop_it;
00255 }
00256
00257 head = (
union link_Packet*) pktq_in_buf (q);
00258
00259
00260
00261
if (!
_pktserial)
00262 {
00263
void *data = (*mac_tx_format) (head,
_eth_addr,
00264 is_ip6 ? IP6_TYPE : IP4_TYPE);
00265 memcpy (MAC_SRC(data), &
_eth_loop_addr,
sizeof(mac_address));
00266 memcpy (data, ip, ip_len);
00267 }
00268
else
00269 memcpy (head, ip, ip_len);
00270
00271
00272
00273 q->in_index = pktq_in_index (q);
00274
00275 ENABLE();
00276
#endif
00277
}
00278 *err_line = 0;
00279
return (ip_len +
_pkt_ip_ofs);
00280
00281 drop_it:
00282
00283
00284
00285
if (is_ip6)
00286 STAT (ip6stats.ip6s_odropped++);
00287
else STAT (ip4stats.ips_odropped++);
00288
return (0);
00289 }
00290
#endif
00291
00292
00302 int _eth_send (
WORD len,
const void *sock,
const char *file,
unsigned line)
00303 {
00304
#if defined(USE_DEBUG) || defined(USE_LOOPBACK)
00305
unsigned errline = 0;
00306
#endif
00307
BOOL send_loopback_to_driver = FALSE;
00308
00309 SIO_TRACE ((
"_eth_send, len %d", len));
00310
00311
if (!
_eth_is_init)
00312 {
00313 SOCK_ERRNO (ENETDOWN);
00314
return (0);
00315 }
00316
00317
#if defined(WIN32)
00318
00319
00320
00321
00322
00323
if (loopback_mode & LBACK_MODE_WINSOCK)
00324 send_loopback_to_driver = TRUE;
00325
#endif
00326
00327
if (proto == IP4_TYPE)
00328 {
00329
00330
00331
const in_Header *ip = (
const in_Header*) nw_pkt;
00332
00333
if (!send_loopback_to_driver &&
00334 _ip4_is_loopback_addr(intel(ip->
destination)))
00335 {
00336
#if defined(USE_LOOPBACK)
00337
len =
send_loopback (*TX_BUF(), FALSE, &errline);
00338
#else
00339
STAT (ip4stats.ips_odropped++);
00340
#endif
00341
goto debug_tx;
00342 }
00343 }
00344
00345
#if defined(USE_IPV6)
00346
else if (proto == IP6_TYPE)
00347 {
00348
const in6_Header *ip = (
const in6_Header*) nw_pkt;
00349
00350
if (!send_loopback_to_driver &&
00351 IN6_IS_ADDR_LOOPBACK(&ip->
destination))
00352 {
00353
#if defined(USE_LOOPBACK)
00354
len =
send_loopback (*TX_BUF(), TRUE, &errline);
00355
#else
00356
STAT (ip6stats.ip6s_odropped++);
00357
#endif
00358
goto debug_tx;
00359 }
00360 }
00361
#endif
00362
00363
#if defined(USE_PPPOE)
00364
else if (proto == PPPOE_SESS_TYPE)
00365 {
00366 pppoe_Packet *pppoe = (pppoe_Packet*) TX_BUF()->eth.data;
00367
00368 pppoe->length = intel16 (len+2);
00369 len += PPPOE_HDR_SIZE + 2;
00370 }
00371
#endif
00372
00373
00374
00375
#if (DOSX) && !defined(WIN32)
00376
if (_dbugxmit &&
has_rdtsc)
00377 get_rdtsc2 (&
_eth_last.tx.tstamp);
00378
#endif
00379
00380
00381
00382
00383
00384
if (_eth_xmit_hook)
00385 len = (*_eth_xmit_hook) (TX_BUF(), len +
_pkt_ip_ofs);
00386
else len = (*mac_transmit) (TX_BUF(), len +
_pkt_ip_ofs);
00387
00388
if (len >
_pkt_ip_ofs)
00389 {
00390
_eth_last.tx.size = len;
00391 len -=
_pkt_ip_ofs;
00392 }
00393
else
00394 {
00395
if (debug_on)
00396 outs (
"Tx failed. ");
00397 len = 0;
00398
_eth_last.tx.size = 0;
00399 }
00400
00401 debug_tx:
00402
00403
#if defined(NEED_PKT_SPLIT)
00404
pkt_split_mac_out (TX_BUF());
00405
#endif
00406
00407
#if defined(USE_STATISTICS)
00408
if (len > 0)
00409
update_out_stat();
00410
#endif
00411
00412
#if defined(USE_DEBUG)
00413
if (_dbugxmit)
00414 (*_dbugxmit) (sock, (
const in_Header*)nw_pkt, file, line);
00415
00416
if (len == 0)
00417 {
00418
if (errline && !send_loopback_to_driver)
00419 dbug_printf (
"** Error in loopback handler, line %u\n", errline);
00420
else
00421 {
00422
const char err[] =
"** Transmit fault **\n";
00423
00424 TCP_CONSOLE_MSG (1, (err));
00425 dbug_printf (err);
00426 }
00427 }
00428
#else
00429
ARGSUSED (sock);
00430 ARGSUSED (file);
00431 ARGSUSED (line);
00432
#endif
00433
00434
00435
00436
if (proto == PPPOE_SESS_TYPE ||
_pktdevclass == PDCLASS_ETHER)
00437
_pkt_ip_ofs =
sizeof(
eth_Header);
00438
return (len);
00439 }
00440
00444 static void *
eth_mac_format (
void *mac_buf,
const void *mac_dest,
WORD type)
00445 {
00446
union link_Packet *buf = (
union link_Packet*) mac_buf;
00447
00448 SIO_TRACE ((
"eth_mac_format"));
00449
00450 proto = type;
00451
00452
00453
00454 memset (&buf->eth.data[0], 0, ETH_MIN-
sizeof(
eth_Header));
00455
00456
#if defined(USE_PPPOE)
00457
if (type == IP4_TYPE &&
pppoe_is_up(mac_dest))
00458 {
00459 proto = PPPOE_SESS_TYPE;
00460
return pppoe_mac_format (buf);
00461 }
00462
#endif
00463
00464
if (mac_dest)
00465 memcpy (&buf->eth.head.destination, mac_dest,
sizeof(mac_address));
00466 memcpy (&buf->eth.head.source, &
_eth_addr,
sizeof(mac_address));
00467
00468 buf->eth.head.type = type;
00469
return (&buf->eth.data);
00470 }
00471
00475 static void *
tok_mac_format (
void *mac_buf,
const void *mac_dest,
WORD type)
00476 {
00477
union link_Packet *buf = (
union link_Packet*) mac_buf;
00478
00479 SIO_TRACE ((
"tok_mac_format"));
00480
00481
00482
00483
if (mac_dest)
00484 memcpy (&buf->tok.head.destination, mac_dest,
sizeof(mac_address));
00485 memcpy (&buf->tok.head.source, &
_eth_addr,
sizeof(mac_address));
00486
00487
#if 0
00488
00489
00490
if (
_pktdevclass == PDCLASSS_TOKEN_RIF)
00491 ((
void)0);
00492
#endif
00493
00494 buf->tok.head.accessCtrl = TR_AC;
00495 buf->tok.head.frameCtrl = TR_FC;
00496 buf->tok.head.DSAP = TR_DSAP;
00497 buf->tok.head.SSAP = TR_SSAP;
00498 buf->tok.head.ctrl = TR_CTRL;
00499 buf->tok.head.org[0] = TR_ORG;
00500 buf->tok.head.org[1] = TR_ORG;
00501 buf->tok.head.org[2] = TR_ORG;
00502 buf->tok.head.type = type;
00503 proto = type;
00504
return (&buf->tok.data);
00505 }
00506
00510 static void *
fddi_mac_format (
void *mac_buf,
const void *mac_dest,
WORD type)
00511 {
00512
union link_Packet *buf = (
union link_Packet*) mac_buf;
00513
00514 SIO_TRACE ((
"fddi_mac_format"));
00515
00516 memset (&buf->fddi.data[0], 0, FDDI_MIN-
sizeof(
fddi_Header));
00517
if (mac_dest)
00518 memcpy (&buf->fddi.head.destination, mac_dest,
sizeof(mac_address));
00519 memcpy (&buf->fddi.head.source, &
_eth_addr,
sizeof(mac_address));
00520
00521 buf->fddi.head.frameCtrl = FDDI_FC;
00522 buf->fddi.head.DSAP = FDDI_DSAP;
00523 buf->fddi.head.SSAP = FDDI_SSAP;
00524 buf->fddi.head.ctrl = FDDI_CTRL;
00525 buf->fddi.head.org[0] = FDDI_ORG;
00526 buf->fddi.head.org[1] = FDDI_ORG;
00527 buf->fddi.head.org[2] = FDDI_ORG;
00528 buf->fddi.head.type = type;
00529 proto = type;
00530
return (&buf->fddi.data);
00531 }
00532
00536 static void *
arcnet_mac_format (
void *mac_buf,
const void *mac_dest,
WORD type)
00537 {
00538
union link_Packet *buf = (
union link_Packet*) mac_buf;
00539
BYTE dest;
00540
00541
if (type == IP4_TYPE)
00542 type = ARCNET_IP_1201;
00543
else if (type == IP6_TYPE)
00544 type = ARCNET_IP6;
00545
else if (type == ARP_TYPE)
00546 type = ARCNET_ARP_1201;
00547
else if (type == RARP_TYPE)
00548 type = ARCNET_RARP_1201;
00549
00550
if (!mac_dest || !memcmp(mac_dest, &
_eth_brdcast,
sizeof(
_eth_brdcast)))
00551 dest = 0x00;
00552
else dest = *(
BYTE*)mac_dest;
00553
00554 buf->arc.head.source =
_eth_addr[0];
00555 buf->arc.head.destination = dest;
00556 buf->arc.head.type = (
BYTE) type;
00557 buf->arc.head.flags = 0;
00558 buf->arc.head.sequence = 0;
00559
#if 0
00560 buf->arc.head.type2 = type;
00561 buf->arc.head.flags2 = 0;
00562 buf->arc.head.sequence2 = 0;
00563
#endif
00564
00565 proto = (
BYTE) type;
00566
return (
void*) ((
BYTE*)&buf->arc + ARC_HDRLEN);
00567 }
00568
00573 static void *
null_mac_format (
void *mac_buf,
const void *mac_dest,
WORD type)
00574 {
00575
union link_Packet *buf = (
union link_Packet*) mac_buf;
00576
00577 SIO_TRACE ((
"null_mac_format"));
00578
00579 memset (&buf->ip.head, 0,
sizeof(buf->ip.head));
00580 ARGSUSED (mac_dest);
00581 ARGSUSED (type);
00582 proto = IP4_TYPE;
00583
return (
void*) (&buf->ip.head);
00584 }
00585
00590 static int eth_mac_xmit (
const void *buf,
WORD len)
00591 {
00592 SIO_TRACE ((
"eth_mac_xmit, len %d", len));
00593
00594
if (len < ETH_MIN)
00595 len = ETH_MIN;
00596
else if (len > ETH_MAX)
00597 len = ETH_MAX;
00598
00599
return pkt_send (buf, len);
00600 }
00601
00602
static int fddi_mac_xmit (
const void *buf,
WORD len)
00603 {
00604 SIO_TRACE ((
"fddi_mac_xmit, len %d", len));
00605
00606
if (len < FDDI_MIN)
00607 len = FDDI_MIN;
00608
else if (len > FDDI_MAX)
00609 len = FDDI_MAX;
00610
00611
return pkt_send (buf, len);
00612 }
00613
00614
static int arcnet_mac_xmit (
const void *buf,
WORD len)
00615 {
00616 SIO_TRACE ((
"arcnet_mac_xmit, len %d", len));
00617
00618
if (len < ARCNET_MIN)
00619 len = ARCNET_MIN;
00620
else if (len > ARCNET_MAX)
00621 len = ARCNET_MAX;
00622
00623
return pkt_send (buf, len);
00624 }
00625
00626
static int tok_mac_xmit (
const void *buf,
WORD len)
00627 {
00628 SIO_TRACE ((
"tok_mac_xmit, len %d", len));
00629
00630
if (len > TOK_MAX)
00631 len = TOK_MAX;
00632
return pkt_send (buf, len);
00633 }
00634
00635
static int null_mac_xmit (
const void *buf,
WORD len)
00636 {
00637 SIO_TRACE ((
"null_mac_xmit, len %d", len));
00638
00639
return pkt_send (buf, len);
00640 }
00641
00642
00648 int _eth_init (
void)
00649 {
00650
int rc;
00651
00652 SIO_TRACE ((
"_eth_init"));
00653
00654
if (
_eth_is_init)
00655
return (0);
00656
00657 rc =
pkt_eth_init (&
_eth_addr);
00658
if (rc)
00659
return (rc);
00660
00661
00662
00663 memcpy (
_eth_real_addr,
_eth_addr,
sizeof(
_eth_real_addr));
00664
00665
switch (
_pktdevclass)
00666 {
00667
case PDCLASS_ETHER:
00668
mac_tx_format =
eth_mac_format;
00669 mac_transmit =
eth_mac_xmit;
00670
break;
00671
case PDCLASS_TOKEN:
00672
case PDCLASS_TOKEN_RIF:
00673
mac_tx_format =
tok_mac_format;
00674 mac_transmit = tok_mac_xmit;
00675
break;
00676
case PDCLASS_FDDI:
00677
mac_tx_format =
fddi_mac_format;
00678 mac_transmit = fddi_mac_xmit;
00679
break;
00680
case PDCLASS_ARCNET:
00681
mac_tx_format =
arcnet_mac_format;
00682 mac_transmit = arcnet_mac_xmit;
00683
break;
00684
case PDCLASS_SLIP:
00685
case PDCLASS_PPP:
00686
case PDCLASS_AX25:
00687
mac_tx_format =
null_mac_format;
00688 mac_transmit = null_mac_xmit;
00689
break;
00690
default:
00691 outsnl (_LANG(
"No supported driver class found"));
00692
return (WERR_NO_DRIVER);
00693 }
00694
00695 memset (TX_BUF(), 0,
sizeof(
union link_Packet));
00696 memset (&
_eth_brdcast, 0xFF,
sizeof(
_eth_brdcast));
00697
_eth_loop_addr[0] = 0xCF;
00698
pkt_buf_wipe();
00699
00700
if (!
_eth_get_hwtype(NULL, &
_eth_mac_len))
00701
_eth_mac_len =
sizeof(
eth_address);
00702
00703
#if !defined(WIN32)
00704
if (!strcmp(_pktdrvrname,
"NDIS3PKT"))
00705
_eth_ndis3pkt = TRUE;
00706
00707
else if (!strcmp(_pktdrvrname,
"SwsVpkt"))
00708
_eth_SwsVpkt = TRUE;
00709
#endif
00710
00711
_eth_is_init = TRUE;
00712 RUNDOWN_ADD (
_eth_release, 10);
00713
00714
return (0);
00715 }
00716
00720 int _eth_set_addr (
const void *addr)
00721 {
00722 SIO_TRACE ((
"_eth_set_addr"));
00723
00724
if (
_pktserial ||
_pktdevclass == PDCLASS_ARCNET)
00725
return (1);
00726
00727
if (
pkt_set_addr(addr))
00728 {
00729 memcpy (
_eth_addr, addr,
sizeof(
_eth_addr));
00730
return (1);
00731 }
00732
return (0);
00733 }
00734
00735
00740 BYTE _eth_get_hwtype (
BYTE *hwtype,
BYTE *hwlen)
00741 {
00742 SIO_TRACE ((
"_eth_get_hwtype"));
00743
00744
if (
_pktdevclass == PDCLASS_ETHER)
00745 {
00746
if (hwlen) *hwlen =
sizeof (
eth_address);
00747
if (hwtype) *hwtype = HW_TYPE_ETHER;
00748
return (HW_TYPE_ETHER);
00749 }
00750
if (
_pktdevclass == PDCLASS_FDDI)
00751 {
00752
if (hwlen) *hwlen =
sizeof (
fddi_address);
00753
if (hwtype) *hwtype = HW_TYPE_FDDI;
00754
return (HW_TYPE_FDDI);
00755 }
00756
if (
_pktdevclass == PDCLASS_TOKEN ||
_pktdevclass == PDCLASS_TOKEN_RIF)
00757 {
00758
if (hwlen) *hwlen =
sizeof (
tok_address);
00759
if (hwtype) *hwtype = HW_TYPE_TOKEN;
00760
return (HW_TYPE_TOKEN);
00761 }
00762
if (
_pktdevclass == PDCLASS_AX25)
00763 {
00764
if (hwlen) *hwlen =
sizeof (
ax25_address);
00765
if (hwtype) *hwtype = HW_TYPE_AX25;
00766
return (HW_TYPE_AX25);
00767 }
00768
if (
_pktdevclass == PDCLASS_ARCNET)
00769 {
00770
if (hwlen) *hwlen =
sizeof (
arcnet_address);
00771
if (hwtype) *hwtype = HW_TYPE_ARCNET;
00772
return (HW_TYPE_ARCNET);
00773 }
00774
return (0);
00775 }
00776
00777
00781 void _eth_free (
const void *pkt)
00782 {
00783 SIO_TRACE ((
"_eth_free"));
00784
00785
if (
_eth_recv_hook)
00786
return;
00787
00788
if (!pkt)
00789
pkt_buf_wipe();
00790
else pkt_free_pkt (pkt);
00791 }
00792
00793
00799
#define RCF DSAP
00800
00801
#define TR_IS_SROUTED(th) ((th)->source[0] & 0x80)
00802
#define TR_IS_BROADCAST(th) (((intel16((th)->RCF) & 0xE000) >> 13) >= 4)
00803
#define TR_RIF_LENGTH(th) ((intel16((th)->RCF) & 0x1F00) >> 8)
00804
00805
#define TR_MAC_SIZE (2+2+2*sizeof(mac_address))
00806
00807
static void fix_tok_head (
tok_Header **trp)
00808 {
00809
tok_Header *tr = *trp;
00810
00811
#if defined(USE_DEBUG)
00812
const BYTE *raw = (
const BYTE*)tr;
00813
int i;
00814
00815 dbug_write (
"TR raw: ");
00816
for (i = 0; i < 50; i++)
00817 dbug_printf (
"%02X ", raw[i]);
00818 dbug_write (
"\n");
00819
#endif
00820
00821 SIO_TRACE ((
"fix_tok_head"));
00822
00823
if (TR_IS_SROUTED(tr))
00824 {
00825
int rlen = TR_RIF_LENGTH (tr);
00826
00827 tr->
source[0] &= 0x7F;
00828
00829
00830
00831
if (TR_IS_BROADCAST(tr))
00832 tr->
destination[0] |= 1;
00833
00834
00835
00836 memmove ((
BYTE*)tr + rlen, tr, TR_MAC_SIZE);
00837 *trp = (
tok_Header*) ((
BYTE*)tr + rlen);
00838 }
00839 }
00840
00841
00842
00843
00844
00845
static BOOL fix_arc_head (
const arcnet_Header *head,
WORD *type)
00846 {
00847
#if defined(USE_DEBUG)
00848
const BYTE *raw = (
const BYTE*)head;
00849
int i;
00850
00851 dbug_write (
"ARC raw: ");
00852
for (i = 0; i < 50; i++)
00853 dbug_printf (
"%02X ", raw[i]);
00854 dbug_write (
"\n");
00855
#endif
00856
00857 *type = head->
type;
00858
00859
00860
00861
if (*type == ARCNET_IP_1051 || *type == ARCNET_IP_1201)
00862 *type = IP4_TYPE;
00863
if (*type == ARCNET_ARP_1051 || *type == ARCNET_ARP_1201)
00864 *type = ARP_TYPE;
00865
00866
if (head->
flags == 0xFF ||
00867 (*type != IP4_TYPE &&
00868 *type != ARP_TYPE))
00869
return (FALSE);
00870
return (TRUE);
00871 }
00872
00884 static union link_Packet *
poll_recv_queue (
WORD *type)
00885 {
00886
#if defined(USE_FAST_PKT) || defined(WIN32)
00887
struct pkt_rx_element *buf;
00888
#endif
00889
struct pkt_ringbuf *q = &
_pkt_inf->
pkt_queue;
00890
union link_Packet *pkt;
00891
struct in_Header *ip;
00892
00893 SIO_TRACE ((
"poll_recv_queue"));
00894
00895 ASSERT_PKT_INF (NULL);
00896
00897
#if defined(USE_DEBUG)
00898
#if defined(USE_FAST_PKT)
00899
if (!pktq_far_check(q))
00900
#else
00901
if (!pktq_check(q))
00902
#endif
00903
{
00904 fprintf (stderr,
"%s: pkt-queue destroyed!\n", __FILE__);
00905 exit (-1);
00906 }
00907
#endif
00908
00909
#if defined(WIN32)
00910
buf = pkt_poll_recv();
00911
if (!buf)
00912
return (NULL);
00913
00914 PROFILE_RECV ((
uint64*)&buf->tstamp_put, (
uint64*)&buf->tstamp_get);
00915
_eth_last.rx.size = buf->rx_length;
00916
_eth_last.rx.tstamp.lo = 0UL;
00917
_eth_last.rx.tstamp.hi = 0UL;
00918 pkt = (
link_Packet*) &buf->rx_buf[0];
00919
00920
#elif defined(USE_FAST_PKT)
00921
buf = pkt_poll_recv();
00922
if (!buf)
00923
return (NULL);
00924
00925 PROFILE_RECV ((
uint64*)buf->tstamp_put, (
uint64*)buf->tstamp_get);
00926 pkt = (
link_Packet*) buf->rx_buf;
00927
_eth_last.rx.size = buf->rx_length_1;
00928
_eth_last.rx.tstamp.lo = buf->tstamp_put[0];
00929
_eth_last.rx.tstamp.hi = buf->tstamp_put[1];
00930
00931
#else
00932
if (!pktq_queued(q))
00933
return (NULL);
00934
00935 pkt = (
link_Packet*) pktq_out_buf (q);
00936
_eth_last.rx.size = ETH_MAX;
00937
_eth_last.rx.tstamp.lo = 0UL;
00938
_eth_last.rx.tstamp.hi = 0UL;
00939
#endif
00940
00941
00942
if (
_pktserial)
00943 {
00944 ip = &pkt->ip.head;
00945 *type = (ip->ver == 4) ? IP4_TYPE : IP6_TYPE;
00946
return (pkt);
00947 }
00948
00949
if (
_pktdevclass == PDCLASS_TOKEN ||
_pktdevclass == PDCLASS_TOKEN_RIF)
00950 {
00951
tok_Header *tr = &pkt->tok.head;
00952
00953 fix_tok_head (&tr);
00954 *type = tr->
type;
00955
return (
union link_Packet*) tr;
00956 }
00957
00958
if (
_pktdevclass == PDCLASS_ARCNET)
00959 {
00960
arcnet_Packet *arc = &pkt->arc;
00961
00962
if (!fix_arc_head(&arc->
head, type))
00963 {
00964 DEBUG_RX (NULL, &arc->
data);
00965
pkt_free_pkt (pkt);
00966 pkt = NULL;
00967 }
00968
return (pkt);
00969 }
00970
00971
if (
_pktdevclass == PDCLASS_FDDI)
00972 {
00973
fddi_Packet *fddi = &pkt->fddi;
00974
00975 *type = fddi->
head.
type;
00976
return (pkt);
00977 }
00978
00979
00980
00981 *type = pkt->eth.head.type;
00982 ARGSUSED (q);
00983
return (pkt);
00984 }
00985
00986
00987
00988
00989
00990 static void fix_llc_head (
void **mac)
00991 {
00992 SIO_TRACE ((
"fix_llc_head"));
00993
#if 1
00994
DEBUG_RX (NULL, *mac);
00995
_eth_free (*mac);
00996 *mac = NULL;
00997
#else
00998
01000
#endif
01001
}
01002
01003
01016 void *
_eth_arrived (
WORD *type_ptr, BOOL *broadcast)
01017 {
01018
union link_Packet *pkt;
01019 mac_address *dst;
01020
void *ret = NULL;
01021 BOOL is_bcast = FALSE;
01022
WORD type = 0;
01023
01024 SIO_TRACE ((
"_eth_arrived"));
01025
01026
if (!
_eth_is_init)
01027
return (NULL);
01028
01029
if (
_eth_recv_hook)
01030 pkt = (
union link_Packet*) (*_eth_recv_hook) (&type);
01031
else pkt =
poll_recv_queue (&type);
01032
01033
if (!pkt)
01034
return (NULL);
01035
01036
if (_eth_recv_peek && !(*_eth_recv_peek)(pkt))
01037 {
01038
_eth_free (pkt);
01039
return (NULL);
01040 }
01041
01042
01043
01044
01045
if (
_ip_recursion &&
01046 (type == IP4_TYPE || type == IP6_TYPE || type == PPPOE_SESS_TYPE))
01047 {
01049 STAT (macstats.
num_ip_recurse++);
01050
_eth_free (pkt);
01051
return (NULL);
01052 }
01053
01054
if (
_pktserial)
01055 {
01056 dst = NULL;
01057 ret = (
void*) &pkt->ip;
01058 }
01059
else if (
_pktdevclass == PDCLASS_TOKEN ||
_pktdevclass == PDCLASS_TOKEN_RIF)
01060 {
01061 dst = &pkt->tok.head.destination;
01062 ret = (
void*) &pkt->tok.data;
01063 }
01064
else if (
_pktdevclass == PDCLASS_FDDI)
01065 {
01066 dst = &pkt->fddi.head.destination;
01067 ret = (
void*) &pkt->fddi.data;
01068 }
01069
else if (
_pktdevclass == PDCLASS_ARCNET)
01070 {
01071 dst = (mac_address*) &pkt->arc.head.destination;
01072 ret = (
void*) ((
BYTE*)pkt + ARC_HDRLEN);
01073 }
01074
else
01075 {
01076 dst = &pkt->eth.head.destination;
01077 ret = (
void*) &pkt->eth.data;
01078 }
01079
01080
#if defined(NEED_PKT_SPLIT)
01081
pkt_split_mac_in (pkt);
01082
#endif
01083
01084
#if defined(USE_STATISTICS)
01085
update_in_stat();
01086
#endif
01087
01088
#if defined(NEED_PKT_SPLIT) && defined(USE_DEBUG) && 0
01089 pkt_print_split_in();
01090
#endif
01091
01092
01093
01094
if (
_pktdevclass != PDCLASS_ARCNET)
01095 {
01096
if (dst && !memcmp(dst, &
_eth_brdcast,
sizeof(
_eth_brdcast)))
01097 is_bcast = TRUE;
01098
01099
if (intel16(type) < 0x600)
01100
fix_llc_head (&ret);
01101 }
01102
else if (dst && *(
BYTE*)dst == 0)
01103 {
01104 is_bcast = TRUE;
01105 }
01106
01107
if (type_ptr)
01108 *type_ptr = type;
01109
01110
if (broadcast)
01111 *broadcast = is_bcast;
01112
01113
return (ret);
01114 }
01115
01116
01117
#if defined(USE_DEBUG)
01118
01121 void *
_eth_mac_hdr (
const in_Header *ip)
01122 {
01123 SIO_TRACE ((
"_eth_mac_hdr"));
01124
01125
if (!
_pktserial)
01126
return (
void*) ((
BYTE*)ip -
_pkt_ip_ofs);
01127
01128 (*_printf) (
"Illegal use of `_eth_mac_hdr()' for class %d\n",
01129
_pktdevclass);
01130 exit (-1);
01131
01132
return (NULL);
01133 }
01134
01138 void *
_eth_mac_dst (
const in_Header *ip)
01139 {
01140
const union link_Packet *pkt;
01141
01142 SIO_TRACE ((
"_eth_mac_dst"));
01143
01144 pkt = (
const union link_Packet*) ((
BYTE*)ip -
_pkt_ip_ofs);
01145
01146
if (
_pktdevclass == PDCLASS_ETHER)
01147
return (
void*) &pkt->eth.head.destination;
01148
01149
if (
_pktdevclass == PDCLASS_TOKEN ||
_pktdevclass == PDCLASS_TOKEN_RIF)
01150
return (
void*) &pkt->tok.head.destination;
01151
01152
if (
_pktdevclass == PDCLASS_FDDI)
01153
return (
void*) &pkt->fddi.head.destination;
01154
01155
if (
_pktdevclass == PDCLASS_ARCNET)
01156
return (
void*) &pkt->arc.head.destination;
01157
01158 (*_printf) (
"Illegal use of `_eth_mac_dst()' for class %d\n",
01159
_pktdevclass);
01160 exit (-1);
01161
01162
return (NULL);
01163 }
01164
01168 void *
_eth_mac_src (
const in_Header *ip)
01169 {
01170
const union link_Packet *pkt;
01171
01172 SIO_TRACE ((
"_eth_mac_src"));
01173
01174 pkt = (
const union link_Packet*) ((
BYTE*)ip -
_pkt_ip_ofs);
01175
01176
if (
_pktdevclass == PDCLASS_ETHER)
01177
return (
void*) &pkt->eth.head.source;
01178
01179
if (
_pktdevclass == PDCLASS_TOKEN ||
_pktdevclass == PDCLASS_TOKEN_RIF)
01180
return (
void*) &pkt->tok.head.source;
01181
01182
if (
_pktdevclass == PDCLASS_FDDI)
01183
return (
void*) &pkt->fddi.head.source;
01184
01185
if (
_pktdevclass == PDCLASS_ARCNET)
01186
return (
void*) &pkt->arc.head.source;
01187
01188 (*_printf) (
"Illegal use of `_eth_mac_src()' for class %d\n",
01189
_pktdevclass);
01190 exit (-1);
01191
01192
return (NULL);
01193 }
01194
01198 WORD _eth_mac_typ (
const in_Header *ip)
01199 {
01200
const union link_Packet *pkt;
01201
01202 SIO_TRACE ((
"_eth_mac_typ"));
01203
01204 pkt = (
const union link_Packet*) ((
BYTE*)ip -
_pkt_ip_ofs);
01205
01206
if (
_pktdevclass == PDCLASS_ETHER)
01207
return (pkt->eth.head.type);
01208
01209
if (
_pktdevclass == PDCLASS_TOKEN ||
_pktdevclass == PDCLASS_TOKEN_RIF)
01210
return (pkt->tok.head.type);
01211
01212
if (
_pktdevclass == PDCLASS_FDDI)
01213
return (pkt->fddi.head.type);
01214
01215
if (
_pktdevclass == PDCLASS_ARCNET)
01216
return (pkt->arc.head.type);
01217
01218 (*_printf) (
"Illegal use of `_eth_mac_typ()' for class %d\n",
01219
_pktdevclass);
01220 exit (-1);
01221
01222
return (0);
01223 }
01224
#endif
01225
01226
01227
01228
01229
01230
01231
#if defined(USE_MULTICAST)
01232
01238 BOOL
_eth_join_mcast_group (
const struct MultiCast *mc)
01239 {
01240
eth_address list [IPMULTI_SIZE];
01241
int i, len, nextentry;
01242 BOOL is_mcast1, is_mcast2, is_promis;
01243
01244 SIO_TRACE ((
"_eth_join_mcast_group"));
01245
01246
01247
01248
01249
#if defined(WIN32)
01250
is_mcast1 = (
_pkt_rxmode &
RXMODE_MULTICAST1);
01251 is_mcast2 = (
_pkt_rxmode &
RXMODE_MULTICAST2);
01252 is_promis = (
_pkt_rxmode &
RXMODE_PROMISCOUS);
01253
#else
01254
is_mcast1 = (
_pkt_rxmode >=
RXMODE_MULTICAST1);
01255 is_mcast2 = (
_pkt_rxmode >=
RXMODE_MULTICAST2);
01256 is_promis = (
_pkt_rxmode >=
RXMODE_PROMISCOUS);
01257
#endif
01258
01259
if (is_mcast2 || is_promis)
01260
return (TRUE);
01261
01262
if (!is_mcast1)
01263 {
01264 is_mcast1 =
pkt_set_rcv_mode(
RXMODE_MULTICAST1);
01265
if (!is_mcast1)
01266 is_promis =
pkt_set_rcv_mode(
RXMODE_PROMISCOUS);
01267
if (is_promis)
01268
return (TRUE);
01269
if (!is_mcast1 && !is_promis)
01270
return (FALSE);
01271 }
01272
01273 len =
sizeof(list);
01274
if (!
pkt_get_multicast_list (list, &len))
01275 {
01276
01277
01278
if (
_pkt_errno == PDERR_NO_MULTICAST)
01279
return pkt_set_rcv_mode (
RXMODE_MULTICAST2);
01280
return (FALSE);
01281 }
01282
01283
01284
01285
for (i = 0; i < len / SIZEOF(list[0]); i++)
01286
if (!memcmp(list[i], &mc->
ethaddr,
sizeof(list[0])))
01287
return (TRUE);
01288
01289
if (len > 0)
01290 nextentry = len /
sizeof(list[0]);
01291
else nextentry = 0;
01292
01293 memcpy (&list[nextentry], &mc->
ethaddr,
sizeof(
eth_address));
01294 len +=
sizeof (list[0]);
01295
01296
if (!
pkt_set_multicast_list((
const eth_address*)&list,len))
01297 {
01298
01299
01300
if (
_pkt_errno == PDERR_NO_SPACE ||
01301
_pkt_errno == PDERR_NO_MULTICAST)
01302
return pkt_set_rcv_mode (
RXMODE_MULTICAST2);
01303
return (FALSE);
01304 }
01305
return (TRUE);
01306 }
01307
01314 BOOL
_eth_leave_mcast_group (
const struct MultiCast *mc)
01315 {
01316
eth_address list[IPMULTI_SIZE];
01317
int i, len, idx;
01318
01319 SIO_TRACE ((
"_eth_leave_mcast_group"));
01320
01321
01322
01323
01324
01325
01326
01327
#if defined(WIN32)
01328
if (
_pkt_rxmode &
RXMODE_MULTICAST2)
01329
return (TRUE);
01330
#else
01331
if (
_pkt_rxmode >=
RXMODE_MULTICAST2)
01332
return (TRUE);
01333
#endif
01334
01335
01336
01337 len =
sizeof(list);
01338
if (!
pkt_get_multicast_list (list, &len))
01339
return (FALSE);
01340
01341
01342
01343
for (i = 0, idx = -1; i < len/SIZEOF(list[0]); i++)
01344
if (!memcmp(list[i],&mc->
ethaddr,
sizeof(list[0])))
01345 idx = i;
01346
01347
01348
01349
if (idx == -1)
01350
return (TRUE);
01351
01352
01353
01354
01355
if (idx+1 < len/SIZEOF(list[0]))
01356 memmove (&list[idx], &list[idx+1], len-(idx+1)*
sizeof(list[0]));
01357
01358 len -=
sizeof(list[0]);
01359
01360
if (!
pkt_set_multicast_list((
const eth_address*)&list, len))
01361 {
01362
01363
01364
if (
_pkt_errno == PDERR_NO_SPACE ||
01365
_pkt_errno == PDERR_NO_MULTICAST)
01366
return pkt_set_rcv_mode (
RXMODE_MULTICAST2);
01367
return (FALSE);
01368 }
01369
return (TRUE);
01370 }
01371
#endif
01372
01377
#include "nochkstk.h"
01378
01382 void _eth_release (
void)
01383 {
01384
if (!
_eth_is_init)
01385
return;
01386
01387
01388
01389
if (!
_watt_fatal_error)
01390 {
01391
if (!
_pktserial)
01392 {
01393
if (memcmp(&
_eth_addr, &
_eth_real_addr,
sizeof(
_eth_addr)))
01394
pkt_set_addr (&
_eth_real_addr);
01395
01396
#if defined(USE_MULTICAST) || defined(USE_IPV6)
01397
if (
_pkt_rxmode0 > -1 &&
_pkt_rxmode0 !=
_pkt_rxmode)
01398
pkt_set_rcv_mode (
_pkt_rxmode0);
01399
#endif
01400
}
01401
01402
#if defined(USE_DEBUG)
01403
if (debug_on > 0)
01404 {
01405
DWORD drops =
pkt_dropped();
01406
if (drops)
01407 (*_printf) (
"%lu packets dropped\n", drops);
01408 }
01409
#endif
01410
}
01411
_eth_is_init = FALSE;
01412
pkt_release();
01413 }
01414