]>
git.saurik.com Git - apple/xnu.git/blob - bsd/net/route.c
ea463b5efb65d1adf0d91da93ad5380ac73da31c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (c) 1980, 1986, 1991, 1993
27 * The Regents of the University of California. All rights reserved.
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 * 3. All advertising materials mentioning features or use of this software
38 * must display the following acknowledgement:
39 * This product includes software developed by the University of
40 * California, Berkeley and its contributors.
41 * 4. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * @(#)route.c 8.2 (Berkeley) 11/15/93
58 * $FreeBSD: src/sys/net/route.c,v 1.59.2.3 2001/07/29 19:18:02 ume Exp $
61 #include <sys/param.h>
62 #include <sys/systm.h>
63 #include <sys/malloc.h>
65 #include <sys/socket.h>
66 #include <sys/domain.h>
67 #include <sys/syslog.h>
70 #include <net/route.h>
72 #include <netinet/in.h>
73 #include <netinet/ip_mroute.h>
75 #define SA(p) ((struct sockaddr *)(p))
77 struct route_cb route_cb
;
78 static struct rtstat rtstat
;
79 struct radix_node_head
*rt_tables
[AF_MAX
+1];
81 static int rttrash
; /* routes not in table but not freed */
83 static void rt_maskedcopy
__P((struct sockaddr
*,
84 struct sockaddr
*, struct sockaddr
*));
85 static void rtable_init
__P((void **));
92 for (dom
= domains
; dom
; dom
= dom
->dom_next
)
93 if (dom
->dom_rtattach
)
94 dom
->dom_rtattach(&table
[dom
->dom_family
],
101 rn_init(); /* initialize all zeroes, all ones, mask table */
102 rtable_init((void **)rt_tables
);
106 * Packet routing routines.
110 register struct route
*ro
;
112 rtalloc_ign(ro
, 0UL);
116 rtalloc_ign(ro
, ignore
)
117 register struct route
*ro
;
123 if ((rt
= ro
->ro_rt
) != NULL
) {
124 if (rt
->rt_ifp
!= NULL
&& rt
->rt_flags
& RTF_UP
)
126 /* XXX - We are probably always at splnet here already. */
132 ro
->ro_rt
= rtalloc1(&ro
->ro_dst
, 1, ignore
);
136 * Look up the route that matches the address given
137 * Or, at least try.. Create a cloned route if needed.
140 rtalloc1(dst
, report
, ignflags
)
141 register struct sockaddr
*dst
;
145 register struct radix_node_head
*rnh
= rt_tables
[dst
->sa_family
];
146 register struct rtentry
*rt
;
147 register struct radix_node
*rn
;
148 struct rtentry
*newrt
= 0;
149 struct rt_addrinfo info
;
151 int s
= splnet(), err
= 0, msgtype
= RTM_MISS
;
154 * Look up the address in the table for that Address Family
156 if (rnh
&& (rn
= rnh
->rnh_matchaddr((caddr_t
)dst
, rnh
)) &&
157 ((rn
->rn_flags
& RNF_ROOT
) == 0)) {
159 * If we find it and it's not the root node, then
160 * get a refernce on the rtentry associated.
162 newrt
= rt
= (struct rtentry
*)rn
;
163 nflags
= rt
->rt_flags
& ~ignflags
;
164 if (report
&& (nflags
& (RTF_CLONING
| RTF_PRCLONING
))) {
166 * We are apparently adding (report = 0 in delete).
167 * If it requires that it be cloned, do so.
168 * (This implies it wasn't a HOST route.)
170 err
= rtrequest(RTM_RESOLVE
, dst
, SA(0),
174 * If the cloning didn't succeed, maybe
175 * what we have will do. Return that.
181 if ((rt
= newrt
) && (rt
->rt_flags
& RTF_XRESOLVE
)) {
183 * If the new route specifies it be
184 * externally resolved, then go do that.
186 msgtype
= RTM_RESOLVE
;
193 * Either we hit the root or couldn't find any match,
194 * Which basically means
195 * "caint get there frm here"
197 rtstat
.rts_unreach
++;
200 * If required, report the failure to the supervising
202 * For a delete, this is not an error. (report == 0)
204 bzero((caddr_t
)&info
, sizeof(info
));
205 info
.rti_info
[RTAX_DST
] = dst
;
206 rt_missmsg(msgtype
, &info
, 0, err
);
214 * Remove a reference count from an rtentry.
215 * If the count gets low enough, take it out of the routing table
219 register struct rtentry
*rt
;
222 * find the tree for that address family
224 register struct radix_node_head
*rnh
=
225 rt_tables
[rt_key(rt
)->sa_family
];
227 if (rt
== 0 || rnh
== 0)
231 * decrement the reference count by one and if it reaches 0,
232 * and there is a close function defined, call the close function
235 if(rnh
->rnh_close
&& rt
->rt_refcnt
== 0) {
236 rnh
->rnh_close((struct radix_node
*)rt
, rnh
);
240 * If we are no longer "up" (and ref == 0)
241 * then we can free the resources associated
244 if (rt
->rt_refcnt
<= 0 && (rt
->rt_flags
& RTF_UP
) == 0) {
245 if (rt
->rt_nodes
->rn_flags
& (RNF_ACTIVE
| RNF_ROOT
))
248 * the rtentry must have been removed from the routing table
249 * so it is represented in rttrash.. remove that now.
254 if (rt
->rt_refcnt
< 0) {
255 printf("rtfree: %p not freed (neg refs)\n", rt
);
261 * release references on items we hold them on..
262 * e.g other routes and ifaddrs.
265 rtfree(rt
->rt_parent
);
267 if(rt
->rt_ifa
&& !(rt
->rt_parent
&& rt
->rt_parent
->rt_ifa
== rt
->rt_ifa
)) {
269 * Only release the ifa if our parent doesn't hold it for us.
270 * The parent route is responsible for holding a reference
271 * to the ifa for us. Ifa refcounts are 16bit, if every
272 * cloned route held a reference, the 16bit refcount may
273 * rollover, making a mess :(
275 * FreeBSD solved this by making the ifa_refcount 32bits, but
276 * we can't do that since it changes the size of the ifaddr struct.
282 * The key is separatly alloc'd so free it (see rt_setgate()).
283 * This also frees the gateway, as they are always malloc'd
289 * and the rtentry itself of course
296 * Decrements the refcount but does not free the route when
297 * the refcount reaches zero. Unless you have really good reason,
298 * use rtfree not rtunref.
301 rtunref(struct rtentry
* rt
)
307 if (rt
->rt_refcnt
<= 0 && (rt
->rt_flags
& RTF_UP
) == 0)
308 printf("rtunref - if rtfree were called, we would have freed route\n");
313 * Add a reference count from an rtentry.
316 rtref(struct rtentry
* rt
)
325 rtsetifa(struct rtentry
*rt
, struct ifaddr
* ifa
)
330 if (rt
->rt_ifa
== ifa
)
333 /* Release the old ifa if it isn't our parent route's ifa */
334 if (rt
->rt_ifa
&& !(rt
->rt_parent
&& rt
->rt_parent
->rt_ifa
== rt
->rt_ifa
))
340 /* Take a reference to the ifa if it isn't our parent route's ifa */
341 if (rt
->rt_ifa
&& !(rt
->rt_parent
&& rt
->rt_parent
->rt_ifa
== ifa
))
347 register struct ifaddr
*ifa
;
351 if (ifa
->ifa_refcnt
== 0) {
353 /* Detect case where an ifa is being freed before it should */
355 /* Verify this ifa isn't attached to an interface */
356 for (ifp
= ifnet
.tqh_first
; ifp
; ifp
= ifp
->if_link
.tqe_next
) {
357 struct ifaddr
*ifaInUse
;
358 for (ifaInUse
= ifp
->if_addrhead
.tqh_first
; ifaInUse
; ifaInUse
= ifaInUse
->ifa_link
.tqe_next
) {
359 if (ifa
== ifaInUse
) {
361 * This is an ugly hack done because we can't move to a 32 bit
362 * refcnt like bsd has. We have to maintain binary compatibility
363 * in our kernel, unlike FreeBSD.
365 log(LOG_ERR
, "ifa attached to ifp is being freed, leaking insted\n");
379 ifaref(struct ifaddr
*ifa
)
388 * Force a routing table entry to the specified
389 * destination to go through the given gateway.
390 * Normally called as a result of a routing redirect
391 * message from the network layer.
393 * N.B.: must be called at splnet
397 rtredirect(dst
, gateway
, netmask
, flags
, src
, rtp
)
398 struct sockaddr
*dst
, *gateway
, *netmask
, *src
;
400 struct rtentry
**rtp
;
402 register struct rtentry
*rt
;
405 struct rt_addrinfo info
;
408 /* verify the gateway is directly reachable */
409 if ((ifa
= ifa_ifwithnet(gateway
)) == 0) {
413 rt
= rtalloc1(dst
, 0, 0UL);
415 * If the redirect isn't from our current router for this dst,
416 * it's either old or wrong. If it redirects us to ourselves,
417 * we have a routing loop, perhaps as a result of an interface
418 * going down recently.
420 #define equal(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0)
421 if (!(flags
& RTF_DONE
) && rt
&&
422 (!equal(src
, rt
->rt_gateway
) || rt
->rt_ifa
!= ifa
))
424 else if (ifa_ifwithaddr(gateway
))
425 error
= EHOSTUNREACH
;
429 * Create a new entry if we just got back a wildcard entry
430 * or the the lookup failed. This is necessary for hosts
431 * which use routing redirects generated by smart gateways
432 * to dynamically build the routing tables.
434 if ((rt
== 0) || (rt_mask(rt
) && rt_mask(rt
)->sa_len
< 2))
437 * Don't listen to the redirect if it's
438 * for a route to an interface.
440 if (rt
->rt_flags
& RTF_GATEWAY
) {
441 if (((rt
->rt_flags
& RTF_HOST
) == 0) && (flags
& RTF_HOST
)) {
443 * Changing from route to net => route to host.
444 * Create new route, rather than smashing route to net.
447 flags
|= RTF_GATEWAY
| RTF_DYNAMIC
;
448 error
= rtrequest((int)RTM_ADD
, dst
, gateway
,
450 (struct rtentry
**)0);
451 stat
= &rtstat
.rts_dynamic
;
454 * Smash the current notion of the gateway to
455 * this destination. Should check about netmask!!!
457 rt
->rt_flags
|= RTF_MODIFIED
;
458 flags
|= RTF_MODIFIED
;
459 stat
= &rtstat
.rts_newgateway
;
461 * add the key and gateway (in one malloc'd chunk).
463 rt_setgate(rt
, rt_key(rt
), gateway
);
466 error
= EHOSTUNREACH
;
476 rtstat
.rts_badredirect
++;
477 else if (stat
!= NULL
)
479 bzero((caddr_t
)&info
, sizeof(info
));
480 info
.rti_info
[RTAX_DST
] = dst
;
481 info
.rti_info
[RTAX_GATEWAY
] = gateway
;
482 info
.rti_info
[RTAX_NETMASK
] = netmask
;
483 info
.rti_info
[RTAX_AUTHOR
] = src
;
484 rt_missmsg(RTM_REDIRECT
, &info
, flags
, error
);
488 * Routing table ioctl interface.
491 rtioctl(req
, data
, p
)
497 /* Multicast goop, grrr... */
499 return mrt_ioctl(req
, data
);
501 return mrt_ioctl(req
, data
, p
);
509 ifa_ifwithroute(flags
, dst
, gateway
)
511 struct sockaddr
*dst
, *gateway
;
513 register struct ifaddr
*ifa
;
514 if ((flags
& RTF_GATEWAY
) == 0) {
516 * If we are adding a route to an interface,
517 * and the interface is a pt to pt link
518 * we should search for the destination
519 * as our clue to the interface. Otherwise
520 * we can use the local address.
523 if (flags
& RTF_HOST
) {
524 ifa
= ifa_ifwithdstaddr(dst
);
527 ifa
= ifa_ifwithaddr(gateway
);
530 * If we are adding a route to a remote net
531 * or host, the gateway may still be on the
532 * other end of a pt to pt link.
534 ifa
= ifa_ifwithdstaddr(gateway
);
537 ifa
= ifa_ifwithnet(gateway
);
539 struct rtentry
*rt
= rtalloc1(dst
, 0, 0UL);
543 if ((ifa
= rt
->rt_ifa
) == 0)
546 if (ifa
->ifa_addr
->sa_family
!= dst
->sa_family
) {
547 struct ifaddr
*oifa
= ifa
;
548 ifa
= ifaof_ifpforaddr(dst
, ifa
->ifa_ifp
);
555 #define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
557 static int rt_fixdelete
__P((struct radix_node
*, void *));
558 static int rt_fixchange
__P((struct radix_node
*, void *));
562 struct radix_node_head
*rnh
;
566 * Do appropriate manipulations of a routing tree given
567 * all the bits of info needed
570 rtrequest(req
, dst
, gateway
, netmask
, flags
, ret_nrt
)
572 struct sockaddr
*dst
, *gateway
, *netmask
;
573 struct rtentry
**ret_nrt
;
575 int s
= splnet(); int error
= 0;
576 register struct rtentry
*rt
;
577 register struct radix_node
*rn
;
578 register struct radix_node_head
*rnh
;
580 struct sockaddr
*ndst
;
581 #define senderr(x) { error = x ; goto bad; }
584 * Find the correct routing tree to use for this Address Family
586 if ((rnh
= rt_tables
[dst
->sa_family
]) == 0)
589 * If we are adding a host route then we don't want to put
590 * a netmask in the tree
592 if (flags
& RTF_HOST
)
597 * Remove the item from the tree and return it.
598 * Complain if it is not there and do no more processing.
600 if ((rn
= rnh
->rnh_deladdr(dst
, netmask
, rnh
)) == 0)
602 if (rn
->rn_flags
& (RNF_ACTIVE
| RNF_ROOT
))
603 panic ("rtrequest delete");
604 rt
= (struct rtentry
*)rn
;
607 * Now search what's left of the subtree for any cloned
608 * routes which might have been formed from this node.
610 if ((rt
->rt_flags
& (RTF_CLONING
| RTF_PRCLONING
)) &&
612 rnh
->rnh_walktree_from(rnh
, dst
, rt_mask(rt
),
617 * Remove any external references we may have.
618 * This might result in another rtentry being freed if
619 * we held its last reference.
621 if (rt
->rt_gwroute
) {
624 (rt
= (struct rtentry
*)rn
)->rt_gwroute
= 0;
628 * NB: RTF_UP must be set during the search above,
629 * because we might delete the last ref, causing
630 * rt to get freed prematurely.
631 * eh? then why not just add a reference?
632 * I'm not sure how RTF_UP helps matters. (JRE)
634 rt
->rt_flags
&= ~RTF_UP
;
637 * give the protocol a chance to keep things in sync.
639 if ((ifa
= rt
->rt_ifa
) && ifa
->ifa_rtrequest
)
640 ifa
->ifa_rtrequest(RTM_DELETE
, rt
, SA(0));
643 * one more rtentry floating around that is not
644 * linked to the routing table.
649 * If the caller wants it, then it can have it,
650 * but it's up to it to free the rtentry as we won't be
655 else if (rt
->rt_refcnt
<= 0) {
656 rt
->rt_refcnt
++; /* make a 1->0 transition */
662 if (ret_nrt
== 0 || (rt
= *ret_nrt
) == 0)
665 flags
= rt
->rt_flags
&
666 ~(RTF_CLONING
| RTF_PRCLONING
| RTF_STATIC
);
667 flags
|= RTF_WASCLONED
;
668 gateway
= rt
->rt_gateway
;
669 if ((netmask
= rt
->rt_genmask
) == 0)
674 if ((flags
& RTF_GATEWAY
) && !gateway
)
675 panic("rtrequest: GATEWAY but no gateway");
677 if ((ifa
= ifa_ifwithroute(flags
, dst
, gateway
)) == 0)
678 senderr(ENETUNREACH
);
681 R_Malloc(rt
, struct rtentry
*, sizeof(*rt
));
684 Bzero(rt
, sizeof(*rt
));
685 rt
->rt_flags
= RTF_UP
| flags
;
687 * Add the gateway. Possibly re-malloc-ing the storage for it
688 * also add the rt_gwroute if possible.
690 if ((error
= rt_setgate(rt
, dst
, gateway
)) != 0) {
696 * point to the (possibly newly malloc'd) dest address.
701 * make sure it contains the value we want (masked if needed).
704 rt_maskedcopy(dst
, ndst
, netmask
);
706 Bcopy(dst
, ndst
, dst
->sa_len
);
709 * Note that we now have a reference to the ifa.
710 * This moved from below so that rnh->rnh_addaddr() can
711 * examine the ifa and ifa->ifa_ifp if it so desires.
714 * Note that we do not use rtsetifa here because
715 * rt_parent has not been setup yet.
719 rt
->rt_ifp
= ifa
->ifa_ifp
;
721 rt
->rt_dlt
= ifa
->ifa_dlt
; /* dl_tag */
723 /* XXX mtu manipulation will be done in rnh_addaddr -- itojun */
725 rn
= rnh
->rnh_addaddr((caddr_t
)ndst
, (caddr_t
)netmask
,
730 * Uh-oh, we already have one of these in the tree.
731 * We do a special hack: if the route that's already
732 * there was generated by the protocol-cloning
733 * mechanism, then we just blow it away and retry
734 * the insertion of the new one.
736 rt2
= rtalloc1(dst
, 0, RTF_PRCLONING
);
737 if (rt2
&& rt2
->rt_parent
) {
738 rtrequest(RTM_DELETE
,
739 (struct sockaddr
*)rt_key(rt2
),
741 rt_mask(rt2
), rt2
->rt_flags
, 0);
743 rn
= rnh
->rnh_addaddr((caddr_t
)ndst
,
747 /* undo the extra ref we got */
753 * If it still failed to go into the tree,
754 * then un-make it (this should be a function)
758 rtfree(rt
->rt_gwroute
);
770 * If we got here from RESOLVE, then we are cloning
771 * so clone the rest, and note that we
772 * are a clone (and increment the parent's references)
774 if (req
== RTM_RESOLVE
) {
775 rt
->rt_rmx
= (*ret_nrt
)->rt_rmx
; /* copy metrics */
776 if ((*ret_nrt
)->rt_flags
& (RTF_CLONING
| RTF_PRCLONING
)) {
777 rt
->rt_parent
= (*ret_nrt
);
781 * If our parent is holding a reference to the same ifa,
782 * free our reference and rely on the parent holding it.
784 if (rt
->rt_parent
&& rt
->rt_parent
->rt_ifa
== rt
->rt_ifa
)
790 * if this protocol has something to add to this then
791 * allow it to do that as well.
793 if (ifa
->ifa_rtrequest
)
794 ifa
->ifa_rtrequest(req
, rt
, SA(ret_nrt
? *ret_nrt
: 0));
797 * We repeat the same procedure from rt_setgate() here because
798 * it doesn't fire when we call it there because the node
799 * hasn't been added to the tree yet.
801 if (!(rt
->rt_flags
& RTF_HOST
) && rt_mask(rt
) != 0) {
805 rnh
->rnh_walktree_from(rnh
, rt_key(rt
), rt_mask(rt
),
810 * actually return a resultant rtentry and
811 * give the caller a single reference.
825 * Called from rtrequest(RTM_DELETE, ...) to fix up the route's ``family''
826 * (i.e., the routes related to it by the operation of cloning). This
827 * routine is iterated over all potential former-child-routes by way of
828 * rnh->rnh_walktree_from() above, and those that actually are children of
829 * the late parent (passed in as VP here) are themselves deleted.
833 struct radix_node
*rn
;
836 struct rtentry
*rt
= (struct rtentry
*)rn
;
837 struct rtentry
*rt0
= vp
;
839 if (rt
->rt_parent
== rt0
&& !(rt
->rt_flags
& RTF_PINNED
)) {
840 return rtrequest(RTM_DELETE
, rt_key(rt
),
841 (struct sockaddr
*)0, rt_mask(rt
),
842 rt
->rt_flags
, (struct rtentry
**)0);
848 * This routine is called from rt_setgate() to do the analogous thing for
849 * adds and changes. There is the added complication in this case of a
850 * middle insert; i.e., insertion of a new network route between an older
851 * network route and (cloned) host routes. For this reason, a simple check
852 * of rt->rt_parent is insufficient; each candidate route must be tested
853 * against the (mask, value) of the new route (passed as before in vp)
854 * to see if the new route matches it.
856 * XXX - it may be possible to do fixdelete() for changes and reserve this
857 * routine just for adds. I'm not sure why I thought it was necessary to do
861 static int rtfcdebug
= 0;
866 struct radix_node
*rn
;
869 struct rtentry
*rt
= (struct rtentry
*)rn
;
870 struct rtfc_arg
*ap
= vp
;
871 struct rtentry
*rt0
= ap
->rt0
;
872 struct radix_node_head
*rnh
= ap
->rnh
;
873 u_char
*xk1
, *xm1
, *xk2
, *xmp
;
878 printf("rt_fixchange: rt %p, rt0 %p\n", rt
, rt0
);
881 if (!rt
->rt_parent
|| (rt
->rt_flags
& RTF_PINNED
)) {
883 if(rtfcdebug
) printf("no parent or pinned\n");
888 if (rt
->rt_parent
== rt0
) {
890 if(rtfcdebug
) printf("parent match\n");
892 return rtrequest(RTM_DELETE
, rt_key(rt
),
893 (struct sockaddr
*)0, rt_mask(rt
),
894 rt
->rt_flags
, (struct rtentry
**)0);
898 * There probably is a function somewhere which does this...
899 * if not, there should be.
901 len
= imin(((struct sockaddr
*)rt_key(rt0
))->sa_len
,
902 ((struct sockaddr
*)rt_key(rt
))->sa_len
);
904 xk1
= (u_char
*)rt_key(rt0
);
905 xm1
= (u_char
*)rt_mask(rt0
);
906 xk2
= (u_char
*)rt_key(rt
);
908 /* avoid applying a less specific route */
909 xmp
= (u_char
*)rt_mask(rt
->rt_parent
);
910 mlen
= ((struct sockaddr
*)rt_key(rt
->rt_parent
))->sa_len
;
911 if (mlen
> ((struct sockaddr
*)rt_key(rt0
))->sa_len
) {
914 printf("rt_fixchange: inserting a less "
919 for (i
= rnh
->rnh_treetop
->rn_offset
; i
< mlen
; i
++) {
920 if ((xmp
[i
] & ~(xmp
[i
] ^ xm1
[i
])) != xmp
[i
]) {
923 printf("rt_fixchange: inserting a less "
930 for (i
= rnh
->rnh_treetop
->rn_offset
; i
< len
; i
++) {
931 if ((xk2
[i
] & xm1
[i
]) != xk1
[i
]) {
933 if(rtfcdebug
) printf("no match\n");
940 * OK, this node is a clone, and matches the node currently being
941 * changed/added under the node's mask. So, get rid of it.
944 if(rtfcdebug
) printf("deleting\n");
946 return rtrequest(RTM_DELETE
, rt_key(rt
), (struct sockaddr
*)0,
947 rt_mask(rt
), rt
->rt_flags
, (struct rtentry
**)0);
951 rt_setgate(rt0
, dst
, gate
)
953 struct sockaddr
*dst
, *gate
;
956 int dlen
= ROUNDUP(dst
->sa_len
), glen
= ROUNDUP(gate
->sa_len
);
957 register struct rtentry
*rt
= rt0
;
958 struct radix_node_head
*rnh
= rt_tables
[dst
->sa_family
];
961 * A host route with the destination equal to the gateway
962 * will interfere with keeping LLINFO in the routing
963 * table, so disallow it.
965 if (((rt0
->rt_flags
& (RTF_HOST
|RTF_GATEWAY
|RTF_LLINFO
)) ==
966 (RTF_HOST
|RTF_GATEWAY
)) &&
967 (dst
->sa_len
== gate
->sa_len
) &&
968 (bcmp(dst
, gate
, dst
->sa_len
) == 0)) {
970 * The route might already exist if this is an RTM_CHANGE
971 * or a routing redirect, so try to delete it.
974 rtrequest(RTM_DELETE
, (struct sockaddr
*)rt_key(rt0
),
975 rt0
->rt_gateway
, rt_mask(rt0
), rt0
->rt_flags
, 0);
976 return EADDRNOTAVAIL
;
980 * Both dst and gateway are stored in the same malloc'd chunk
981 * (If I ever get my hands on....)
982 * if we need to malloc a new chunk, then keep the old one around
983 * till we don't need it any more.
985 if (rt
->rt_gateway
== 0 || glen
> ROUNDUP(rt
->rt_gateway
->sa_len
)) {
986 old
= (caddr_t
)rt_key(rt
);
987 R_Malloc(new, caddr_t
, dlen
+ glen
);
990 rt
->rt_nodes
->rn_key
= new;
993 * otherwise just overwrite the old one
995 new = rt
->rt_nodes
->rn_key
;
1000 * copy the new gateway value into the memory chunk
1002 Bcopy(gate
, (rt
->rt_gateway
= (struct sockaddr
*)(new + dlen
)), glen
);
1005 * if we are replacing the chunk (or it's new) we need to
1006 * replace the dst as well
1009 Bcopy(dst
, new, dlen
);
1014 * If there is already a gwroute, it's now almost definitly wrong
1017 if (rt
->rt_gwroute
) {
1018 rt
= rt
->rt_gwroute
; rtfree(rt
);
1019 rt
= rt0
; rt
->rt_gwroute
= 0;
1022 * Cloning loop avoidance:
1023 * In the presence of protocol-cloning and bad configuration,
1024 * it is possible to get stuck in bottomless mutual recursion
1025 * (rtrequest rt_setgate rtalloc1). We avoid this by not allowing
1026 * protocol-cloning to operate for gateways (which is probably the
1027 * correct choice anyway), and avoid the resulting reference loops
1028 * by disallowing any route to run through itself as a gateway.
1029 * This is obviously mandatory when we get rt->rt_output().
1031 if (rt
->rt_flags
& RTF_GATEWAY
) {
1032 rt
->rt_gwroute
= rtalloc1(gate
, 1, RTF_PRCLONING
);
1033 if (rt
->rt_gwroute
== rt
) {
1034 rtfree(rt
->rt_gwroute
);
1036 return EDQUOT
; /* failure */
1041 * This isn't going to do anything useful for host routes, so
1042 * don't bother. Also make sure we have a reasonable mask
1043 * (we don't yet have one during adds).
1045 if (!(rt
->rt_flags
& RTF_HOST
) && rt_mask(rt
) != 0) {
1046 struct rtfc_arg arg
;
1049 rnh
->rnh_walktree_from(rnh
, rt_key(rt
), rt_mask(rt
),
1050 rt_fixchange
, &arg
);
1057 rt_maskedcopy(src
, dst
, netmask
)
1058 struct sockaddr
*src
, *dst
, *netmask
;
1060 register u_char
*cp1
= (u_char
*)src
;
1061 register u_char
*cp2
= (u_char
*)dst
;
1062 register u_char
*cp3
= (u_char
*)netmask
;
1063 u_char
*cplim
= cp2
+ *cp3
;
1064 u_char
*cplim2
= cp2
+ *cp1
;
1066 *cp2
++ = *cp1
++; *cp2
++ = *cp1
++; /* copies sa_len & sa_family */
1071 *cp2
++ = *cp1
++ & *cp3
++;
1073 bzero((caddr_t
)cp2
, (unsigned)(cplim2
- cp2
));
1077 * Set up a routing table entry, normally
1081 rtinit(ifa
, cmd
, flags
)
1082 register struct ifaddr
*ifa
;
1085 register struct rtentry
*rt
;
1086 register struct sockaddr
*dst
;
1087 register struct sockaddr
*deldst
;
1089 struct rtentry
*nrt
= 0;
1092 dst
= flags
& RTF_HOST
? ifa
->ifa_dstaddr
: ifa
->ifa_addr
;
1094 * If it's a delete, check that if it exists, it's on the correct
1095 * interface or we might scrub a route to another ifa which would
1096 * be confusing at best and possibly worse.
1098 if (cmd
== RTM_DELETE
) {
1100 * It's a delete, so it should already exist..
1101 * If it's a net, mask off the host bits
1102 * (Assuming we have a mask)
1104 if ((flags
& RTF_HOST
) == 0 && ifa
->ifa_netmask
) {
1105 m
= m_get(M_DONTWAIT
, MT_SONAME
);
1108 deldst
= mtod(m
, struct sockaddr
*);
1109 rt_maskedcopy(dst
, deldst
, ifa
->ifa_netmask
);
1113 * Get an rtentry that is in the routing tree and
1114 * contains the correct info. (if this fails, can't get there).
1115 * We set "report" to FALSE so that if it doesn't exist,
1116 * it doesn't report an error or clone a route, etc. etc.
1118 rt
= rtalloc1(dst
, 0, 0UL);
1121 * Ok so we found the rtentry. it has an extra reference
1122 * for us at this stage. we won't need that so
1126 if (rt
->rt_ifa
!= ifa
) {
1128 * If the interface in the rtentry doesn't match
1129 * the interface we are using, then we don't
1130 * want to delete it, so return an error.
1131 * This seems to be the only point of
1132 * this whole RTM_DELETE clause.
1136 return (flags
& RTF_HOST
? EHOSTUNREACH
1144 * One would think that as we are deleting, and we know
1145 * it doesn't exist, we could just return at this point
1146 * with an "ELSE" clause, but apparently not..
1148 return (flags
& RTF_HOST
? EHOSTUNREACH
1154 * Do the actual request
1156 error
= rtrequest(cmd
, dst
, ifa
->ifa_addr
, ifa
->ifa_netmask
,
1157 flags
| ifa
->ifa_flags
, &nrt
);
1161 * If we are deleting, and we found an entry, then
1162 * it's been removed from the tree.. now throw it away.
1164 if (cmd
== RTM_DELETE
&& error
== 0 && (rt
= nrt
)) {
1166 * notify any listenning routing agents of the change
1168 rt_newaddrmsg(cmd
, ifa
, error
, nrt
);
1169 if (rt
->rt_refcnt
<= 0) {
1170 rt
->rt_refcnt
++; /* need a 1->0 transition to free */
1176 * We are adding, and we have a returned routing entry.
1177 * We need to sanity check the result.
1179 if (cmd
== RTM_ADD
&& error
== 0 && (rt
= nrt
)) {
1181 * We just wanted to add it.. we don't actually need a reference
1185 * If it came back with an unexpected interface, then it must
1186 * have already existed or something. (XXX)
1188 if (rt
->rt_ifa
!= ifa
) {
1189 if (!(rt
->rt_ifa
->ifa_ifp
->if_flags
&
1190 (IFF_POINTOPOINT
|IFF_LOOPBACK
)))
1191 printf("rtinit: wrong ifa (%p) was (%p)\n",
1194 * Ask that the protocol in question
1195 * remove anything it has associated with
1196 * this route and ifaddr.
1198 if (rt
->rt_ifa
->ifa_rtrequest
)
1199 rt
->rt_ifa
->ifa_rtrequest(RTM_DELETE
, rt
, SA(0));
1201 * Set the route's ifa.
1205 * And substitute in references to the ifaddr
1208 rt
->rt_ifp
= ifa
->ifa_ifp
;
1210 rt
->rt_dlt
= ifa
->ifa_dlt
; /* dl_tag */
1212 rt
->rt_rmx
.rmx_mtu
= ifa
->ifa_ifp
->if_mtu
; /*XXX*/
1214 * Now ask the protocol to check if it needs
1215 * any special processing in its new form.
1217 if (ifa
->ifa_rtrequest
)
1218 ifa
->ifa_rtrequest(RTM_ADD
, rt
, SA(0));
1221 * notify any listenning routing agents of the change
1223 rt_newaddrmsg(cmd
, ifa
, error
, nrt
);