dist -> vaxdist
[unix-history] / usr / src / sbin / routed / input.c
CommitLineData
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 14static 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 */
26rip_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}