1 /* $OpenBSD: if.c,v 1.50 2001/12/09 12:57:26 jason 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 TAILQ_FOREACH(ifp, &ifnet, if_list) { 413 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 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 } 425 return (NULL); 426 } 427 /* 428 * Locate the point to point interface with a given destination address. 429 */ 430 /*ARGSUSED*/ 431 struct ifaddr * 432 ifa_ifwithdstaddr(addr) 433 register struct sockaddr *addr; 434 { 435 register struct ifnet *ifp; 436 register struct ifaddr *ifa; 437 438 TAILQ_FOREACH(ifp, &ifnet, if_list) { 439 if (ifp->if_flags & IFF_POINTOPOINT) 440 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 441 if (ifa->ifa_addr->sa_family != addr->sa_family || 442 ifa->ifa_dstaddr == NULL) 443 continue; 444 if (equal(addr, ifa->ifa_dstaddr)) 445 return (ifa); 446 } 447 } 448 return (NULL); 449 } 450 451 /* 452 * Find an interface on a specific network. If many, choice 453 * is most specific found. 454 */ 455 struct ifaddr * 456 ifa_ifwithnet(addr) 457 struct sockaddr *addr; 458 { 459 register struct ifnet *ifp; 460 register struct ifaddr *ifa; 461 struct ifaddr *ifa_maybe = 0; 462 u_int af = addr->sa_family; 463 char *addr_data = addr->sa_data, *cplim; 464 465 if (af == AF_LINK) { 466 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr; 467 if (sdl->sdl_index && sdl->sdl_index <= if_index) 468 return (ifnet_addrs[sdl->sdl_index]); 469 } 470 TAILQ_FOREACH(ifp, &ifnet, if_list) { 471 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 472 register char *cp, *cp2, *cp3; 473 474 if (ifa->ifa_addr->sa_family != af || 475 ifa->ifa_netmask == 0) 476 next: continue; 477 cp = addr_data; 478 cp2 = ifa->ifa_addr->sa_data; 479 cp3 = ifa->ifa_netmask->sa_data; 480 cplim = (char *)ifa->ifa_netmask + 481 ifa->ifa_netmask->sa_len; 482 while (cp3 < cplim) 483 if ((*cp++ ^ *cp2++) & *cp3++) 484 /* want to continue for() loop */ 485 goto next; 486 if (ifa_maybe == 0 || 487 rn_refines((caddr_t)ifa->ifa_netmask, 488 (caddr_t)ifa_maybe->ifa_netmask)) 489 ifa_maybe = ifa; 490 } 491 } 492 return (ifa_maybe); 493 } 494 495 /* 496 * Find an interface using a specific address family 497 */ 498 struct ifaddr * 499 ifa_ifwithaf(af) 500 register int af; 501 { 502 register struct ifnet *ifp; 503 register struct ifaddr *ifa; 504 505 TAILQ_FOREACH(ifp, &ifnet, if_list) { 506 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 507 if (ifa->ifa_addr->sa_family == af) 508 return (ifa); 509 } 510 } 511 return (NULL); 512 } 513 514 /* 515 * Find an interface address specific to an interface best matching 516 * a given address. 517 */ 518 struct ifaddr * 519 ifaof_ifpforaddr(addr, ifp) 520 struct sockaddr *addr; 521 register struct ifnet *ifp; 522 { 523 register struct ifaddr *ifa; 524 register char *cp, *cp2, *cp3; 525 register char *cplim; 526 struct ifaddr *ifa_maybe = 0; 527 u_int af = addr->sa_family; 528 529 if (af >= AF_MAX) 530 return (NULL); 531 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 532 if (ifa->ifa_addr->sa_family != af) 533 continue; 534 ifa_maybe = ifa; 535 if (ifa->ifa_netmask == 0) { 536 if (equal(addr, ifa->ifa_addr) || 537 (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))) 538 return (ifa); 539 continue; 540 } 541 cp = addr->sa_data; 542 cp2 = ifa->ifa_addr->sa_data; 543 cp3 = ifa->ifa_netmask->sa_data; 544 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 545 for (; cp3 < cplim; cp3++) 546 if ((*cp++ ^ *cp2++) & *cp3) 547 break; 548 if (cp3 == cplim) 549 return (ifa); 550 } 551 return (ifa_maybe); 552 } 553 554 /* 555 * Default action when installing a route with a Link Level gateway. 556 * Lookup an appropriate real ifa to point to. 557 * This should be moved to /sys/net/link.c eventually. 558 */ 559 void 560 link_rtrequest(cmd, rt, info) 561 int cmd; 562 register struct rtentry *rt; 563 struct rt_addrinfo *info; 564 { 565 register struct ifaddr *ifa; 566 struct sockaddr *dst; 567 struct ifnet *ifp; 568 569 if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || 570 ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) 571 return; 572 if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) { 573 IFAFREE(rt->rt_ifa); 574 rt->rt_ifa = ifa; 575 ifa->ifa_refcnt++; 576 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) 577 ifa->ifa_rtrequest(cmd, rt, info); 578 } 579 } 580 581 /* 582 * Mark an interface down and notify protocols of 583 * the transition. 584 * NOTE: must be called at splsoftnet or equivalent. 585 */ 586 void 587 if_down(ifp) 588 register struct ifnet *ifp; 589 { 590 register struct ifaddr *ifa; 591 struct radix_node_head *rnh; 592 int i; 593 594 ifp->if_flags &= ~IFF_UP; 595 microtime(&ifp->if_lastchange); 596 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 597 pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 598 } 599 IFQ_PURGE(&ifp->if_snd); 600 rt_ifmsg(ifp); 601 602 /* 603 * Find and mark as ignore all routes which are using this interface. 604 * XXX Factor out into a route.c function? 605 */ 606 for (i = 1; i <= AF_MAX; i++) { 607 rnh = rt_tables[i]; 608 if (rnh) 609 (*rnh->rnh_walktree)(rnh, if_mark_ignore, ifp); 610 } 611 } 612 613 /* 614 * Mark an interface up and notify protocols of 615 * the transition. 616 * NOTE: must be called at splsoftnet or equivalent. 617 */ 618 void 619 if_up(ifp) 620 register struct ifnet *ifp; 621 { 622 #ifdef notyet 623 register struct ifaddr *ifa; 624 #endif 625 struct radix_node_head *rnh; 626 int i; 627 628 ifp->if_flags |= IFF_UP; 629 microtime(&ifp->if_lastchange); 630 #ifdef notyet 631 /* this has no effect on IP, and will kill all ISO connections XXX */ 632 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 633 pfctlinput(PRC_IFUP, ifa->ifa_addr); 634 } 635 #endif 636 rt_ifmsg(ifp); 637 #ifdef INET6 638 in6_if_up(ifp); 639 #endif 640 641 /* 642 * Find and unignore all routes which are using this interface. 643 * XXX Factor out into a route.c function? 644 */ 645 for (i = 1; i <= AF_MAX; i++) { 646 rnh = rt_tables[i]; 647 if (rnh) 648 (*rnh->rnh_walktree)(rnh, if_mark_unignore, ifp); 649 } 650 } 651 652 /* 653 * Flush an interface queue. 654 */ 655 void 656 if_qflush(ifq) 657 register struct ifqueue *ifq; 658 { 659 register struct mbuf *m, *n; 660 661 n = ifq->ifq_head; 662 while ((m = n) != NULL) { 663 n = m->m_act; 664 m_freem(m); 665 } 666 ifq->ifq_head = 0; 667 ifq->ifq_tail = 0; 668 ifq->ifq_len = 0; 669 } 670 671 /* 672 * Handle interface watchdog timer routines. Called 673 * from softclock, we decrement timers (if set) and 674 * call the appropriate interface routine on expiration. 675 */ 676 void 677 if_slowtimo(arg) 678 void *arg; 679 { 680 struct timeout *to = (struct timeout *)arg; 681 struct ifnet *ifp; 682 int s = splimp(); 683 684 TAILQ_FOREACH(ifp, &ifnet, if_list) { 685 if (ifp->if_timer == 0 || --ifp->if_timer) 686 continue; 687 if (ifp->if_watchdog) 688 (*ifp->if_watchdog)(ifp); 689 } 690 splx(s); 691 timeout_add(to, hz / IFNET_SLOWHZ); 692 } 693 694 /* 695 * Map interface name to 696 * interface structure pointer. 697 */ 698 struct ifnet * 699 ifunit(name) 700 register char *name; 701 { 702 register struct ifnet *ifp; 703 704 TAILQ_FOREACH(ifp, &ifnet, if_list) { 705 if (strcmp(ifp->if_xname, name) == 0) 706 return (ifp); 707 } 708 return (NULL); 709 } 710 711 /* 712 * Interface ioctls. 713 */ 714 int 715 ifioctl(so, cmd, data, p) 716 struct socket *so; 717 u_long cmd; 718 caddr_t data; 719 struct proc *p; 720 { 721 register struct ifnet *ifp; 722 register struct ifreq *ifr; 723 int error = 0; 724 short oif_flags; 725 726 switch (cmd) { 727 728 case SIOCGIFCONF: 729 case OSIOCGIFCONF: 730 return (ifconf(cmd, data)); 731 } 732 ifr = (struct ifreq *)data; 733 ifp = ifunit(ifr->ifr_name); 734 if (ifp == 0) 735 return (ENXIO); 736 oif_flags = ifp->if_flags; 737 switch (cmd) { 738 739 case SIOCGIFFLAGS: 740 ifr->ifr_flags = ifp->if_flags; 741 break; 742 743 case SIOCGIFMETRIC: 744 ifr->ifr_metric = ifp->if_metric; 745 break; 746 747 case SIOCGIFMTU: 748 ifr->ifr_mtu = ifp->if_mtu; 749 break; 750 751 case SIOCGIFDATA: 752 error = copyout((caddr_t)&ifp->if_data, ifr->ifr_data, 753 sizeof(ifp->if_data)); 754 break; 755 756 case SIOCSIFFLAGS: 757 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 758 return (error); 759 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 760 int s = splimp(); 761 if_down(ifp); 762 splx(s); 763 } 764 if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) { 765 int s = splimp(); 766 if_up(ifp); 767 splx(s); 768 } 769 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 770 (ifr->ifr_flags &~ IFF_CANTCHANGE); 771 if (ifp->if_ioctl) 772 (void) (*ifp->if_ioctl)(ifp, cmd, data); 773 break; 774 775 case SIOCSIFMETRIC: 776 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 777 return (error); 778 ifp->if_metric = ifr->ifr_metric; 779 break; 780 781 case SIOCSIFMTU: 782 { 783 #ifdef INET6 784 int oldmtu = ifp->if_mtu; 785 #endif 786 787 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 788 return (error); 789 if (ifp->if_ioctl == NULL) 790 return (EOPNOTSUPP); 791 error = (*ifp->if_ioctl)(ifp, cmd, data); 792 793 /* 794 * If the link MTU changed, do network layer specific procedure. 795 */ 796 #ifdef INET6 797 if (ifp->if_mtu != oldmtu) 798 nd6_setmtu(ifp); 799 #endif 800 break; 801 } 802 803 case SIOCSIFPHYADDR: 804 case SIOCDIFPHYADDR: 805 #ifdef INET6 806 case SIOCSIFPHYADDR_IN6: 807 #endif 808 case SIOCSLIFPHYADDR: 809 case SIOCADDMULTI: 810 case SIOCDELMULTI: 811 case SIOCSIFMEDIA: 812 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 813 return (error); 814 /* FALLTHROUGH */ 815 case SIOCGIFPSRCADDR: 816 case SIOCGIFPDSTADDR: 817 case SIOCGLIFPHYADDR: 818 case SIOCGIFMEDIA: 819 if (ifp->if_ioctl == 0) 820 return (EOPNOTSUPP); 821 error = (*ifp->if_ioctl)(ifp, cmd, data); 822 break; 823 824 default: 825 if (so->so_proto == 0) 826 return (EOPNOTSUPP); 827 #if !defined(COMPAT_43) && !defined(COMPAT_LINUX) && !defined(COMPAT_SVR4) 828 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 829 (struct mbuf *) cmd, (struct mbuf *) data, 830 (struct mbuf *) ifp)); 831 #else 832 { 833 u_long ocmd = cmd; 834 835 switch (cmd) { 836 837 case SIOCSIFADDR: 838 case SIOCSIFDSTADDR: 839 case SIOCSIFBRDADDR: 840 case SIOCSIFNETMASK: 841 #if BYTE_ORDER != BIG_ENDIAN 842 if (ifr->ifr_addr.sa_family == 0 && 843 ifr->ifr_addr.sa_len < 16) { 844 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 845 ifr->ifr_addr.sa_len = 16; 846 } 847 #else 848 if (ifr->ifr_addr.sa_len == 0) 849 ifr->ifr_addr.sa_len = 16; 850 #endif 851 break; 852 853 case OSIOCGIFADDR: 854 cmd = SIOCGIFADDR; 855 break; 856 857 case OSIOCGIFDSTADDR: 858 cmd = SIOCGIFDSTADDR; 859 break; 860 861 case OSIOCGIFBRDADDR: 862 cmd = SIOCGIFBRDADDR; 863 break; 864 865 case OSIOCGIFNETMASK: 866 cmd = SIOCGIFNETMASK; 867 } 868 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 869 (struct mbuf *) cmd, (struct mbuf *) data, 870 (struct mbuf *) ifp)); 871 switch (ocmd) { 872 873 case OSIOCGIFADDR: 874 case OSIOCGIFDSTADDR: 875 case OSIOCGIFBRDADDR: 876 case OSIOCGIFNETMASK: 877 *(u_int16_t *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 878 } 879 880 } 881 #endif 882 break; 883 } 884 885 if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) { 886 #ifdef INET6 887 if ((ifp->if_flags & IFF_UP) != 0) { 888 int s = splsoftnet(); 889 in6_if_up(ifp); 890 splx(s); 891 } 892 #endif 893 } 894 return (error); 895 } 896 897 /* 898 * Return interface configuration 899 * of system. List may be used 900 * in later ioctl's (above) to get 901 * other information. 902 */ 903 /*ARGSUSED*/ 904 int 905 ifconf(cmd, data) 906 u_long cmd; 907 caddr_t data; 908 { 909 register struct ifconf *ifc = (struct ifconf *)data; 910 register struct ifnet *ifp; 911 register struct ifaddr *ifa; 912 struct ifreq ifr, *ifrp; 913 int space = ifc->ifc_len, error = 0; 914 915 /* If ifc->ifc_len is 0, fill it in with the needed size and return. */ 916 if (space == 0) { 917 TAILQ_FOREACH(ifp, &ifnet, if_list) { 918 register struct sockaddr *sa; 919 920 if (TAILQ_EMPTY(&ifp->if_addrlist)) 921 space += sizeof (ifr); 922 else 923 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 924 sa = ifa->ifa_addr; 925 #if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4) 926 if (cmd != OSIOCGIFCONF) 927 #endif 928 if (sa->sa_len > sizeof(*sa)) 929 space += sa->sa_len - 930 sizeof (*sa); 931 space += sizeof (ifr); 932 } 933 } 934 ifc->ifc_len = space; 935 return(0); 936 } 937 938 ifrp = ifc->ifc_req; 939 for (ifp = TAILQ_FIRST(&ifnet); space >= sizeof(ifr) && 940 ifp != TAILQ_END(&ifnet); ifp = TAILQ_NEXT(ifp, if_list)) { 941 bcopy(ifp->if_xname, ifr.ifr_name, IFNAMSIZ); 942 if (TAILQ_EMPTY(&ifp->if_addrlist)) { 943 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 944 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 945 sizeof(ifr)); 946 if (error) 947 break; 948 space -= sizeof (ifr), ifrp++; 949 } else 950 for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 951 space >= sizeof (ifr) && 952 ifa != TAILQ_END(&ifp->if_addrlist); 953 ifa = TAILQ_NEXT(ifa, ifa_list)) { 954 register struct sockaddr *sa = ifa->ifa_addr; 955 #if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4) 956 if (cmd == OSIOCGIFCONF) { 957 struct osockaddr *osa = 958 (struct osockaddr *)&ifr.ifr_addr; 959 ifr.ifr_addr = *sa; 960 osa->sa_family = sa->sa_family; 961 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 962 sizeof (ifr)); 963 ifrp++; 964 } else 965 #endif 966 if (sa->sa_len <= sizeof(*sa)) { 967 ifr.ifr_addr = *sa; 968 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 969 sizeof (ifr)); 970 ifrp++; 971 } else { 972 space -= sa->sa_len - sizeof(*sa); 973 if (space < sizeof (ifr)) 974 break; 975 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 976 sizeof (ifr.ifr_name)); 977 if (error == 0) 978 error = copyout((caddr_t)sa, 979 (caddr_t)&ifrp->ifr_addr, 980 sa->sa_len); 981 ifrp = (struct ifreq *)(sa->sa_len + 982 (caddr_t)&ifrp->ifr_addr); 983 } 984 if (error) 985 break; 986 space -= sizeof (ifr); 987 } 988 } 989 ifc->ifc_len -= space; 990 return (error); 991 } 992 993 /* 994 * Dummy functions replaced in ifnet during detach (if protocols decide to 995 * fiddle with the if during detach. 996 */ 997 void 998 if_detached_start(struct ifnet *ifp) 999 { 1000 struct mbuf *m; 1001 1002 while (1) { 1003 IF_DEQUEUE(&ifp->if_snd, m); 1004 1005 if (m == NULL) 1006 return; 1007 m_freem(m); 1008 } 1009 } 1010 1011 int 1012 if_detached_ioctl(struct ifnet *ifp, u_long a, caddr_t b) 1013 { 1014 return ENODEV; 1015 } 1016 1017 void 1018 if_detached_watchdog(struct ifnet *ifp) 1019 { 1020 /* nothing */ 1021 } 1022 1023 /* 1024 * Set/clear promiscuous mode on interface ifp based on the truth value 1025 * of pswitch. The calls are reference counted so that only the first 1026 * "on" request actually has an effect, as does the final "off" request. 1027 * Results are undefined if the "off" and "on" requests are not matched. 1028 */ 1029 int 1030 ifpromisc(ifp, pswitch) 1031 struct ifnet *ifp; 1032 int pswitch; 1033 { 1034 struct ifreq ifr; 1035 1036 if (pswitch) { 1037 /* 1038 * If the device is not configured up, we cannot put it in 1039 * promiscuous mode. 1040 */ 1041 if ((ifp->if_flags & IFF_UP) == 0) 1042 return (ENETDOWN); 1043 if (ifp->if_pcount++ != 0) 1044 return (0); 1045 ifp->if_flags |= IFF_PROMISC; 1046 } else { 1047 if (--ifp->if_pcount > 0) 1048 return (0); 1049 ifp->if_flags &= ~IFF_PROMISC; 1050 /* 1051 * If the device is not configured up, we should not need to 1052 * turn off promiscuous mode (device should have turned it 1053 * off when interface went down; and will look at IFF_PROMISC 1054 * again next time interface comes up). 1055 */ 1056 if ((ifp->if_flags & IFF_UP) == 0) 1057 return (0); 1058 } 1059 ifr.ifr_flags = ifp->if_flags; 1060 return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr)); 1061 } 1062