1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * Copyright (c) 2018 Andrey V. Elsukov <ae@FreeBSD.org> 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 * $KAME: if_gif.c,v 1.87 2001/10/19 08:50:27 itojun Exp $ 33 */ 34 35 #include <sys/cdefs.h> 36 __FBSDID("$FreeBSD$"); 37 38 #include "opt_inet.h" 39 #include "opt_inet6.h" 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/kernel.h> 44 #include <sys/lock.h> 45 #include <sys/malloc.h> 46 #include <sys/mbuf.h> 47 #include <sys/module.h> 48 #include <sys/rmlock.h> 49 #include <sys/socket.h> 50 #include <sys/sockio.h> 51 #include <sys/sx.h> 52 #include <sys/errno.h> 53 #include <sys/time.h> 54 #include <sys/sysctl.h> 55 #include <sys/syslog.h> 56 #include <sys/priv.h> 57 #include <sys/proc.h> 58 #include <sys/conf.h> 59 #include <machine/cpu.h> 60 61 #include <net/if.h> 62 #include <net/if_var.h> 63 #include <net/if_private.h> 64 #include <net/if_clone.h> 65 #include <net/if_types.h> 66 #include <net/netisr.h> 67 #include <net/route.h> 68 #include <net/bpf.h> 69 #include <net/vnet.h> 70 71 #include <netinet/in.h> 72 #include <netinet/in_systm.h> 73 #include <netinet/ip.h> 74 #include <netinet/ip_ecn.h> 75 #ifdef INET 76 #include <netinet/in_var.h> 77 #include <netinet/ip_var.h> 78 #endif /* INET */ 79 80 #ifdef INET6 81 #ifndef INET 82 #include <netinet/in.h> 83 #endif 84 #include <netinet6/in6_var.h> 85 #include <netinet/ip6.h> 86 #include <netinet6/ip6_ecn.h> 87 #include <netinet6/ip6_var.h> 88 #endif /* INET6 */ 89 90 #include <netinet/ip_encap.h> 91 #include <net/ethernet.h> 92 #include <net/if_bridgevar.h> 93 #include <net/if_gif.h> 94 95 #include <security/mac/mac_framework.h> 96 97 static const char gifname[] = "gif"; 98 99 MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface"); 100 static struct sx gif_ioctl_sx; 101 SX_SYSINIT(gif_ioctl_sx, &gif_ioctl_sx, "gif_ioctl"); 102 103 void (*ng_gif_input_p)(struct ifnet *ifp, struct mbuf **mp, int af); 104 void (*ng_gif_input_orphan_p)(struct ifnet *ifp, struct mbuf *m, int af); 105 void (*ng_gif_attach_p)(struct ifnet *ifp); 106 void (*ng_gif_detach_p)(struct ifnet *ifp); 107 108 #ifdef VIMAGE 109 static void gif_reassign(struct ifnet *, struct vnet *, char *); 110 #endif 111 static void gif_delete_tunnel(struct gif_softc *); 112 static int gif_ioctl(struct ifnet *, u_long, caddr_t); 113 static int gif_transmit(struct ifnet *, struct mbuf *); 114 static void gif_qflush(struct ifnet *); 115 static int gif_clone_create(struct if_clone *, int, caddr_t); 116 static void gif_clone_destroy(struct ifnet *); 117 VNET_DEFINE_STATIC(struct if_clone *, gif_cloner); 118 #define V_gif_cloner VNET(gif_cloner) 119 120 SYSCTL_DECL(_net_link); 121 static SYSCTL_NODE(_net_link, IFT_GIF, gif, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 122 "Generic Tunnel Interface"); 123 #ifndef MAX_GIF_NEST 124 /* 125 * This macro controls the default upper limitation on nesting of gif tunnels. 126 * Since, setting a large value to this macro with a careless configuration 127 * may introduce system crash, we don't allow any nestings by default. 128 * If you need to configure nested gif tunnels, you can define this macro 129 * in your kernel configuration file. However, if you do so, please be 130 * careful to configure the tunnels so that it won't make a loop. 131 */ 132 #define MAX_GIF_NEST 1 133 #endif 134 VNET_DEFINE_STATIC(int, max_gif_nesting) = MAX_GIF_NEST; 135 #define V_max_gif_nesting VNET(max_gif_nesting) 136 SYSCTL_INT(_net_link_gif, OID_AUTO, max_nesting, CTLFLAG_VNET | CTLFLAG_RW, 137 &VNET_NAME(max_gif_nesting), 0, "Max nested tunnels"); 138 139 static int 140 gif_clone_create(struct if_clone *ifc, int unit, caddr_t params) 141 { 142 struct gif_softc *sc; 143 144 sc = malloc(sizeof(struct gif_softc), M_GIF, M_WAITOK | M_ZERO); 145 sc->gif_fibnum = curthread->td_proc->p_fibnum; 146 GIF2IFP(sc) = if_alloc(IFT_GIF); 147 GIF2IFP(sc)->if_softc = sc; 148 if_initname(GIF2IFP(sc), gifname, unit); 149 150 GIF2IFP(sc)->if_addrlen = 0; 151 GIF2IFP(sc)->if_mtu = GIF_MTU; 152 GIF2IFP(sc)->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 153 GIF2IFP(sc)->if_ioctl = gif_ioctl; 154 GIF2IFP(sc)->if_transmit = gif_transmit; 155 GIF2IFP(sc)->if_qflush = gif_qflush; 156 GIF2IFP(sc)->if_output = gif_output; 157 #ifdef VIMAGE 158 GIF2IFP(sc)->if_reassign = gif_reassign; 159 #endif 160 GIF2IFP(sc)->if_capabilities |= IFCAP_LINKSTATE; 161 GIF2IFP(sc)->if_capenable |= IFCAP_LINKSTATE; 162 if_attach(GIF2IFP(sc)); 163 bpfattach(GIF2IFP(sc), DLT_NULL, sizeof(u_int32_t)); 164 if (ng_gif_attach_p != NULL) 165 (*ng_gif_attach_p)(GIF2IFP(sc)); 166 167 return (0); 168 } 169 170 #ifdef VIMAGE 171 static void 172 gif_reassign(struct ifnet *ifp, struct vnet *new_vnet __unused, 173 char *unused __unused) 174 { 175 struct gif_softc *sc; 176 177 sx_xlock(&gif_ioctl_sx); 178 sc = ifp->if_softc; 179 if (sc != NULL) 180 gif_delete_tunnel(sc); 181 sx_xunlock(&gif_ioctl_sx); 182 } 183 #endif /* VIMAGE */ 184 185 static void 186 gif_clone_destroy(struct ifnet *ifp) 187 { 188 struct gif_softc *sc; 189 190 sx_xlock(&gif_ioctl_sx); 191 sc = ifp->if_softc; 192 gif_delete_tunnel(sc); 193 if (ng_gif_detach_p != NULL) 194 (*ng_gif_detach_p)(ifp); 195 bpfdetach(ifp); 196 if_detach(ifp); 197 ifp->if_softc = NULL; 198 sx_xunlock(&gif_ioctl_sx); 199 200 GIF_WAIT(); 201 if_free(ifp); 202 free(sc, M_GIF); 203 } 204 205 static void 206 vnet_gif_init(const void *unused __unused) 207 { 208 209 V_gif_cloner = if_clone_simple(gifname, gif_clone_create, 210 gif_clone_destroy, 0); 211 #ifdef INET 212 in_gif_init(); 213 #endif 214 #ifdef INET6 215 in6_gif_init(); 216 #endif 217 } 218 VNET_SYSINIT(vnet_gif_init, SI_SUB_PSEUDO, SI_ORDER_ANY, 219 vnet_gif_init, NULL); 220 221 static void 222 vnet_gif_uninit(const void *unused __unused) 223 { 224 225 if_clone_detach(V_gif_cloner); 226 #ifdef INET 227 in_gif_uninit(); 228 #endif 229 #ifdef INET6 230 in6_gif_uninit(); 231 #endif 232 } 233 VNET_SYSUNINIT(vnet_gif_uninit, SI_SUB_PSEUDO, SI_ORDER_ANY, 234 vnet_gif_uninit, NULL); 235 236 static int 237 gifmodevent(module_t mod, int type, void *data) 238 { 239 240 switch (type) { 241 case MOD_LOAD: 242 case MOD_UNLOAD: 243 break; 244 default: 245 return (EOPNOTSUPP); 246 } 247 return (0); 248 } 249 250 static moduledata_t gif_mod = { 251 "if_gif", 252 gifmodevent, 253 0 254 }; 255 256 DECLARE_MODULE(if_gif, gif_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 257 MODULE_VERSION(if_gif, 1); 258 259 struct gif_list * 260 gif_hashinit(void) 261 { 262 struct gif_list *hash; 263 int i; 264 265 hash = malloc(sizeof(struct gif_list) * GIF_HASH_SIZE, 266 M_GIF, M_WAITOK); 267 for (i = 0; i < GIF_HASH_SIZE; i++) 268 CK_LIST_INIT(&hash[i]); 269 270 return (hash); 271 } 272 273 void 274 gif_hashdestroy(struct gif_list *hash) 275 { 276 277 free(hash, M_GIF); 278 } 279 280 #define MTAG_GIF 1080679712 281 static int 282 gif_transmit(struct ifnet *ifp, struct mbuf *m) 283 { 284 struct gif_softc *sc; 285 struct etherip_header *eth; 286 #ifdef INET 287 struct ip *ip; 288 #endif 289 #ifdef INET6 290 struct ip6_hdr *ip6; 291 uint32_t t; 292 #endif 293 uint32_t af; 294 uint8_t proto, ecn; 295 int error; 296 297 NET_EPOCH_ASSERT(); 298 #ifdef MAC 299 error = mac_ifnet_check_transmit(ifp, m); 300 if (error) { 301 m_freem(m); 302 goto err; 303 } 304 #endif 305 error = ENETDOWN; 306 sc = ifp->if_softc; 307 if ((ifp->if_flags & IFF_MONITOR) != 0 || 308 (ifp->if_flags & IFF_UP) == 0 || 309 (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || 310 sc->gif_family == 0 || 311 (error = if_tunnel_check_nesting(ifp, m, MTAG_GIF, 312 V_max_gif_nesting)) != 0) { 313 m_freem(m); 314 goto err; 315 } 316 /* Now pull back the af that we stashed in the csum_data. */ 317 if (ifp->if_bridge) 318 af = AF_LINK; 319 else 320 af = m->m_pkthdr.csum_data; 321 m->m_flags &= ~(M_BCAST|M_MCAST); 322 M_SETFIB(m, sc->gif_fibnum); 323 BPF_MTAP2(ifp, &af, sizeof(af), m); 324 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 325 if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len); 326 /* inner AF-specific encapsulation */ 327 ecn = 0; 328 switch (af) { 329 #ifdef INET 330 case AF_INET: 331 proto = IPPROTO_IPV4; 332 if (m->m_len < sizeof(struct ip)) 333 m = m_pullup(m, sizeof(struct ip)); 334 if (m == NULL) { 335 error = ENOBUFS; 336 goto err; 337 } 338 ip = mtod(m, struct ip *); 339 ip_ecn_ingress((ifp->if_flags & IFF_LINK1) ? ECN_ALLOWED: 340 ECN_NOCARE, &ecn, &ip->ip_tos); 341 break; 342 #endif 343 #ifdef INET6 344 case AF_INET6: 345 proto = IPPROTO_IPV6; 346 if (m->m_len < sizeof(struct ip6_hdr)) 347 m = m_pullup(m, sizeof(struct ip6_hdr)); 348 if (m == NULL) { 349 error = ENOBUFS; 350 goto err; 351 } 352 t = 0; 353 ip6 = mtod(m, struct ip6_hdr *); 354 ip6_ecn_ingress((ifp->if_flags & IFF_LINK1) ? ECN_ALLOWED: 355 ECN_NOCARE, &t, &ip6->ip6_flow); 356 ecn = (ntohl(t) >> 20) & 0xff; 357 break; 358 #endif 359 case AF_LINK: 360 proto = IPPROTO_ETHERIP; 361 M_PREPEND(m, sizeof(struct etherip_header), M_NOWAIT); 362 if (m == NULL) { 363 error = ENOBUFS; 364 goto err; 365 } 366 eth = mtod(m, struct etherip_header *); 367 eth->eip_resvh = 0; 368 eth->eip_ver = ETHERIP_VERSION; 369 eth->eip_resvl = 0; 370 break; 371 default: 372 error = EAFNOSUPPORT; 373 m_freem(m); 374 goto err; 375 } 376 /* XXX should we check if our outer source is legal? */ 377 /* dispatch to output logic based on outer AF */ 378 switch (sc->gif_family) { 379 #ifdef INET 380 case AF_INET: 381 error = in_gif_output(ifp, m, proto, ecn); 382 break; 383 #endif 384 #ifdef INET6 385 case AF_INET6: 386 error = in6_gif_output(ifp, m, proto, ecn); 387 break; 388 #endif 389 default: 390 m_freem(m); 391 } 392 err: 393 if (error) 394 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 395 return (error); 396 } 397 398 static void 399 gif_qflush(struct ifnet *ifp __unused) 400 { 401 402 } 403 404 int 405 gif_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, 406 struct route *ro) 407 { 408 uint32_t af; 409 410 if (dst->sa_family == AF_UNSPEC) 411 bcopy(dst->sa_data, &af, sizeof(af)); 412 else 413 af = RO_GET_FAMILY(ro, dst); 414 /* 415 * Now save the af in the inbound pkt csum data, this is a cheat since 416 * we are using the inbound csum_data field to carry the af over to 417 * the gif_transmit() routine, avoiding using yet another mtag. 418 */ 419 m->m_pkthdr.csum_data = af; 420 return (ifp->if_transmit(ifp, m)); 421 } 422 423 void 424 gif_input(struct mbuf *m, struct ifnet *ifp, int proto, uint8_t ecn) 425 { 426 struct etherip_header *eip; 427 #ifdef INET 428 struct ip *ip; 429 #endif 430 #ifdef INET6 431 struct ip6_hdr *ip6; 432 uint32_t t; 433 #endif 434 struct ether_header *eh; 435 struct ifnet *oldifp; 436 int isr, n, af; 437 438 NET_EPOCH_ASSERT(); 439 440 if (ifp == NULL) { 441 /* just in case */ 442 m_freem(m); 443 return; 444 } 445 m->m_pkthdr.rcvif = ifp; 446 m_clrprotoflags(m); 447 switch (proto) { 448 #ifdef INET 449 case IPPROTO_IPV4: 450 af = AF_INET; 451 if (m->m_len < sizeof(struct ip)) 452 m = m_pullup(m, sizeof(struct ip)); 453 if (m == NULL) 454 goto drop; 455 ip = mtod(m, struct ip *); 456 if (ip_ecn_egress((ifp->if_flags & IFF_LINK1) ? ECN_ALLOWED: 457 ECN_NOCARE, &ecn, &ip->ip_tos) == 0) { 458 m_freem(m); 459 goto drop; 460 } 461 break; 462 #endif 463 #ifdef INET6 464 case IPPROTO_IPV6: 465 af = AF_INET6; 466 if (m->m_len < sizeof(struct ip6_hdr)) 467 m = m_pullup(m, sizeof(struct ip6_hdr)); 468 if (m == NULL) 469 goto drop; 470 t = htonl((uint32_t)ecn << 20); 471 ip6 = mtod(m, struct ip6_hdr *); 472 if (ip6_ecn_egress((ifp->if_flags & IFF_LINK1) ? ECN_ALLOWED: 473 ECN_NOCARE, &t, &ip6->ip6_flow) == 0) { 474 m_freem(m); 475 goto drop; 476 } 477 break; 478 #endif 479 case IPPROTO_ETHERIP: 480 af = AF_LINK; 481 break; 482 default: 483 m_freem(m); 484 goto drop; 485 } 486 487 #ifdef MAC 488 mac_ifnet_create_mbuf(ifp, m); 489 #endif 490 491 if (bpf_peers_present(ifp->if_bpf)) { 492 uint32_t af1 = af; 493 bpf_mtap2(ifp->if_bpf, &af1, sizeof(af1), m); 494 } 495 496 if ((ifp->if_flags & IFF_MONITOR) != 0) { 497 if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); 498 if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len); 499 m_freem(m); 500 return; 501 } 502 503 if (ng_gif_input_p != NULL) { 504 (*ng_gif_input_p)(ifp, &m, af); 505 if (m == NULL) 506 goto drop; 507 } 508 509 /* 510 * Put the packet to the network layer input queue according to the 511 * specified address family. 512 * Note: older versions of gif_input directly called network layer 513 * input functions, e.g. ip6_input, here. We changed the policy to 514 * prevent too many recursive calls of such input functions, which 515 * might cause kernel panic. But the change may introduce another 516 * problem; if the input queue is full, packets are discarded. 517 * The kernel stack overflow really happened, and we believed 518 * queue-full rarely occurs, so we changed the policy. 519 */ 520 switch (af) { 521 #ifdef INET 522 case AF_INET: 523 isr = NETISR_IP; 524 break; 525 #endif 526 #ifdef INET6 527 case AF_INET6: 528 isr = NETISR_IPV6; 529 break; 530 #endif 531 case AF_LINK: 532 n = sizeof(struct etherip_header) + 533 sizeof(struct ether_header); 534 if (n > m->m_len) 535 m = m_pullup(m, n); 536 if (m == NULL) 537 goto drop; 538 eip = mtod(m, struct etherip_header *); 539 if (eip->eip_ver != ETHERIP_VERSION) { 540 /* discard unknown versions */ 541 m_freem(m); 542 goto drop; 543 } 544 545 m_adj_decap(m, sizeof(struct etherip_header)); 546 547 m->m_flags &= ~(M_BCAST|M_MCAST); 548 m->m_pkthdr.rcvif = ifp; 549 550 if (ifp->if_bridge) { 551 oldifp = ifp; 552 eh = mtod(m, struct ether_header *); 553 if (ETHER_IS_MULTICAST(eh->ether_dhost)) { 554 if (ETHER_IS_BROADCAST(eh->ether_dhost)) 555 m->m_flags |= M_BCAST; 556 else 557 m->m_flags |= M_MCAST; 558 if_inc_counter(ifp, IFCOUNTER_IMCASTS, 1); 559 } 560 BRIDGE_INPUT(ifp, m); 561 562 if (m != NULL && ifp != oldifp) { 563 /* 564 * The bridge gave us back itself or one of the 565 * members for which the frame is addressed. 566 */ 567 ether_demux(ifp, m); 568 return; 569 } 570 } 571 if (m != NULL) 572 m_freem(m); 573 return; 574 575 default: 576 if (ng_gif_input_orphan_p != NULL) 577 (*ng_gif_input_orphan_p)(ifp, m, af); 578 else 579 m_freem(m); 580 return; 581 } 582 583 if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); 584 if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len); 585 M_SETFIB(m, ifp->if_fib); 586 netisr_dispatch(isr, m); 587 return; 588 drop: 589 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 590 } 591 592 static int 593 gif_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 594 { 595 struct ifreq *ifr = (struct ifreq*)data; 596 struct gif_softc *sc; 597 u_int options; 598 int error; 599 600 switch (cmd) { 601 case SIOCSIFADDR: 602 ifp->if_flags |= IFF_UP; 603 case SIOCADDMULTI: 604 case SIOCDELMULTI: 605 case SIOCGIFMTU: 606 case SIOCSIFFLAGS: 607 return (0); 608 case SIOCSIFMTU: 609 if (ifr->ifr_mtu < GIF_MTU_MIN || 610 ifr->ifr_mtu > GIF_MTU_MAX) 611 return (EINVAL); 612 else 613 ifp->if_mtu = ifr->ifr_mtu; 614 return (0); 615 } 616 sx_xlock(&gif_ioctl_sx); 617 sc = ifp->if_softc; 618 if (sc == NULL) { 619 error = ENXIO; 620 goto bad; 621 } 622 error = 0; 623 switch (cmd) { 624 case SIOCDIFPHYADDR: 625 if (sc->gif_family == 0) 626 break; 627 gif_delete_tunnel(sc); 628 break; 629 #ifdef INET 630 case SIOCSIFPHYADDR: 631 case SIOCGIFPSRCADDR: 632 case SIOCGIFPDSTADDR: 633 error = in_gif_ioctl(sc, cmd, data); 634 break; 635 #endif 636 #ifdef INET6 637 case SIOCSIFPHYADDR_IN6: 638 case SIOCGIFPSRCADDR_IN6: 639 case SIOCGIFPDSTADDR_IN6: 640 error = in6_gif_ioctl(sc, cmd, data); 641 break; 642 #endif 643 case SIOCGTUNFIB: 644 ifr->ifr_fib = sc->gif_fibnum; 645 break; 646 case SIOCSTUNFIB: 647 if ((error = priv_check(curthread, PRIV_NET_GIF)) != 0) 648 break; 649 if (ifr->ifr_fib >= rt_numfibs) 650 error = EINVAL; 651 else 652 sc->gif_fibnum = ifr->ifr_fib; 653 break; 654 case GIFGOPTS: 655 options = sc->gif_options; 656 error = copyout(&options, ifr_data_get_ptr(ifr), 657 sizeof(options)); 658 break; 659 case GIFSOPTS: 660 if ((error = priv_check(curthread, PRIV_NET_GIF)) != 0) 661 break; 662 error = copyin(ifr_data_get_ptr(ifr), &options, 663 sizeof(options)); 664 if (error) 665 break; 666 if (options & ~GIF_OPTMASK) { 667 error = EINVAL; 668 break; 669 } 670 if (sc->gif_options != options) { 671 switch (sc->gif_family) { 672 #ifdef INET 673 case AF_INET: 674 error = in_gif_setopts(sc, options); 675 break; 676 #endif 677 #ifdef INET6 678 case AF_INET6: 679 error = in6_gif_setopts(sc, options); 680 break; 681 #endif 682 default: 683 /* No need to invoke AF-handler */ 684 sc->gif_options = options; 685 } 686 } 687 break; 688 default: 689 error = EINVAL; 690 break; 691 } 692 if (error == 0 && sc->gif_family != 0) { 693 if ( 694 #ifdef INET 695 cmd == SIOCSIFPHYADDR || 696 #endif 697 #ifdef INET6 698 cmd == SIOCSIFPHYADDR_IN6 || 699 #endif 700 0) { 701 if_link_state_change(ifp, LINK_STATE_UP); 702 } 703 } 704 bad: 705 sx_xunlock(&gif_ioctl_sx); 706 return (error); 707 } 708 709 static void 710 gif_delete_tunnel(struct gif_softc *sc) 711 { 712 713 sx_assert(&gif_ioctl_sx, SA_XLOCKED); 714 if (sc->gif_family != 0) { 715 CK_LIST_REMOVE(sc, srchash); 716 CK_LIST_REMOVE(sc, chain); 717 /* Wait until it become safe to free gif_hdr */ 718 GIF_WAIT(); 719 free(sc->gif_hdr, M_GIF); 720 } 721 sc->gif_family = 0; 722 GIF2IFP(sc)->if_drv_flags &= ~IFF_DRV_RUNNING; 723 if_link_state_change(GIF2IFP(sc), LINK_STATE_DOWN); 724 } 725