in6_rmx.c revision 294706
1193323Sed/*- 2193323Sed * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 3193323Sed * All rights reserved. 4193323Sed * 5193323Sed * Redistribution and use in source and binary forms, with or without 6193323Sed * modification, are permitted provided that the following conditions 7193323Sed * are met: 8193323Sed * 1. Redistributions of source code must retain the above copyright 9193323Sed * notice, this list of conditions and the following disclaimer. 10193323Sed * 2. Redistributions in binary form must reproduce the above copyright 11193323Sed * notice, this list of conditions and the following disclaimer in the 12193323Sed * documentation and/or other materials provided with the distribution. 13193323Sed * 3. Neither the name of the project nor the names of its contributors 14193323Sed * may be used to endorse or promote products derived from this software 15193323Sed * without specific prior written permission. 16198892Srdivacky * 17193323Sed * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 18201360Srdivacky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19193323Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20198090Srdivacky * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21193323Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22198090Srdivacky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23193323Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24193323Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25193323Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26193323Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27193323Sed * SUCH DAMAGE. 28193323Sed * 29198090Srdivacky * $KAME: in6_rmx.c,v 1.11 2001/07/26 06:53:16 jinmei Exp $ 30193323Sed */ 31202375Srdivacky 32198090Srdivacky/*- 33193323Sed * Copyright 1994, 1995 Massachusetts Institute of Technology 34193323Sed * 35193323Sed * Permission to use, copy, modify, and distribute this software and 36193323Sed * its documentation for any purpose and without fee is hereby 37202375Srdivacky * granted, provided that both the above copyright notice and this 38193323Sed * permission notice appear in all copies, that both the above 39193323Sed * copyright notice and this permission notice appear in all 40193323Sed * supporting documentation, and that the name of M.I.T. not be used 41193323Sed * in advertising or publicity pertaining to distribution of the 42193323Sed * software without specific, written prior permission. M.I.T. makes 43193323Sed * no representations about the suitability of this software for any 44193323Sed * purpose. It is provided "as is" without express or implied 45193323Sed * warranty. 46193323Sed * 47193323Sed * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 48193323Sed * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 49193323Sed * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 50193323Sed * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 51193323Sed * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 52193323Sed * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 53193323Sed * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 54193323Sed * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 55193323Sed * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 56193323Sed * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 57193323Sed * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58193323Sed * SUCH DAMAGE. 59193323Sed * 60193323Sed */ 61193323Sed 62193323Sed#include <sys/cdefs.h> 63193323Sed__FBSDID("$FreeBSD: head/sys/netinet6/in6_rmx.c 294706 2016-01-25 06:33:15Z melifaro $"); 64193323Sed 65193323Sed#include <sys/param.h> 66193323Sed#include <sys/systm.h> 67193323Sed#include <sys/kernel.h> 68193323Sed#include <sys/lock.h> 69193323Sed#include <sys/queue.h> 70193323Sed#include <sys/socket.h> 71193323Sed#include <sys/socketvar.h> 72193323Sed#include <sys/mbuf.h> 73193323Sed#include <sys/rwlock.h> 74193323Sed#include <sys/syslog.h> 75193323Sed#include <sys/callout.h> 76193323Sed 77193323Sed#include <net/if.h> 78193323Sed#include <net/if_var.h> 79193323Sed#include <net/route.h> 80193323Sed#include <net/route_var.h> 81193323Sed 82193323Sed#include <netinet/in.h> 83193323Sed#include <netinet/ip_var.h> 84193323Sed#include <netinet/in_var.h> 85193323Sed 86193323Sed#include <netinet/ip6.h> 87193323Sed#include <netinet6/ip6_var.h> 88193323Sed 89193323Sed#include <netinet/icmp6.h> 90193323Sed#include <netinet6/nd6.h> 91193323Sed 92193323Sed#include <netinet/tcp.h> 93193323Sed#include <netinet/tcp_seq.h> 94193323Sed#include <netinet/tcp_timer.h> 95193323Sed#include <netinet/tcp_var.h> 96193323Sed 97193323Sedextern int in6_inithead(void **head, int off); 98193323Sed#ifdef VIMAGE 99193323Sedextern int in6_detachhead(void **head, int off); 100193323Sed#endif 101193323Sed 102193323Sed/* 103193323Sed * Do what we need to do when inserting a route. 104193323Sed */ 105193323Sedstatic struct radix_node * 106193323Sedin6_addroute(void *v_arg, void *n_arg, struct radix_head *head, 107193323Sed struct radix_node *treenodes) 108193323Sed{ 109193323Sed struct rtentry *rt = (struct rtentry *)treenodes; 110193323Sed struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)rt_key(rt); 111193323Sed 112193323Sed if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 113193323Sed rt->rt_flags |= RTF_MULTICAST; 114193323Sed 115193323Sed /* 116193323Sed * A little bit of help for both IPv6 output and input: 117193323Sed * For local addresses, we make sure that RTF_LOCAL is set, 118193323Sed * with the thought that this might one day be used to speed up 119193323Sed * ip_input(). 120193323Sed * 121193323Sed * We also mark routes to multicast addresses as such, because 122193323Sed * it's easy to do and might be useful (but this is much more 123193323Sed * dubious since it's so easy to inspect the address). (This 124193323Sed * is done above.) 125193323Sed * 126193323Sed * XXX 127193323Sed * should elaborate the code. 128193323Sed */ 129193323Sed if (rt->rt_flags & RTF_HOST) { 130195340Sed if (IN6_ARE_ADDR_EQUAL(&satosin6(rt->rt_ifa->ifa_addr) 131193323Sed ->sin6_addr, 132193323Sed &sin6->sin6_addr)) { 133193323Sed rt->rt_flags |= RTF_LOCAL; 134193323Sed } 135193323Sed } 136193323Sed 137193323Sed if (rt->rt_ifp != NULL) { 138193323Sed 139193323Sed /* 140193323Sed * Check route MTU: 141193323Sed * inherit interface MTU if not set or 142193323Sed * check if MTU is too large. 143193323Sed */ 144193323Sed if (rt->rt_mtu == 0) { 145193323Sed rt->rt_mtu = IN6_LINKMTU(rt->rt_ifp); 146193323Sed } else if (rt->rt_mtu > IN6_LINKMTU(rt->rt_ifp)) 147193323Sed rt->rt_mtu = IN6_LINKMTU(rt->rt_ifp); 148193323Sed } 149193323Sed 150193323Sed return (rn_addroute(v_arg, n_arg, head, treenodes)); 151193323Sed} 152193323Sed 153195340Sed/* 154193323Sed * Age old PMTUs. 155193323Sed */ 156193323Sedstruct mtuex_arg { 157193323Sed struct rib_head *rnh; 158193323Sed time_t nextstop; 159193323Sed}; 160193323Sedstatic VNET_DEFINE(struct callout, rtq_mtutimer); 161195098Sed#define V_rtq_mtutimer VNET(rtq_mtutimer) 162195098Sed 163195098Sedstatic int 164193323Sedin6_mtuexpire(struct rtentry *rt, void *rock) 165193323Sed{ 166198090Srdivacky struct mtuex_arg *ap = rock; 167193323Sed 168193323Sed if (rt->rt_expire && !(rt->rt_flags & RTF_PROBEMTU)) { 169193323Sed if (rt->rt_expire <= time_uptime) { 170193323Sed rt->rt_flags |= RTF_PROBEMTU; 171193323Sed } else { 172193323Sed ap->nextstop = lmin(ap->nextstop, rt->rt_expire); 173193323Sed } 174193323Sed } 175193323Sed 176193323Sed return (0); 177193323Sed} 178193323Sed 179193323Sed#define MTUTIMO_DEFAULT (60*1) 180193323Sed 181193323Sedstatic void 182193323Sedin6_mtutimo_setwa(struct rib_head *rnh, uint32_t fibum, int af, 183193323Sed void *_arg) 184193323Sed{ 185193323Sed struct mtuex_arg *arg; 186193323Sed 187198892Srdivacky arg = (struct mtuex_arg *)_arg; 188198892Srdivacky 189193323Sed arg->rnh = rnh; 190193323Sed} 191193323Sed 192193323Sedstatic void 193193323Sedin6_mtutimo(void *rock) 194193323Sed{ 195199481Srdivacky CURVNET_SET_QUIET((struct vnet *) rock); 196199481Srdivacky struct timeval atv; 197199481Srdivacky struct mtuex_arg arg; 198199481Srdivacky 199199481Srdivacky rt_foreach_fib_walk(AF_INET6, in6_mtutimo_setwa, in6_mtuexpire, &arg); 200199481Srdivacky 201199481Srdivacky atv.tv_sec = MTUTIMO_DEFAULT; 202199481Srdivacky atv.tv_usec = 0; 203193323Sed callout_reset(&V_rtq_mtutimer, tvtohz(&atv), in6_mtutimo, rock); 204193323Sed CURVNET_RESTORE(); 205193323Sed} 206193323Sed 207193323Sed/* 208193323Sed * Initialize our routing tree. 209193323Sed */ 210193323Sedstatic VNET_DEFINE(int, _in6_rt_was_here); 211198892Srdivacky#define V__in6_rt_was_here VNET(_in6_rt_was_here) 212193323Sed 213193323Sedint 214195340Sedin6_inithead(void **head, int off) 215195098Sed{ 216193323Sed struct rib_head *rh; 217195340Sed 218195340Sed rh = rt_table_init(offsetof(struct sockaddr_in6, sin6_addr) << 3); 219195098Sed if (rh == NULL) 220193323Sed return (0); 221198113Srdivacky 222195098Sed rh->rnh_addaddr = in6_addroute; 223193323Sed *head = (void *)rh; 224193323Sed 225198113Srdivacky if (V__in6_rt_was_here == 0) { 226198113Srdivacky callout_init(&V_rtq_mtutimer, 1); 227193323Sed in6_mtutimo(curvnet); /* kick off timeout first time */ 228193323Sed V__in6_rt_was_here = 1; 229198396Srdivacky } 230198113Srdivacky 231198396Srdivacky return (1); 232198396Srdivacky} 233198113Srdivacky 234195340Sed#ifdef VIMAGE 235195098Sedint 236193323Sedin6_detachhead(void **head, int off) 237193323Sed{ 238195340Sed 239195340Sed callout_drain(&V_rtq_mtutimer); 240195340Sed return (rn_detachhead(head)); 241195340Sed} 242195340Sed#endif 243193323Sed 244195098Sed/* 245193323Sed * Extended API for IPv6 FIB support. 246193323Sed */ 247193323Sedvoid 248193323Sedin6_rtredirect(struct sockaddr *dst, struct sockaddr *gw, struct sockaddr *nm, 249193323Sed int flags, struct sockaddr *src, u_int fibnum) 250193323Sed{ 251198090Srdivacky 252193323Sed rtredirect_fib(dst, gw, nm, flags, src, fibnum); 253195098Sed} 254193323Sed 255193323Sedint 256193323Sedin6_rtrequest(int req, struct sockaddr *dst, struct sockaddr *gw, 257198892Srdivacky struct sockaddr *mask, int flags, struct rtentry **ret_nrt, u_int fibnum) 258193323Sed{ 259193323Sed 260195098Sed return (rtrequest_fib(req, dst, gw, mask, flags, ret_nrt, fibnum)); 261193323Sed} 262193323Sed 263193323Sedvoid 264193323Sedin6_rtalloc(struct route_in6 *ro, u_int fibnum) 265195098Sed{ 266193323Sed 267193323Sed rtalloc_ign_fib((struct route *)ro, 0ul, fibnum); 268195098Sed} 269193323Sed 270193323Sedvoid 271199481Srdivackyin6_rtalloc_ign(struct route_in6 *ro, u_long ignflags, u_int fibnum) 272199481Srdivacky{ 273193323Sed 274195098Sed rtalloc_ign_fib((struct route *)ro, ignflags, fibnum); 275193323Sed} 276193323Sed 277193323Sedstruct rtentry * 278193323Sedin6_rtalloc1(struct sockaddr *dst, int report, u_long ignflags, u_int fibnum) 279195098Sed{ 280193323Sed 281198892Srdivacky return (rtalloc1_fib(dst, report, ignflags, fibnum)); 282202375Srdivacky} 283198892Srdivacky