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

SRC/pcarp.c

Go to the documentation of this file.
00001 00011 #include <stdio.h> 00012 #include <stdlib.h> 00013 #include <string.h> 00014 00015 #include "copyrigh.h" 00016 #include "wattcp.h" 00017 #include "strings.h" 00018 #include "language.h" 00019 #include "netaddr.h" 00020 #include "misc.h" 00021 #include "timer.h" 00022 #include "rs232.h" 00023 #include "ip4_in.h" 00024 #include "ip4_out.h" 00025 #include "sock_ini.h" 00026 #include "chksum.h" 00027 #include "pcdbug.h" 00028 #include "pctcp.h" 00029 #include "pcsed.h" 00030 #include "pcconfig.h" 00031 #include "pcqueue.h" 00032 #include "pcicmp.h" 00033 #include "pcdhcp.h" 00034 #include "pcpkt.h" 00035 #include "pcarp.h" 00036 00037 #ifndef __inline 00038 #define __inline 00039 #endif 00040 00041 /* Local parameters. 00042 */ 00043 static int arp_timeout = 2; /* 2 seconds ARP timeout */ 00044 static int arp_alive = 300; /* 5 min ARP cache lifespan */ 00045 static int arp_rexmit_to = 250; /* 250 milliseconds per try */ 00046 static int arp_num_cache = 64; /* # of entries in ARP cache (not yet) */ 00047 static BOOL dead_gw_detect = FALSE; /* Enable Dead Gateway detection */ 00048 static BOOL arp_gratiotous = FALSE; 00049 00050 static BOOL LAN_lookup (DWORD ip, eth_address *eth); 00051 static BOOL is_on_LAN (DWORD ip); 00052 static void arp_daemon (void); 00053 00057 #define DEAD_GW_TIMEOUT 10000 /* 10 sec */ 00058 #define GATE_TOP_OF_CACHE 8 00059 00060 static int gate_top = 0; 00061 00062 static struct gate_entry gate_list [GATE_TOP_OF_CACHE]; 00063 00064 00065 #if defined(USE_DEBUG) 00066 00071 int _arp_list_gateways (struct gate_entry *gw, int max) 00072 { 00073 int i; 00074 00075 for (i = 0; i < gate_top && i < max; i++, gw++) 00076 { 00077 memset (gw, 0, sizeof(*gw)); 00078 gw->gate_ip = gate_list[i].gate_ip; 00079 gw->subnet = gate_list[i].subnet; 00080 gw->mask = gate_list[i].mask; 00081 gw->echo_pending = gate_list[i].echo_pending; 00082 gw->is_dead = gate_list[i].is_dead; 00083 } 00084 return (i); 00085 } 00086 #endif 00087 00088 #if defined(USE_DEAD_GWD) 00089 00093 static WORD icmp_id = 0; 00094 static WORD icmp_seq = 0; 00095 00096 static int ping_gateway (DWORD host, void *eth) 00097 { 00098 struct ping_pkt *pkt; 00099 struct ICMP_echo *icmp; 00100 struct in_Header *ip; 00101 int len; 00102 00103 pkt = (struct ping_pkt*) _eth_formatpacket (eth, IP4_TYPE); 00104 ip = &pkt->in; 00105 icmp = &pkt->icmp; 00106 len = sizeof (*icmp); 00107 icmp_id = (WORD) set_timeout (0); /* "random" id */ 00108 00109 printf ("ping_gateway %s\n", _inet_ntoa(NULL,host)); // !! 00110 00111 icmp->type = ICMP_ECHO; 00112 icmp->code = 0; 00113 icmp->index = 1; 00114 icmp->identifier = icmp_id; 00115 icmp->sequence = icmp_seq++; 00116 icmp->checksum = 0; 00117 icmp->checksum = ~CHECKSUM (icmp, len); 00118 00119 return IP4_OUTPUT (ip, 0, intel(host), ICMP_PROTO, 1, 00120 (BYTE)_default_tos, 0, len, NULL); 00121 } 00122 00123 /* 00124 * This functiom is called once each second. 00125 */ 00126 static void check_dead_gw (void) 00127 { 00128 static int i = 0; 00129 00130 if (i >= gate_top) 00131 i = 0; 00132 00133 for ( ; i < gate_top; i++) 00134 { 00135 struct gate_entry *gw = &gate_list [i]; 00136 eth_address eth; 00137 00138 printf ("check_dead_gw (1), i %d\n", i); // !! 00139 00140 if (!is_on_LAN(gw->gate_ip)) 00141 continue; 00142 00143 if (!LAN_lookup(gw->gate_ip,&eth)) 00144 { 00145 printf ("check_dead_gw (2), IP %s\n", _inet_ntoa(NULL,gw->gate_ip)); // !! 00146 continue; 00147 } 00148 00149 if (gw->chk_timer == 0UL || !chk_timeout(gw->chk_timer)) 00150 { 00151 gw->chk_timer = set_timeout (DEAD_GW_TIMEOUT); 00152 continue; 00153 } 00154 00155 if (gw->echo_pending && 00156 _chk_ping(gw->gate_ip,NULL) == (DWORD)-1) 00157 { 00158 printf ("check_dead_gw (3), i %d\n", i); // !! 00159 00160 gw->is_dead = TRUE; 00161 gw->echo_pending = FALSE; 00162 TCP_CONSOLE_MSG (1, ("Dead default GW %s (%d) detected\n", 00163 _inet_ntoa(NULL,gw->gate_ip), i)); 00164 } 00165 00166 if (ping_gateway(gw->gate_ip, eth)) 00167 gw->echo_pending = TRUE; 00168 00169 gw->chk_timer = set_timeout (DEAD_GW_TIMEOUT); 00170 return; /* only one ping per interval */ 00171 } 00172 } 00173 #endif 00174 00175 00185 BOOL _arp_add_gateway (const char *config_string, DWORD ip) 00186 { 00187 struct gate_entry *gw; 00188 DWORD subnet = 0UL; 00189 DWORD mask = 0UL; 00190 int i; 00191 00192 SIO_TRACE (("_arp_add_gateway")); 00193 00194 if (config_string) 00195 { 00196 const char* subnetp, *maskp; 00197 00198 /* Get gateways IP address from string 00199 */ 00200 ip = aton (config_string); 00201 if (ip == 0) 00202 return (FALSE); /* invalid */ 00203 00204 /* Check if optional subnet was supplied 00205 */ 00206 subnetp = strchr (config_string, ','); 00207 if (subnetp) 00208 { 00209 /* NB: atoi (used in aton) stops conversion when the first non-number 00210 * is hit, so there is no need to manually null-terminate the string. 00211 * i.e. aton ("123.123.123.123,blabla") = 123.123.123.123 00212 */ 00213 subnet = aton (++subnetp); 00214 00215 /* Check if optional mask was supplied 00216 */ 00217 maskp = strchr (subnetp, ','); 00218 if (maskp) 00219 mask = aton (++maskp); 00220 else /* No mask was supplied, we derive it from the supplied subnet */ 00221 { 00222 switch (subnet >> 30) 00223 { 00224 case 0: 00225 case 1: 00226 mask = 0xFF000000UL; 00227 break; 00228 case 2: 00229 mask = 0xFFFFFE00UL; /* minimal class B */ 00230 break; 00231 case 3: 00232 default: 00233 mask = 0xFFFFFF00UL; 00234 break; 00235 } 00236 } 00237 } 00238 } 00239 else /* (config_string == NULL) */ 00240 { 00241 if (ip == 0UL) 00242 { 00243 outsnl ("_arp_add_gateway(): Illegal router"); 00244 return (FALSE); /* args invalid */ 00245 } 00246 } 00247 00248 /* Figure out where to put our new gateway 00249 */ 00250 gw = NULL; 00251 00252 /* Check if gateway is already is in list 00253 */ 00254 for (i = 0; i < gate_top; i++) 00255 if (gate_list[i].gate_ip == ip) 00256 { 00257 gw = &gate_list[i]; 00258 break; 00259 } 00260 00261 /* If a 'new' gateway, we check if we have enough room and simply 00262 * add it to the end of the list. 00263 * 00264 * There is not much point in sorting the list, as the 'whole' list is 00265 * scanned when a gateway is needed. Usually there will only be 1 anyway. 00266 * If we do sort, we would use plain old insert-sort and NOT quicksort, 00267 * as quicksort goes O(n^2) on an already sorted list, plus it has a high 00268 * overhead that especially hurts on a tiny list like this. 00269 */ 00270 if (gw == NULL) 00271 { 00272 if (gate_top+1 >= DIM(gate_list)) 00273 { 00274 outsnl (_LANG("Gateway table full")); 00275 return (FALSE); /* no more room */ 00276 } 00277 gw = &gate_list [gate_top++]; 00278 } 00279 00280 /* Fill in new entry 00281 */ 00282 memset (gw, 0, sizeof(*gw)); 00283 gw->gate_ip = ip; 00284 gw->mask = mask; 00285 gw->subnet = subnet; 00286 return (TRUE); 00287 } 00288 00292 void _arp_kill_gateways (void) 00293 { 00294 SIO_TRACE (("_arp_kill_gateways")); 00295 gate_top = 0; 00296 } 00297 00301 BOOL _arp_have_default_gw (void) 00302 { 00303 int i, num = 0; 00304 00305 SIO_TRACE (("_arp_have_default_gw")); 00306 for (i = 0; i < gate_top; i++) 00307 if (gate_list[i].subnet == 0UL) 00308 num++; 00309 return (num > 0); 00310 } 00311 00312 00356 #define ARP_TOP_OF_CACHE 64 00359 #define ARP_TOP_PENDING ARP_TOP_OF_CACHE 00360 #define ARP_TOP_FREE arp_first_pending 00361 #define ARP_TOP_DYNAMIC arp_first_free 00362 #define ARP_TOP_FIXED arp_first_dynamic 00363 #define ARP_FIRST_FIXED 0 00364 00365 static int arp_first_pending = ARP_TOP_PENDING; 00366 static int arp_first_free = 0; 00367 static int arp_first_dynamic = 0; 00368 00369 static struct arp_entry arp_list [ARP_TOP_OF_CACHE]; 00370 00374 static __inline BOOL arp_send (const arp_Header *arp, unsigned line) 00375 { 00376 SIO_TRACE (("_arp_send")); 00377 ARGSUSED (arp); 00378 00379 return _eth_send (sizeof(*arp), NULL, __FILE__, line); 00380 } 00381 00382 00386 static BOOL arp_send_request (DWORD ip) 00387 { 00388 arp_Header *arp = (arp_Header*) _eth_formatpacket (&_eth_brdcast[0], ARP_TYPE); 00389 00390 SIO_TRACE (("_arp_send_request")); 00391 00392 arp->hwType = intel16 (_eth_get_hwtype(NULL,NULL)); 00393 arp->protType = IP4_TYPE; 00394 arp->hwAddrLen = sizeof (eth_address); 00395 arp->protoAddrLen = sizeof (ip); 00396 arp->opcode = ARP_REQUEST; 00397 arp->srcIPAddr = intel (my_ip_addr); 00398 arp->dstIPAddr = intel (ip); 00399 memcpy (arp->srcEthAddr, _eth_addr, sizeof(arp->srcEthAddr)); 00400 memset (arp->dstEthAddr, 0, sizeof(arp->dstEthAddr)); 00401 return arp_send (arp, __LINE__); 00402 } 00403 00404 00409 BOOL _arp_reply (const void *mac_dst, DWORD src_ip, DWORD dst_ip) 00410 { 00411 arp_Header *arp; 00412 00413 SIO_TRACE (("_arp_reply")); 00414 00415 if (!mac_dst) 00416 mac_dst = &_eth_brdcast; 00417 00418 arp = (arp_Header*) _eth_formatpacket (mac_dst, ARP_TYPE); 00419 arp->hwType = intel16 (_eth_get_hwtype(NULL,NULL)); 00420 arp->protType = IP4_TYPE; 00421 arp->hwAddrLen = sizeof (mac_address); 00422 arp->protoAddrLen = sizeof (dst_ip); 00423 arp->opcode = ARP_REPLY; 00424 arp->dstIPAddr = src_ip; 00425 arp->srcIPAddr = dst_ip; 00426 00427 memcpy (arp->srcEthAddr, _eth_addr,sizeof(mac_address)); 00428 memcpy (arp->dstEthAddr, mac_dst, sizeof(mac_address)); 00429 return arp_send (arp, __LINE__); 00430 } 00431 00435 static __inline void arp_move_entry (int to_index, int from_index) 00436 { 00437 memcpy (&arp_list[to_index], &arp_list[from_index], sizeof(struct arp_entry)); 00438 } 00439 00446 static BOOL LAN_start_lookup (DWORD ip) 00447 { 00448 struct arp_entry *ae; 00449 int i; 00450 00451 SIO_TRACE (("LAN_start_lookup")); 00452 00453 /* Ignore if IP is already in any list section (pending, fixed, dynamic) 00454 */ 00455 for (i = arp_first_pending; i < ARP_TOP_PENDING; i++) 00456 if (arp_list[i].ip == ip) 00457 return (TRUE); 00458 00459 for (i = arp_first_dynamic; i < ARP_TOP_DYNAMIC; i++) 00460 if (arp_list[i].ip == ip) 00461 return (TRUE); 00462 00463 for (i = ARP_FIRST_FIXED; i < ARP_TOP_FIXED; i++) 00464 if (arp_list[i].ip == ip) 00465 return (TRUE); 00466 00467 /* Figure out where to put the new guy 00468 */ 00469 if (arp_first_free < ARP_TOP_FREE) /* Do we have any free slots? */ 00470 { 00471 /* yes, ok! */ 00472 } 00473 else if (arp_first_dynamic < ARP_TOP_DYNAMIC) /* any dynamic entries? */ 00474 { 00475 /* This new request is probably more important than an existing 00476 * dynamic entry, so we sacrifice the top dynamic entry. It might be 00477 * neater to kill the oldest entry, but all this shouldn't happen anyway. 00478 * NB: Table size reallocation would go here. 00479 */ 00480 --ARP_TOP_DYNAMIC; /* nuke top entry */ 00481 outsnl (_LANG("ARP table overflow")); 00482 } 00483 else /* No more room - table is full with pending + fixed entries. */ 00484 { 00485 outsnl (_LANG("ARP table full")); 00486 return (FALSE); /* failed, nothing we can do right now. */ 00487 } 00488 00489 /* Fill new slot, send out ARP request 00490 */ 00491 ae = &arp_list [--arp_first_pending]; 00492 ae->ip = ip; 00493 ae->expiry = set_timeout (1000UL * arp_timeout); 00494 ae->flags = (ARP_INUSE | ARP_PENDING); 00495 00496 /* If request fails, we try again a little sooner 00497 */ 00498 if (!arp_send_request(ip)) 00499 ae->retransmit_to = set_timeout (arp_rexmit_to / 4); 00500 else ae->retransmit_to = set_timeout (arp_rexmit_to); 00501 00502 return (TRUE); /* ok, new request logged */ 00503 } 00504 00508 static BOOL LAN_lookup (DWORD ip, eth_address *eth) 00509 { 00510 int i; 00511 00512 SIO_TRACE (("LAN_lookup")); 00513 00514 /* Check in dynamic + fixed list section 00515 */ 00516 for (i = ARP_FIRST_FIXED; i < ARP_TOP_DYNAMIC; i++) 00517 { 00518 if (arp_list[i].ip != ip) 00519 continue; 00520 if (eth) 00521 memcpy (eth, arp_list[i].hardware, sizeof(*eth)); 00522 return (TRUE); 00523 } 00524 return (FALSE); 00525 } 00526 00530 static BOOL LAN_lookup_pending (DWORD ip) 00531 { 00532 int i; 00533 00534 SIO_TRACE (("LAN_lookup_pending")); 00535 00536 /* Scan pending list section 00537 */ 00538 for (i = arp_first_pending; i < ARP_TOP_PENDING; i++) 00539 if (arp_list[i].ip == ip) 00540 return (TRUE); 00541 return (FALSE); 00542 } 00543 00551 static void arp_check_timeouts (BOOL check_dynamic_entries) 00552 { 00553 struct arp_entry *ae; 00554 int i; 00555 00556 SIO_TRACE (("arp_check_timeouts")); 00557 00558 /* Check pending entries for retansmit & expiry 00559 */ 00560 for (i = arp_first_pending; i < ARP_TOP_PENDING; i++) 00561 { 00562 ae = &arp_list[i]; 00563 00564 /* If entry has expired (without being resolved): kill it 00565 */ 00566 if (chk_timeout(ae->expiry)) 00567 { 00568 if (i > arp_first_pending) 00569 { 00570 ae->flags &= ~ARP_INUSE; 00571 arp_move_entry (i--, arp_first_pending++); /* fill hole */ 00572 continue; /* backed 'i' up a step, now re-check 'new' current entry */ 00573 } 00574 ++arp_first_pending; 00575 } 00576 /* If time for a retransmission: do it & restart timeout 00577 */ 00578 else if (chk_timeout(ae->retransmit_to)) 00579 { 00580 /* If request fails, we try again a little sooner 00581 */ 00582 ae->retransmit_to = set_timeout (arp_send_request(ae->ip) ? 00583 arp_rexmit_to : arp_rexmit_to / 4); 00584 } 00585 } 00586 00587 /* Check dynamic entries for expiry 00588 */ 00589 if (!check_dynamic_entries) 00590 return; 00591 00592 for (i = arp_first_dynamic; i < ARP_TOP_DYNAMIC; i++) 00593 { 00594 ae = &arp_list[i]; 00595 00596 if (chk_timeout(ae->expiry)) /* entry has expired: kill it */ 00597 { 00598 if (i < --ARP_TOP_DYNAMIC) 00599 { 00600 ae->flags &= ~ARP_INUSE; 00601 arp_move_entry (i--, ARP_TOP_DYNAMIC); /* fill hole */ 00602 /* backed 'i' up a step, now re-check 'new' current entry */ 00603 } 00604 } 00605 } 00606 } 00607 00608 00613 /* Route table internal structure: 00614 * \verbatim 00615 * 00616 * Index pointers Route cache table 00617 * -------------- ----------------- 00618 * 00619 * (top_of_cache) -> 00620 * (= top_pending) ---------------------- 00621 * | ... 00622 * | PENDING ROUTE ENTRIES (ARPing gateway - no reply yet) 00623 * first_pending -> | ... grow downwards (into free slots) 00624 * (= top_free) ---------------------- 00625 * | ... 00626 * | ... 00627 * | FREE SLOTS 00628 * | ... 00629 * first_free ----> | ... 00630 * (= top_dynamic) ---------------------- 00631 * | ... grow upwards (into free slots) 00632 * | ... 00633 * | "DYNAMIC" ROUTE ENTRIES 00634 * first_dynamic -> | ... 00635 * ---------------------- 00636 * \endverbatim 00637 * 00638 * \note 00639 * - "Top" means last entry + 1. 00640 * - The entries inside each section are not ordered in any way. 00641 * - The route cache only holds entries of hosts that are OUTSIDE of our LAN. 00642 * - The entries time out when the gateways ARP cache entry times out. 00643 */ 00644 00648 struct route_entry { 00649 DWORD host_ip; /* when connection to this host ... */ 00650 DWORD gate_ip; /* ... we use this gateway */ 00651 }; 00652 00653 #define route_top_of_cache 32 00654 #define route_top_pending route_top_of_cache 00655 #define route_top_free route_first_pending 00656 #define route_top_dynamic route_first_free 00657 #define route_first_dynamic 0 00658 00659 static int route_first_pending = route_top_pending; 00660 static int route_first_free = 0; 00661 00662 static struct route_entry route_list [route_top_of_cache]; 00663 00664 static __inline void route_move_entry (int to_index, int from_index) 00665 { 00666 memcpy (&route_list[to_index], &route_list[from_index], 00667 sizeof(struct route_entry)); 00668 } 00669 00670 static BOOL route_makeNewSlot (DWORD host_ip, DWORD gate_ip) 00671 { 00672 struct route_entry *re; 00673 00674 /* We assume IP was already checked for, otherwise we would add it twice. 00675 * Check where we have room. 00676 */ 00677 if (route_first_free < route_top_free) 00678 { 00679 /* Ok, free slots available */ 00680 } 00681 else if (route_first_dynamic < route_top_dynamic) 00682 { 00683 /* Slaughter first dynamic entry, as new entry probably is more important 00684 */ 00685 if (route_first_dynamic < --route_top_dynamic) 00686 route_move_entry (route_first_dynamic, route_top_dynamic); 00687 outsnl (_LANG("Route table overflow")); 00688 } 00689 else 00690 { 00691 outsnl (_LANG("Route table full")); 00692 return (FALSE); /* Nothing we can do - list is full of pending entries */ 00693 } 00694 00695 /* Put the new entry in 00696 */ 00697 re = &route_list [--route_first_pending]; 00698 re->host_ip = host_ip; /* when connection to this host ... */ 00699 re->gate_ip = gate_ip; /* ... use this gateway */ 00700 return (TRUE); 00701 } 00702 00706 static BOOL is_on_LAN (DWORD ip) 00707 { 00708 return (((ip ^ my_ip_addr) & sin_mask) == 0); 00709 } 00710 00718 BOOL _arp_register (DWORD use_this_gateway_ip, DWORD for_this_host_ip) 00719 { 00720 int i; 00721 00722 SIO_TRACE (("_arp_register")); 00723 00724 /* Only makes sense if ("old") host is outside of our LAN, 00725 * and ("new") gateway is on LAN. 00726 */ 00727 if (!is_on_LAN (use_this_gateway_ip) || is_on_LAN (for_this_host_ip)) 00728 return (FALSE); 00729 00730 /* See if this guy is in our dynamic table 00731 */ 00732 for (i = route_first_dynamic; i < route_top_dynamic; i++) 00733 { 00734 struct route_entry *re = &route_list[i]; 00735 00736 if (re->host_ip != for_this_host_ip) 00737 continue; 00738 00739 if (re->gate_ip == use_this_gateway_ip) 00740 return (TRUE); /* Already done */ 00741 00742 if (LAN_lookup (use_this_gateway_ip, NULL)) 00743 { 00744 re->gate_ip = use_this_gateway_ip; 00745 return (TRUE); /* New gateway is already in ARP cache, done */ 00746 } 00747 00748 if (!LAN_start_lookup (use_this_gateway_ip)) 00749 { 00750 outsnl (_LANG ("Unable to add redirect to ARP cache")); 00751 return (FALSE); /* ARP table full */ 00752 } 00753 00754 /* Kill 'old' dynamic entry, fill hole 00755 */ 00756 if (i < --route_top_dynamic) 00757 route_move_entry (i, route_top_dynamic); 00758 00759 /* Add new request, the new dynamic slot will be created when the 00760 * gateway ARP reply comes 00761 */ 00762 return route_makeNewSlot (use_this_gateway_ip, for_this_host_ip); 00763 } 00764 00765 /* Note: We do not check the pending section, as the gateway sending 00766 * the redirect could not really know the best route to a host that 00767 * we have not yet even started to connect to. Redirects referring 00768 * to a pending entry could be some sort of redirect attack. 00769 */ 00770 return (FALSE); 00771 } 00772 00776 static BOOL route_lookup (DWORD host_ip, eth_address *eth) 00777 { 00778 int i; 00779 00780 SIO_TRACE (("route_lookup")); 00781 00782 /* 1st, we need to find the gateway entry for the specified host 00783 * in our route table 00784 */ 00785 for (i = route_first_dynamic; i < route_top_dynamic; i++) 00786 { 00787 if (route_list[i].host_ip != host_ip) 00788 continue; 00789 00790 /* 2nd, the gateway needs to be in the ARP table 00791 */ 00792 return LAN_lookup (route_list[i].gate_ip, eth); 00793 } 00794 return (FALSE); /* host not here */ 00795 } 00796 00801 static BOOL route_lookup_pending (DWORD host_ip) 00802 { 00803 int i; 00804 00805 SIO_TRACE (("route_lookup_pending")); 00806 00807 /* Scan our pending list for the supplied host ip 00808 */ 00809 for (i = route_first_pending; i < route_top_pending; i++) 00810 { 00811 if (route_list [i].host_ip == host_ip) 00812 return (TRUE); 00813 } 00814 return (FALSE); /* host not here */ 00815 } 00816 00820 static BOOL route_start_lookup (DWORD host_ip) 00821 { 00822 DWORD first_gate_ip; 00823 int i; 00824 00825 SIO_TRACE (("route_start_lookup")); 00826 00827 /* Check if we already have an entry anywhere for this host 00828 */ 00829 for (i = route_first_pending; i < route_top_pending; i++) 00830 if (route_list [i].host_ip == host_ip) 00831 return (TRUE); /* Already here */ 00832 00833 for (i = route_first_dynamic; i < route_top_dynamic; i++) 00834 if (route_list [i].host_ip == host_ip) 00835 return (TRUE); /* Already here */ 00836 00837 /* Abort if we don't have any gateways 00838 */ 00839 if (gate_top <= 0) 00840 { 00841 outsnl (_LANG ("No gateways defined.")); 00842 return (FALSE); 00843 } 00844 00845 /* Find the first 'fitting' gateway 00846 */ 00847 first_gate_ip = 0; /* we remember the first gateway IP that fits */ 00848 00849 for (i = 0; i < gate_top; i++) 00850 { 00851 struct gate_entry *gw = &gate_list [i]; 00852 00853 if (/* !! sin_mask != 0xFFFFFFFFUL && */ !is_on_LAN(gw->gate_ip)) 00854 continue; 00855 00856 if ((gw->mask & host_ip) != gw->subnet) 00857 continue; 00858 00859 if (gw->is_dead) 00860 continue; 00861 00862 if (!LAN_start_lookup (gw->gate_ip)) 00863 { 00864 outsnl (_LANG ("Unable to add gateway to ARP cache")); 00865 return (FALSE); /* ARP table full, no point in going on right now */ 00866 } 00867 first_gate_ip = gw->gate_ip; /* We start with this guy */ 00868 break; 00869 } 00870 00871 /* Abort if we didn't find anybody at all to ARP, or all ARPs failed 00872 */ 00873 if (first_gate_ip == 0) 00874 { 00875 outsnl (_LANG ("No matching gateway")); 00876 return (FALSE); 00877 } 00878 00879 /* Create a new route cache slot with our guy 00880 */ 00881 route_makeNewSlot (host_ip, first_gate_ip); 00882 return (TRUE); 00883 } 00884 00885 00893 static void route_check_timeouts (BOOL check_dynamic_entries) 00894 { 00895 int i, j; 00896 00897 /* Check our pending entries 00898 */ 00899 for (i = route_first_pending; i < route_top_pending; i++) 00900 { 00901 struct route_entry *re = &route_list [i]; 00902 00903 /* Was the ARP lookup able to resolve the gateway IP? 00904 */ 00905 if (LAN_lookup (re->gate_ip, NULL)) 00906 { 00907 /* Success - move route entry from pending to dynamic list 00908 */ 00909 struct route_entry temp = *re; /* Make a copy so we can safely delete 00910 * the pending entry 00911 */ 00912 if (i > route_first_pending) 00913 route_move_entry (i--, route_first_pending); /* fill hole */ 00914 /* (i-- to "re"check new current entry) */ 00915 00916 ++route_first_pending; /* remove from pending list */ 00917 route_list [route_top_dynamic++] = temp; /* add to dynamic list */ 00918 } 00919 /* Is the ARP lookup still pending? -> Keep waiting 00920 */ 00921 else if (LAN_lookup_pending (re->gate_ip)) 00922 { 00923 /* Do nothing */ 00924 } 00925 /* The ARP lookup failed, we try the next possible gateway 00926 */ 00927 else 00928 { 00929 /* Find the gateway that was tried last (the one that just timed out) 00930 */ 00931 BOOL foundLastGateway = FALSE; 00932 BOOL foundNextGateway = FALSE; 00933 00934 for (j = 0; j < gate_top; j++) 00935 { 00936 if (gate_list[j].gate_ip != re->gate_ip) 00937 continue; 00938 foundLastGateway = TRUE; 00939 break; 00940 } 00941 00942 if (!foundLastGateway) 00943 j = -1; /* If search failed, we try the first gateway "again". */ 00944 00945 /* Now we look for the next gateway that could be used 00946 */ 00947 while (++j < gate_top) 00948 { 00949 struct gate_entry *gw = &gate_list [j]; 00950 00951 if (/* !! sin_mask != 0xFFFFFFFFUL && */ !is_on_LAN(gw->gate_ip)) 00952 continue; 00953 00954 if ((gw->mask & re->host_ip) != gw->subnet) 00955 continue; 00956 00957 if (!LAN_start_lookup (gw->gate_ip)) 00958 break; /* No room in ARP table, fail */ 00959 00960 re->gate_ip = gw->gate_ip; /* Ok, now we try this gateway */ 00961 foundNextGateway = TRUE; 00962 break; 00963 } 00964 00965 /* No more gateways to try, hence lookup failed, kill entry 00966 */ 00967 if (!foundNextGateway) 00968 { 00969 if (i > route_first_pending) 00970 route_move_entry (i--, route_first_pending); /* fill hole */ 00971 ++route_first_pending; 00972 } 00973 } 00974 } 00975 00976 /* Check our dynamic list for expired entries 00977 */ 00978 if (check_dynamic_entries) 00979 { 00980 for (i = route_first_dynamic; i < route_top_dynamic; i++) 00981 { 00982 if (LAN_lookup (route_list [i].gate_ip, NULL)) 00983 continue; /* Still in ARP cache - ok */ 00984 00985 /* This guy has expired, kill from list 00986 */ 00987 if (i < --route_top_dynamic) 00988 { 00989 route_move_entry (i--, route_top_dynamic); /* fill hole */ 00990 /* (i backed up a step so 'new' slot is rechecked) */ 00991 } 00992 } 00993 } 00994 } 00995 00996 01006 #if !defined(USE_UDP_ONLY) 01007 01012 BOOL arp_start_lookup (DWORD ip) 01013 { 01014 SIO_TRACE (("arp_start_lookup")); 01015 01016 if (_pktserial) /* Skip if using serial driver */ 01017 return (TRUE); 01018 01019 if (is_on_LAN(ip)) 01020 return LAN_start_lookup (ip); 01021 return route_start_lookup (ip); 01022 } 01023 01024 01029 BOOL arp_lookup (DWORD ip, eth_address *eth) 01030 { 01031 SIO_TRACE (("arp_lookup")); 01032 01033 /* Check if serial driver, return null MAC 01034 */ 01035 if (_pktserial) 01036 { 01037 if (eth) 01038 memset (eth, 0, sizeof(*eth)); 01039 return (TRUE); 01040 } 01041 01042 if (_ip4_is_local_addr(ip)) 01043 { 01044 if (eth) 01045 memcpy (eth, _eth_addr, sizeof(*eth)); 01046 return (TRUE); 01047 } 01048 01049 if (is_on_LAN(ip)) 01050 return LAN_lookup (ip, eth); 01051 return route_lookup (ip, eth); 01052 } 01053 01054 01061 BOOL arp_lookup_pending (DWORD ip) 01062 { 01063 SIO_TRACE (("arp_lookup_pending")); 01064 01065 if (is_on_LAN(ip)) 01066 return LAN_lookup_pending (ip); 01067 return route_lookup_pending (ip); 01068 } 01069 01074 BOOL arp_lookup_fixed (DWORD ip, eth_address *eth) 01075 { 01076 int i; 01077 01078 SIO_TRACE (("arp_lookup_fixed")); 01079 01080 if (_pktserial) 01081 { 01082 if (eth) 01083 memset (eth, 0, sizeof(*eth)); 01084 return (TRUE); 01085 } 01086 01087 if (!is_on_LAN(ip)) /* We only have/need a LAN version */ 01088 return (FALSE); 01089 01090 /* Scan fixed table section 01091 */ 01092 for (i = ARP_FIRST_FIXED; i < ARP_TOP_FIXED; i++) 01093 { 01094 if (arp_list[i].ip != ip) 01095 continue; 01096 if (eth) 01097 memcpy (eth, arp_list[i].hardware, sizeof(*eth)); 01098 return (TRUE); 01099 } 01100 return (FALSE); 01101 } 01102 #endif /* USE_UDP_ONLY */ 01103 01104 01108 BOOL _arp_resolve (DWORD ip, eth_address *eth) 01109 { 01110 WORD brk_mode; 01111 BOOL (*lookup) (DWORD, eth_address*); 01112 BOOL (*start_lookup) (DWORD); 01113 BOOL (*pending_lookup) (DWORD); 01114 BOOL rc = FALSE; 01115 01116 SIO_TRACE (("_arp_resolve")); 01117 01118 /* Check if serial driver, return null MAC 01119 */ 01120 if (_pktserial) 01121 { 01122 if (eth) 01123 memset (eth, 0, sizeof(*eth)); 01124 return (TRUE); 01125 } 01126 01127 /* Check if ip is local address, return own MAC address 01128 */ 01129 if (_ip4_is_local_addr(ip)) 01130 { 01131 if (eth) 01132 memcpy (eth, _eth_addr, sizeof(*eth)); 01133 return (TRUE); 01134 } 01135 01136 /* Quick-check if we have this guy in our cache. 01137 */ 01138 if (is_on_LAN(ip)) 01139 { 01140 lookup = LAN_lookup; 01141 start_lookup = LAN_start_lookup; 01142 pending_lookup = LAN_lookup_pending; 01143 } 01144 else 01145 { 01146 lookup = route_lookup; 01147 start_lookup = route_start_lookup; 01148 pending_lookup = route_lookup_pending; 01149 } 01150 01151 if ((*lookup)(ip, eth)) 01152 return (TRUE); /* Ok, done */ 01153 01154 /* Put out the request for the MAC 01155 */ 01156 if (!(*start_lookup)(ip)) 01157 { 01158 TCP_CONSOLE_MSG (2, ("%s (%d): %s() failed\n", 01159 __FILE__, __LINE__, (start_lookup == LAN_start_lookup) ? 01160 "LAN_start_lookup" : "route_start_lookup")); 01161 return (FALSE); /* Request failed, resolve doomed */ 01162 } 01163 01164 NEW_BREAK_MODE (brk_mode, 1); 01165 01166 /* Now busy-wait until reply is here or timeout (or Ctrl-C) 01167 */ 01168 do 01169 { 01170 tcp_tick (NULL); /* will call our daemon to timeout/retran */ 01171 arp_daemon(); /* added for faster lookup */ 01172 01173 if ((*lookup)(ip, eth)) 01174 { 01175 rc = TRUE; 01176 break; 01177 } 01178 WATT_YIELD(); 01179 01180 if (_watt_cbroke) 01181 { 01182 _watt_cbroke = 0; 01183 break; 01184 } 01185 } 01186 while ((*pending_lookup)(ip)); 01187 01188 OLD_BREAK_MODE (brk_mode); 01189 return (rc); 01190 } 01191 01192 01197 BOOL _arp_add_cache (DWORD ip, const void *eth, BOOL expires) 01198 { 01199 struct arp_entry *ae; 01200 01201 SIO_TRACE (("_arp_add_cache")); 01202 01203 if (!my_ip_addr && !expires) 01204 { 01205 /* If called from e.g. pcconfig, my_ip_addr may be 0 when using 01206 * DHCP. Allow adding fixed entries. 01207 */ 01208 } 01209 else if (!is_on_LAN (ip)) /* Only makes sense if on our LAN. */ 01210 return (FALSE); 01211 01212 _arp_delete_cache (ip); /* Kill it if already here somewhere */ 01213 01214 /* Now add to correct list 01215 */ 01216 if (expires) /* dynamic list */ 01217 { 01218 if (arp_first_free >= ARP_TOP_FREE) /* No free dynamic slots */ 01219 return (FALSE); 01220 01221 /* Fill new slot data 01222 */ 01223 ae = &arp_list [ARP_TOP_DYNAMIC++]; 01224 ae->ip = ip; 01225 memcpy (&ae->hardware, eth, sizeof(ae->hardware)); 01226 ae->expiry = set_timeout (1000UL * arp_alive); 01227 ae->flags = (ARP_INUSE | ARP_DYNAMIC); 01228 } 01229 else /* fixed list */ 01230 { 01231 /* Check if we have any free slots; make room if possible 01232 */ 01233 if (arp_first_free >= ARP_TOP_FREE) /* No more fixed slots? */ 01234 { 01235 if (arp_first_dynamic >= ARP_TOP_DYNAMIC) 01236 return (FALSE); /* No free AND no dynamic slots! */ 01237 --ARP_TOP_DYNAMIC; /* Kill the top dynamic slot to make room */ 01238 } 01239 01240 /* Roll dynamic entires up one slot to make room for the new fixed entry 01241 */ 01242 if (arp_first_dynamic < ARP_TOP_DYNAMIC) 01243 arp_move_entry (ARP_TOP_DYNAMIC, arp_first_dynamic); 01244 ++ARP_TOP_DYNAMIC; 01245 01246 /* Fill new slot data 01247 */ 01248 ae = &arp_list [ARP_TOP_FIXED++]; /* implies ++arp_first_dynamic! */ 01249 ae->ip = ip; 01250 ae->flags = (ARP_INUSE | ARP_FIXED); 01251 memcpy (&ae->hardware, eth, sizeof(ae->hardware)); 01252 } 01253 return (TRUE); 01254 } 01255 01256 01261 BOOL _arp_delete_cache (DWORD ip) 01262 { 01263 int i; 01264 01265 SIO_TRACE (("_arp_delete_cache")); 01266 01267 /* Remove from dynamic list if present 01268 */ 01269 for (i = arp_first_dynamic; i < ARP_TOP_DYNAMIC; i++) 01270 { 01271 if (arp_list[i].ip != ip) 01272 continue; 01273 01274 if (i < --ARP_TOP_DYNAMIC) 01275 arp_move_entry (i, ARP_TOP_DYNAMIC); /* fill hole */ 01276 arp_list[i].flags &= ~ARP_INUSE; 01277 return (TRUE); 01278 } 01279 01280 /* Remove from fixed list if present 01281 */ 01282 for (i = ARP_FIRST_FIXED; i < ARP_TOP_FIXED; i++) 01283 { 01284 if (arp_list[i].ip != ip) 01285 continue; 01286 01287 if (i < --ARP_TOP_FIXED) 01288 arp_move_entry (i, ARP_TOP_FIXED); /* fill hole */ 01289 01290 /* Do we have any dynamic entries we need to roll down one slot? 01291 * arp_first_dynamic same as ARP_TOP_FIXED, already implicity 01292 * decremented above! 01293 */ 01294 if (arp_first_dynamic < --ARP_TOP_DYNAMIC) 01295 arp_move_entry (arp_first_dynamic, ARP_TOP_DYNAMIC); 01296 arp_list[i].flags &= ~ARP_INUSE; 01297 return (TRUE); 01298 } 01299 01300 /* Remove from pending list if present 01301 */ 01302 for (i = arp_first_pending; i < ARP_TOP_PENDING; i++) 01303 { 01304 if (arp_list[i].ip != ip) 01305 continue; 01306 01307 if (i > arp_first_pending) 01308 arp_move_entry (i, arp_first_pending); /* fill hole */ 01309 ++arp_first_pending; 01310 arp_list[i].flags &= ~ARP_INUSE; 01311 return (TRUE); 01312 } 01313 return (FALSE); /* Didn't have it in cache */ 01314 } 01315 01323 static void arp_daemon (void) 01324 { 01325 static BOOL check_dynamic = TRUE; 01326 static DWORD check_dynamic_timer = 0UL; 01327 01328 arp_check_timeouts (check_dynamic); 01329 route_check_timeouts (check_dynamic); 01330 01331 if (check_dynamic) 01332 { 01333 #if defined(USE_DEAD_GWD) /* check dead gateways if we have >1 default GW */ 01334 if (dead_gw_detect) 01335 { 01336 if (_arp_check_gateways() <= 1) 01337 dead_gw_detect = FALSE; 01338 else check_dead_gw(); 01339 } 01340 #endif 01341 01342 /* Preset check_dynamic for next call 01343 */ 01344 check_dynamic_timer = set_timeout (1000UL); 01345 check_dynamic = FALSE; 01346 } 01347 else if (chk_timeout(check_dynamic_timer)) 01348 { 01349 check_dynamic = TRUE; 01350 } 01351 } 01352 01356 static void (*prev_cfg_hook) (const char*, const char*); 01357 01358 static void arp_parse (const char *name, const char *value) 01359 { 01360 static const struct config_table arp_cfg[] = { 01361 { "TIMEOUT", ARG_ATOI, (void*)&arp_timeout }, 01362 { "RETRANS_TO", ARG_ATOI, (void*)&arp_rexmit_to }, 01363 { "ALIVE", ARG_ATOI, (void*)&arp_alive }, 01364 { "NUM_CACHE", ARG_ATOI, (void*)&arp_num_cache }, 01365 { "DEAD_GW_DETECT",ARG_ATOI, (void*)&dead_gw_detect }, 01366 { "GRATIOTOUS", ARG_ATOI, (void*)&arp_gratiotous }, 01367 { NULL, 0, NULL } 01368 }; 01369 if (!parse_config_table(&arp_cfg[0], "ARP.", name, value) && prev_cfg_hook) 01370 (*prev_cfg_hook) (name, value); 01371 } 01372 01373 #ifdef NOT_YET 01374 static void (*prev_post_hook) (void); 01375 01376 static void arp_alloc (void) 01377 { 01378 if (arp_num_cache < 10) 01379 arp_num_cache = 10; 01380 arp_list = calloc (sizeof(struct arp_entry), arp_num_cache); 01381 if (!arp_list) 01382 { 01383 outsnl (_LANG("Fatal: failed to allocate ARP-cache")); 01384 exit (-1); 01385 } 01386 if (prev_post_hook) 01387 (*prev_post_hook)(); 01388 } 01389 #endif 01390 01394 void _arp_init (void) 01395 { 01396 SIO_TRACE (("_arp_init")); 01397 addwattcpd (arp_daemon); 01398 01399 #ifdef NOT_YET 01400 prev_post_hook = _watt_post_hook; 01401 _watt_post_hook = arp_alloc; 01402 #endif 01403 prev_cfg_hook = usr_init; 01404 usr_init = arp_parse; 01405 } 01406 01407 01412 BOOL _arp_handler (const arp_Header *ah, BOOL brdcast) 01413 { 01414 const eth_address *eth; 01415 WORD hw_needed = intel16 (_eth_get_hwtype(NULL,NULL)); 01416 DWORD src, dst; 01417 BOOL do_reply = FALSE; 01418 int i; 01419 01420 SIO_TRACE (("_arp_handler")); 01421 01422 DEBUG_RX (NULL, ah); 01423 01424 if (ah->hwType != hw_needed || /* wrong hardware type, */ 01425 ah->protType != IP4_TYPE) /* or not IPv4-protocol */ 01426 return (FALSE); 01427 01428 #if 0 01429 if (ah->hwAddrLen != sizeof(mac_address) || 01430 ah->protoAddrLen != sizeof(ip)) 01431 return (FALSE); 01432 #endif 01433 01434 /* Does someone else want our Ethernet address? 01435 */ 01436 if (ah->opcode == ARP_REQUEST) 01437 { 01438 src = intel (ah->srcIPAddr); 01439 dst = intel (ah->dstIPAddr); 01440 01441 if (_ip4_is_local_addr(dst) && 01442 !_ip4_is_multicast(dst) && 01443 !_ip4_is_loopback_addr(dst)) 01444 do_reply = TRUE; 01445 01446 if (src == my_ip_addr && _pkt_rxmode <= RXMODE_BROADCAST && 01447 memcmp(&_eth_addr,&ah->srcEthAddr,_eth_mac_len)) 01448 { 01449 TCP_CONSOLE_MSG (1, ("Address conflict from %s (%s)\n)", 01450 _inet_ntoa(NULL,src), 01451 MAC_address(&ah->srcEthAddr))); 01452 } 01453 01454 /* Prevent anti-sniffers detecting us if we're not in normal rx-mode 01455 */ 01456 if (_pkt_rxmode > RXMODE_BROADCAST && 01457 memcmp(MAC_DST(ah),_eth_brdcast,sizeof(_eth_brdcast))) /* not bcast */ 01458 do_reply = FALSE; 01459 01460 if (do_reply) 01461 _arp_reply (&ah->srcEthAddr, ah->srcIPAddr, ah->dstIPAddr); 01462 } 01463 01464 /* See if the senders IP & MAC is anything we can use 01465 */ 01466 src = intel (ah->srcIPAddr); 01467 eth = &ah->srcEthAddr; 01468 01469 /* Is this the awaited reply to a pending entry? 01470 */ 01471 for (i = arp_first_pending; i < ARP_TOP_PENDING; i++) 01472 { 01473 struct arp_entry *ae; 01474 01475 if (ah->opcode != ARP_REPLY || arp_list[i].ip != src) 01476 continue; 01477 01478 /* Remove from pending list 01479 */ 01480 if (i > arp_first_pending) 01481 arp_move_entry (i, arp_first_pending); /* fill 'hole' */ 01482 ++arp_first_pending; 01483 arp_list[i].flags &= ~ARP_PENDING; 01484 arp_list[i].flags &= ~ARP_INUSE; 01485 01486 /* fill new dynamic entry 01487 * (at least one slot is free because we just freed a pending slot) 01488 */ 01489 ae = &arp_list [ARP_TOP_DYNAMIC++]; 01490 ae->ip = src; 01491 ae->flags = (ARP_INUSE | ARP_DYNAMIC); 01492 01493 memcpy (&ae->hardware, eth, sizeof(*eth)); 01494 ae->expiry = set_timeout (1000UL * arp_alive); 01495 return (TRUE); /* ARP reply was useful */ 01496 } 01497 01498 /* Or is this a 'refresher' of a dynamic entry? 01499 * We'll use both ARP_REQUEST and ARP_REPLY to refresh. 01500 */ 01501 for (i = arp_first_dynamic; i < ARP_TOP_DYNAMIC; i++) 01502 { 01503 BOOL equal; 01504 DWORD timeout; 01505 01506 if (arp_list[i].ip != src) 01507 continue; 01508 01509 /* This could also be an 'ARP poisoning attack', where an attacker is 01510 * trying to slip us a fake MAC address. 01511 * Knowing that, we check if the MAC address has changed, and if so 01512 * prematurely expire the entry. We will re-request it when we need it. 01513 * If the MAC address is 'still' the same, we just restart the timeout. 01514 */ 01515 equal = (memcmp(&arp_list[i].hardware, eth, sizeof(*eth)) == 0); 01516 01517 /* if poisoned, we give the 'real guy' 500 ms grace to reclaim his MAC ;) 01518 */ 01519 timeout = (equal ? (1000UL * arp_alive) : 500UL); 01520 arp_list[i].expiry = set_timeout (timeout); 01521 return (TRUE); /* ARP reply was useful */ 01522 } 01523 01524 /* Add to cache if we replied. 01525 */ 01526 if (do_reply) 01527 { 01528 _arp_add_cache (src, &ah->srcEthAddr, TRUE); 01529 return (TRUE); 01530 } 01531 01532 /* Most TCP stacks add any 'sniffed' ARP replies to their cache in case 01533 * they're needed later. But what are the odds? :) 01534 * Anyway, this could quickly fill the table with 'junk' entries on 01535 * heavily populated LANs; plus it makes us vulnerable to ARP-flooding 01536 * attacks ... so it's probably wiser to just ignore them. 01537 */ 01538 ARGSUSED (brdcast); 01539 return (FALSE); /* i.e. not handled */ 01540 } 01541 01542 01543 #if defined(USE_DHCP) 01544 01550 BOOL _arp_check_own_ip (eth_address *other_guy) 01551 { 01552 DWORD save = my_ip_addr; 01553 BOOL rc; 01554 01555 SIO_TRACE (("_arp_check_own_ip")); 01556 01557 my_ip_addr = 0; 01558 memset (other_guy, 0, sizeof(*other_guy)); 01559 rc = _arp_resolve (save, other_guy); 01560 my_ip_addr = save; 01561 01562 if (rc && memcmp(other_guy,(const void*)"\0\0\0\0\0\0",sizeof(*other_guy))) 01563 return (FALSE); 01564 return (TRUE); 01565 } 01566 #endif 01567 01568 01569 #if defined(USE_DEBUG) 01570 01576 int _arp_list_cache (struct arp_entry *arp, int max) 01577 { 01578 int i, num; 01579 01580 for (i = num = 0; i < DIM(arp_list) && i < max; i++) 01581 { 01582 if (!(arp_list[i].flags & ARP_INUSE)) 01583 continue; 01584 01585 arp->ip = arp_list[i].ip; 01586 arp->expiry = arp_list[i].expiry; 01587 arp->flags = arp_list[i].flags; 01588 memcpy (arp->hardware, arp_list[i].hardware, sizeof(eth_address)); 01589 arp++; 01590 num++; 01591 } 01592 return (num); 01593 } 01594 01598 int _arp_check_gateways (void) 01599 { 01600 int i, num = 0; 01601 01602 SIO_TRACE (("_arp_check_gateways")); 01603 01604 /* Send a gratiotous ARP. Don't if already done DHCP_arp_check(). 01605 */ 01606 #if defined(USE_DHCP) 01607 if (dhcp_did_gratuitous_arp) 01608 arp_gratiotous = FALSE; 01609 #endif 01610 01611 if (arp_gratiotous) 01612 _arp_reply (NULL, intel(IP_BCAST_ADDR), intel(my_ip_addr)); 01613 01614 for (i = 0; i < gate_top; i++) 01615 if (gate_list[i].subnet == 0UL) 01616 num++; 01617 return (num); 01618 } 01619 01625 void _arp_debug_dump (void) 01626 { 01627 DWORD now = set_timeout (0UL); 01628 int i; 01629 01630 /* Gateways 01631 */ 01632 if (!dbug_printf ("Gateway list:\n")) 01633 return; 01634 01635 if (gate_top == 0) 01636 { 01637 dbug_printf (" --none--\n"); 01638 } 01639 else for (i = 0; i < gate_top; i++) 01640 { 01641 const struct gate_entry *gw = &gate_list[i]; 01642 DWORD mask = gw->mask ? gw->mask : sin_mask; 01643 01644 dbug_printf (" #%03d: %-15s ", i, _inet_ntoa(NULL, gw->gate_ip)); 01645 dbug_printf ("(network: %-15s ", _inet_ntoa(NULL, gw->subnet)); 01646 dbug_printf ("mask: %s)\n" , _inet_ntoa(NULL, mask)); 01647 } 01648 01649 /* Route table 01650 */ 01651 dbug_printf ("\nRouting cache:\n" 01652 "------- top of cache -----------------------------------------------\n" 01653 " (%03d) top of pending slots ---------------------------------------\n", 01654 route_top_pending); 01655 01656 if (route_first_pending == route_top_pending) 01657 { 01658 dbug_printf (" --none--\n"); 01659 } 01660 else if (route_first_pending > route_top_pending) 01661 { 01662 dbug_printf (" INDEX ERROR!\n"); 01663 } 01664 else for (i = route_top_pending-1; i >= route_first_pending; i--) 01665 { 01666 const struct route_entry *re = &route_list [i]; 01667 01668 dbug_printf (" #%03d: IP: %-15s -> gateway IP %-15s\n", 01669 i, _inet_ntoa(NULL,re->host_ip), 01670 _inet_ntoa(NULL,re->gate_ip)); 01671 } 01672 01673 dbug_printf ("- (%03d) top of free slots ------------------------------------------\n", 01674 route_top_free); 01675 01676 if (route_first_free == route_top_free) 01677 { 01678 dbug_printf (" --none--\n"); 01679 } 01680 else if (route_first_free > route_top_free) 01681 { 01682 dbug_printf (" INDEX ERROR!\n"); 01683 } 01684 else if (route_top_free - route_first_free <= 3) 01685 { 01686 for (i = route_top_free-1; i >= route_first_free; i--) 01687 dbug_printf (" #%03d: (free)\n", i); 01688 } 01689 else 01690 { 01691 dbug_printf (" #%03d: (free)\n", route_top_free-1); 01692 dbug_printf (" ... (free)\n"); 01693 dbug_printf (" #%03d: (free)\n", route_first_free); 01694 } 01695 01696 dbug_printf ("- (%03d) top of dynamic slots ---------------------------------------\n", 01697 route_top_dynamic); 01698 if (route_first_dynamic == route_top_dynamic) 01699 { 01700 dbug_printf (" --none--\n"); 01701 } 01702 else if (route_first_dynamic > route_top_dynamic) 01703 { 01704 dbug_printf (" INDEX ERROR!\n"); 01705 } 01706 else for (i = route_top_dynamic-1; i >= route_first_dynamic; i--) 01707 { 01708 const struct route_entry *re = &route_list [i]; 01709 01710 dbug_printf (" #%03d: IP: %-15s -> gateway IP %-15s\n", 01711 i, _inet_ntoa(NULL,re->host_ip), 01712 _inet_ntoa(NULL,re->gate_ip)); 01713 } 01714 dbug_printf ("------- bottom of cache --------------------------------------------\n"); 01715 01716 /* ARP table 01717 */ 01718 dbug_printf ("\nARP cache:\n" 01719 "------- top of cache -----------------------------------------------\n" 01720 " (%03d) top of pending slots ---------------------------------------\n", 01721 ARP_TOP_PENDING); 01722 01723 if (arp_first_pending == ARP_TOP_PENDING) 01724 { 01725 dbug_printf (" --none--\n"); 01726 } 01727 else if (arp_first_pending > ARP_TOP_PENDING) 01728 { 01729 dbug_printf (" INDEX ERROR!\n"); 01730 } 01731 else for (i = ARP_TOP_PENDING-1; i >= arp_first_pending; i--) 01732 { 01733 const struct arp_entry *ae = &arp_list [i]; 01734 01735 dbug_printf (" #%03d: IP: %-15s -> ??:??:??:??:??:?? expires in %ss\n", 01736 i, _inet_ntoa(NULL, ae->ip), time_str(ae->expiry - now)); 01737 } 01738 01739 dbug_printf ("- (%03d) top of free slots ------------------------------------------\n", 01740 ARP_TOP_FREE); 01741 if (arp_first_free == ARP_TOP_FREE) 01742 { 01743 dbug_printf (" --none--\n"); 01744 } 01745 else if (arp_first_free > ARP_TOP_FREE) 01746 { 01747 dbug_printf (" INDEX ERROR!\n"); 01748 } 01749 else if (ARP_TOP_FREE - arp_first_free <= 3) 01750 { 01751 for (i = ARP_TOP_FREE-1; i >= arp_first_free; i--) 01752 dbug_printf (" #%03d: (free)\n", i); 01753 } 01754 else 01755 { 01756 dbug_printf (" #%03d: (free)\n", ARP_TOP_FREE-1); 01757 dbug_printf (" ... (free)\n"); 01758 dbug_printf (" #%03d: (free)\n", arp_first_free); 01759 } 01760 01761 dbug_printf ("- (%03d) top of dynamic slots ---------------------------------------\n", 01762 ARP_TOP_DYNAMIC); 01763 if (arp_first_dynamic == ARP_TOP_DYNAMIC) 01764 { 01765 dbug_printf (" --none--\n"); 01766 } 01767 else if (arp_first_dynamic > ARP_TOP_DYNAMIC) 01768 { 01769 dbug_printf (" INDEX ERROR!\n"); 01770 } 01771 else for (i = ARP_TOP_DYNAMIC-1; i >= arp_first_dynamic; i--) 01772 { 01773 const struct arp_entry *ae = &arp_list [i]; 01774 01775 dbug_printf (" #%03d: IP: %-15s -> %s expires in %ss\n", 01776 i, _inet_ntoa(NULL,ae->ip), MAC_address(&ae->hardware), 01777 time_str(ae->expiry - now)); 01778 } 01779 01780 dbug_printf ("- (%03d) top of fixed slots -----------------------------------------\n", 01781 ARP_TOP_FIXED); 01782 if (ARP_FIRST_FIXED == ARP_TOP_FIXED) 01783 { 01784 dbug_printf (" --none--\n"); 01785 } 01786 else if (ARP_FIRST_FIXED > ARP_TOP_FIXED) 01787 { 01788 dbug_printf (" INDEX ERROR!\n"); 01789 } 01790 else for (i = ARP_TOP_FIXED-1; i >= ARP_FIRST_FIXED; i--) 01791 { 01792 const struct arp_entry *ae = &arp_list [i]; 01793 01794 dbug_printf (" #%03d: IP: %-15s -> %s\n", 01795 i, _inet_ntoa(NULL,ae->ip), MAC_address(&ae->hardware)); 01796 } 01797 dbug_printf ("------- bottom of cache --------------------------------------------\n"); 01798 } 01799 #endif /* USE_DEBUG */

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