xref: /csrg-svn/sbin/XNSrouted/input.c (revision 35551)
124328Ssklower /*
2*35551Sbostic  * Copyright (c) 1985 The Regents of the University of California.
3*35551Sbostic  * All rights reserved.
424328Ssklower  *
5*35551Sbostic  * This file includes significant work done at Cornell University by
6*35551Sbostic  * Bill Nesheim.  That work included by permission.
7*35551Sbostic  *
8*35551Sbostic  * Redistribution and use in source and binary forms are permitted
9*35551Sbostic  * provided that the above copyright notice and this paragraph are
10*35551Sbostic  * duplicated in all such forms and that any documentation,
11*35551Sbostic  * advertising materials, and other materials related to such
12*35551Sbostic  * distribution and use acknowledge that the software was developed
13*35551Sbostic  * by the University of California, Berkeley.  The name of the
14*35551Sbostic  * University may not be used to endorse or promote products derived
15*35551Sbostic  * from this software without specific prior written permission.
16*35551Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17*35551Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18*35551Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1924328Ssklower  */
2024328Ssklower 
2124307Ssklower #ifndef lint
22*35551Sbostic static char sccsid[] = "@(#)input.c	5.7 (Berkeley) 09/19/88";
23*35551Sbostic #endif /* not lint */
2424307Ssklower 
2524307Ssklower /*
2624307Ssklower  * XNS Routing Table Management Daemon
2724307Ssklower  */
2824307Ssklower #include "defs.h"
2924307Ssklower 
3024307Ssklower struct sockaddr *
3124307Ssklower xns_nettosa(net)
3226170Ssklower union ns_net net;
3324307Ssklower {
3424317Ssklower 	static struct sockaddr_ns sxn;
3524317Ssklower 	extern char ether_broadcast_addr[6];
3624307Ssklower 
3724317Ssklower 	bzero(&sxn, sizeof (struct sockaddr_ns));
3824317Ssklower 	sxn.sns_family = AF_NS;
3926170Ssklower 	sxn.sns_addr.x_net = net;
4024317Ssklower 	sxn.sns_addr.x_host = *(union ns_host *)ether_broadcast_addr;
4124307Ssklower 	return( (struct sockaddr *)&sxn);
4224307Ssklower 
4324307Ssklower }
4424307Ssklower 
4524307Ssklower /*
4624307Ssklower  * Process a newly received packet.
4724307Ssklower  */
4824307Ssklower rip_input(from, size)
4924307Ssklower 	struct sockaddr *from;
5024307Ssklower 	int size;
5124307Ssklower {
5224307Ssklower 	struct rt_entry *rt;
5324307Ssklower 	struct netinfo *n;
5424307Ssklower 	struct interface *ifp;
5524307Ssklower 	int newsize;
5624307Ssklower 	struct afswitch *afp;
5724307Ssklower 
5824307Ssklower 
5924317Ssklower 	ifp = 0;
6024307Ssklower 	TRACE_INPUT(ifp, from, size);
6124307Ssklower 	if (from->sa_family >= AF_MAX)
6224307Ssklower 		return;
6324307Ssklower 	afp = &afswitch[from->sa_family];
6424307Ssklower 
6524307Ssklower 	size -= sizeof (u_short)	/* command */;
6624307Ssklower 	n = msg->rip_nets;
6724307Ssklower 
6824307Ssklower 	switch (ntohs(msg->rip_cmd)) {
6924307Ssklower 
7024307Ssklower 	case RIPCMD_REQUEST:
7124307Ssklower 		newsize = 0;
7224307Ssklower 		while (size > 0) {
7324307Ssklower 			if (size < sizeof (struct netinfo))
7424307Ssklower 				break;
7524307Ssklower 			size -= sizeof (struct netinfo);
7624307Ssklower 
7724307Ssklower 			/*
7824307Ssklower 			 * A single entry with rip_dst == DSTNETS_ALL and
7924307Ssklower 			 * metric ``infinity'' means ``all routes''.
8024307Ssklower 			 */
8126170Ssklower 			if (ns_neteqnn(n->rip_dst, ns_anynet) &&
8224317Ssklower 		            ntohs(n->rip_metric) == HOPCNT_INFINITY &&
8324317Ssklower 			    size == 0) {
8424317Ssklower 				ifp = if_ifwithnet(from);
8524317Ssklower 				supply(from, 0, ifp);
8624307Ssklower 				return;
8724307Ssklower 			}
8824307Ssklower 			/*
8924307Ssklower 			 * request for specific nets
9024307Ssklower 			 */
9124307Ssklower 			rt = rtlookup(xns_nettosa(n->rip_dst));
9224875Ssklower 			if (ftrace) {
9324328Ssklower 				fprintf(ftrace,
9426170Ssklower 					"specific request for %s",
9526170Ssklower 					xns_nettoa(n->rip_dst));
9624328Ssklower 				fprintf(ftrace,
9726170Ssklower 					" yields route %x\n",
9824328Ssklower 					rt);
9924328Ssklower 			}
10024307Ssklower 			n->rip_metric = htons( rt == 0 ? HOPCNT_INFINITY :
10124307Ssklower 				min(rt->rt_metric+1, HOPCNT_INFINITY));
10226170Ssklower 			n++;
10326170Ssklower 		        newsize += sizeof (struct netinfo);
10424307Ssklower 		}
10524307Ssklower 		if (newsize > 0) {
10624307Ssklower 			msg->rip_cmd = htons(RIPCMD_RESPONSE);
10724307Ssklower 			newsize += sizeof (u_short);
10824307Ssklower 			/* should check for if with dstaddr(from) first */
10924875Ssklower 			(*afp->af_output)(0, from, newsize);
11026170Ssklower 			ifp = if_ifwithnet(from);
11126170Ssklower 			TRACE_OUTPUT(ifp, from, newsize);
11224875Ssklower 			if (ftrace) {
11324328Ssklower 				fprintf(ftrace,
11426170Ssklower 					"request arrived on interface %s\n",
11526170Ssklower 					ifp->int_name);
11624328Ssklower 			}
11724307Ssklower 		}
11824307Ssklower 		return;
11924307Ssklower 
12024307Ssklower 	case RIPCMD_RESPONSE:
12124307Ssklower 		/* verify message came from a router */
12224307Ssklower 		if ((*afp->af_portmatch)(from) == 0)
12324307Ssklower 			return;
12424317Ssklower 		(*afp->af_canon)(from);
12524317Ssklower 		/* are we talking to ourselves? */
12624317Ssklower 		if (ifp = if_ifwithaddr(from)) {
12724317Ssklower 			rt = rtfind(from);
12824317Ssklower 			if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0)
12924317Ssklower 				addrouteforif(ifp);
13024317Ssklower 			else
13124317Ssklower 				rt->rt_timer = 0;
13224317Ssklower 			return;
13324317Ssklower 		}
13424328Ssklower 		/* Update timer for interface on which the packet arrived.
13524328Ssklower 		 * If from other end of a point-to-point link that isn't
13624328Ssklower 		 * in the routing tables, (re-)add the route.
13724328Ssklower 		 */
13824328Ssklower 		if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE)) {
13924875Ssklower 			if(ftrace) fprintf(ftrace, "Got route\n");
14024307Ssklower 			rt->rt_timer = 0;
14124328Ssklower 		} else if (ifp = if_ifwithdstaddr(from)) {
14224875Ssklower 			if(ftrace) fprintf(ftrace, "Got partner\n");
14324328Ssklower 			addrouteforif(ifp);
14424328Ssklower 		}
14524307Ssklower 		for (; size > 0; size -= sizeof (struct netinfo), n++) {
14624328Ssklower 			struct sockaddr *sa;
14724307Ssklower 			if (size < sizeof (struct netinfo))
14824307Ssklower 				break;
14925507Ssklower 			if ((unsigned) ntohs(n->rip_metric) >= HOPCNT_INFINITY)
15024307Ssklower 				continue;
15124328Ssklower 			rt = rtfind(sa = xns_nettosa(n->rip_dst));
15224307Ssklower 			if (rt == 0) {
15324328Ssklower 				rtadd(sa, from, ntohs(n->rip_metric), 0);
15424307Ssklower 				continue;
15524307Ssklower 			}
15624307Ssklower 
15724307Ssklower 			/*
15824307Ssklower 			 * Update if from gateway and different,
15924307Ssklower 			 * from anywhere and shorter, or getting stale and equivalent.
16024307Ssklower 			 */
16124307Ssklower 			if ((equal(from, &rt->rt_router) &&
16224307Ssklower 			    ntohs(n->rip_metric) != rt->rt_metric ) ||
16324307Ssklower 			    (unsigned) ntohs(n->rip_metric) < rt->rt_metric ||
16424307Ssklower 			    (rt->rt_timer > (EXPIRE_TIME/2) &&
16524307Ssklower 			    rt->rt_metric == ntohs(n->rip_metric))) {
16624307Ssklower 				rtchange(rt, from, ntohs(n->rip_metric));
16724307Ssklower 				rt->rt_timer = 0;
16824307Ssklower 			}
16924307Ssklower 		}
17024307Ssklower 		return;
17124307Ssklower 	}
17224307Ssklower }
173