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
00042
00043
static int arp_timeout = 2;
00044
static int arp_alive = 300;
00045
static int arp_rexmit_to = 250;
00046
static int arp_num_cache = 64;
00047
static BOOL dead_gw_detect = FALSE;
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
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);
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
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,ð))
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;
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
00199
00200 ip =
aton (config_string);
00201
if (ip == 0)
00202
return (FALSE);
00203
00204
00205
00206 subnetp = strchr (config_string,
',');
00207
if (subnetp)
00208 {
00209
00210
00211
00212
00213 subnet =
aton (++subnetp);
00214
00215
00216
00217 maskp = strchr (subnetp,
',');
00218
if (maskp)
00219 mask =
aton (++maskp);
00220
else
00221 {
00222
switch (subnet >> 30)
00223 {
00224
case 0:
00225
case 1:
00226 mask = 0xFF000000UL;
00227
break;
00228
case 2:
00229 mask = 0xFFFFFE00UL;
00230
break;
00231
case 3:
00232
default:
00233 mask = 0xFFFFFF00UL;
00234
break;
00235 }
00236 }
00237 }
00238 }
00239
else
00240 {
00241
if (ip == 0UL)
00242 {
00243 outsnl (
"_arp_add_gateway(): Illegal router");
00244
return (FALSE);
00245 }
00246 }
00247
00248
00249
00250 gw = NULL;
00251
00252
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
00262
00263
00264
00265
00266
00267
00268
00269
00270
if (gw == NULL)
00271 {
00272
if (gate_top+1 >= DIM(gate_list))
00273 {
00274 outsnl (_LANG(
"Gateway table full"));
00275
return (FALSE);
00276 }
00277 gw = &gate_list [gate_top++];
00278 }
00279
00280
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
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
00468
00469
if (arp_first_free < ARP_TOP_FREE)
00470 {
00471
00472 }
00473
else if (arp_first_dynamic < ARP_TOP_DYNAMIC)
00474 {
00475
00476
00477
00478
00479
00480 --ARP_TOP_DYNAMIC;
00481 outsnl (_LANG(
"ARP table overflow"));
00482 }
00483
else
00484 {
00485 outsnl (_LANG(
"ARP table full"));
00486
return (FALSE);
00487 }
00488
00489
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
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);
00503 }
00504
00508 static BOOL
LAN_lookup (
DWORD ip,
eth_address *eth)
00509 {
00510
int i;
00511
00512 SIO_TRACE ((
"LAN_lookup"));
00513
00514
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
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
00559
00560
for (i = arp_first_pending; i < ARP_TOP_PENDING; i++)
00561 {
00562 ae = &arp_list[i];
00563
00564
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++);
00572
continue;
00573 }
00574 ++arp_first_pending;
00575 }
00576
00577
00578
else if (
chk_timeout(ae->retransmit_to))
00579 {
00580
00581
00582 ae->retransmit_to =
set_timeout (
arp_send_request(ae->ip) ?
00583 arp_rexmit_to : arp_rexmit_to / 4);
00584 }
00585 }
00586
00587
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))
00597 {
00598
if (i < --ARP_TOP_DYNAMIC)
00599 {
00600 ae->
flags &= ~ARP_INUSE;
00601
arp_move_entry (i--, ARP_TOP_DYNAMIC);
00602
00603 }
00604 }
00605 }
00606 }
00607
00608
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00648 struct route_entry {
00649
DWORD host_ip;
00650
DWORD gate_ip;
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
00675
00676
00677
if (route_first_free < route_top_free)
00678 {
00679
00680 }
00681
else if (route_first_dynamic < route_top_dynamic)
00682 {
00683
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);
00693 }
00694
00695
00696
00697 re = &route_list [--route_first_pending];
00698 re->
host_ip = host_ip;
00699 re->gate_ip = gate_ip;
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
00725
00726
00727
if (!
is_on_LAN (use_this_gateway_ip) ||
is_on_LAN (for_this_host_ip))
00728
return (FALSE);
00729
00730
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);
00741
00742
if (
LAN_lookup (use_this_gateway_ip, NULL))
00743 {
00744 re->
gate_ip = use_this_gateway_ip;
00745
return (TRUE);
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);
00752 }
00753
00754
00755
00756
if (i < --route_top_dynamic)
00757 route_move_entry (i, route_top_dynamic);
00758
00759
00760
00761
00762
return route_makeNewSlot (use_this_gateway_ip, for_this_host_ip);
00763 }
00764
00765
00766
00767
00768
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
00783
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
00791
00792
return LAN_lookup (route_list[i].gate_ip, eth);
00793 }
00794
return (FALSE);
00795 }
00796
00801 static BOOL
route_lookup_pending (
DWORD host_ip)
00802 {
00803
int i;
00804
00805 SIO_TRACE ((
"route_lookup_pending"));
00806
00807
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);
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
00828
00829
for (i = route_first_pending; i < route_top_pending; i++)
00830
if (route_list [i].
host_ip == host_ip)
00831
return (TRUE);
00832
00833
for (i = route_first_dynamic; i < route_top_dynamic; i++)
00834
if (route_list [i].
host_ip == host_ip)
00835
return (TRUE);
00836
00837
00838
00839
if (gate_top <= 0)
00840 {
00841 outsnl (_LANG (
"No gateways defined."));
00842
return (FALSE);
00843 }
00844
00845
00846
00847 first_gate_ip = 0;
00848
00849
for (i = 0; i < gate_top; i++)
00850 {
00851
struct gate_entry *gw = &gate_list [i];
00852
00853
if ( !
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);
00866 }
00867 first_gate_ip = gw->gate_ip;
00868
break;
00869 }
00870
00871
00872
00873
if (first_gate_ip == 0)
00874 {
00875 outsnl (_LANG (
"No matching gateway"));
00876
return (FALSE);
00877 }
00878
00879
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
00898
00899
for (i = route_first_pending; i < route_top_pending; i++)
00900 {
00901
struct route_entry *re = &route_list [i];
00902
00903
00904
00905
if (
LAN_lookup (re->gate_ip, NULL))
00906 {
00907
00908
00909
struct route_entry temp = *re;
00910
00911
00912
if (i > route_first_pending)
00913 route_move_entry (i--, route_first_pending);
00914
00915
00916 ++route_first_pending;
00917 route_list [route_top_dynamic++] = temp;
00918 }
00919
00920
00921
else if (
LAN_lookup_pending (re->gate_ip))
00922 {
00923
00924 }
00925
00926
00927
else
00928 {
00929
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;
00944
00945
00946
00947
while (++j < gate_top)
00948 {
00949
struct gate_entry *gw = &gate_list [j];
00950
00951
if ( !
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;
00959
00960 re->
gate_ip = gw->gate_ip;
00961 foundNextGateway = TRUE;
00962
break;
00963 }
00964
00965
00966
00967
if (!foundNextGateway)
00968 {
00969
if (i > route_first_pending)
00970 route_move_entry (i--, route_first_pending);
00971 ++route_first_pending;
00972 }
00973 }
00974 }
00975
00976
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;
00984
00985
00986
00987
if (i < --route_top_dynamic)
00988 {
00989 route_move_entry (i--, route_top_dynamic);
00990
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)
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
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))
01088
return (FALSE);
01089
01090
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
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
01119
01120
if (
_pktserial)
01121 {
01122
if (eth)
01123 memset (eth, 0,
sizeof(*eth));
01124
return (TRUE);
01125 }
01126
01127
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
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);
01153
01154
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);
01162 }
01163
01164 NEW_BREAK_MODE (brk_mode, 1);
01165
01166
01167
01168
do
01169 {
01170
tcp_tick (NULL);
01171
arp_daemon();
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
01206
01207
01208 }
01209
else if (!
is_on_LAN (ip))
01210
return (FALSE);
01211
01212
_arp_delete_cache (ip);
01213
01214
01215
01216
if (expires)
01217 {
01218
if (arp_first_free >= ARP_TOP_FREE)
01219
return (FALSE);
01220
01221
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
01230 {
01231
01232
01233
if (arp_first_free >= ARP_TOP_FREE)
01234 {
01235
if (arp_first_dynamic >= ARP_TOP_DYNAMIC)
01236
return (FALSE);
01237 --ARP_TOP_DYNAMIC;
01238 }
01239
01240
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
01247
01248 ae = &arp_list [ARP_TOP_FIXED++];
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
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);
01276 arp_list[i].
flags &= ~ARP_INUSE;
01277
return (TRUE);
01278 }
01279
01280
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);
01289
01290
01291
01292
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
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);
01309 ++arp_first_pending;
01310 arp_list[i].
flags &= ~ARP_INUSE;
01311
return (TRUE);
01312 }
01313
return (FALSE);
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)
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
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 ||
01425 ah->
protType != IP4_TYPE)
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
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
01455
01456
if (
_pkt_rxmode >
RXMODE_BROADCAST &&
01457 memcmp(MAC_DST(ah),
_eth_brdcast,
sizeof(
_eth_brdcast)))
01458 do_reply = FALSE;
01459
01460
if (do_reply)
01461
_arp_reply (&ah->
srcEthAddr, ah->
srcIPAddr, ah->
dstIPAddr);
01462 }
01463
01464
01465
01466 src = intel (ah->
srcIPAddr);
01467 eth = &ah->
srcEthAddr;
01468
01469
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
01479
01480
if (i > arp_first_pending)
01481
arp_move_entry (i, arp_first_pending);
01482 ++arp_first_pending;
01483 arp_list[i].
flags &= ~ARP_PENDING;
01484 arp_list[i].
flags &= ~ARP_INUSE;
01485
01486
01487
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);
01496 }
01497
01498
01499
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
01510
01511
01512
01513
01514
01515 equal = (memcmp(&arp_list[i].hardware, eth,
sizeof(*eth)) == 0);
01516
01517
01518
01519 timeout = (equal ? (1000UL * arp_alive) : 500UL);
01520 arp_list[i].
expiry =
set_timeout (timeout);
01521
return (TRUE);
01522 }
01523
01524
01525
01526
if (do_reply)
01527 {
01528
_arp_add_cache (src, &ah->
srcEthAddr, TRUE);
01529
return (TRUE);
01530 }
01531
01532
01533
01534
01535
01536
01537
01538 ARGSUSED (brdcast);
01539
return (FALSE);
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
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
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
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
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