if_stf.c revision 263478
125450Speter/* $FreeBSD: stable/10/sys/net/if_stf.c 263478 2014-03-21 15:15:30Z glebius $ */ 250476Speter/* $KAME: if_stf.c,v 1.73 2001/12/03 11:08:30 keiichi Exp $ */ 325450Speter 425450Speter/*- 525450Speter * Copyright (C) 2000 WIDE Project. 625450Speter * All rights reserved. 725450Speter * 825450Speter * Redistribution and use in source and binary forms, with or without 925450Speter * modification, are permitted provided that the following conditions 1025450Speter * are met: 1125450Speter * 1. Redistributions of source code must retain the above copyright 1225450Speter * notice, this list of conditions and the following disclaimer. 1325450Speter * 2. Redistributions in binary form must reproduce the above copyright 1425450Speter * notice, this list of conditions and the following disclaimer in the 1525450Speter * documentation and/or other materials provided with the distribution. 1625450Speter * 3. Neither the name of the project nor the names of its contributors 1725450Speter * may be used to endorse or promote products derived from this software 1825450Speter * without specific prior written permission. 1925450Speter * 2025450Speter * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 2125450Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2225450Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2325450Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2425450Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2525450Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2625450Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2725450Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2825450Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2925450Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3025450Speter * SUCH DAMAGE. 3125450Speter */ 3225450Speter 3325450Speter/* 3425450Speter * 6to4 interface, based on RFC3056. 3525450Speter * 3625450Speter * 6to4 interface is NOT capable of link-layer (I mean, IPv4) multicasting. 3725450Speter * There is no address mapping defined from IPv6 multicast address to IPv4 3825450Speter * address. Therefore, we do not have IFF_MULTICAST on the interface. 3925450Speter * 4025450Speter * Due to the lack of address mapping for link-local addresses, we cannot 4125450Speter * throw packets toward link-local addresses (fe80::x). Also, we cannot throw 4225450Speter * packets to link-local multicast addresses (ff02::x). 4325450Speter * 4425450Speter * Here are interesting symptoms due to the lack of link-local address: 4525450Speter * 4625450Speter * Unicast routing exchange: 4725450Speter * - RIPng: Impossible. Uses link-local multicast packet toward ff02::9, 4825450Speter * and link-local addresses as nexthop. 4925450Speter * - OSPFv6: Impossible. OSPFv6 assumes that there's link-local address 5025450Speter * assigned to the link, and makes use of them. Also, HELLO packets use 5125450Speter * link-local multicast addresses (ff02::5 and ff02::6). 5225450Speter * - BGP4+: Maybe. You can only use global address as nexthop, and global 5325450Speter * address as TCP endpoint address. 5425450Speter * 5525450Speter * Multicast routing protocols: 5625450Speter * - PIM: Hello packet cannot be used to discover adjacent PIM routers. 5725450Speter * Adjacent PIM routers must be configured manually (is it really spec-wise 5825450Speter * correct thing to do?). 5925450Speter * 6025450Speter * ICMPv6: 6125450Speter * - Redirects cannot be used due to the lack of link-local address. 6225450Speter * 6325450Speter * stf interface does not have, and will not need, a link-local address. 6425450Speter * It seems to have no real benefit and does not help the above symptoms much. 6525450Speter * Even if we assign link-locals to interface, we cannot really 6625450Speter * use link-local unicast/multicast on top of 6to4 cloud (since there's no 6725450Speter * encapsulation defined for link-local address), and the above analysis does 6825450Speter * not change. RFC3056 does not mandate the assignment of link-local address 6925450Speter * either. 7025450Speter * 7125450Speter * 6to4 interface has security issues. Refer to 7225450Speter * http://playground.iijlab.net/i-d/draft-itojun-ipv6-transition-abuse-00.txt 7325450Speter * for details. The code tries to filter out some of malicious packets. 7425450Speter * Note that there is no way to be 100% secure. 7525450Speter */ 7625450Speter 7725450Speter#include "opt_inet.h" 7825450Speter#include "opt_inet6.h" 7925450Speter 8025450Speter#include <sys/param.h> 8125450Speter#include <sys/systm.h> 8225450Speter#include <sys/socket.h> 8325450Speter#include <sys/sockio.h> 8425450Speter#include <sys/mbuf.h> 8525450Speter#include <sys/errno.h> 8625450Speter#include <sys/kernel.h> 8725450Speter#include <sys/module.h> 8825450Speter#include <sys/protosw.h> 8925450Speter#include <sys/proc.h> 9025450Speter#include <sys/queue.h> 9125450Speter#include <sys/sysctl.h> 9295005Simp#include <machine/cpu.h> 9395005Simp 94114164Ssam#include <sys/malloc.h> 9595005Simp 9695005Simp#include <net/if.h> 9795005Simp#include <net/if_clone.h> 9895005Simp#include <net/route.h> 9925450Speter#include <net/netisr.h> 10095005Simp#include <net/if_types.h> 10195005Simp#include <net/if_stf.h> 10295005Simp#include <net/vnet.h> 10395005Simp 10477385Sphk#include <netinet/in.h> 105138593Ssam#include <netinet/in_systm.h> 106139494Ssam#include <netinet/ip.h> 10725450Speter#include <netinet/ip_var.h> 10825450Speter#include <netinet/in_var.h> 10925450Speter 11025450Speter#include <netinet/ip6.h> 11125450Speter#include <netinet6/ip6_var.h> 11225450Speter#include <netinet6/in6_var.h> 11325450Speter#include <netinet/ip_ecn.h> 11425450Speter 11525450Speter#include <netinet/ip_encap.h> 11625450Speter 11725450Speter#include <machine/stdarg.h> 11825450Speter 11925450Speter#include <net/bpf.h> 12025450Speter 12125450Speter#include <security/mac/mac_framework.h> 12225450Speter 12325450SpeterSYSCTL_DECL(_net_link); 12425450Speterstatic SYSCTL_NODE(_net_link, IFT_STF, stf, CTLFLAG_RW, 0, "6to4 Interface"); 12525450Speter 12625450Speterstatic int stf_route_cache = 1; 12725450SpeterSYSCTL_INT(_net_link_stf, OID_AUTO, route_cache, CTLFLAG_RW, 12825450Speter &stf_route_cache, 0, "Caching of IPv4 routes for 6to4 Output"); 12925450Speter 13025450Speterstatic int stf_permit_rfc1918 = 0; 13125450SpeterTUNABLE_INT("net.link.stf.permit_rfc1918", &stf_permit_rfc1918); 13225450SpeterSYSCTL_INT(_net_link_stf, OID_AUTO, permit_rfc1918, CTLFLAG_RW | CTLFLAG_TUN, 13325450Speter &stf_permit_rfc1918, 0, "Permit the use of private IPv4 addresses"); 13425450Speter 13577385Sphk#define STFUNIT 0 13625450Speter 13725450Speter#define IN6_IS_ADDR_6TO4(x) (ntohs((x)->s6_addr16[0]) == 0x2002) 13825450Speter 13977385Sphk/* 14025450Speter * XXX: Return a pointer with 16-bit aligned. Don't cast it to 14125450Speter * struct in_addr *; use bcopy() instead. 14225450Speter */ 14377385Sphk#define GET_V4(x) (&(x)->s6_addr16[1]) 14477385Sphk 14525450Speterstruct stf_softc { 14677385Sphk struct ifnet *sc_ifp; 14725450Speter union { 14825450Speter struct route __sc_ro4; 149161536Sthomas struct route_in6 __sc_ro6; /* just for safety */ 15025450Speter } __sc_ro46; 15125450Speter#define sc_ro __sc_ro46.__sc_ro4 15225450Speter struct mtx sc_ro_mtx; 15325450Speter u_int sc_fibnum; 15425450Speter const struct encaptab *encap_cookie; 15525450Speter}; 15625450Speter#define STF2IFP(sc) ((sc)->sc_ifp) 15725450Speter 15825450Speterstatic const char stfname[] = "stf"; 15925450Speter 16025450Speter/* 16125450Speter * Note that mutable fields in the softc are not currently locked. 16225450Speter * We do lock sc_ro in stf_output though. 163114232Sharti */ 16477217Sphkstatic MALLOC_DEFINE(M_STF, stfname, "6to4 Tunnel Interface"); 16577217Sphkstatic const int ip_stf_ttl = 40; 16677217Sphk 16777217Sphkextern struct domain inetdomain; 16877217Sphkstruct protosw in_stf_protosw = { 16977217Sphk .pr_type = SOCK_RAW, 17077217Sphk .pr_domain = &inetdomain, 17125450Speter .pr_protocol = IPPROTO_IPV6, 17285853Syar .pr_flags = PR_ATOMIC|PR_ADDR, 17325450Speter .pr_input = in_stf_input, 17425450Speter .pr_output = (pr_output_t *)rip_output, 17577385Sphk .pr_ctloutput = rip_ctloutput, 17677385Sphk .pr_usrreqs = &rip_usrreqs 17725450Speter}; 17877385Sphk 17977385Sphkstatic char *stfnames[] = {"stf0", "stf", "6to4", NULL}; 18077385Sphk 18125450Speterstatic int stfmodevent(module_t, int, void *); 18225450Speterstatic int stf_encapcheck(const struct mbuf *, int, int, void *); 18325450Speterstatic struct in6_ifaddr *stf_getsrcifa6(struct ifnet *); 18425450Speterstatic int stf_output(struct ifnet *, struct mbuf *, const struct sockaddr *, 18525450Speter struct route *); 18625450Speterstatic int isrfc1918addr(struct in_addr *); 187140913Sambriskostatic int stf_checkaddr4(struct stf_softc *, struct in_addr *, 188140913Sambrisko struct ifnet *); 18925450Speterstatic int stf_checkaddr6(struct stf_softc *, struct in6_addr *, 190140913Sambrisko struct ifnet *); 191140913Sambriskostatic void stf_rtrequest(int, struct rtentry *, struct rt_addrinfo *); 19225450Speterstatic int stf_ioctl(struct ifnet *, u_long, caddr_t); 193140913Sambrisko 194140913Sambriskostatic int stf_clone_match(struct if_clone *, const char *); 195140913Sambriskostatic int stf_clone_create(struct if_clone *, char *, size_t, caddr_t); 196140913Sambriskostatic int stf_clone_destroy(struct if_clone *, struct ifnet *); 19725450Speterstatic struct if_clone *stf_cloner; 198140913Sambrisko 199140913Sambriskostatic int 200140913Sambriskostf_clone_match(struct if_clone *ifc, const char *name) 201140913Sambrisko{ 202140913Sambrisko int i; 203140913Sambrisko 204140913Sambrisko for(i = 0; stfnames[i] != NULL; i++) { 20525450Speter if (strcmp(stfnames[i], name) == 0) 206140913Sambrisko return (1); 207140913Sambrisko } 208140913Sambrisko 20925450Speter return (0); 210140913Sambrisko} 211140913Sambrisko 21225450Speterstatic int 213140913Sambriskostf_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) 214140913Sambrisko{ 215140913Sambrisko int err, unit; 216140913Sambrisko struct stf_softc *sc; 217140913Sambrisko struct ifnet *ifp; 218140913Sambrisko 219140913Sambrisko /* 220140913Sambrisko * We can only have one unit, but since unit allocation is 221140913Sambrisko * already locked, we use it to keep from allocating extra 222140913Sambrisko * interfaces. 223140913Sambrisko */ 224140913Sambrisko unit = STFUNIT; 22525450Speter err = ifc_alloc_unit(ifc, &unit); 22625450Speter if (err != 0) 227140913Sambrisko return (err); 228140913Sambrisko 22925450Speter sc = malloc(sizeof(struct stf_softc), M_STF, M_WAITOK | M_ZERO); 230140913Sambrisko ifp = STF2IFP(sc) = if_alloc(IFT_STF); 231140913Sambrisko if (ifp == NULL) { 232140913Sambrisko free(sc, M_STF); 233140913Sambrisko ifc_free_unit(ifc, unit); 234140913Sambrisko return (ENOSPC); 235140913Sambrisko } 236140913Sambrisko ifp->if_softc = sc; 237154240Sambrisko sc->sc_fibnum = curthread->td_proc->p_fibnum; 238140913Sambrisko 239140913Sambrisko /* 240140913Sambrisko * Set the name manually rather then using if_initname because 241140913Sambrisko * we don't conform to the default naming convention for interfaces. 242140913Sambrisko */ 243140913Sambrisko strlcpy(ifp->if_xname, name, IFNAMSIZ); 244140913Sambrisko ifp->if_dname = stfname; 245140913Sambrisko ifp->if_dunit = IF_DUNIT_NONE; 246140913Sambrisko 247140913Sambrisko mtx_init(&(sc)->sc_ro_mtx, "stf ro", NULL, MTX_DEF); 248140913Sambrisko sc->encap_cookie = encap_attach_func(AF_INET, IPPROTO_IPV6, 249140913Sambrisko stf_encapcheck, &in_stf_protosw, sc); 250140913Sambrisko if (sc->encap_cookie == NULL) { 251140913Sambrisko if_printf(ifp, "attach failed\n"); 252140913Sambrisko free(sc, M_STF); 253140913Sambrisko ifc_free_unit(ifc, unit); 254140913Sambrisko return (ENOMEM); 25525450Speter } 25625450Speter 25725450Speter ifp->if_mtu = IPV6_MMTU; 25825450Speter ifp->if_ioctl = stf_ioctl; 25925450Speter ifp->if_output = stf_output; 26025450Speter ifp->if_snd.ifq_maxlen = ifqmaxlen; 26125450Speter if_attach(ifp); 26225450Speter bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); 26325450Speter return (0); 264140913Sambrisko} 26525450Speter 26625450Speterstatic int 267140913Sambriskostf_clone_destroy(struct if_clone *ifc, struct ifnet *ifp) 268140913Sambrisko{ 26925450Speter struct stf_softc *sc = ifp->if_softc; 270140913Sambrisko int err; 271140913Sambrisko 272140913Sambrisko err = encap_detach(sc->encap_cookie); 273140913Sambrisko KASSERT(err == 0, ("Unexpected error detaching encap_cookie")); 274140913Sambrisko mtx_destroy(&(sc)->sc_ro_mtx); 275140913Sambrisko bpfdetach(ifp); 27625450Speter if_detach(ifp); 27725450Speter if_free(ifp); 278138593Ssam 27995005Simp free(sc, M_STF); 28025450Speter ifc_free_unit(ifc, STFUNIT); 28125450Speter 28225450Speter return (0); 28325450Speter} 28425450Speter 285138593Ssamstatic int 28695005Simpstfmodevent(mod, type, data) 28725450Speter module_t mod; 28825450Speter int type; 28925450Speter void *data; 29025450Speter{ 29125450Speter 29225450Speter switch (type) { 29395005Simp case MOD_LOAD: 29425450Speter stf_cloner = if_clone_advanced(stfname, 0, stf_clone_match, 295140913Sambrisko stf_clone_create, stf_clone_destroy); 296140913Sambrisko break; 29725450Speter case MOD_UNLOAD: 298140913Sambrisko if_clone_detach(stf_cloner); 29925450Speter break; 300140913Sambrisko default: 30125450Speter return (EOPNOTSUPP); 30225450Speter } 303140913Sambrisko 30425450Speter return (0); 30525450Speter} 306165359Sjkim 307165359Sjkimstatic moduledata_t stf_mod = { 308165359Sjkim "if_stf", 309165359Sjkim stfmodevent, 310165359Sjkim 0 31125450Speter}; 312165359Sjkim 313140913SambriskoDECLARE_MODULE(if_stf, stf_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 314140913Sambrisko 31525450Speterstatic int 31625450Speterstf_encapcheck(m, off, proto, arg) 317114164Ssam const struct mbuf *m; 318138593Ssam int off; 319114164Ssam int proto; 320114164Ssam void *arg; 321140913Sambrisko{ 322140913Sambrisko struct ip ip; 323114164Ssam struct in6_ifaddr *ia6; 324140913Sambrisko struct stf_softc *sc; 325114164Ssam struct in_addr a, b, mask; 326140913Sambrisko 327114164Ssam sc = (struct stf_softc *)arg; 328114164Ssam if (sc == NULL) 329140913Sambrisko return 0; 330114164Ssam 331140913Sambrisko if ((STF2IFP(sc)->if_flags & IFF_UP) == 0) 332140913Sambrisko return 0; 333114164Ssam 334114164Ssam /* IFF_LINK0 means "no decapsulation" */ 33525450Speter if ((STF2IFP(sc)->if_flags & IFF_LINK0) != 0) 33625450Speter return 0; 33725450Speter 33825450Speter if (proto != IPPROTO_IPV6) 33925450Speter return 0; 34025450Speter 34125450Speter /* LINTED const cast */ 34225450Speter m_copydata((struct mbuf *)(uintptr_t)m, 0, sizeof(ip), (caddr_t)&ip); 34325450Speter 34425450Speter if (ip.ip_v != 4) 34525450Speter return 0; 34625450Speter 34725450Speter ia6 = stf_getsrcifa6(STF2IFP(sc)); 34825450Speter if (ia6 == NULL) 34925450Speter return 0; 35025450Speter 35125450Speter /* 35225450Speter * check if IPv4 dst matches the IPv4 address derived from the 35325450Speter * local 6to4 address. 35425450Speter * success on: dst = 10.1.1.1, ia6->ia_addr = 2002:0a01:0101:... 35525450Speter */ 35625450Speter if (bcmp(GET_V4(&ia6->ia_addr.sin6_addr), &ip.ip_dst, 35725450Speter sizeof(ip.ip_dst)) != 0) { 35825450Speter ifa_free(&ia6->ia_ifa); 35925450Speter return 0; 36025450Speter } 36125450Speter 36225450Speter /* 36325450Speter * check if IPv4 src matches the IPv4 address derived from the 36425450Speter * local 6to4 address masked by prefixmask. 36525450Speter * success on: src = 10.1.1.1, ia6->ia_addr = 2002:0a00:.../24 36625450Speter * fail on: src = 10.1.1.1, ia6->ia_addr = 2002:0b00:.../24 36725450Speter */ 36825450Speter bzero(&a, sizeof(a)); 36977217Sphk bcopy(GET_V4(&ia6->ia_addr.sin6_addr), &a, sizeof(a)); 37077217Sphk bcopy(GET_V4(&ia6->ia_prefixmask.sin6_addr), &mask, sizeof(mask)); 37177217Sphk ifa_free(&ia6->ia_ifa); 37277217Sphk a.s_addr &= mask.s_addr; 37377217Sphk b = ip.ip_src; 37477217Sphk b.s_addr &= mask.s_addr; 37577217Sphk if (a.s_addr != b.s_addr) 37677217Sphk return 0; 37777217Sphk 378114164Ssam /* stf interface makes single side match only */ 379114164Ssam return 32; 380114164Ssam} 381116820Ssam 382116820Ssamstatic struct in6_ifaddr * 383116820Ssamstf_getsrcifa6(ifp) 384114232Sharti struct ifnet *ifp; 385114232Sharti{ 386114232Sharti struct ifaddr *ia; 387114232Sharti struct in_ifaddr *ia4; 388114232Sharti struct sockaddr_in6 *sin6; 389114232Sharti struct in_addr in; 390114232Sharti 391114232Sharti if_addr_rlock(ifp); 392114232Sharti TAILQ_FOREACH(ia, &ifp->if_addrhead, ifa_link) { 39325450Speter if (ia->ifa_addr->sa_family != AF_INET6) 39425450Speter continue; 39525450Speter sin6 = (struct sockaddr_in6 *)ia->ifa_addr; 39625450Speter if (!IN6_IS_ADDR_6TO4(&sin6->sin6_addr)) 39725450Speter continue; 39825450Speter 39925450Speter bcopy(GET_V4(&sin6->sin6_addr), &in, sizeof(in)); 40025450Speter LIST_FOREACH(ia4, INADDR_HASH(in.s_addr), ia_hash) 40125450Speter if (ia4->ia_addr.sin_addr.s_addr == in.s_addr) 40225450Speter break; 40325450Speter if (ia4 == NULL) 40425450Speter continue; 40525450Speter 40625450Speter ifa_ref(ia); 40725450Speter if_addr_runlock(ifp); 40825450Speter return (struct in6_ifaddr *)ia; 40925450Speter } 41025450Speter if_addr_runlock(ifp); 411114164Ssam 412114164Ssam return NULL; 413114164Ssam} 414116820Ssam 41525450Speterstatic int 41625450Speterstf_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, 41725450Speter struct route *ro) 41825450Speter{ 41925450Speter struct stf_softc *sc; 42025450Speter const struct sockaddr_in6 *dst6; 42125450Speter struct route *cached_route; 42225450Speter struct in_addr in4; 42325450Speter const void *ptr; 42425450Speter struct sockaddr_in *dst4; 42525450Speter u_int8_t tos; 42625450Speter struct ip *ip; 42725450Speter struct ip6_hdr *ip6; 42825450Speter struct in6_ifaddr *ia6; 42977217Sphk int error; 43025450Speter 43125450Speter#ifdef MAC 432114164Ssam error = mac_ifnet_check_transmit(ifp, m); 433114164Ssam if (error) { 434114164Ssam m_freem(m); 43525450Speter return (error); 43625450Speter } 43725450Speter#endif 43825450Speter 43925450Speter sc = ifp->if_softc; 44025450Speter dst6 = (const struct sockaddr_in6 *)dst; 44125450Speter 44225450Speter /* just in case */ 44325450Speter if ((ifp->if_flags & IFF_UP) == 0) { 44425450Speter m_freem(m); 44525450Speter ifp->if_oerrors++; 44677217Sphk return ENETDOWN; 44725450Speter } 44825450Speter 449114164Ssam /* 450114164Ssam * If we don't have an ip4 address that match my inner ip6 address, 451114164Ssam * we shouldn't generate output. Without this check, we'll end up 45225450Speter * using wrong IPv4 source. 45325450Speter */ 45425450Speter ia6 = stf_getsrcifa6(ifp); 45525450Speter if (ia6 == NULL) { 45625450Speter m_freem(m); 45725450Speter ifp->if_oerrors++; 45825450Speter return ENETDOWN; 45925450Speter } 46025450Speter 46125450Speter if (m->m_len < sizeof(*ip6)) { 46225450Speter m = m_pullup(m, sizeof(*ip6)); 46377217Sphk if (!m) { 46425450Speter ifa_free(&ia6->ia_ifa); 46525450Speter ifp->if_oerrors++; 466114164Ssam return ENOBUFS; 467114164Ssam } 468114164Ssam } 46925450Speter ip6 = mtod(m, struct ip6_hdr *); 47077217Sphk tos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; 47177217Sphk 47277217Sphk /* 47377217Sphk * Pickup the right outer dst addr from the list of candidates. 47477217Sphk * ip6_dst has priority as it may be able to give us shorter IPv4 hops. 47577217Sphk */ 47677217Sphk ptr = NULL; 47777217Sphk if (IN6_IS_ADDR_6TO4(&ip6->ip6_dst)) 47877217Sphk ptr = GET_V4(&ip6->ip6_dst); 47977217Sphk else if (IN6_IS_ADDR_6TO4(&dst6->sin6_addr)) 48077217Sphk ptr = GET_V4(&dst6->sin6_addr); 48177217Sphk else { 48277217Sphk ifa_free(&ia6->ia_ifa); 483114164Ssam m_freem(m); 484114164Ssam ifp->if_oerrors++; 485116820Ssam return ENETUNREACH; 486114164Ssam } 487114164Ssam bcopy(ptr, &in4, sizeof(in4)); 48877217Sphk 489114232Sharti if (bpf_peers_present(ifp->if_bpf)) { 490114232Sharti /* 491114232Sharti * We need to prepend the address family as 492114232Sharti * a four byte field. Cons up a dummy header 493114232Sharti * to pacify bpf. This is safe because bpf 494114232Sharti * will only read from the mbuf (i.e., it won't 495114232Sharti * try to free it or keep a pointer a to it). 496114232Sharti */ 497114232Sharti u_int af = AF_INET6; 498114232Sharti bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m); 499114232Sharti } 500114232Sharti 501114232Sharti M_PREPEND(m, sizeof(struct ip), M_NOWAIT); 502114232Sharti if (m && m->m_len < sizeof(struct ip)) 503114232Sharti m = m_pullup(m, sizeof(struct ip)); 504114232Sharti if (m == NULL) { 505114232Sharti ifa_free(&ia6->ia_ifa); 50625450Speter ifp->if_oerrors++; 50725450Speter return ENOBUFS; 50825450Speter } 50995005Simp ip = mtod(m, struct ip *); 51025450Speter 51125450Speter bzero(ip, sizeof(*ip)); 51225450Speter 51325450Speter bcopy(GET_V4(&((struct sockaddr_in6 *)&ia6->ia_addr)->sin6_addr), 51425450Speter &ip->ip_src, sizeof(ip->ip_src)); 51525450Speter ifa_free(&ia6->ia_ifa); 51625450Speter bcopy(&in4, &ip->ip_dst, sizeof(ip->ip_dst)); 51725450Speter ip->ip_p = IPPROTO_IPV6; 51825450Speter ip->ip_ttl = ip_stf_ttl; 51925450Speter ip->ip_len = htons(m->m_pkthdr.len); 52025450Speter if (ifp->if_flags & IFF_LINK1) 52125450Speter ip_ecn_ingress(ECN_ALLOWED, &ip->ip_tos, &tos); 52225450Speter else 52325450Speter ip_ecn_ingress(ECN_NOCARE, &ip->ip_tos, &tos); 52425450Speter 52525450Speter if (!stf_route_cache) { 52625450Speter cached_route = NULL; 52725450Speter goto sendit; 52825450Speter } 529114164Ssam 53025450Speter /* 53125450Speter * Do we have a cached route? 53225450Speter */ 533114164Ssam mtx_lock(&(sc)->sc_ro_mtx); 534114164Ssam dst4 = (struct sockaddr_in *)&sc->sc_ro.ro_dst; 535114164Ssam if (dst4->sin_family != AF_INET || 536114164Ssam bcmp(&dst4->sin_addr, &ip->ip_dst, sizeof(ip->ip_dst)) != 0) { 537114164Ssam /* cache route doesn't match */ 538114164Ssam dst4->sin_family = AF_INET; 539114164Ssam dst4->sin_len = sizeof(struct sockaddr_in); 540114164Ssam bcopy(&ip->ip_dst, &dst4->sin_addr, sizeof(dst4->sin_addr)); 541114164Ssam if (sc->sc_ro.ro_rt) { 542114164Ssam RTFREE(sc->sc_ro.ro_rt); 543114164Ssam sc->sc_ro.ro_rt = NULL; 544114164Ssam } 545114164Ssam } 546114164Ssam 547114164Ssam if (sc->sc_ro.ro_rt == NULL) { 548114164Ssam rtalloc_fib(&sc->sc_ro, sc->sc_fibnum); 549114164Ssam if (sc->sc_ro.ro_rt == NULL) { 550114164Ssam m_freem(m); 551114164Ssam mtx_unlock(&(sc)->sc_ro_mtx); 552114164Ssam ifp->if_oerrors++; 553114164Ssam return ENETUNREACH; 554114164Ssam } 555114164Ssam } 55695005Simp cached_route = &sc->sc_ro; 55725450Speter 55825450Spetersendit: 55925450Speter M_SETFIB(m, sc->sc_fibnum); 56025450Speter ifp->if_opackets++; 56125450Speter error = ip_output(m, NULL, cached_route, 0, NULL, NULL); 56225450Speter 56325450Speter if (cached_route != NULL) 56425450Speter mtx_unlock(&(sc)->sc_ro_mtx); 56525450Speter return error; 56625450Speter} 56725450Speter 56825450Speterstatic int 56925450Speterisrfc1918addr(in) 57025450Speter struct in_addr *in; 57125450Speter{ 57225450Speter /* 57325450Speter * returns 1 if private address range: 57425450Speter * 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 57525450Speter */ 57625450Speter if (stf_permit_rfc1918 == 0 && ( 57725450Speter (ntohl(in->s_addr) & 0xff000000) >> 24 == 10 || 57825450Speter (ntohl(in->s_addr) & 0xfff00000) >> 16 == 172 * 256 + 16 || 57925450Speter (ntohl(in->s_addr) & 0xffff0000) >> 16 == 192 * 256 + 168)) 58025450Speter return 1; 58125450Speter 58225450Speter return 0; 58325450Speter} 58425450Speter 58525450Speterstatic int 58625450Speterstf_checkaddr4(sc, in, inifp) 58725450Speter struct stf_softc *sc; 58825450Speter struct in_addr *in; 58925450Speter struct ifnet *inifp; /* incoming interface */ 59025450Speter{ 59125450Speter struct in_ifaddr *ia4; 59225450Speter 59325450Speter /* 59425450Speter * reject packets with the following address: 59525450Speter * 224.0.0.0/4 0.0.0.0/8 127.0.0.0/8 255.0.0.0/8 59625450Speter */ 59795005Simp if (IN_MULTICAST(ntohl(in->s_addr))) 59825450Speter return -1; 59925450Speter switch ((ntohl(in->s_addr) & 0xff000000) >> 24) { 60025450Speter case 0: case 127: case 255: 60125450Speter return -1; 60225450Speter } 60325450Speter 60425450Speter /* 60525450Speter * reject packets with private address range. 60625450Speter * (requirement from RFC3056 section 2 1st paragraph) 60795005Simp */ 60825450Speter if (isrfc1918addr(in)) 60925450Speter return -1; 61077385Sphk 61177385Sphk /* 61277385Sphk * reject packets with broadcast 61377385Sphk */ 61477385Sphk IN_IFADDR_RLOCK(); 61577385Sphk TAILQ_FOREACH(ia4, &V_in_ifaddrhead, ia_link) { 61677385Sphk if ((ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST) == 0) 61777385Sphk continue; 61895005Simp if (in->s_addr == ia4->ia_broadaddr.sin_addr.s_addr) { 61977385Sphk IN_IFADDR_RUNLOCK(); 62077385Sphk return -1; 62125450Speter } 62225450Speter } 62325450Speter IN_IFADDR_RUNLOCK(); 62425450Speter 62525450Speter /* 62625450Speter * perform ingress filter 62777385Sphk */ 62877385Sphk if (sc && (STF2IFP(sc)->if_flags & IFF_LINK2) == 0 && inifp) { 62977385Sphk struct sockaddr_in sin; 63077385Sphk struct rtentry *rt; 63195005Simp 63295005Simp bzero(&sin, sizeof(sin)); 63377385Sphk sin.sin_family = AF_INET; 63477385Sphk sin.sin_len = sizeof(struct sockaddr_in); 63577385Sphk sin.sin_addr = *in; 63677385Sphk rt = rtalloc1_fib((struct sockaddr *)&sin, 0, 63777385Sphk 0UL, sc->sc_fibnum); 63877385Sphk if (!rt || rt->rt_ifp != inifp) { 63977385Sphk#if 0 64077385Sphk log(LOG_WARNING, "%s: packet from 0x%x dropped " 64177385Sphk "due to ingress filter\n", if_name(STF2IFP(sc)), 64277385Sphk (u_int32_t)ntohl(sin.sin_addr.s_addr)); 64377385Sphk#endif 64477385Sphk if (rt) 64577385Sphk RTFREE_LOCKED(rt); 64677385Sphk return -1; 64777385Sphk } 64877385Sphk RTFREE_LOCKED(rt); 64977385Sphk } 650114164Ssam 651114164Ssam return 0; 652114164Ssam} 653114164Ssam 654114164Ssamstatic int 655114164Ssamstf_checkaddr6(sc, in6, inifp) 656114164Ssam struct stf_softc *sc; 657114164Ssam struct in6_addr *in6; 658114164Ssam struct ifnet *inifp; /* incoming interface */ 659114164Ssam{ 660114164Ssam /* 661114164Ssam * check 6to4 addresses 662114164Ssam */ 663114164Ssam if (IN6_IS_ADDR_6TO4(in6)) { 664114164Ssam struct in_addr in4; 665114164Ssam bcopy(GET_V4(in6), &in4, sizeof(in4)); 666114164Ssam return stf_checkaddr4(sc, &in4, inifp); 667114164Ssam } 668114164Ssam 66977385Sphk /* 67095005Simp * reject anything that look suspicious. the test is implemented 67177385Sphk * in ip6_input too, but we check here as well to 67277385Sphk * (1) reject bad packets earlier, and 67377385Sphk * (2) to be safe against future ip6_input change. 67477385Sphk */ 67577385Sphk if (IN6_IS_ADDR_V4COMPAT(in6) || IN6_IS_ADDR_V4MAPPED(in6)) 67677385Sphk return -1; 67777385Sphk 67877385Sphk return 0; 67925450Speter} 68025450Speter 68125450Spetervoid 68277385Sphkin_stf_input(m, off) 68377385Sphk struct mbuf *m; 68425450Speter int off; 68525450Speter{ 68625450Speter int proto; 68725450Speter struct stf_softc *sc; 68825450Speter struct ip *ip; 68925450Speter struct ip6_hdr *ip6; 69025450Speter u_int8_t otos, itos; 69125450Speter struct ifnet *ifp; 69277385Sphk 693161536Sthomas proto = mtod(m, struct ip *)->ip_p; 694161536Sthomas 695161536Sthomas if (proto != IPPROTO_IPV6) { 696161536Sthomas m_freem(m); 69725450Speter return; 69877385Sphk } 69977385Sphk 70077385Sphk ip = mtod(m, struct ip *); 70125450Speter 70225450Speter sc = (struct stf_softc *)encap_getarg(m); 703114164Ssam 704114164Ssam if (sc == NULL || (STF2IFP(sc)->if_flags & IFF_UP) == 0) { 705116820Ssam m_freem(m); 706114164Ssam return; 707114164Ssam } 708114164Ssam 70925450Speter ifp = STF2IFP(sc); 71025450Speter 71125450Speter#ifdef MAC 71225450Speter mac_ifnet_create_mbuf(ifp, m); 71325450Speter#endif 71425450Speter 71525450Speter /* 71625450Speter * perform sanity check against outer src/dst. 71725450Speter * for source, perform ingress filter as well. 71825450Speter */ 71925450Speter if (stf_checkaddr4(sc, &ip->ip_dst, NULL) < 0 || 72025450Speter stf_checkaddr4(sc, &ip->ip_src, m->m_pkthdr.rcvif) < 0) { 72125450Speter m_freem(m); 72225450Speter return; 72325450Speter } 72425450Speter 72525450Speter otos = ip->ip_tos; 72677385Sphk m_adj(m, off); 72795005Simp 72877385Sphk if (m->m_len < sizeof(*ip6)) { 72977385Sphk m = m_pullup(m, sizeof(*ip6)); 73077385Sphk if (!m) 73177385Sphk return; 73277385Sphk } 73377385Sphk ip6 = mtod(m, struct ip6_hdr *); 73477385Sphk 73577385Sphk /* 73677385Sphk * perform sanity check against inner src/dst. 73777385Sphk * for source, perform ingress filter as well. 73877385Sphk */ 73977385Sphk if (stf_checkaddr6(sc, &ip6->ip6_dst, NULL) < 0 || 74077385Sphk stf_checkaddr6(sc, &ip6->ip6_src, m->m_pkthdr.rcvif) < 0) { 74177385Sphk m_freem(m); 74277385Sphk return; 74377385Sphk } 74477385Sphk 74577385Sphk itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; 74677385Sphk if ((ifp->if_flags & IFF_LINK1) != 0) 74777385Sphk ip_ecn_egress(ECN_ALLOWED, &otos, &itos); 748161536Sthomas else 749161536Sthomas ip_ecn_egress(ECN_NOCARE, &otos, &itos); 750161536Sthomas ip6->ip6_flow &= ~htonl(0xff << 20); 751161536Sthomas ip6->ip6_flow |= htonl((u_int32_t)itos << 20); 75277385Sphk 75377385Sphk m->m_pkthdr.rcvif = ifp; 75477385Sphk 755114164Ssam if (bpf_peers_present(ifp->if_bpf)) { 756114164Ssam /* 757114164Ssam * We need to prepend the address family as 758114164Ssam * a four byte field. Cons up a dummy header 75977385Sphk * to pacify bpf. This is safe because bpf 76077385Sphk * will only read from the mbuf (i.e., it won't 76177385Sphk * try to free it or keep a pointer a to it). 76277385Sphk */ 76377385Sphk u_int32_t af = AF_INET6; 76477385Sphk bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m); 76577385Sphk } 76677385Sphk 76777385Sphk /* 76877385Sphk * Put the packet to the network layer input queue according to the 76977385Sphk * specified address family. 77077385Sphk * See net/if_gif.c for possible issues with packet processing 77177385Sphk * reorder due to extra queueing. 77225450Speter */ 77325450Speter ifp->if_ipackets++; 77425450Speter ifp->if_ibytes += m->m_pkthdr.len; 775138593Ssam M_SETFIB(m, ifp->if_fib); 776138593Ssam netisr_dispatch(NETISR_IPV6, m); 777138593Ssam} 778138593Ssam 779138593Ssam/* ARGSUSED */ 780138593Ssamstatic void 781138593Ssamstf_rtrequest(cmd, rt, info) 782138593Ssam int cmd; 783138593Ssam struct rtentry *rt; 784138593Ssam struct rt_addrinfo *info; 785139494Ssam{ 786138593Ssam RT_LOCK_ASSERT(rt); 787138593Ssam rt->rt_mtu = rt->rt_ifp->if_mtu; 788138593Ssam} 789138593Ssam 790138593Ssamstatic int 791138593Ssamstf_ioctl(ifp, cmd, data) 792138593Ssam struct ifnet *ifp; 793138593Ssam u_long cmd; 794138593Ssam caddr_t data; 795138593Ssam{ 796138593Ssam struct ifaddr *ifa; 797138593Ssam struct ifreq *ifr; 798138593Ssam struct sockaddr_in6 *sin6; 799 struct in_addr addr; 800 int error, mtu; 801 802 error = 0; 803 switch (cmd) { 804 case SIOCSIFADDR: 805 ifa = (struct ifaddr *)data; 806 if (ifa == NULL || ifa->ifa_addr->sa_family != AF_INET6) { 807 error = EAFNOSUPPORT; 808 break; 809 } 810 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 811 if (!IN6_IS_ADDR_6TO4(&sin6->sin6_addr)) { 812 error = EINVAL; 813 break; 814 } 815 bcopy(GET_V4(&sin6->sin6_addr), &addr, sizeof(addr)); 816 if (isrfc1918addr(&addr)) { 817 error = EINVAL; 818 break; 819 } 820 821 ifa->ifa_rtrequest = stf_rtrequest; 822 ifp->if_flags |= IFF_UP; 823 break; 824 825 case SIOCADDMULTI: 826 case SIOCDELMULTI: 827 ifr = (struct ifreq *)data; 828 if (ifr && ifr->ifr_addr.sa_family == AF_INET6) 829 ; 830 else 831 error = EAFNOSUPPORT; 832 break; 833 834 case SIOCGIFMTU: 835 break; 836 837 case SIOCSIFMTU: 838 ifr = (struct ifreq *)data; 839 mtu = ifr->ifr_mtu; 840 /* RFC 4213 3.2 ideal world MTU */ 841 if (mtu < IPV6_MINMTU || mtu > IF_MAXMTU - 20) 842 return (EINVAL); 843 ifp->if_mtu = mtu; 844 break; 845 846 default: 847 error = EINVAL; 848 break; 849 } 850 851 return error; 852} 853