xref: /original-bsd/sbin/routed/input.c (revision f0fd5f8a)
1 #ifndef lint
2 static char sccsid[] = "@(#)input.c	4.1 11/02/82";
3 #endif
4 
5 /*
6  * Routing Table Management Daemon
7  */
8 #include "router.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 			/*
40 			 * A single entry with sa_family == AF_UNSPEC and
41 			 * metric ``infinity'' means ``all routes''.
42 			 */
43 			if (n->rip_dst.sa_family == AF_UNSPEC &&
44 			    n->rip_metric == HOPCNT_INFINITY && size == 0) {
45 				supply(from, 0, ifp);
46 				return;
47 			}
48 			rt = rtlookup(&n->rip_dst);
49 			n->rip_metric = rt == 0 ? HOPCNT_INFINITY :
50 				min(rt->rt_metric+1, HOPCNT_INFINITY);
51 			n++, newsize += sizeof (struct netinfo);
52 		}
53 		if (newsize > 0) {
54 			msg->rip_cmd = RIPCMD_RESPONSE;
55 			newsize += sizeof (int);
56 			(*afp->af_output)(s, from, newsize);
57 		}
58 		return;
59 
60 	case RIPCMD_TRACEON:
61 	case RIPCMD_TRACEOFF:
62 		/* verify message came from a priviledged port */
63 		if ((*afp->af_portcheck)(from) == 0)
64 			return;
65 		packet[size] = '\0';
66 		if (msg->rip_cmd == RIPCMD_TRACEON)
67 			traceon(msg->rip_tracefile);
68 		else
69 			traceoff();
70 		return;
71 
72 	case RIPCMD_RESPONSE:
73 		/* verify message came from a router */
74 		if ((*afp->af_portmatch)(from) == 0)
75 			return;
76 		(*afp->af_canon)(from);
77 		/* are we talking to ourselves? */
78 		ifp = if_ifwithaddr(from);
79 		if (ifp) {
80 			rt = rtfind(from);
81 			if (rt == 0)
82 				addrouteforif(ifp);
83 			else
84 				rt->rt_timer = 0;
85 			return;
86 		}
87 		size -= 4 * sizeof (char);
88 		n = msg->rip_nets;
89 		for (; size > 0; size -= sizeof (struct netinfo), n++) {
90 			if (size < sizeof (struct netinfo))
91 				break;
92 			if (n->rip_metric >= HOPCNT_INFINITY)
93 				continue;
94 			rt = rtlookup(&n->rip_dst);
95 			if (rt == 0) {
96 				rtadd(&n->rip_dst, from, n->rip_metric, 0);
97 				continue;
98 			}
99 
100 			/*
101 			 * Update if from gateway, shorter, or getting
102 			 * stale and equivalent.
103 			 */
104 			if (equal(from, &rt->rt_router) ||
105 			    n->rip_metric < rt->rt_metric ||
106 			    (rt->rt_timer > (EXPIRE_TIME/2) &&
107 			    rt->rt_metric == n->rip_metric)) {
108 				rtchange(rt, from, n->rip_metric);
109 				rt->rt_timer = 0;
110 			}
111 		}
112 		return;
113 	}
114 }
115