1139826Simp/*- 253541Sshin * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 353541Sshin * All rights reserved. 453541Sshin * 553541Sshin * Redistribution and use in source and binary forms, with or without 653541Sshin * modification, are permitted provided that the following conditions 753541Sshin * are met: 853541Sshin * 1. Redistributions of source code must retain the above copyright 953541Sshin * notice, this list of conditions and the following disclaimer. 1053541Sshin * 2. Redistributions in binary form must reproduce the above copyright 1153541Sshin * notice, this list of conditions and the following disclaimer in the 1253541Sshin * documentation and/or other materials provided with the distribution. 1353541Sshin * 3. Neither the name of the project nor the names of its contributors 1453541Sshin * may be used to endorse or promote products derived from this software 1553541Sshin * without specific prior written permission. 1653541Sshin * 1753541Sshin * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 1853541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1953541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2053541Sshin * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2153541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2253541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2353541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2453541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2553541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2653541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2753541Sshin * SUCH DAMAGE. 28174510Sobrien * 29174510Sobrien * $KAME: in6_rmx.c,v 1.11 2001/07/26 06:53:16 jinmei Exp $ 3053541Sshin */ 3153541Sshin 32139826Simp/*- 3353541Sshin * Copyright 1994, 1995 Massachusetts Institute of Technology 3453541Sshin * 3553541Sshin * Permission to use, copy, modify, and distribute this software and 3653541Sshin * its documentation for any purpose and without fee is hereby 3753541Sshin * granted, provided that both the above copyright notice and this 3853541Sshin * permission notice appear in all copies, that both the above 3953541Sshin * copyright notice and this permission notice appear in all 4053541Sshin * supporting documentation, and that the name of M.I.T. not be used 4153541Sshin * in advertising or publicity pertaining to distribution of the 4253541Sshin * software without specific, written prior permission. M.I.T. makes 4353541Sshin * no representations about the suitability of this software for any 4453541Sshin * purpose. It is provided "as is" without express or implied 4553541Sshin * warranty. 4653541Sshin * 4753541Sshin * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 4853541Sshin * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 4953541Sshin * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 5053541Sshin * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 5153541Sshin * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 5253541Sshin * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 5353541Sshin * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 5453541Sshin * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 5553541Sshin * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 5653541Sshin * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 5753541Sshin * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5853541Sshin * SUCH DAMAGE. 5953541Sshin * 6053541Sshin */ 6153541Sshin 62174510Sobrien#include <sys/cdefs.h> 63174510Sobrien__FBSDID("$FreeBSD$"); 64174510Sobrien 6553541Sshin#include <sys/param.h> 6653541Sshin#include <sys/systm.h> 6753541Sshin#include <sys/kernel.h> 68185751Simp#include <sys/lock.h> 6953541Sshin#include <sys/queue.h> 7053541Sshin#include <sys/socket.h> 7153541Sshin#include <sys/socketvar.h> 7253541Sshin#include <sys/mbuf.h> 73185747Skmacy#include <sys/rwlock.h> 7453541Sshin#include <sys/syslog.h> 75120727Ssam#include <sys/callout.h> 7653541Sshin 7753541Sshin#include <net/if.h> 78257176Sglebius#include <net/if_var.h> 79194714Sbz#include <net/route.h> 80294706Smelifaro#include <net/route_var.h> 81185571Sbz 8253541Sshin#include <netinet/in.h> 8353541Sshin#include <netinet/ip_var.h> 8453541Sshin#include <netinet/in_var.h> 8553541Sshin 8662587Sitojun#include <netinet/ip6.h> 8753541Sshin#include <netinet6/ip6_var.h> 8853541Sshin 8962587Sitojun#include <netinet/icmp6.h> 90121283Sume#include <netinet6/nd6.h> 9153541Sshin 9253541Sshin#include <netinet/tcp.h> 9353541Sshin#include <netinet/tcp_seq.h> 9453541Sshin#include <netinet/tcp_timer.h> 9553541Sshin#include <netinet/tcp_var.h> 9653541Sshin 97175162Sobrienextern int in6_inithead(void **head, int off); 98193731Szec#ifdef VIMAGE 99193731Szecextern int in6_detachhead(void **head, int off); 100193731Szec#endif 10153541Sshin 10253541Sshin/* 10353541Sshin * Do what we need to do when inserting a route. 10453541Sshin */ 10553541Sshinstatic struct radix_node * 106294706Smelifaroin6_addroute(void *v_arg, void *n_arg, struct radix_head *head, 107171260Sdelphij struct radix_node *treenodes) 10853541Sshin{ 10953541Sshin struct rtentry *rt = (struct rtentry *)treenodes; 11053541Sshin struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)rt_key(rt); 11153541Sshin 11253541Sshin if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 11353541Sshin rt->rt_flags |= RTF_MULTICAST; 11453541Sshin 11553541Sshin /* 11653541Sshin * A little bit of help for both IPv6 output and input: 11753541Sshin * For local addresses, we make sure that RTF_LOCAL is set, 11853541Sshin * with the thought that this might one day be used to speed up 11953541Sshin * ip_input(). 12053541Sshin * 12153541Sshin * We also mark routes to multicast addresses as such, because 12253541Sshin * it's easy to do and might be useful (but this is much more 12353541Sshin * dubious since it's so easy to inspect the address). (This 12453541Sshin * is done above.) 12553541Sshin * 12653541Sshin * XXX 12753541Sshin * should elaborate the code. 12853541Sshin */ 12953541Sshin if (rt->rt_flags & RTF_HOST) { 13053541Sshin if (IN6_ARE_ADDR_EQUAL(&satosin6(rt->rt_ifa->ifa_addr) 13153541Sshin ->sin6_addr, 13253541Sshin &sin6->sin6_addr)) { 13353541Sshin rt->rt_flags |= RTF_LOCAL; 13453541Sshin } 13553541Sshin } 13653541Sshin 137274175Smelifaro if (rt->rt_ifp != NULL) { 13853541Sshin 139274175Smelifaro /* 140274175Smelifaro * Check route MTU: 141274175Smelifaro * inherit interface MTU if not set or 142274175Smelifaro * check if MTU is too large. 143274175Smelifaro */ 144274175Smelifaro if (rt->rt_mtu == 0) { 145274175Smelifaro rt->rt_mtu = IN6_LINKMTU(rt->rt_ifp); 146274175Smelifaro } else if (rt->rt_mtu > IN6_LINKMTU(rt->rt_ifp)) 147274175Smelifaro rt->rt_mtu = IN6_LINKMTU(rt->rt_ifp); 148274175Smelifaro } 149274175Smelifaro 150293471Smelifaro return (rn_addroute(v_arg, n_arg, head, treenodes)); 15153541Sshin} 15253541Sshin 15353541Sshin/* 15453541Sshin * Age old PMTUs. 15553541Sshin */ 15653541Sshinstruct mtuex_arg { 157294706Smelifaro struct rib_head *rnh; 15853541Sshin time_t nextstop; 15953541Sshin}; 160215701Sdimstatic VNET_DEFINE(struct callout, rtq_mtutimer); 161195727Srwatson#define V_rtq_mtutimer VNET(rtq_mtutimer) 162195699Srwatson 16353541Sshinstatic int 164286458Smelifaroin6_mtuexpire(struct rtentry *rt, void *rock) 16553541Sshin{ 16653541Sshin struct mtuex_arg *ap = rock; 16753541Sshin 168262763Sglebius if (rt->rt_expire && !(rt->rt_flags & RTF_PROBEMTU)) { 169262763Sglebius if (rt->rt_expire <= time_uptime) { 17053541Sshin rt->rt_flags |= RTF_PROBEMTU; 17153541Sshin } else { 172262763Sglebius ap->nextstop = lmin(ap->nextstop, rt->rt_expire); 17353541Sshin } 17453541Sshin } 17553541Sshin 176286458Smelifaro return (0); 17753541Sshin} 17853541Sshin 17953541Sshin#define MTUTIMO_DEFAULT (60*1) 18053541Sshin 18153541Sshinstatic void 182294706Smelifaroin6_mtutimo_setwa(struct rib_head *rnh, uint32_t fibum, int af, 183286594Smelifaro void *_arg) 18453541Sshin{ 185286458Smelifaro struct mtuex_arg *arg; 18653541Sshin 187286458Smelifaro arg = (struct mtuex_arg *)_arg; 188286458Smelifaro 189286458Smelifaro arg->rnh = rnh; 190231852Sbz} 19153541Sshin 192231852Sbzstatic void 193231852Sbzin6_mtutimo(void *rock) 194231852Sbz{ 195231852Sbz CURVNET_SET_QUIET((struct vnet *) rock); 196231852Sbz struct timeval atv; 197286458Smelifaro struct mtuex_arg arg; 198231852Sbz 199286594Smelifaro rt_foreach_fib_walk(AF_INET6, in6_mtutimo_setwa, in6_mtuexpire, &arg); 200231852Sbz 201231852Sbz atv.tv_sec = MTUTIMO_DEFAULT; 20253541Sshin atv.tv_usec = 0; 203181803Sbz callout_reset(&V_rtq_mtutimer, tvtohz(&atv), in6_mtutimo, rock); 204183550Szec CURVNET_RESTORE(); 20553541Sshin} 20653541Sshin 20753541Sshin/* 20853541Sshin * Initialize our routing tree. 20953541Sshin */ 210231852Sbzstatic VNET_DEFINE(int, _in6_rt_was_here); 211231852Sbz#define V__in6_rt_was_here VNET(_in6_rt_was_here) 212231852Sbz 21353541Sshinint 21453541Sshinin6_inithead(void **head, int off) 21553541Sshin{ 216294706Smelifaro struct rib_head *rh; 21753541Sshin 218294706Smelifaro rh = rt_table_init(offsetof(struct sockaddr_in6, sin6_addr) << 3); 219294706Smelifaro if (rh == NULL) 220274118Smelifaro return (0); 22153541Sshin 222294706Smelifaro rh->rnh_addaddr = in6_addroute; 223294706Smelifaro *head = (void *)rh; 224272361Smelifaro 225231852Sbz if (V__in6_rt_was_here == 0) { 226283291Sjkim callout_init(&V_rtq_mtutimer, 1); 227231852Sbz in6_mtutimo(curvnet); /* kick off timeout first time */ 228231852Sbz V__in6_rt_was_here = 1; 229231852Sbz } 230231852Sbz 231274118Smelifaro return (1); 23253541Sshin} 233193731Szec 234193731Szec#ifdef VIMAGE 235193731Szecint 236193731Szecin6_detachhead(void **head, int off) 237193731Szec{ 238193731Szec 239193731Szec callout_drain(&V_rtq_mtutimer); 240295529Sdteske rt_table_destroy((struct rib_head *)(*head)); 241295529Sdteske 242295529Sdteske return (1); 243193731Szec} 244193731Szec#endif 245231852Sbz 246231852Sbz/* 247231852Sbz * Extended API for IPv6 FIB support. 248231852Sbz */ 249231852Sbzvoid 250231852Sbzin6_rtredirect(struct sockaddr *dst, struct sockaddr *gw, struct sockaddr *nm, 251231852Sbz int flags, struct sockaddr *src, u_int fibnum) 252231852Sbz{ 253231852Sbz 254231852Sbz rtredirect_fib(dst, gw, nm, flags, src, fibnum); 255231852Sbz} 256231852Sbz 257231852Sbzint 258231852Sbzin6_rtrequest(int req, struct sockaddr *dst, struct sockaddr *gw, 259231852Sbz struct sockaddr *mask, int flags, struct rtentry **ret_nrt, u_int fibnum) 260231852Sbz{ 261231852Sbz 262231852Sbz return (rtrequest_fib(req, dst, gw, mask, flags, ret_nrt, fibnum)); 263231852Sbz} 264231852Sbz 265231852Sbzvoid 266231852Sbzin6_rtalloc(struct route_in6 *ro, u_int fibnum) 267231852Sbz{ 268231852Sbz 269231852Sbz rtalloc_ign_fib((struct route *)ro, 0ul, fibnum); 270231852Sbz} 271231852Sbz 272231852Sbzvoid 273231852Sbzin6_rtalloc_ign(struct route_in6 *ro, u_long ignflags, u_int fibnum) 274231852Sbz{ 275231852Sbz 276231852Sbz rtalloc_ign_fib((struct route *)ro, ignflags, fibnum); 277231852Sbz} 278231852Sbz 279231852Sbzstruct rtentry * 280231852Sbzin6_rtalloc1(struct sockaddr *dst, int report, u_long ignflags, u_int fibnum) 281231852Sbz{ 282231852Sbz 283231852Sbz return (rtalloc1_fib(dst, report, ignflags, fibnum)); 284231852Sbz} 285