|
|
1.1 root 1: /*
2: * Copyright (c) 1983, 1988 Regents of the University of California.
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.
11: */
12:
13: #ifndef lint
14: static char sccsid[] = "@(#)input.c 5.17 (Berkeley) 6/6/88";
15: #endif /* not lint */
16:
17: /*
18: * Routing Table Management Daemon
19: */
20: #include "defs.h"
21: #include <sys/syslog.h>
22:
23: /*
24: * Process a newly received packet.
25: */
26: rip_input(from, size)
27: struct sockaddr *from;
28: int size;
29: {
30: register struct rt_entry *rt;
31: register struct netinfo *n;
32: register struct interface *ifp;
33: struct interface *if_ifwithdstaddr();
34: int newsize;
35: register struct afswitch *afp;
36: static struct sockaddr badfrom, badfrom2;
37:
38: ifp = 0;
39: TRACE_INPUT(ifp, from, size);
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);
45: return;
46: }
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:
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: }
63: /*
64: * A single entry with sa_family == AF_UNSPEC and
65: * metric ``infinity'' means ``all routes''.
66: * We respond to routers only if we are acting
67: * as a supplier, or to anyone other than a router
68: * (eg, query).
69: */
70: if (n->rip_dst.sa_family == AF_UNSPEC &&
71: n->rip_metric == HOPCNT_INFINITY && size == 0) {
72: if (supplier || (*afp->af_portmatch)(from) == 0)
73: supply(from, 0, 0);
74: return;
75: }
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;
81: n->rip_metric = rt == 0 ? HOPCNT_INFINITY :
82: min(rt->rt_metric + 1, HOPCNT_INFINITY);
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: }
88: n++, newsize += sizeof (struct netinfo);
89: }
90: if (newsize > 0) {
91: msg->rip_cmd = RIPCMD_RESPONSE;
92: newsize += sizeof (int);
93: (*afp->af_output)(s, 0, from, newsize);
94: }
95: return;
96:
97: case RIPCMD_TRACEON:
98: case RIPCMD_TRACEOFF:
99: /* verify message came from a privileged port */
100: if ((*afp->af_portcheck)(from) == 0)
101: return;
102: if ((ifp = if_iflookup(from)) == 0 || (ifp->int_flags &
103: (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 ||
104: ifp->int_flags & IFF_PASSIVE) {
105: syslog(LOG_ERR, "trace command from unknown router, %s",
106: (*afswitch[from->sa_family].af_format)(from));
107: return;
108: }
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) {
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: }
130: rt = rtfind(from);
131: if (rt == 0 || ((rt->rt_state & RTS_INTERFACE) == 0) &&
132: rt->rt_metric >= ifp->int_metric)
133: addrouteforif(ifp);
134: else
135: rt->rt_timer = 0;
136: return;
137: }
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: */
143: if ((rt = rtfind(from)) &&
144: (rt->rt_state & (RTS_INTERFACE | RTS_REMOTE)))
145: rt->rt_timer = 0;
146: else if ((ifp = if_ifwithdstaddr(from)) &&
147: (rt == 0 || rt->rt_metric >= ifp->int_metric))
148: addrouteforif(ifp);
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 &
156: (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 ||
157: ifp->int_flags & IFF_PASSIVE) {
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: }
165: return;
166: }
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;
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: }
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);
185: continue;
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);
192: continue;
193: }
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: }
206: /*
207: * Adjust metric according to incoming interface.
208: */
209: if ((unsigned) n->rip_metric < HOPCNT_INFINITY)
210: n->rip_metric += ifp->int_metric;
211: if ((unsigned) n->rip_metric > HOPCNT_INFINITY)
212: n->rip_metric = HOPCNT_INFINITY;
213: rt = rtlookup(&n->rip_dst);
214: if (rt == 0 ||
215: (rt->rt_state & (RTS_INTERNAL|RTS_INTERFACE)) ==
216: (RTS_INTERNAL|RTS_INTERFACE)) {
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;
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;
234: rtadd(&n->rip_dst, from, n->rip_metric, 0);
235: }
236: continue;
237: }
238:
239: /*
240: * Update if from gateway and different,
241: * shorter, or equivalent but old route
242: * is getting stale.
243: */
244: if (equal(from, &rt->rt_router)) {
245: if (n->rip_metric != rt->rt_metric) {
246: rtchange(rt, from, n->rip_metric);
247: rt->rt_timer = 0;
248: if (rt->rt_metric >= HOPCNT_INFINITY)
249: rt->rt_timer =
250: GARBAGE_TIME - EXPIRE_TIME;
251: } else if (rt->rt_metric < HOPCNT_INFINITY)
252: rt->rt_timer = 0;
253: } else if ((unsigned) n->rip_metric < rt->rt_metric ||
254: (rt->rt_metric == n->rip_metric &&
255: rt->rt_timer > (EXPIRE_TIME/2) &&
256: (unsigned) n->rip_metric < HOPCNT_INFINITY)) {
257: rtchange(rt, from, n->rip_metric);
258: rt->rt_timer = 0;
259: }
260: }
261: return;
262: }
263: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.