xref: /csrg-svn/sbin/routed/input.c (revision 21836)
19016Ssam #ifndef lint
2*21836Skarels static char sccsid[] = "@(#)input.c	4.12 (Berkeley) 06/03/85";
39016Ssam #endif
49016Ssam 
59016Ssam /*
69016Ssam  * Routing Table Management Daemon
79016Ssam  */
810245Ssam #include "defs.h"
99016Ssam 
109016Ssam /*
119016Ssam  * Process a newly received packet.
129016Ssam  */
139016Ssam rip_input(from, size)
149016Ssam 	struct sockaddr *from;
159016Ssam 	int size;
169016Ssam {
17*21836Skarels 	register struct rt_entry *rt;
18*21836Skarels 	register struct netinfo *n;
19*21836Skarels 	register struct interface *ifp;
20*21836Skarels 	struct interface *if_ifwithdstaddr();
219016Ssam 	int newsize;
22*21836Skarels 	register struct afswitch *afp;
239016Ssam 
249016Ssam 	ifp = 0;
259016Ssam 	TRACE_INPUT(ifp, from, size);
269016Ssam 	if (from->sa_family >= AF_MAX)
279016Ssam 		return;
289016Ssam 	afp = &afswitch[from->sa_family];
299016Ssam 	switch (msg->rip_cmd) {
309016Ssam 
319016Ssam 	case RIPCMD_REQUEST:
329016Ssam 		newsize = 0;
339016Ssam 		size -= 4 * sizeof (char);
349016Ssam 		n = msg->rip_nets;
359016Ssam 		while (size > 0) {
369016Ssam 			if (size < sizeof (struct netinfo))
379016Ssam 				break;
389016Ssam 			size -= sizeof (struct netinfo);
399016Ssam 
4012726Ssam 			if (msg->rip_vers > 0) {
4112726Ssam 				n->rip_dst.sa_family =
4212726Ssam 					ntohs(n->rip_dst.sa_family);
4312726Ssam 				n->rip_metric = ntohl(n->rip_metric);
4412726Ssam 			}
459016Ssam 			/*
469016Ssam 			 * A single entry with sa_family == AF_UNSPEC and
479016Ssam 			 * metric ``infinity'' means ``all routes''.
489016Ssam 			 */
499016Ssam 			if (n->rip_dst.sa_family == AF_UNSPEC &&
509016Ssam 			    n->rip_metric == HOPCNT_INFINITY && size == 0) {
519016Ssam 				supply(from, 0, ifp);
529016Ssam 				return;
539016Ssam 			}
549016Ssam 			rt = rtlookup(&n->rip_dst);
559016Ssam 			n->rip_metric = rt == 0 ? HOPCNT_INFINITY :
569016Ssam 				min(rt->rt_metric+1, HOPCNT_INFINITY);
5712726Ssam 			if (msg->rip_vers > 0) {
5812726Ssam 				n->rip_dst.sa_family =
5912726Ssam 					htons(n->rip_dst.sa_family);
6012726Ssam 				n->rip_metric = htonl(n->rip_metric);
6112726Ssam 			}
629016Ssam 			n++, newsize += sizeof (struct netinfo);
639016Ssam 		}
649016Ssam 		if (newsize > 0) {
659016Ssam 			msg->rip_cmd = RIPCMD_RESPONSE;
669016Ssam 			newsize += sizeof (int);
6712156Ssam 			(*afp->af_output)(s, 0, from, newsize);
689016Ssam 		}
699016Ssam 		return;
709016Ssam 
719016Ssam 	case RIPCMD_TRACEON:
729016Ssam 	case RIPCMD_TRACEOFF:
7316314Skarels 		/* verify message came from a privileged port */
749016Ssam 		if ((*afp->af_portcheck)(from) == 0)
759016Ssam 			return;
769016Ssam 		packet[size] = '\0';
779016Ssam 		if (msg->rip_cmd == RIPCMD_TRACEON)
789016Ssam 			traceon(msg->rip_tracefile);
799016Ssam 		else
809016Ssam 			traceoff();
819016Ssam 		return;
829016Ssam 
839016Ssam 	case RIPCMD_RESPONSE:
849016Ssam 		/* verify message came from a router */
859016Ssam 		if ((*afp->af_portmatch)(from) == 0)
869016Ssam 			return;
879016Ssam 		(*afp->af_canon)(from);
889016Ssam 		/* are we talking to ourselves? */
899016Ssam 		ifp = if_ifwithaddr(from);
909016Ssam 		if (ifp) {
919016Ssam 			rt = rtfind(from);
9216314Skarels 			if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0)
939016Ssam 				addrouteforif(ifp);
949016Ssam 			else
959016Ssam 				rt->rt_timer = 0;
969016Ssam 			return;
979016Ssam 		}
9817573Skarels 		/*
9917573Skarels 		 * Update timer for interface on which the packet arrived.
10017573Skarels 		 * If from other end of a point-to-point link that isn't
10117573Skarels 		 * in the routing tables, (re-)add the route.
10217573Skarels 		 */
10316314Skarels 		if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE))
10416314Skarels 			rt->rt_timer = 0;
10517573Skarels 		else if (ifp = if_ifwithdstaddr(from))
10617573Skarels 			addrouteforif(ifp);
1079016Ssam 		size -= 4 * sizeof (char);
1089016Ssam 		n = msg->rip_nets;
1099016Ssam 		for (; size > 0; size -= sizeof (struct netinfo), n++) {
1109016Ssam 			if (size < sizeof (struct netinfo))
1119016Ssam 				break;
11212726Ssam 			if (msg->rip_vers > 0) {
11312726Ssam 				n->rip_dst.sa_family =
11412726Ssam 					ntohs(n->rip_dst.sa_family);
11512726Ssam 				n->rip_metric = ntohl(n->rip_metric);
11612726Ssam 			}
117*21836Skarels 			if ((unsigned) n->rip_metric > HOPCNT_INFINITY)
1189016Ssam 				continue;
11916753Skarels 			if (n->rip_dst.sa_family >= AF_MAX)
12016753Skarels 				continue;
12116753Skarels 			afp = &afswitch[n->rip_dst.sa_family];
12216128Skarels 			if (((*afp->af_checkhost)(&n->rip_dst)) == 0)
12316128Skarels 				continue;
1249016Ssam 			rt = rtlookup(&n->rip_dst);
1259016Ssam 			if (rt == 0) {
126*21836Skarels 				if (n->rip_metric < HOPCNT_INFINITY)
127*21836Skarels 				    rtadd(&n->rip_dst, from, n->rip_metric, 0);
1289016Ssam 				continue;
1299016Ssam 			}
1309016Ssam 
1319016Ssam 			/*
13216323Skarels 			 * Update if from gateway and different,
13316323Skarels 			 * shorter, or getting stale and equivalent.
1349016Ssam 			 */
13518112Skarels 			if (equal(from, &rt->rt_router)) {
136*21836Skarels 				if (n->rip_metric == HOPCNT_INFINITY) {
137*21836Skarels 					rtdelete(rt);
138*21836Skarels 					continue;
139*21836Skarels 				}
14018112Skarels 				if (n->rip_metric != rt->rt_metric)
14118112Skarels 					rtchange(rt, from, n->rip_metric);
14218112Skarels 				rt->rt_timer = 0;
14318112Skarels 			} else if ((unsigned) (n->rip_metric) < rt->rt_metric ||
1449016Ssam 			    (rt->rt_timer > (EXPIRE_TIME/2) &&
1459016Ssam 			    rt->rt_metric == n->rip_metric)) {
1469016Ssam 				rtchange(rt, from, n->rip_metric);
1479016Ssam 				rt->rt_timer = 0;
1489016Ssam 			}
1499016Ssam 		}
1509016Ssam 		return;
1519016Ssam 	}
1529016Ssam }
153