xref: /csrg-svn/sbin/XNSrouted/input.c (revision 24317)
124307Ssklower #ifndef lint
224307Ssklower static char rcsid[] = "$Header$";
324307Ssklower #endif
424307Ssklower 
524307Ssklower /*
624307Ssklower  * XNS Routing Table Management Daemon
724307Ssklower  */
824307Ssklower #include "defs.h"
924307Ssklower 
1024307Ssklower struct sockaddr *
1124307Ssklower xns_nettosa(net)
1224307Ssklower u_short *net;
1324307Ssklower {
14*24317Ssklower 	static struct sockaddr_ns sxn;
15*24317Ssklower 	extern char ether_broadcast_addr[6];
1624307Ssklower 
17*24317Ssklower 	bzero(&sxn, sizeof (struct sockaddr_ns));
18*24317Ssklower 	sxn.sns_family = AF_NS;
19*24317Ssklower 	xnnet(sxn.sns_addr.x_net) = xnnet(net[0]);
20*24317Ssklower 	sxn.sns_addr.x_host = *(union ns_host *)ether_broadcast_addr;
2124307Ssklower 	return( (struct sockaddr *)&sxn);
2224307Ssklower 
2324307Ssklower }
2424307Ssklower 
2524307Ssklower /*
2624307Ssklower  * Process a newly received packet.
2724307Ssklower  */
2824307Ssklower rip_input(from, size)
2924307Ssklower 	struct sockaddr *from;
3024307Ssklower 	int size;
3124307Ssklower {
3224307Ssklower 	struct rt_entry *rt;
3324307Ssklower 	struct netinfo *n;
3424307Ssklower 	struct interface *ifp;
3524307Ssklower 	int newsize;
3624307Ssklower 	struct afswitch *afp;
3724307Ssklower 
3824307Ssklower 
39*24317Ssklower 	ifp = 0;
4024307Ssklower 	TRACE_INPUT(ifp, from, size);
4124307Ssklower 	if (from->sa_family >= AF_MAX)
4224307Ssklower 		return;
4324307Ssklower 	afp = &afswitch[from->sa_family];
4424307Ssklower 
4524307Ssklower 	size -= sizeof (u_short)	/* command */;
4624307Ssklower 	n = msg->rip_nets;
4724307Ssklower 
4824307Ssklower 	switch (ntohs(msg->rip_cmd)) {
4924307Ssklower 
5024307Ssklower 	case RIPCMD_REQUEST:
5124307Ssklower 		/* Be quiet if we don't have anything interesting to talk about */
5224307Ssklower 		if (!supplier) return;
5324307Ssklower 		newsize = 0;
5424307Ssklower 		while (size > 0) {
5524307Ssklower 			if (size < sizeof (struct netinfo))
5624307Ssklower 				break;
5724307Ssklower 			size -= sizeof (struct netinfo);
5824307Ssklower 
5924307Ssklower 			/*
6024307Ssklower 			 * A single entry with rip_dst == DSTNETS_ALL and
6124307Ssklower 			 * metric ``infinity'' means ``all routes''.
6224307Ssklower 			 */
63*24317Ssklower 			if (ntohl(xnnet(n->rip_dst[0])) == DSTNETS_ALL &&
64*24317Ssklower 		            ntohs(n->rip_metric) == HOPCNT_INFINITY &&
65*24317Ssklower 			    size == 0) {
66*24317Ssklower 				ifp = if_ifwithnet(from);
67*24317Ssklower 				supply(from, 0, ifp);
6824307Ssklower 				return;
6924307Ssklower 			}
7024307Ssklower 			/*
7124307Ssklower 			 * request for specific nets
7224307Ssklower 			 */
7324307Ssklower 			rt = rtlookup(xns_nettosa(n->rip_dst));
7424307Ssklower 			n->rip_metric = htons( rt == 0 ? HOPCNT_INFINITY :
7524307Ssklower 				min(rt->rt_metric+1, HOPCNT_INFINITY));
7624307Ssklower 			n++, newsize += sizeof (struct netinfo);
7724307Ssklower 		}
7824307Ssklower 		if (newsize > 0) {
7924307Ssklower 			msg->rip_cmd = htons(RIPCMD_RESPONSE);
8024307Ssklower 			newsize += sizeof (u_short);
8124307Ssklower 			/* should check for if with dstaddr(from) first */
8224307Ssklower 			if(ifp = if_ifwithnet(from))
83*24317Ssklower 			    (*afp->af_output)(0, from, newsize);
8424307Ssklower 		}
8524307Ssklower 		return;
8624307Ssklower 
8724307Ssklower 	case RIPCMD_RESPONSE:
8824307Ssklower 		/* verify message came from a router */
8924307Ssklower 		if ((*afp->af_portmatch)(from) == 0)
9024307Ssklower 			return;
91*24317Ssklower 		(*afp->af_canon)(from);
92*24317Ssklower 		/* are we talking to ourselves? */
93*24317Ssklower 		if (ifp = if_ifwithaddr(from)) {
94*24317Ssklower 			rt = rtfind(from);
95*24317Ssklower 			if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0)
96*24317Ssklower 				addrouteforif(ifp);
97*24317Ssklower 			else
98*24317Ssklower 				rt->rt_timer = 0;
99*24317Ssklower 			return;
100*24317Ssklower 		}
10124307Ssklower 		/* update timer for interface on which the packet arrived */
10224307Ssklower 		if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE))
10324307Ssklower 			rt->rt_timer = 0;
10424307Ssklower 		for (; size > 0; size -= sizeof (struct netinfo), n++) {
10524307Ssklower 			if (size < sizeof (struct netinfo))
10624307Ssklower 				break;
10724307Ssklower 			if ((unsigned) ntohs(n->rip_metric) > HOPCNT_INFINITY)
10824307Ssklower 				continue;
109*24317Ssklower 			rt = rtfind(xns_nettosa(n->rip_dst));
11024307Ssklower 			if (rt == 0) {
11124307Ssklower 				rtadd(xns_nettosa(n->rip_dst), from, ntohs(n->rip_metric), 0);
11224307Ssklower 				continue;
11324307Ssklower 			}
11424307Ssklower 
11524307Ssklower 			/*
11624307Ssklower 			 * Update if from gateway and different,
11724307Ssklower 			 * from anywhere and shorter, or getting stale and equivalent.
11824307Ssklower 			 */
11924307Ssklower 			if ((equal(from, &rt->rt_router) &&
12024307Ssklower 			    ntohs(n->rip_metric) != rt->rt_metric ) ||
12124307Ssklower 			    (unsigned) ntohs(n->rip_metric) < rt->rt_metric ||
12224307Ssklower 			    (rt->rt_timer > (EXPIRE_TIME/2) &&
12324307Ssklower 			    rt->rt_metric == ntohs(n->rip_metric))) {
12424307Ssklower 				rtchange(rt, from, ntohs(n->rip_metric));
12524307Ssklower 				rt->rt_timer = 0;
12624307Ssklower 			}
12724307Ssklower 		}
12824307Ssklower 		return;
12924307Ssklower 	}
13024307Ssklower }
131