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 * from: @(#)if.c 8.3 (Berkeley) 1/4/94 34 * $Id: if.c,v 1.15 1994/05/13 06:02:26 mycroft Exp $ 35 */ 36 37 #include <sys/param.h> 38 #include <sys/mbuf.h> 39 #include <sys/systm.h> 40 #include <sys/proc.h> 41 #include <sys/socket.h> 42 #include <sys/socketvar.h> 43 #include <sys/protosw.h> 44 #include <sys/kernel.h> 45 #include <sys/ioctl.h> 46 47 #include <net/if.h> 48 #include <net/if_dl.h> 49 #include <net/if_types.h> 50 51 int ifqmaxlen = IFQ_MAXLEN; 52 void if_slowtimo __P((void *arg)); 53 54 /* 55 * Network interface utility routines. 56 * 57 * Routines with ifa_ifwith* names take sockaddr *'s as 58 * parameters. 59 */ 60 void 61 ifinit() 62 { 63 register struct ifnet *ifp; 64 65 for (ifp = ifnet; ifp; ifp = ifp->if_next) 66 if (ifp->if_snd.ifq_maxlen == 0) 67 ifp->if_snd.ifq_maxlen = ifqmaxlen; 68 if_slowtimo(NULL); 69 } 70 71 #ifdef vax 72 /* 73 * Call each interface on a Unibus reset. 74 */ 75 void 76 ifubareset(uban) 77 int uban; 78 { 79 register struct ifnet *ifp; 80 81 for (ifp = ifnet; ifp; ifp = ifp->if_next) 82 if (ifp->if_reset) 83 (*ifp->if_reset)(ifp->if_unit, uban); 84 } 85 #endif 86 87 int if_index = 0; 88 struct ifaddr **ifnet_addrs; 89 static char *sprint_d __P((u_int, char *, int)); 90 91 /* 92 * Attach an interface to the 93 * list of "active" interfaces. 94 */ 95 void 96 if_attach(ifp) 97 struct ifnet *ifp; 98 { 99 unsigned socksize, ifasize; 100 int namelen, unitlen, masklen; 101 char workbuf[12], *unitname; 102 register struct ifnet **p = &ifnet; 103 register struct sockaddr_dl *sdl; 104 register struct ifaddr *ifa; 105 static int if_indexlim = 8; 106 extern void link_rtrequest(); 107 108 while (*p) 109 p = &((*p)->if_next); 110 *p = ifp; 111 ifp->if_index = ++if_index; 112 if (ifnet_addrs == 0 || if_index >= if_indexlim) { 113 unsigned n = (if_indexlim <<= 1) * sizeof(ifa); 114 struct ifaddr **q = (struct ifaddr **) 115 malloc(n, M_IFADDR, M_WAITOK); 116 if (ifnet_addrs) { 117 bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2); 118 free((caddr_t)ifnet_addrs, M_IFADDR); 119 } 120 ifnet_addrs = q; 121 } 122 /* 123 * create a Link Level name for this device 124 */ 125 unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf)); 126 namelen = strlen(ifp->if_name); 127 unitlen = strlen(unitname); 128 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) 129 masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + 130 unitlen + namelen; 131 socksize = masklen + ifp->if_addrlen; 132 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) 133 socksize = ROUNDUP(socksize); 134 if (socksize < sizeof(*sdl)) 135 socksize = sizeof(*sdl); 136 ifasize = sizeof(*ifa) + 2 * socksize; 137 ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK); 138 if (ifa == 0) 139 return; 140 bzero((caddr_t)ifa, ifasize); 141 sdl = (struct sockaddr_dl *)(ifa + 1); 142 sdl->sdl_len = socksize; 143 sdl->sdl_family = AF_LINK; 144 bcopy(ifp->if_name, sdl->sdl_data, namelen); 145 bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen); 146 sdl->sdl_nlen = (namelen += unitlen); 147 sdl->sdl_index = ifp->if_index; 148 sdl->sdl_type = ifp->if_type; 149 ifnet_addrs[if_index - 1] = ifa; 150 ifa->ifa_ifp = ifp; 151 ifa->ifa_next = ifp->if_addrlist; 152 ifa->ifa_rtrequest = link_rtrequest; 153 ifp->if_addrlist = ifa; 154 ifa->ifa_addr = (struct sockaddr *)sdl; 155 sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); 156 ifa->ifa_netmask = (struct sockaddr *)sdl; 157 sdl->sdl_len = masklen; 158 while (namelen != 0) 159 sdl->sdl_data[--namelen] = 0xff; 160 } 161 /* 162 * Locate an interface based on a complete address. 163 */ 164 /*ARGSUSED*/ 165 struct ifaddr * 166 ifa_ifwithaddr(addr) 167 register struct sockaddr *addr; 168 { 169 register struct ifnet *ifp; 170 register struct ifaddr *ifa; 171 172 #define equal(a1, a2) \ 173 (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) 174 for (ifp = ifnet; ifp; ifp = ifp->if_next) 175 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 176 if (ifa->ifa_addr->sa_family != addr->sa_family) 177 continue; 178 if (equal(addr, ifa->ifa_addr)) 179 return (ifa); 180 if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && 181 equal(ifa->ifa_broadaddr, addr)) 182 return (ifa); 183 } 184 return ((struct ifaddr *)0); 185 } 186 /* 187 * Locate the point to point interface with a given destination address. 188 */ 189 /*ARGSUSED*/ 190 struct ifaddr * 191 ifa_ifwithdstaddr(addr) 192 register struct sockaddr *addr; 193 { 194 register struct ifnet *ifp; 195 register struct ifaddr *ifa; 196 197 for (ifp = ifnet; ifp; ifp = ifp->if_next) 198 if (ifp->if_flags & IFF_POINTOPOINT) 199 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 200 if (ifa->ifa_addr->sa_family != addr->sa_family) 201 continue; 202 if (equal(addr, ifa->ifa_dstaddr)) 203 return (ifa); 204 } 205 return ((struct ifaddr *)0); 206 } 207 208 /* 209 * Find an interface on a specific network. If many, choice 210 * is most specific found. 211 */ 212 struct ifaddr * 213 ifa_ifwithnet(addr) 214 struct sockaddr *addr; 215 { 216 register struct ifnet *ifp; 217 register struct ifaddr *ifa; 218 struct ifaddr *ifa_maybe = 0; 219 u_int af = addr->sa_family; 220 char *addr_data = addr->sa_data, *cplim; 221 222 if (af == AF_LINK) { 223 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr; 224 if (sdl->sdl_index && sdl->sdl_index <= if_index) 225 return (ifnet_addrs[sdl->sdl_index - 1]); 226 } 227 for (ifp = ifnet; ifp; ifp = ifp->if_next) 228 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 229 register char *cp, *cp2, *cp3; 230 231 if (ifa->ifa_addr->sa_family != af || 232 ifa->ifa_netmask == 0) 233 next: continue; 234 cp = addr_data; 235 cp2 = ifa->ifa_addr->sa_data; 236 cp3 = ifa->ifa_netmask->sa_data; 237 cplim = (char *)ifa->ifa_netmask + 238 ifa->ifa_netmask->sa_len; 239 while (cp3 < cplim) 240 if ((*cp++ ^ *cp2++) & *cp3++) 241 goto next; 242 if (ifa_maybe == 0 || 243 rn_refines((caddr_t)ifa->ifa_netmask, 244 (caddr_t)ifa_maybe->ifa_netmask)) 245 ifa_maybe = ifa; 246 } 247 return (ifa_maybe); 248 } 249 250 /* 251 * Find an interface using a specific address family 252 */ 253 struct ifaddr * 254 ifa_ifwithaf(af) 255 register int af; 256 { 257 register struct ifnet *ifp; 258 register struct ifaddr *ifa; 259 260 for (ifp = ifnet; ifp; ifp = ifp->if_next) 261 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 262 if (ifa->ifa_addr->sa_family == af) 263 return (ifa); 264 return ((struct ifaddr *)0); 265 } 266 267 /* 268 * Find an interface address specific to an interface best matching 269 * a given address. 270 */ 271 struct ifaddr * 272 ifaof_ifpforaddr(addr, ifp) 273 struct sockaddr *addr; 274 register struct ifnet *ifp; 275 { 276 register struct ifaddr *ifa; 277 register char *cp, *cp2, *cp3; 278 register char *cplim; 279 struct ifaddr *ifa_maybe = 0; 280 u_int af = addr->sa_family; 281 282 if (af >= AF_MAX) 283 return (0); 284 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 285 if (ifa->ifa_addr->sa_family != af) 286 continue; 287 ifa_maybe = ifa; 288 if (ifa->ifa_netmask == 0) { 289 if (equal(addr, ifa->ifa_addr) || 290 (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))) 291 return (ifa); 292 continue; 293 } 294 cp = addr->sa_data; 295 cp2 = ifa->ifa_addr->sa_data; 296 cp3 = ifa->ifa_netmask->sa_data; 297 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 298 for (; cp3 < cplim; cp3++) 299 if ((*cp++ ^ *cp2++) & *cp3) 300 break; 301 if (cp3 == cplim) 302 return (ifa); 303 } 304 return (ifa_maybe); 305 } 306 307 #include <net/route.h> 308 309 /* 310 * Default action when installing a route with a Link Level gateway. 311 * Lookup an appropriate real ifa to point to. 312 * This should be moved to /sys/net/link.c eventually. 313 */ 314 void 315 link_rtrequest(cmd, rt, sa) 316 int cmd; 317 register struct rtentry *rt; 318 struct sockaddr *sa; 319 { 320 register struct ifaddr *ifa; 321 struct sockaddr *dst; 322 struct ifnet *ifp; 323 324 if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || 325 ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) 326 return; 327 if (ifa = ifaof_ifpforaddr(dst, ifp)) { 328 IFAFREE(rt->rt_ifa); 329 rt->rt_ifa = ifa; 330 ifa->ifa_refcnt++; 331 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) 332 ifa->ifa_rtrequest(cmd, rt, sa); 333 } 334 } 335 336 /* 337 * Mark an interface down and notify protocols of 338 * the transition. 339 * NOTE: must be called at splnet or eqivalent. 340 */ 341 void 342 if_down(ifp) 343 register struct ifnet *ifp; 344 { 345 register struct ifaddr *ifa; 346 347 ifp->if_flags &= ~IFF_UP; 348 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 349 pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 350 if_qflush(&ifp->if_snd); 351 rt_ifmsg(ifp); 352 } 353 354 /* 355 * Mark an interface up and notify protocols of 356 * the transition. 357 * NOTE: must be called at splnet or equivalent. 358 */ 359 void 360 if_up(ifp) 361 register struct ifnet *ifp; 362 { 363 register struct ifaddr *ifa; 364 365 ifp->if_flags |= IFF_UP; 366 #ifdef notyet 367 /* this has no effect on IP, and will kill all ISO connections XXX */ 368 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 369 pfctlinput(PRC_IFUP, ifa->ifa_addr); 370 #endif 371 rt_ifmsg(ifp); 372 } 373 374 /* 375 * Flush an interface queue. 376 */ 377 void 378 if_qflush(ifq) 379 register struct ifqueue *ifq; 380 { 381 register struct mbuf *m, *n; 382 383 n = ifq->ifq_head; 384 while (m = n) { 385 n = m->m_act; 386 m_freem(m); 387 } 388 ifq->ifq_head = 0; 389 ifq->ifq_tail = 0; 390 ifq->ifq_len = 0; 391 } 392 393 /* 394 * Handle interface watchdog timer routines. Called 395 * from softclock, we decrement timers (if set) and 396 * call the appropriate interface routine on expiration. 397 */ 398 void 399 if_slowtimo(arg) 400 void *arg; 401 { 402 register struct ifnet *ifp; 403 int s = splimp(); 404 405 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 406 if (ifp->if_timer == 0 || --ifp->if_timer) 407 continue; 408 if (ifp->if_watchdog) 409 (*ifp->if_watchdog)(ifp->if_unit); 410 } 411 splx(s); 412 timeout(if_slowtimo, NULL, hz / IFNET_SLOWHZ); 413 } 414 415 /* 416 * Map interface name to 417 * interface structure pointer. 418 */ 419 struct ifnet * 420 ifunit(name) 421 register char *name; 422 { 423 register char *cp; 424 register struct ifnet *ifp; 425 int unit; 426 unsigned len; 427 char *ep, c; 428 429 for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 430 if (*cp >= '0' && *cp <= '9') 431 break; 432 if (*cp == '\0' || cp == name + IFNAMSIZ) 433 return ((struct ifnet *)0); 434 /* 435 * Save first char of unit, and pointer to it, 436 * so we can put a null there to avoid matching 437 * initial substrings of interface names. 438 */ 439 len = cp - name + 1; 440 c = *cp; 441 ep = cp; 442 for (unit = 0; *cp >= '0' && *cp <= '9'; ) 443 unit = unit * 10 + *cp++ - '0'; 444 *ep = 0; 445 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 446 if (bcmp(ifp->if_name, name, len)) 447 continue; 448 if (unit == ifp->if_unit) 449 break; 450 } 451 *ep = c; 452 return (ifp); 453 } 454 455 /* 456 * Interface ioctls. 457 */ 458 int 459 ifioctl(so, cmd, data, p) 460 struct socket *so; 461 int cmd; 462 caddr_t data; 463 struct proc *p; 464 { 465 register struct ifnet *ifp; 466 register struct ifreq *ifr; 467 int error; 468 469 switch (cmd) { 470 471 case SIOCGIFCONF: 472 case OSIOCGIFCONF: 473 return (ifconf(cmd, data)); 474 } 475 ifr = (struct ifreq *)data; 476 ifp = ifunit(ifr->ifr_name); 477 if (ifp == 0) 478 return (ENXIO); 479 switch (cmd) { 480 481 case SIOCGIFFLAGS: 482 ifr->ifr_flags = ifp->if_flags; 483 break; 484 485 case SIOCGIFMETRIC: 486 ifr->ifr_metric = ifp->if_metric; 487 break; 488 489 case SIOCSIFFLAGS: 490 if (error = suser(p->p_ucred, &p->p_acflag)) 491 return (error); 492 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 493 int s = splimp(); 494 if_down(ifp); 495 splx(s); 496 } 497 if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) { 498 int s = splimp(); 499 if_up(ifp); 500 splx(s); 501 } 502 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 503 (ifr->ifr_flags &~ IFF_CANTCHANGE); 504 if (ifp->if_ioctl) 505 (void) (*ifp->if_ioctl)(ifp, cmd, data); 506 break; 507 508 case SIOCSIFMETRIC: 509 if (error = suser(p->p_ucred, &p->p_acflag)) 510 return (error); 511 ifp->if_metric = ifr->ifr_metric; 512 break; 513 514 case SIOCADDMULTI: 515 case SIOCDELMULTI: 516 if (error = suser(p->p_ucred, &p->p_acflag)) 517 return (error); 518 if (ifp->if_ioctl == 0) 519 return (EOPNOTSUPP); 520 return ((*ifp->if_ioctl)(ifp, cmd, data)); 521 522 default: 523 if (so->so_proto == 0) 524 return (EOPNOTSUPP); 525 #ifndef COMPAT_43 526 return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 527 cmd, data, ifp)); 528 #else 529 { 530 int ocmd = cmd; 531 532 switch (cmd) { 533 534 case SIOCSIFDSTADDR: 535 case SIOCSIFADDR: 536 case SIOCSIFBRDADDR: 537 case SIOCSIFNETMASK: 538 #if BYTE_ORDER != BIG_ENDIAN 539 if (ifr->ifr_addr.sa_family == 0 && 540 ifr->ifr_addr.sa_len < 16) { 541 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 542 ifr->ifr_addr.sa_len = 16; 543 } 544 #else 545 if (ifr->ifr_addr.sa_len == 0) 546 ifr->ifr_addr.sa_len = 16; 547 #endif 548 break; 549 550 case OSIOCGIFADDR: 551 cmd = SIOCGIFADDR; 552 break; 553 554 case OSIOCGIFDSTADDR: 555 cmd = SIOCGIFDSTADDR; 556 break; 557 558 case OSIOCGIFBRDADDR: 559 cmd = SIOCGIFBRDADDR; 560 break; 561 562 case OSIOCGIFNETMASK: 563 cmd = SIOCGIFNETMASK; 564 } 565 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 566 cmd, data, ifp)); 567 switch (ocmd) { 568 569 case OSIOCGIFADDR: 570 case OSIOCGIFDSTADDR: 571 case OSIOCGIFBRDADDR: 572 case OSIOCGIFNETMASK: 573 *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 574 } 575 return (error); 576 577 } 578 #endif 579 } 580 return (0); 581 } 582 583 /* 584 * Return interface configuration 585 * of system. List may be used 586 * in later ioctl's (above) to get 587 * other information. 588 */ 589 /*ARGSUSED*/ 590 int 591 ifconf(cmd, data) 592 int cmd; 593 caddr_t data; 594 { 595 register struct ifconf *ifc = (struct ifconf *)data; 596 register struct ifnet *ifp = ifnet; 597 register struct ifaddr *ifa; 598 register char *cp, *ep; 599 struct ifreq ifr, *ifrp; 600 int space = ifc->ifc_len, error = 0; 601 602 ifrp = ifc->ifc_req; 603 ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 604 for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 605 strncpy(ifr.ifr_name, ifp->if_name, sizeof(ifr.ifr_name) - 2); 606 for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 607 continue; 608 *cp++ = '0' + ifp->if_unit; *cp = '\0'; 609 if ((ifa = ifp->if_addrlist) == 0) { 610 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 611 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 612 sizeof(ifr)); 613 if (error) 614 break; 615 space -= sizeof (ifr), ifrp++; 616 } else 617 for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { 618 register struct sockaddr *sa = ifa->ifa_addr; 619 #ifdef COMPAT_43 620 if (cmd == OSIOCGIFCONF) { 621 struct osockaddr *osa = 622 (struct osockaddr *)&ifr.ifr_addr; 623 ifr.ifr_addr = *sa; 624 osa->sa_family = sa->sa_family; 625 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 626 sizeof (ifr)); 627 ifrp++; 628 } else 629 #endif 630 if (sa->sa_len <= sizeof(*sa)) { 631 ifr.ifr_addr = *sa; 632 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 633 sizeof (ifr)); 634 ifrp++; 635 } else { 636 space -= sa->sa_len - sizeof(*sa); 637 if (space < sizeof (ifr)) 638 break; 639 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 640 sizeof (ifr.ifr_name)); 641 if (error == 0) 642 error = copyout((caddr_t)sa, 643 (caddr_t)&ifrp->ifr_addr, sa->sa_len); 644 ifrp = (struct ifreq *) 645 (sa->sa_len + (caddr_t)&ifrp->ifr_addr); 646 } 647 if (error) 648 break; 649 space -= sizeof (ifr); 650 } 651 } 652 ifc->ifc_len -= space; 653 return (error); 654 } 655 656 static char * 657 sprint_d(n, buf, buflen) 658 u_int n; 659 char *buf; 660 int buflen; 661 { 662 register char *cp = buf + buflen - 1; 663 664 *cp = 0; 665 do { 666 cp--; 667 *cp = "0123456789"[n % 10]; 668 n /= 10; 669 } while (n != 0); 670 return (cp); 671 } 672