1 /* $OpenBSD: if.c,v 1.49 2001/06/29 22:46:05 fgsch Exp $ */ 2 /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ 3 4 /* 5 * Copyright (C) 1995, 1996, 1997, and 1998 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 * Copyright (c) 1980, 1986, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. All advertising materials mentioning features or use of this software 46 * must display the following acknowledgement: 47 * This product includes software developed by the University of 48 * California, Berkeley and its contributors. 49 * 4. Neither the name of the University nor the names of its contributors 50 * may be used to endorse or promote products derived from this software 51 * without specific prior written permission. 52 * 53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 * SUCH DAMAGE. 64 * 65 * @(#)if.c 8.3 (Berkeley) 1/4/94 66 */ 67 68 #include "bpfilter.h" 69 #include "bridge.h" 70 71 #include <sys/param.h> 72 #include <sys/systm.h> 73 #include <sys/mbuf.h> 74 #include <sys/proc.h> 75 #include <sys/socket.h> 76 #include <sys/socketvar.h> 77 #include <sys/protosw.h> 78 #include <sys/kernel.h> 79 #include <sys/ioctl.h> 80 81 #include <net/if.h> 82 #include <net/if_dl.h> 83 #include <net/route.h> 84 85 #ifdef INET 86 #include <netinet/in.h> 87 #include <netinet/in_var.h> 88 #include <netinet/if_ether.h> 89 #include <netinet/igmp.h> 90 #ifdef MROUTING 91 #include <netinet/ip_mroute.h> 92 #endif 93 #endif 94 95 #ifdef INET6 96 #ifndef INET 97 #include <netinet/in.h> 98 #endif 99 #include <netinet6/in6_ifattach.h> 100 #endif 101 102 #if NBPFILTER > 0 103 #include <net/bpf.h> 104 #endif 105 106 #if NBRIDGE > 0 107 #include <net/if_bridge.h> 108 #endif 109 110 void if_attachsetup __P((struct ifnet *)); 111 int if_detach_rtdelete __P((struct radix_node *, void *)); 112 int if_mark_ignore __P((struct radix_node *, void *)); 113 int if_mark_unignore __P((struct radix_node *, void *)); 114 115 int ifqmaxlen = IFQ_MAXLEN; 116 117 void if_detached_start __P((struct ifnet *)); 118 int if_detached_ioctl __P((struct ifnet *, u_long, caddr_t)); 119 void if_detached_watchdog __P((struct ifnet *)); 120 121 #ifdef INET6 122 /* 123 * XXX: declare here to avoid to include many inet6 related files.. 124 * should be more generalized? 125 */ 126 extern void nd6_setmtu __P((struct ifnet *)); 127 #endif 128 129 /* 130 * Network interface utility routines. 131 * 132 * Routines with ifa_ifwith* names take sockaddr *'s as 133 * parameters. 134 */ 135 void 136 ifinit() 137 { 138 static struct timeout if_slowtim; 139 140 timeout_set(&if_slowtim, if_slowtimo, &if_slowtim); 141 142 if_slowtimo(&if_slowtim); 143 } 144 145 int if_index = 0; 146 struct ifaddr **ifnet_addrs = NULL; 147 struct ifnet **ifindex2ifnet = NULL; 148 149 /* 150 * Attach an interface to the 151 * list of "active" interfaces. 152 */ 153 void 154 if_attachsetup(ifp) 155 struct ifnet *ifp; 156 { 157 unsigned int socksize, ifasize; 158 int namelen, masklen; 159 register struct sockaddr_dl *sdl; 160 register struct ifaddr *ifa; 161 static int if_indexlim = 8; 162 163 ifp->if_index = ++if_index; 164 165 /* 166 * We have some arrays that should be indexed by if_index. 167 * since if_index will grow dynamically, they should grow too. 168 * struct ifadd **ifnet_addrs 169 * struct ifnet **ifindex2ifnet 170 */ 171 if (ifnet_addrs == 0 || ifindex2ifnet == 0 || if_index >= if_indexlim) { 172 size_t n; 173 caddr_t q; 174 175 while (if_index >= if_indexlim) 176 if_indexlim <<= 1; 177 178 /* grow ifnet_addrs */ 179 n = if_indexlim * sizeof(ifa); 180 q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK); 181 bzero(q, n); 182 if (ifnet_addrs) { 183 bcopy((caddr_t)ifnet_addrs, q, n/2); 184 free((caddr_t)ifnet_addrs, M_IFADDR); 185 } 186 ifnet_addrs = (struct ifaddr **)q; 187 188 /* grow ifindex2ifnet */ 189 n = if_indexlim * sizeof(struct ifnet *); 190 q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK); 191 bzero(q, n); 192 if (ifindex2ifnet) { 193 bcopy((caddr_t)ifindex2ifnet, q, n/2); 194 free((caddr_t)ifindex2ifnet, M_IFADDR); 195 } 196 ifindex2ifnet = (struct ifnet **)q; 197 } 198 199 ifindex2ifnet[if_index] = ifp; 200 201 if (ifp->if_snd.ifq_maxlen == 0) 202 ifp->if_snd.ifq_maxlen = ifqmaxlen; 203 204 /* 205 * create a Link Level name for this device 206 */ 207 namelen = strlen(ifp->if_xname); 208 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) 209 masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen; 210 socksize = masklen + ifp->if_addrlen; 211 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) 212 if (socksize < sizeof(*sdl)) 213 socksize = sizeof(*sdl); 214 socksize = ROUNDUP(socksize); 215 ifasize = sizeof(*ifa) + 2 * socksize; 216 ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK); 217 bzero((caddr_t)ifa, ifasize); 218 sdl = (struct sockaddr_dl *)(ifa + 1); 219 sdl->sdl_len = socksize; 220 sdl->sdl_family = AF_LINK; 221 bcopy(ifp->if_xname, sdl->sdl_data, namelen); 222 sdl->sdl_nlen = namelen; 223 sdl->sdl_index = ifp->if_index; 224 sdl->sdl_type = ifp->if_type; 225 ifnet_addrs[if_index] = ifa; 226 ifa->ifa_ifp = ifp; 227 ifa->ifa_rtrequest = link_rtrequest; 228 TAILQ_INSERT_HEAD(&ifp->if_addrlist, ifa, ifa_list); 229 ifa->ifa_addr = (struct sockaddr *)sdl; 230 sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); 231 ifa->ifa_netmask = (struct sockaddr *)sdl; 232 sdl->sdl_len = masklen; 233 while (namelen != 0) 234 sdl->sdl_data[--namelen] = 0xff; 235 #ifdef ALTQ 236 ifp->if_snd.altq_type = 0; 237 ifp->if_snd.altq_disc = NULL; 238 ifp->if_snd.altq_flags &= ALTQF_CANTCHANGE; 239 ifp->if_snd.altq_tbr = NULL; 240 ifp->if_snd.altq_ifp = ifp; 241 #endif 242 } 243 244 void 245 if_attachhead(ifp) 246 struct ifnet *ifp; 247 { 248 if (if_index == 0) 249 TAILQ_INIT(&ifnet); 250 TAILQ_INIT(&ifp->if_addrlist); 251 TAILQ_INSERT_HEAD(&ifnet, ifp, if_list); 252 if_attachsetup(ifp); 253 } 254 255 void 256 if_attach(ifp) 257 struct ifnet *ifp; 258 { 259 if (if_index == 0) 260 TAILQ_INIT(&ifnet); 261 TAILQ_INIT(&ifp->if_addrlist); 262 TAILQ_INSERT_TAIL(&ifnet, ifp, if_list); 263 if_attachsetup(ifp); 264 } 265 266 /* 267 * Delete a route if it has a specific interface for output. 268 * This function complies to the rn_walktree callback API. 269 */ 270 int 271 if_detach_rtdelete(rn, vifp) 272 struct radix_node *rn; 273 void *vifp; 274 { 275 struct ifnet *ifp = vifp; 276 struct rtentry *rt = (struct rtentry *)rn; 277 278 if (rt->rt_ifp == ifp) 279 rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), 280 0, NULL); 281 282 /* 283 * XXX There should be no need to check for rt_ifa belonging to this 284 * interface, because then rt_ifp is set, right? 285 */ 286 287 return (0); 288 } 289 290 int 291 if_mark_ignore(rn, vifp) 292 struct radix_node *rn; 293 void *vifp; 294 { 295 struct ifnet *ifp = vifp; 296 struct rtentry *rt = (struct rtentry *)rn; 297 298 if (rt->rt_ifp == ifp) 299 rn->rn_flags |= RNF_IGNORE; 300 301 return (0); 302 } 303 304 int 305 if_mark_unignore(rn, vifp) 306 struct radix_node *rn; 307 void *vifp; 308 { 309 struct ifnet *ifp = vifp; 310 struct rtentry *rt = (struct rtentry *)rn; 311 312 if (rt->rt_ifp == ifp) 313 rn->rn_flags &= ~RNF_IGNORE; 314 315 return (0); 316 } 317 318 /* 319 * Detach an interface from everything in the kernel. Also deallocate 320 * private resources. 321 * XXX So far only the INET protocol family has been looked over 322 * wrt resource usage that needs to be decoupled. 323 */ 324 void 325 if_detach(ifp) 326 struct ifnet *ifp; 327 { 328 struct ifaddr *ifa; 329 int i, s = splimp(); 330 struct radix_node_head *rnh; 331 332 ifp->if_flags &= ~IFF_OACTIVE; 333 ifp->if_start = if_detached_start; 334 ifp->if_ioctl = if_detached_ioctl; 335 ifp->if_watchdog = if_detached_watchdog; 336 337 #if NBRIDGE > 0 338 /* Remove the interface from any bridge it is part of. */ 339 if (ifp->if_bridge) 340 bridge_ifdetach(ifp); 341 #endif 342 343 #if NBPFILTER > 0 344 /* If there is a bpf device attached, detach from it. */ 345 if (ifp->if_bpf) 346 bpfdetach(ifp); 347 #endif 348 #ifdef ALTQ 349 if (ALTQ_IS_ENABLED(&ifp->if_snd)) 350 altq_disable(&ifp->if_snd); 351 if (ALTQ_IS_ATTACHED(&ifp->if_snd)) 352 altq_detach(&ifp->if_snd); 353 #endif 354 355 /* 356 * Find and remove all routes which is using this interface. 357 * XXX Factor out into a route.c function? 358 */ 359 for (i = 1; i <= AF_MAX; i++) { 360 rnh = rt_tables[i]; 361 if (rnh) 362 (*rnh->rnh_walktree)(rnh, if_detach_rtdelete, ifp); 363 } 364 365 #ifdef INET 366 rti_delete(ifp); 367 #if NETHER > 0 368 myip_ifp = NULL; 369 #endif 370 #ifdef MROUTING 371 vif_delete(ifp); 372 #endif 373 #endif 374 #ifdef INET6 375 in6_ifdetach(ifp); 376 #endif 377 /* 378 * XXX transient ifp refs? inpcb.ip_moptions.imo_multicast_ifp? 379 * Other network stacks than INET? 380 */ 381 382 /* Remove the interface from the list of all interfaces. */ 383 TAILQ_REMOVE(&ifnet, ifp, if_list); 384 385 /* Deallocate private resources. */ 386 for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa; 387 ifa = TAILQ_FIRST(&ifp->if_addrlist)) { 388 TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list); 389 #ifdef INET 390 if (ifa->ifa_addr->sa_family == AF_INET) 391 TAILQ_REMOVE(&in_ifaddr, (struct in_ifaddr *)ifa, 392 ia_list); 393 #endif 394 free(ifa, M_IFADDR); 395 } 396 splx(s); 397 } 398 399 /* 400 * Locate an interface based on a complete address. 401 */ 402 /*ARGSUSED*/ 403 struct ifaddr * 404 ifa_ifwithaddr(addr) 405 register struct sockaddr *addr; 406 { 407 register struct ifnet *ifp; 408 register struct ifaddr *ifa; 409 410 #define equal(a1, a2) \ 411 (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) 412 for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) 413 for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) { 414 if (ifa->ifa_addr->sa_family != addr->sa_family) 415 continue; 416 if (equal(addr, ifa->ifa_addr)) 417 return (ifa); 418 if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && 419 /* IP6 doesn't have broadcast */ 420 ifa->ifa_broadaddr->sa_len != 0 && 421 equal(ifa->ifa_broadaddr, addr)) 422 return (ifa); 423 } 424 return (NULL); 425 } 426 /* 427 * Locate the point to point interface with a given destination address. 428 */ 429 /*ARGSUSED*/ 430 struct ifaddr * 431 ifa_ifwithdstaddr(addr) 432 register struct sockaddr *addr; 433 { 434 register struct ifnet *ifp; 435 register struct ifaddr *ifa; 436 437 for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) 438 if (ifp->if_flags & IFF_POINTOPOINT) 439 for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) { 440 if (ifa->ifa_addr->sa_family != addr->sa_family || 441 ifa->ifa_dstaddr == NULL) 442 continue; 443 if (equal(addr, ifa->ifa_dstaddr)) 444 return (ifa); 445 } 446 return (NULL); 447 } 448 449 /* 450 * Find an interface on a specific network. If many, choice 451 * is most specific found. 452 */ 453 struct ifaddr * 454 ifa_ifwithnet(addr) 455 struct sockaddr *addr; 456 { 457 register struct ifnet *ifp; 458 register struct ifaddr *ifa; 459 struct ifaddr *ifa_maybe = 0; 460 u_int af = addr->sa_family; 461 char *addr_data = addr->sa_data, *cplim; 462 463 if (af == AF_LINK) { 464 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr; 465 if (sdl->sdl_index && sdl->sdl_index <= if_index) 466 return (ifnet_addrs[sdl->sdl_index]); 467 } 468 for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) 469 for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) { 470 register char *cp, *cp2, *cp3; 471 472 if (ifa->ifa_addr->sa_family != af || 473 ifa->ifa_netmask == 0) 474 next: continue; 475 cp = addr_data; 476 cp2 = ifa->ifa_addr->sa_data; 477 cp3 = ifa->ifa_netmask->sa_data; 478 cplim = (char *)ifa->ifa_netmask + 479 ifa->ifa_netmask->sa_len; 480 while (cp3 < cplim) 481 if ((*cp++ ^ *cp2++) & *cp3++) 482 /* want to continue for() loop */ 483 goto next; 484 if (ifa_maybe == 0 || 485 rn_refines((caddr_t)ifa->ifa_netmask, 486 (caddr_t)ifa_maybe->ifa_netmask)) 487 ifa_maybe = ifa; 488 } 489 return (ifa_maybe); 490 } 491 492 /* 493 * Find an interface using a specific address family 494 */ 495 struct ifaddr * 496 ifa_ifwithaf(af) 497 register int af; 498 { 499 register struct ifnet *ifp; 500 register struct ifaddr *ifa; 501 502 for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) 503 for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) 504 if (ifa->ifa_addr->sa_family == af) 505 return (ifa); 506 return (NULL); 507 } 508 509 /* 510 * Find an interface address specific to an interface best matching 511 * a given address. 512 */ 513 struct ifaddr * 514 ifaof_ifpforaddr(addr, ifp) 515 struct sockaddr *addr; 516 register struct ifnet *ifp; 517 { 518 register struct ifaddr *ifa; 519 register char *cp, *cp2, *cp3; 520 register char *cplim; 521 struct ifaddr *ifa_maybe = 0; 522 u_int af = addr->sa_family; 523 524 if (af >= AF_MAX) 525 return (NULL); 526 for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) { 527 if (ifa->ifa_addr->sa_family != af) 528 continue; 529 ifa_maybe = ifa; 530 if (ifa->ifa_netmask == 0) { 531 if (equal(addr, ifa->ifa_addr) || 532 (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))) 533 return (ifa); 534 continue; 535 } 536 cp = addr->sa_data; 537 cp2 = ifa->ifa_addr->sa_data; 538 cp3 = ifa->ifa_netmask->sa_data; 539 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 540 for (; cp3 < cplim; cp3++) 541 if ((*cp++ ^ *cp2++) & *cp3) 542 break; 543 if (cp3 == cplim) 544 return (ifa); 545 } 546 return (ifa_maybe); 547 } 548 549 /* 550 * Default action when installing a route with a Link Level gateway. 551 * Lookup an appropriate real ifa to point to. 552 * This should be moved to /sys/net/link.c eventually. 553 */ 554 void 555 link_rtrequest(cmd, rt, info) 556 int cmd; 557 register struct rtentry *rt; 558 struct rt_addrinfo *info; 559 { 560 register struct ifaddr *ifa; 561 struct sockaddr *dst; 562 struct ifnet *ifp; 563 564 if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || 565 ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) 566 return; 567 if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) { 568 IFAFREE(rt->rt_ifa); 569 rt->rt_ifa = ifa; 570 ifa->ifa_refcnt++; 571 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) 572 ifa->ifa_rtrequest(cmd, rt, info); 573 } 574 } 575 576 /* 577 * Mark an interface down and notify protocols of 578 * the transition. 579 * NOTE: must be called at splsoftnet or equivalent. 580 */ 581 void 582 if_down(ifp) 583 register struct ifnet *ifp; 584 { 585 register struct ifaddr *ifa; 586 struct radix_node_head *rnh; 587 int i; 588 589 ifp->if_flags &= ~IFF_UP; 590 microtime(&ifp->if_lastchange); 591 for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) 592 pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 593 IFQ_PURGE(&ifp->if_snd); 594 rt_ifmsg(ifp); 595 596 /* 597 * Find and mark as ignore all routes which are using this interface. 598 * XXX Factor out into a route.c function? 599 */ 600 for (i = 1; i <= AF_MAX; i++) { 601 rnh = rt_tables[i]; 602 if (rnh) 603 (*rnh->rnh_walktree)(rnh, if_mark_ignore, ifp); 604 } 605 } 606 607 /* 608 * Mark an interface up and notify protocols of 609 * the transition. 610 * NOTE: must be called at splsoftnet or equivalent. 611 */ 612 void 613 if_up(ifp) 614 register struct ifnet *ifp; 615 { 616 #ifdef notyet 617 register struct ifaddr *ifa; 618 #endif 619 struct radix_node_head *rnh; 620 int i; 621 622 ifp->if_flags |= IFF_UP; 623 microtime(&ifp->if_lastchange); 624 #ifdef notyet 625 /* this has no effect on IP, and will kill all ISO connections XXX */ 626 for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; 627 ifa = ifa->ifa_list.tqe_next) 628 pfctlinput(PRC_IFUP, ifa->ifa_addr); 629 #endif 630 rt_ifmsg(ifp); 631 #ifdef INET6 632 in6_if_up(ifp); 633 #endif 634 635 /* 636 * Find and unignore all routes which are using this interface. 637 * XXX Factor out into a route.c function? 638 */ 639 for (i = 1; i <= AF_MAX; i++) { 640 rnh = rt_tables[i]; 641 if (rnh) 642 (*rnh->rnh_walktree)(rnh, if_mark_unignore, ifp); 643 } 644 } 645 646 /* 647 * Flush an interface queue. 648 */ 649 void 650 if_qflush(ifq) 651 register struct ifqueue *ifq; 652 { 653 register struct mbuf *m, *n; 654 655 n = ifq->ifq_head; 656 while ((m = n) != NULL) { 657 n = m->m_act; 658 m_freem(m); 659 } 660 ifq->ifq_head = 0; 661 ifq->ifq_tail = 0; 662 ifq->ifq_len = 0; 663 } 664 665 /* 666 * Handle interface watchdog timer routines. Called 667 * from softclock, we decrement timers (if set) and 668 * call the appropriate interface routine on expiration. 669 */ 670 void 671 if_slowtimo(arg) 672 void *arg; 673 { 674 struct timeout *to = (struct timeout *)arg; 675 struct ifnet *ifp; 676 int s = splimp(); 677 678 for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) { 679 if (ifp->if_timer == 0 || --ifp->if_timer) 680 continue; 681 if (ifp->if_watchdog) 682 (*ifp->if_watchdog)(ifp); 683 } 684 splx(s); 685 timeout_add(to, hz / IFNET_SLOWHZ); 686 } 687 688 /* 689 * Map interface name to 690 * interface structure pointer. 691 */ 692 struct ifnet * 693 ifunit(name) 694 register char *name; 695 { 696 register struct ifnet *ifp; 697 698 for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) 699 if (strcmp(ifp->if_xname, name) == 0) 700 return (ifp); 701 702 return (NULL); 703 } 704 705 /* 706 * Interface ioctls. 707 */ 708 int 709 ifioctl(so, cmd, data, p) 710 struct socket *so; 711 u_long cmd; 712 caddr_t data; 713 struct proc *p; 714 { 715 register struct ifnet *ifp; 716 register struct ifreq *ifr; 717 int error = 0; 718 short oif_flags; 719 720 switch (cmd) { 721 722 case SIOCGIFCONF: 723 case OSIOCGIFCONF: 724 return (ifconf(cmd, data)); 725 } 726 ifr = (struct ifreq *)data; 727 ifp = ifunit(ifr->ifr_name); 728 if (ifp == 0) 729 return (ENXIO); 730 oif_flags = ifp->if_flags; 731 switch (cmd) { 732 733 case SIOCGIFFLAGS: 734 ifr->ifr_flags = ifp->if_flags; 735 break; 736 737 case SIOCGIFMETRIC: 738 ifr->ifr_metric = ifp->if_metric; 739 break; 740 741 case SIOCGIFMTU: 742 ifr->ifr_mtu = ifp->if_mtu; 743 break; 744 745 case SIOCGIFDATA: 746 error = copyout((caddr_t)&ifp->if_data, ifr->ifr_data, 747 sizeof(ifp->if_data)); 748 break; 749 750 case SIOCSIFFLAGS: 751 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 752 return (error); 753 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 754 int s = splimp(); 755 if_down(ifp); 756 splx(s); 757 } 758 if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) { 759 int s = splimp(); 760 if_up(ifp); 761 splx(s); 762 } 763 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 764 (ifr->ifr_flags &~ IFF_CANTCHANGE); 765 if (ifp->if_ioctl) 766 (void) (*ifp->if_ioctl)(ifp, cmd, data); 767 break; 768 769 case SIOCSIFMETRIC: 770 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 771 return (error); 772 ifp->if_metric = ifr->ifr_metric; 773 break; 774 775 case SIOCSIFMTU: 776 { 777 #ifdef INET6 778 int oldmtu = ifp->if_mtu; 779 #endif 780 781 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 782 return (error); 783 if (ifp->if_ioctl == NULL) 784 return (EOPNOTSUPP); 785 error = (*ifp->if_ioctl)(ifp, cmd, data); 786 787 /* 788 * If the link MTU changed, do network layer specific procedure. 789 */ 790 #ifdef INET6 791 if (ifp->if_mtu != oldmtu) 792 nd6_setmtu(ifp); 793 #endif 794 break; 795 } 796 797 case SIOCSIFPHYADDR: 798 case SIOCDIFPHYADDR: 799 #ifdef INET6 800 case SIOCSIFPHYADDR_IN6: 801 #endif 802 case SIOCSLIFPHYADDR: 803 case SIOCADDMULTI: 804 case SIOCDELMULTI: 805 case SIOCSIFMEDIA: 806 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 807 return (error); 808 /* FALLTHROUGH */ 809 case SIOCGIFPSRCADDR: 810 case SIOCGIFPDSTADDR: 811 case SIOCGLIFPHYADDR: 812 case SIOCGIFMEDIA: 813 if (ifp->if_ioctl == 0) 814 return (EOPNOTSUPP); 815 error = (*ifp->if_ioctl)(ifp, cmd, data); 816 break; 817 818 default: 819 if (so->so_proto == 0) 820 return (EOPNOTSUPP); 821 #if !defined(COMPAT_43) && !defined(COMPAT_LINUX) && !defined(COMPAT_SVR4) 822 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 823 (struct mbuf *) cmd, (struct mbuf *) data, 824 (struct mbuf *) ifp)); 825 #else 826 { 827 u_long ocmd = cmd; 828 829 switch (cmd) { 830 831 case SIOCSIFADDR: 832 case SIOCSIFDSTADDR: 833 case SIOCSIFBRDADDR: 834 case SIOCSIFNETMASK: 835 #if BYTE_ORDER != BIG_ENDIAN 836 if (ifr->ifr_addr.sa_family == 0 && 837 ifr->ifr_addr.sa_len < 16) { 838 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 839 ifr->ifr_addr.sa_len = 16; 840 } 841 #else 842 if (ifr->ifr_addr.sa_len == 0) 843 ifr->ifr_addr.sa_len = 16; 844 #endif 845 break; 846 847 case OSIOCGIFADDR: 848 cmd = SIOCGIFADDR; 849 break; 850 851 case OSIOCGIFDSTADDR: 852 cmd = SIOCGIFDSTADDR; 853 break; 854 855 case OSIOCGIFBRDADDR: 856 cmd = SIOCGIFBRDADDR; 857 break; 858 859 case OSIOCGIFNETMASK: 860 cmd = SIOCGIFNETMASK; 861 } 862 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 863 (struct mbuf *) cmd, (struct mbuf *) data, 864 (struct mbuf *) ifp)); 865 switch (ocmd) { 866 867 case OSIOCGIFADDR: 868 case OSIOCGIFDSTADDR: 869 case OSIOCGIFBRDADDR: 870 case OSIOCGIFNETMASK: 871 *(u_int16_t *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 872 } 873 874 } 875 #endif 876 break; 877 } 878 879 if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) { 880 #ifdef INET6 881 if ((ifp->if_flags & IFF_UP) != 0) { 882 int s = splsoftnet(); 883 in6_if_up(ifp); 884 splx(s); 885 } 886 #endif 887 } 888 return (error); 889 } 890 891 /* 892 * Return interface configuration 893 * of system. List may be used 894 * in later ioctl's (above) to get 895 * other information. 896 */ 897 /*ARGSUSED*/ 898 int 899 ifconf(cmd, data) 900 u_long cmd; 901 caddr_t data; 902 { 903 register struct ifconf *ifc = (struct ifconf *)data; 904 register struct ifnet *ifp; 905 register struct ifaddr *ifa; 906 struct ifreq ifr, *ifrp; 907 int space = ifc->ifc_len, error = 0; 908 909 /* If ifc->ifc_len is 0, fill it in with the needed size and return. */ 910 if (space == 0) { 911 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) { 912 register struct sockaddr *sa; 913 914 if ((ifa = ifp->if_addrlist.tqh_first) == 0) 915 space += sizeof (ifr); 916 else 917 for (; ifa != 0; ifa = ifa->ifa_list.tqe_next) { 918 sa = ifa->ifa_addr; 919 #if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4) 920 if (cmd != OSIOCGIFCONF) 921 #endif 922 if (sa->sa_len > sizeof(*sa)) 923 space += sa->sa_len - 924 sizeof (*sa); 925 space += sizeof (ifr); 926 } 927 } 928 ifc->ifc_len = space; 929 return(0); 930 } 931 932 ifrp = ifc->ifc_req; 933 for (ifp = ifnet.tqh_first; space >= sizeof (ifr) && ifp != 0; 934 ifp = ifp->if_list.tqe_next) { 935 bcopy(ifp->if_xname, ifr.ifr_name, IFNAMSIZ); 936 if ((ifa = ifp->if_addrlist.tqh_first) == 0) { 937 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 938 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 939 sizeof(ifr)); 940 if (error) 941 break; 942 space -= sizeof (ifr), ifrp++; 943 } else 944 for (; space >= sizeof (ifr) && ifa != 0; 945 ifa = ifa->ifa_list.tqe_next) { 946 register struct sockaddr *sa = ifa->ifa_addr; 947 #if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4) 948 if (cmd == OSIOCGIFCONF) { 949 struct osockaddr *osa = 950 (struct osockaddr *)&ifr.ifr_addr; 951 ifr.ifr_addr = *sa; 952 osa->sa_family = sa->sa_family; 953 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 954 sizeof (ifr)); 955 ifrp++; 956 } else 957 #endif 958 if (sa->sa_len <= sizeof(*sa)) { 959 ifr.ifr_addr = *sa; 960 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 961 sizeof (ifr)); 962 ifrp++; 963 } else { 964 space -= sa->sa_len - sizeof(*sa); 965 if (space < sizeof (ifr)) 966 break; 967 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 968 sizeof (ifr.ifr_name)); 969 if (error == 0) 970 error = copyout((caddr_t)sa, 971 (caddr_t)&ifrp->ifr_addr, 972 sa->sa_len); 973 ifrp = (struct ifreq *)(sa->sa_len + 974 (caddr_t)&ifrp->ifr_addr); 975 } 976 if (error) 977 break; 978 space -= sizeof (ifr); 979 } 980 } 981 ifc->ifc_len -= space; 982 return (error); 983 } 984 985 /* 986 * Dummy functions replaced in ifnet during detach (if protocols decide to 987 * fiddle with the if during detach. 988 */ 989 void 990 if_detached_start(struct ifnet *ifp) 991 { 992 struct mbuf *m; 993 994 while (1) { 995 IF_DEQUEUE(&ifp->if_snd, m); 996 997 if (m == NULL) 998 return; 999 m_freem(m); 1000 } 1001 } 1002 1003 int 1004 if_detached_ioctl(struct ifnet *ifp, u_long a, caddr_t b) 1005 { 1006 return ENODEV; 1007 } 1008 1009 void 1010 if_detached_watchdog(struct ifnet *ifp) 1011 { 1012 /* nothing */ 1013 } 1014 1015 /* 1016 * Set/clear promiscuous mode on interface ifp based on the truth value 1017 * of pswitch. The calls are reference counted so that only the first 1018 * "on" request actually has an effect, as does the final "off" request. 1019 * Results are undefined if the "off" and "on" requests are not matched. 1020 */ 1021 int 1022 ifpromisc(ifp, pswitch) 1023 struct ifnet *ifp; 1024 int pswitch; 1025 { 1026 struct ifreq ifr; 1027 1028 if (pswitch) { 1029 /* 1030 * If the device is not configured up, we cannot put it in 1031 * promiscuous mode. 1032 */ 1033 if ((ifp->if_flags & IFF_UP) == 0) 1034 return (ENETDOWN); 1035 if (ifp->if_pcount++ != 0) 1036 return (0); 1037 ifp->if_flags |= IFF_PROMISC; 1038 } else { 1039 if (--ifp->if_pcount > 0) 1040 return (0); 1041 ifp->if_flags &= ~IFF_PROMISC; 1042 /* 1043 * If the device is not configured up, we should not need to 1044 * turn off promiscuous mode (device should have turned it 1045 * off when interface went down; and will look at IFF_PROMISC 1046 * again next time interface comes up). 1047 */ 1048 if ((ifp->if_flags & IFF_UP) == 0) 1049 return (0); 1050 } 1051 ifr.ifr_flags = ifp->if_flags; 1052 return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr)); 1053 } 1054