xref: /csrg-svn/sbin/XNSrouted/input.c (revision 24875)
124328Ssklower /*
224328Ssklower  * Copyright (c) 1985 Regents of the University of California.
324328Ssklower  * All rights reserved.  The Berkeley software License Agreement
424328Ssklower  * specifies the terms and conditions for redistribution.
524328Ssklower  *
624328Ssklower  * Includes material written at Cornell University by Bill Nesheim,
724328Ssklower  * by permission of the author.
824328Ssklower  */
924328Ssklower 
1024328Ssklower 
1124307Ssklower #ifndef lint
12*24875Ssklower static char sccsid[] = "@(#)input.c	5.4 (Berkeley) 09/17/85";
1324328Ssklower #endif not lint
1424307Ssklower 
1524307Ssklower /*
1624307Ssklower  * XNS Routing Table Management Daemon
1724307Ssklower  */
1824307Ssklower #include "defs.h"
1924307Ssklower 
2024307Ssklower struct sockaddr *
2124307Ssklower xns_nettosa(net)
2224307Ssklower u_short *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;
2924317Ssklower 	xnnet(sxn.sns_addr.x_net) = xnnet(net[0]);
3024317Ssklower 	sxn.sns_addr.x_host = *(union ns_host *)ether_broadcast_addr;
3124307Ssklower 	return( (struct sockaddr *)&sxn);
3224307Ssklower 
3324307Ssklower }
3424307Ssklower 
3524307Ssklower /*
3624307Ssklower  * Process a newly received packet.
3724307Ssklower  */
3824307Ssklower rip_input(from, size)
3924307Ssklower 	struct sockaddr *from;
4024307Ssklower 	int size;
4124307Ssklower {
4224307Ssklower 	struct rt_entry *rt;
4324307Ssklower 	struct netinfo *n;
4424307Ssklower 	struct interface *ifp;
4524307Ssklower 	int newsize;
4624307Ssklower 	struct afswitch *afp;
4724307Ssklower 
4824307Ssklower 
4924317Ssklower 	ifp = 0;
5024307Ssklower 	TRACE_INPUT(ifp, from, size);
5124307Ssklower 	if (from->sa_family >= AF_MAX)
5224307Ssklower 		return;
5324307Ssklower 	afp = &afswitch[from->sa_family];
5424307Ssklower 
5524307Ssklower 	size -= sizeof (u_short)	/* command */;
5624307Ssklower 	n = msg->rip_nets;
5724307Ssklower 
5824307Ssklower 	switch (ntohs(msg->rip_cmd)) {
5924307Ssklower 
6024307Ssklower 	case RIPCMD_REQUEST:
6124307Ssklower 		newsize = 0;
6224307Ssklower 		while (size > 0) {
6324307Ssklower 			if (size < sizeof (struct netinfo))
6424307Ssklower 				break;
6524307Ssklower 			size -= sizeof (struct netinfo);
6624307Ssklower 
6724307Ssklower 			/*
6824307Ssklower 			 * A single entry with rip_dst == DSTNETS_ALL and
6924307Ssklower 			 * metric ``infinity'' means ``all routes''.
7024307Ssklower 			 */
7124317Ssklower 			if (ntohl(xnnet(n->rip_dst[0])) == DSTNETS_ALL &&
7224317Ssklower 		            ntohs(n->rip_metric) == HOPCNT_INFINITY &&
7324317Ssklower 			    size == 0) {
7424317Ssklower 				ifp = if_ifwithnet(from);
7524317Ssklower 				supply(from, 0, ifp);
7624307Ssklower 				return;
7724307Ssklower 			}
7824307Ssklower 			/*
7924307Ssklower 			 * request for specific nets
8024307Ssklower 			 */
8124307Ssklower 			rt = rtlookup(xns_nettosa(n->rip_dst));
82*24875Ssklower 			if (ftrace) {
8324328Ssklower 				fprintf(ftrace,
8424328Ssklower 					"specific request for %d",
8524328Ssklower 					ntohl(xnnet(n->rip_dst[0])));
8624328Ssklower 				fprintf(ftrace,
8724328Ssklower 					"yields route %x",
8824328Ssklower 					rt);
8924328Ssklower 			}
9024307Ssklower 			n->rip_metric = htons( rt == 0 ? HOPCNT_INFINITY :
9124307Ssklower 				min(rt->rt_metric+1, HOPCNT_INFINITY));
9224307Ssklower 			n++, newsize += sizeof (struct netinfo);
9324307Ssklower 		}
9424307Ssklower 		if (newsize > 0) {
9524307Ssklower 			msg->rip_cmd = htons(RIPCMD_RESPONSE);
9624307Ssklower 			newsize += sizeof (u_short);
9724307Ssklower 			/* should check for if with dstaddr(from) first */
98*24875Ssklower 			(*afp->af_output)(0, from, newsize);
9924328Ssklower 			(ifp = if_ifwithnet(from));
100*24875Ssklower 			if (ftrace) {
10124328Ssklower 				fprintf(ftrace,
10224328Ssklower 					", request arriving on interface %x\n",
10324328Ssklower 					ifp);
10424328Ssklower 			}
10524307Ssklower 		}
10624307Ssklower 		return;
10724307Ssklower 
10824307Ssklower 	case RIPCMD_RESPONSE:
10924307Ssklower 		/* verify message came from a router */
11024307Ssklower 		if ((*afp->af_portmatch)(from) == 0)
11124307Ssklower 			return;
11224317Ssklower 		(*afp->af_canon)(from);
11324317Ssklower 		/* are we talking to ourselves? */
11424317Ssklower 		if (ifp = if_ifwithaddr(from)) {
11524317Ssklower 			rt = rtfind(from);
11624317Ssklower 			if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0)
11724317Ssklower 				addrouteforif(ifp);
11824317Ssklower 			else
11924317Ssklower 				rt->rt_timer = 0;
12024317Ssklower 			return;
12124317Ssklower 		}
12224328Ssklower 		/* Update timer for interface on which the packet arrived.
12324328Ssklower 		 * If from other end of a point-to-point link that isn't
12424328Ssklower 		 * in the routing tables, (re-)add the route.
12524328Ssklower 		 */
12624328Ssklower 		if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE)) {
127*24875Ssklower 			if(ftrace) fprintf(ftrace, "Got route\n");
12824307Ssklower 			rt->rt_timer = 0;
12924328Ssklower 		} else if (ifp = if_ifwithdstaddr(from)) {
130*24875Ssklower 			if(ftrace) fprintf(ftrace, "Got partner\n");
13124328Ssklower 			addrouteforif(ifp);
13224328Ssklower 		}
13324307Ssklower 		for (; size > 0; size -= sizeof (struct netinfo), n++) {
13424328Ssklower 			struct sockaddr *sa;
13524307Ssklower 			if (size < sizeof (struct netinfo))
13624307Ssklower 				break;
13724307Ssklower 			if ((unsigned) ntohs(n->rip_metric) > HOPCNT_INFINITY)
13824307Ssklower 				continue;
13924328Ssklower 			rt = rtfind(sa = xns_nettosa(n->rip_dst));
14024307Ssklower 			if (rt == 0) {
14124328Ssklower 				rtadd(sa, from, ntohs(n->rip_metric), 0);
14224307Ssklower 				continue;
14324307Ssklower 			}
14424307Ssklower 
14524307Ssklower 			/*
14624307Ssklower 			 * Update if from gateway and different,
14724307Ssklower 			 * from anywhere and shorter, or getting stale and equivalent.
14824307Ssklower 			 */
14924307Ssklower 			if ((equal(from, &rt->rt_router) &&
15024307Ssklower 			    ntohs(n->rip_metric) != rt->rt_metric ) ||
15124307Ssklower 			    (unsigned) ntohs(n->rip_metric) < rt->rt_metric ||
15224307Ssklower 			    (rt->rt_timer > (EXPIRE_TIME/2) &&
15324307Ssklower 			    rt->rt_metric == ntohs(n->rip_metric))) {
15424307Ssklower 				rtchange(rt, from, ntohs(n->rip_metric));
15524307Ssklower 				rt->rt_timer = 0;
15624307Ssklower 			}
15724307Ssklower 		}
15824307Ssklower 		return;
15924307Ssklower 	}
16024307Ssklower }
161