xref: /csrg-svn/sbin/XNSrouted/input.c (revision 24307)
1*24307Ssklower #ifndef lint
2*24307Ssklower static char rcsid[] = "$Header$";
3*24307Ssklower #endif
4*24307Ssklower 
5*24307Ssklower /*
6*24307Ssklower  * XNS Routing Table Management Daemon
7*24307Ssklower  */
8*24307Ssklower #include "defs.h"
9*24307Ssklower 
10*24307Ssklower struct sockaddr *
11*24307Ssklower xns_nettosa(net)
12*24307Ssklower u_short *net;
13*24307Ssklower {
14*24307Ssklower 	static struct sockaddr_xn sxn;
15*24307Ssklower 
16*24307Ssklower 	bzero(&sxn, sizeof (struct sockaddr_xn));
17*24307Ssklower 	sxn.sxn_family = AF_XNS;
18*24307Ssklower 	xnnet(sxn.sxn_addr.xn_net) = xnnet(net);
19*24307Ssklower 	return( (struct sockaddr *)&sxn);
20*24307Ssklower 
21*24307Ssklower }
22*24307Ssklower 
23*24307Ssklower /*
24*24307Ssklower  * Process a newly received packet.
25*24307Ssklower  */
26*24307Ssklower rip_input(from, size)
27*24307Ssklower 	struct sockaddr *from;
28*24307Ssklower 	int size;
29*24307Ssklower {
30*24307Ssklower 	struct rt_entry *rt;
31*24307Ssklower 	struct netinfo *n;
32*24307Ssklower 	struct interface *ifp;
33*24307Ssklower 	int newsize;
34*24307Ssklower 	struct afswitch *afp;
35*24307Ssklower 
36*24307Ssklower 
37*24307Ssklower 	TRACE_INPUT(ifp, from, size);
38*24307Ssklower 	if (from->sa_family >= AF_MAX)
39*24307Ssklower 		return;
40*24307Ssklower 	afp = &afswitch[from->sa_family];
41*24307Ssklower 
42*24307Ssklower 	/* are we talking to ourselves? */
43*24307Ssklower 	if (ifp = if_ifwithaddr(from)) {
44*24307Ssklower 		rt = rtfind(from);
45*24307Ssklower 		if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0)
46*24307Ssklower 			addrouteforif(ifp);
47*24307Ssklower 		else
48*24307Ssklower 			rt->rt_timer = 0;
49*24307Ssklower 		return;
50*24307Ssklower 	}
51*24307Ssklower 
52*24307Ssklower 	size -= sizeof (u_short)	/* command */;
53*24307Ssklower 	n = msg->rip_nets;
54*24307Ssklower 
55*24307Ssklower 	switch (ntohs(msg->rip_cmd)) {
56*24307Ssklower 
57*24307Ssklower 	case RIPCMD_REQUEST:
58*24307Ssklower 		/* Be quiet if we don't have anything interesting to talk about */
59*24307Ssklower 		if (!supplier) return;
60*24307Ssklower 		newsize = 0;
61*24307Ssklower 		while (size > 0) {
62*24307Ssklower 			if (size < sizeof (struct netinfo))
63*24307Ssklower 				break;
64*24307Ssklower 			size -= sizeof (struct netinfo);
65*24307Ssklower 
66*24307Ssklower 			/*
67*24307Ssklower 			 * A single entry with rip_dst == DSTNETS_ALL and
68*24307Ssklower 			 * metric ``infinity'' means ``all routes''.
69*24307Ssklower 			 */
70*24307Ssklower 			if (ntohl(xnnet(n->rip_dst)) == DSTNETS_ALL &&
71*24307Ssklower 		            ntohs(n->rip_metric) == HOPCNT_INFINITY && size == 0) {
72*24307Ssklower 				if(ifp = if_ifwithnet(from))
73*24307Ssklower 				    supply(from, 0, ifp);
74*24307Ssklower 				return;
75*24307Ssklower 			}
76*24307Ssklower 			/*
77*24307Ssklower 			 * request for specific nets
78*24307Ssklower 			 */
79*24307Ssklower 			rt = rtlookup(xns_nettosa(n->rip_dst));
80*24307Ssklower 			n->rip_metric = htons( rt == 0 ? HOPCNT_INFINITY :
81*24307Ssklower 				min(rt->rt_metric+1, HOPCNT_INFINITY));
82*24307Ssklower 			n++, newsize += sizeof (struct netinfo);
83*24307Ssklower 		}
84*24307Ssklower 		if (newsize > 0) {
85*24307Ssklower 			msg->rip_cmd = htons(RIPCMD_RESPONSE);
86*24307Ssklower 			newsize += sizeof (u_short);
87*24307Ssklower 			/* should check for if with dstaddr(from) first */
88*24307Ssklower 			if(ifp = if_ifwithnet(from))
89*24307Ssklower 			    (*afp->af_output)(ifp->int_ripsock[0], 0, from, newsize);
90*24307Ssklower 		}
91*24307Ssklower 		return;
92*24307Ssklower 
93*24307Ssklower 	case RIPCMD_RESPONSE:
94*24307Ssklower 		/* verify message came from a router */
95*24307Ssklower 		if ((*afp->af_portmatch)(from) == 0)
96*24307Ssklower 			return;
97*24307Ssklower 		/* update timer for interface on which the packet arrived */
98*24307Ssklower 		if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE))
99*24307Ssklower 			rt->rt_timer = 0;
100*24307Ssklower 		for (; size > 0; size -= sizeof (struct netinfo), n++) {
101*24307Ssklower 			if (size < sizeof (struct netinfo))
102*24307Ssklower 				break;
103*24307Ssklower 			if ((unsigned) ntohs(n->rip_metric) > HOPCNT_INFINITY)
104*24307Ssklower 				continue;
105*24307Ssklower 			rt = rtlookup(xns_nettosa(n->rip_dst));
106*24307Ssklower 			if (rt == 0) {
107*24307Ssklower 				rtadd(xns_nettosa(n->rip_dst), from, ntohs(n->rip_metric), 0);
108*24307Ssklower 				continue;
109*24307Ssklower 			}
110*24307Ssklower 
111*24307Ssklower 			/*
112*24307Ssklower 			 * Update if from gateway and different,
113*24307Ssklower 			 * from anywhere and shorter, or getting stale and equivalent.
114*24307Ssklower 			 */
115*24307Ssklower 			if ((equal(from, &rt->rt_router) &&
116*24307Ssklower 			    ntohs(n->rip_metric) != rt->rt_metric ) ||
117*24307Ssklower 			    (unsigned) ntohs(n->rip_metric) < rt->rt_metric ||
118*24307Ssklower 			    (rt->rt_timer > (EXPIRE_TIME/2) &&
119*24307Ssklower 			    rt->rt_metric == ntohs(n->rip_metric))) {
120*24307Ssklower 				rtchange(rt, from, ntohs(n->rip_metric));
121*24307Ssklower 				rt->rt_timer = 0;
122*24307Ssklower 			}
123*24307Ssklower 		}
124*24307Ssklower 		return;
125*24307Ssklower 	}
126*24307Ssklower }
127