1 /* $NetBSD: if_stf.c,v 1.3 2000/05/14 03:44:02 itojun Exp $ */ 2 /* $KAME: if_stf.c,v 1.37 2000/05/05 11:00:55 sumikawa Exp $ */ 3 4 /* 5 * Copyright (C) 2000 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 /* 34 * 6to4 interface, based on draft-ietf-ngtrans-6to4-03.txt. 35 * 36 * 6to4 interface is NOT capable of link-layer (I mean, IPv4) multicasting. 37 * There is no address mapping defined from IPv6 multicast address to IPv4 38 * address. Therefore, we do not have IFF_MULTICAST on the interface. 39 * 40 * Due to the lack of address mapping for link-local addresses, we cannot 41 * throw packets toward link-local addresses (fe80::x). Also, we cannot throw 42 * packets to link-local multicast addresses (ff02::x). 43 * 44 * Here are interesting symptoms due to the lack of link-local address: 45 * 46 * Unicast routing exchange: 47 * - RIPng: Impossible. Uses link-local multicast packet toward ff02::9, 48 * and link-local addresses as nexthop. 49 * - OSPFv6: Impossible. OSPFv6 assumes that there's link-local address 50 * assigned to the link, and makes use of them. Also, HELLO packets use 51 * link-local multicast addresses (ff02::5 and ff02::6). 52 * - BGP4+: Maybe. You can only use global address as nexthop, and global 53 * address as TCP endpoint address. 54 * 55 * Multicast routing protocols: 56 * - PIM: Hello packet cannot be used to discover adjacent PIM routers. 57 * Adjacent PIM routers must be configured manually (is it really spec-wise 58 * correct thing to do?). 59 * 60 * ICMPv6: 61 * - Redirects cannot be used due to the lack of link-local address. 62 * 63 * 04 draft suggests to have link-local address onto 6to4 interface. 64 * However, it seems to have no real use and does not help the above symptom 65 * much. Even if we assign link-locals to interface, we cannot really 66 * use link-local unicast/multicast on top of 6to4 cloud, and the above 67 * analysis does not change. 68 * 69 * 6to4 interface has security issues. Refer to 70 * http://playground.iijlab.net/i-d/draft-itojun-ipv6-transition-abuse-00.txt 71 * for details. The code tries to filter out some of malicious packets. 72 * Note that there is no way to be 100% secure. 73 */ 74 75 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 76 #include "opt_inet.h" 77 #include "opt_inet6.h" 78 #endif 79 #ifdef __NetBSD__ 80 #include "opt_inet.h" 81 #endif 82 83 #include <sys/param.h> 84 #include <sys/systm.h> 85 #include <sys/socket.h> 86 #include <sys/sockio.h> 87 #include <sys/mbuf.h> 88 #include <sys/errno.h> 89 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) 90 #include <sys/ioctl.h> 91 #endif 92 #include <sys/protosw.h> 93 #ifdef __FreeBSD__ 94 #include <sys/kernel.h> 95 #endif 96 #include <machine/cpu.h> 97 98 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 99 #include <sys/malloc.h> 100 #endif 101 102 #include <net/if.h> 103 #include <net/route.h> 104 #include <net/netisr.h> 105 #include <net/if_types.h> 106 #include <net/if_stf.h> 107 108 #include <netinet/in.h> 109 #include <netinet/in_systm.h> 110 #include <netinet/ip.h> 111 #include <netinet/ip_var.h> 112 #include <netinet/in_var.h> 113 114 #include <netinet/ip6.h> 115 #include <netinet6/ip6_var.h> 116 #include <netinet6/in6_gif.h> 117 #include <netinet6/in6_var.h> 118 #include <netinet/ip_ecn.h> 119 120 #include <netinet/ip_encap.h> 121 122 #include <machine/stdarg.h> 123 124 #include <net/net_osdep.h> 125 126 #if defined(__FreeBSD__) && __FreeBSD__ >= 4 127 #include "bpf.h" 128 #define NBPFILTER NBPF 129 #else 130 #include "bpfilter.h" 131 #endif 132 #include "stf.h" 133 #include "gif.h" /*XXX*/ 134 135 #if NBPFILTER > 0 136 #include <net/bpf.h> 137 #endif 138 139 #if NGIF > 0 140 #include <net/if_gif.h> 141 #endif 142 143 #if NSTF > 0 144 #if NSTF != 1 145 # error only single stf interface allowed 146 #endif 147 148 #define IN6_IS_ADDR_6TO4(x) (ntohs((x)->s6_addr16[0]) == 0x2002) 149 #define GET_V4(x) ((struct in_addr *)(&(x)->s6_addr16[1])) 150 151 struct stf_softc { 152 struct ifnet sc_if; /* common area */ 153 union { 154 struct route __sc_ro4; 155 struct route_in6 __sc_ro6; /* just for safety */ 156 } __sc_ro46; 157 #define sc_ro __sc_ro46.__sc_ro4 158 const struct encaptab *encap_cookie; 159 }; 160 161 static struct stf_softc *stf; 162 static int nstf; 163 164 #if NGIF > 0 165 extern int ip_gif_ttl; /*XXX*/ 166 #else 167 static int ip_gif_ttl = 40; /*XXX*/ 168 #endif 169 170 extern struct protosw in_stf_protosw; 171 172 #ifdef __FreeBSD__ 173 void stfattach __P((void *)); 174 #else 175 void stfattach __P((int)); 176 #endif 177 static int stf_encapcheck __P((const struct mbuf *, int, int, void *)); 178 static struct in6_ifaddr *stf_getsrcifa6 __P((struct ifnet *)); 179 static int stf_output __P((struct ifnet *, struct mbuf *, struct sockaddr *, 180 struct rtentry *)); 181 static int stf_checkaddr4 __P((struct in_addr *, struct ifnet *)); 182 static int stf_checkaddr6 __P((struct in6_addr *, struct ifnet *)); 183 #if defined(__bsdi__) && _BSDI_VERSION >= 199802 184 static void stf_rtrequest __P((int, struct rtentry *, struct rt_addrinfo *)); 185 #else 186 static void stf_rtrequest __P((int, struct rtentry *, struct sockaddr *)); 187 #endif 188 #if defined(__FreeBSD__) && __FreeBSD__ < 3 189 static int stf_ioctl __P((struct ifnet *, int, caddr_t)); 190 #else 191 static int stf_ioctl __P((struct ifnet *, u_long, caddr_t)); 192 #endif 193 194 void 195 stfattach(dummy) 196 #ifdef __FreeBSD__ 197 void *dummy; 198 #else 199 int dummy; 200 #endif 201 { 202 struct stf_softc *sc; 203 int i; 204 const struct encaptab *p; 205 206 #ifdef __NetBSD__ 207 nstf = dummy; 208 #else 209 nstf = NSTF; 210 #endif 211 stf = malloc(nstf * sizeof(struct stf_softc), M_DEVBUF, M_WAIT); 212 bzero(stf, nstf * sizeof(struct stf_softc)); 213 sc = stf; 214 215 /* XXX just in case... */ 216 for (i = 0; i < nstf; i++) { 217 sc = &stf[i]; 218 bzero(sc, sizeof(*sc)); 219 #if defined(__NetBSD__) || defined(__OpenBSD__) 220 sprintf(sc->sc_if.if_xname, "stf%d", i); 221 #else 222 sc->sc_if.if_name = "stf"; 223 sc->sc_if.if_unit = i; 224 #endif 225 226 p = encap_attach_func(AF_INET, IPPROTO_IPV6, stf_encapcheck, 227 &in_stf_protosw, sc); 228 if (p == NULL) { 229 printf("%s: attach failed\n", if_name(&sc->sc_if)); 230 continue; 231 } 232 sc->encap_cookie = p; 233 234 sc->sc_if.if_mtu = IPV6_MMTU; 235 sc->sc_if.if_flags = 0; 236 sc->sc_if.if_ioctl = stf_ioctl; 237 sc->sc_if.if_output = stf_output; 238 sc->sc_if.if_type = IFT_STF; 239 #if defined(__FreeBSD__) && __FreeBSD__ >= 4 240 sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN; 241 #endif 242 if_attach(&sc->sc_if); 243 #if NBPFILTER > 0 244 #ifdef HAVE_OLD_BPF 245 bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int)); 246 #else 247 bpfattach(&sc->sc_if.if_bpf, &sc->sc_if, DLT_NULL, sizeof(u_int)); 248 #endif 249 #endif 250 } 251 } 252 253 #ifdef __FreeBSD__ 254 PSEUDO_SET(stfattach, if_stf); 255 #endif 256 257 static int 258 stf_encapcheck(m, off, proto, arg) 259 const struct mbuf *m; 260 int off; 261 int proto; 262 void *arg; 263 { 264 struct ip ip; 265 struct in6_ifaddr *ia6; 266 struct stf_softc *sc; 267 struct in_addr a, b; 268 269 sc = (struct stf_softc *)arg; 270 if (sc == NULL) 271 return 0; 272 273 if ((sc->sc_if.if_flags & IFF_UP) == 0) 274 return 0; 275 276 if (proto != IPPROTO_IPV6) 277 return 0; 278 279 /* LINTED const cast */ 280 m_copydata((struct mbuf *)m, 0, sizeof(ip), (caddr_t)&ip); 281 282 if (ip.ip_v != 4) 283 return 0; 284 285 ia6 = stf_getsrcifa6(&sc->sc_if); 286 if (ia6 == NULL) 287 return 0; 288 289 /* 290 * check if IPv4 dst matches the IPv4 address derived from the 291 * local 6to4 address. 292 * success on: dst = 10.1.1.1, ia6->ia_addr = 2002:0a01:0101:... 293 */ 294 if (bcmp(GET_V4(&ia6->ia_addr.sin6_addr), &ip.ip_dst, 295 sizeof(ip.ip_dst)) != 0) 296 return 0; 297 298 /* 299 * check if IPv4 src matches the IPv4 address derived from the 300 * local 6to4 address masked by prefixmask. 301 * success on: src = 10.1.1.1, ia6->ia_addr = 2002:0a00:.../24 302 * fail on: src = 10.1.1.1, ia6->ia_addr = 2002:0b00:.../24 303 */ 304 bzero(&a, sizeof(a)); 305 a.s_addr = GET_V4(&ia6->ia_addr.sin6_addr)->s_addr; 306 a.s_addr &= GET_V4(&ia6->ia_prefixmask.sin6_addr)->s_addr; 307 b = ip.ip_src; 308 b.s_addr &= GET_V4(&ia6->ia_prefixmask.sin6_addr)->s_addr; 309 if (a.s_addr != b.s_addr) 310 return 0; 311 312 /* stf interface makes single side match only */ 313 return 32; 314 } 315 316 static struct in6_ifaddr * 317 stf_getsrcifa6(ifp) 318 struct ifnet *ifp; 319 { 320 struct ifaddr *ia; 321 struct in_ifaddr *ia4; 322 struct sockaddr_in6 *sin6; 323 struct in_addr in; 324 325 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) 326 for (ia = ifp->if_addrlist; ia; ia = ia->ifa_next) 327 #else 328 for (ia = ifp->if_addrlist.tqh_first; 329 ia; 330 ia = ia->ifa_list.tqe_next) 331 #endif 332 { 333 if (ia->ifa_addr == NULL) 334 continue; 335 if (ia->ifa_addr->sa_family != AF_INET6) 336 continue; 337 sin6 = (struct sockaddr_in6 *)ia->ifa_addr; 338 if (!IN6_IS_ADDR_6TO4(&sin6->sin6_addr)) 339 continue; 340 341 bcopy(GET_V4(&sin6->sin6_addr), &in, sizeof(in)); 342 #ifdef __NetBSD__ 343 INADDR_TO_IA(in, ia4); 344 #else 345 #ifdef __OpenBSD__ 346 for (ia4 = in_ifaddr.tqh_first; 347 ia4; 348 ia4 = ia4->ia_list.tqe_next) 349 #elif defined(__FreeBSD__) && __FreeBSD__ >= 3 350 for (ia4 = TAILQ_FIRST(&in_ifaddrhead); 351 ia4; 352 ia4 = TAILQ_NEXT(ia4, ia_link)) 353 #else 354 for (ia4 = in_ifaddr; ia4 != NULL; ia4 = ia4->ia_next) 355 #endif 356 { 357 if (ia4->ia_addr.sin_addr.s_addr == in.s_addr) 358 break; 359 } 360 #endif 361 if (ia4 == NULL) 362 continue; 363 364 return (struct in6_ifaddr *)ia; 365 } 366 367 return NULL; 368 } 369 370 static int 371 stf_output(ifp, m, dst, rt) 372 struct ifnet *ifp; 373 struct mbuf *m; 374 struct sockaddr *dst; 375 struct rtentry *rt; 376 { 377 struct stf_softc *sc; 378 struct sockaddr_in6 *dst6; 379 struct sockaddr_in *dst4; 380 u_int8_t tos; 381 struct ip *ip; 382 struct ip6_hdr *ip6; 383 struct in6_ifaddr *ia6; 384 385 sc = (struct stf_softc*)ifp; 386 dst6 = (struct sockaddr_in6 *)dst; 387 388 /* just in case */ 389 if ((ifp->if_flags & IFF_UP) == 0) { 390 m_freem(m); 391 return ENETDOWN; 392 } 393 394 /* 395 * If we don't have an ip4 address that match my inner ip6 address, 396 * we shouldn't generate output. Without this check, we'll end up 397 * using wrong IPv4 source. 398 */ 399 ia6 = stf_getsrcifa6(ifp); 400 if (ia6 == NULL) { 401 m_freem(m); 402 return ENETDOWN; 403 } 404 405 if (m->m_len < sizeof(*ip6)) { 406 m = m_pullup(m, sizeof(*ip6)); 407 if (!m) 408 return ENOBUFS; 409 } 410 ip6 = mtod(m, struct ip6_hdr *); 411 tos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; 412 413 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); 414 if (m && m->m_len < sizeof(struct ip)) 415 m = m_pullup(m, sizeof(struct ip)); 416 if (m == NULL) 417 return ENOBUFS; 418 ip = mtod(m, struct ip *); 419 420 bzero(ip, sizeof(*ip)); 421 422 bcopy(GET_V4(&((struct sockaddr_in6 *)&ia6->ia_addr)->sin6_addr), 423 &ip->ip_src, sizeof(ip->ip_src)); 424 bcopy(GET_V4(&dst6->sin6_addr), &ip->ip_dst, sizeof(ip->ip_dst)); 425 ip->ip_p = IPPROTO_IPV6; 426 ip->ip_ttl = ip_gif_ttl; /*XXX*/ 427 ip->ip_len = m->m_pkthdr.len; /*host order*/ 428 if (ifp->if_flags & IFF_LINK1) 429 ip_ecn_ingress(ECN_ALLOWED, &ip->ip_tos, &tos); 430 431 dst4 = (struct sockaddr_in *)&sc->sc_ro.ro_dst; 432 if (dst4->sin_family != AF_INET || 433 bcmp(&dst4->sin_addr, &ip->ip_dst, sizeof(ip->ip_dst)) != 0) { 434 /* cache route doesn't match */ 435 dst4->sin_family = AF_INET; 436 dst4->sin_len = sizeof(struct sockaddr_in); 437 bcopy(&ip->ip_dst, &dst4->sin_addr, sizeof(dst4->sin_addr)); 438 if (sc->sc_ro.ro_rt) { 439 RTFREE(sc->sc_ro.ro_rt); 440 sc->sc_ro.ro_rt = NULL; 441 } 442 } 443 444 if (sc->sc_ro.ro_rt == NULL) { 445 rtalloc(&sc->sc_ro); 446 if (sc->sc_ro.ro_rt == NULL) { 447 m_freem(m); 448 return ENETUNREACH; 449 } 450 } 451 452 #ifndef __OpenBSD__ 453 return ip_output(m, NULL, &sc->sc_ro, 0, NULL); 454 #else 455 return ip_output(m, NULL, &sc->sc_ro, 0, NULL, NULL); 456 #endif 457 } 458 459 static int 460 stf_checkaddr4(in, ifp) 461 struct in_addr *in; 462 struct ifnet *ifp; /* incoming interface */ 463 { 464 struct in_ifaddr *ia4; 465 466 /* 467 * reject packets with the following address: 468 * 224.0.0.0/4 0.0.0.0/8 127.0.0.0/8 255.0.0.0/8 469 */ 470 if (IN_MULTICAST(in->s_addr)) 471 return -1; 472 switch ((ntohl(in->s_addr) & 0xff000000) >> 24) { 473 case 0: case 127: case 255: 474 return -1; 475 } 476 477 /* 478 * reject packets with broadcast 479 */ 480 #if defined(__OpenBSD__) || defined(__NetBSD__) 481 for (ia4 = in_ifaddr.tqh_first; ia4; ia4 = ia4->ia_list.tqe_next) 482 #elif defined(__FreeBSD__) && __FreeBSD__ >= 3 483 for (ia4 = TAILQ_FIRST(&in_ifaddrhead); 484 ia4; 485 ia4 = TAILQ_NEXT(ia4, ia_link)) 486 #else 487 for (ia4 = in_ifaddr; ia4 != NULL; ia4 = ia4->ia_next) 488 #endif 489 { 490 if ((ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST) == 0) 491 continue; 492 if (in->s_addr == ia4->ia_broadaddr.sin_addr.s_addr) 493 return -1; 494 } 495 496 /* 497 * perform ingress filter 498 */ 499 if (ifp) { 500 struct sockaddr_in sin; 501 struct rtentry *rt; 502 503 bzero(&sin, sizeof(sin)); 504 sin.sin_family = AF_INET; 505 sin.sin_len = sizeof(struct sockaddr_in); 506 sin.sin_addr = *in; 507 #ifdef __FreeBSD__ 508 rt = rtalloc1((struct sockaddr *)&sin, 0, 0UL); 509 #else 510 rt = rtalloc1((struct sockaddr *)&sin, 0); 511 #endif 512 if (!rt) 513 return -1; 514 if (rt->rt_ifp != ifp) { 515 rtfree(rt); 516 return -1; 517 } 518 rtfree(rt); 519 } 520 521 return 0; 522 } 523 524 static int 525 stf_checkaddr6(in6, ifp) 526 struct in6_addr *in6; 527 struct ifnet *ifp; /* incoming interface */ 528 { 529 /* 530 * check 6to4 addresses 531 */ 532 if (IN6_IS_ADDR_6TO4(in6)) 533 return stf_checkaddr4(GET_V4(in6), ifp); 534 535 /* 536 * reject anything that look suspicious. the test is implemented 537 * in ip6_input too, but we check here as well to 538 * (1) reject bad packets earlier, and 539 * (2) to be safe against future ip6_input change. 540 */ 541 if (IN6_IS_ADDR_V4COMPAT(in6) || IN6_IS_ADDR_V4MAPPED(in6)) 542 return -1; 543 544 return 0; 545 } 546 547 void 548 #if __STDC__ 549 in_stf_input(struct mbuf *m, ...) 550 #else 551 in_stf_input(m, va_alist) 552 register struct mbuf *m; 553 #endif 554 { 555 int off, proto; 556 struct stf_softc *sc; 557 struct ip *ip; 558 struct ip6_hdr *ip6; 559 u_int8_t otos, itos; 560 int s, isr; 561 struct ifqueue *ifq = NULL; 562 struct ifnet *ifp; 563 va_list ap; 564 565 va_start(ap, m); 566 off = va_arg(ap, int); 567 proto = va_arg(ap, int); 568 va_end(ap); 569 570 if (proto != IPPROTO_IPV6) { 571 m_freem(m); 572 return; 573 } 574 575 ip = mtod(m, struct ip *); 576 577 sc = (struct stf_softc *)encap_getarg(m); 578 579 if (sc == NULL || (sc->sc_if.if_flags & IFF_UP) == 0) { 580 m_freem(m); 581 return; 582 } 583 584 ifp = &sc->sc_if; 585 586 /* 587 * perform sanity check against outer src/dst. 588 * for source, perform ingress filter as well. 589 */ 590 if (stf_checkaddr4(&ip->ip_dst, NULL) < 0 || 591 stf_checkaddr4(&ip->ip_src, m->m_pkthdr.rcvif) < 0) { 592 m_freem(m); 593 return; 594 } 595 596 otos = ip->ip_tos; 597 m_adj(m, off); 598 599 if (m->m_len < sizeof(*ip6)) { 600 m = m_pullup(m, sizeof(*ip6)); 601 if (!m) 602 return; 603 } 604 ip6 = mtod(m, struct ip6_hdr *); 605 606 /* 607 * perform sanity check against inner src/dst. 608 * for source, perform ingress filter as well. 609 */ 610 if (stf_checkaddr6(&ip6->ip6_dst, NULL) < 0 || 611 stf_checkaddr6(&ip6->ip6_src, m->m_pkthdr.rcvif) < 0) { 612 m_freem(m); 613 return; 614 } 615 616 itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; 617 if ((ifp->if_flags & IFF_LINK1) != 0) 618 ip_ecn_egress(ECN_ALLOWED, &otos, &itos); 619 ip6->ip6_flow &= ~htonl(0xff << 20); 620 ip6->ip6_flow |= htonl((u_int32_t)itos << 20); 621 622 m->m_pkthdr.rcvif = ifp; 623 624 #if NBPFILTER > 0 625 if (ifp->if_bpf) { 626 /* 627 * We need to prepend the address family as 628 * a four byte field. Cons up a dummy header 629 * to pacify bpf. This is safe because bpf 630 * will only read from the mbuf (i.e., it won't 631 * try to free it or keep a pointer a to it). 632 */ 633 struct mbuf m0; 634 u_int af = AF_INET6; 635 636 m0.m_next = m; 637 m0.m_len = 4; 638 m0.m_data = (char *)⁡ 639 640 #ifdef HAVE_OLD_BPF 641 bpf_mtap(ifp, &m0); 642 #else 643 bpf_mtap(ifp->if_bpf, &m0); 644 #endif 645 } 646 #endif /*NBPFILTER > 0*/ 647 648 /* 649 * Put the packet to the network layer input queue according to the 650 * specified address family. 651 * See net/if_gif.c for possible issues with packet processing 652 * reorder due to extra queueing. 653 */ 654 ifq = &ip6intrq; 655 isr = NETISR_IPV6; 656 657 s = splimp(); 658 if (IF_QFULL(ifq)) { 659 IF_DROP(ifq); /* update statistics */ 660 m_freem(m); 661 splx(s); 662 return; 663 } 664 IF_ENQUEUE(ifq, m); 665 schednetisr(isr); 666 ifp->if_ipackets++; 667 ifp->if_ibytes += m->m_pkthdr.len; 668 splx(s); 669 } 670 671 /* ARGSUSED */ 672 static void 673 stf_rtrequest(cmd, rt, sa) 674 int cmd; 675 struct rtentry *rt; 676 #if defined(__bsdi__) && _BSDI_VERSION >= 199802 677 struct rt_addrinfo *sa; 678 #else 679 struct sockaddr *sa; 680 #endif 681 { 682 683 if (rt) 684 rt->rt_rmx.rmx_mtu = IPV6_MMTU; 685 } 686 687 static int 688 stf_ioctl(ifp, cmd, data) 689 struct ifnet *ifp; 690 #if defined(__FreeBSD__) && __FreeBSD__ < 3 691 int cmd; 692 #else 693 u_long cmd; 694 #endif 695 caddr_t data; 696 { 697 struct ifaddr *ifa; 698 struct ifreq *ifr; 699 struct sockaddr_in6 *sin6; 700 int error; 701 702 error = 0; 703 switch (cmd) { 704 case SIOCSIFADDR: 705 ifa = (struct ifaddr *)data; 706 if (ifa == NULL || ifa->ifa_addr->sa_family != AF_INET6) { 707 error = EAFNOSUPPORT; 708 break; 709 } 710 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 711 if (IN6_IS_ADDR_6TO4(&sin6->sin6_addr)) { 712 ifa->ifa_rtrequest = stf_rtrequest; 713 ifp->if_flags |= IFF_UP; 714 } else 715 error = EINVAL; 716 break; 717 718 case SIOCADDMULTI: 719 case SIOCDELMULTI: 720 ifr = (struct ifreq *)data; 721 if (ifr && ifr->ifr_addr.sa_family == AF_INET6) 722 ; 723 else 724 error = EAFNOSUPPORT; 725 break; 726 727 default: 728 error = EINVAL; 729 break; 730 } 731 732 return error; 733 } 734 735 #endif /* NSTF > 0 */ 736