xref: /freebsd/sys/net/route.c (revision 3e0f6b97b257a96f7275e4442204263e44b16686)
1 /*
2  * Copyright (c) 1980, 1986, 1991, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *	@(#)route.c	8.2 (Berkeley) 11/15/93
34  *	$FreeBSD$
35  */
36 
37 #include "opt_mrouting.h"
38 
39 #include <sys/param.h>
40 #include <sys/queue.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/proc.h>
44 #include <sys/mbuf.h>
45 #include <sys/socket.h>
46 #include <sys/socketvar.h>
47 #include <sys/domain.h>
48 #include <sys/protosw.h>
49 #include <sys/ioctl.h>
50 
51 #include <net/if.h>
52 #include <net/route.h>
53 #include <net/raw_cb.h>
54 
55 #include <netinet/in.h>
56 #include <netinet/in_var.h>
57 #include <netinet/ip_mroute.h>
58 
59 #define	SA(p) ((struct sockaddr *)(p))
60 
61 struct route_cb route_cb;
62 static struct rtstat rtstat;
63 struct radix_node_head *rt_tables[AF_MAX+1];
64 
65 static int	rttrash;		/* routes not in table but not freed */
66 
67 static void rt_maskedcopy __P((struct sockaddr *,
68 	    struct sockaddr *, struct sockaddr *));
69 static void rtable_init __P((void **));
70 
71 static void
72 rtable_init(table)
73 	void **table;
74 {
75 	struct domain *dom;
76 	for (dom = domains; dom; dom = dom->dom_next)
77 		if (dom->dom_rtattach)
78 			dom->dom_rtattach(&table[dom->dom_family],
79 			    dom->dom_rtoffset);
80 }
81 
82 void
83 route_init()
84 {
85 	rn_init();	/* initialize all zeroes, all ones, mask table */
86 	rtable_init((void **)rt_tables);
87 }
88 
89 /*
90  * Packet routing routines.
91  */
92 void
93 rtalloc(ro)
94 	register struct route *ro;
95 {
96 	if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP))
97 		return;				 /* XXX */
98 	ro->ro_rt = rtalloc1(&ro->ro_dst, 1, 0UL);
99 }
100 
101 void
102 rtalloc_ign(ro, ignore)
103 	register struct route *ro;
104 	u_long ignore;
105 {
106 	if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP))
107 		return;				 /* XXX */
108 	ro->ro_rt = rtalloc1(&ro->ro_dst, 1, ignore);
109 }
110 
111 /*
112  * Look up the route that matches the address given
113  * Or, at least try.. Create a cloned route if needed.
114  */
115 struct rtentry *
116 rtalloc1(dst, report, ignflags)
117 	register struct sockaddr *dst;
118 	int report;
119 	u_long ignflags;
120 {
121 	register struct radix_node_head *rnh = rt_tables[dst->sa_family];
122 	register struct rtentry *rt;
123 	register struct radix_node *rn;
124 	struct rtentry *newrt = 0;
125 	struct rt_addrinfo info;
126 	u_long nflags;
127 	int  s = splnet(), err = 0, msgtype = RTM_MISS;
128 
129 	/*
130 	 * Look up the address in the table for that Address Family
131 	 */
132 	if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) &&
133 	    ((rn->rn_flags & RNF_ROOT) == 0)) {
134 		/*
135 		 * If we find it and it's not the root node, then
136 		 * get a refernce on the rtentry associated.
137 		 */
138 		newrt = rt = (struct rtentry *)rn;
139 		nflags = rt->rt_flags & ~ignflags;
140 		if (report && (nflags & (RTF_CLONING | RTF_PRCLONING))) {
141 			/*
142 			 * We are apparently adding (report = 0 in delete).
143 			 * If it requires that it be cloned, do so.
144 			 * (This implies it wasn't a HOST route.)
145 			 */
146 			err = rtrequest(RTM_RESOLVE, dst, SA(0),
147 					      SA(0), 0, &newrt);
148 			if (err) {
149 				/*
150 				 * If the cloning didn't succeed, maybe
151 				 * what we have will do. Return that.
152 				 */
153 				newrt = rt;
154 				rt->rt_refcnt++;
155 				goto miss;
156 			}
157 			if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) {
158 				/*
159 				 * If the new route specifies it be
160 				 * externally resolved, then go do that.
161 				 */
162 				msgtype = RTM_RESOLVE;
163 				goto miss;
164 			}
165 		} else
166 			rt->rt_refcnt++;
167 	} else {
168 		/*
169 		 * Either we hit the root or couldn't find any match,
170 		 * Which basically means
171 		 * "caint get there frm here"
172 		 */
173 		rtstat.rts_unreach++;
174 	miss:	if (report) {
175 			/*
176 			 * If required, report the failure to the supervising
177 			 * Authorities.
178 			 * For a delete, this is not an error. (report == 0)
179 			 */
180 			bzero((caddr_t)&info, sizeof(info));
181 			info.rti_info[RTAX_DST] = dst;
182 			rt_missmsg(msgtype, &info, 0, err);
183 		}
184 	}
185 	splx(s);
186 	return (newrt);
187 }
188 
189 void
190 rtfree(rt)
191 	register struct rtentry *rt;
192 {
193 	register struct radix_node_head *rnh =
194 		rt_tables[rt_key(rt)->sa_family];
195 	register struct ifaddr *ifa;
196 
197 	if (rt == 0 || rnh == 0)
198 		panic("rtfree");
199 	rt->rt_refcnt--;
200 	if(rnh->rnh_close && rt->rt_refcnt == 0) {
201 		rnh->rnh_close((struct radix_node *)rt, rnh);
202 	}
203 	if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) {
204 		if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT))
205 			panic ("rtfree 2");
206 		rttrash--;
207 		if (rt->rt_refcnt < 0) {
208 			printf("rtfree: %p not freed (neg refs)\n", rt);
209 			return;
210 		}
211 		ifa = rt->rt_ifa;
212 		IFAFREE(ifa);
213 		if (rt->rt_parent) {
214 			RTFREE(rt->rt_parent);
215 		}
216 		Free(rt_key(rt));
217 		Free(rt);
218 	}
219 }
220 
221 void
222 ifafree(ifa)
223 	register struct ifaddr *ifa;
224 {
225 	if (ifa == NULL)
226 		panic("ifafree");
227 	if (ifa->ifa_refcnt == 0)
228 		free(ifa, M_IFADDR);
229 	else
230 		ifa->ifa_refcnt--;
231 }
232 
233 /*
234  * Force a routing table entry to the specified
235  * destination to go through the given gateway.
236  * Normally called as a result of a routing redirect
237  * message from the network layer.
238  *
239  * N.B.: must be called at splnet
240  *
241  */
242 void
243 rtredirect(dst, gateway, netmask, flags, src, rtp)
244 	struct sockaddr *dst, *gateway, *netmask, *src;
245 	int flags;
246 	struct rtentry **rtp;
247 {
248 	register struct rtentry *rt;
249 	int error = 0;
250 	short *stat = 0;
251 	struct rt_addrinfo info;
252 	struct ifaddr *ifa;
253 
254 	/* verify the gateway is directly reachable */
255 	if ((ifa = ifa_ifwithnet(gateway)) == 0) {
256 		error = ENETUNREACH;
257 		goto out;
258 	}
259 	rt = rtalloc1(dst, 0, 0UL);
260 	/*
261 	 * If the redirect isn't from our current router for this dst,
262 	 * it's either old or wrong.  If it redirects us to ourselves,
263 	 * we have a routing loop, perhaps as a result of an interface
264 	 * going down recently.
265 	 */
266 #define	equal(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0)
267 	if (!(flags & RTF_DONE) && rt &&
268 	     (!equal(src, rt->rt_gateway) || rt->rt_ifa != ifa))
269 		error = EINVAL;
270 	else if (ifa_ifwithaddr(gateway))
271 		error = EHOSTUNREACH;
272 	if (error)
273 		goto done;
274 	/*
275 	 * Create a new entry if we just got back a wildcard entry
276 	 * or the the lookup failed.  This is necessary for hosts
277 	 * which use routing redirects generated by smart gateways
278 	 * to dynamically build the routing tables.
279 	 */
280 	if ((rt == 0) || (rt_mask(rt) && rt_mask(rt)->sa_len < 2))
281 		goto create;
282 	/*
283 	 * Don't listen to the redirect if it's
284 	 * for a route to an interface.
285 	 */
286 	if (rt->rt_flags & RTF_GATEWAY) {
287 		if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) {
288 			/*
289 			 * Changing from route to net => route to host.
290 			 * Create new route, rather than smashing route to net.
291 			 */
292 		create:
293 			flags |=  RTF_GATEWAY | RTF_DYNAMIC;
294 			error = rtrequest((int)RTM_ADD, dst, gateway,
295 				    netmask, flags,
296 				    (struct rtentry **)0);
297 			stat = &rtstat.rts_dynamic;
298 		} else {
299 			/*
300 			 * Smash the current notion of the gateway to
301 			 * this destination.  Should check about netmask!!!
302 			 */
303 			rt->rt_flags |= RTF_MODIFIED;
304 			flags |= RTF_MODIFIED;
305 			stat = &rtstat.rts_newgateway;
306 			rt_setgate(rt, rt_key(rt), gateway);
307 		}
308 	} else
309 		error = EHOSTUNREACH;
310 done:
311 	if (rt) {
312 		if (rtp && !error)
313 			*rtp = rt;
314 		else
315 			rtfree(rt);
316 	}
317 out:
318 	if (error)
319 		rtstat.rts_badredirect++;
320 	else if (stat != NULL)
321 		(*stat)++;
322 	bzero((caddr_t)&info, sizeof(info));
323 	info.rti_info[RTAX_DST] = dst;
324 	info.rti_info[RTAX_GATEWAY] = gateway;
325 	info.rti_info[RTAX_NETMASK] = netmask;
326 	info.rti_info[RTAX_AUTHOR] = src;
327 	rt_missmsg(RTM_REDIRECT, &info, flags, error);
328 }
329 
330 /*
331 * Routing table ioctl interface.
332 */
333 int
334 rtioctl(req, data, p)
335 	int req;
336 	caddr_t data;
337 	struct proc *p;
338 {
339 #ifdef INET
340 	/* Multicast goop, grrr... */
341 #ifdef MROUTING
342 	return mrt_ioctl(req, data);
343 #else
344 	return mrt_ioctl(req, data, p);
345 #endif
346 #else /* INET */
347 	return ENXIO;
348 #endif /* INET */
349 }
350 
351 struct ifaddr *
352 ifa_ifwithroute(flags, dst, gateway)
353 	int flags;
354 	struct sockaddr	*dst, *gateway;
355 {
356 	register struct ifaddr *ifa;
357 	if ((flags & RTF_GATEWAY) == 0) {
358 		/*
359 		 * If we are adding a route to an interface,
360 		 * and the interface is a pt to pt link
361 		 * we should search for the destination
362 		 * as our clue to the interface.  Otherwise
363 		 * we can use the local address.
364 		 */
365 		ifa = 0;
366 		if (flags & RTF_HOST) {
367 			ifa = ifa_ifwithdstaddr(dst);
368 		}
369 		if (ifa == 0)
370 			ifa = ifa_ifwithaddr(gateway);
371 	} else {
372 		/*
373 		 * If we are adding a route to a remote net
374 		 * or host, the gateway may still be on the
375 		 * other end of a pt to pt link.
376 		 */
377 		ifa = ifa_ifwithdstaddr(gateway);
378 	}
379 	if (ifa == 0)
380 		ifa = ifa_ifwithnet(gateway);
381 	if (ifa == 0) {
382 		struct rtentry *rt = rtalloc1(dst, 0, 0UL);
383 		if (rt == 0)
384 			return (0);
385 		rt->rt_refcnt--;
386 		if ((ifa = rt->rt_ifa) == 0)
387 			return (0);
388 	}
389 	if (ifa->ifa_addr->sa_family != dst->sa_family) {
390 		struct ifaddr *oifa = ifa;
391 		ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp);
392 		if (ifa == 0)
393 			ifa = oifa;
394 	}
395 	return (ifa);
396 }
397 
398 #define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
399 
400 static int rt_fixdelete(struct radix_node *, void *);
401 static int rt_fixchange(struct radix_node *, void *);
402 
403 struct rtfc_arg {
404 	struct rtentry *rt0;
405 	struct radix_node_head *rnh;
406 };
407 
408 /*
409  * Do appropriate manipulations of a routing tree given
410  * all the bits of info needed
411  */
412 int
413 rtrequest(req, dst, gateway, netmask, flags, ret_nrt)
414 	int req, flags;
415 	struct sockaddr *dst, *gateway, *netmask;
416 	struct rtentry **ret_nrt;
417 {
418 	int s = splnet(); int error = 0;
419 	register struct rtentry *rt;
420 	register struct radix_node *rn;
421 	register struct radix_node_head *rnh;
422 	struct ifaddr *ifa;
423 	struct sockaddr *ndst;
424 #define senderr(x) { error = x ; goto bad; }
425 
426 	/*
427 	 * Find the correct routing tree to use for this Address Family
428 	 */
429 	if ((rnh = rt_tables[dst->sa_family]) == 0)
430 		senderr(ESRCH);
431 	/*
432 	 * If we are adding a host route then we don't want to put
433 	 * a netmask in the tree
434 	 */
435 	if (flags & RTF_HOST)
436 		netmask = 0;
437 	switch (req) {
438 	case RTM_DELETE:
439 		/*
440 		 * Remove the item from the tree and return it.
441 		 * Complain if it is not there and do no more processing.
442 		 */
443 		if ((rn = rnh->rnh_deladdr(dst, netmask, rnh)) == 0)
444 			senderr(ESRCH);
445 		if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT))
446 			panic ("rtrequest delete");
447 		rt = (struct rtentry *)rn;
448 
449 		/*
450 		 * Now search what's left of the subtree for any cloned
451 		 * routes which might have been formed from this node.
452 		 */
453 		if ((rt->rt_flags & RTF_PRCLONING) && netmask) {
454 			rnh->rnh_walktree_from(rnh, dst, netmask,
455 					       rt_fixdelete, rt);
456 		}
457 
458 		/*
459 		 * Remove any external references we may have.
460 		 * This might result in another rtentry being freed if
461 		 * we held it's last reference.
462 		 */
463 		if (rt->rt_gwroute) {
464 			rt = rt->rt_gwroute;
465 			RTFREE(rt);
466 			(rt = (struct rtentry *)rn)->rt_gwroute = 0;
467 		}
468 
469 		/*
470 		 * NB: RTF_UP must be set during the search above,
471 		 * because we might delete the last ref, causing
472 		 * rt to get freed prematurely.
473 		 */
474 		rt->rt_flags &= ~RTF_UP;
475 
476 		/*
477 		 * If there is llinfo or similar associated with the
478 		 * route, give the protocol a chance to deal with it..
479 		 */
480 		if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest)
481 			ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0));
482 		rttrash++;
483 		/*
484 		 * If the caller wants it, then it can have it, but it's up to it
485 		 * to free the rtentry as we won't be doing it.
486 		 */
487 		if (ret_nrt)
488 			*ret_nrt = rt;
489 		else if (rt->rt_refcnt <= 0) {
490 			rt->rt_refcnt++; /* make a 1->0 transition */
491 			rtfree(rt);
492 		}
493 		break;
494 
495 	case RTM_RESOLVE:
496 		if (ret_nrt == 0 || (rt = *ret_nrt) == 0)
497 			senderr(EINVAL);
498 		ifa = rt->rt_ifa;
499 		flags = rt->rt_flags &
500 		    ~(RTF_CLONING | RTF_PRCLONING | RTF_STATIC);
501 		flags |= RTF_WASCLONED;
502 		gateway = rt->rt_gateway;
503 		if ((netmask = rt->rt_genmask) == 0)
504 			flags |= RTF_HOST;
505 		goto makeroute;
506 
507 	case RTM_ADD:
508 		if ((flags & RTF_GATEWAY) && !gateway)
509 			panic("rtrequest: GATEWAY but no gateway");
510 
511 		if ((ifa = ifa_ifwithroute(flags, dst, gateway)) == 0)
512 			senderr(ENETUNREACH);
513 
514 	makeroute:
515 		R_Malloc(rt, struct rtentry *, sizeof(*rt));
516 		if (rt == 0)
517 			senderr(ENOBUFS);
518 		Bzero(rt, sizeof(*rt));
519 		rt->rt_flags = RTF_UP | flags;
520 		if (error = rt_setgate(rt, dst, gateway)) {
521 			Free(rt);
522 			senderr(error);
523 		}
524 		ndst = rt_key(rt);
525 		if (netmask) {
526 			rt_maskedcopy(dst, ndst, netmask);
527 		} else
528 			Bcopy(dst, ndst, dst->sa_len);
529 
530 		/*
531 		 * This moved from below so that rnh->rnh_addaddr() can
532 		 * examine the ifa and ifp if it so desires.
533 		 */
534 		ifa->ifa_refcnt++;
535 		rt->rt_ifa = ifa;
536 		rt->rt_ifp = ifa->ifa_ifp;
537 
538 		rn = rnh->rnh_addaddr((caddr_t)ndst, (caddr_t)netmask,
539 					rnh, rt->rt_nodes);
540 		if (rn == 0) {
541 			struct rtentry *rt2;
542 			/*
543 			 * Uh-oh, we already have one of these in the tree.
544 			 * We do a special hack: if the route that's already
545 			 * there was generated by the protocol-cloning
546 			 * mechanism, then we just blow it away and retry
547 			 * the insertion of the new one.
548 			 */
549 			rt2 = rtalloc1(dst, 0, RTF_PRCLONING);
550 			if (rt2 && rt2->rt_parent) {
551 				rtrequest(RTM_DELETE,
552 					  (struct sockaddr *)rt_key(rt2),
553 					  rt2->rt_gateway,
554 					  rt_mask(rt2), rt2->rt_flags, 0);
555 				RTFREE(rt2);
556 				rn = rnh->rnh_addaddr((caddr_t)ndst,
557 						      (caddr_t)netmask,
558 						      rnh, rt->rt_nodes);
559 			} else if (rt2) {
560 				RTFREE(rt2);
561 			}
562 		}
563 
564 		if (rn == 0) {
565 			if (rt->rt_gwroute)
566 				rtfree(rt->rt_gwroute);
567 			if (rt->rt_ifa) {
568 				IFAFREE(rt->rt_ifa);
569 			}
570 			Free(rt_key(rt));
571 			Free(rt);
572 			senderr(EEXIST);
573 		}
574 		rt->rt_parent = 0;
575 
576 		if (req == RTM_RESOLVE) {
577 			rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */
578 			if ((*ret_nrt)->rt_flags & RTF_PRCLONING) {
579 				rt->rt_parent = (*ret_nrt);
580 				(*ret_nrt)->rt_refcnt++;
581 			}
582 		}
583 		if (ifa->ifa_rtrequest)
584 			ifa->ifa_rtrequest(req, rt, SA(ret_nrt ? *ret_nrt : 0));
585 		/*
586 		 * We repeat the same procedure from rt_setgate() here because
587 		 * it doesn't fire when we call it there because the node
588 		 * hasn't been added to the tree yet.
589 		 */
590 		if (!(rt->rt_flags & RTF_HOST) && rt_mask(rt) != 0) {
591 			struct rtfc_arg arg;
592 			arg.rnh = rnh;
593 			arg.rt0 = rt;
594 			rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt),
595 					       rt_fixchange, &arg);
596 		}
597 
598 		if (ret_nrt) {
599 			*ret_nrt = rt;
600 			rt->rt_refcnt++;
601 		}
602 		break;
603 	}
604 bad:
605 	splx(s);
606 	return (error);
607 }
608 
609 /*
610  * Called from rtrequest(RTM_DELETE, ...) to fix up the route's ``family''
611  * (i.e., the routes related to it by the operation of cloning).  This
612  * routine is iterated over all potential former-child-routes by way of
613  * rnh->rnh_walktree_from() above, and those that actually are children of
614  * the late parent (passed in as VP here) are themselves deleted.
615  */
616 static int
617 rt_fixdelete(struct radix_node *rn, void *vp)
618 {
619 	struct rtentry *rt = (struct rtentry *)rn;
620 	struct rtentry *rt0 = vp;
621 
622 	if (rt->rt_parent == rt0 && !(rt->rt_flags & RTF_PINNED)) {
623 		return rtrequest(RTM_DELETE, rt_key(rt),
624 				 (struct sockaddr *)0, rt_mask(rt),
625 				 rt->rt_flags, (struct rtentry **)0);
626 	}
627 	return 0;
628 }
629 
630 /*
631  * This routine is called from rt_setgate() to do the analogous thing for
632  * adds and changes.  There is the added complication in this case of a
633  * middle insert; i.e., insertion of a new network route between an older
634  * network route and (cloned) host routes.  For this reason, a simple check
635  * of rt->rt_parent is insufficient; each candidate route must be tested
636  * against the (mask, value) of the new route (passed as before in vp)
637  * to see if the new route matches it.  Unfortunately, this has the obnoxious
638  * property of also triggering for insertion /above/ a pre-existing network
639  * route and clones.  Sigh.  This may be fixed some day.
640  *
641  * XXX - it may be possible to do fixdelete() for changes and reserve this
642  * routine just for adds.  I'm not sure why I thought it was necessary to do
643  * changes this way.
644  */
645 #ifdef DEBUG
646 int rtfcdebug = 0;
647 #endif
648 
649 static int
650 rt_fixchange(struct radix_node *rn, void *vp)
651 {
652 	struct rtentry *rt = (struct rtentry *)rn;
653 	struct rtfc_arg *ap = vp;
654 	struct rtentry *rt0 = ap->rt0;
655 	struct radix_node_head *rnh = ap->rnh;
656 	u_char *xk1, *xm1, *xk2;
657 	int i, len;
658 
659 #ifdef DEBUG
660 	if (rtfcdebug)
661 		printf("rt_fixchange: rt %p, rt0 %p\n", rt, rt0);
662 #endif
663 
664 	if (!rt->rt_parent || (rt->rt_flags & RTF_PINNED)) {
665 #ifdef DEBUG
666 		if(rtfcdebug) printf("no parent or pinned\n");
667 #endif
668 		return 0;
669 	}
670 
671 	if (rt->rt_parent == rt0) {
672 #ifdef DEBUG
673 		if(rtfcdebug) printf("parent match\n");
674 #endif
675 		return rtrequest(RTM_DELETE, rt_key(rt),
676 				 (struct sockaddr *)0, rt_mask(rt),
677 				 rt->rt_flags, (struct rtentry **)0);
678 	}
679 
680 	/*
681 	 * There probably is a function somewhere which does this...
682 	 * if not, there should be.
683 	 */
684 	len = imin(((struct sockaddr *)rt_key(rt0))->sa_len,
685 		   ((struct sockaddr *)rt_key(rt))->sa_len);
686 
687 	xk1 = (u_char *)rt_key(rt0);
688 	xm1 = (u_char *)rt_mask(rt0);
689 	xk2 = (u_char *)rt_key(rt);
690 
691 	for (i = rnh->rnh_treetop->rn_off; i < len; i++) {
692 		if ((xk2[i] & xm1[i]) != xk1[i]) {
693 #ifdef DEBUG
694 			if(rtfcdebug) printf("no match\n");
695 #endif
696 			return 0;
697 		}
698 	}
699 
700 	/*
701 	 * OK, this node is a clone, and matches the node currently being
702 	 * changed/added under the node's mask.  So, get rid of it.
703 	 */
704 #ifdef DEBUG
705 	if(rtfcdebug) printf("deleting\n");
706 #endif
707 	return rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0,
708 			 rt_mask(rt), rt->rt_flags, (struct rtentry **)0);
709 }
710 
711 int
712 rt_setgate(rt0, dst, gate)
713 	struct rtentry *rt0;
714 	struct sockaddr *dst, *gate;
715 {
716 	caddr_t new, old;
717 	int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len);
718 	register struct rtentry *rt = rt0;
719 	struct radix_node_head *rnh = rt_tables[dst->sa_family];
720 
721 	/*
722 	 * A host route with the destination equal to the gateway
723 	 * will interfere with keeping LLINFO in the routing
724 	 * table, so disallow it.
725 	 */
726 	if (((rt0->rt_flags & (RTF_HOST|RTF_GATEWAY|RTF_LLINFO)) ==
727 					(RTF_HOST|RTF_GATEWAY)) &&
728 	    (dst->sa_len == gate->sa_len) &&
729 	    (bcmp(dst, gate, dst->sa_len) == 0)) {
730 		/*
731 		 * The route might already exist if this is an RTM_CHANGE
732 		 * or a routing redirect, so try to delete it.
733 		 */
734 		if (rt_key(rt0))
735 			rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt0),
736 			    rt0->rt_gateway, rt_mask(rt0), rt0->rt_flags, 0);
737 		return EADDRNOTAVAIL;
738 	}
739 
740 	if (rt->rt_gateway == 0 || glen > ROUNDUP(rt->rt_gateway->sa_len)) {
741 		old = (caddr_t)rt_key(rt);
742 		R_Malloc(new, caddr_t, dlen + glen);
743 		if (new == 0)
744 			return ENOBUFS;
745 		rt->rt_nodes->rn_key = new;
746 	} else {
747 		new = rt->rt_nodes->rn_key;
748 		old = 0;
749 	}
750 	Bcopy(gate, (rt->rt_gateway = (struct sockaddr *)(new + dlen)), glen);
751 	if (old) {
752 		Bcopy(dst, new, dlen);
753 		Free(old);
754 	}
755 	if (rt->rt_gwroute) {
756 		rt = rt->rt_gwroute; RTFREE(rt);
757 		rt = rt0; rt->rt_gwroute = 0;
758 	}
759 	/*
760 	 * Cloning loop avoidance:
761 	 * In the presence of protocol-cloning and bad configuration,
762 	 * it is possible to get stuck in bottomless mutual recursion
763 	 * (rtrequest rt_setgate rtalloc1).  We avoid this by not allowing
764 	 * protocol-cloning to operate for gateways (which is probably the
765 	 * correct choice anyway), and avoid the resulting reference loops
766 	 * by disallowing any route to run through itself as a gateway.
767 	 * This is obviuosly mandatory when we get rt->rt_output().
768 	 */
769 	if (rt->rt_flags & RTF_GATEWAY) {
770 		rt->rt_gwroute = rtalloc1(gate, 1, RTF_PRCLONING);
771 		if (rt->rt_gwroute == rt) {
772 			RTFREE(rt->rt_gwroute);
773 			rt->rt_gwroute = 0;
774 			return EDQUOT; /* failure */
775 		}
776 	}
777 
778 	/*
779 	 * This isn't going to do anything useful for host routes, so
780 	 * don't bother.  Also make sure we have a reasonable mask
781 	 * (we don't yet have one during adds).
782 	 */
783 	if (!(rt->rt_flags & RTF_HOST) && rt_mask(rt) != 0) {
784 		struct rtfc_arg arg;
785 		arg.rnh = rnh;
786 		arg.rt0 = rt;
787 		rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt),
788 				       rt_fixchange, &arg);
789 	}
790 
791 	return 0;
792 }
793 
794 static void
795 rt_maskedcopy(src, dst, netmask)
796 	struct sockaddr *src, *dst, *netmask;
797 {
798 	register u_char *cp1 = (u_char *)src;
799 	register u_char *cp2 = (u_char *)dst;
800 	register u_char *cp3 = (u_char *)netmask;
801 	u_char *cplim = cp2 + *cp3;
802 	u_char *cplim2 = cp2 + *cp1;
803 
804 	*cp2++ = *cp1++; *cp2++ = *cp1++; /* copies sa_len & sa_family */
805 	cp3 += 2;
806 	if (cplim > cplim2)
807 		cplim = cplim2;
808 	while (cp2 < cplim)
809 		*cp2++ = *cp1++ & *cp3++;
810 	if (cp2 < cplim2)
811 		bzero((caddr_t)cp2, (unsigned)(cplim2 - cp2));
812 }
813 
814 /*
815  * Set up a routing table entry, normally
816  * for an interface.
817  */
818 int
819 rtinit(ifa, cmd, flags)
820 	register struct ifaddr *ifa;
821 	int cmd, flags;
822 {
823 	register struct rtentry *rt;
824 	register struct sockaddr *dst;
825 	register struct sockaddr *deldst;
826 	struct mbuf *m = 0;
827 	struct rtentry *nrt = 0;
828 	int error;
829 
830 	dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr;
831 	/*
832 	 * If it's a delete, check that if it exists, it's on the correct
833 	 * interface or we might scrub a route to another ifa which would
834 	 * be confusing at best and possibly worse.
835 	 */
836 	if (cmd == RTM_DELETE) {
837 		/*
838 		 * It's a delete, so it should already exist..
839 		 * If it's a net, mask off the host bits
840 		 * (Assuming we have a mask)
841 		 */
842 		if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) {
843 			m = m_get(M_WAIT, MT_SONAME);
844 			deldst = mtod(m, struct sockaddr *);
845 			rt_maskedcopy(dst, deldst, ifa->ifa_netmask);
846 			dst = deldst;
847 		}
848 		/*
849 		 * Get an rtentry that is in the routing tree and
850 		 * contains the correct info. (if this fails we can't get there).
851 		 * We set "report" to FALSE so that if it doesn't exist,
852 		 * it doesn't report an error or clone a route, etc. etc.
853 		 */
854 		rt = rtalloc1(dst, 0, 0UL);
855 		if (rt) {
856 			/*
857 			 * Ok so we found the rtentry. it has an extra reference
858 			 * for us at this stage. we won't need that so
859 			 * lop that off now.
860 			 */
861 			rt->rt_refcnt--;
862 			if (rt->rt_ifa != ifa) {
863 				/*
864 				 * If the interface in the rtentry doesn't match
865 				 * the interface we are using, then we don't
866 				 * want to delete it, so return an error.
867 				 * This seems to be the only point of
868 				 * this whole RTM_DELETE clause.
869 				 */
870 				if (m)
871 					(void) m_free(m);
872 				return (flags & RTF_HOST ? EHOSTUNREACH
873 							: ENETUNREACH);
874 			}
875 		}
876 		/* XXX */
877 #if 0
878 		else {
879 			/*
880 			 * One would think that as we are deleting, and we know
881 			 * it doesn't exist, we could just return at this point
882 			 * with an "ELSE" clause, but apparently not..
883 			 */
884 			return (flags & RTF_HOST ? EHOSTUNREACH
885 							: ENETUNREACH);
886 		}
887 #endif
888 	}
889 	/*
890 	 * Do the actual request
891 	 */
892 	error = rtrequest(cmd, dst, ifa->ifa_addr, ifa->ifa_netmask,
893 			flags | ifa->ifa_flags, &nrt);
894 	if (m)
895 		(void) m_free(m);
896 	/*
897 	 * If we are deleting, and we found an entry, then
898 	 * it's been removed from the tree.. now throw it away.
899 	 */
900 	if (cmd == RTM_DELETE && error == 0 && (rt = nrt)) {
901 		/*
902 		 * notify any listenning routing agents of the change
903 		 */
904 		rt_newaddrmsg(cmd, ifa, error, nrt);
905 		if (rt->rt_refcnt <= 0) {
906 			rt->rt_refcnt++; /* need a 1->0 transition to free */
907 			rtfree(rt);
908 		}
909 	}
910 
911 	/*
912 	 * We are adding, and we have a returned routing entry.
913 	 * We need to sanity check the result.
914 	 */
915 	if (cmd == RTM_ADD && error == 0 && (rt = nrt)) {
916 		/*
917 		 * We just wanted to add it.. we don't actually need a reference
918 		 */
919 		rt->rt_refcnt--;
920 		/*
921 		 * If it came back with an unexpected interface, then it must
922 		 * have already existed or something. (XXX)
923 		 */
924 		if (rt->rt_ifa != ifa) {
925 			printf("rtinit: wrong ifa (%p) was (%p)\n", ifa,
926 				rt->rt_ifa);
927 			/*
928 			 * Ask that the route we got back be removed
929 			 * from the routing tables as we are trying
930 			 * to supersede it.
931 			 */
932 			if (rt->rt_ifa->ifa_rtrequest)
933 			    rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0));
934 			/*
935 			 * Remove the referenve to the it's ifaddr.
936 			 */
937 			IFAFREE(rt->rt_ifa);
938 			/*
939 			 * And substitute in references to the ifaddr
940 			 * we are adding.
941 			 */
942 			rt->rt_ifa = ifa;
943 			rt->rt_ifp = ifa->ifa_ifp;
944 			ifa->ifa_refcnt++;
945 			/*
946 			 * Now add it to the routing table
947 			 * XXX could we have just left it?
948 			 * as it might have been in the right place..
949 			 */
950 			if (ifa->ifa_rtrequest)
951 			    ifa->ifa_rtrequest(RTM_ADD, rt, SA(0));
952 		}
953 		/*
954 		 * notify any listenning routing agents of the change
955 		 */
956 		rt_newaddrmsg(cmd, ifa, error, nrt);
957 	}
958 	return (error);
959 }
960