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.14 (Berkeley) 04/20/91 8 */ 9 10 #include "param.h" 11 #include "mbuf.h" 12 #include "systm.h" 13 #include "socket.h" 14 #include "socketvar.h" 15 #include "protosw.h" 16 #include "proc.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 if_attach(ifp) 70 struct ifnet *ifp; 71 { 72 unsigned socksize, ifasize; 73 int namelen, unitlen; 74 char workbuf[12], *unitname; 75 register struct ifnet **p = &ifnet; 76 register struct sockaddr_dl *sdl; 77 register struct ifaddr *ifa; 78 static int if_indexlim = 8; 79 extern link_rtrequest(), ether_output(); 80 81 while (*p) 82 p = &((*p)->if_next); 83 *p = ifp; 84 ifp->if_index = ++if_index; 85 if (ifnet_addrs == 0 || if_index >= if_indexlim) { 86 unsigned n = (if_indexlim <<= 1) * sizeof(ifa); 87 struct ifaddr **q = (struct ifaddr **) 88 malloc(n, M_IFADDR, M_WAITOK); 89 if (ifnet_addrs) { 90 bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2); 91 free((caddr_t)ifnet_addrs, M_IFADDR); 92 } 93 ifnet_addrs = q; 94 } 95 /* XXX -- Temporary fix before changing 10 ethernet drivers */ 96 if (ifp->if_output == ether_output) { 97 ifp->if_type = IFT_ETHER; 98 ifp->if_addrlen = 6; 99 ifp->if_hdrlen = 14; 100 } 101 /* 102 * create a Link Level name for this device 103 */ 104 unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf)); 105 namelen = strlen(ifp->if_name); 106 unitlen = strlen(unitname); 107 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) 108 socksize = _offsetof(struct sockaddr_dl, sdl_data[0]) + 109 unitlen + namelen + ifp->if_addrlen; 110 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) 111 socksize = ROUNDUP(socksize); 112 if (socksize < sizeof(*sdl)) 113 socksize = sizeof(*sdl); 114 ifasize = sizeof(*ifa) + 2 * socksize; 115 ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK); 116 if (ifa == 0) 117 return; 118 ifnet_addrs[if_index - 1] = ifa; 119 bzero((caddr_t)ifa, ifasize); 120 sdl = (struct sockaddr_dl *)(ifa + 1); 121 ifa->ifa_addr = (struct sockaddr *)sdl; 122 ifa->ifa_ifp = ifp; 123 sdl->sdl_len = socksize; 124 sdl->sdl_family = AF_LINK; 125 bcopy(ifp->if_name, sdl->sdl_data, namelen); 126 bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen); 127 sdl->sdl_nlen = (namelen += unitlen); 128 sdl->sdl_index = ifp->if_index; 129 sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); 130 ifa->ifa_netmask = (struct sockaddr *)sdl; 131 sdl->sdl_len = socksize - ifp->if_addrlen; 132 while (namelen != 0) 133 sdl->sdl_data[--namelen] = 0xff; 134 ifa->ifa_next = ifp->if_addrlist; 135 ifa->ifa_rtrequest = link_rtrequest; 136 ifp->if_addrlist = ifa; 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 first 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 u_int af = addr->sa_family; 196 197 if (af >= AF_MAX) 198 return (0); 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 register char *cplim; 208 if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0) 209 continue; 210 cp = addr->sa_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 for (; cp3 < cplim; cp3++) 215 if ((*cp++ ^ *cp2++) & *cp3) 216 break; 217 if (cp3 == cplim) 218 return (ifa); 219 } 220 return ((struct ifaddr *)0); 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 register struct rtentry *rt; 287 struct sockaddr *sa; 288 { 289 register struct ifaddr *ifa; 290 struct sockaddr *dst; 291 struct ifnet *ifp, *oldifnet = ifnet; 292 293 if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || 294 ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) 295 return; 296 if (ifa = ifaof_ifpforaddr(dst, ifp)) { 297 rt->rt_ifa = ifa; 298 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) 299 ifa->ifa_rtrequest(cmd, rt, sa); 300 } 301 } 302 303 /* 304 * Mark an interface down and notify protocols of 305 * the transition. 306 * NOTE: must be called at splnet or eqivalent. 307 */ 308 if_down(ifp) 309 register struct ifnet *ifp; 310 { 311 register struct ifaddr *ifa; 312 313 ifp->if_flags &= ~IFF_UP; 314 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 315 pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 316 if_qflush(&ifp->if_snd); 317 } 318 319 /* 320 * Flush an interface queue. 321 */ 322 if_qflush(ifq) 323 register struct ifqueue *ifq; 324 { 325 register struct mbuf *m, *n; 326 327 n = ifq->ifq_head; 328 while (m = n) { 329 n = m->m_act; 330 m_freem(m); 331 } 332 ifq->ifq_head = 0; 333 ifq->ifq_tail = 0; 334 ifq->ifq_len = 0; 335 } 336 337 /* 338 * Handle interface watchdog timer routines. Called 339 * from softclock, we decrement timers (if set) and 340 * call the appropriate interface routine on expiration. 341 */ 342 if_slowtimo() 343 { 344 register struct ifnet *ifp; 345 int s = splimp(); 346 347 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 348 if (ifp->if_timer == 0 || --ifp->if_timer) 349 continue; 350 if (ifp->if_watchdog) 351 (*ifp->if_watchdog)(ifp->if_unit); 352 } 353 splx(s); 354 timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); 355 } 356 357 /* 358 * Map interface name to 359 * interface structure pointer. 360 */ 361 struct ifnet * 362 ifunit(name) 363 register char *name; 364 { 365 register char *cp; 366 register struct ifnet *ifp; 367 int unit; 368 unsigned len; 369 char *ep, c; 370 371 for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 372 if (*cp >= '0' && *cp <= '9') 373 break; 374 if (*cp == '\0' || cp == name + IFNAMSIZ) 375 return ((struct ifnet *)0); 376 /* 377 * Save first char of unit, and pointer to it, 378 * so we can put a null there to avoid matching 379 * initial substrings of interface names. 380 */ 381 len = cp - name + 1; 382 c = *cp; 383 ep = cp; 384 for (unit = 0; *cp >= '0' && *cp <= '9'; ) 385 unit = unit * 10 + *cp++ - '0'; 386 *ep = 0; 387 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 388 if (bcmp(ifp->if_name, name, len)) 389 continue; 390 if (unit == ifp->if_unit) 391 break; 392 } 393 *ep = c; 394 return (ifp); 395 } 396 397 /* 398 * Interface ioctls. 399 */ 400 ifioctl(so, cmd, data, p) 401 struct socket *so; 402 int cmd; 403 caddr_t data; 404 struct proc *p; 405 { 406 register struct ifnet *ifp; 407 register struct ifreq *ifr; 408 int error; 409 410 switch (cmd) { 411 412 case SIOCGIFCONF: 413 case OSIOCGIFCONF: 414 return (ifconf(cmd, data)); 415 416 #if defined(INET) && NETHER > 0 417 case SIOCSARP: 418 case SIOCDARP: 419 if (error = suser(p->p_ucred, &p->p_acflag)) 420 return (error); 421 /* FALL THROUGH */ 422 case SIOCGARP: 423 case OSIOCGARP: 424 return (arpioctl(cmd, data)); 425 #endif 426 } 427 ifr = (struct ifreq *)data; 428 ifp = ifunit(ifr->ifr_name); 429 if (ifp == 0) 430 return (ENXIO); 431 switch (cmd) { 432 433 case SIOCGIFFLAGS: 434 ifr->ifr_flags = ifp->if_flags; 435 break; 436 437 case SIOCGIFMETRIC: 438 ifr->ifr_metric = ifp->if_metric; 439 break; 440 441 case SIOCSIFFLAGS: 442 if (error = suser(p->p_ucred, &p->p_acflag)) 443 return (error); 444 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 445 int s = splimp(); 446 if_down(ifp); 447 splx(s); 448 } 449 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 450 (ifr->ifr_flags &~ IFF_CANTCHANGE); 451 if (ifp->if_ioctl) 452 (void) (*ifp->if_ioctl)(ifp, cmd, data); 453 break; 454 455 case SIOCSIFMETRIC: 456 if (error = suser(p->p_ucred, &p->p_acflag)) 457 return (error); 458 ifp->if_metric = ifr->ifr_metric; 459 break; 460 461 default: 462 if (so->so_proto == 0) 463 return (EOPNOTSUPP); 464 #ifndef COMPAT_43 465 return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 466 cmd, data, ifp)); 467 #else 468 { 469 int ocmd = cmd; 470 471 switch (cmd) { 472 473 case SIOCSIFDSTADDR: 474 case SIOCSIFADDR: 475 case SIOCSIFBRDADDR: 476 case SIOCSIFNETMASK: 477 #if BYTE_ORDER != BIG_ENDIAN 478 if (ifr->ifr_addr.sa_family == 0 && 479 ifr->ifr_addr.sa_len < 16) { 480 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 481 ifr->ifr_addr.sa_len = 16; 482 } 483 #else 484 if (ifr->ifr_addr.sa_len == 0) 485 ifr->ifr_addr.sa_len = 16; 486 #endif 487 break; 488 489 case OSIOCGIFADDR: 490 cmd = SIOCGIFADDR; 491 break; 492 493 case OSIOCGIFDSTADDR: 494 cmd = SIOCGIFDSTADDR; 495 break; 496 497 case OSIOCGIFBRDADDR: 498 cmd = SIOCGIFBRDADDR; 499 break; 500 501 case OSIOCGIFNETMASK: 502 cmd = SIOCGIFNETMASK; 503 } 504 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 505 cmd, data, ifp)); 506 switch (ocmd) { 507 508 case OSIOCGIFADDR: 509 case OSIOCGIFDSTADDR: 510 case OSIOCGIFBRDADDR: 511 case OSIOCGIFNETMASK: 512 *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 513 } 514 return (error); 515 516 } 517 #endif 518 } 519 return (0); 520 } 521 522 /* 523 * Return interface configuration 524 * of system. List may be used 525 * in later ioctl's (above) to get 526 * other information. 527 */ 528 /*ARGSUSED*/ 529 ifconf(cmd, data) 530 int cmd; 531 caddr_t data; 532 { 533 register struct ifconf *ifc = (struct ifconf *)data; 534 register struct ifnet *ifp = ifnet; 535 register struct ifaddr *ifa; 536 register char *cp, *ep; 537 struct ifreq ifr, *ifrp; 538 int space = ifc->ifc_len, error = 0; 539 540 ifrp = ifc->ifc_req; 541 ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 542 for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 543 bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); 544 for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 545 ; 546 *cp++ = '0' + ifp->if_unit; *cp = '\0'; 547 if ((ifa = ifp->if_addrlist) == 0) { 548 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 549 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 550 if (error) 551 break; 552 space -= sizeof (ifr), ifrp++; 553 } else 554 for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { 555 register struct sockaddr *sa = ifa->ifa_addr; 556 #ifdef COMPAT_43 557 if (cmd == OSIOCGIFCONF) { 558 struct osockaddr *osa = 559 (struct osockaddr *)&ifr.ifr_addr; 560 ifr.ifr_addr = *sa; 561 osa->sa_family = sa->sa_family; 562 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 563 sizeof (ifr)); 564 ifrp++; 565 } else 566 #endif 567 if (sa->sa_len <= sizeof(*sa)) { 568 ifr.ifr_addr = *sa; 569 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 570 sizeof (ifr)); 571 ifrp++; 572 } else { 573 space -= sa->sa_len - sizeof(*sa); 574 if (space < sizeof (ifr)) 575 break; 576 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 577 sizeof (ifr.ifr_name)); 578 if (error == 0) 579 error = copyout((caddr_t)sa, 580 (caddr_t)&ifrp->ifr_addr, sa->sa_len); 581 ifrp = (struct ifreq *) 582 (sa->sa_len + (caddr_t)&ifrp->ifr_addr); 583 } 584 if (error) 585 break; 586 space -= sizeof (ifr); 587 } 588 } 589 ifc->ifc_len -= space; 590 return (error); 591 } 592 593 static char * 594 sprint_d(n, buf, buflen) 595 u_int n; 596 char *buf; 597 int buflen; 598 { 599 register char *cp = buf + buflen - 1; 600 601 *cp = 0; 602 do { 603 cp--; 604 *cp = "0123456789"[n % 10]; 605 n /= 10; 606 } while (n != 0); 607 return (cp); 608 } 609