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