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 KASSERT(ifp->if_bridge == NULL, 411 ("%s: unexpectedly called with bridge attached", __func__)); 412 413 if (dst->sa_family == AF_UNSPEC) 414 memcpy(&af, dst->sa_data, sizeof(af)); 415 else 416 af = RO_GET_FAMILY(ro, dst); 417 /* 418 * Now save the af in the inbound pkt csum data, this is a cheat since 419 * we are using the inbound csum_data field to carry the af over to 420 * the gif_transmit() routine, avoiding using yet another mtag. 421 */ 422 m->m_pkthdr.csum_data = af; 423 return (ifp->if_transmit(ifp, m)); 424 } 425 426 void 427 gif_input(struct mbuf *m, struct ifnet *ifp, int proto, uint8_t ecn) 428 { 429 struct etherip_header *eip; 430 #ifdef INET 431 struct ip *ip; 432 #endif 433 #ifdef INET6 434 struct ip6_hdr *ip6; 435 uint32_t t; 436 #endif 437 struct ether_header *eh; 438 struct ifnet *oldifp; 439 int isr, n, af; 440 441 NET_EPOCH_ASSERT(); 442 443 if (ifp == NULL) { 444 /* just in case */ 445 m_freem(m); 446 return; 447 } 448 m->m_pkthdr.rcvif = ifp; 449 m_clrprotoflags(m); 450 switch (proto) { 451 #ifdef INET 452 case IPPROTO_IPV4: 453 af = AF_INET; 454 if (m->m_len < sizeof(struct ip)) 455 m = m_pullup(m, sizeof(struct ip)); 456 if (m == NULL) 457 goto drop; 458 ip = mtod(m, struct ip *); 459 if (ip_ecn_egress((ifp->if_flags & IFF_LINK1) ? ECN_ALLOWED: 460 ECN_NOCARE, &ecn, &ip->ip_tos) == 0) { 461 m_freem(m); 462 goto drop; 463 } 464 break; 465 #endif 466 #ifdef INET6 467 case IPPROTO_IPV6: 468 af = AF_INET6; 469 if (m->m_len < sizeof(struct ip6_hdr)) 470 m = m_pullup(m, sizeof(struct ip6_hdr)); 471 if (m == NULL) 472 goto drop; 473 t = htonl((uint32_t)ecn << 20); 474 ip6 = mtod(m, struct ip6_hdr *); 475 if (ip6_ecn_egress((ifp->if_flags & IFF_LINK1) ? ECN_ALLOWED: 476 ECN_NOCARE, &t, &ip6->ip6_flow) == 0) { 477 m_freem(m); 478 goto drop; 479 } 480 break; 481 #endif 482 case IPPROTO_ETHERIP: 483 af = AF_LINK; 484 break; 485 default: 486 m_freem(m); 487 goto drop; 488 } 489 490 #ifdef MAC 491 mac_ifnet_create_mbuf(ifp, m); 492 #endif 493 494 if (bpf_peers_present(ifp->if_bpf)) { 495 uint32_t af1 = af; 496 bpf_mtap2(ifp->if_bpf, &af1, sizeof(af1), m); 497 } 498 499 if ((ifp->if_flags & IFF_MONITOR) != 0) { 500 if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); 501 if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len); 502 m_freem(m); 503 return; 504 } 505 506 if (ng_gif_input_p != NULL) { 507 (*ng_gif_input_p)(ifp, &m, af); 508 if (m == NULL) 509 goto drop; 510 } 511 512 /* 513 * Put the packet to the network layer input queue according to the 514 * specified address family. 515 * Note: older versions of gif_input directly called network layer 516 * input functions, e.g. ip6_input, here. We changed the policy to 517 * prevent too many recursive calls of such input functions, which 518 * might cause kernel panic. But the change may introduce another 519 * problem; if the input queue is full, packets are discarded. 520 * The kernel stack overflow really happened, and we believed 521 * queue-full rarely occurs, so we changed the policy. 522 */ 523 switch (af) { 524 #ifdef INET 525 case AF_INET: 526 isr = NETISR_IP; 527 break; 528 #endif 529 #ifdef INET6 530 case AF_INET6: 531 isr = NETISR_IPV6; 532 break; 533 #endif 534 case AF_LINK: 535 n = sizeof(struct etherip_header) + 536 sizeof(struct ether_header); 537 if (n > m->m_len) 538 m = m_pullup(m, n); 539 if (m == NULL) 540 goto drop; 541 eip = mtod(m, struct etherip_header *); 542 if (eip->eip_ver != ETHERIP_VERSION) { 543 /* discard unknown versions */ 544 m_freem(m); 545 goto drop; 546 } 547 548 m_adj_decap(m, sizeof(struct etherip_header)); 549 550 m->m_flags &= ~(M_BCAST|M_MCAST); 551 m->m_pkthdr.rcvif = ifp; 552 553 if (ifp->if_bridge) { 554 oldifp = ifp; 555 eh = mtod(m, struct ether_header *); 556 if (ETHER_IS_MULTICAST(eh->ether_dhost)) { 557 if (ETHER_IS_BROADCAST(eh->ether_dhost)) 558 m->m_flags |= M_BCAST; 559 else 560 m->m_flags |= M_MCAST; 561 if_inc_counter(ifp, IFCOUNTER_IMCASTS, 1); 562 } 563 BRIDGE_INPUT(ifp, m); 564 565 if (m != NULL && ifp != oldifp) { 566 /* 567 * The bridge gave us back itself or one of the 568 * members for which the frame is addressed. 569 */ 570 ether_demux(ifp, m); 571 return; 572 } 573 } 574 if (m != NULL) 575 m_freem(m); 576 return; 577 578 default: 579 if (ng_gif_input_orphan_p != NULL) 580 (*ng_gif_input_orphan_p)(ifp, m, af); 581 else 582 m_freem(m); 583 return; 584 } 585 586 if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); 587 if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len); 588 M_SETFIB(m, ifp->if_fib); 589 netisr_dispatch(isr, m); 590 return; 591 drop: 592 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 593 } 594 595 static int 596 gif_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 597 { 598 struct ifreq *ifr = (struct ifreq*)data; 599 struct gif_softc *sc; 600 u_int options; 601 int error; 602 603 switch (cmd) { 604 case SIOCSIFADDR: 605 ifp->if_flags |= IFF_UP; 606 case SIOCADDMULTI: 607 case SIOCDELMULTI: 608 case SIOCGIFMTU: 609 case SIOCSIFFLAGS: 610 return (0); 611 case SIOCSIFMTU: 612 if (ifr->ifr_mtu < GIF_MTU_MIN || 613 ifr->ifr_mtu > GIF_MTU_MAX) 614 return (EINVAL); 615 else 616 ifp->if_mtu = ifr->ifr_mtu; 617 return (0); 618 } 619 sx_xlock(&gif_ioctl_sx); 620 sc = ifp->if_softc; 621 if (sc == NULL) { 622 error = ENXIO; 623 goto bad; 624 } 625 error = 0; 626 switch (cmd) { 627 case SIOCDIFPHYADDR: 628 if (sc->gif_family == 0) 629 break; 630 gif_delete_tunnel(sc); 631 break; 632 #ifdef INET 633 case SIOCSIFPHYADDR: 634 case SIOCGIFPSRCADDR: 635 case SIOCGIFPDSTADDR: 636 error = in_gif_ioctl(sc, cmd, data); 637 break; 638 #endif 639 #ifdef INET6 640 case SIOCSIFPHYADDR_IN6: 641 case SIOCGIFPSRCADDR_IN6: 642 case SIOCGIFPDSTADDR_IN6: 643 error = in6_gif_ioctl(sc, cmd, data); 644 break; 645 #endif 646 case SIOCGTUNFIB: 647 ifr->ifr_fib = sc->gif_fibnum; 648 break; 649 case SIOCSTUNFIB: 650 if ((error = priv_check(curthread, PRIV_NET_GIF)) != 0) 651 break; 652 if (ifr->ifr_fib >= rt_numfibs) 653 error = EINVAL; 654 else 655 sc->gif_fibnum = ifr->ifr_fib; 656 break; 657 case GIFGOPTS: 658 options = sc->gif_options; 659 error = copyout(&options, ifr_data_get_ptr(ifr), 660 sizeof(options)); 661 break; 662 case GIFSOPTS: 663 if ((error = priv_check(curthread, PRIV_NET_GIF)) != 0) 664 break; 665 error = copyin(ifr_data_get_ptr(ifr), &options, 666 sizeof(options)); 667 if (error) 668 break; 669 if (options & ~GIF_OPTMASK) { 670 error = EINVAL; 671 break; 672 } 673 if (sc->gif_options != options) { 674 switch (sc->gif_family) { 675 #ifdef INET 676 case AF_INET: 677 error = in_gif_setopts(sc, options); 678 break; 679 #endif 680 #ifdef INET6 681 case AF_INET6: 682 error = in6_gif_setopts(sc, options); 683 break; 684 #endif 685 default: 686 /* No need to invoke AF-handler */ 687 sc->gif_options = options; 688 } 689 } 690 break; 691 default: 692 error = EINVAL; 693 break; 694 } 695 if (error == 0 && sc->gif_family != 0) { 696 if ( 697 #ifdef INET 698 cmd == SIOCSIFPHYADDR || 699 #endif 700 #ifdef INET6 701 cmd == SIOCSIFPHYADDR_IN6 || 702 #endif 703 0) { 704 if_link_state_change(ifp, LINK_STATE_UP); 705 } 706 } 707 bad: 708 sx_xunlock(&gif_ioctl_sx); 709 return (error); 710 } 711 712 static void 713 gif_delete_tunnel(struct gif_softc *sc) 714 { 715 716 sx_assert(&gif_ioctl_sx, SA_XLOCKED); 717 if (sc->gif_family != 0) { 718 CK_LIST_REMOVE(sc, srchash); 719 CK_LIST_REMOVE(sc, chain); 720 /* Wait until it become safe to free gif_hdr */ 721 GIF_WAIT(); 722 free(sc->gif_hdr, M_GIF); 723 } 724 sc->gif_family = 0; 725 GIF2IFP(sc)->if_drv_flags &= ~IFF_DRV_RUNNING; 726 if_link_state_change(GIF2IFP(sc), LINK_STATE_DOWN); 727 } 728