1caf43b02SWarner Losh /*- 2*51369649SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3*51369649SPedro F. Giffuni * 482cd038dSYoshinobu Inoue * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 582cd038dSYoshinobu Inoue * All rights reserved. 682cd038dSYoshinobu Inoue * 782cd038dSYoshinobu Inoue * Redistribution and use in source and binary forms, with or without 882cd038dSYoshinobu Inoue * modification, are permitted provided that the following conditions 982cd038dSYoshinobu Inoue * are met: 1082cd038dSYoshinobu Inoue * 1. Redistributions of source code must retain the above copyright 1182cd038dSYoshinobu Inoue * notice, this list of conditions and the following disclaimer. 1282cd038dSYoshinobu Inoue * 2. Redistributions in binary form must reproduce the above copyright 1382cd038dSYoshinobu Inoue * notice, this list of conditions and the following disclaimer in the 1482cd038dSYoshinobu Inoue * documentation and/or other materials provided with the distribution. 1582cd038dSYoshinobu Inoue * 3. Neither the name of the project nor the names of its contributors 1682cd038dSYoshinobu Inoue * may be used to endorse or promote products derived from this software 1782cd038dSYoshinobu Inoue * without specific prior written permission. 1882cd038dSYoshinobu Inoue * 1982cd038dSYoshinobu Inoue * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 2082cd038dSYoshinobu Inoue * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2182cd038dSYoshinobu Inoue * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2282cd038dSYoshinobu Inoue * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2382cd038dSYoshinobu Inoue * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2482cd038dSYoshinobu Inoue * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2582cd038dSYoshinobu Inoue * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2682cd038dSYoshinobu Inoue * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2782cd038dSYoshinobu Inoue * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2882cd038dSYoshinobu Inoue * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2982cd038dSYoshinobu Inoue * SUCH DAMAGE. 30b48287a3SDavid E. O'Brien * 31b48287a3SDavid E. O'Brien * $KAME: in6_rmx.c,v 1.11 2001/07/26 06:53:16 jinmei Exp $ 3282cd038dSYoshinobu Inoue */ 3382cd038dSYoshinobu Inoue 34caf43b02SWarner Losh /*- 3582cd038dSYoshinobu Inoue * Copyright 1994, 1995 Massachusetts Institute of Technology 3682cd038dSYoshinobu Inoue * 3782cd038dSYoshinobu Inoue * Permission to use, copy, modify, and distribute this software and 3882cd038dSYoshinobu Inoue * its documentation for any purpose and without fee is hereby 3982cd038dSYoshinobu Inoue * granted, provided that both the above copyright notice and this 4082cd038dSYoshinobu Inoue * permission notice appear in all copies, that both the above 4182cd038dSYoshinobu Inoue * copyright notice and this permission notice appear in all 4282cd038dSYoshinobu Inoue * supporting documentation, and that the name of M.I.T. not be used 4382cd038dSYoshinobu Inoue * in advertising or publicity pertaining to distribution of the 4482cd038dSYoshinobu Inoue * software without specific, written prior permission. M.I.T. makes 4582cd038dSYoshinobu Inoue * no representations about the suitability of this software for any 4682cd038dSYoshinobu Inoue * purpose. It is provided "as is" without express or implied 4782cd038dSYoshinobu Inoue * warranty. 4882cd038dSYoshinobu Inoue * 4982cd038dSYoshinobu Inoue * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 5082cd038dSYoshinobu Inoue * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 5182cd038dSYoshinobu Inoue * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 5282cd038dSYoshinobu Inoue * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 5382cd038dSYoshinobu Inoue * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 5482cd038dSYoshinobu Inoue * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 5582cd038dSYoshinobu Inoue * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 5682cd038dSYoshinobu Inoue * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 5782cd038dSYoshinobu Inoue * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 5882cd038dSYoshinobu Inoue * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 5982cd038dSYoshinobu Inoue * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 6082cd038dSYoshinobu Inoue * SUCH DAMAGE. 6182cd038dSYoshinobu Inoue * 6282cd038dSYoshinobu Inoue */ 6382cd038dSYoshinobu Inoue 64b48287a3SDavid E. O'Brien #include <sys/cdefs.h> 65b48287a3SDavid E. O'Brien __FBSDID("$FreeBSD$"); 66b48287a3SDavid E. O'Brien 6782cd038dSYoshinobu Inoue #include <sys/param.h> 6882cd038dSYoshinobu Inoue #include <sys/systm.h> 6982cd038dSYoshinobu Inoue #include <sys/kernel.h> 70609ff41fSWarner Losh #include <sys/lock.h> 7182cd038dSYoshinobu Inoue #include <sys/queue.h> 7282cd038dSYoshinobu Inoue #include <sys/socket.h> 7382cd038dSYoshinobu Inoue #include <sys/socketvar.h> 7482cd038dSYoshinobu Inoue #include <sys/mbuf.h> 753120b9d4SKip Macy #include <sys/rwlock.h> 7682cd038dSYoshinobu Inoue #include <sys/syslog.h> 77d1dd20beSSam Leffler #include <sys/callout.h> 7882cd038dSYoshinobu Inoue 7982cd038dSYoshinobu Inoue #include <net/if.h> 8076039bc8SGleb Smirnoff #include <net/if_var.h> 810c88be04SBjoern A. Zeeb #include <net/route.h> 8261eee0e2SAlexander V. Chernikov #include <net/route_var.h> 834b79449eSBjoern A. Zeeb 8482cd038dSYoshinobu Inoue #include <netinet/in.h> 8582cd038dSYoshinobu Inoue #include <netinet/ip_var.h> 8682cd038dSYoshinobu Inoue #include <netinet/in_var.h> 8782cd038dSYoshinobu Inoue 88686cdd19SJun-ichiro itojun Hagino #include <netinet/ip6.h> 8982cd038dSYoshinobu Inoue #include <netinet6/ip6_var.h> 9082cd038dSYoshinobu Inoue 91686cdd19SJun-ichiro itojun Hagino #include <netinet/icmp6.h> 9231b3783cSHajimu UMEMOTO #include <netinet6/nd6.h> 9382cd038dSYoshinobu Inoue 9482cd038dSYoshinobu Inoue #include <netinet/tcp.h> 9582cd038dSYoshinobu Inoue #include <netinet/tcp_seq.h> 9682cd038dSYoshinobu Inoue #include <netinet/tcp_timer.h> 9782cd038dSYoshinobu Inoue #include <netinet/tcp_var.h> 9882cd038dSYoshinobu Inoue 999233d8f3SDavid E. O'Brien extern int in6_inithead(void **head, int off); 100bc29160dSMarko Zec #ifdef VIMAGE 101bc29160dSMarko Zec extern int in6_detachhead(void **head, int off); 102bc29160dSMarko Zec #endif 10382cd038dSYoshinobu Inoue 10482cd038dSYoshinobu Inoue /* 10582cd038dSYoshinobu Inoue * Do what we need to do when inserting a route. 10682cd038dSYoshinobu Inoue */ 10782cd038dSYoshinobu Inoue static struct radix_node * 10861eee0e2SAlexander V. Chernikov in6_addroute(void *v_arg, void *n_arg, struct radix_head *head, 10982cd038dSYoshinobu Inoue struct radix_node *treenodes) 11082cd038dSYoshinobu Inoue { 11182cd038dSYoshinobu Inoue struct rtentry *rt = (struct rtentry *)treenodes; 11282cd038dSYoshinobu Inoue struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)rt_key(rt); 11382cd038dSYoshinobu Inoue 11482cd038dSYoshinobu Inoue if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 11582cd038dSYoshinobu Inoue rt->rt_flags |= RTF_MULTICAST; 11682cd038dSYoshinobu Inoue 11782cd038dSYoshinobu Inoue /* 11882cd038dSYoshinobu Inoue * A little bit of help for both IPv6 output and input: 11982cd038dSYoshinobu Inoue * For local addresses, we make sure that RTF_LOCAL is set, 12082cd038dSYoshinobu Inoue * with the thought that this might one day be used to speed up 12182cd038dSYoshinobu Inoue * ip_input(). 12282cd038dSYoshinobu Inoue * 12382cd038dSYoshinobu Inoue * We also mark routes to multicast addresses as such, because 12482cd038dSYoshinobu Inoue * it's easy to do and might be useful (but this is much more 12582cd038dSYoshinobu Inoue * dubious since it's so easy to inspect the address). (This 12682cd038dSYoshinobu Inoue * is done above.) 12782cd038dSYoshinobu Inoue * 12882cd038dSYoshinobu Inoue * XXX 12982cd038dSYoshinobu Inoue * should elaborate the code. 13082cd038dSYoshinobu Inoue */ 13182cd038dSYoshinobu Inoue if (rt->rt_flags & RTF_HOST) { 13282cd038dSYoshinobu Inoue if (IN6_ARE_ADDR_EQUAL(&satosin6(rt->rt_ifa->ifa_addr) 13382cd038dSYoshinobu Inoue ->sin6_addr, 13482cd038dSYoshinobu Inoue &sin6->sin6_addr)) { 13582cd038dSYoshinobu Inoue rt->rt_flags |= RTF_LOCAL; 13682cd038dSYoshinobu Inoue } 13782cd038dSYoshinobu Inoue } 13882cd038dSYoshinobu Inoue 1391a75e3b2SAlexander V. Chernikov if (rt->rt_ifp != NULL) { 1401a75e3b2SAlexander V. Chernikov 1411a75e3b2SAlexander V. Chernikov /* 1421a75e3b2SAlexander V. Chernikov * Check route MTU: 1431a75e3b2SAlexander V. Chernikov * inherit interface MTU if not set or 1441a75e3b2SAlexander V. Chernikov * check if MTU is too large. 1451a75e3b2SAlexander V. Chernikov */ 1461a75e3b2SAlexander V. Chernikov if (rt->rt_mtu == 0) { 147e3a7aa6fSGleb Smirnoff rt->rt_mtu = IN6_LINKMTU(rt->rt_ifp); 1481a75e3b2SAlexander V. Chernikov } else if (rt->rt_mtu > IN6_LINKMTU(rt->rt_ifp)) 1491a75e3b2SAlexander V. Chernikov rt->rt_mtu = IN6_LINKMTU(rt->rt_ifp); 1501a75e3b2SAlexander V. Chernikov } 15182cd038dSYoshinobu Inoue 1525dba456cSAlexander V. Chernikov return (rn_addroute(v_arg, n_arg, head, treenodes)); 15382cd038dSYoshinobu Inoue } 15482cd038dSYoshinobu Inoue 15582cd038dSYoshinobu Inoue /* 15682cd038dSYoshinobu Inoue * Age old PMTUs. 15782cd038dSYoshinobu Inoue */ 15882cd038dSYoshinobu Inoue struct mtuex_arg { 15961eee0e2SAlexander V. Chernikov struct rib_head *rnh; 16082cd038dSYoshinobu Inoue time_t nextstop; 16182cd038dSYoshinobu Inoue }; 1623e288e62SDimitry Andric static VNET_DEFINE(struct callout, rtq_mtutimer); 1631e77c105SRobert Watson #define V_rtq_mtutimer VNET(rtq_mtutimer) 16482cd038dSYoshinobu Inoue 16582cd038dSYoshinobu Inoue static int 1664bdf0b6aSAlexander V. Chernikov in6_mtuexpire(struct rtentry *rt, void *rock) 16782cd038dSYoshinobu Inoue { 16882cd038dSYoshinobu Inoue struct mtuex_arg *ap = rock; 16982cd038dSYoshinobu Inoue 170e3a7aa6fSGleb Smirnoff if (rt->rt_expire && !(rt->rt_flags & RTF_PROBEMTU)) { 171e3a7aa6fSGleb Smirnoff if (rt->rt_expire <= time_uptime) { 17282cd038dSYoshinobu Inoue rt->rt_flags |= RTF_PROBEMTU; 17382cd038dSYoshinobu Inoue } else { 174e3a7aa6fSGleb Smirnoff ap->nextstop = lmin(ap->nextstop, rt->rt_expire); 17582cd038dSYoshinobu Inoue } 17682cd038dSYoshinobu Inoue } 17782cd038dSYoshinobu Inoue 1784bdf0b6aSAlexander V. Chernikov return (0); 17982cd038dSYoshinobu Inoue } 18082cd038dSYoshinobu Inoue 18182cd038dSYoshinobu Inoue #define MTUTIMO_DEFAULT (60*1) 18282cd038dSYoshinobu Inoue 18382cd038dSYoshinobu Inoue static void 18461eee0e2SAlexander V. Chernikov in6_mtutimo_setwa(struct rib_head *rnh, uint32_t fibum, int af, 1852caee4beSAlexander V. Chernikov void *_arg) 18682cd038dSYoshinobu Inoue { 1874bdf0b6aSAlexander V. Chernikov struct mtuex_arg *arg; 18882cd038dSYoshinobu Inoue 1894bdf0b6aSAlexander V. Chernikov arg = (struct mtuex_arg *)_arg; 1904bdf0b6aSAlexander V. Chernikov 1914bdf0b6aSAlexander V. Chernikov arg->rnh = rnh; 19282cd038dSYoshinobu Inoue } 19381d5d46bSBjoern A. Zeeb 19481d5d46bSBjoern A. Zeeb static void 19581d5d46bSBjoern A. Zeeb in6_mtutimo(void *rock) 19681d5d46bSBjoern A. Zeeb { 19781d5d46bSBjoern A. Zeeb CURVNET_SET_QUIET((struct vnet *) rock); 19881d5d46bSBjoern A. Zeeb struct timeval atv; 1994bdf0b6aSAlexander V. Chernikov struct mtuex_arg arg; 20081d5d46bSBjoern A. Zeeb 2012caee4beSAlexander V. Chernikov rt_foreach_fib_walk(AF_INET6, in6_mtutimo_setwa, in6_mtuexpire, &arg); 20281d5d46bSBjoern A. Zeeb 20381d5d46bSBjoern A. Zeeb atv.tv_sec = MTUTIMO_DEFAULT; 20481d5d46bSBjoern A. Zeeb atv.tv_usec = 0; 205603724d3SBjoern A. Zeeb callout_reset(&V_rtq_mtutimer, tvtohz(&atv), in6_mtutimo, rock); 2068b615593SMarko Zec CURVNET_RESTORE(); 20782cd038dSYoshinobu Inoue } 20882cd038dSYoshinobu Inoue 20982cd038dSYoshinobu Inoue /* 21082cd038dSYoshinobu Inoue * Initialize our routing tree. 21182cd038dSYoshinobu Inoue */ 21281d5d46bSBjoern A. Zeeb static VNET_DEFINE(int, _in6_rt_was_here); 21381d5d46bSBjoern A. Zeeb #define V__in6_rt_was_here VNET(_in6_rt_was_here) 21481d5d46bSBjoern A. Zeeb 21582cd038dSYoshinobu Inoue int 21682cd038dSYoshinobu Inoue in6_inithead(void **head, int off) 21782cd038dSYoshinobu Inoue { 21861eee0e2SAlexander V. Chernikov struct rib_head *rh; 21982cd038dSYoshinobu Inoue 22061eee0e2SAlexander V. Chernikov rh = rt_table_init(offsetof(struct sockaddr_in6, sin6_addr) << 3); 22161eee0e2SAlexander V. Chernikov if (rh == NULL) 2229f25cbe4SAlexander V. Chernikov return (0); 22382cd038dSYoshinobu Inoue 22461eee0e2SAlexander V. Chernikov rh->rnh_addaddr = in6_addroute; 22561eee0e2SAlexander V. Chernikov *head = (void *)rh; 22681d5d46bSBjoern A. Zeeb 22781d5d46bSBjoern A. Zeeb if (V__in6_rt_was_here == 0) { 228fd90e2edSJung-uk Kim callout_init(&V_rtq_mtutimer, 1); 22921ca7b57SMarko Zec in6_mtutimo(curvnet); /* kick off timeout first time */ 23081d5d46bSBjoern A. Zeeb V__in6_rt_was_here = 1; 23181d5d46bSBjoern A. Zeeb } 23281d5d46bSBjoern A. Zeeb 2339f25cbe4SAlexander V. Chernikov return (1); 23482cd038dSYoshinobu Inoue } 235bc29160dSMarko Zec 236bc29160dSMarko Zec #ifdef VIMAGE 237bc29160dSMarko Zec int 238bc29160dSMarko Zec in6_detachhead(void **head, int off) 239bc29160dSMarko Zec { 240bc29160dSMarko Zec 241bc29160dSMarko Zec callout_drain(&V_rtq_mtutimer); 242a5243af2SBjoern A. Zeeb rt_table_destroy((struct rib_head *)(*head)); 243a5243af2SBjoern A. Zeeb 244a5243af2SBjoern A. Zeeb return (1); 245bc29160dSMarko Zec } 246bc29160dSMarko Zec #endif 247db566a23SBjoern A. Zeeb 248db566a23SBjoern A. Zeeb /* 249db566a23SBjoern A. Zeeb * Extended API for IPv6 FIB support. 250db566a23SBjoern A. Zeeb */ 251db566a23SBjoern A. Zeeb void 252db566a23SBjoern A. Zeeb in6_rtredirect(struct sockaddr *dst, struct sockaddr *gw, struct sockaddr *nm, 253db566a23SBjoern A. Zeeb int flags, struct sockaddr *src, u_int fibnum) 254db566a23SBjoern A. Zeeb { 255db566a23SBjoern A. Zeeb 256db566a23SBjoern A. Zeeb rtredirect_fib(dst, gw, nm, flags, src, fibnum); 257db566a23SBjoern A. Zeeb } 258db566a23SBjoern A. Zeeb 259db566a23SBjoern A. Zeeb int 260db566a23SBjoern A. Zeeb in6_rtrequest(int req, struct sockaddr *dst, struct sockaddr *gw, 261db566a23SBjoern A. Zeeb struct sockaddr *mask, int flags, struct rtentry **ret_nrt, u_int fibnum) 262db566a23SBjoern A. Zeeb { 263db566a23SBjoern A. Zeeb 264db566a23SBjoern A. Zeeb return (rtrequest_fib(req, dst, gw, mask, flags, ret_nrt, fibnum)); 265db566a23SBjoern A. Zeeb } 266db566a23SBjoern A. Zeeb 267db566a23SBjoern A. Zeeb void 268db566a23SBjoern A. Zeeb in6_rtalloc(struct route_in6 *ro, u_int fibnum) 269db566a23SBjoern A. Zeeb { 270db566a23SBjoern A. Zeeb 271db566a23SBjoern A. Zeeb rtalloc_ign_fib((struct route *)ro, 0ul, fibnum); 272db566a23SBjoern A. Zeeb } 273db566a23SBjoern A. Zeeb 274db566a23SBjoern A. Zeeb void 275db566a23SBjoern A. Zeeb in6_rtalloc_ign(struct route_in6 *ro, u_long ignflags, u_int fibnum) 276db566a23SBjoern A. Zeeb { 277db566a23SBjoern A. Zeeb 278db566a23SBjoern A. Zeeb rtalloc_ign_fib((struct route *)ro, ignflags, fibnum); 279db566a23SBjoern A. Zeeb } 280db566a23SBjoern A. Zeeb 281db566a23SBjoern A. Zeeb struct rtentry * 282db566a23SBjoern A. Zeeb in6_rtalloc1(struct sockaddr *dst, int report, u_long ignflags, u_int fibnum) 283db566a23SBjoern A. Zeeb { 284db566a23SBjoern A. Zeeb 285db566a23SBjoern A. Zeeb return (rtalloc1_fib(dst, report, ignflags, fibnum)); 286db566a23SBjoern A. Zeeb } 287