xref: /original-bsd/sbin/XNSrouted/input.c (revision 42f60e33)
1 /*
2  * Copyright (c) 1985, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This file includes significant work done at Cornell University by
6  * Bill Nesheim.  That work included by permission.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 static char sccsid[] = "@(#)input.c	8.1 (Berkeley) 06/05/93";
13 #endif /* not lint */
14 
15 /*
16  * XNS Routing Table Management Daemon
17  */
18 #include "defs.h"
19 
20 struct sockaddr *
21 xns_nettosa(net)
22 union ns_net net;
23 {
24 	static struct sockaddr_ns sxn;
25 	extern char ether_broadcast_addr[6];
26 
27 	bzero(&sxn, sizeof (struct sockaddr_ns));
28 	sxn.sns_family = AF_NS;
29 	sxn.sns_len = sizeof (sxn);
30 	sxn.sns_addr.x_net = net;
31 	sxn.sns_addr.x_host = *(union ns_host *)ether_broadcast_addr;
32 	return( (struct sockaddr *)&sxn);
33 
34 }
35 
36 /*
37  * Process a newly received packet.
38  */
39 rip_input(from, size)
40 	struct sockaddr *from;
41 	int size;
42 {
43 	struct rt_entry *rt;
44 	struct netinfo *n;
45 	struct interface *ifp;
46 	int newsize;
47 	struct afswitch *afp;
48 
49 
50 	ifp = 0;
51 	TRACE_INPUT(ifp, from, size);
52 	if (from->sa_family >= AF_MAX)
53 		return;
54 	afp = &afswitch[from->sa_family];
55 
56 	size -= sizeof (u_short)	/* command */;
57 	n = msg->rip_nets;
58 
59 	switch (ntohs(msg->rip_cmd)) {
60 
61 	case RIPCMD_REQUEST:
62 		newsize = 0;
63 		while (size > 0) {
64 			if (size < sizeof (struct netinfo))
65 				break;
66 			size -= sizeof (struct netinfo);
67 
68 			/*
69 			 * A single entry with rip_dst == DSTNETS_ALL and
70 			 * metric ``infinity'' means ``all routes''.
71 			 */
72 			if (ns_neteqnn(n->rip_dst, ns_anynet) &&
73 		            ntohs(n->rip_metric) == HOPCNT_INFINITY &&
74 			    size == 0) {
75 				ifp = if_ifwithnet(from);
76 				supply(from, 0, ifp);
77 				return;
78 			}
79 			/*
80 			 * request for specific nets
81 			 */
82 			rt = rtlookup(xns_nettosa(n->rip_dst));
83 			if (ftrace) {
84 				fprintf(ftrace,
85 					"specific request for %s",
86 					xns_nettoa(n->rip_dst));
87 				fprintf(ftrace,
88 					" yields route %x\n",
89 					rt);
90 			}
91 			n->rip_metric = htons( rt == 0 ? HOPCNT_INFINITY :
92 				min(rt->rt_metric+1, HOPCNT_INFINITY));
93 			n++;
94 		        newsize += sizeof (struct netinfo);
95 		}
96 		if (newsize > 0) {
97 			msg->rip_cmd = htons(RIPCMD_RESPONSE);
98 			newsize += sizeof (u_short);
99 			/* should check for if with dstaddr(from) first */
100 			(*afp->af_output)(0, from, newsize);
101 			ifp = if_ifwithnet(from);
102 			TRACE_OUTPUT(ifp, from, newsize);
103 			if (ftrace) {
104 				fprintf(ftrace,
105 					"request arrived on interface %s\n",
106 					ifp->int_name);
107 			}
108 		}
109 		return;
110 
111 	case RIPCMD_RESPONSE:
112 		/* verify message came from a router */
113 		if ((*afp->af_portmatch)(from) == 0)
114 			return;
115 		(*afp->af_canon)(from);
116 		/* are we talking to ourselves? */
117 		if (ifp = if_ifwithaddr(from)) {
118 			rt = rtfind(from);
119 			if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0)
120 				addrouteforif(ifp);
121 			else
122 				rt->rt_timer = 0;
123 			return;
124 		}
125 		/* Update timer for interface on which the packet arrived.
126 		 * If from other end of a point-to-point link that isn't
127 		 * in the routing tables, (re-)add the route.
128 		 */
129 		if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE)) {
130 			if(ftrace) fprintf(ftrace, "Got route\n");
131 			rt->rt_timer = 0;
132 		} else if (ifp = if_ifwithdstaddr(from)) {
133 			if(ftrace) fprintf(ftrace, "Got partner\n");
134 			addrouteforif(ifp);
135 		}
136 		for (; size > 0; size -= sizeof (struct netinfo), n++) {
137 			struct sockaddr *sa;
138 			if (size < sizeof (struct netinfo))
139 				break;
140 			if ((unsigned) ntohs(n->rip_metric) >= HOPCNT_INFINITY)
141 				continue;
142 			rt = rtfind(sa = xns_nettosa(n->rip_dst));
143 			if (rt == 0) {
144 				rtadd(sa, from, ntohs(n->rip_metric), 0);
145 				continue;
146 			}
147 
148 			/*
149 			 * Update if from gateway and different,
150 			 * from anywhere and shorter, or getting stale and equivalent.
151 			 */
152 			if ((equal(from, &rt->rt_router) &&
153 			    ntohs(n->rip_metric) != rt->rt_metric ) ||
154 			    (unsigned) ntohs(n->rip_metric) < rt->rt_metric ||
155 			    (rt->rt_timer > (EXPIRE_TIME/2) &&
156 			    rt->rt_metric == ntohs(n->rip_metric))) {
157 				rtchange(rt, from, ntohs(n->rip_metric));
158 				rt->rt_timer = 0;
159 			}
160 		}
161 		return;
162 	}
163 }
164