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