1152909Sanholt/*- 2152909Sanholt * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 395584Sanholt * All rights reserved. 495584Sanholt * 595584Sanholt * Redistribution and use in source and binary forms, with or without 695584Sanholt * modification, are permitted provided that the following conditions 795584Sanholt * are met: 895584Sanholt * 1. Redistributions of source code must retain the above copyright 995584Sanholt * notice, this list of conditions and the following disclaimer. 1095584Sanholt * 2. Redistributions in binary form must reproduce the above copyright 1195584Sanholt * notice, this list of conditions and the following disclaimer in the 1295584Sanholt * documentation and/or other materials provided with the distribution. 1395584Sanholt * 3. Neither the name of the project nor the names of its contributors 1495584Sanholt * may be used to endorse or promote products derived from this software 1595584Sanholt * without specific prior written permission. 1695584Sanholt * 1795584Sanholt * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 1895584Sanholt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1995584Sanholt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2095584Sanholt * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2195584Sanholt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2295584Sanholt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2395584Sanholt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2495584Sanholt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2595584Sanholt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2695584Sanholt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2795584Sanholt * SUCH DAMAGE. 2895584Sanholt * 2995584Sanholt * $KAME: in6_rmx.c,v 1.11 2001/07/26 06:53:16 jinmei Exp $ 3095584Sanholt */ 31152909Sanholt 32152909Sanholt/*- 33152909Sanholt * Copyright 1994, 1995 Massachusetts Institute of Technology 3495584Sanholt * 3595584Sanholt * Permission to use, copy, modify, and distribute this software and 3695584Sanholt * its documentation for any purpose and without fee is hereby 37145132Sanholt * granted, provided that both the above copyright notice and this 38145132Sanholt * permission notice appear in all copies, that both the above 39145132Sanholt * copyright notice and this permission notice appear in all 40145132Sanholt * supporting documentation, and that the name of M.I.T. not be used 41145132Sanholt * in advertising or publicity pertaining to distribution of the 42145132Sanholt * software without specific, written prior permission. M.I.T. makes 43145132Sanholt * no representations about the suitability of this software for any 44196470Srnoland * purpose. It is provided "as is" without express or implied 45145132Sanholt * warranty. 46145132Sanholt * 47145132Sanholt * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 48145132Sanholt * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 49145132Sanholt * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 50145132Sanholt * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 51145132Sanholt * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 52145132Sanholt * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 53145132Sanholt * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 54145132Sanholt * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 55145132Sanholt * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 56145132Sanholt * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 57145132Sanholt * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58145132Sanholt * SUCH DAMAGE. 59145132Sanholt * 60145132Sanholt */ 61145132Sanholt 62145132Sanholt#include <sys/cdefs.h> 63145132Sanholt__FBSDID("$FreeBSD: stable/10/sys/netinet6/in6_rmx.c 314667 2017-03-04 13:03:31Z avg $"); 64145132Sanholt 65145132Sanholt#include <sys/param.h> 66145132Sanholt#include <sys/systm.h> 67145132Sanholt#include <sys/kernel.h> 68145132Sanholt#include <sys/lock.h> 69145132Sanholt#include <sys/sysctl.h> 70145132Sanholt#include <sys/queue.h> 71145132Sanholt#include <sys/socket.h> 72145132Sanholt#include <sys/socketvar.h> 73145132Sanholt#include <sys/mbuf.h> 74145132Sanholt#include <sys/rwlock.h> 75145132Sanholt#include <sys/syslog.h> 76145132Sanholt#include <sys/callout.h> 77145132Sanholt 78145132Sanholt#include <net/if.h> 79145132Sanholt#include <net/route.h> 80145132Sanholt 81145132Sanholt#include <netinet/in.h> 82145132Sanholt#include <netinet/ip_var.h> 83145132Sanholt#include <netinet/in_var.h> 84145132Sanholt 85145132Sanholt#include <netinet/ip6.h> 86145132Sanholt#include <netinet6/ip6_var.h> 87145132Sanholt 88152909Sanholt#include <netinet/icmp6.h> 89157617Sanholt#include <netinet6/nd6.h> 90157617Sanholt 91157617Sanholt#include <netinet/tcp.h> 92157617Sanholt#include <netinet/tcp_seq.h> 93152909Sanholt#include <netinet/tcp_timer.h> 94157617Sanholt#include <netinet/tcp_var.h> 95157617Sanholt 96157617Sanholtextern int in6_inithead(void **head, int off); 97157617Sanholt#ifdef VIMAGE 98157617Sanholtextern int in6_detachhead(void **head, int off); 99162132Sanholt#endif 100162132Sanholt 101182080Srnoland/* 102182080Srnoland * Do what we need to do when inserting a route. 103182080Srnoland */ 104182080Srnolandstatic struct radix_node * 105196471Srnolandin6_addroute(void *v_arg, void *n_arg, struct radix_node_head *head, 106196471Srnoland struct radix_node *treenodes) 107145132Sanholt{ 108145132Sanholt struct rtentry *rt = (struct rtentry *)treenodes; 109196471Srnoland struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)rt_key(rt); 110145132Sanholt struct radix_node *ret; 111145132Sanholt 112157617Sanholt RADIX_NODE_HEAD_WLOCK_ASSERT(head); 113157617Sanholt if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 114157617Sanholt rt->rt_flags |= RTF_MULTICAST; 115145132Sanholt 116145132Sanholt /* 117157617Sanholt * A little bit of help for both IPv6 output and input: 118145132Sanholt * For local addresses, we make sure that RTF_LOCAL is set, 119152909Sanholt * with the thought that this might one day be used to speed up 120157617Sanholt * ip_input(). 121145132Sanholt * 122145132Sanholt * We also mark routes to multicast addresses as such, because 123157617Sanholt * it's easy to do and might be useful (but this is much more 124145132Sanholt * dubious since it's so easy to inspect the address). (This 125145132Sanholt * is done above.) 126148211Sanholt * 127145132Sanholt * XXX 128157617Sanholt * should elaborate the code. 129148211Sanholt */ 130183830Srnoland if (rt->rt_flags & RTF_HOST) { 131157617Sanholt if (IN6_ARE_ADDR_EQUAL(&satosin6(rt->rt_ifa->ifa_addr) 132157617Sanholt ->sin6_addr, 133182080Srnoland &sin6->sin6_addr)) { 134189499Srnoland rt->rt_flags |= RTF_LOCAL; 135182080Srnoland } 136183828Srnoland } 137182080Srnoland 138182080Srnoland if (!rt->rt_mtu && rt->rt_ifp) 139182080Srnoland rt->rt_mtu = IN6_LINKMTU(rt->rt_ifp); 140182080Srnoland 141182080Srnoland ret = rn_addroute(v_arg, n_arg, head, treenodes); 142182080Srnoland if (ret == NULL) { 143189499Srnoland struct rtentry *rt2; 144189499Srnoland /* 145189499Srnoland * We are trying to add a net route, but can't. 146197605Srnoland * The following case should be allowed, so we'll make a 147189499Srnoland * special check for this: 148189499Srnoland * Two IPv6 addresses with the same prefix is assigned 149189499Srnoland * to a single interrface. 150196142Srnoland * # ifconfig if0 inet6 3ffe:0501::1 prefix 64 alias (*1) 151189499Srnoland * # ifconfig if0 inet6 3ffe:0501::2 prefix 64 alias (*2) 152189499Srnoland * In this case, (*1) and (*2) want to add the same 153189499Srnoland * net route entry, 3ffe:0501:: -> if0. 154197605Srnoland * This case should not raise an error. 155145132Sanholt */ 156145132Sanholt rt2 = in6_rtalloc1((struct sockaddr *)sin6, 0, RTF_RNH_LOCKED, 157145132Sanholt rt->rt_fibnum); 158189499Srnoland if (rt2) { 159189499Srnoland if (((rt2->rt_flags & (RTF_HOST|RTF_GATEWAY)) == 0) 160189499Srnoland && rt2->rt_gateway 161189499Srnoland && rt2->rt_gateway->sa_family == AF_LINK 162189499Srnoland && rt2->rt_ifp == rt->rt_ifp) { 163189499Srnoland ret = rt2->rt_nodes; 164145132Sanholt } 165145132Sanholt RTFREE_LOCKED(rt2); 166145132Sanholt } 167145132Sanholt } 168182080Srnoland return (ret); 169182080Srnoland} 170182080Srnoland 171182080SrnolandSYSCTL_DECL(_net_inet6_ip6); 172182080Srnoland 173182080Srnolandstatic VNET_DEFINE(int, rtq_toomany6) = 128; 174182080Srnoland /* 128 cached routes is ``too many'' */ 175182080Srnoland#define V_rtq_toomany6 VNET(rtq_toomany6) 176182080SrnolandSYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_RTMAXCACHE, rtmaxcache, CTLFLAG_RW, 177182080Srnoland &VNET_NAME(rtq_toomany6) , 0, ""); 178182080Srnoland 179145132Sanholtstruct rtqk_arg { 180145132Sanholt struct radix_node_head *rnh; 18195584Sanholt int mode; 182145132Sanholt int updating; 183182080Srnoland int draining; 184145132Sanholt int killed; 185145132Sanholt int found; 18695584Sanholt time_t nextstop; 18795584Sanholt}; 18895584Sanholt 18995584Sanholt/* 19095584Sanholt * Age old PMTUs. 191189499Srnoland */ 192189499Srnolandstruct mtuex_arg { 19395584Sanholt struct radix_node_head *rnh; 194182080Srnoland time_t nextstop; 195182080Srnoland}; 196182080Srnolandstatic VNET_DEFINE(struct callout, rtq_mtutimer); 197182080Srnoland#define V_rtq_mtutimer VNET(rtq_mtutimer) 198182080Srnoland 199182080Srnolandstatic int 20095584Sanholtin6_mtuexpire(struct radix_node *rn, void *rock) 20195584Sanholt{ 20295584Sanholt struct rtentry *rt = (struct rtentry *)rn; 20395584Sanholt struct mtuex_arg *ap = rock; 20495584Sanholt 20595584Sanholt /* sanity */ 20695584Sanholt if (!rt) 20795584Sanholt panic("rt == NULL in in6_mtuexpire"); 20895584Sanholt 20995584Sanholt if (rt->rt_expire && !(rt->rt_flags & RTF_PROBEMTU)) { 21095584Sanholt if (rt->rt_expire <= time_uptime) { 21195584Sanholt rt->rt_flags |= RTF_PROBEMTU; 21295584Sanholt } else { 213145132Sanholt ap->nextstop = lmin(ap->nextstop, rt->rt_expire); 214145132Sanholt } 215145132Sanholt } 216112015Sanholt 217112015Sanholt return 0; 218112015Sanholt} 219112015Sanholt 220112015Sanholt#define MTUTIMO_DEFAULT (60*1) 221112015Sanholt 222182080Srnolandstatic void 223112015Sanholtin6_mtutimo_one(struct radix_node_head *rnh) 224112015Sanholt{ 225145132Sanholt struct mtuex_arg arg; 226145132Sanholt 227145132Sanholt arg.rnh = rnh; 228145132Sanholt arg.nextstop = time_uptime + MTUTIMO_DEFAULT; 229145132Sanholt RADIX_NODE_HEAD_LOCK(rnh); 230145132Sanholt rnh->rnh_walktree(rnh, in6_mtuexpire, &arg); 231145132Sanholt RADIX_NODE_HEAD_UNLOCK(rnh); 232145132Sanholt} 233145132Sanholt 234145132Sanholtstatic void 235145132Sanholtin6_mtutimo(void *rock) 236145132Sanholt{ 237182080Srnoland CURVNET_SET_QUIET((struct vnet *) rock); 238189499Srnoland struct radix_node_head *rnh; 239145132Sanholt struct timeval atv; 240145132Sanholt u_int fibnum; 241196470Srnoland 242196470Srnoland for (fibnum = 0; fibnum < rt_numfibs; fibnum++) { 243196470Srnoland rnh = rt_tables_get_rnh(fibnum, AF_INET6); 244196470Srnoland if (rnh != NULL) 245196470Srnoland in6_mtutimo_one(rnh); 246196470Srnoland } 247196470Srnoland 248196470Srnoland atv.tv_sec = MTUTIMO_DEFAULT; 249196470Srnoland atv.tv_usec = 0; 250196470Srnoland callout_reset(&V_rtq_mtutimer, tvtohz(&atv), in6_mtutimo, rock); 251196470Srnoland CURVNET_RESTORE(); 252196470Srnoland} 253196470Srnoland 254196470Srnoland/* 255196470Srnoland * Initialize our routing tree. 256196470Srnoland * XXX MRT When off == 0, we are being called from vfs_export.c 257196470Srnoland * so just set up their table and leave. (we know what the correct 258196470Srnoland * value should be so just use that).. FIX AFTER RELENG_7 is MFC'd 259196470Srnoland * see also comments in in_inithead() vfs_export.c and domain.h 260196470Srnoland */ 261196470Srnolandstatic VNET_DEFINE(int, _in6_rt_was_here); 262196470Srnoland#define V__in6_rt_was_here VNET(_in6_rt_was_here) 263196470Srnoland 264196470Srnolandint 265196470Srnolandin6_inithead(void **head, int off) 266196470Srnoland{ 267196470Srnoland struct radix_node_head *rnh; 268196470Srnoland 269196470Srnoland if (!rn_inithead(head, offsetof(struct sockaddr_in6, sin6_addr) << 3)) 270196470Srnoland return 0; /* See above */ 271196470Srnoland 272196470Srnoland if (off == 0) /* See above */ 273196470Srnoland return 1; /* only do the rest for the real thing */ 274196470Srnoland 275196470Srnoland rnh = *head; 276196470Srnoland rnh->rnh_addaddr = in6_addroute; 277196470Srnoland 278196470Srnoland if (V__in6_rt_was_here == 0) { 279196470Srnoland callout_init(&V_rtq_mtutimer, 1); 280196470Srnoland in6_mtutimo(curvnet); /* kick off timeout first time */ 281189499Srnoland V__in6_rt_was_here = 1; 282189499Srnoland } 283182080Srnoland 28495584Sanholt return 1; 28595584Sanholt} 28695584Sanholt 28795584Sanholt#ifdef VIMAGE 288122580Sanholtint 289157617Sanholtin6_detachhead(void **head, int off) 290157617Sanholt{ 291122580Sanholt 292119895Sanholt callout_drain(&V_rtq_mtutimer); 293119895Sanholt return (rn_detachhead(head)); 294119895Sanholt} 29595584Sanholt#endif 29695584Sanholt 29795584Sanholt/* 29895584Sanholt * Extended API for IPv6 FIB support. 299145132Sanholt */ 300145132Sanholtvoid 30195584Sanholtin6_rtredirect(struct sockaddr *dst, struct sockaddr *gw, struct sockaddr *nm, 302112015Sanholt int flags, struct sockaddr *src, u_int fibnum) 30395584Sanholt{ 30495584Sanholt 305112015Sanholt rtredirect_fib(dst, gw, nm, flags, src, fibnum); 306189499Srnoland} 307189499Srnoland 308112015Sanholtint 309112015Sanholtin6_rtrequest(int req, struct sockaddr *dst, struct sockaddr *gw, 310112015Sanholt struct sockaddr *mask, int flags, struct rtentry **ret_nrt, u_int fibnum) 311112015Sanholt{ 312112015Sanholt 313112015Sanholt return (rtrequest_fib(req, dst, gw, mask, flags, ret_nrt, fibnum)); 314112015Sanholt} 315112015Sanholt 316112015Sanholtvoid 317112015Sanholtin6_rtalloc(struct route_in6 *ro, u_int fibnum) 31895584Sanholt{ 319112015Sanholt 32095584Sanholt rtalloc_ign_fib((struct route *)ro, 0ul, fibnum); 32195584Sanholt} 32295584Sanholt 32395584Sanholtvoid 32495584Sanholtin6_rtalloc_ign(struct route_in6 *ro, u_long ignflags, u_int fibnum) 32595584Sanholt{ 32695584Sanholt 32795584Sanholt rtalloc_ign_fib((struct route *)ro, ignflags, fibnum); 32895584Sanholt} 32995584Sanholt 33095584Sanholtstruct rtentry * 33195584Sanholtin6_rtalloc1(struct sockaddr *dst, int report, u_long ignflags, u_int fibnum) 33295584Sanholt{ 33395584Sanholt 33495584Sanholt return (rtalloc1_fib(dst, report, ignflags, fibnum)); 33595584Sanholt} 33695584Sanholt