1 1.109 thorpej /* $NetBSD: if_stf.c,v 1.109 2022/09/03 02:47:59 thorpej Exp $ */ 2 1.59 ad /* $KAME: if_stf.c,v 1.62 2001/06/07 22:32:16 itojun Exp $ */ 3 1.1 itojun 4 1.1 itojun /* 5 1.1 itojun * Copyright (C) 2000 WIDE Project. 6 1.1 itojun * All rights reserved. 7 1.1 itojun * 8 1.1 itojun * Redistribution and use in source and binary forms, with or without 9 1.1 itojun * modification, are permitted provided that the following conditions 10 1.1 itojun * are met: 11 1.1 itojun * 1. Redistributions of source code must retain the above copyright 12 1.1 itojun * notice, this list of conditions and the following disclaimer. 13 1.1 itojun * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 itojun * notice, this list of conditions and the following disclaimer in the 15 1.1 itojun * documentation and/or other materials provided with the distribution. 16 1.1 itojun * 3. Neither the name of the project nor the names of its contributors 17 1.1 itojun * may be used to endorse or promote products derived from this software 18 1.1 itojun * without specific prior written permission. 19 1.1 itojun * 20 1.1 itojun * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 1.1 itojun * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 1.1 itojun * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 1.1 itojun * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 1.1 itojun * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 1.1 itojun * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 1.1 itojun * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 1.1 itojun * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 1.1 itojun * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 1.1 itojun * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 1.1 itojun * SUCH DAMAGE. 31 1.1 itojun */ 32 1.1 itojun 33 1.1 itojun /* 34 1.11 itojun * 6to4 interface, based on RFC3056. 35 1.1 itojun * 36 1.1 itojun * 6to4 interface is NOT capable of link-layer (I mean, IPv4) multicasting. 37 1.1 itojun * There is no address mapping defined from IPv6 multicast address to IPv4 38 1.1 itojun * address. Therefore, we do not have IFF_MULTICAST on the interface. 39 1.1 itojun * 40 1.1 itojun * Due to the lack of address mapping for link-local addresses, we cannot 41 1.1 itojun * throw packets toward link-local addresses (fe80::x). Also, we cannot throw 42 1.1 itojun * packets to link-local multicast addresses (ff02::x). 43 1.1 itojun * 44 1.1 itojun * Here are interesting symptoms due to the lack of link-local address: 45 1.1 itojun * 46 1.1 itojun * Unicast routing exchange: 47 1.2 itojun * - RIPng: Impossible. Uses link-local multicast packet toward ff02::9, 48 1.1 itojun * and link-local addresses as nexthop. 49 1.1 itojun * - OSPFv6: Impossible. OSPFv6 assumes that there's link-local address 50 1.1 itojun * assigned to the link, and makes use of them. Also, HELLO packets use 51 1.1 itojun * link-local multicast addresses (ff02::5 and ff02::6). 52 1.1 itojun * - BGP4+: Maybe. You can only use global address as nexthop, and global 53 1.1 itojun * address as TCP endpoint address. 54 1.1 itojun * 55 1.1 itojun * Multicast routing protocols: 56 1.1 itojun * - PIM: Hello packet cannot be used to discover adjacent PIM routers. 57 1.1 itojun * Adjacent PIM routers must be configured manually (is it really spec-wise 58 1.1 itojun * correct thing to do?). 59 1.1 itojun * 60 1.1 itojun * ICMPv6: 61 1.1 itojun * - Redirects cannot be used due to the lack of link-local address. 62 1.1 itojun * 63 1.45 perry * stf interface does not have, and will not need, a link-local address. 64 1.11 itojun * It seems to have no real benefit and does not help the above symptoms much. 65 1.11 itojun * Even if we assign link-locals to interface, we cannot really 66 1.11 itojun * use link-local unicast/multicast on top of 6to4 cloud (since there's no 67 1.11 itojun * encapsulation defined for link-local address), and the above analysis does 68 1.11 itojun * not change. RFC3056 does not mandate the assignment of link-local address 69 1.11 itojun * either. 70 1.1 itojun * 71 1.1 itojun * 6to4 interface has security issues. Refer to 72 1.1 itojun * http://playground.iijlab.net/i-d/draft-itojun-ipv6-transition-abuse-00.txt 73 1.1 itojun * for details. The code tries to filter out some of malicious packets. 74 1.1 itojun * Note that there is no way to be 100% secure. 75 1.1 itojun */ 76 1.21 lukem 77 1.21 lukem #include <sys/cdefs.h> 78 1.109 thorpej __KERNEL_RCSID(0, "$NetBSD: if_stf.c,v 1.109 2022/09/03 02:47:59 thorpej Exp $"); 79 1.1 itojun 80 1.82 pooka #ifdef _KERNEL_OPT 81 1.3 itojun #include "opt_inet.h" 82 1.98 christos #include "stf.h" 83 1.82 pooka #endif 84 1.82 pooka 85 1.80 christos #ifndef INET6 86 1.80 christos #error "pseudo-device stf requires options INET6" 87 1.80 christos #endif 88 1.1 itojun 89 1.1 itojun #include <sys/param.h> 90 1.1 itojun #include <sys/systm.h> 91 1.1 itojun #include <sys/socket.h> 92 1.1 itojun #include <sys/sockio.h> 93 1.1 itojun #include <sys/mbuf.h> 94 1.1 itojun #include <sys/errno.h> 95 1.1 itojun #include <sys/ioctl.h> 96 1.46 tron #include <sys/proc.h> 97 1.5 thorpej #include <sys/queue.h> 98 1.10 itojun #include <sys/syslog.h> 99 1.98 christos #include <sys/device.h> 100 1.98 christos #include <sys/module.h> 101 1.51 elad 102 1.62 ad #include <sys/cpu.h> 103 1.1 itojun 104 1.1 itojun #include <net/if.h> 105 1.1 itojun #include <net/route.h> 106 1.1 itojun #include <net/if_types.h> 107 1.1 itojun #include <net/if_stf.h> 108 1.1 itojun 109 1.1 itojun #include <netinet/in.h> 110 1.1 itojun #include <netinet/in_systm.h> 111 1.1 itojun #include <netinet/ip.h> 112 1.1 itojun #include <netinet/ip_var.h> 113 1.1 itojun #include <netinet/in_var.h> 114 1.1 itojun 115 1.1 itojun #include <netinet/ip6.h> 116 1.1 itojun #include <netinet6/ip6_var.h> 117 1.1 itojun #include <netinet6/in6_var.h> 118 1.1 itojun #include <netinet/ip_ecn.h> 119 1.1 itojun 120 1.1 itojun #include <netinet/ip_encap.h> 121 1.1 itojun 122 1.1 itojun #include <net/bpf.h> 123 1.1 itojun 124 1.81 christos #include "ioconf.h" 125 1.81 christos 126 1.1 itojun #define IN6_IS_ADDR_6TO4(x) (ntohs((x)->s6_addr16[0]) == 0x2002) 127 1.57 dyoung #define GET_V4(x) ((const struct in_addr *)(&(x)->s6_addr16[1])) 128 1.1 itojun 129 1.1 itojun struct stf_softc { 130 1.1 itojun struct ifnet sc_if; /* common area */ 131 1.60 dyoung struct route sc_ro; 132 1.1 itojun const struct encaptab *encap_cookie; 133 1.5 thorpej LIST_ENTRY(stf_softc) sc_list; 134 1.1 itojun }; 135 1.1 itojun 136 1.50 thorpej static LIST_HEAD(, stf_softc) stf_softc_list; 137 1.5 thorpej 138 1.50 thorpej static int stf_clone_create(struct if_clone *, int); 139 1.50 thorpej static int stf_clone_destroy(struct ifnet *); 140 1.5 thorpej 141 1.5 thorpej struct if_clone stf_cloner = 142 1.5 thorpej IF_CLONE_INITIALIZER("stf", stf_clone_create, stf_clone_destroy); 143 1.1 itojun 144 1.99 knakahar static int ip_stf_ttl = STF_TTL; 145 1.1 itojun 146 1.85 riastrad extern struct domain inetdomain; 147 1.85 riastrad 148 1.86 knakahar static const struct encapsw in_stf_encapsw = 149 1.85 riastrad { 150 1.87 knakahar .encapsw4 = { 151 1.86 knakahar .pr_input = in_stf_input, 152 1.86 knakahar .pr_ctlinput = NULL, 153 1.86 knakahar } 154 1.23 itojun }; 155 1.1 itojun 156 1.50 thorpej static int stf_encapcheck(struct mbuf *, int, int, void *); 157 1.50 thorpej static struct in6_ifaddr *stf_getsrcifa6(struct ifnet *); 158 1.57 dyoung static int stf_output(struct ifnet *, struct mbuf *, const struct sockaddr *, 159 1.88 ozaki const struct rtentry *); 160 1.57 dyoung static int isrfc1918addr(const struct in_addr *); 161 1.57 dyoung static int stf_checkaddr4(struct stf_softc *, const struct in_addr *, 162 1.50 thorpej struct ifnet *); 163 1.57 dyoung static int stf_checkaddr6(struct stf_softc *, const struct in6_addr *, 164 1.50 thorpej struct ifnet *); 165 1.67 dyoung static void stf_rtrequest(int, struct rtentry *, const struct rt_addrinfo *); 166 1.58 christos static int stf_ioctl(struct ifnet *, u_long, void *); 167 1.1 itojun 168 1.5 thorpej /* ARGSUSED */ 169 1.1 itojun void 170 1.54 christos stfattach(int count) 171 1.5 thorpej { 172 1.5 thorpej 173 1.98 christos /* 174 1.98 christos * Nothing to do here, initialization is handled by the 175 1.98 christos * module initialization code in stfinit() below). 176 1.98 christos */ 177 1.98 christos } 178 1.98 christos 179 1.98 christos static void 180 1.98 christos stfinit(void) 181 1.98 christos { 182 1.98 christos 183 1.5 thorpej LIST_INIT(&stf_softc_list); 184 1.5 thorpej if_clone_attach(&stf_cloner); 185 1.5 thorpej } 186 1.5 thorpej 187 1.50 thorpej static int 188 1.98 christos stfdetach(void) 189 1.98 christos { 190 1.98 christos int error = 0; 191 1.98 christos 192 1.98 christos if (!LIST_EMPTY(&stf_softc_list)) 193 1.98 christos error = EBUSY; 194 1.98 christos 195 1.98 christos if (error == 0) 196 1.98 christos if_clone_detach(&stf_cloner); 197 1.98 christos 198 1.98 christos return error; 199 1.98 christos } 200 1.98 christos 201 1.98 christos static int 202 1.50 thorpej stf_clone_create(struct if_clone *ifc, int unit) 203 1.1 itojun { 204 1.1 itojun struct stf_softc *sc; 205 1.93 knakahar int error; 206 1.1 itojun 207 1.92 knakahar sc = malloc(sizeof(struct stf_softc), M_DEVBUF, M_WAIT|M_ZERO); 208 1.92 knakahar if_initname(&sc->sc_if, ifc->ifc_name, unit); 209 1.92 knakahar 210 1.93 knakahar error = encap_lock_enter(); 211 1.93 knakahar if (error) { 212 1.93 knakahar free(sc, M_DEVBUF); 213 1.93 knakahar return error; 214 1.93 knakahar } 215 1.93 knakahar 216 1.5 thorpej if (LIST_FIRST(&stf_softc_list) != NULL) { 217 1.5 thorpej /* Only one stf interface is allowed. */ 218 1.92 knakahar encap_lock_exit(); 219 1.92 knakahar free(sc, M_DEVBUF); 220 1.102 msaitoh return EEXIST; 221 1.5 thorpej } 222 1.5 thorpej 223 1.5 thorpej sc->encap_cookie = encap_attach_func(AF_INET, IPPROTO_IPV6, 224 1.86 knakahar stf_encapcheck, &in_stf_encapsw, sc); 225 1.92 knakahar encap_lock_exit(); 226 1.5 thorpej if (sc->encap_cookie == NULL) { 227 1.5 thorpej printf("%s: unable to attach encap\n", if_name(&sc->sc_if)); 228 1.5 thorpej free(sc, M_DEVBUF); 229 1.102 msaitoh return EIO; /* XXX */ 230 1.5 thorpej } 231 1.5 thorpej 232 1.46 tron sc->sc_if.if_mtu = STF_MTU; 233 1.5 thorpej sc->sc_if.if_flags = 0; 234 1.5 thorpej sc->sc_if.if_ioctl = stf_ioctl; 235 1.5 thorpej sc->sc_if.if_output = stf_output; 236 1.5 thorpej sc->sc_if.if_type = IFT_STF; 237 1.7 thorpej sc->sc_if.if_dlt = DLT_NULL; 238 1.108 riastrad if_attach(&sc->sc_if); 239 1.8 thorpej if_alloc_sadl(&sc->sc_if); 240 1.75 joerg bpf_attach(&sc->sc_if, DLT_NULL, sizeof(u_int)); 241 1.5 thorpej LIST_INSERT_HEAD(&stf_softc_list, sc, sc_list); 242 1.102 msaitoh return 0; 243 1.5 thorpej } 244 1.5 thorpej 245 1.50 thorpej static int 246 1.50 thorpej stf_clone_destroy(struct ifnet *ifp) 247 1.5 thorpej { 248 1.5 thorpej struct stf_softc *sc = (void *) ifp; 249 1.5 thorpej 250 1.92 knakahar encap_lock_enter(); 251 1.5 thorpej LIST_REMOVE(sc, sc_list); 252 1.5 thorpej encap_detach(sc->encap_cookie); 253 1.92 knakahar encap_lock_exit(); 254 1.75 joerg bpf_detach(ifp); 255 1.5 thorpej if_detach(ifp); 256 1.60 dyoung rtcache_free(&sc->sc_ro); 257 1.5 thorpej free(sc, M_DEVBUF); 258 1.41 peter 259 1.102 msaitoh return 0; 260 1.1 itojun } 261 1.1 itojun 262 1.1 itojun static int 263 1.54 christos stf_encapcheck(struct mbuf *m, int off, int proto, void *arg) 264 1.1 itojun { 265 1.1 itojun struct ip ip; 266 1.1 itojun struct in6_ifaddr *ia6; 267 1.1 itojun struct stf_softc *sc; 268 1.1 itojun struct in_addr a, b; 269 1.1 itojun 270 1.1 itojun sc = (struct stf_softc *)arg; 271 1.1 itojun if (sc == NULL) 272 1.1 itojun return 0; 273 1.1 itojun 274 1.1 itojun if ((sc->sc_if.if_flags & IFF_UP) == 0) 275 1.1 itojun return 0; 276 1.1 itojun 277 1.14 itojun /* IFF_LINK0 means "no decapsulation" */ 278 1.14 itojun if ((sc->sc_if.if_flags & IFF_LINK0) != 0) 279 1.14 itojun return 0; 280 1.14 itojun 281 1.1 itojun if (proto != IPPROTO_IPV6) 282 1.1 itojun return 0; 283 1.1 itojun 284 1.58 christos m_copydata(m, 0, sizeof(ip), (void *)&ip); 285 1.1 itojun 286 1.1 itojun if (ip.ip_v != 4) 287 1.1 itojun return 0; 288 1.1 itojun 289 1.1 itojun ia6 = stf_getsrcifa6(&sc->sc_if); 290 1.1 itojun if (ia6 == NULL) 291 1.1 itojun return 0; 292 1.1 itojun 293 1.1 itojun /* 294 1.1 itojun * check if IPv4 dst matches the IPv4 address derived from the 295 1.1 itojun * local 6to4 address. 296 1.1 itojun * success on: dst = 10.1.1.1, ia6->ia_addr = 2002:0a01:0101:... 297 1.1 itojun */ 298 1.69 cegger if (memcmp(GET_V4(&ia6->ia_addr.sin6_addr), &ip.ip_dst, 299 1.1 itojun sizeof(ip.ip_dst)) != 0) 300 1.1 itojun return 0; 301 1.1 itojun 302 1.1 itojun /* 303 1.1 itojun * check if IPv4 src matches the IPv4 address derived from the 304 1.1 itojun * local 6to4 address masked by prefixmask. 305 1.1 itojun * success on: src = 10.1.1.1, ia6->ia_addr = 2002:0a00:.../24 306 1.1 itojun * fail on: src = 10.1.1.1, ia6->ia_addr = 2002:0b00:.../24 307 1.1 itojun */ 308 1.17 thorpej memset(&a, 0, sizeof(a)); 309 1.1 itojun a.s_addr = GET_V4(&ia6->ia_addr.sin6_addr)->s_addr; 310 1.1 itojun a.s_addr &= GET_V4(&ia6->ia_prefixmask.sin6_addr)->s_addr; 311 1.1 itojun b = ip.ip_src; 312 1.1 itojun b.s_addr &= GET_V4(&ia6->ia_prefixmask.sin6_addr)->s_addr; 313 1.1 itojun if (a.s_addr != b.s_addr) 314 1.1 itojun return 0; 315 1.1 itojun 316 1.1 itojun /* stf interface makes single side match only */ 317 1.1 itojun return 32; 318 1.1 itojun } 319 1.1 itojun 320 1.1 itojun static struct in6_ifaddr * 321 1.50 thorpej stf_getsrcifa6(struct ifnet *ifp) 322 1.1 itojun { 323 1.44 matt struct ifaddr *ifa; 324 1.1 itojun struct in_ifaddr *ia4; 325 1.1 itojun struct sockaddr_in6 *sin6; 326 1.1 itojun struct in_addr in; 327 1.97 ozaki int s; 328 1.1 itojun 329 1.97 ozaki s = pserialize_read_enter(); 330 1.97 ozaki IFADDR_READER_FOREACH(ifa, ifp) { 331 1.44 matt if (ifa->ifa_addr->sa_family != AF_INET6) 332 1.1 itojun continue; 333 1.44 matt sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 334 1.1 itojun if (!IN6_IS_ADDR_6TO4(&sin6->sin6_addr)) 335 1.1 itojun continue; 336 1.1 itojun 337 1.72 tsutsui memcpy(&in, GET_V4(&sin6->sin6_addr), sizeof(in)); 338 1.96 ozaki ia4 = in_get_ia(in); 339 1.1 itojun if (ia4 == NULL) 340 1.1 itojun continue; 341 1.1 itojun 342 1.97 ozaki pserialize_read_exit(s); 343 1.97 ozaki /* TODO NOMPSAFE */ 344 1.44 matt return (struct in6_ifaddr *)ifa; 345 1.1 itojun } 346 1.97 ozaki pserialize_read_exit(s); 347 1.1 itojun 348 1.1 itojun return NULL; 349 1.1 itojun } 350 1.1 itojun 351 1.1 itojun static int 352 1.57 dyoung stf_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, 353 1.88 ozaki const struct rtentry *rt0) 354 1.1 itojun { 355 1.63 dyoung struct rtentry *rt; 356 1.1 itojun struct stf_softc *sc; 357 1.57 dyoung const struct sockaddr_in6 *dst6; 358 1.57 dyoung const struct in_addr *in4; 359 1.65 matt uint8_t tos; 360 1.1 itojun struct ip *ip; 361 1.1 itojun struct ip6_hdr *ip6; 362 1.1 itojun struct in6_ifaddr *ia6; 363 1.60 dyoung union { 364 1.60 dyoung struct sockaddr dst; 365 1.60 dyoung struct sockaddr_in dst4; 366 1.60 dyoung } u; 367 1.1 itojun 368 1.1 itojun sc = (struct stf_softc*)ifp; 369 1.57 dyoung dst6 = (const struct sockaddr_in6 *)dst; 370 1.1 itojun 371 1.1 itojun /* just in case */ 372 1.1 itojun if ((ifp->if_flags & IFF_UP) == 0) { 373 1.1 itojun m_freem(m); 374 1.1 itojun return ENETDOWN; 375 1.1 itojun } 376 1.1 itojun 377 1.1 itojun /* 378 1.1 itojun * If we don't have an ip4 address that match my inner ip6 address, 379 1.1 itojun * we shouldn't generate output. Without this check, we'll end up 380 1.1 itojun * using wrong IPv4 source. 381 1.1 itojun */ 382 1.1 itojun ia6 = stf_getsrcifa6(ifp); 383 1.1 itojun if (ia6 == NULL) { 384 1.1 itojun m_freem(m); 385 1.107 thorpej if_statinc(ifp, if_oerrors); 386 1.1 itojun return ENETDOWN; 387 1.1 itojun } 388 1.1 itojun 389 1.1 itojun if (m->m_len < sizeof(*ip6)) { 390 1.1 itojun m = m_pullup(m, sizeof(*ip6)); 391 1.26 tron if (m == NULL) { 392 1.107 thorpej if_statinc(ifp, if_oerrors); 393 1.1 itojun return ENOBUFS; 394 1.26 tron } 395 1.1 itojun } 396 1.1 itojun ip6 = mtod(m, struct ip6_hdr *); 397 1.1 itojun tos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; 398 1.1 itojun 399 1.14 itojun /* 400 1.14 itojun * Pickup the right outer dst addr from the list of candidates. 401 1.14 itojun * ip6_dst has priority as it may be able to give us shorter IPv4 hops. 402 1.14 itojun */ 403 1.14 itojun if (IN6_IS_ADDR_6TO4(&ip6->ip6_dst)) 404 1.14 itojun in4 = GET_V4(&ip6->ip6_dst); 405 1.14 itojun else if (IN6_IS_ADDR_6TO4(&dst6->sin6_addr)) 406 1.14 itojun in4 = GET_V4(&dst6->sin6_addr); 407 1.14 itojun else { 408 1.14 itojun m_freem(m); 409 1.107 thorpej if_statinc(ifp, if_oerrors); 410 1.14 itojun return ENETUNREACH; 411 1.14 itojun } 412 1.16 itojun 413 1.105 msaitoh bpf_mtap_af(ifp, AF_INET6, m, BPF_D_OUT); 414 1.14 itojun 415 1.1 itojun M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); 416 1.1 itojun if (m && m->m_len < sizeof(struct ip)) 417 1.1 itojun m = m_pullup(m, sizeof(struct ip)); 418 1.26 tron if (m == NULL) { 419 1.107 thorpej if_statinc(ifp, if_oerrors); 420 1.1 itojun return ENOBUFS; 421 1.26 tron } 422 1.1 itojun ip = mtod(m, struct ip *); 423 1.1 itojun 424 1.17 thorpej memset(ip, 0, sizeof(*ip)); 425 1.1 itojun 426 1.1 itojun bcopy(GET_V4(&((struct sockaddr_in6 *)&ia6->ia_addr)->sin6_addr), 427 1.1 itojun &ip->ip_src, sizeof(ip->ip_src)); 428 1.72 tsutsui memcpy(&ip->ip_dst, in4, sizeof(ip->ip_dst)); 429 1.1 itojun ip->ip_p = IPPROTO_IPV6; 430 1.99 knakahar ip->ip_ttl = ip_stf_ttl; 431 1.29 itojun ip->ip_len = htons(m->m_pkthdr.len); 432 1.1 itojun if (ifp->if_flags & IFF_LINK1) 433 1.1 itojun ip_ecn_ingress(ECN_ALLOWED, &ip->ip_tos, &tos); 434 1.15 itojun else 435 1.15 itojun ip_ecn_ingress(ECN_NOCARE, &ip->ip_tos, &tos); 436 1.1 itojun 437 1.60 dyoung sockaddr_in_init(&u.dst4, &ip->ip_dst, 0); 438 1.63 dyoung if ((rt = rtcache_lookup(&sc->sc_ro, &u.dst)) == NULL) { 439 1.60 dyoung m_freem(m); 440 1.107 thorpej if_statinc(ifp, if_oerrors); 441 1.60 dyoung return ENETUNREACH; 442 1.1 itojun } 443 1.1 itojun 444 1.56 joerg /* If the route constitutes infinite encapsulation, punt. */ 445 1.63 dyoung if (rt->rt_ifp == ifp) { 446 1.100 ozaki rtcache_unref(rt, &sc->sc_ro); 447 1.56 joerg rtcache_free(&sc->sc_ro); 448 1.56 joerg m_freem(m); 449 1.107 thorpej if_statinc(ifp, if_oerrors); 450 1.56 joerg return ENETUNREACH; 451 1.56 joerg } 452 1.100 ozaki rtcache_unref(rt, &sc->sc_ro); 453 1.56 joerg 454 1.107 thorpej if_statadd2(ifp, if_opackets, 1, 455 1.107 thorpej if_obytes, m->m_pkthdr.len - sizeof(struct ip)); 456 1.60 dyoung return ip_output(m, NULL, &sc->sc_ro, 0, NULL, NULL); 457 1.1 itojun } 458 1.1 itojun 459 1.1 itojun static int 460 1.57 dyoung isrfc1918addr(const struct in_addr *in) 461 1.30 itojun { 462 1.30 itojun /* 463 1.30 itojun * returns 1 if private address range: 464 1.30 itojun * 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 465 1.30 itojun */ 466 1.30 itojun if ((ntohl(in->s_addr) & 0xff000000) >> 24 == 10 || 467 1.30 itojun (ntohl(in->s_addr) & 0xfff00000) >> 16 == 172 * 256 + 16 || 468 1.30 itojun (ntohl(in->s_addr) & 0xffff0000) >> 16 == 192 * 256 + 168) 469 1.30 itojun return 1; 470 1.30 itojun 471 1.30 itojun return 0; 472 1.30 itojun } 473 1.30 itojun 474 1.30 itojun static int 475 1.57 dyoung stf_checkaddr4(struct stf_softc *sc, const struct in_addr *in, 476 1.50 thorpej struct ifnet *inifp /*incoming interface*/) 477 1.1 itojun { 478 1.1 itojun struct in_ifaddr *ia4; 479 1.1 itojun 480 1.1 itojun /* 481 1.1 itojun * reject packets with the following address: 482 1.3 itojun * 224.0.0.0/4 0.0.0.0/8 127.0.0.0/8 255.0.0.0/8 483 1.1 itojun */ 484 1.3 itojun if (IN_MULTICAST(in->s_addr)) 485 1.3 itojun return -1; 486 1.3 itojun switch ((ntohl(in->s_addr) & 0xff000000) >> 24) { 487 1.3 itojun case 0: case 127: case 255: 488 1.1 itojun return -1; 489 1.1 itojun } 490 1.24 itojun 491 1.24 itojun /* 492 1.30 itojun * reject packets with private address range. 493 1.30 itojun * (requirement from RFC3056 section 2 1st paragraph) 494 1.24 itojun */ 495 1.30 itojun if (isrfc1918addr(in)) 496 1.24 itojun return -1; 497 1.1 itojun 498 1.1 itojun /* 499 1.32 itojun * reject packet with IPv4 link-local (169.254.0.0/16), 500 1.32 itojun * as suggested in draft-savola-v6ops-6to4-security-00.txt 501 1.32 itojun */ 502 1.32 itojun if (((ntohl(in->s_addr) & 0xff000000) >> 24) == 169 && 503 1.32 itojun ((ntohl(in->s_addr) & 0x00ff0000) >> 16) == 254) 504 1.32 itojun return -1; 505 1.32 itojun 506 1.32 itojun /* 507 1.1 itojun * reject packets with broadcast 508 1.1 itojun */ 509 1.94 ozaki IN_ADDRLIST_READER_FOREACH(ia4) { 510 1.1 itojun if ((ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST) == 0) 511 1.1 itojun continue; 512 1.1 itojun if (in->s_addr == ia4->ia_broadaddr.sin_addr.s_addr) 513 1.1 itojun return -1; 514 1.1 itojun } 515 1.1 itojun 516 1.1 itojun /* 517 1.1 itojun * perform ingress filter 518 1.1 itojun */ 519 1.10 itojun if (sc && (sc->sc_if.if_flags & IFF_LINK2) == 0 && inifp) { 520 1.1 itojun struct sockaddr_in sin; 521 1.1 itojun struct rtentry *rt; 522 1.1 itojun 523 1.17 thorpej memset(&sin, 0, sizeof(sin)); 524 1.1 itojun sin.sin_family = AF_INET; 525 1.1 itojun sin.sin_len = sizeof(struct sockaddr_in); 526 1.1 itojun sin.sin_addr = *in; 527 1.1 itojun rt = rtalloc1((struct sockaddr *)&sin, 0); 528 1.10 itojun if (!rt || rt->rt_ifp != inifp) { 529 1.10 itojun #if 0 530 1.10 itojun log(LOG_WARNING, "%s: packet from 0x%x dropped " 531 1.10 itojun "due to ingress filter\n", if_name(&sc->sc_if), 532 1.65 matt (uint32_t)ntohl(sin.sin_addr.s_addr)); 533 1.10 itojun #endif 534 1.10 itojun if (rt) 535 1.101 ozaki rt_unref(rt); 536 1.1 itojun return -1; 537 1.1 itojun } 538 1.101 ozaki rt_unref(rt); 539 1.1 itojun } 540 1.1 itojun 541 1.1 itojun return 0; 542 1.1 itojun } 543 1.1 itojun 544 1.1 itojun static int 545 1.57 dyoung stf_checkaddr6(struct stf_softc *sc, const struct in6_addr *in6, 546 1.50 thorpej struct ifnet *inifp /*incoming interface*/) 547 1.1 itojun { 548 1.32 itojun 549 1.1 itojun /* 550 1.1 itojun * check 6to4 addresses 551 1.1 itojun */ 552 1.1 itojun if (IN6_IS_ADDR_6TO4(in6)) 553 1.10 itojun return stf_checkaddr4(sc, GET_V4(in6), inifp); 554 1.1 itojun 555 1.1 itojun /* 556 1.1 itojun * reject anything that look suspicious. the test is implemented 557 1.1 itojun * in ip6_input too, but we check here as well to 558 1.1 itojun * (1) reject bad packets earlier, and 559 1.1 itojun * (2) to be safe against future ip6_input change. 560 1.1 itojun */ 561 1.1 itojun if (IN6_IS_ADDR_V4COMPAT(in6) || IN6_IS_ADDR_V4MAPPED(in6)) 562 1.32 itojun return -1; 563 1.32 itojun 564 1.32 itojun /* 565 1.32 itojun * reject link-local and site-local unicast 566 1.32 itojun * as suggested in draft-savola-v6ops-6to4-security-00.txt 567 1.32 itojun */ 568 1.32 itojun if (IN6_IS_ADDR_LINKLOCAL(in6) || IN6_IS_ADDR_SITELOCAL(in6)) 569 1.32 itojun return -1; 570 1.32 itojun 571 1.32 itojun /* 572 1.32 itojun * reject node-local and link-local multicast 573 1.32 itojun * as suggested in draft-savola-v6ops-6to4-security-00.txt 574 1.32 itojun */ 575 1.32 itojun if (IN6_IS_ADDR_MC_NODELOCAL(in6) || IN6_IS_ADDR_MC_LINKLOCAL(in6)) 576 1.1 itojun return -1; 577 1.1 itojun 578 1.1 itojun return 0; 579 1.1 itojun } 580 1.1 itojun 581 1.87 knakahar void 582 1.103 knakahar in_stf_input(struct mbuf *m, int off, int proto, void *eparg) 583 1.1 itojun { 584 1.86 knakahar int s; 585 1.103 knakahar struct stf_softc *sc = eparg; 586 1.1 itojun struct ip *ip; 587 1.1 itojun struct ip6_hdr *ip6; 588 1.65 matt uint8_t otos, itos; 589 1.1 itojun struct ifnet *ifp; 590 1.79 rmind size_t pktlen; 591 1.1 itojun 592 1.103 knakahar KASSERT(sc != NULL); 593 1.103 knakahar 594 1.1 itojun if (proto != IPPROTO_IPV6) { 595 1.1 itojun m_freem(m); 596 1.87 knakahar return; 597 1.1 itojun } 598 1.1 itojun 599 1.1 itojun ip = mtod(m, struct ip *); 600 1.1 itojun 601 1.103 knakahar if ((sc->sc_if.if_flags & IFF_UP) == 0) { 602 1.1 itojun m_freem(m); 603 1.87 knakahar return; 604 1.1 itojun } 605 1.1 itojun 606 1.1 itojun ifp = &sc->sc_if; 607 1.1 itojun 608 1.1 itojun /* 609 1.1 itojun * perform sanity check against outer src/dst. 610 1.1 itojun * for source, perform ingress filter as well. 611 1.1 itojun */ 612 1.10 itojun if (stf_checkaddr4(sc, &ip->ip_dst, NULL) < 0 || 613 1.90 ozaki stf_checkaddr4(sc, &ip->ip_src, m_get_rcvif_NOMPSAFE(m)) < 0) { 614 1.1 itojun m_freem(m); 615 1.87 knakahar return; 616 1.1 itojun } 617 1.1 itojun 618 1.1 itojun otos = ip->ip_tos; 619 1.1 itojun m_adj(m, off); 620 1.1 itojun 621 1.1 itojun if (m->m_len < sizeof(*ip6)) { 622 1.1 itojun m = m_pullup(m, sizeof(*ip6)); 623 1.1 itojun if (!m) 624 1.87 knakahar return; 625 1.1 itojun } 626 1.1 itojun ip6 = mtod(m, struct ip6_hdr *); 627 1.1 itojun 628 1.1 itojun /* 629 1.1 itojun * perform sanity check against inner src/dst. 630 1.1 itojun * for source, perform ingress filter as well. 631 1.1 itojun */ 632 1.10 itojun if (stf_checkaddr6(sc, &ip6->ip6_dst, NULL) < 0 || 633 1.90 ozaki stf_checkaddr6(sc, &ip6->ip6_src, m_get_rcvif_NOMPSAFE(m)) < 0) { 634 1.1 itojun m_freem(m); 635 1.87 knakahar return; 636 1.1 itojun } 637 1.1 itojun 638 1.1 itojun itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; 639 1.1 itojun if ((ifp->if_flags & IFF_LINK1) != 0) 640 1.1 itojun ip_ecn_egress(ECN_ALLOWED, &otos, &itos); 641 1.15 itojun else 642 1.15 itojun ip_ecn_egress(ECN_NOCARE, &otos, &itos); 643 1.1 itojun ip6->ip6_flow &= ~htonl(0xff << 20); 644 1.65 matt ip6->ip6_flow |= htonl((uint32_t)itos << 20); 645 1.1 itojun 646 1.79 rmind pktlen = m->m_pkthdr.len; 647 1.89 ozaki m_set_rcvif(m, ifp); 648 1.45 perry 649 1.105 msaitoh bpf_mtap_af(ifp, AF_INET6, m, BPF_D_IN); 650 1.1 itojun 651 1.1 itojun /* 652 1.1 itojun * Put the packet to the network layer input queue according to the 653 1.1 itojun * specified address family. 654 1.1 itojun * See net/if_gif.c for possible issues with packet processing 655 1.1 itojun * reorder due to extra queueing. 656 1.1 itojun */ 657 1.1 itojun 658 1.13 thorpej s = splnet(); 659 1.79 rmind if (__predict_true(pktq_enqueue(ip6_pktq, m, 0))) { 660 1.107 thorpej if_statadd2(ifp, if_ipackets, 1, if_ibytes, pktlen); 661 1.79 rmind } else { 662 1.1 itojun m_freem(m); 663 1.1 itojun } 664 1.1 itojun splx(s); 665 1.86 knakahar 666 1.87 knakahar return; 667 1.1 itojun } 668 1.1 itojun 669 1.1 itojun /* ARGSUSED */ 670 1.1 itojun static void 671 1.54 christos stf_rtrequest(int cmd, struct rtentry *rt, 672 1.67 dyoung const struct rt_addrinfo *info) 673 1.1 itojun { 674 1.46 tron if (rt != NULL) { 675 1.46 tron struct stf_softc *sc; 676 1.1 itojun 677 1.46 tron sc = LIST_FIRST(&stf_softc_list); 678 1.46 tron rt->rt_rmx.rmx_mtu = (sc != NULL) ? sc->sc_if.if_mtu : STF_MTU; 679 1.46 tron } 680 1.1 itojun } 681 1.1 itojun 682 1.1 itojun static int 683 1.58 christos stf_ioctl(struct ifnet *ifp, u_long cmd, void *data) 684 1.1 itojun { 685 1.46 tron struct ifaddr *ifa; 686 1.64 dyoung struct ifreq *ifr = data; 687 1.46 tron struct sockaddr_in6 *sin6; 688 1.46 tron int error; 689 1.1 itojun 690 1.1 itojun error = 0; 691 1.1 itojun switch (cmd) { 692 1.68 dyoung case SIOCINITIFADDR: 693 1.1 itojun ifa = (struct ifaddr *)data; 694 1.1 itojun if (ifa == NULL || ifa->ifa_addr->sa_family != AF_INET6) { 695 1.1 itojun error = EAFNOSUPPORT; 696 1.1 itojun break; 697 1.1 itojun } 698 1.1 itojun sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 699 1.30 itojun if (IN6_IS_ADDR_6TO4(&sin6->sin6_addr) && 700 1.30 itojun !isrfc1918addr(GET_V4(&sin6->sin6_addr))) { 701 1.1 itojun ifa->ifa_rtrequest = stf_rtrequest; 702 1.1 itojun ifp->if_flags |= IFF_UP; 703 1.1 itojun } else 704 1.1 itojun error = EINVAL; 705 1.1 itojun break; 706 1.1 itojun 707 1.1 itojun case SIOCADDMULTI: 708 1.1 itojun case SIOCDELMULTI: 709 1.61 dyoung if (ifr != NULL && 710 1.61 dyoung ifreq_getaddr(cmd, ifr)->sa_family == AF_INET6) 711 1.1 itojun ; 712 1.1 itojun else 713 1.1 itojun error = EAFNOSUPPORT; 714 1.1 itojun break; 715 1.1 itojun 716 1.46 tron case SIOCSIFMTU: 717 1.64 dyoung if (ifr->ifr_mtu < STF_MTU_MIN || ifr->ifr_mtu > STF_MTU_MAX) 718 1.46 tron return EINVAL; 719 1.64 dyoung else if ((error = ifioctl_common(ifp, cmd, data)) == ENETRESET) 720 1.64 dyoung error = 0; 721 1.46 tron break; 722 1.46 tron 723 1.1 itojun default: 724 1.68 dyoung error = ifioctl_common(ifp, cmd, data); 725 1.1 itojun break; 726 1.1 itojun } 727 1.1 itojun 728 1.1 itojun return error; 729 1.1 itojun } 730 1.98 christos 731 1.98 christos /* 732 1.98 christos * Module infrastructure 733 1.98 christos */ 734 1.98 christos #include "if_module.h" 735 1.98 christos 736 1.106 pgoyette IF_MODULE(MODULE_CLASS_DRIVER, stf, NULL) 737