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