xref: /original-bsd/sbin/XNSrouted/input.c (revision 962d13e9)
1 /*
2  * Copyright (c) 1985 The Regents of the University of California.
3  * 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  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by the University of California, Berkeley.  The name of the
14  * University may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  */
20 
21 #ifndef lint
22 static char sccsid[] = "@(#)input.c	5.8 (Berkeley) 08/21/89";
23 #endif /* not lint */
24 
25 /*
26  * XNS Routing Table Management Daemon
27  */
28 #include "defs.h"
29 
30 struct sockaddr *
31 xns_nettosa(net)
32 union ns_net net;
33 {
34 	static struct sockaddr_ns sxn;
35 	extern char ether_broadcast_addr[6];
36 
37 	bzero(&sxn, sizeof (struct sockaddr_ns));
38 	sxn.sns_family = AF_NS;
39 	sxn.sns_len = sizeof (sxn);
40 	sxn.sns_addr.x_net = net;
41 	sxn.sns_addr.x_host = *(union ns_host *)ether_broadcast_addr;
42 	return( (struct sockaddr *)&sxn);
43 
44 }
45 
46 /*
47  * Process a newly received packet.
48  */
49 rip_input(from, size)
50 	struct sockaddr *from;
51 	int size;
52 {
53 	struct rt_entry *rt;
54 	struct netinfo *n;
55 	struct interface *ifp;
56 	int newsize;
57 	struct afswitch *afp;
58 
59 
60 	ifp = 0;
61 	TRACE_INPUT(ifp, from, size);
62 	if (from->sa_family >= AF_MAX)
63 		return;
64 	afp = &afswitch[from->sa_family];
65 
66 	size -= sizeof (u_short)	/* command */;
67 	n = msg->rip_nets;
68 
69 	switch (ntohs(msg->rip_cmd)) {
70 
71 	case RIPCMD_REQUEST:
72 		newsize = 0;
73 		while (size > 0) {
74 			if (size < sizeof (struct netinfo))
75 				break;
76 			size -= sizeof (struct netinfo);
77 
78 			/*
79 			 * A single entry with rip_dst == DSTNETS_ALL and
80 			 * metric ``infinity'' means ``all routes''.
81 			 */
82 			if (ns_neteqnn(n->rip_dst, ns_anynet) &&
83 		            ntohs(n->rip_metric) == HOPCNT_INFINITY &&
84 			    size == 0) {
85 				ifp = if_ifwithnet(from);
86 				supply(from, 0, ifp);
87 				return;
88 			}
89 			/*
90 			 * request for specific nets
91 			 */
92 			rt = rtlookup(xns_nettosa(n->rip_dst));
93 			if (ftrace) {
94 				fprintf(ftrace,
95 					"specific request for %s",
96 					xns_nettoa(n->rip_dst));
97 				fprintf(ftrace,
98 					" yields route %x\n",
99 					rt);
100 			}
101 			n->rip_metric = htons( rt == 0 ? HOPCNT_INFINITY :
102 				min(rt->rt_metric+1, HOPCNT_INFINITY));
103 			n++;
104 		        newsize += sizeof (struct netinfo);
105 		}
106 		if (newsize > 0) {
107 			msg->rip_cmd = htons(RIPCMD_RESPONSE);
108 			newsize += sizeof (u_short);
109 			/* should check for if with dstaddr(from) first */
110 			(*afp->af_output)(0, from, newsize);
111 			ifp = if_ifwithnet(from);
112 			TRACE_OUTPUT(ifp, from, newsize);
113 			if (ftrace) {
114 				fprintf(ftrace,
115 					"request arrived on interface %s\n",
116 					ifp->int_name);
117 			}
118 		}
119 		return;
120 
121 	case RIPCMD_RESPONSE:
122 		/* verify message came from a router */
123 		if ((*afp->af_portmatch)(from) == 0)
124 			return;
125 		(*afp->af_canon)(from);
126 		/* are we talking to ourselves? */
127 		if (ifp = if_ifwithaddr(from)) {
128 			rt = rtfind(from);
129 			if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0)
130 				addrouteforif(ifp);
131 			else
132 				rt->rt_timer = 0;
133 			return;
134 		}
135 		/* Update timer for interface on which the packet arrived.
136 		 * If from other end of a point-to-point link that isn't
137 		 * in the routing tables, (re-)add the route.
138 		 */
139 		if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE)) {
140 			if(ftrace) fprintf(ftrace, "Got route\n");
141 			rt->rt_timer = 0;
142 		} else if (ifp = if_ifwithdstaddr(from)) {
143 			if(ftrace) fprintf(ftrace, "Got partner\n");
144 			addrouteforif(ifp);
145 		}
146 		for (; size > 0; size -= sizeof (struct netinfo), n++) {
147 			struct sockaddr *sa;
148 			if (size < sizeof (struct netinfo))
149 				break;
150 			if ((unsigned) ntohs(n->rip_metric) >= HOPCNT_INFINITY)
151 				continue;
152 			rt = rtfind(sa = xns_nettosa(n->rip_dst));
153 			if (rt == 0) {
154 				rtadd(sa, from, ntohs(n->rip_metric), 0);
155 				continue;
156 			}
157 
158 			/*
159 			 * Update if from gateway and different,
160 			 * from anywhere and shorter, or getting stale and equivalent.
161 			 */
162 			if ((equal(from, &rt->rt_router) &&
163 			    ntohs(n->rip_metric) != rt->rt_metric ) ||
164 			    (unsigned) ntohs(n->rip_metric) < rt->rt_metric ||
165 			    (rt->rt_timer > (EXPIRE_TIME/2) &&
166 			    rt->rt_metric == ntohs(n->rip_metric))) {
167 				rtchange(rt, from, ntohs(n->rip_metric));
168 				rt->rt_timer = 0;
169 			}
170 		}
171 		return;
172 	}
173 }
174