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