Commit | Line | Data |
---|---|---|
2e74322d | 1 | #ifndef lint |
f1e15e15 | 2 | static char sccsid[] = "@(#)input.c 4.10 (Berkeley) %G%"; |
2e74322d SL |
3 | #endif |
4 | ||
5 | /* | |
6 | * Routing Table Management Daemon | |
7 | */ | |
7fe7fe74 | 8 | #include "defs.h" |
2e74322d SL |
9 | |
10 | /* | |
11 | * Process a newly received packet. | |
12 | */ | |
13 | rip_input(from, size) | |
14 | struct sockaddr *from; | |
15 | int size; | |
16 | { | |
17 | struct rt_entry *rt; | |
18 | struct netinfo *n; | |
19 | struct interface *ifp; | |
20 | int newsize; | |
21 | struct afswitch *afp; | |
22 | ||
23 | ifp = 0; | |
24 | TRACE_INPUT(ifp, from, size); | |
25 | if (from->sa_family >= AF_MAX) | |
26 | return; | |
27 | afp = &afswitch[from->sa_family]; | |
28 | switch (msg->rip_cmd) { | |
29 | ||
30 | case RIPCMD_REQUEST: | |
31 | newsize = 0; | |
32 | size -= 4 * sizeof (char); | |
33 | n = msg->rip_nets; | |
34 | while (size > 0) { | |
35 | if (size < sizeof (struct netinfo)) | |
36 | break; | |
37 | size -= sizeof (struct netinfo); | |
38 | ||
55d340a4 SL |
39 | if (msg->rip_vers > 0) { |
40 | n->rip_dst.sa_family = | |
41 | ntohs(n->rip_dst.sa_family); | |
42 | n->rip_metric = ntohl(n->rip_metric); | |
43 | } | |
2e74322d SL |
44 | /* |
45 | * A single entry with sa_family == AF_UNSPEC and | |
46 | * metric ``infinity'' means ``all routes''. | |
47 | */ | |
48 | if (n->rip_dst.sa_family == AF_UNSPEC && | |
49 | n->rip_metric == HOPCNT_INFINITY && size == 0) { | |
50 | supply(from, 0, ifp); | |
51 | return; | |
52 | } | |
53 | rt = rtlookup(&n->rip_dst); | |
54 | n->rip_metric = rt == 0 ? HOPCNT_INFINITY : | |
55 | min(rt->rt_metric+1, HOPCNT_INFINITY); | |
55d340a4 SL |
56 | if (msg->rip_vers > 0) { |
57 | n->rip_dst.sa_family = | |
58 | htons(n->rip_dst.sa_family); | |
59 | n->rip_metric = htonl(n->rip_metric); | |
60 | } | |
2e74322d SL |
61 | n++, newsize += sizeof (struct netinfo); |
62 | } | |
63 | if (newsize > 0) { | |
64 | msg->rip_cmd = RIPCMD_RESPONSE; | |
65 | newsize += sizeof (int); | |
4f4bffaa | 66 | (*afp->af_output)(s, 0, from, newsize); |
2e74322d SL |
67 | } |
68 | return; | |
69 | ||
70 | case RIPCMD_TRACEON: | |
71 | case RIPCMD_TRACEOFF: | |
b7e4f8be | 72 | /* verify message came from a privileged port */ |
2e74322d SL |
73 | if ((*afp->af_portcheck)(from) == 0) |
74 | return; | |
75 | packet[size] = '\0'; | |
76 | if (msg->rip_cmd == RIPCMD_TRACEON) | |
77 | traceon(msg->rip_tracefile); | |
78 | else | |
79 | traceoff(); | |
80 | return; | |
81 | ||
82 | case RIPCMD_RESPONSE: | |
83 | /* verify message came from a router */ | |
84 | if ((*afp->af_portmatch)(from) == 0) | |
85 | return; | |
86 | (*afp->af_canon)(from); | |
87 | /* are we talking to ourselves? */ | |
88 | ifp = if_ifwithaddr(from); | |
89 | if (ifp) { | |
90 | rt = rtfind(from); | |
b7e4f8be | 91 | if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0) |
2e74322d SL |
92 | addrouteforif(ifp); |
93 | else | |
94 | rt->rt_timer = 0; | |
95 | return; | |
96 | } | |
f1e15e15 MK |
97 | /* |
98 | * Update timer for interface on which the packet arrived. | |
99 | * If from other end of a point-to-point link that isn't | |
100 | * in the routing tables, (re-)add the route. | |
101 | */ | |
b7e4f8be MK |
102 | if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE)) |
103 | rt->rt_timer = 0; | |
f1e15e15 MK |
104 | else if (ifp = if_ifwithdstaddr(from)) |
105 | addrouteforif(ifp); | |
2e74322d SL |
106 | size -= 4 * sizeof (char); |
107 | n = msg->rip_nets; | |
108 | for (; size > 0; size -= sizeof (struct netinfo), n++) { | |
109 | if (size < sizeof (struct netinfo)) | |
110 | break; | |
55d340a4 SL |
111 | if (msg->rip_vers > 0) { |
112 | n->rip_dst.sa_family = | |
113 | ntohs(n->rip_dst.sa_family); | |
114 | n->rip_metric = ntohl(n->rip_metric); | |
115 | } | |
d5568f13 MK |
116 | if ((unsigned) n->rip_metric >= HOPCNT_INFINITY) |
117 | continue; | |
ed36994a MK |
118 | if (n->rip_dst.sa_family >= AF_MAX) |
119 | continue; | |
120 | afp = &afswitch[n->rip_dst.sa_family]; | |
d5568f13 | 121 | if (((*afp->af_checkhost)(&n->rip_dst)) == 0) |
2e74322d SL |
122 | continue; |
123 | rt = rtlookup(&n->rip_dst); | |
124 | if (rt == 0) { | |
125 | rtadd(&n->rip_dst, from, n->rip_metric, 0); | |
126 | continue; | |
127 | } | |
128 | ||
129 | /* | |
38ca17a8 MK |
130 | * Update if from gateway and different, |
131 | * shorter, or getting stale and equivalent. | |
2e74322d | 132 | */ |
38ca17a8 MK |
133 | if ((equal(from, &rt->rt_router) && |
134 | n->rip_metric != rt->rt_metric ) || | |
b7e4f8be | 135 | (unsigned) (n->rip_metric) < rt->rt_metric || |
2e74322d SL |
136 | (rt->rt_timer > (EXPIRE_TIME/2) && |
137 | rt->rt_metric == n->rip_metric)) { | |
138 | rtchange(rt, from, n->rip_metric); | |
139 | rt->rt_timer = 0; | |
140 | } | |
141 | } | |
142 | return; | |
143 | } | |
144 | } |