xref: /freebsd/sys/netinet/in_rmx.c (revision a5243af2622328f6be57d9c4c7b89792557a609a)
1c398230bSWarner Losh /*-
2ea80aed1SGarrett Wollman  * Copyright 1994, 1995 Massachusetts Institute of Technology
3d4a8d8f2SGarrett Wollman  *
4ea80aed1SGarrett Wollman  * Permission to use, copy, modify, and distribute this software and
5ea80aed1SGarrett Wollman  * its documentation for any purpose and without fee is hereby
6ea80aed1SGarrett Wollman  * granted, provided that both the above copyright notice and this
7ea80aed1SGarrett Wollman  * permission notice appear in all copies, that both the above
8ea80aed1SGarrett Wollman  * copyright notice and this permission notice appear in all
9ea80aed1SGarrett Wollman  * supporting documentation, and that the name of M.I.T. not be used
10ea80aed1SGarrett Wollman  * in advertising or publicity pertaining to distribution of the
11ea80aed1SGarrett Wollman  * software without specific, written prior permission.  M.I.T. makes
12ea80aed1SGarrett Wollman  * no representations about the suitability of this software for any
13ea80aed1SGarrett Wollman  * purpose.  It is provided "as is" without express or implied
14ea80aed1SGarrett Wollman  * warranty.
15d4a8d8f2SGarrett Wollman  *
16ea80aed1SGarrett Wollman  * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
17ea80aed1SGarrett Wollman  * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
18ea80aed1SGarrett Wollman  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19ea80aed1SGarrett Wollman  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
20ea80aed1SGarrett Wollman  * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21ea80aed1SGarrett Wollman  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22ea80aed1SGarrett Wollman  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23ea80aed1SGarrett Wollman  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24ea80aed1SGarrett Wollman  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25ea80aed1SGarrett Wollman  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26ea80aed1SGarrett Wollman  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27ea80aed1SGarrett Wollman  * SUCH DAMAGE.
28d4a8d8f2SGarrett Wollman  */
29d4a8d8f2SGarrett Wollman 
304b421e2dSMike Silbersack #include <sys/cdefs.h>
314b421e2dSMike Silbersack __FBSDID("$FreeBSD$");
324b421e2dSMike Silbersack 
33d4a8d8f2SGarrett Wollman #include <sys/param.h>
34d4a8d8f2SGarrett Wollman #include <sys/systm.h>
35d4a8d8f2SGarrett Wollman #include <sys/kernel.h>
3698163b98SPoul-Henning Kamp #include <sys/sysctl.h>
37d4a8d8f2SGarrett Wollman #include <sys/socket.h>
38d4a8d8f2SGarrett Wollman #include <sys/mbuf.h>
39d4a8d8f2SGarrett Wollman 
40d4a8d8f2SGarrett Wollman #include <net/if.h>
4176039bc8SGleb Smirnoff #include <net/if_var.h>
42d4a8d8f2SGarrett Wollman #include <net/route.h>
4361eee0e2SAlexander V. Chernikov #include <net/route_var.h>
44530c0060SRobert Watson #include <net/vnet.h>
454b79449eSBjoern A. Zeeb 
46d4a8d8f2SGarrett Wollman #include <netinet/in.h>
47d4a8d8f2SGarrett Wollman #include <netinet/in_var.h>
483c2824b9SAlexander V. Chernikov #include <netinet/ip.h>
493c2824b9SAlexander V. Chernikov #include <netinet/ip_icmp.h>
501e3d5af0SRuslan Ermilov #include <netinet/ip_var.h>
51d4a8d8f2SGarrett Wollman 
524d77a549SAlfred Perlstein extern int	in_inithead(void **head, int off);
53bc29160dSMarko Zec #ifdef VIMAGE
54bc29160dSMarko Zec extern int	in_detachhead(void **head, int off);
55bc29160dSMarko Zec #endif
56ce7609a4SBruce Evans 
57d4a8d8f2SGarrett Wollman /*
58d4a8d8f2SGarrett Wollman  * Do what we need to do when inserting a route.
59d4a8d8f2SGarrett Wollman  */
60d4a8d8f2SGarrett Wollman static struct radix_node *
6161eee0e2SAlexander V. Chernikov in_addroute(void *v_arg, void *n_arg, struct radix_head *head,
62d4a8d8f2SGarrett Wollman     struct radix_node *treenodes)
63d4a8d8f2SGarrett Wollman {
64d4a8d8f2SGarrett Wollman 	struct rtentry *rt = (struct rtentry *)treenodes;
65dd224982SGarrett Wollman 	struct sockaddr_in *sin = (struct sockaddr_in *)rt_key(rt);
66d4a8d8f2SGarrett Wollman 
67d4a8d8f2SGarrett Wollman 	/*
689f9b3dc4SGarrett Wollman 	 * A little bit of help for both IP output and input:
699f9b3dc4SGarrett Wollman 	 *   For host routes, we make sure that RTF_BROADCAST
709f9b3dc4SGarrett Wollman 	 *   is set for anything that looks like a broadcast address.
719f9b3dc4SGarrett Wollman 	 *   This way, we can avoid an expensive call to in_broadcast()
729f9b3dc4SGarrett Wollman 	 *   in ip_output() most of the time (because the route passed
739f9b3dc4SGarrett Wollman 	 *   to ip_output() is almost always a host route).
749f9b3dc4SGarrett Wollman 	 *
759f9b3dc4SGarrett Wollman 	 *   We also do the same for local addresses, with the thought
769f9b3dc4SGarrett Wollman 	 *   that this might one day be used to speed up ip_input().
779f9b3dc4SGarrett Wollman 	 *
789f9b3dc4SGarrett Wollman 	 * We also mark routes to multicast addresses as such, because
799f9b3dc4SGarrett Wollman 	 * it's easy to do and might be useful (but this is much more
8026d02ca7SAndre Oppermann 	 * dubious since it's so easy to inspect the address).
819f9b3dc4SGarrett Wollman 	 */
829f9b3dc4SGarrett Wollman 	if (rt->rt_flags & RTF_HOST) {
839f9b3dc4SGarrett Wollman 		if (in_broadcast(sin->sin_addr, rt->rt_ifp)) {
849f9b3dc4SGarrett Wollman 			rt->rt_flags |= RTF_BROADCAST;
8524652ff6SJeffrey Hsu 		} else if (satosin(rt->rt_ifa->ifa_addr)->sin_addr.s_addr ==
8624652ff6SJeffrey Hsu 		    sin->sin_addr.s_addr) {
879f9b3dc4SGarrett Wollman 			rt->rt_flags |= RTF_LOCAL;
889f9b3dc4SGarrett Wollman 		}
89bbb7c710SGarrett Wollman 	}
9026d02ca7SAndre Oppermann 	if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
9126d02ca7SAndre Oppermann 		rt->rt_flags |= RTF_MULTICAST;
92d4a8d8f2SGarrett Wollman 
931a75e3b2SAlexander V. Chernikov 	if (rt->rt_ifp != NULL) {
941a75e3b2SAlexander V. Chernikov 
951a75e3b2SAlexander V. Chernikov 		/*
961a75e3b2SAlexander V. Chernikov 		 * Check route MTU:
971a75e3b2SAlexander V. Chernikov 		 * inherit interface MTU if not set or
981a75e3b2SAlexander V. Chernikov 		 * check if MTU is too large.
991a75e3b2SAlexander V. Chernikov 		 */
1001a75e3b2SAlexander V. Chernikov 		if (rt->rt_mtu == 0) {
101e3a7aa6fSGleb Smirnoff 			rt->rt_mtu = rt->rt_ifp->if_mtu;
1021a75e3b2SAlexander V. Chernikov 		} else if (rt->rt_mtu > rt->rt_ifp->if_mtu)
1031a75e3b2SAlexander V. Chernikov 			rt->rt_mtu = rt->rt_ifp->if_mtu;
1041a75e3b2SAlexander V. Chernikov 	}
105dd224982SGarrett Wollman 
1066e6b3f7cSQing Li 	return (rn_addroute(v_arg, n_arg, head, treenodes));
107d4a8d8f2SGarrett Wollman }
108d4a8d8f2SGarrett Wollman 
1098b07e49aSJulian Elischer static int _in_rt_was_here;
110d4a8d8f2SGarrett Wollman /*
111d4a8d8f2SGarrett Wollman  * Initialize our routing tree.
112d4a8d8f2SGarrett Wollman  */
113d4a8d8f2SGarrett Wollman int
114d4a8d8f2SGarrett Wollman in_inithead(void **head, int off)
115d4a8d8f2SGarrett Wollman {
11661eee0e2SAlexander V. Chernikov 	struct rib_head *rh;
117d4a8d8f2SGarrett Wollman 
11861eee0e2SAlexander V. Chernikov 	rh = rt_table_init(32);
11961eee0e2SAlexander V. Chernikov 	if (rh == NULL)
12061eee0e2SAlexander V. Chernikov 		return (0);
121d4a8d8f2SGarrett Wollman 
12261eee0e2SAlexander V. Chernikov 	rh->rnh_addaddr = in_addroute;
12361eee0e2SAlexander V. Chernikov 	*head = (void *)rh;
12431f0d081SAlexander V. Chernikov 
1258b07e49aSJulian Elischer 	if (_in_rt_was_here == 0 ) {
1268b07e49aSJulian Elischer 		_in_rt_was_here = 1;
1278b07e49aSJulian Elischer 	}
128d4a8d8f2SGarrett Wollman 	return 1;
129d4a8d8f2SGarrett Wollman }
130d4a8d8f2SGarrett Wollman 
131bc29160dSMarko Zec #ifdef VIMAGE
132bc29160dSMarko Zec int
133bc29160dSMarko Zec in_detachhead(void **head, int off)
134bc29160dSMarko Zec {
135bc29160dSMarko Zec 
136*a5243af2SBjoern A. Zeeb 	rt_table_destroy((struct rib_head *)(*head));
137*a5243af2SBjoern A. Zeeb 	return (1);
138bc29160dSMarko Zec }
139bc29160dSMarko Zec #endif
140bc29160dSMarko Zec 
14139191c8eSGarrett Wollman /*
14291854268SRuslan Ermilov  * This zaps old routes when the interface goes down or interface
14391854268SRuslan Ermilov  * address is deleted.  In the latter case, it deletes static routes
14491854268SRuslan Ermilov  * that point to this address.  If we don't do this, we may end up
14591854268SRuslan Ermilov  * using the old address in the future.  The ones we always want to
14691854268SRuslan Ermilov  * get rid of are things like ARP entries, since the user might down
14791854268SRuslan Ermilov  * the interface, walk over to a completely different network, and
14891854268SRuslan Ermilov  * plug back in.
14939191c8eSGarrett Wollman  */
15039191c8eSGarrett Wollman struct in_ifadown_arg {
15139191c8eSGarrett Wollman 	struct ifaddr *ifa;
15291854268SRuslan Ermilov 	int del;
15339191c8eSGarrett Wollman };
15439191c8eSGarrett Wollman 
15539191c8eSGarrett Wollman static int
156e8b0643eSAlexander V. Chernikov in_ifadownkill(const struct rtentry *rt, void *xap)
15739191c8eSGarrett Wollman {
15839191c8eSGarrett Wollman 	struct in_ifadown_arg *ap = xap;
15939191c8eSGarrett Wollman 
160e8b0643eSAlexander V. Chernikov 	if (rt->rt_ifa != ap->ifa)
1614579930dSBjoern A. Zeeb 		return (0);
16239191c8eSGarrett Wollman 
163e8b0643eSAlexander V. Chernikov 	if ((rt->rt_flags & RTF_STATIC) != 0 && ap->del == 0)
164e8b0643eSAlexander V. Chernikov 		return (0);
1654bdf0b6aSAlexander V. Chernikov 
166e8b0643eSAlexander V. Chernikov 	return (1);
1674bdf0b6aSAlexander V. Chernikov }
1684bdf0b6aSAlexander V. Chernikov 
169586904c2SGleb Smirnoff void
17091854268SRuslan Ermilov in_ifadown(struct ifaddr *ifa, int delete)
17139191c8eSGarrett Wollman {
17239191c8eSGarrett Wollman 	struct in_ifadown_arg arg;
17339191c8eSGarrett Wollman 
174586904c2SGleb Smirnoff 	KASSERT(ifa->ifa_addr->sa_family == AF_INET,
175586904c2SGleb Smirnoff 	    ("%s: wrong family", __func__));
17639191c8eSGarrett Wollman 
17739191c8eSGarrett Wollman 	arg.ifa = ifa;
17891854268SRuslan Ermilov 	arg.del = delete;
1794bdf0b6aSAlexander V. Chernikov 
180e8b0643eSAlexander V. Chernikov 	rt_foreach_fib_walk_del(AF_INET, in_ifadownkill, &arg);
181d1dd20beSSam Leffler 	ifa->ifa_flags &= ~IFA_ROUTE;		/* XXXlocking? */
1828b07e49aSJulian Elischer }
1838b07e49aSJulian Elischer 
1848b07e49aSJulian Elischer /*
1858b07e49aSJulian Elischer  * inet versions of rt functions. These have fib extensions and
1868b07e49aSJulian Elischer  * for now will just reference the _fib variants.
1878b07e49aSJulian Elischer  * eventually this order will be reversed,
1888b07e49aSJulian Elischer  */
1898b07e49aSJulian Elischer void
1908b07e49aSJulian Elischer in_rtalloc_ign(struct route *ro, u_long ignflags, u_int fibnum)
1918b07e49aSJulian Elischer {
1928b07e49aSJulian Elischer 	rtalloc_ign_fib(ro, ignflags, fibnum);
1938b07e49aSJulian Elischer }
1948b07e49aSJulian Elischer 
1958b07e49aSJulian Elischer void
1968b07e49aSJulian Elischer in_rtredirect(struct sockaddr *dst,
1978b07e49aSJulian Elischer 	struct sockaddr *gateway,
1988b07e49aSJulian Elischer 	struct sockaddr *netmask,
1998b07e49aSJulian Elischer 	int flags,
2008b07e49aSJulian Elischer 	struct sockaddr *src,
2018b07e49aSJulian Elischer 	u_int fibnum)
2028b07e49aSJulian Elischer {
2038b07e49aSJulian Elischer 	rtredirect_fib(dst, gateway, netmask, flags, src, fibnum);
2048b07e49aSJulian Elischer }
2058b07e49aSJulian Elischer 
206