1 /* 2 * Copyright (c) 1980, 1986, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)if.c 8.3 (Berkeley) 1/4/94 34 * $Id: if.c,v 1.48 1997/05/03 21:07:13 peter Exp $ 35 */ 36 37 #include <sys/param.h> 38 #include <sys/queue.h> 39 #include <sys/mbuf.h> 40 #include <sys/systm.h> 41 #include <sys/proc.h> 42 #include <sys/socket.h> 43 #include <sys/socketvar.h> 44 #include <sys/protosw.h> 45 #include <sys/kernel.h> 46 #include <sys/sockio.h> 47 #include <sys/errno.h> 48 #include <sys/syslog.h> 49 #include <sys/sysctl.h> 50 51 #include <net/if.h> 52 #include <net/if_dl.h> 53 #include <net/if_types.h> 54 #include <net/radix.h> 55 56 /* 57 * System initialization 58 */ 59 60 static int ifconf __P((int, caddr_t)); 61 static void ifinit __P((void *)); 62 static void if_qflush __P((struct ifqueue *)); 63 static void if_slowtimo __P((void *)); 64 static void link_rtrequest __P((int, struct rtentry *, struct sockaddr *)); 65 66 SYSINIT(interfaces, SI_SUB_PROTO_IF, SI_ORDER_FIRST, ifinit, NULL) 67 68 69 int ifqmaxlen = IFQ_MAXLEN; 70 struct ifnethead ifnet; /* depend on static init XXX */ 71 72 /* 73 * Network interface utility routines. 74 * 75 * Routines with ifa_ifwith* names take sockaddr *'s as 76 * parameters. 77 * 78 * This routine assumes that it will be called at splimp() or higher. 79 */ 80 /* ARGSUSED*/ 81 void 82 ifinit(dummy) 83 void *dummy; 84 { 85 register struct ifnet *ifp; 86 87 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) 88 if (ifp->if_snd.ifq_maxlen == 0) 89 ifp->if_snd.ifq_maxlen = ifqmaxlen; 90 if_slowtimo(0); 91 } 92 93 int if_index = 0; 94 struct ifaddr **ifnet_addrs; 95 96 97 /* 98 * Attach an interface to the 99 * list of "active" interfaces. 100 */ 101 void 102 if_attach(ifp) 103 struct ifnet *ifp; 104 { 105 unsigned socksize, ifasize; 106 int namelen, masklen; 107 char workbuf[64]; 108 register struct sockaddr_dl *sdl; 109 register struct ifaddr *ifa; 110 static int if_indexlim = 8; 111 static int inited; 112 113 if (!inited) { 114 TAILQ_INIT(&ifnet); 115 inited = 1; 116 } 117 118 TAILQ_INSERT_TAIL(&ifnet, ifp, if_link); 119 ifp->if_index = ++if_index; 120 /* 121 * XXX - 122 * The old code would work if the interface passed a pre-existing 123 * chain of ifaddrs to this code. We don't trust our callers to 124 * properly initialize the tailq, however, so we no longer allow 125 * this unlikely case. 126 */ 127 TAILQ_INIT(&ifp->if_addrhead); 128 LIST_INIT(&ifp->if_multiaddrs); 129 microtime(&ifp->if_lastchange); 130 if (ifnet_addrs == 0 || if_index >= if_indexlim) { 131 unsigned n = (if_indexlim <<= 1) * sizeof(ifa); 132 struct ifaddr **q = (struct ifaddr **) 133 malloc(n, M_IFADDR, M_WAITOK); 134 bzero((caddr_t)q, n); 135 if (ifnet_addrs) { 136 bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2); 137 free((caddr_t)ifnet_addrs, M_IFADDR); 138 } 139 ifnet_addrs = q; 140 } 141 /* 142 * create a Link Level name for this device 143 */ 144 namelen = sprintf(workbuf, "%s%d", ifp->if_name, ifp->if_unit); 145 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) 146 masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen; 147 socksize = masklen + ifp->if_addrlen; 148 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) 149 socksize = ROUNDUP(socksize); 150 if (socksize < sizeof(*sdl)) 151 socksize = sizeof(*sdl); 152 ifasize = sizeof(*ifa) + 2 * socksize; 153 ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK); 154 if (ifa) { 155 bzero((caddr_t)ifa, ifasize); 156 sdl = (struct sockaddr_dl *)(ifa + 1); 157 sdl->sdl_len = socksize; 158 sdl->sdl_family = AF_LINK; 159 bcopy(workbuf, sdl->sdl_data, namelen); 160 sdl->sdl_nlen = namelen; 161 sdl->sdl_index = ifp->if_index; 162 sdl->sdl_type = ifp->if_type; 163 ifnet_addrs[if_index - 1] = ifa; 164 ifa->ifa_ifp = ifp; 165 ifa->ifa_rtrequest = link_rtrequest; 166 ifa->ifa_addr = (struct sockaddr *)sdl; 167 sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); 168 ifa->ifa_netmask = (struct sockaddr *)sdl; 169 sdl->sdl_len = masklen; 170 while (namelen != 0) 171 sdl->sdl_data[--namelen] = 0xff; 172 TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link); 173 } 174 } 175 /* 176 * Locate an interface based on a complete address. 177 */ 178 /*ARGSUSED*/ 179 struct ifaddr * 180 ifa_ifwithaddr(addr) 181 register struct sockaddr *addr; 182 { 183 register struct ifnet *ifp; 184 register struct ifaddr *ifa; 185 186 #define equal(a1, a2) \ 187 (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) 188 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) 189 for (ifa = ifp->if_addrhead.tqh_first; ifa; 190 ifa = ifa->ifa_link.tqe_next) { 191 if (ifa->ifa_addr->sa_family != addr->sa_family) 192 continue; 193 if (equal(addr, ifa->ifa_addr)) 194 return (ifa); 195 if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && 196 equal(ifa->ifa_broadaddr, addr)) 197 return (ifa); 198 } 199 return ((struct ifaddr *)0); 200 } 201 /* 202 * Locate the point to point interface with a given destination address. 203 */ 204 /*ARGSUSED*/ 205 struct ifaddr * 206 ifa_ifwithdstaddr(addr) 207 register struct sockaddr *addr; 208 { 209 register struct ifnet *ifp; 210 register struct ifaddr *ifa; 211 212 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) 213 if (ifp->if_flags & IFF_POINTOPOINT) 214 for (ifa = ifp->if_addrhead.tqh_first; ifa; 215 ifa = ifa->ifa_link.tqe_next) { 216 if (ifa->ifa_addr->sa_family != addr->sa_family) 217 continue; 218 if (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)) 219 return (ifa); 220 } 221 return ((struct ifaddr *)0); 222 } 223 224 /* 225 * Find an interface on a specific network. If many, choice 226 * is most specific found. 227 */ 228 struct ifaddr * 229 ifa_ifwithnet(addr) 230 struct sockaddr *addr; 231 { 232 register struct ifnet *ifp; 233 register struct ifaddr *ifa; 234 struct ifaddr *ifa_maybe = (struct ifaddr *) 0; 235 u_int af = addr->sa_family; 236 char *addr_data = addr->sa_data, *cplim; 237 238 if (af == AF_LINK) { 239 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr; 240 if (sdl->sdl_index && sdl->sdl_index <= if_index) 241 return (ifnet_addrs[sdl->sdl_index - 1]); 242 } 243 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) { 244 for (ifa = ifp->if_addrhead.tqh_first; ifa; 245 ifa = ifa->ifa_link.tqe_next) { 246 register char *cp, *cp2, *cp3; 247 248 if (ifa->ifa_addr->sa_family != af) 249 next: continue; 250 if (ifp->if_flags & IFF_POINTOPOINT) { 251 if (ifa->ifa_dstaddr != 0 252 && equal(addr, ifa->ifa_dstaddr)) 253 return (ifa); 254 } else { 255 if (ifa->ifa_netmask == 0) 256 continue; 257 cp = addr_data; 258 cp2 = ifa->ifa_addr->sa_data; 259 cp3 = ifa->ifa_netmask->sa_data; 260 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 261 while (cp3 < cplim) 262 if ((*cp++ ^ *cp2++) & *cp3++) 263 goto next; 264 if (ifa_maybe == 0 || 265 rn_refines((caddr_t)ifa->ifa_netmask, 266 (caddr_t)ifa_maybe->ifa_netmask)) 267 ifa_maybe = ifa; 268 } 269 } 270 } 271 return (ifa_maybe); 272 } 273 274 /* 275 * Find an interface address specific to an interface best matching 276 * a given address. 277 */ 278 struct ifaddr * 279 ifaof_ifpforaddr(addr, ifp) 280 struct sockaddr *addr; 281 register struct ifnet *ifp; 282 { 283 register struct ifaddr *ifa; 284 register char *cp, *cp2, *cp3; 285 register char *cplim; 286 struct ifaddr *ifa_maybe = 0; 287 u_int af = addr->sa_family; 288 289 if (af >= AF_MAX) 290 return (0); 291 for (ifa = ifp->if_addrhead.tqh_first; ifa; 292 ifa = ifa->ifa_link.tqe_next) { 293 if (ifa->ifa_addr->sa_family != af) 294 continue; 295 if (ifa_maybe == 0) 296 ifa_maybe = ifa; 297 if (ifa->ifa_netmask == 0) { 298 if (equal(addr, ifa->ifa_addr) || 299 (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))) 300 return (ifa); 301 continue; 302 } 303 if (ifp->if_flags & IFF_POINTOPOINT) { 304 if (equal(addr, ifa->ifa_dstaddr)) 305 return (ifa); 306 } else { 307 cp = addr->sa_data; 308 cp2 = ifa->ifa_addr->sa_data; 309 cp3 = ifa->ifa_netmask->sa_data; 310 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 311 for (; cp3 < cplim; cp3++) 312 if ((*cp++ ^ *cp2++) & *cp3) 313 break; 314 if (cp3 == cplim) 315 return (ifa); 316 } 317 } 318 return (ifa_maybe); 319 } 320 321 #include <net/route.h> 322 323 /* 324 * Default action when installing a route with a Link Level gateway. 325 * Lookup an appropriate real ifa to point to. 326 * This should be moved to /sys/net/link.c eventually. 327 */ 328 static void 329 link_rtrequest(cmd, rt, sa) 330 int cmd; 331 register struct rtentry *rt; 332 struct sockaddr *sa; 333 { 334 register struct ifaddr *ifa; 335 struct sockaddr *dst; 336 struct ifnet *ifp; 337 338 if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || 339 ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) 340 return; 341 ifa = ifaof_ifpforaddr(dst, ifp); 342 if (ifa) { 343 IFAFREE(rt->rt_ifa); 344 rt->rt_ifa = ifa; 345 ifa->ifa_refcnt++; 346 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) 347 ifa->ifa_rtrequest(cmd, rt, sa); 348 } 349 } 350 351 /* 352 * Mark an interface down and notify protocols of 353 * the transition. 354 * NOTE: must be called at splnet or eqivalent. 355 */ 356 void 357 if_down(ifp) 358 register struct ifnet *ifp; 359 { 360 register struct ifaddr *ifa; 361 362 ifp->if_flags &= ~IFF_UP; 363 microtime(&ifp->if_lastchange); 364 for (ifa = ifp->if_addrhead.tqh_first; ifa; 365 ifa = ifa->ifa_link.tqe_next) 366 pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 367 if_qflush(&ifp->if_snd); 368 rt_ifmsg(ifp); 369 } 370 371 /* 372 * Mark an interface up and notify protocols of 373 * the transition. 374 * NOTE: must be called at splnet or eqivalent. 375 */ 376 void 377 if_up(ifp) 378 register struct ifnet *ifp; 379 { 380 register struct ifaddr *ifa; 381 382 ifp->if_flags |= IFF_UP; 383 microtime(&ifp->if_lastchange); 384 for (ifa = ifp->if_addrhead.tqh_first; ifa; 385 ifa = ifa->ifa_link.tqe_next) 386 pfctlinput(PRC_IFUP, ifa->ifa_addr); 387 rt_ifmsg(ifp); 388 } 389 390 /* 391 * Flush an interface queue. 392 */ 393 static void 394 if_qflush(ifq) 395 register struct ifqueue *ifq; 396 { 397 register struct mbuf *m, *n; 398 399 n = ifq->ifq_head; 400 while ((m = n) != 0) { 401 n = m->m_act; 402 m_freem(m); 403 } 404 ifq->ifq_head = 0; 405 ifq->ifq_tail = 0; 406 ifq->ifq_len = 0; 407 } 408 409 /* 410 * Handle interface watchdog timer routines. Called 411 * from softclock, we decrement timers (if set) and 412 * call the appropriate interface routine on expiration. 413 */ 414 static void 415 if_slowtimo(arg) 416 void *arg; 417 { 418 register struct ifnet *ifp; 419 int s = splimp(); 420 421 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) { 422 if (ifp->if_timer == 0 || --ifp->if_timer) 423 continue; 424 if (ifp->if_watchdog) 425 (*ifp->if_watchdog)(ifp); 426 } 427 splx(s); 428 timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ); 429 } 430 431 /* 432 * Map interface name to 433 * interface structure pointer. 434 */ 435 struct ifnet * 436 ifunit(name) 437 register char *name; 438 { 439 register char *cp; 440 register struct ifnet *ifp; 441 int unit; 442 unsigned len; 443 char *ep, c; 444 445 for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 446 if (*cp >= '0' && *cp <= '9') 447 break; 448 if (*cp == '\0' || cp == name + IFNAMSIZ) 449 return ((struct ifnet *)0); 450 /* 451 * Save first char of unit, and pointer to it, 452 * so we can put a null there to avoid matching 453 * initial substrings of interface names. 454 */ 455 len = cp - name + 1; 456 c = *cp; 457 ep = cp; 458 for (unit = 0; *cp >= '0' && *cp <= '9'; ) 459 unit = unit * 10 + *cp++ - '0'; 460 if (*cp != '\0') 461 return 0; /* no trailing garbage allowed */ 462 *ep = 0; 463 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) { 464 if (bcmp(ifp->if_name, name, len)) 465 continue; 466 if (unit == ifp->if_unit) 467 break; 468 } 469 *ep = c; 470 return (ifp); 471 } 472 473 /* 474 * Interface ioctls. 475 */ 476 int 477 ifioctl(so, cmd, data, p) 478 struct socket *so; 479 int cmd; 480 caddr_t data; 481 struct proc *p; 482 { 483 register struct ifnet *ifp; 484 register struct ifreq *ifr; 485 int error; 486 487 switch (cmd) { 488 489 case SIOCGIFCONF: 490 case OSIOCGIFCONF: 491 return (ifconf(cmd, data)); 492 } 493 ifr = (struct ifreq *)data; 494 ifp = ifunit(ifr->ifr_name); 495 if (ifp == 0) 496 return (ENXIO); 497 switch (cmd) { 498 499 case SIOCGIFFLAGS: 500 ifr->ifr_flags = ifp->if_flags; 501 break; 502 503 case SIOCGIFMETRIC: 504 ifr->ifr_metric = ifp->if_metric; 505 break; 506 507 case SIOCGIFMTU: 508 ifr->ifr_mtu = ifp->if_mtu; 509 break; 510 511 case SIOCGIFPHYS: 512 ifr->ifr_phys = ifp->if_physical; 513 break; 514 515 case SIOCSIFFLAGS: 516 error = suser(p->p_ucred, &p->p_acflag); 517 if (error) 518 return (error); 519 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 520 int s = splimp(); 521 if_down(ifp); 522 splx(s); 523 } 524 if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) { 525 int s = splimp(); 526 if_up(ifp); 527 splx(s); 528 } 529 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 530 (ifr->ifr_flags &~ IFF_CANTCHANGE); 531 if (ifp->if_ioctl) 532 (void) (*ifp->if_ioctl)(ifp, cmd, data); 533 microtime(&ifp->if_lastchange); 534 break; 535 536 case SIOCSIFMETRIC: 537 error = suser(p->p_ucred, &p->p_acflag); 538 if (error) 539 return (error); 540 ifp->if_metric = ifr->ifr_metric; 541 microtime(&ifp->if_lastchange); 542 break; 543 544 case SIOCSIFPHYS: 545 error = suser(p->p_ucred, &p->p_acflag); 546 if (error) 547 return error; 548 if (!ifp->if_ioctl) 549 return EOPNOTSUPP; 550 error = (*ifp->if_ioctl)(ifp, cmd, data); 551 if (error == 0) 552 microtime(&ifp->if_lastchange); 553 return(error); 554 555 case SIOCSIFMTU: 556 error = suser(p->p_ucred, &p->p_acflag); 557 if (error) 558 return (error); 559 if (ifp->if_ioctl == NULL) 560 return (EOPNOTSUPP); 561 /* 562 * 72 was chosen below because it is the size of a TCP/IP 563 * header (40) + the minimum mss (32). 564 */ 565 if (ifr->ifr_mtu < 72 || ifr->ifr_mtu > 65535) 566 return (EINVAL); 567 error = (*ifp->if_ioctl)(ifp, cmd, data); 568 if (error == 0) 569 microtime(&ifp->if_lastchange); 570 return(error); 571 572 case SIOCADDMULTI: 573 case SIOCDELMULTI: 574 error = suser(p->p_ucred, &p->p_acflag); 575 if (error) 576 return (error); 577 578 /* Don't allow group membership on non-multicast interfaces. */ 579 if ((ifp->if_flags & IFF_MULTICAST) == 0) 580 return EOPNOTSUPP; 581 582 /* Don't let users screw up protocols' entries. */ 583 if (ifr->ifr_addr.sa_family != AF_LINK) 584 return EINVAL; 585 586 if (cmd == SIOCADDMULTI) { 587 struct ifmultiaddr *ifma; 588 error = if_addmulti(ifp, &ifr->ifr_addr, &ifma); 589 } else { 590 error = if_delmulti(ifp, &ifr->ifr_addr); 591 } 592 if (error == 0) 593 microtime(&ifp->if_lastchange); 594 return error; 595 596 case SIOCSIFMEDIA: 597 error = suser(p->p_ucred, &p->p_acflag); 598 if (error) 599 return (error); 600 if (ifp->if_ioctl == 0) 601 return (EOPNOTSUPP); 602 error = (*ifp->if_ioctl)(ifp, cmd, data); 603 if (error == 0) 604 microtime(&ifp->if_lastchange); 605 return error; 606 607 case SIOCGIFMEDIA: 608 if (ifp->if_ioctl == 0) 609 return (EOPNOTSUPP); 610 return ((*ifp->if_ioctl)(ifp, cmd, data)); 611 612 default: 613 if (so->so_proto == 0) 614 return (EOPNOTSUPP); 615 #ifndef COMPAT_43 616 return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd, 617 data, 618 ifp)); 619 #else 620 { 621 int ocmd = cmd; 622 623 switch (cmd) { 624 625 case SIOCSIFDSTADDR: 626 case SIOCSIFADDR: 627 case SIOCSIFBRDADDR: 628 case SIOCSIFNETMASK: 629 #if BYTE_ORDER != BIG_ENDIAN 630 if (ifr->ifr_addr.sa_family == 0 && 631 ifr->ifr_addr.sa_len < 16) { 632 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 633 ifr->ifr_addr.sa_len = 16; 634 } 635 #else 636 if (ifr->ifr_addr.sa_len == 0) 637 ifr->ifr_addr.sa_len = 16; 638 #endif 639 break; 640 641 case OSIOCGIFADDR: 642 cmd = SIOCGIFADDR; 643 break; 644 645 case OSIOCGIFDSTADDR: 646 cmd = SIOCGIFDSTADDR; 647 break; 648 649 case OSIOCGIFBRDADDR: 650 cmd = SIOCGIFBRDADDR; 651 break; 652 653 case OSIOCGIFNETMASK: 654 cmd = SIOCGIFNETMASK; 655 } 656 error = ((*so->so_proto->pr_usrreqs->pru_control)(so, 657 cmd, 658 data, 659 ifp, p)); 660 switch (ocmd) { 661 662 case OSIOCGIFADDR: 663 case OSIOCGIFDSTADDR: 664 case OSIOCGIFBRDADDR: 665 case OSIOCGIFNETMASK: 666 *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 667 } 668 return (error); 669 670 } 671 #endif 672 } 673 return (0); 674 } 675 676 /* 677 * Set/clear promiscuous mode on interface ifp based on the truth value 678 * of pswitch. The calls are reference counted so that only the first 679 * "on" request actually has an effect, as does the final "off" request. 680 * Results are undefined if the "off" and "on" requests are not matched. 681 */ 682 int 683 ifpromisc(ifp, pswitch) 684 struct ifnet *ifp; 685 int pswitch; 686 { 687 struct ifreq ifr; 688 int error; 689 690 if (pswitch) { 691 /* 692 * If the device is not configured up, we cannot put it in 693 * promiscuous mode. 694 */ 695 if ((ifp->if_flags & IFF_UP) == 0) 696 return (ENETDOWN); 697 if (ifp->if_pcount++ != 0) 698 return (0); 699 ifp->if_flags |= IFF_PROMISC; 700 log(LOG_INFO, "%s%d: promiscuous mode enabled\n", 701 ifp->if_name, ifp->if_unit); 702 } else { 703 if (--ifp->if_pcount > 0) 704 return (0); 705 ifp->if_flags &= ~IFF_PROMISC; 706 } 707 ifr.ifr_flags = ifp->if_flags; 708 error = (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr); 709 if (error == 0) 710 rt_ifmsg(ifp); 711 return error; 712 } 713 714 /* 715 * Return interface configuration 716 * of system. List may be used 717 * in later ioctl's (above) to get 718 * other information. 719 */ 720 /*ARGSUSED*/ 721 static int 722 ifconf(cmd, data) 723 int cmd; 724 caddr_t data; 725 { 726 register struct ifconf *ifc = (struct ifconf *)data; 727 register struct ifnet *ifp = ifnet.tqh_first; 728 register struct ifaddr *ifa; 729 struct ifreq ifr, *ifrp; 730 int space = ifc->ifc_len, error = 0; 731 732 ifrp = ifc->ifc_req; 733 for (; space > sizeof (ifr) && ifp; ifp = ifp->if_link.tqe_next) { 734 char workbuf[64]; 735 int ifnlen; 736 737 ifnlen = sprintf(workbuf, "%s%d", ifp->if_name, ifp->if_unit); 738 if(ifnlen + 1 > sizeof ifr.ifr_name) { 739 error = ENAMETOOLONG; 740 } else { 741 strcpy(ifr.ifr_name, workbuf); 742 } 743 744 if ((ifa = ifp->if_addrhead.tqh_first) == 0) { 745 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 746 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 747 sizeof (ifr)); 748 if (error) 749 break; 750 space -= sizeof (ifr), ifrp++; 751 } else 752 for ( ; space > sizeof (ifr) && ifa; 753 ifa = ifa->ifa_link.tqe_next) { 754 register struct sockaddr *sa = ifa->ifa_addr; 755 #ifdef COMPAT_43 756 if (cmd == OSIOCGIFCONF) { 757 struct osockaddr *osa = 758 (struct osockaddr *)&ifr.ifr_addr; 759 ifr.ifr_addr = *sa; 760 osa->sa_family = sa->sa_family; 761 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 762 sizeof (ifr)); 763 ifrp++; 764 } else 765 #endif 766 if (sa->sa_len <= sizeof(*sa)) { 767 ifr.ifr_addr = *sa; 768 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 769 sizeof (ifr)); 770 ifrp++; 771 } else { 772 space -= sa->sa_len - sizeof(*sa); 773 if (space < sizeof (ifr)) 774 break; 775 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 776 sizeof (ifr.ifr_name)); 777 if (error == 0) 778 error = copyout((caddr_t)sa, 779 (caddr_t)&ifrp->ifr_addr, sa->sa_len); 780 ifrp = (struct ifreq *) 781 (sa->sa_len + (caddr_t)&ifrp->ifr_addr); 782 } 783 if (error) 784 break; 785 space -= sizeof (ifr); 786 } 787 } 788 ifc->ifc_len -= space; 789 return (error); 790 } 791 792 /* 793 * Just like if_promisc(), but for all-multicast-reception mode. 794 */ 795 int 796 if_allmulti(ifp, onswitch) 797 struct ifnet *ifp; 798 int onswitch; 799 { 800 int error = 0; 801 int s = splimp(); 802 803 if (onswitch) { 804 if (ifp->if_amcount++ == 0) { 805 ifp->if_flags |= IFF_ALLMULTI; 806 error = ifp->if_ioctl(ifp, SIOCSIFFLAGS, 0); 807 } 808 } else { 809 if (ifp->if_amcount > 1) { 810 ifp->if_amcount--; 811 } else { 812 ifp->if_amcount = 0; 813 ifp->if_flags &= ~IFF_ALLMULTI; 814 error = ifp->if_ioctl(ifp, SIOCSIFFLAGS, 0); 815 } 816 } 817 splx(s); 818 819 if (error == 0) 820 rt_ifmsg(ifp); 821 return error; 822 } 823 824 /* 825 * Add a multicast listenership to the interface in question. 826 * The link layer provides a routine which converts 827 */ 828 int 829 if_addmulti(ifp, sa, retifma) 830 struct ifnet *ifp; /* interface to manipulate */ 831 struct sockaddr *sa; /* address to add */ 832 struct ifmultiaddr **retifma; 833 { 834 struct sockaddr *llsa, *dupsa; 835 int error, s; 836 struct ifmultiaddr *ifma; 837 838 /* 839 * If the matching multicast address already exists 840 * then don't add a new one, just add a reference 841 */ 842 for (ifma = ifp->if_multiaddrs.lh_first; ifma; 843 ifma = ifma->ifma_link.le_next) { 844 if (equal(sa, ifma->ifma_addr)) { 845 ifma->ifma_refcount++; 846 if (retifma) 847 *retifma = ifma; 848 return 0; 849 } 850 } 851 852 /* 853 * Give the link layer a chance to accept/reject it, and also 854 * find out which AF_LINK address this maps to, if it isn't one 855 * already. 856 */ 857 if (ifp->if_resolvemulti) { 858 error = ifp->if_resolvemulti(ifp, &llsa, sa); 859 if (error) return error; 860 } else { 861 llsa = 0; 862 } 863 864 MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma, M_IFMADDR, M_WAITOK); 865 MALLOC(dupsa, struct sockaddr *, sa->sa_len, M_IFMADDR, M_WAITOK); 866 bcopy(sa, dupsa, sa->sa_len); 867 868 ifma->ifma_addr = dupsa; 869 ifma->ifma_lladdr = llsa; 870 ifma->ifma_ifp = ifp; 871 ifma->ifma_refcount = 1; 872 ifma->ifma_protospec = 0; 873 rt_newmaddrmsg(RTM_NEWMADDR, ifma); 874 875 /* 876 * Some network interfaces can scan the address list at 877 * interrupt time; lock them out. 878 */ 879 s = splimp(); 880 LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link); 881 splx(s); 882 *retifma = ifma; 883 884 if (llsa != 0) { 885 for (ifma = ifp->if_multiaddrs.lh_first; ifma; 886 ifma = ifma->ifma_link.le_next) { 887 if (equal(ifma->ifma_addr, llsa)) 888 break; 889 } 890 if (ifma) { 891 ifma->ifma_refcount++; 892 } else { 893 MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma, 894 M_IFMADDR, M_WAITOK); 895 MALLOC(dupsa, struct sockaddr *, llsa->sa_len, 896 M_IFMADDR, M_WAITOK); 897 bcopy(llsa, dupsa, llsa->sa_len); 898 ifma->ifma_addr = dupsa; 899 ifma->ifma_ifp = ifp; 900 ifma->ifma_refcount = 1; 901 s = splimp(); 902 LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link); 903 splx(s); 904 } 905 } 906 /* 907 * We are certain we have added something, so call down to the 908 * interface to let them know about it. 909 */ 910 s = splimp(); 911 ifp->if_ioctl(ifp, SIOCADDMULTI, 0); 912 splx(s); 913 914 return 0; 915 } 916 917 /* 918 * Remove a reference to a multicast address on this interface. Yell 919 * if the request does not match an existing membership. 920 */ 921 int 922 if_delmulti(ifp, sa) 923 struct ifnet *ifp; 924 struct sockaddr *sa; 925 { 926 struct ifmultiaddr *ifma; 927 int s; 928 929 for (ifma = ifp->if_multiaddrs.lh_first; ifma; 930 ifma = ifma->ifma_link.le_next) 931 if (equal(sa, ifma->ifma_addr)) 932 break; 933 if (ifma == 0) 934 return ENOENT; 935 936 if (ifma->ifma_refcount > 1) { 937 ifma->ifma_refcount--; 938 return 0; 939 } 940 941 rt_newmaddrmsg(RTM_DELMADDR, ifma); 942 sa = ifma->ifma_lladdr; 943 s = splimp(); 944 LIST_REMOVE(ifma, ifma_link); 945 splx(s); 946 free(ifma->ifma_addr, M_IFMADDR); 947 free(ifma, M_IFMADDR); 948 if (sa == 0) 949 return 0; 950 951 /* 952 * Now look for the link-layer address which corresponds to 953 * this network address. It had been squirreled away in 954 * ifma->ifma_lladdr for this purpose (so we don't have 955 * to call ifp->if_resolvemulti() again), and we saved that 956 * value in sa above. If some nasty deleted the 957 * link-layer address out from underneath us, we can deal because 958 * the address we stored was is not the same as the one which was 959 * in the record for the link-layer address. (So we don't complain 960 * in that case.) 961 */ 962 for (ifma = ifp->if_multiaddrs.lh_first; ifma; 963 ifma = ifma->ifma_link.le_next) 964 if (equal(sa, ifma->ifma_addr)) 965 break; 966 if (ifma == 0) 967 return 0; 968 969 if (ifma->ifma_refcount > 1) { 970 ifma->ifma_refcount--; 971 return 0; 972 } 973 974 s = splimp(); 975 LIST_REMOVE(ifma, ifma_link); 976 splx(s); 977 free(ifma->ifma_addr, M_IFMADDR); 978 free(sa, M_IFMADDR); 979 free(ifma, M_IFMADDR); 980 981 return 0; 982 } 983 984 struct ifmultiaddr * 985 ifmaof_ifpforaddr(sa, ifp) 986 struct sockaddr *sa; 987 struct ifnet *ifp; 988 { 989 struct ifmultiaddr *ifma; 990 991 for (ifma = ifp->if_multiaddrs.lh_first; ifma; 992 ifma = ifma->ifma_link.le_next) 993 if (equal(ifma->ifma_addr, sa)) 994 break; 995 996 return ifma; 997 } 998 999 SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers"); 1000 SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management"); 1001