Deleted Added
full compact
route.c (85052) route.c (85074)
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

--- 17 unchanged lines hidden (view full) ---

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.3 (Berkeley) 1/9/95
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

--- 17 unchanged lines hidden (view full) ---

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.3 (Berkeley) 1/9/95
34 * $FreeBSD: head/sys/net/route.c 85052 2001-10-17 11:10:55Z ru $
34 * $FreeBSD: head/sys/net/route.c 85074 2001-10-17 18:07:05Z ru $
35 */
36
37#include "opt_inet.h"
38#include "opt_mrouting.h"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/malloc.h>

--- 117 unchanged lines hidden (view full) ---

160 if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) {
161 /*
162 * If the new route specifies it be
163 * externally resolved, then go do that.
164 */
165 msgtype = RTM_RESOLVE;
166 goto miss;
167 }
35 */
36
37#include "opt_inet.h"
38#include "opt_mrouting.h"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/malloc.h>

--- 117 unchanged lines hidden (view full) ---

160 if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) {
161 /*
162 * If the new route specifies it be
163 * externally resolved, then go do that.
164 */
165 msgtype = RTM_RESOLVE;
166 goto miss;
167 }
168 /* Inform listeners of the new route. */
169 bzero(&info, sizeof(info));
170 info.rti_info[RTAX_DST] = rt_key(rt);
171 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
172 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
173 if (rt->rt_ifp != NULL) {
174 info.rti_info[RTAX_IFP] =
175 TAILQ_FIRST(&rt->rt_ifp->if_addrhead)->ifa_addr;
176 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
177 }
178 rt_missmsg(RTM_ADD, &info, rt->rt_flags, 0);
168 } else
169 rt->rt_refcnt++;
170 } else {
171 /*
172 * Either we hit the root or couldn't find any match,
173 * Which basically means
174 * "caint get there frm here"
175 */

--- 107 unchanged lines hidden (view full) ---

283 *
284 */
285void
286rtredirect(dst, gateway, netmask, flags, src, rtp)
287 struct sockaddr *dst, *gateway, *netmask, *src;
288 int flags;
289 struct rtentry **rtp;
290{
179 } else
180 rt->rt_refcnt++;
181 } else {
182 /*
183 * Either we hit the root or couldn't find any match,
184 * Which basically means
185 * "caint get there frm here"
186 */

--- 107 unchanged lines hidden (view full) ---

294 *
295 */
296void
297rtredirect(dst, gateway, netmask, flags, src, rtp)
298 struct sockaddr *dst, *gateway, *netmask, *src;
299 int flags;
300 struct rtentry **rtp;
301{
291 register struct rtentry *rt;
302 struct rtentry *rt;
292 int error = 0;
293 short *stat = 0;
294 struct rt_addrinfo info;
295 struct ifaddr *ifa;
296
297 /* verify the gateway is directly reachable */
298 if ((ifa = ifa_ifwithnet(gateway)) == 0) {
299 error = ENETUNREACH;

--- 28 unchanged lines hidden (view full) ---

328 */
329 if (rt->rt_flags & RTF_GATEWAY) {
330 if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) {
331 /*
332 * Changing from route to net => route to host.
333 * Create new route, rather than smashing route to net.
334 */
335 create:
303 int error = 0;
304 short *stat = 0;
305 struct rt_addrinfo info;
306 struct ifaddr *ifa;
307
308 /* verify the gateway is directly reachable */
309 if ((ifa = ifa_ifwithnet(gateway)) == 0) {
310 error = ENETUNREACH;

--- 28 unchanged lines hidden (view full) ---

339 */
340 if (rt->rt_flags & RTF_GATEWAY) {
341 if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) {
342 /*
343 * Changing from route to net => route to host.
344 * Create new route, rather than smashing route to net.
345 */
346 create:
347 if (rt)
348 rtfree(rt);
336 flags |= RTF_GATEWAY | RTF_DYNAMIC;
349 flags |= RTF_GATEWAY | RTF_DYNAMIC;
337 error = rtrequest((int)RTM_ADD, dst, gateway,
338 netmask, flags,
339 (struct rtentry **)0);
350 bzero((caddr_t)&info, sizeof(info));
351 info.rti_info[RTAX_DST] = dst;
352 info.rti_info[RTAX_GATEWAY] = gateway;
353 info.rti_info[RTAX_NETMASK] = netmask;
354 info.rti_ifa = ifa;
355 info.rti_flags = flags;
356 rt = NULL;
357 error = rtrequest1(RTM_ADD, &info, &rt);
358 if (rt != NULL)
359 flags = rt->rt_flags;
340 stat = &rtstat.rts_dynamic;
341 } else {
342 /*
343 * Smash the current notion of the gateway to
344 * this destination. Should check about netmask!!!
345 */
346 rt->rt_flags |= RTF_MODIFIED;
347 flags |= RTF_MODIFIED;

--- 83 unchanged lines hidden (view full) ---

431 struct ifaddr *oifa = ifa;
432 ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp);
433 if (ifa == 0)
434 ifa = oifa;
435 }
436 return (ifa);
437}
438
360 stat = &rtstat.rts_dynamic;
361 } else {
362 /*
363 * Smash the current notion of the gateway to
364 * this destination. Should check about netmask!!!
365 */
366 rt->rt_flags |= RTF_MODIFIED;
367 flags |= RTF_MODIFIED;

--- 83 unchanged lines hidden (view full) ---

451 struct ifaddr *oifa = ifa;
452 ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp);
453 if (ifa == 0)
454 ifa = oifa;
455 }
456 return (ifa);
457}
458
439#define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
440
441static int rt_fixdelete __P((struct radix_node *, void *));
442static int rt_fixchange __P((struct radix_node *, void *));
443
444struct rtfc_arg {
445 struct rtentry *rt0;
446 struct radix_node_head *rnh;
447};
448
449/*
450 * Do appropriate manipulations of a routing tree given
451 * all the bits of info needed
452 */
453int
454rtrequest(req, dst, gateway, netmask, flags, ret_nrt)
455 int req, flags;
456 struct sockaddr *dst, *gateway, *netmask;
457 struct rtentry **ret_nrt;
458{
459static int rt_fixdelete __P((struct radix_node *, void *));
460static int rt_fixchange __P((struct radix_node *, void *));
461
462struct rtfc_arg {
463 struct rtentry *rt0;
464 struct radix_node_head *rnh;
465};
466
467/*
468 * Do appropriate manipulations of a routing tree given
469 * all the bits of info needed
470 */
471int
472rtrequest(req, dst, gateway, netmask, flags, ret_nrt)
473 int req, flags;
474 struct sockaddr *dst, *gateway, *netmask;
475 struct rtentry **ret_nrt;
476{
477 struct rt_addrinfo info;
478
479 bzero((caddr_t)&info, sizeof(info));
480 info.rti_flags = flags;
481 info.rti_info[RTAX_DST] = dst;
482 info.rti_info[RTAX_GATEWAY] = gateway;
483 info.rti_info[RTAX_NETMASK] = netmask;
484 return rtrequest1(req, &info, ret_nrt);
485}
486
487/*
488 * These (questionable) definitions of apparent local variables apply
489 * to the next two functions. XXXXXX!!!
490 */
491#define dst info->rti_info[RTAX_DST]
492#define gateway info->rti_info[RTAX_GATEWAY]
493#define netmask info->rti_info[RTAX_NETMASK]
494#define ifaaddr info->rti_info[RTAX_IFA]
495#define ifpaddr info->rti_info[RTAX_IFP]
496#define flags info->rti_flags
497
498int
499rt_getifa(info)
500 struct rt_addrinfo *info;
501{
502 struct ifaddr *ifa;
503 int error = 0;
504
505 /*
506 * ifp may be specified by sockaddr_dl
507 * when protocol address is ambiguous.
508 */
509 if (info->rti_ifp == NULL && ifpaddr != NULL &&
510 ifpaddr->sa_family == AF_LINK &&
511 (ifa = ifa_ifwithnet(ifpaddr)) != NULL)
512 info->rti_ifp = ifa->ifa_ifp;
513 if (info->rti_ifa == NULL && ifaaddr != NULL)
514 info->rti_ifa = ifa_ifwithaddr(ifaaddr);
515 if (info->rti_ifa == NULL) {
516 struct sockaddr *sa;
517
518 sa = ifaaddr != NULL ? ifaaddr :
519 (gateway != NULL ? gateway : dst);
520 if (sa != NULL && info->rti_ifp != NULL)
521 info->rti_ifa = ifaof_ifpforaddr(sa, info->rti_ifp);
522 else if (dst != NULL && gateway != NULL)
523 info->rti_ifa = ifa_ifwithroute(flags, dst, gateway);
524 else if (sa != NULL)
525 info->rti_ifa = ifa_ifwithroute(flags, sa, sa);
526 }
527 if ((ifa = info->rti_ifa) != NULL) {
528 if (info->rti_ifp == NULL)
529 info->rti_ifp = ifa->ifa_ifp;
530 } else
531 error = ENETUNREACH;
532 return (error);
533}
534
535int
536rtrequest1(req, info, ret_nrt)
537 int req;
538 struct rt_addrinfo *info;
539 struct rtentry **ret_nrt;
540{
459 int s = splnet(); int error = 0;
460 register struct rtentry *rt;
461 register struct radix_node *rn;
462 register struct radix_node_head *rnh;
463 struct ifaddr *ifa;
464 struct sockaddr *ndst;
465#define senderr(x) { error = x ; goto bad; }
466
467 /*
468 * Find the correct routing tree to use for this Address Family
469 */
470 if ((rnh = rt_tables[dst->sa_family]) == 0)
541 int s = splnet(); int error = 0;
542 register struct rtentry *rt;
543 register struct radix_node *rn;
544 register struct radix_node_head *rnh;
545 struct ifaddr *ifa;
546 struct sockaddr *ndst;
547#define senderr(x) { error = x ; goto bad; }
548
549 /*
550 * Find the correct routing tree to use for this Address Family
551 */
552 if ((rnh = rt_tables[dst->sa_family]) == 0)
471 senderr(ESRCH);
553 senderr(EAFNOSUPPORT);
472 /*
473 * If we are adding a host route then we don't want to put
474 * a netmask in the tree, nor do we want to clone it.
475 */
476 if (flags & RTF_HOST) {
477 netmask = 0;
478 flags &= ~(RTF_CLONING | RTF_PRCLONING);
479 }

--- 38 unchanged lines hidden (view full) ---

518 * I'm not sure how RTF_UP helps matters. (JRE)
519 */
520 rt->rt_flags &= ~RTF_UP;
521
522 /*
523 * give the protocol a chance to keep things in sync.
524 */
525 if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest)
554 /*
555 * If we are adding a host route then we don't want to put
556 * a netmask in the tree, nor do we want to clone it.
557 */
558 if (flags & RTF_HOST) {
559 netmask = 0;
560 flags &= ~(RTF_CLONING | RTF_PRCLONING);
561 }

--- 38 unchanged lines hidden (view full) ---

600 * I'm not sure how RTF_UP helps matters. (JRE)
601 */
602 rt->rt_flags &= ~RTF_UP;
603
604 /*
605 * give the protocol a chance to keep things in sync.
606 */
607 if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest)
526 ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0));
608 ifa->ifa_rtrequest(RTM_DELETE, rt, info);
527
528 /*
529 * one more rtentry floating around that is not
530 * linked to the routing table.
531 */
532 rttrash++;
533
534 /*

--- 20 unchanged lines hidden (view full) ---

555 if ((netmask = rt->rt_genmask) == 0)
556 flags |= RTF_HOST;
557 goto makeroute;
558
559 case RTM_ADD:
560 if ((flags & RTF_GATEWAY) && !gateway)
561 panic("rtrequest: GATEWAY but no gateway");
562
609
610 /*
611 * one more rtentry floating around that is not
612 * linked to the routing table.
613 */
614 rttrash++;
615
616 /*

--- 20 unchanged lines hidden (view full) ---

637 if ((netmask = rt->rt_genmask) == 0)
638 flags |= RTF_HOST;
639 goto makeroute;
640
641 case RTM_ADD:
642 if ((flags & RTF_GATEWAY) && !gateway)
643 panic("rtrequest: GATEWAY but no gateway");
644
563 if ((ifa = ifa_ifwithroute(flags, dst, gateway)) == 0)
564 senderr(ENETUNREACH);
645 if (info->rti_ifa == NULL && (error = rt_getifa(info)))
646 senderr(error);
647 ifa = info->rti_ifa;
565
566 makeroute:
567 R_Malloc(rt, struct rtentry *, sizeof(*rt));
568 if (rt == 0)
569 senderr(ENOBUFS);
570 Bzero(rt, sizeof(*rt));
571 rt->rt_flags = RTF_UP | flags;
572 /*

--- 85 unchanged lines hidden (view full) ---

658 }
659 }
660
661 /*
662 * if this protocol has something to add to this then
663 * allow it to do that as well.
664 */
665 if (ifa->ifa_rtrequest)
648
649 makeroute:
650 R_Malloc(rt, struct rtentry *, sizeof(*rt));
651 if (rt == 0)
652 senderr(ENOBUFS);
653 Bzero(rt, sizeof(*rt));
654 rt->rt_flags = RTF_UP | flags;
655 /*

--- 85 unchanged lines hidden (view full) ---

741 }
742 }
743
744 /*
745 * if this protocol has something to add to this then
746 * allow it to do that as well.
747 */
748 if (ifa->ifa_rtrequest)
666 ifa->ifa_rtrequest(req, rt, SA(ret_nrt ? *ret_nrt : 0));
749 ifa->ifa_rtrequest(req, rt, info);
667
668 /*
669 * We repeat the same procedure from rt_setgate() here because
670 * it doesn't fire when we call it there because the node
671 * hasn't been added to the tree yet.
672 */
673 if (!(rt->rt_flags & RTF_HOST) && rt_mask(rt) != 0) {
674 struct rtfc_arg arg;

--- 7 unchanged lines hidden (view full) ---

682 * actually return a resultant rtentry and
683 * give the caller a single reference.
684 */
685 if (ret_nrt) {
686 *ret_nrt = rt;
687 rt->rt_refcnt++;
688 }
689 break;
750
751 /*
752 * We repeat the same procedure from rt_setgate() here because
753 * it doesn't fire when we call it there because the node
754 * hasn't been added to the tree yet.
755 */
756 if (!(rt->rt_flags & RTF_HOST) && rt_mask(rt) != 0) {
757 struct rtfc_arg arg;

--- 7 unchanged lines hidden (view full) ---

765 * actually return a resultant rtentry and
766 * give the caller a single reference.
767 */
768 if (ret_nrt) {
769 *ret_nrt = rt;
770 rt->rt_refcnt++;
771 }
772 break;
773 default:
774 error = EOPNOTSUPP;
690 }
691bad:
692 splx(s);
693 return (error);
775 }
776bad:
777 splx(s);
778 return (error);
779#undef dst
780#undef gateway
781#undef netmask
782#undef ifaaddr
783#undef ifpaddr
784#undef flags
694}
695
696/*
697 * Called from rtrequest(RTM_DELETE, ...) to fix up the route's ``family''
698 * (i.e., the routes related to it by the operation of cloning). This
699 * routine is iterated over all potential former-child-routes by way of
700 * rnh->rnh_walktree_from() above, and those that actually are children of
701 * the late parent (passed in as VP here) are themselves deleted.

--- 112 unchanged lines hidden (view full) ---

814 */
815#ifdef DEBUG
816 if(rtfcdebug) printf("deleting\n");
817#endif
818 return rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0,
819 rt_mask(rt), rt->rt_flags, (struct rtentry **)0);
820}
821
785}
786
787/*
788 * Called from rtrequest(RTM_DELETE, ...) to fix up the route's ``family''
789 * (i.e., the routes related to it by the operation of cloning). This
790 * routine is iterated over all potential former-child-routes by way of
791 * rnh->rnh_walktree_from() above, and those that actually are children of
792 * the late parent (passed in as VP here) are themselves deleted.

--- 112 unchanged lines hidden (view full) ---

905 */
906#ifdef DEBUG
907 if(rtfcdebug) printf("deleting\n");
908#endif
909 return rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0,
910 rt_mask(rt), rt->rt_flags, (struct rtentry **)0);
911}
912
913#define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
914
822int
823rt_setgate(rt0, dst, gate)
824 struct rtentry *rt0;
825 struct sockaddr *dst, *gate;
826{
827 caddr_t new, old;
828 int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len);
829 register struct rtentry *rt = rt0;

--- 51 unchanged lines hidden (view full) ---

881 Bcopy(dst, new, dlen);
882 Free(old);
883 }
884
885 /*
886 * If there is already a gwroute, it's now almost definitly wrong
887 * so drop it.
888 */
915int
916rt_setgate(rt0, dst, gate)
917 struct rtentry *rt0;
918 struct sockaddr *dst, *gate;
919{
920 caddr_t new, old;
921 int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len);
922 register struct rtentry *rt = rt0;

--- 51 unchanged lines hidden (view full) ---

974 Bcopy(dst, new, dlen);
975 Free(old);
976 }
977
978 /*
979 * If there is already a gwroute, it's now almost definitly wrong
980 * so drop it.
981 */
889 if (rt->rt_gwroute) {
890 rt = rt->rt_gwroute; RTFREE(rt);
891 rt = rt0; rt->rt_gwroute = 0;
982 if (rt->rt_gwroute != NULL) {
983 RTFREE(rt->rt_gwroute);
984 rt->rt_gwroute = NULL;
892 }
893 /*
894 * Cloning loop avoidance:
895 * In the presence of protocol-cloning and bad configuration,
896 * it is possible to get stuck in bottomless mutual recursion
897 * (rtrequest rt_setgate rtalloc1). We avoid this by not allowing
898 * protocol-cloning to operate for gateways (which is probably the
899 * correct choice anyway), and avoid the resulting reference loops

--- 52 unchanged lines hidden (view full) ---

952int
953rtinit(ifa, cmd, flags)
954 register struct ifaddr *ifa;
955 int cmd, flags;
956{
957 register struct rtentry *rt;
958 register struct sockaddr *dst;
959 register struct sockaddr *deldst;
985 }
986 /*
987 * Cloning loop avoidance:
988 * In the presence of protocol-cloning and bad configuration,
989 * it is possible to get stuck in bottomless mutual recursion
990 * (rtrequest rt_setgate rtalloc1). We avoid this by not allowing
991 * protocol-cloning to operate for gateways (which is probably the
992 * correct choice anyway), and avoid the resulting reference loops

--- 52 unchanged lines hidden (view full) ---

1045int
1046rtinit(ifa, cmd, flags)
1047 register struct ifaddr *ifa;
1048 int cmd, flags;
1049{
1050 register struct rtentry *rt;
1051 register struct sockaddr *dst;
1052 register struct sockaddr *deldst;
1053 struct sockaddr *netmask;
960 struct mbuf *m = 0;
961 struct rtentry *nrt = 0;
1054 struct mbuf *m = 0;
1055 struct rtentry *nrt = 0;
1056 struct radix_node_head *rnh;
1057 struct radix_node *rn;
962 int error;
1058 int error;
1059 struct rt_addrinfo info;
963
1060
964 dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr;
1061 if (flags & RTF_HOST) {
1062 dst = ifa->ifa_dstaddr;
1063 netmask = NULL;
1064 } else {
1065 dst = ifa->ifa_addr;
1066 netmask = ifa->ifa_netmask;
1067 }
965 /*
966 * If it's a delete, check that if it exists, it's on the correct
967 * interface or we might scrub a route to another ifa which would
968 * be confusing at best and possibly worse.
969 */
970 if (cmd == RTM_DELETE) {
971 /*
972 * It's a delete, so it should already exist..
973 * If it's a net, mask off the host bits
974 * (Assuming we have a mask)
975 */
1068 /*
1069 * If it's a delete, check that if it exists, it's on the correct
1070 * interface or we might scrub a route to another ifa which would
1071 * be confusing at best and possibly worse.
1072 */
1073 if (cmd == RTM_DELETE) {
1074 /*
1075 * It's a delete, so it should already exist..
1076 * If it's a net, mask off the host bits
1077 * (Assuming we have a mask)
1078 */
976 if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) {
1079 if (netmask != NULL) {
977 m = m_get(M_DONTWAIT, MT_SONAME);
978 if (m == NULL)
979 return(ENOBUFS);
980 deldst = mtod(m, struct sockaddr *);
1080 m = m_get(M_DONTWAIT, MT_SONAME);
1081 if (m == NULL)
1082 return(ENOBUFS);
1083 deldst = mtod(m, struct sockaddr *);
981 rt_maskedcopy(dst, deldst, ifa->ifa_netmask);
1084 rt_maskedcopy(dst, deldst, netmask);
982 dst = deldst;
983 }
984 /*
1085 dst = deldst;
1086 }
1087 /*
985 * Get an rtentry that is in the routing tree and
986 * contains the correct info. (if this fails, can't get there).
987 * We set "report" to FALSE so that if it doesn't exist,
988 * it doesn't report an error or clone a route, etc. etc.
1088 * Look up an rtentry that is in the routing tree and
1089 * contains the correct info.
989 */
1090 */
990 rt = rtalloc1(dst, 0, 0UL);
991 if (rt) {
992 /*
993 * Ok so we found the rtentry. it has an extra reference
994 * for us at this stage. we won't need that so
995 * lop that off now.
996 */
997 rt->rt_refcnt--;
998 if (rt->rt_ifa != ifa) {
999 /*
1000 * If the interface in the rtentry doesn't match
1001 * the interface we are using, then we don't
1002 * want to delete it, so return an error.
1003 * This seems to be the only point of
1004 * this whole RTM_DELETE clause.
1005 */
1006 if (m)
1007 (void) m_free(m);
1008 return (flags & RTF_HOST ? EHOSTUNREACH
1009 : ENETUNREACH);
1010 }
1091 if ((rnh = rt_tables[dst->sa_family]) == NULL ||
1092 (rn = rnh->rnh_lookup(dst, netmask, rnh)) == NULL ||
1093 (rn->rn_flags & RNF_ROOT) ||
1094 ((struct rtentry *)rn)->rt_ifa != ifa ||
1095 !equal(SA(rn->rn_key), dst)) {
1096 if (m)
1097 (void) m_free(m);
1098 return (flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
1011 }
1012 /* XXX */
1013#if 0
1014 else {
1015 /*
1016 * One would think that as we are deleting, and we know
1017 * it doesn't exist, we could just return at this point
1018 * with an "ELSE" clause, but apparently not..
1019 */
1099 }
1100 /* XXX */
1101#if 0
1102 else {
1103 /*
1104 * One would think that as we are deleting, and we know
1105 * it doesn't exist, we could just return at this point
1106 * with an "ELSE" clause, but apparently not..
1107 */
1020 return (flags & RTF_HOST ? EHOSTUNREACH
1021 : ENETUNREACH);
1108 return (flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
1022 }
1023#endif
1024 }
1025 /*
1026 * Do the actual request
1027 */
1109 }
1110#endif
1111 }
1112 /*
1113 * Do the actual request
1114 */
1028 error = rtrequest(cmd, dst, ifa->ifa_addr, ifa->ifa_netmask,
1029 flags | ifa->ifa_flags, &nrt);
1030 if (m)
1031 (void) m_free(m);
1032 /*
1033 * If we are deleting, and we found an entry, then
1034 * it's been removed from the tree.. now throw it away.
1035 */
1036 if (cmd == RTM_DELETE && error == 0 && (rt = nrt)) {
1115 bzero((caddr_t)&info, sizeof(info));
1116 info.rti_ifa = ifa;
1117 info.rti_flags = flags | ifa->ifa_flags;
1118 info.rti_info[RTAX_DST] = dst;
1119 info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
1120 info.rti_info[RTAX_NETMASK] = netmask;
1121 error = rtrequest1(cmd, &info, &nrt);
1122 if (error == 0 && (rt = nrt) != NULL) {
1037 /*
1038 * notify any listenning routing agents of the change
1039 */
1123 /*
1124 * notify any listenning routing agents of the change
1125 */
1040 rt_newaddrmsg(cmd, ifa, error, nrt);
1041 if (rt->rt_refcnt <= 0) {
1042 rt->rt_refcnt++; /* need a 1->0 transition to free */
1043 rtfree(rt);
1044 }
1045 }
1046
1047 /*
1048 * We are adding, and we have a returned routing entry.
1049 * We need to sanity check the result.
1050 */
1051 if (cmd == RTM_ADD && error == 0 && (rt = nrt)) {
1052 /*
1053 * We just wanted to add it.. we don't actually need a reference
1054 */
1055 rt->rt_refcnt--;
1056 /*
1057 * If it came back with an unexpected interface, then it must
1058 * have already existed or something. (XXX)
1059 */
1060 if (rt->rt_ifa != ifa) {
1061 if (!(rt->rt_ifa->ifa_ifp->if_flags &
1062 (IFF_POINTOPOINT|IFF_LOOPBACK)))
1063 printf("rtinit: wrong ifa (%p) was (%p)\n",
1064 ifa, rt->rt_ifa);
1126 rt_newaddrmsg(cmd, ifa, error, rt);
1127 if (cmd == RTM_DELETE) {
1065 /*
1128 /*
1066 * Ask that the protocol in question
1067 * remove anything it has associated with
1068 * this route and ifaddr.
1129 * If we are deleting, and we found an entry, then
1130 * it's been removed from the tree.. now throw it away.
1069 */
1131 */
1070 if (rt->rt_ifa->ifa_rtrequest)
1071 rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0));
1132 if (rt->rt_refcnt <= 0) {
1133 rt->rt_refcnt++; /* make a 1->0 transition */
1134 rtfree(rt);
1135 }
1136 } else if (cmd == RTM_ADD) {
1072 /*
1137 /*
1073 * Remove the reference to its ifaddr.
1138 * We just wanted to add it.. we don't actually
1139 * need a reference.
1074 */
1140 */
1075 IFAFREE(rt->rt_ifa);
1076 /*
1077 * And substitute in references to the ifaddr
1078 * we are adding.
1079 */
1080 rt->rt_ifa = ifa;
1081 rt->rt_ifp = ifa->ifa_ifp;
1082 rt->rt_rmx.rmx_mtu = ifa->ifa_ifp->if_mtu; /*XXX*/
1083 ifa->ifa_refcnt++;
1084 /*
1085 * Now ask the protocol to check if it needs
1086 * any special processing in its new form.
1087 */
1088 if (ifa->ifa_rtrequest)
1089 ifa->ifa_rtrequest(RTM_ADD, rt, SA(0));
1141 rt->rt_refcnt--;
1090 }
1142 }
1091 /*
1092 * notify any listenning routing agents of the change
1093 */
1094 rt_newaddrmsg(cmd, ifa, error, nrt);
1095 }
1143 }
1144 if (m)
1145 (void) m_free(m);
1096 return (error);
1097}
1098
1099/* This must be before ip6_init2(), which is now SI_ORDER_MIDDLE */
1100SYSINIT(route, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, route_init, 0);
1146 return (error);
1147}
1148
1149/* This must be before ip6_init2(), which is now SI_ORDER_MIDDLE */
1150SYSINIT(route, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, route_init, 0);