1: /*
2: * Copyright (c) 1983 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char sccsid[] = "@(#)input.c 5.6 (Berkeley) 6/3/86";
9: #endif not lint
10:
11: /*
12: * Routing Table Management Daemon
13: */
14: #include "defs.h"
15: #include <sys/syslog.h>
16:
17: /*
18: * Process a newly received packet.
19: */
20: rip_input(from, size)
21: struct sockaddr *from;
22: int size;
23: {
24: register struct rt_entry *rt;
25: register struct netinfo *n;
26: register struct interface *ifp;
27: struct interface *if_ifwithdstaddr();
28: int newsize;
29: register struct afswitch *afp;
30:
31: ifp = 0;
32: TRACE_INPUT(ifp, from, size);
33: if (from->sa_family >= af_max ||
34: (afp = &afswitch[from->sa_family])->af_hash == (int (*)())0) {
35: syslog(LOG_INFO,
36: "\"from\" address in unsupported address family (%d), cmd %d\n",
37: from->sa_family, msg->rip_cmd);
38: return;
39: }
40: switch (msg->rip_cmd) {
41:
42: case RIPCMD_REQUEST:
43: newsize = 0;
44: size -= 4 * sizeof (char);
45: n = msg->rip_nets;
46: while (size > 0) {
47: if (size < sizeof (struct netinfo))
48: break;
49: size -= sizeof (struct netinfo);
50:
51: if (msg->rip_vers > 0) {
52: n->rip_dst.sa_family =
53: ntohs(n->rip_dst.sa_family);
54: n->rip_metric = ntohl(n->rip_metric);
55: }
56: /*
57: * A single entry with sa_family == AF_UNSPEC and
58: * metric ``infinity'' means ``all routes''.
59: * We respond to routers only if we are acting
60: * as a supplier, or to anyone other than a router
61: * (eg, query).
62: */
63: if (n->rip_dst.sa_family == AF_UNSPEC &&
64: n->rip_metric == HOPCNT_INFINITY && size == 0) {
65: if (supplier || (*afp->af_portmatch)(from) == 0)
66: supply(from, 0, 0);
67: return;
68: }
69: if (n->rip_dst.sa_family < af_max &&
70: afswitch[n->rip_dst.sa_family].af_hash)
71: rt = rtlookup(&n->rip_dst);
72: else
73: rt = 0;
74: n->rip_metric = rt == 0 ? HOPCNT_INFINITY :
75: min(rt->rt_metric+1, HOPCNT_INFINITY);
76: if (msg->rip_vers > 0) {
77: n->rip_dst.sa_family =
78: htons(n->rip_dst.sa_family);
79: n->rip_metric = htonl(n->rip_metric);
80: }
81: n++, newsize += sizeof (struct netinfo);
82: }
83: if (newsize > 0) {
84: msg->rip_cmd = RIPCMD_RESPONSE;
85: newsize += sizeof (int);
86: (*afp->af_output)(s, 0, from, newsize);
87: }
88: return;
89:
90: case RIPCMD_TRACEON:
91: case RIPCMD_TRACEOFF:
92: /* verify message came from a privileged port */
93: if ((*afp->af_portcheck)(from) == 0)
94: return;
95: if (if_iflookup(from) == 0) {
96: syslog(LOG_ERR, "trace command from unknown router, %s",
97: (*afswitch[from->sa_family].af_format)(from));
98: return;
99: }
100: packet[size] = '\0';
101: if (msg->rip_cmd == RIPCMD_TRACEON)
102: traceon(msg->rip_tracefile);
103: else
104: traceoff();
105: return;
106:
107: case RIPCMD_RESPONSE:
108: /* verify message came from a router */
109: if ((*afp->af_portmatch)(from) == 0)
110: return;
111: (*afp->af_canon)(from);
112: /* are we talking to ourselves? */
113: ifp = if_ifwithaddr(from);
114: if (ifp) {
115: rt = rtfind(from);
116: if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0)
117: addrouteforif(ifp);
118: else
119: rt->rt_timer = 0;
120: return;
121: }
122: /*
123: * Update timer for interface on which the packet arrived.
124: * If from other end of a point-to-point link that isn't
125: * in the routing tables, (re-)add the route.
126: */
127: if ((rt = rtfind(from)) &&
128: (rt->rt_state & (RTS_INTERFACE | RTS_REMOTE)))
129: rt->rt_timer = 0;
130: else if (ifp = if_ifwithdstaddr(from))
131: addrouteforif(ifp);
132: else if (if_iflookup(from) == 0) {
133: syslog(LOG_ERR, "packet from unknown router, %s",
134: (*afswitch[from->sa_family].af_format)(from));
135: return;
136: }
137: size -= 4 * sizeof (char);
138: n = msg->rip_nets;
139: for (; size > 0; size -= sizeof (struct netinfo), n++) {
140: if (size < sizeof (struct netinfo))
141: break;
142: if (msg->rip_vers > 0) {
143: n->rip_dst.sa_family =
144: ntohs(n->rip_dst.sa_family);
145: n->rip_metric = ntohl(n->rip_metric);
146: }
147: if ((unsigned) n->rip_metric > HOPCNT_INFINITY)
148: continue;
149: if (n->rip_dst.sa_family >= af_max ||
150: (afp = &afswitch[n->rip_dst.sa_family])->af_hash ==
151: (int (*)())0) {
152: syslog(LOG_INFO,
153: "route in unsupported address family (%d), from %s (af %d)\n",
154: n->rip_dst.sa_family,
155: (*afswitch[from->sa_family].af_format)(from),
156: from->sa_family);
157: continue;
158: }
159: if (((*afp->af_checkhost)(&n->rip_dst)) == 0) {
160: syslog(LOG_DEBUG,
161: "bad host in route from %s (af %d)\n",
162: (*afswitch[from->sa_family].af_format)(from),
163: from->sa_family);
164: continue;
165: }
166: rt = rtlookup(&n->rip_dst);
167: if (rt == 0 ||
168: (rt->rt_state & (RTS_INTERNAL|RTS_INTERFACE)) ==
169: (RTS_INTERNAL|RTS_INTERFACE)) {
170: rt = rtfind(&n->rip_dst);
171: if (rt && equal(from, &rt->rt_router) &&
172: rt->rt_metric == n->rip_metric)
173: continue;
174: if (n->rip_metric < HOPCNT_INFINITY)
175: rtadd(&n->rip_dst, from, n->rip_metric, 0);
176: continue;
177: }
178:
179: /*
180: * Update if from gateway and different,
181: * shorter, or getting stale and equivalent.
182: */
183: if (equal(from, &rt->rt_router)) {
184: if (n->rip_metric == HOPCNT_INFINITY) {
185: rtdelete(rt);
186: continue;
187: }
188: if (n->rip_metric != rt->rt_metric)
189: rtchange(rt, from, n->rip_metric);
190: rt->rt_timer = 0;
191: } else if ((unsigned) (n->rip_metric) < rt->rt_metric ||
192: (rt->rt_timer > (EXPIRE_TIME/2) &&
193: rt->rt_metric == n->rip_metric)) {
194: rtchange(rt, from, n->rip_metric);
195: rt->rt_timer = 0;
196: }
197: }
198: return;
199: }
200: }
Defined functions
Defined variables
sccsid
defined in line
8;
never used