in6_rmx.c revision 283291
1180394Sgnn/*- 2180394Sgnn * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 3180394Sgnn * All rights reserved. 4180394Sgnn * 5180394Sgnn * Redistribution and use in source and binary forms, with or without 6180394Sgnn * modification, are permitted provided that the following conditions 7180394Sgnn * are met: 8180394Sgnn * 1. Redistributions of source code must retain the above copyright 9180394Sgnn * notice, this list of conditions and the following disclaimer. 10180394Sgnn * 2. Redistributions in binary form must reproduce the above copyright 11180394Sgnn * notice, this list of conditions and the following disclaimer in the 12180394Sgnn * documentation and/or other materials provided with the distribution. 13180394Sgnn * 3. Neither the name of the project nor the names of its contributors 14180394Sgnn * may be used to endorse or promote products derived from this software 15180394Sgnn * without specific prior written permission. 16180394Sgnn * 17180394Sgnn * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 18180394Sgnn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19180394Sgnn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20180394Sgnn * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21180394Sgnn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22180394Sgnn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23180394Sgnn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24180394Sgnn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25180394Sgnn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26180394Sgnn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27180394Sgnn * SUCH DAMAGE. 28180394Sgnn * 29180394Sgnn * $KAME: in6_rmx.c,v 1.11 2001/07/26 06:53:16 jinmei Exp $ 30180394Sgnn */ 31180394Sgnn 32180394Sgnn/*- 33180394Sgnn * Copyright 1994, 1995 Massachusetts Institute of Technology 34180394Sgnn * 35180394Sgnn * Permission to use, copy, modify, and distribute this software and 36180394Sgnn * its documentation for any purpose and without fee is hereby 37180394Sgnn * granted, provided that both the above copyright notice and this 38180394Sgnn * permission notice appear in all copies, that both the above 39180394Sgnn * copyright notice and this permission notice appear in all 40180394Sgnn * supporting documentation, and that the name of M.I.T. not be used 41180394Sgnn * in advertising or publicity pertaining to distribution of the 42180394Sgnn * software without specific, written prior permission. M.I.T. makes 43180394Sgnn * no representations about the suitability of this software for any 44180394Sgnn * purpose. It is provided "as is" without express or implied 45180394Sgnn * warranty. 46180394Sgnn * 47180394Sgnn * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 48180394Sgnn * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 49180394Sgnn * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 50180394Sgnn * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 51180394Sgnn * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 52180394Sgnn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 53180394Sgnn * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 54180394Sgnn * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 55180394Sgnn * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 56180394Sgnn * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 57180394Sgnn * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58180394Sgnn * SUCH DAMAGE. 59180394Sgnn * 60180394Sgnn */ 61180394Sgnn 62180394Sgnn#include <sys/cdefs.h> 63180394Sgnn__FBSDID("$FreeBSD: head/sys/netinet6/in6_rmx.c 283291 2015-05-22 17:05:21Z jkim $"); 64180394Sgnn 65180394Sgnn#include <sys/param.h> 66180394Sgnn#include <sys/systm.h> 67180394Sgnn#include <sys/kernel.h> 68180394Sgnn#include <sys/lock.h> 69180394Sgnn#include <sys/queue.h> 70180394Sgnn#include <sys/socket.h> 71180394Sgnn#include <sys/socketvar.h> 72180394Sgnn#include <sys/mbuf.h> 73180394Sgnn#include <sys/rwlock.h> 74180394Sgnn#include <sys/syslog.h> 75180394Sgnn#include <sys/callout.h> 76180394Sgnn 77180394Sgnn#include <net/if.h> 78180394Sgnn#include <net/if_var.h> 79180394Sgnn#include <net/route.h> 80180394Sgnn 81180394Sgnn#include <netinet/in.h> 82180394Sgnn#include <netinet/ip_var.h> 83180394Sgnn#include <netinet/in_var.h> 84180394Sgnn 85180394Sgnn#include <netinet/ip6.h> 86180394Sgnn#include <netinet6/ip6_var.h> 87180394Sgnn 88180394Sgnn#include <netinet/icmp6.h> 89180394Sgnn#include <netinet6/nd6.h> 90180394Sgnn 91261426Sgnn#include <netinet/tcp.h> 92180394Sgnn#include <netinet/tcp_seq.h> 93180394Sgnn#include <netinet/tcp_timer.h> 94180394Sgnn#include <netinet/tcp_var.h> 95180394Sgnn 96180394Sgnnextern int in6_inithead(void **head, int off); 97180394Sgnn#ifdef VIMAGE 98180394Sgnnextern int in6_detachhead(void **head, int off); 99180394Sgnn#endif 100180394Sgnn 101180394Sgnn/* 102180394Sgnn * Do what we need to do when inserting a route. 103180394Sgnn */ 104180394Sgnnstatic struct radix_node * 105180394Sgnnin6_addroute(void *v_arg, void *n_arg, struct radix_node_head *head, 106180394Sgnn struct radix_node *treenodes) 107180394Sgnn{ 108180394Sgnn struct rtentry *rt = (struct rtentry *)treenodes; 109180394Sgnn struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)rt_key(rt); 110180394Sgnn struct radix_node *ret; 111180394Sgnn 112180394Sgnn RADIX_NODE_HEAD_WLOCK_ASSERT(head); 113180394Sgnn if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 114180394Sgnn rt->rt_flags |= RTF_MULTICAST; 115180394Sgnn 116180394Sgnn /* 117180394Sgnn * A little bit of help for both IPv6 output and input: 118180394Sgnn * For local addresses, we make sure that RTF_LOCAL is set, 119180394Sgnn * with the thought that this might one day be used to speed up 120180394Sgnn * ip_input(). 121180394Sgnn * 122180394Sgnn * We also mark routes to multicast addresses as such, because 123180394Sgnn * it's easy to do and might be useful (but this is much more 124180394Sgnn * dubious since it's so easy to inspect the address). (This 125180394Sgnn * is done above.) 126180394Sgnn * 127180394Sgnn * XXX 128180394Sgnn * should elaborate the code. 129180394Sgnn */ 130180394Sgnn if (rt->rt_flags & RTF_HOST) { 131180394Sgnn if (IN6_ARE_ADDR_EQUAL(&satosin6(rt->rt_ifa->ifa_addr) 132180394Sgnn ->sin6_addr, 133180394Sgnn &sin6->sin6_addr)) { 134180394Sgnn rt->rt_flags |= RTF_LOCAL; 135180394Sgnn } 136180394Sgnn } 137180394Sgnn 138180394Sgnn if (rt->rt_ifp != NULL) { 139180394Sgnn 140180394Sgnn /* 141261426Sgnn * Check route MTU: 142261426Sgnn * inherit interface MTU if not set or 143261426Sgnn * check if MTU is too large. 144261426Sgnn */ 145180394Sgnn if (rt->rt_mtu == 0) { 146180394Sgnn rt->rt_mtu = IN6_LINKMTU(rt->rt_ifp); 147180394Sgnn } else if (rt->rt_mtu > IN6_LINKMTU(rt->rt_ifp)) 148180394Sgnn rt->rt_mtu = IN6_LINKMTU(rt->rt_ifp); 149180394Sgnn } 150180394Sgnn 151180394Sgnn ret = rn_addroute(v_arg, n_arg, head, treenodes); 152180394Sgnn if (ret == NULL) { 153180394Sgnn struct rtentry *rt2; 154180394Sgnn /* 155180394Sgnn * We are trying to add a net route, but can't. 156180394Sgnn * The following case should be allowed, so we'll make a 157180394Sgnn * special check for this: 158180394Sgnn * Two IPv6 addresses with the same prefix is assigned 159180394Sgnn * to a single interrface. 160180394Sgnn * # ifconfig if0 inet6 3ffe:0501::1 prefix 64 alias (*1) 161180394Sgnn * # ifconfig if0 inet6 3ffe:0501::2 prefix 64 alias (*2) 162180394Sgnn * In this case, (*1) and (*2) want to add the same 163180394Sgnn * net route entry, 3ffe:0501:: -> if0. 164180394Sgnn * This case should not raise an error. 165261426Sgnn */ 166180394Sgnn rt2 = in6_rtalloc1((struct sockaddr *)sin6, 0, RTF_RNH_LOCKED, 167261426Sgnn rt->rt_fibnum); 168180394Sgnn if (rt2) { 169180394Sgnn if (((rt2->rt_flags & (RTF_HOST|RTF_GATEWAY)) == 0) 170261426Sgnn && rt2->rt_gateway 171180394Sgnn && rt2->rt_gateway->sa_family == AF_LINK 172180394Sgnn && rt2->rt_ifp == rt->rt_ifp) { 173180394Sgnn ret = rt2->rt_nodes; 174180394Sgnn } 175180394Sgnn RTFREE_LOCKED(rt2); 176180394Sgnn } 177180394Sgnn } 178180394Sgnn return (ret); 179180394Sgnn} 180180394Sgnn 181180394Sgnn/* 182180394Sgnn * Age old PMTUs. 183180394Sgnn */ 184261426Sgnnstruct mtuex_arg { 185261426Sgnn struct radix_node_head *rnh; 186261426Sgnn time_t nextstop; 187180394Sgnn}; 188180394Sgnnstatic VNET_DEFINE(struct callout, rtq_mtutimer); 189180394Sgnn#define V_rtq_mtutimer VNET(rtq_mtutimer) 190180394Sgnn 191180394Sgnnstatic int 192180394Sgnnin6_mtuexpire(struct radix_node *rn, void *rock) 193261426Sgnn{ 194180394Sgnn struct rtentry *rt = (struct rtentry *)rn; 195180394Sgnn struct mtuex_arg *ap = rock; 196 197 /* sanity */ 198 if (!rt) 199 panic("rt == NULL in in6_mtuexpire"); 200 201 if (rt->rt_expire && !(rt->rt_flags & RTF_PROBEMTU)) { 202 if (rt->rt_expire <= time_uptime) { 203 rt->rt_flags |= RTF_PROBEMTU; 204 } else { 205 ap->nextstop = lmin(ap->nextstop, rt->rt_expire); 206 } 207 } 208 209 return 0; 210} 211 212#define MTUTIMO_DEFAULT (60*1) 213 214static void 215in6_mtutimo_one(struct radix_node_head *rnh) 216{ 217 struct mtuex_arg arg; 218 219 arg.rnh = rnh; 220 arg.nextstop = time_uptime + MTUTIMO_DEFAULT; 221 RADIX_NODE_HEAD_LOCK(rnh); 222 rnh->rnh_walktree(rnh, in6_mtuexpire, &arg); 223 RADIX_NODE_HEAD_UNLOCK(rnh); 224} 225 226static void 227in6_mtutimo(void *rock) 228{ 229 CURVNET_SET_QUIET((struct vnet *) rock); 230 struct radix_node_head *rnh; 231 struct timeval atv; 232 u_int fibnum; 233 234 for (fibnum = 0; fibnum < rt_numfibs; fibnum++) { 235 rnh = rt_tables_get_rnh(fibnum, AF_INET6); 236 if (rnh != NULL) 237 in6_mtutimo_one(rnh); 238 } 239 240 atv.tv_sec = MTUTIMO_DEFAULT; 241 atv.tv_usec = 0; 242 callout_reset(&V_rtq_mtutimer, tvtohz(&atv), in6_mtutimo, rock); 243 CURVNET_RESTORE(); 244} 245 246/* 247 * Initialize our routing tree. 248 */ 249static VNET_DEFINE(int, _in6_rt_was_here); 250#define V__in6_rt_was_here VNET(_in6_rt_was_here) 251 252int 253in6_inithead(void **head, int off) 254{ 255 struct radix_node_head *rnh; 256 257 if (!rn_inithead(head, offsetof(struct sockaddr_in6, sin6_addr) << 3)) 258 return (0); 259 260 rnh = *head; 261 RADIX_NODE_HEAD_LOCK_INIT(rnh); 262 263 rnh->rnh_addaddr = in6_addroute; 264 265 if (V__in6_rt_was_here == 0) { 266 callout_init(&V_rtq_mtutimer, 1); 267 in6_mtutimo(curvnet); /* kick off timeout first time */ 268 V__in6_rt_was_here = 1; 269 } 270 271 return (1); 272} 273 274#ifdef VIMAGE 275int 276in6_detachhead(void **head, int off) 277{ 278 279 callout_drain(&V_rtq_mtutimer); 280 return (1); 281} 282#endif 283 284/* 285 * Extended API for IPv6 FIB support. 286 */ 287void 288in6_rtredirect(struct sockaddr *dst, struct sockaddr *gw, struct sockaddr *nm, 289 int flags, struct sockaddr *src, u_int fibnum) 290{ 291 292 rtredirect_fib(dst, gw, nm, flags, src, fibnum); 293} 294 295int 296in6_rtrequest(int req, struct sockaddr *dst, struct sockaddr *gw, 297 struct sockaddr *mask, int flags, struct rtentry **ret_nrt, u_int fibnum) 298{ 299 300 return (rtrequest_fib(req, dst, gw, mask, flags, ret_nrt, fibnum)); 301} 302 303void 304in6_rtalloc(struct route_in6 *ro, u_int fibnum) 305{ 306 307 rtalloc_ign_fib((struct route *)ro, 0ul, fibnum); 308} 309 310void 311in6_rtalloc_ign(struct route_in6 *ro, u_long ignflags, u_int fibnum) 312{ 313 314 rtalloc_ign_fib((struct route *)ro, ignflags, fibnum); 315} 316 317struct rtentry * 318in6_rtalloc1(struct sockaddr *dst, int report, u_long ignflags, u_int fibnum) 319{ 320 321 return (rtalloc1_fib(dst, report, ignflags, fibnum)); 322} 323