xref: /csrg-svn/sbin/routed/input.c (revision 12156)
19016Ssam #ifndef lint
2*12156Ssam static char sccsid[] = "@(#)input.c	4.3 05/01/83";
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 {
179016Ssam 	struct rt_entry *rt;
189016Ssam 	struct netinfo *n;
199016Ssam 	struct interface *ifp;
209016Ssam 	int newsize;
219016Ssam 	struct afswitch *afp;
229016Ssam 
239016Ssam 	ifp = 0;
249016Ssam 	TRACE_INPUT(ifp, from, size);
259016Ssam 	if (from->sa_family >= AF_MAX)
269016Ssam 		return;
279016Ssam 	afp = &afswitch[from->sa_family];
289016Ssam 	switch (msg->rip_cmd) {
299016Ssam 
309016Ssam 	case RIPCMD_REQUEST:
319016Ssam 		newsize = 0;
329016Ssam 		size -= 4 * sizeof (char);
339016Ssam 		n = msg->rip_nets;
349016Ssam 		while (size > 0) {
359016Ssam 			if (size < sizeof (struct netinfo))
369016Ssam 				break;
379016Ssam 			size -= sizeof (struct netinfo);
389016Ssam 
399016Ssam 			/*
409016Ssam 			 * A single entry with sa_family == AF_UNSPEC and
419016Ssam 			 * metric ``infinity'' means ``all routes''.
429016Ssam 			 */
439016Ssam 			if (n->rip_dst.sa_family == AF_UNSPEC &&
449016Ssam 			    n->rip_metric == HOPCNT_INFINITY && size == 0) {
459016Ssam 				supply(from, 0, ifp);
469016Ssam 				return;
479016Ssam 			}
489016Ssam 			rt = rtlookup(&n->rip_dst);
499016Ssam 			n->rip_metric = rt == 0 ? HOPCNT_INFINITY :
509016Ssam 				min(rt->rt_metric+1, HOPCNT_INFINITY);
519016Ssam 			n++, newsize += sizeof (struct netinfo);
529016Ssam 		}
539016Ssam 		if (newsize > 0) {
549016Ssam 			msg->rip_cmd = RIPCMD_RESPONSE;
559016Ssam 			newsize += sizeof (int);
56*12156Ssam 			(*afp->af_output)(s, 0, from, newsize);
579016Ssam 		}
589016Ssam 		return;
599016Ssam 
609016Ssam 	case RIPCMD_TRACEON:
619016Ssam 	case RIPCMD_TRACEOFF:
629016Ssam 		/* verify message came from a priviledged port */
639016Ssam 		if ((*afp->af_portcheck)(from) == 0)
649016Ssam 			return;
659016Ssam 		packet[size] = '\0';
669016Ssam 		if (msg->rip_cmd == RIPCMD_TRACEON)
679016Ssam 			traceon(msg->rip_tracefile);
689016Ssam 		else
699016Ssam 			traceoff();
709016Ssam 		return;
719016Ssam 
729016Ssam 	case RIPCMD_RESPONSE:
739016Ssam 		/* verify message came from a router */
749016Ssam 		if ((*afp->af_portmatch)(from) == 0)
759016Ssam 			return;
769016Ssam 		(*afp->af_canon)(from);
779016Ssam 		/* are we talking to ourselves? */
789016Ssam 		ifp = if_ifwithaddr(from);
799016Ssam 		if (ifp) {
809016Ssam 			rt = rtfind(from);
819016Ssam 			if (rt == 0)
829016Ssam 				addrouteforif(ifp);
839016Ssam 			else
849016Ssam 				rt->rt_timer = 0;
859016Ssam 			return;
869016Ssam 		}
879016Ssam 		size -= 4 * sizeof (char);
889016Ssam 		n = msg->rip_nets;
899016Ssam 		for (; size > 0; size -= sizeof (struct netinfo), n++) {
909016Ssam 			if (size < sizeof (struct netinfo))
919016Ssam 				break;
929016Ssam 			if (n->rip_metric >= HOPCNT_INFINITY)
939016Ssam 				continue;
949016Ssam 			rt = rtlookup(&n->rip_dst);
959016Ssam 			if (rt == 0) {
969016Ssam 				rtadd(&n->rip_dst, from, n->rip_metric, 0);
979016Ssam 				continue;
989016Ssam 			}
999016Ssam 
1009016Ssam 			/*
1019016Ssam 			 * Update if from gateway, shorter, or getting
1029016Ssam 			 * stale and equivalent.
1039016Ssam 			 */
1049016Ssam 			if (equal(from, &rt->rt_router) ||
1059016Ssam 			    n->rip_metric < rt->rt_metric ||
1069016Ssam 			    (rt->rt_timer > (EXPIRE_TIME/2) &&
1079016Ssam 			    rt->rt_metric == n->rip_metric)) {
1089016Ssam 				rtchange(rt, from, n->rip_metric);
1099016Ssam 				rt->rt_timer = 0;
1109016Ssam 			}
1119016Ssam 		}
1129016Ssam 		return;
1139016Ssam 	}
1149016Ssam }
115