xref: /original-bsd/sbin/routed/input.c (revision 23a40993)
1 #ifndef lint
2 static char sccsid[] = "@(#)input.c	4.5 (Berkeley) 06/01/83";
3 #endif
4 
5 /*
6  * Routing Table Management Daemon
7  */
8 #include "defs.h"
9 
10 /*
11  * Process a newly received packet.
12  */
13 rip_input(from, size)
14 	struct sockaddr *from;
15 	int size;
16 {
17 	struct rt_entry *rt;
18 	struct netinfo *n;
19 	struct interface *ifp;
20 	int newsize;
21 	struct afswitch *afp;
22 
23 	ifp = 0;
24 	TRACE_INPUT(ifp, from, size);
25 	if (from->sa_family >= AF_MAX)
26 		return;
27 	afp = &afswitch[from->sa_family];
28 	switch (msg->rip_cmd) {
29 
30 	case RIPCMD_REQUEST:
31 		newsize = 0;
32 		size -= 4 * sizeof (char);
33 		n = msg->rip_nets;
34 		while (size > 0) {
35 			if (size < sizeof (struct netinfo))
36 				break;
37 			size -= sizeof (struct netinfo);
38 
39 			if (msg->rip_vers > 0) {
40 				n->rip_dst.sa_family =
41 					ntohs(n->rip_dst.sa_family);
42 				n->rip_metric = ntohl(n->rip_metric);
43 			}
44 			/*
45 			 * A single entry with sa_family == AF_UNSPEC and
46 			 * metric ``infinity'' means ``all routes''.
47 			 */
48 			if (n->rip_dst.sa_family == AF_UNSPEC &&
49 			    n->rip_metric == HOPCNT_INFINITY && size == 0) {
50 				supply(from, 0, ifp);
51 				return;
52 			}
53 			rt = rtlookup(&n->rip_dst);
54 			n->rip_metric = rt == 0 ? HOPCNT_INFINITY :
55 				min(rt->rt_metric+1, HOPCNT_INFINITY);
56 			if (msg->rip_vers > 0) {
57 				n->rip_dst.sa_family =
58 					htons(n->rip_dst.sa_family);
59 				n->rip_metric = htonl(n->rip_metric);
60 			}
61 			n++, newsize += sizeof (struct netinfo);
62 		}
63 		if (newsize > 0) {
64 			msg->rip_cmd = RIPCMD_RESPONSE;
65 			newsize += sizeof (int);
66 			(*afp->af_output)(s, 0, from, newsize);
67 		}
68 		return;
69 
70 	case RIPCMD_TRACEON:
71 	case RIPCMD_TRACEOFF:
72 		/* verify message came from a priviledged port */
73 		if ((*afp->af_portcheck)(from) == 0)
74 			return;
75 		packet[size] = '\0';
76 		if (msg->rip_cmd == RIPCMD_TRACEON)
77 			traceon(msg->rip_tracefile);
78 		else
79 			traceoff();
80 		return;
81 
82 	case RIPCMD_RESPONSE:
83 		/* verify message came from a router */
84 		if ((*afp->af_portmatch)(from) == 0)
85 			return;
86 		(*afp->af_canon)(from);
87 		/* are we talking to ourselves? */
88 		ifp = if_ifwithaddr(from);
89 		if (ifp) {
90 			rt = rtfind(from);
91 			if (rt == 0)
92 				addrouteforif(ifp);
93 			else
94 				rt->rt_timer = 0;
95 			return;
96 		}
97 		size -= 4 * sizeof (char);
98 		n = msg->rip_nets;
99 		for (; size > 0; size -= sizeof (struct netinfo), n++) {
100 			if (size < sizeof (struct netinfo))
101 				break;
102 			if (msg->rip_vers > 0) {
103 				n->rip_dst.sa_family =
104 					ntohs(n->rip_dst.sa_family);
105 				n->rip_metric = ntohl(n->rip_metric);
106 			}
107 			if (n->rip_metric >= HOPCNT_INFINITY)
108 				continue;
109 			rt = rtlookup(&n->rip_dst);
110 			if (rt == 0) {
111 				rtadd(&n->rip_dst, from, n->rip_metric, 0);
112 				continue;
113 			}
114 
115 			/*
116 			 * Update if from gateway, shorter, or getting
117 			 * stale and equivalent.
118 			 */
119 			if (equal(from, &rt->rt_router) ||
120 			    n->rip_metric < rt->rt_metric ||
121 			    (rt->rt_timer > (EXPIRE_TIME/2) &&
122 			    rt->rt_metric == n->rip_metric)) {
123 				rtchange(rt, from, n->rip_metric);
124 				rt->rt_timer = 0;
125 			}
126 		}
127 		return;
128 	}
129 }
130