Deleted Added
sdiff udiff text old ( 85052 ) new ( 85074 )
full compact
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 $
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 } 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{
291 register 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:
336 flags |= RTF_GATEWAY | RTF_DYNAMIC;
337 error = rtrequest((int)RTM_ADD, dst, gateway,
338 netmask, flags,
339 (struct rtentry **)0);
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
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{
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)
471 senderr(ESRCH);
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)
526 ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0));
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
563 if ((ifa = ifa_ifwithroute(flags, dst, gateway)) == 0)
564 senderr(ENETUNREACH);
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)
666 ifa->ifa_rtrequest(req, rt, SA(ret_nrt ? *ret_nrt : 0));
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;
690 }
691bad:
692 splx(s);
693 return (error);
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
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 */
889 if (rt->rt_gwroute) {
890 rt = rt->rt_gwroute; RTFREE(rt);
891 rt = rt0; rt->rt_gwroute = 0;
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;
960 struct mbuf *m = 0;
961 struct rtentry *nrt = 0;
962 int error;
963
964 dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr;
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 */
976 if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) {
977 m = m_get(M_DONTWAIT, MT_SONAME);
978 if (m == NULL)
979 return(ENOBUFS);
980 deldst = mtod(m, struct sockaddr *);
981 rt_maskedcopy(dst, deldst, ifa->ifa_netmask);
982 dst = deldst;
983 }
984 /*
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.
989 */
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 }
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 */
1020 return (flags & RTF_HOST ? EHOSTUNREACH
1021 : ENETUNREACH);
1022 }
1023#endif
1024 }
1025 /*
1026 * Do the actual request
1027 */
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)) {
1037 /*
1038 * notify any listenning routing agents of the change
1039 */
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);
1065 /*
1066 * Ask that the protocol in question
1067 * remove anything it has associated with
1068 * this route and ifaddr.
1069 */
1070 if (rt->rt_ifa->ifa_rtrequest)
1071 rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0));
1072 /*
1073 * Remove the reference to its ifaddr.
1074 */
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));
1090 }
1091 /*
1092 * notify any listenning routing agents of the change
1093 */
1094 rt_newaddrmsg(cmd, ifa, error, nrt);
1095 }
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);