xref: /freebsd/sys/net/route.c (revision 05c7a37afb48ddd5ee1bd921a5d46fe59cc70b15)
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  *	$Id: route.c,v 1.32 1996/03/11 15:13:05 davidg Exp $
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 struct rtentry *
112 rtalloc1(dst, report, ignflags)
113 	register struct sockaddr *dst;
114 	int report;
115 	u_long ignflags;
116 {
117 	register struct radix_node_head *rnh = rt_tables[dst->sa_family];
118 	register struct rtentry *rt;
119 	register struct radix_node *rn;
120 	struct rtentry *newrt = 0;
121 	struct rt_addrinfo info;
122 	u_long nflags;
123 	int  s = splnet(), err = 0, msgtype = RTM_MISS;
124 
125 	if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) &&
126 	    ((rn->rn_flags & RNF_ROOT) == 0)) {
127 		newrt = rt = (struct rtentry *)rn;
128 		nflags = rt->rt_flags & ~ignflags;
129 		if (report && (nflags & (RTF_CLONING | RTF_PRCLONING))) {
130 			err = rtrequest(RTM_RESOLVE, dst, SA(0),
131 					      SA(0), 0, &newrt);
132 			if (err) {
133 				newrt = rt;
134 				rt->rt_refcnt++;
135 				goto miss;
136 			}
137 			if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) {
138 				msgtype = RTM_RESOLVE;
139 				goto miss;
140 			}
141 		} else
142 			rt->rt_refcnt++;
143 	} else {
144 		rtstat.rts_unreach++;
145 	miss:	if (report) {
146 			bzero((caddr_t)&info, sizeof(info));
147 			info.rti_info[RTAX_DST] = dst;
148 			rt_missmsg(msgtype, &info, 0, err);
149 		}
150 	}
151 	splx(s);
152 	return (newrt);
153 }
154 
155 void
156 rtfree(rt)
157 	register struct rtentry *rt;
158 {
159 	register struct radix_node_head *rnh =
160 		rt_tables[rt_key(rt)->sa_family];
161 	register struct ifaddr *ifa;
162 
163 	if (rt == 0 || rnh == 0)
164 		panic("rtfree");
165 	rt->rt_refcnt--;
166 	if(rnh->rnh_close && rt->rt_refcnt == 0) {
167 		rnh->rnh_close((struct radix_node *)rt, rnh);
168 	}
169 	if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) {
170 		if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT))
171 			panic ("rtfree 2");
172 		rttrash--;
173 		if (rt->rt_refcnt < 0) {
174 			printf("rtfree: %p not freed (neg refs)\n", rt);
175 			return;
176 		}
177 		ifa = rt->rt_ifa;
178 		IFAFREE(ifa);
179 		if (rt->rt_parent) {
180 			RTFREE(rt->rt_parent);
181 		}
182 		Free(rt_key(rt));
183 		Free(rt);
184 	}
185 }
186 
187 void
188 ifafree(ifa)
189 	register struct ifaddr *ifa;
190 {
191 	if (ifa == NULL)
192 		panic("ifafree");
193 	if (ifa->ifa_refcnt == 0)
194 		free(ifa, M_IFADDR);
195 	else
196 		ifa->ifa_refcnt--;
197 }
198 
199 /*
200  * Force a routing table entry to the specified
201  * destination to go through the given gateway.
202  * Normally called as a result of a routing redirect
203  * message from the network layer.
204  *
205  * N.B.: must be called at splnet
206  *
207  */
208 void
209 rtredirect(dst, gateway, netmask, flags, src, rtp)
210 	struct sockaddr *dst, *gateway, *netmask, *src;
211 	int flags;
212 	struct rtentry **rtp;
213 {
214 	register struct rtentry *rt;
215 	int error = 0;
216 	short *stat = 0;
217 	struct rt_addrinfo info;
218 	struct ifaddr *ifa;
219 
220 	/* verify the gateway is directly reachable */
221 	if ((ifa = ifa_ifwithnet(gateway)) == 0) {
222 		error = ENETUNREACH;
223 		goto out;
224 	}
225 	rt = rtalloc1(dst, 0, 0UL);
226 	/*
227 	 * If the redirect isn't from our current router for this dst,
228 	 * it's either old or wrong.  If it redirects us to ourselves,
229 	 * we have a routing loop, perhaps as a result of an interface
230 	 * going down recently.
231 	 */
232 #define	equal(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0)
233 	if (!(flags & RTF_DONE) && rt &&
234 	     (!equal(src, rt->rt_gateway) || rt->rt_ifa != ifa))
235 		error = EINVAL;
236 	else if (ifa_ifwithaddr(gateway))
237 		error = EHOSTUNREACH;
238 	if (error)
239 		goto done;
240 	/*
241 	 * Create a new entry if we just got back a wildcard entry
242 	 * or the the lookup failed.  This is necessary for hosts
243 	 * which use routing redirects generated by smart gateways
244 	 * to dynamically build the routing tables.
245 	 */
246 	if ((rt == 0) || (rt_mask(rt) && rt_mask(rt)->sa_len < 2))
247 		goto create;
248 	/*
249 	 * Don't listen to the redirect if it's
250 	 * for a route to an interface.
251 	 */
252 	if (rt->rt_flags & RTF_GATEWAY) {
253 		if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) {
254 			/*
255 			 * Changing from route to net => route to host.
256 			 * Create new route, rather than smashing route to net.
257 			 */
258 		create:
259 			flags |=  RTF_GATEWAY | RTF_DYNAMIC;
260 			error = rtrequest((int)RTM_ADD, dst, gateway,
261 				    netmask, flags,
262 				    (struct rtentry **)0);
263 			stat = &rtstat.rts_dynamic;
264 		} else {
265 			/*
266 			 * Smash the current notion of the gateway to
267 			 * this destination.  Should check about netmask!!!
268 			 */
269 			rt->rt_flags |= RTF_MODIFIED;
270 			flags |= RTF_MODIFIED;
271 			stat = &rtstat.rts_newgateway;
272 			rt_setgate(rt, rt_key(rt), gateway);
273 		}
274 	} else
275 		error = EHOSTUNREACH;
276 done:
277 	if (rt) {
278 		if (rtp && !error)
279 			*rtp = rt;
280 		else
281 			rtfree(rt);
282 	}
283 out:
284 	if (error)
285 		rtstat.rts_badredirect++;
286 	else if (stat != NULL)
287 		(*stat)++;
288 	bzero((caddr_t)&info, sizeof(info));
289 	info.rti_info[RTAX_DST] = dst;
290 	info.rti_info[RTAX_GATEWAY] = gateway;
291 	info.rti_info[RTAX_NETMASK] = netmask;
292 	info.rti_info[RTAX_AUTHOR] = src;
293 	rt_missmsg(RTM_REDIRECT, &info, flags, error);
294 }
295 
296 /*
297 * Routing table ioctl interface.
298 */
299 int
300 rtioctl(req, data, p)
301 	int req;
302 	caddr_t data;
303 	struct proc *p;
304 {
305 #ifdef INET
306 	/* Multicast goop, grrr... */
307 #ifdef MROUTING
308 	return mrt_ioctl(req, data);
309 #else
310 	return mrt_ioctl(req, data, p);
311 #endif
312 #else /* INET */
313 	return ENXIO;
314 #endif /* INET */
315 }
316 
317 struct ifaddr *
318 ifa_ifwithroute(flags, dst, gateway)
319 	int flags;
320 	struct sockaddr	*dst, *gateway;
321 {
322 	register struct ifaddr *ifa;
323 	if ((flags & RTF_GATEWAY) == 0) {
324 		/*
325 		 * If we are adding a route to an interface,
326 		 * and the interface is a pt to pt link
327 		 * we should search for the destination
328 		 * as our clue to the interface.  Otherwise
329 		 * we can use the local address.
330 		 */
331 		ifa = 0;
332 		if (flags & RTF_HOST) {
333 			ifa = ifa_ifwithdstaddr(dst);
334 		}
335 		if (ifa == 0)
336 			ifa = ifa_ifwithaddr(gateway);
337 	} else {
338 		/*
339 		 * If we are adding a route to a remote net
340 		 * or host, the gateway may still be on the
341 		 * other end of a pt to pt link.
342 		 */
343 		ifa = ifa_ifwithdstaddr(gateway);
344 	}
345 	if (ifa == 0)
346 		ifa = ifa_ifwithnet(gateway);
347 	if (ifa == 0) {
348 		struct rtentry *rt = rtalloc1(dst, 0, 0UL);
349 		if (rt == 0)
350 			return (0);
351 		rt->rt_refcnt--;
352 		if ((ifa = rt->rt_ifa) == 0)
353 			return (0);
354 	}
355 	if (ifa->ifa_addr->sa_family != dst->sa_family) {
356 		struct ifaddr *oifa = ifa;
357 		ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp);
358 		if (ifa == 0)
359 			ifa = oifa;
360 	}
361 	return (ifa);
362 }
363 
364 #define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
365 
366 static int rt_fixdelete(struct radix_node *, void *);
367 static int rt_fixchange(struct radix_node *, void *);
368 
369 struct rtfc_arg {
370 	struct rtentry *rt0;
371 	struct radix_node_head *rnh;
372 };
373 
374 int
375 rtrequest(req, dst, gateway, netmask, flags, ret_nrt)
376 	int req, flags;
377 	struct sockaddr *dst, *gateway, *netmask;
378 	struct rtentry **ret_nrt;
379 {
380 	int s = splnet(); int error = 0;
381 	register struct rtentry *rt;
382 	register struct radix_node *rn;
383 	register struct radix_node_head *rnh;
384 	struct ifaddr *ifa;
385 	struct sockaddr *ndst;
386 #define senderr(x) { error = x ; goto bad; }
387 
388 	if ((rnh = rt_tables[dst->sa_family]) == 0)
389 		senderr(ESRCH);
390 	if (flags & RTF_HOST)
391 		netmask = 0;
392 	switch (req) {
393 	case RTM_DELETE:
394 		if ((rn = rnh->rnh_deladdr(dst, netmask, rnh)) == 0)
395 			senderr(ESRCH);
396 		if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT))
397 			panic ("rtrequest delete");
398 		rt = (struct rtentry *)rn;
399 
400 		/*
401 		 * Now search what's left of the subtree for any cloned
402 		 * routes which might have been formed from this node.
403 		 */
404 		if ((rt->rt_flags & RTF_PRCLONING) && netmask) {
405 			rnh->rnh_walktree_from(rnh, dst, netmask,
406 					       rt_fixdelete, rt);
407 		}
408 
409 		if (rt->rt_gwroute) {
410 			rt = rt->rt_gwroute; RTFREE(rt);
411 			(rt = (struct rtentry *)rn)->rt_gwroute = 0;
412 		}
413 
414 		/*
415 		 * NB: RTF_UP must be set during the search above,
416 		 * because we might delete the last ref, causing
417 		 * rt to get freed prematurely.
418 		 */
419 		rt->rt_flags &= ~RTF_UP;
420 
421 		if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest)
422 			ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0));
423 		rttrash++;
424 		if (ret_nrt)
425 			*ret_nrt = rt;
426 		else if (rt->rt_refcnt <= 0) {
427 			rt->rt_refcnt++;
428 			rtfree(rt);
429 		}
430 		break;
431 
432 	case RTM_RESOLVE:
433 		if (ret_nrt == 0 || (rt = *ret_nrt) == 0)
434 			senderr(EINVAL);
435 		ifa = rt->rt_ifa;
436 		flags = rt->rt_flags &
437 		    ~(RTF_CLONING | RTF_PRCLONING | RTF_STATIC);
438 		flags |= RTF_WASCLONED;
439 		gateway = rt->rt_gateway;
440 		if ((netmask = rt->rt_genmask) == 0)
441 			flags |= RTF_HOST;
442 		goto makeroute;
443 
444 	case RTM_ADD:
445 		if ((flags & RTF_GATEWAY) && !gateway)
446 			panic("rtrequest: GATEWAY but no gateway");
447 
448 		if ((ifa = ifa_ifwithroute(flags, dst, gateway)) == 0)
449 			senderr(ENETUNREACH);
450 
451 	makeroute:
452 		R_Malloc(rt, struct rtentry *, sizeof(*rt));
453 		if (rt == 0)
454 			senderr(ENOBUFS);
455 		Bzero(rt, sizeof(*rt));
456 		rt->rt_flags = RTF_UP | flags;
457 		if (rt_setgate(rt, dst, gateway)) {
458 			Free(rt);
459 			senderr(ENOBUFS);
460 		}
461 		ndst = rt_key(rt);
462 		if (netmask) {
463 			rt_maskedcopy(dst, ndst, netmask);
464 		} else
465 			Bcopy(dst, ndst, dst->sa_len);
466 
467 		/*
468 		 * This moved from below so that rnh->rnh_addaddr() can
469 		 * examine the ifa and ifp if it so desires.
470 		 */
471 		ifa->ifa_refcnt++;
472 		rt->rt_ifa = ifa;
473 		rt->rt_ifp = ifa->ifa_ifp;
474 
475 		rn = rnh->rnh_addaddr((caddr_t)ndst, (caddr_t)netmask,
476 					rnh, rt->rt_nodes);
477 		if (rn == 0) {
478 			struct rtentry *rt2;
479 			/*
480 			 * Uh-oh, we already have one of these in the tree.
481 			 * We do a special hack: if the route that's already
482 			 * there was generated by the protocol-cloning
483 			 * mechanism, then we just blow it away and retry
484 			 * the insertion of the new one.
485 			 */
486 			rt2 = rtalloc1(dst, 0, RTF_PRCLONING);
487 			if (rt2 && rt2->rt_parent) {
488 				rtrequest(RTM_DELETE,
489 					  (struct sockaddr *)rt_key(rt2),
490 					  rt2->rt_gateway,
491 					  rt_mask(rt2), rt2->rt_flags, 0);
492 				RTFREE(rt2);
493 				rn = rnh->rnh_addaddr((caddr_t)ndst,
494 						      (caddr_t)netmask,
495 						      rnh, rt->rt_nodes);
496 			} else if (rt2) {
497 				RTFREE(rt2);
498 			}
499 		}
500 
501 		if (rn == 0) {
502 			if (rt->rt_gwroute)
503 				rtfree(rt->rt_gwroute);
504 			if (rt->rt_ifa) {
505 				IFAFREE(rt->rt_ifa);
506 			}
507 			Free(rt_key(rt));
508 			Free(rt);
509 			senderr(EEXIST);
510 		}
511 		rt->rt_parent = 0;
512 
513 		if (req == RTM_RESOLVE) {
514 			rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */
515 			if ((*ret_nrt)->rt_flags & RTF_PRCLONING) {
516 				rt->rt_parent = (*ret_nrt);
517 				(*ret_nrt)->rt_refcnt++;
518 			}
519 		}
520 		if (ifa->ifa_rtrequest)
521 			ifa->ifa_rtrequest(req, rt, SA(ret_nrt ? *ret_nrt : 0));
522 		/*
523 		 * We repeat the same procedure from rt_setgate() here because
524 		 * it doesn't fire when we call it there because the node
525 		 * hasn't been added to the tree yet.
526 		 */
527 		if (!(rt->rt_flags & RTF_HOST)) {
528 			struct rtfc_arg arg;
529 			arg.rnh = rnh;
530 			arg.rt0 = rt;
531 			rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt),
532 					       rt_fixchange, &arg);
533 		}
534 
535 		if (ret_nrt) {
536 			*ret_nrt = rt;
537 			rt->rt_refcnt++;
538 		}
539 		break;
540 	}
541 bad:
542 	splx(s);
543 	return (error);
544 }
545 
546 /*
547  * Called from rtrequest(RTM_DELETE, ...) to fix up the route's ``family''
548  * (i.e., the routes related to it by the operation of cloning).  This
549  * routine is iterated over all potential former-child-routes by way of
550  * rnh->rnh_walktree_from() above, and those that actually are children of
551  * the late parent (passed in as VP here) are themselves deleted.
552  */
553 static int
554 rt_fixdelete(struct radix_node *rn, void *vp)
555 {
556 	struct rtentry *rt = (struct rtentry *)rn;
557 	struct rtentry *rt0 = vp;
558 
559 	if (rt->rt_parent == rt0 && !(rt->rt_flags & RTF_PINNED)) {
560 		return rtrequest(RTM_DELETE, rt_key(rt),
561 				 (struct sockaddr *)0, rt_mask(rt),
562 				 rt->rt_flags, (struct rtentry **)0);
563 	}
564 	return 0;
565 }
566 
567 /*
568  * This routine is called from rt_setgate() to do the analogous thing for
569  * adds and changes.  There is the added complication in this case of a
570  * middle insert; i.e., insertion of a new network route between an older
571  * network route and (cloned) host routes.  For this reason, a simple check
572  * of rt->rt_parent is insufficient; each candidate route must be tested
573  * against the (mask, value) of the new route (passed as before in vp)
574  * to see if the new route matches it.  Unfortunately, this has the obnoxious
575  * property of also triggering for insertion /above/ a pre-existing network
576  * route and clones.  Sigh.  This may be fixed some day.
577  *
578  * XXX - it may be possible to do fixdelete() for changes and reserve this
579  * routine just for adds.  I'm not sure why I thought it was necessary to do
580  * changes this way.
581  */
582 #ifdef DEBUG
583 int rtfcdebug = 0;
584 #endif
585 
586 static int
587 rt_fixchange(struct radix_node *rn, void *vp)
588 {
589 	struct rtentry *rt = (struct rtentry *)rn;
590 	struct rtfc_arg *ap = vp;
591 	struct rtentry *rt0 = ap->rt0;
592 	struct radix_node_head *rnh = ap->rnh;
593 	u_char *xk1, *xm1, *xk2;
594 	int i, len;
595 
596 #ifdef DEBUG
597 	if (rtfcdebug)
598 		printf("rt_fixchange: rt %p, rt0 %p\n", rt, rt0);
599 #endif
600 
601 	if (!rt->rt_parent || (rt->rt_flags & RTF_PINNED)) {
602 #ifdef DEBUG
603 		if(rtfcdebug) printf("no parent or pinned\n");
604 #endif
605 		return 0;
606 	}
607 
608 	if (rt->rt_parent == rt0) {
609 #ifdef DEBUG
610 		if(rtfcdebug) printf("parent match\n");
611 #endif
612 		return rtrequest(RTM_DELETE, rt_key(rt),
613 				 (struct sockaddr *)0, rt_mask(rt),
614 				 rt->rt_flags, (struct rtentry **)0);
615 	}
616 
617 	/*
618 	 * There probably is a function somewhere which does this...
619 	 * if not, there should be.
620 	 */
621 	len = imin(((struct sockaddr *)rt_key(rt0))->sa_len,
622 		   ((struct sockaddr *)rt_key(rt))->sa_len);
623 
624 	xk1 = (u_char *)rt_key(rt0);
625 	xm1 = (u_char *)rt_mask(rt0);
626 	xk2 = (u_char *)rt_key(rt);
627 
628 	for (i = rnh->rnh_treetop->rn_off; i < len; i++) {
629 		if ((xk2[i] & xm1[i]) != xk1[i]) {
630 #ifdef DEBUG
631 			if(rtfcdebug) printf("no match\n");
632 #endif
633 			return 0;
634 		}
635 	}
636 
637 	/*
638 	 * OK, this node is a clone, and matches the node currently being
639 	 * changed/added under the node's mask.  So, get rid of it.
640 	 */
641 #ifdef DEBUG
642 	if(rtfcdebug) printf("deleting\n");
643 #endif
644 	return rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0,
645 			 rt_mask(rt), rt->rt_flags, (struct rtentry **)0);
646 }
647 
648 int
649 rt_setgate(rt0, dst, gate)
650 	struct rtentry *rt0;
651 	struct sockaddr *dst, *gate;
652 {
653 	caddr_t new, old;
654 	int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len);
655 	register struct rtentry *rt = rt0;
656 	struct radix_node_head *rnh = rt_tables[dst->sa_family];
657 
658 	if (rt->rt_gateway == 0 || glen > ROUNDUP(rt->rt_gateway->sa_len)) {
659 		old = (caddr_t)rt_key(rt);
660 		R_Malloc(new, caddr_t, dlen + glen);
661 		if (new == 0)
662 			return 1;
663 		rt->rt_nodes->rn_key = new;
664 	} else {
665 		new = rt->rt_nodes->rn_key;
666 		old = 0;
667 	}
668 	Bcopy(gate, (rt->rt_gateway = (struct sockaddr *)(new + dlen)), glen);
669 	if (old) {
670 		Bcopy(dst, new, dlen);
671 		Free(old);
672 	}
673 	if (rt->rt_gwroute) {
674 		rt = rt->rt_gwroute; RTFREE(rt);
675 		rt = rt0; rt->rt_gwroute = 0;
676 	}
677 	/*
678 	 * Cloning loop avoidance:
679 	 * In the presence of protocol-cloning and bad configuration,
680 	 * it is possible to get stuck in bottomless mutual recursion
681 	 * (rtrequest rt_setgate rtalloc1).  We avoid this by not allowing
682 	 * protocol-cloning to operate for gateways (which is probably the
683 	 * correct choice anyway), and avoid the resulting reference loops
684 	 * by disallowing any route to run through itself as a gateway.
685 	 * This is obviuosly mandatory when we get rt->rt_output().
686 	 */
687 	if (rt->rt_flags & RTF_GATEWAY) {
688 		rt->rt_gwroute = rtalloc1(gate, 1, RTF_PRCLONING);
689 		if (rt->rt_gwroute == rt) {
690 			RTFREE(rt->rt_gwroute);
691 			rt->rt_gwroute = 0;
692 			return 1; /* failure */
693 		}
694 	}
695 
696 	/*
697 	 * This isn't going to do anything useful for host routes, so
698 	 * don't bother.  Also make sure we have a reasonable mask
699 	 * (we don't yet have one during adds).
700 	 */
701 	if (!(rt->rt_flags & RTF_HOST) && rt_mask(rt) != 0) {
702 		struct rtfc_arg arg;
703 		arg.rnh = rnh;
704 		arg.rt0 = rt;
705 		rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt),
706 				       rt_fixchange, &arg);
707 	}
708 
709 	return 0;
710 }
711 
712 static void
713 rt_maskedcopy(src, dst, netmask)
714 	struct sockaddr *src, *dst, *netmask;
715 {
716 	register u_char *cp1 = (u_char *)src;
717 	register u_char *cp2 = (u_char *)dst;
718 	register u_char *cp3 = (u_char *)netmask;
719 	u_char *cplim = cp2 + *cp3;
720 	u_char *cplim2 = cp2 + *cp1;
721 
722 	*cp2++ = *cp1++; *cp2++ = *cp1++; /* copies sa_len & sa_family */
723 	cp3 += 2;
724 	if (cplim > cplim2)
725 		cplim = cplim2;
726 	while (cp2 < cplim)
727 		*cp2++ = *cp1++ & *cp3++;
728 	if (cp2 < cplim2)
729 		bzero((caddr_t)cp2, (unsigned)(cplim2 - cp2));
730 }
731 
732 /*
733  * Set up a routing table entry, normally
734  * for an interface.
735  */
736 int
737 rtinit(ifa, cmd, flags)
738 	register struct ifaddr *ifa;
739 	int cmd, flags;
740 {
741 	register struct rtentry *rt;
742 	register struct sockaddr *dst;
743 	register struct sockaddr *deldst;
744 	struct mbuf *m = 0;
745 	struct rtentry *nrt = 0;
746 	int error;
747 
748 	dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr;
749 	if (cmd == RTM_DELETE) {
750 		if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) {
751 			m = m_get(M_WAIT, MT_SONAME);
752 			deldst = mtod(m, struct sockaddr *);
753 			rt_maskedcopy(dst, deldst, ifa->ifa_netmask);
754 			dst = deldst;
755 		}
756 		rt = rtalloc1(dst, 0, 0UL);
757 		if (rt) {
758 			rt->rt_refcnt--;
759 			if (rt->rt_ifa != ifa) {
760 				if (m)
761 					(void) m_free(m);
762 				return (flags & RTF_HOST ? EHOSTUNREACH
763 							: ENETUNREACH);
764 			}
765 		}
766 	}
767 	error = rtrequest(cmd, dst, ifa->ifa_addr, ifa->ifa_netmask,
768 			flags | ifa->ifa_flags, &nrt);
769 	if (m)
770 		(void) m_free(m);
771 	if (cmd == RTM_DELETE && error == 0 && (rt = nrt)) {
772 		rt_newaddrmsg(cmd, ifa, error, nrt);
773 		if (rt->rt_refcnt <= 0) {
774 			rt->rt_refcnt++;
775 			rtfree(rt);
776 		}
777 	}
778 	if (cmd == RTM_ADD && error == 0 && (rt = nrt)) {
779 		rt->rt_refcnt--;
780 		if (rt->rt_ifa != ifa) {
781 			printf("rtinit: wrong ifa (%p) was (%p)\n", ifa,
782 				rt->rt_ifa);
783 			if (rt->rt_ifa->ifa_rtrequest)
784 			    rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0));
785 			IFAFREE(rt->rt_ifa);
786 			rt->rt_ifa = ifa;
787 			rt->rt_ifp = ifa->ifa_ifp;
788 			ifa->ifa_refcnt++;
789 			if (ifa->ifa_rtrequest)
790 			    ifa->ifa_rtrequest(RTM_ADD, rt, SA(0));
791 		}
792 		rt_newaddrmsg(cmd, ifa, error, nrt);
793 	}
794 	return (error);
795 }
796