Commit | Line | Data |
---|---|---|
5ff67f98 | 1 | /* |
0f7c421b | 2 | * Copyright (c) 1983, 1988 Regents of the University of California. |
0eb85d71 KB |
3 | * All rights reserved. |
4 | * | |
5 | * Redistribution and use in source and binary forms are permitted | |
6 | * provided that this notice is preserved and that due credit is given | |
7 | * to the University of California at Berkeley. The name of the University | |
8 | * may not be used to endorse or promote products derived from this | |
9 | * software without specific prior written permission. This software | |
10 | * is provided ``as is'' without express or implied warranty. | |
5ff67f98 DF |
11 | */ |
12 | ||
2e74322d | 13 | #ifndef lint |
09b9aef2 | 14 | static char sccsid[] = "@(#)input.c 5.17 (Berkeley) %G%"; |
0eb85d71 | 15 | #endif /* not lint */ |
2e74322d SL |
16 | |
17 | /* | |
18 | * Routing Table Management Daemon | |
19 | */ | |
7fe7fe74 | 20 | #include "defs.h" |
17fe297f | 21 | #include <sys/syslog.h> |
2e74322d SL |
22 | |
23 | /* | |
24 | * Process a newly received packet. | |
25 | */ | |
26 | rip_input(from, size) | |
27 | struct sockaddr *from; | |
28 | int size; | |
29 | { | |
20df59f1 MK |
30 | register struct rt_entry *rt; |
31 | register struct netinfo *n; | |
32 | register struct interface *ifp; | |
33 | struct interface *if_ifwithdstaddr(); | |
2e74322d | 34 | int newsize; |
20df59f1 | 35 | register struct afswitch *afp; |
09b9aef2 | 36 | static struct sockaddr badfrom, badfrom2; |
2e74322d SL |
37 | |
38 | ifp = 0; | |
39 | TRACE_INPUT(ifp, from, size); | |
17fe297f MK |
40 | if (from->sa_family >= af_max || |
41 | (afp = &afswitch[from->sa_family])->af_hash == (int (*)())0) { | |
42 | syslog(LOG_INFO, | |
43 | "\"from\" address in unsupported address family (%d), cmd %d\n", | |
44 | from->sa_family, msg->rip_cmd); | |
2e74322d | 45 | return; |
17fe297f | 46 | } |
2e74322d SL |
47 | switch (msg->rip_cmd) { |
48 | ||
49 | case RIPCMD_REQUEST: | |
50 | newsize = 0; | |
51 | size -= 4 * sizeof (char); | |
52 | n = msg->rip_nets; | |
53 | while (size > 0) { | |
54 | if (size < sizeof (struct netinfo)) | |
55 | break; | |
56 | size -= sizeof (struct netinfo); | |
57 | ||
55d340a4 SL |
58 | if (msg->rip_vers > 0) { |
59 | n->rip_dst.sa_family = | |
60 | ntohs(n->rip_dst.sa_family); | |
61 | n->rip_metric = ntohl(n->rip_metric); | |
62 | } | |
2e74322d SL |
63 | /* |
64 | * A single entry with sa_family == AF_UNSPEC and | |
65 | * metric ``infinity'' means ``all routes''. | |
17fe297f MK |
66 | * We respond to routers only if we are acting |
67 | * as a supplier, or to anyone other than a router | |
68 | * (eg, query). | |
2e74322d SL |
69 | */ |
70 | if (n->rip_dst.sa_family == AF_UNSPEC && | |
17deb420 MK |
71 | n->rip_metric == HOPCNT_INFINITY && size == 0) { |
72 | if (supplier || (*afp->af_portmatch)(from) == 0) | |
4fad5a6e | 73 | supply(from, 0, 0); |
2e74322d SL |
74 | return; |
75 | } | |
17deb420 MK |
76 | if (n->rip_dst.sa_family < af_max && |
77 | afswitch[n->rip_dst.sa_family].af_hash) | |
78 | rt = rtlookup(&n->rip_dst); | |
79 | else | |
80 | rt = 0; | |
2e74322d | 81 | n->rip_metric = rt == 0 ? HOPCNT_INFINITY : |
cdf21aa5 | 82 | min(rt->rt_metric + 1, HOPCNT_INFINITY); |
55d340a4 SL |
83 | if (msg->rip_vers > 0) { |
84 | n->rip_dst.sa_family = | |
85 | htons(n->rip_dst.sa_family); | |
86 | n->rip_metric = htonl(n->rip_metric); | |
87 | } | |
2e74322d SL |
88 | n++, newsize += sizeof (struct netinfo); |
89 | } | |
90 | if (newsize > 0) { | |
91 | msg->rip_cmd = RIPCMD_RESPONSE; | |
92 | newsize += sizeof (int); | |
4f4bffaa | 93 | (*afp->af_output)(s, 0, from, newsize); |
2e74322d SL |
94 | } |
95 | return; | |
96 | ||
97 | case RIPCMD_TRACEON: | |
98 | case RIPCMD_TRACEOFF: | |
b7e4f8be | 99 | /* verify message came from a privileged port */ |
2e74322d SL |
100 | if ((*afp->af_portcheck)(from) == 0) |
101 | return; | |
71786f50 | 102 | if ((ifp = if_iflookup(from)) == 0 || (ifp->int_flags & |
98a1809a MK |
103 | (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 || |
104 | ifp->int_flags & IFF_PASSIVE) { | |
09069ad0 | 105 | syslog(LOG_ERR, "trace command from unknown router, %s", |
eb39c032 | 106 | (*afswitch[from->sa_family].af_format)(from)); |
09069ad0 MK |
107 | return; |
108 | } | |
2e74322d SL |
109 | packet[size] = '\0'; |
110 | if (msg->rip_cmd == RIPCMD_TRACEON) | |
111 | traceon(msg->rip_tracefile); | |
112 | else | |
113 | traceoff(); | |
114 | return; | |
115 | ||
116 | case RIPCMD_RESPONSE: | |
117 | /* verify message came from a router */ | |
118 | if ((*afp->af_portmatch)(from) == 0) | |
119 | return; | |
120 | (*afp->af_canon)(from); | |
121 | /* are we talking to ourselves? */ | |
122 | ifp = if_ifwithaddr(from); | |
123 | if (ifp) { | |
0f7c421b MK |
124 | if (ifp->int_flags & IFF_PASSIVE) { |
125 | syslog(LOG_ERR, | |
126 | "bogus input (from passive interface, %s)", | |
127 | (*afswitch[from->sa_family].af_format)(from)); | |
128 | return; | |
129 | } | |
2e74322d | 130 | rt = rtfind(from); |
7892134c MK |
131 | if (rt == 0 || ((rt->rt_state & RTS_INTERFACE) == 0) && |
132 | rt->rt_metric >= ifp->int_metric) | |
2e74322d SL |
133 | addrouteforif(ifp); |
134 | else | |
135 | rt->rt_timer = 0; | |
136 | return; | |
137 | } | |
f1e15e15 MK |
138 | /* |
139 | * Update timer for interface on which the packet arrived. | |
140 | * If from other end of a point-to-point link that isn't | |
141 | * in the routing tables, (re-)add the route. | |
142 | */ | |
09069ad0 MK |
143 | if ((rt = rtfind(from)) && |
144 | (rt->rt_state & (RTS_INTERFACE | RTS_REMOTE))) | |
b7e4f8be | 145 | rt->rt_timer = 0; |
7892134c MK |
146 | else if ((ifp = if_ifwithdstaddr(from)) && |
147 | (rt == 0 || rt->rt_metric >= ifp->int_metric)) | |
f1e15e15 | 148 | addrouteforif(ifp); |
71786f50 MK |
149 | /* |
150 | * "Authenticate" router from which message originated. | |
151 | * We accept routing packets from routers directly connected | |
152 | * via broadcast or point-to-point networks, | |
153 | * and from those listed in /etc/gateways. | |
154 | */ | |
155 | if ((ifp = if_iflookup(from)) == 0 || (ifp->int_flags & | |
98a1809a MK |
156 | (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 || |
157 | ifp->int_flags & IFF_PASSIVE) { | |
eb39c032 MK |
158 | if (bcmp((char *)from, (char *)&badfrom, |
159 | sizeof(badfrom)) != 0) { | |
160 | syslog(LOG_ERR, | |
161 | "packet from unknown router, %s", | |
162 | (*afswitch[from->sa_family].af_format)(from)); | |
163 | badfrom = *from; | |
164 | } | |
09069ad0 MK |
165 | return; |
166 | } | |
2e74322d SL |
167 | size -= 4 * sizeof (char); |
168 | n = msg->rip_nets; | |
169 | for (; size > 0; size -= sizeof (struct netinfo), n++) { | |
170 | if (size < sizeof (struct netinfo)) | |
171 | break; | |
55d340a4 SL |
172 | if (msg->rip_vers > 0) { |
173 | n->rip_dst.sa_family = | |
174 | ntohs(n->rip_dst.sa_family); | |
175 | n->rip_metric = ntohl(n->rip_metric); | |
176 | } | |
17fe297f MK |
177 | if (n->rip_dst.sa_family >= af_max || |
178 | (afp = &afswitch[n->rip_dst.sa_family])->af_hash == | |
179 | (int (*)())0) { | |
180 | syslog(LOG_INFO, | |
181 | "route in unsupported address family (%d), from %s (af %d)\n", | |
182 | n->rip_dst.sa_family, | |
183 | (*afswitch[from->sa_family].af_format)(from), | |
184 | from->sa_family); | |
ed36994a | 185 | continue; |
17fe297f MK |
186 | } |
187 | if (((*afp->af_checkhost)(&n->rip_dst)) == 0) { | |
188 | syslog(LOG_DEBUG, | |
189 | "bad host in route from %s (af %d)\n", | |
190 | (*afswitch[from->sa_family].af_format)(from), | |
191 | from->sa_family); | |
2e74322d | 192 | continue; |
17fe297f | 193 | } |
09b9aef2 MK |
194 | if (n->rip_metric == 0 || |
195 | (unsigned) n->rip_metric > HOPCNT_INFINITY) { | |
196 | if (bcmp((char *)from, (char *)&badfrom2, | |
197 | sizeof(badfrom2)) != 0) { | |
198 | syslog(LOG_ERR, | |
199 | "bad metric (%d) from %s\n", | |
200 | n->rip_metric, | |
201 | (*afswitch[from->sa_family].af_format)(from)); | |
202 | badfrom2 = *from; | |
203 | } | |
204 | continue; | |
205 | } | |
7892134c MK |
206 | /* |
207 | * Adjust metric according to incoming interface. | |
208 | */ | |
cdf21aa5 | 209 | if ((unsigned) n->rip_metric < HOPCNT_INFINITY) |
7892134c | 210 | n->rip_metric += ifp->int_metric; |
cdf21aa5 MK |
211 | if ((unsigned) n->rip_metric > HOPCNT_INFINITY) |
212 | n->rip_metric = HOPCNT_INFINITY; | |
2e74322d | 213 | rt = rtlookup(&n->rip_dst); |
97cb3618 MK |
214 | if (rt == 0 || |
215 | (rt->rt_state & (RTS_INTERNAL|RTS_INTERFACE)) == | |
216 | (RTS_INTERNAL|RTS_INTERFACE)) { | |
7892134c MK |
217 | /* |
218 | * If we're hearing a logical network route | |
219 | * back from a peer to which we sent it, | |
220 | * ignore it. | |
221 | */ | |
222 | if (rt && rt->rt_state & RTS_SUBNET && | |
223 | (*afp->af_sendroute)(rt, from)) | |
224 | continue; | |
0f7c421b MK |
225 | if ((unsigned)n->rip_metric < HOPCNT_INFINITY) { |
226 | /* | |
227 | * Look for an equivalent route that | |
228 | * includes this one before adding | |
229 | * this route. | |
230 | */ | |
231 | rt = rtfind(&n->rip_dst); | |
232 | if (rt && equal(from, &rt->rt_router)) | |
233 | continue; | |
20df59f1 | 234 | rtadd(&n->rip_dst, from, n->rip_metric, 0); |
0f7c421b | 235 | } |
2e74322d SL |
236 | continue; |
237 | } | |
238 | ||
239 | /* | |
38ca17a8 | 240 | * Update if from gateway and different, |
0f7c421b MK |
241 | * shorter, or equivalent but old route |
242 | * is getting stale. | |
2e74322d | 243 | */ |
15e56604 | 244 | if (equal(from, &rt->rt_router)) { |
88709531 | 245 | if (n->rip_metric != rt->rt_metric) { |
15e56604 | 246 | rtchange(rt, from, n->rip_metric); |
0f7c421b | 247 | rt->rt_timer = 0; |
7892134c | 248 | if (rt->rt_metric >= HOPCNT_INFINITY) |
88709531 MK |
249 | rt->rt_timer = |
250 | GARBAGE_TIME - EXPIRE_TIME; | |
251 | } else if (rt->rt_metric < HOPCNT_INFINITY) | |
585e6328 | 252 | rt->rt_timer = 0; |
cdf21aa5 | 253 | } else if ((unsigned) n->rip_metric < rt->rt_metric || |
0f7c421b MK |
254 | (rt->rt_metric == n->rip_metric && |
255 | rt->rt_timer > (EXPIRE_TIME/2) && | |
cdf21aa5 | 256 | (unsigned) n->rip_metric < HOPCNT_INFINITY)) { |
2e74322d SL |
257 | rtchange(rt, from, n->rip_metric); |
258 | rt->rt_timer = 0; | |
259 | } | |
260 | } | |
261 | return; | |
262 | } | |
263 | } |