xref: /csrg-svn/sbin/XNSrouted/input.c (revision 61474)
124328Ssklower /*
2*61474Sbostic  * Copyright (c) 1985, 1993
3*61474Sbostic  *	The Regents of the University of California.  All rights reserved.
424328Ssklower  *
535551Sbostic  * This file includes significant work done at Cornell University by
635551Sbostic  * Bill Nesheim.  That work included by permission.
735551Sbostic  *
842698Sbostic  * %sccs.include.redist.c%
924328Ssklower  */
1024328Ssklower 
1124307Ssklower #ifndef lint
12*61474Sbostic static char sccsid[] = "@(#)input.c	8.1 (Berkeley) 06/05/93";
1335551Sbostic #endif /* not lint */
1424307Ssklower 
1524307Ssklower /*
1624307Ssklower  * XNS Routing Table Management Daemon
1724307Ssklower  */
1824307Ssklower #include "defs.h"
1924307Ssklower 
2024307Ssklower struct sockaddr *
xns_nettosa(net)2124307Ssklower xns_nettosa(net)
2226170Ssklower union ns_net net;
2324307Ssklower {
2424317Ssklower 	static struct sockaddr_ns sxn;
2524317Ssklower 	extern char ether_broadcast_addr[6];
2624307Ssklower 
2724317Ssklower 	bzero(&sxn, sizeof (struct sockaddr_ns));
2824317Ssklower 	sxn.sns_family = AF_NS;
2938687Ssklower 	sxn.sns_len = sizeof (sxn);
3026170Ssklower 	sxn.sns_addr.x_net = net;
3124317Ssklower 	sxn.sns_addr.x_host = *(union ns_host *)ether_broadcast_addr;
3224307Ssklower 	return( (struct sockaddr *)&sxn);
3324307Ssklower 
3424307Ssklower }
3524307Ssklower 
3624307Ssklower /*
3724307Ssklower  * Process a newly received packet.
3824307Ssklower  */
3924307Ssklower rip_input(from, size)
4024307Ssklower 	struct sockaddr *from;
4124307Ssklower 	int size;
4224307Ssklower {
4324307Ssklower 	struct rt_entry *rt;
4424307Ssklower 	struct netinfo *n;
4524307Ssklower 	struct interface *ifp;
4624307Ssklower 	int newsize;
4724307Ssklower 	struct afswitch *afp;
4824307Ssklower 
4924307Ssklower 
5024317Ssklower 	ifp = 0;
5124307Ssklower 	TRACE_INPUT(ifp, from, size);
5224307Ssklower 	if (from->sa_family >= AF_MAX)
5324307Ssklower 		return;
5424307Ssklower 	afp = &afswitch[from->sa_family];
5524307Ssklower 
5624307Ssklower 	size -= sizeof (u_short)	/* command */;
5724307Ssklower 	n = msg->rip_nets;
5824307Ssklower 
5924307Ssklower 	switch (ntohs(msg->rip_cmd)) {
6024307Ssklower 
6124307Ssklower 	case RIPCMD_REQUEST:
6224307Ssklower 		newsize = 0;
6324307Ssklower 		while (size > 0) {
6424307Ssklower 			if (size < sizeof (struct netinfo))
6524307Ssklower 				break;
6624307Ssklower 			size -= sizeof (struct netinfo);
6724307Ssklower 
6824307Ssklower 			/*
6924307Ssklower 			 * A single entry with rip_dst == DSTNETS_ALL and
7024307Ssklower 			 * metric ``infinity'' means ``all routes''.
7124307Ssklower 			 */
7226170Ssklower 			if (ns_neteqnn(n->rip_dst, ns_anynet) &&
7324317Ssklower 		            ntohs(n->rip_metric) == HOPCNT_INFINITY &&
7424317Ssklower 			    size == 0) {
7524317Ssklower 				ifp = if_ifwithnet(from);
7624317Ssklower 				supply(from, 0, ifp);
7724307Ssklower 				return;
7824307Ssklower 			}
7924307Ssklower 			/*
8024307Ssklower 			 * request for specific nets
8124307Ssklower 			 */
8224307Ssklower 			rt = rtlookup(xns_nettosa(n->rip_dst));
8324875Ssklower 			if (ftrace) {
8424328Ssklower 				fprintf(ftrace,
8526170Ssklower 					"specific request for %s",
8626170Ssklower 					xns_nettoa(n->rip_dst));
8724328Ssklower 				fprintf(ftrace,
8826170Ssklower 					" yields route %x\n",
8924328Ssklower 					rt);
9024328Ssklower 			}
9124307Ssklower 			n->rip_metric = htons( rt == 0 ? HOPCNT_INFINITY :
9224307Ssklower 				min(rt->rt_metric+1, HOPCNT_INFINITY));
9326170Ssklower 			n++;
9426170Ssklower 		        newsize += sizeof (struct netinfo);
9524307Ssklower 		}
9624307Ssklower 		if (newsize > 0) {
9724307Ssklower 			msg->rip_cmd = htons(RIPCMD_RESPONSE);
9824307Ssklower 			newsize += sizeof (u_short);
9924307Ssklower 			/* should check for if with dstaddr(from) first */
10024875Ssklower 			(*afp->af_output)(0, from, newsize);
10126170Ssklower 			ifp = if_ifwithnet(from);
10226170Ssklower 			TRACE_OUTPUT(ifp, from, newsize);
10324875Ssklower 			if (ftrace) {
10424328Ssklower 				fprintf(ftrace,
10526170Ssklower 					"request arrived on interface %s\n",
10626170Ssklower 					ifp->int_name);
10724328Ssklower 			}
10824307Ssklower 		}
10924307Ssklower 		return;
11024307Ssklower 
11124307Ssklower 	case RIPCMD_RESPONSE:
11224307Ssklower 		/* verify message came from a router */
11324307Ssklower 		if ((*afp->af_portmatch)(from) == 0)
11424307Ssklower 			return;
11524317Ssklower 		(*afp->af_canon)(from);
11624317Ssklower 		/* are we talking to ourselves? */
11724317Ssklower 		if (ifp = if_ifwithaddr(from)) {
11824317Ssklower 			rt = rtfind(from);
11924317Ssklower 			if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0)
12024317Ssklower 				addrouteforif(ifp);
12124317Ssklower 			else
12224317Ssklower 				rt->rt_timer = 0;
12324317Ssklower 			return;
12424317Ssklower 		}
12524328Ssklower 		/* Update timer for interface on which the packet arrived.
12624328Ssklower 		 * If from other end of a point-to-point link that isn't
12724328Ssklower 		 * in the routing tables, (re-)add the route.
12824328Ssklower 		 */
12924328Ssklower 		if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE)) {
13024875Ssklower 			if(ftrace) fprintf(ftrace, "Got route\n");
13124307Ssklower 			rt->rt_timer = 0;
13224328Ssklower 		} else if (ifp = if_ifwithdstaddr(from)) {
13324875Ssklower 			if(ftrace) fprintf(ftrace, "Got partner\n");
13424328Ssklower 			addrouteforif(ifp);
13524328Ssklower 		}
13624307Ssklower 		for (; size > 0; size -= sizeof (struct netinfo), n++) {
13724328Ssklower 			struct sockaddr *sa;
13824307Ssklower 			if (size < sizeof (struct netinfo))
13924307Ssklower 				break;
14025507Ssklower 			if ((unsigned) ntohs(n->rip_metric) >= HOPCNT_INFINITY)
14124307Ssklower 				continue;
14224328Ssklower 			rt = rtfind(sa = xns_nettosa(n->rip_dst));
14324307Ssklower 			if (rt == 0) {
14424328Ssklower 				rtadd(sa, from, ntohs(n->rip_metric), 0);
14524307Ssklower 				continue;
14624307Ssklower 			}
14724307Ssklower 
14824307Ssklower 			/*
14924307Ssklower 			 * Update if from gateway and different,
15024307Ssklower 			 * from anywhere and shorter, or getting stale and equivalent.
15124307Ssklower 			 */
15224307Ssklower 			if ((equal(from, &rt->rt_router) &&
15324307Ssklower 			    ntohs(n->rip_metric) != rt->rt_metric ) ||
15424307Ssklower 			    (unsigned) ntohs(n->rip_metric) < rt->rt_metric ||
15524307Ssklower 			    (rt->rt_timer > (EXPIRE_TIME/2) &&
15624307Ssklower 			    rt->rt_metric == ntohs(n->rip_metric))) {
15724307Ssklower 				rtchange(rt, from, ntohs(n->rip_metric));
15824307Ssklower 				rt->rt_timer = 0;
15924307Ssklower 			}
16024307Ssklower 		}
16124307Ssklower 		return;
16224307Ssklower 	}
16324307Ssklower }
164