Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

SRC/pcsed.c

Go to the documentation of this file.
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 /* !!fix-me: Should allow the largest possible MAC-address to be used; 00047 * An AX-25 address is 7 bytes. 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; /* protocol set in _eth_formatpacket() */ 00100 static void *nw_pkt; /* where network protocol packet starts */ 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 /* Call loopback handler with IP-packet 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 * Don't let pkt_receiver() modify the queue while testing/copying. 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 /* Enqueue packet to head of input IP-queue. 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) /* queue is full, drop it */ 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 /* Enqueue packet to head of input IP-queue. 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 /* Update queue head index 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) /* queue is full, drop it */ 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 /* Enqueue packet to head of input IP-queue. 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 /* Update queue head index 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 * Maybe this should be an input counter 00284 */ 00285 if (is_ip6) 00286 STAT (ip6stats.ip6s_odropped++); 00287 else STAT (ip4stats.ips_odropped++); 00288 return (0); 00289 } 00290 #endif /* USE_LOOPBACK */ 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) /* GvB 2002-09, Lets us run without a working eth */ 00312 { 00313 SOCK_ERRNO (ENETDOWN); 00314 return (0); 00315 } 00316 00317 #if defined(WIN32) 00318 /* 00319 * Just a test for now; send it to the driver and look what happens.... 00320 * They go on the wire and not to the Winsock loopback provider. 00321 * No surprise here yet. 00322 */ 00323 if (loopback_mode & LBACK_MODE_WINSOCK) 00324 send_loopback_to_driver = TRUE; 00325 #endif 00326 00327 if (proto == IP4_TYPE) 00328 { 00329 /* Sending to loopback device if IPv4. 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++); /* packet dropped (null-device) */ 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 /* USE_IPV6 */ 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; /* add 2 for protocol */ 00370 } 00371 #endif 00372 00373 /* Store the last Tx CPU timestamp (for debugging). 00374 */ 00375 #if (DOSX) && !defined(WIN32) 00376 if (_dbugxmit && has_rdtsc) 00377 get_rdtsc2 (&_eth_last.tx.tstamp); 00378 #endif 00379 00380 /* Do the MAC-dependent transmit. `len' on return is total length 00381 * of link-layer packet sent. `len' is 0 on failure. The xmit-hook 00382 * is used by e.g. libpcap/libnet. 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 /* Undo hack done in pppoe_mac_format() 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; /* remember protocol for _eth_send() */ 00451 00452 /* Clear any remains of an old small packet 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 /* No need to clear data behind header. 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 /* !!fix me: need to expand the RIF 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) /* Map to DataPoint proto types */ 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; /* map to ARCNET broadcast */ 00552 else dest = *(BYTE*)mac_dest; /* Use MSB as destination */ 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 /* should never be transmitted */ 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; /* zero padding already done in eth_mac_format() */ 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) /* Token-Ring has no min. length */ 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); /* error message already printed */ 00660 00661 /* Save our MAC-address incase we change it. Change back at exit. 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: /* !! for now */ 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); /* everything okay */ 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); /* 1 byte */ 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) /* hook-function should free it's own packet */ 00786 return; 00787 00788 if (!pkt) 00789 pkt_buf_wipe(); /* restart the queue */ 00790 else pkt_free_pkt (pkt); 00791 } 00792 00793 00799 #define RCF DSAP /* Routing Control where DSAP is when no routing */ 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)) /* AC,FC,src/dst */ 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)) /* Source routed */ 00824 { 00825 int rlen = TR_RIF_LENGTH (tr); 00826 00827 tr->source[0] &= 0x7F; /* clear RII bit */ 00828 00829 /* Set our notion of link-layer broadcast 00830 */ 00831 if (TR_IS_BROADCAST(tr)) 00832 tr->destination[0] |= 1; 00833 00834 /* Copy MAC-header rlen bytes upwards 00835 */ 00836 memmove ((BYTE*)tr + rlen, tr, TR_MAC_SIZE); 00837 *trp = (tok_Header*) ((BYTE*)tr + rlen); 00838 } 00839 } 00840 00841 /* 00842 * Check (and fix?) the received ARCNET header. 00843 * All frames must have a common layout with headlen ARC_HDRLEN. 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 /* Map to IANA numbers 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 || /* Exception packet */ 00867 (*type != IP4_TYPE && /* Neither IP nor ARP */ 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; /* no need yet */ 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; /* length on 1st upcall */ 00928 _eth_last.rx.tstamp.lo = buf->tstamp_put[0]; /* TSC set in asmpkt */ 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; /* !! wrong, but doesn't matter for pcap */ 00937 _eth_last.rx.tstamp.lo = 0UL; /* pcdbug.c writes rx-time == dbg-time */ 00938 _eth_last.rx.tstamp.hi = 0UL; 00939 #endif 00940 00941 00942 if (_pktserial) 00943 { 00944 ip = &pkt->ip.head; /* SLIP/PPP/AX25 */ 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 /* must be PDCLASS_ETHER */ 00980 00981 *type = pkt->eth.head.type; 00982 ARGSUSED (q); 00983 return (pkt); 00984 } 00985 00986 /* 00987 * Fix the LLC header to look like ordinary Ethernet II 00988 * !! not yet. 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) /* GvB 2002-09, Lets us run without a working driver */ 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 /* Hack: If _ip?_handler() can't be reentered, only accept 01043 * non-IP packets. Assume PPPoE session packets carries only IP. 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 /* must be ether */ 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 /* test */ 01089 pkt_print_split_in(); 01090 #endif 01091 01092 /* ARCnet should never have LLC fields. So don't test for it 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) /* LLC length field */ 01100 fix_llc_head (&ret); 01101 } 01102 else if (dst && *(BYTE*)dst == 0) /* ARCnet broadcast */ 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 /*@-unreachable@*/ 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 /*@-unreachable@*/ 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 /*@-unreachable@*/ 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 /*@-unreachable@*/ 01222 return (0); 01223 } 01224 #endif /* USE_DEBUG */ 01225 01226 01227 /* 01228 * Jim Martin's Multicast extensions 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 /* Return if we're already receiving all multicasts or is in 01247 * promiscous mode. 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); /* hopeless, give up */ 01271 } 01272 01273 len = sizeof(list); 01274 if (!pkt_get_multicast_list (list, &len)) 01275 { 01276 /* If no MC support, switch to MC2 mode 01277 */ 01278 if (_pkt_errno == PDERR_NO_MULTICAST) 01279 return pkt_set_rcv_mode (RXMODE_MULTICAST2); 01280 return (FALSE); 01281 } 01282 01283 /* check to see if the address is already in the list 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]); /* append entry */ 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 /* If no space or no MC support, switch to MC2 mode 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 /* \note This should be expanded to include switching back to 01322 * RXMODE_MULTCAST1 if the list of multicast addresses has 01323 * shrunk sufficiently. 01324 * 01325 * First check to see if we're in RXMODE_MULTICAST2. if so return 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 /* get the list of current multicast addresses 01336 */ 01337 len = sizeof(list); 01338 if (!pkt_get_multicast_list (list, &len)) 01339 return (FALSE); 01340 01341 /* find the apropriate entry 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 /* if it's not in the list, just return 01348 */ 01349 if (idx == -1) 01350 return (TRUE); 01351 01352 /* ahh, but it _is_ in the list. So shorten the list 01353 * and send it back to the PKTDRVR 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 /* If no space or no MC support, switch mode 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 /* USE_MULTICAST */ 01372 01377 #include "nochkstk.h" 01378 01382 void _eth_release (void) 01383 { 01384 if (!_eth_is_init) 01385 return; 01386 01387 /* Set original MAC address (if not fatal-error or serial-driver) 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) /* restore startup Rx mode */ 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; /* in case we crash in pkt_release() */ 01412 pkt_release(); 01413 } 01414

Generated on Wed Aug 4 08:55:52 2010 for Watt-32 tcp/ip by doxygen 1.3.8