1 /* 2 * Copyright (c) 1980, 1986 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)if.c 7.10 (Berkeley) 05/10/90 18 */ 19 20 #include "param.h" 21 #include "mbuf.h" 22 #include "systm.h" 23 #include "socket.h" 24 #include "socketvar.h" 25 #include "protosw.h" 26 #include "user.h" 27 #include "kernel.h" 28 #include "ioctl.h" 29 #include "errno.h" 30 31 #include "if.h" 32 #include "af.h" 33 #include "if_dl.h" 34 35 #include "ether.h" 36 37 int ifqmaxlen = IFQ_MAXLEN; 38 39 /* 40 * Network interface utility routines. 41 * 42 * Routines with ifa_ifwith* names take sockaddr *'s as 43 * parameters. 44 */ 45 46 ifinit() 47 { 48 register struct ifnet *ifp; 49 50 for (ifp = ifnet; ifp; ifp = ifp->if_next) 51 if (ifp->if_snd.ifq_maxlen == 0) 52 ifp->if_snd.ifq_maxlen = ifqmaxlen; 53 if_slowtimo(); 54 } 55 56 #ifdef vax 57 /* 58 * Call each interface on a Unibus reset. 59 */ 60 ifubareset(uban) 61 int uban; 62 { 63 register struct ifnet *ifp; 64 65 for (ifp = ifnet; ifp; ifp = ifp->if_next) 66 if (ifp->if_reset) 67 (*ifp->if_reset)(ifp->if_unit, uban); 68 } 69 #endif 70 71 int if_index = 0; 72 /* 73 * Attach an interface to the 74 * list of "active" interfaces. 75 */ 76 if_attach(ifp) 77 struct ifnet *ifp; 78 { 79 register struct ifnet **p = &ifnet; 80 unsigned socksize, ifasize; 81 int namelen, unitlen; 82 char workbuf[16]; 83 register struct sockaddr_dl *sdl; 84 register struct ifaddr *ifa; 85 86 while (*p) 87 p = &((*p)->if_next); 88 *p = ifp; 89 ifp->if_index = ++if_index; 90 /* create a link level name for this device */ 91 sprint_d(workbuf, ifp->if_unit); 92 namelen = strlen(ifp->if_name); 93 unitlen = strlen(workbuf); 94 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) 95 socksize = _offsetof(struct sockaddr_dl, sdl_data[0]) + 96 unitlen + namelen + ifp->if_addrlen; 97 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) 98 socksize = ROUNDUP(socksize); 99 ifasize = sizeof(*ifa) + 2 * socksize; 100 ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK); 101 if (ifa == 0) 102 return; 103 bzero((caddr_t)ifa, ifasize); 104 sdl = (struct sockaddr_dl *)(ifa + 1); 105 ifa->ifa_addr = (struct sockaddr *)sdl; 106 ifa->ifa_ifp = ifp; 107 sdl->sdl_len = socksize; 108 sdl->sdl_family = AF_LINK; 109 bcopy(ifp->if_name, sdl->sdl_data, namelen); 110 bcopy((caddr_t)workbuf, namelen + (caddr_t)sdl->sdl_data, unitlen); 111 sdl->sdl_nlen = (namelen += unitlen); 112 sdl->sdl_index = ifp->if_index; 113 sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); 114 ifa->ifa_netmask = (struct sockaddr *)sdl; 115 sdl->sdl_len = socksize - ifp->if_addrlen; 116 while (namelen != 0) 117 sdl->sdl_data[--namelen] = 0xff; 118 ifa->ifa_next = ifp->if_addrlist; 119 ifp->if_addrlist = ifa; 120 } 121 122 /* 123 * Locate an interface based on a complete address. 124 */ 125 /*ARGSUSED*/ 126 struct ifaddr * 127 ifa_ifwithaddr(addr) 128 register struct sockaddr *addr; 129 { 130 register struct ifnet *ifp; 131 register struct ifaddr *ifa; 132 133 #define equal(a1, a2) \ 134 (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) 135 for (ifp = ifnet; ifp; ifp = ifp->if_next) 136 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 137 if (ifa->ifa_addr->sa_family != addr->sa_family) 138 continue; 139 if (equal(addr, ifa->ifa_addr)) 140 return (ifa); 141 if ((ifp->if_flags & IFF_BROADCAST) && 142 equal(&ifa->ifa_broadaddr, addr)) 143 return (ifa); 144 } 145 return ((struct ifaddr *)0); 146 } 147 /* 148 * Locate the point to point interface with a given destination address. 149 */ 150 /*ARGSUSED*/ 151 struct ifaddr * 152 ifa_ifwithdstaddr(addr) 153 register struct sockaddr *addr; 154 { 155 register struct ifnet *ifp; 156 register struct ifaddr *ifa; 157 158 for (ifp = ifnet; ifp; ifp = ifp->if_next) 159 if (ifp->if_flags & IFF_POINTOPOINT) 160 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 161 if (ifa->ifa_addr->sa_family != addr->sa_family) 162 continue; 163 if (equal(addr, ifa->ifa_dstaddr)) 164 return (ifa); 165 } 166 return ((struct ifaddr *)0); 167 } 168 169 /* 170 * Find an interface on a specific network. If many, choice 171 * is first found. 172 */ 173 struct ifaddr * 174 ifa_ifwithnet(addr) 175 struct sockaddr *addr; 176 { 177 register struct ifnet *ifp; 178 register struct ifaddr *ifa; 179 register char *cp, *cp2, *cp3; 180 register char *cplim; 181 u_int af = addr->sa_family; 182 183 if (af >= AF_MAX) 184 return (0); 185 for (ifp = ifnet; ifp; ifp = ifp->if_next) 186 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 187 if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0) 188 continue; 189 cp = addr->sa_data; 190 cp2 = ifa->ifa_addr->sa_data; 191 cp3 = ifa->ifa_netmask->sa_data; 192 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 193 for (; cp3 < cplim; cp3++) 194 if ((*cp++ ^ *cp2++) & *cp3) 195 break; 196 if (cp3 == cplim) 197 return (ifa); 198 } 199 return ((struct ifaddr *)0); 200 } 201 202 #ifdef notdef 203 /* 204 * Find an interface using a specific address family 205 */ 206 struct ifaddr * 207 ifa_ifwithaf(af) 208 register int af; 209 { 210 register struct ifnet *ifp; 211 register struct ifaddr *ifa; 212 213 for (ifp = ifnet; ifp; ifp = ifp->if_next) 214 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 215 if (ifa->ifa_addr->sa_family == af) 216 return (ifa); 217 return ((struct ifaddr *)0); 218 } 219 #endif 220 221 /* 222 * Mark an interface down and notify protocols of 223 * the transition. 224 * NOTE: must be called at splnet or eqivalent. 225 */ 226 if_down(ifp) 227 register struct ifnet *ifp; 228 { 229 register struct ifaddr *ifa; 230 231 ifp->if_flags &= ~IFF_UP; 232 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 233 pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 234 if_qflush(&ifp->if_snd); 235 } 236 237 /* 238 * Flush an interface queue. 239 */ 240 if_qflush(ifq) 241 register struct ifqueue *ifq; 242 { 243 register struct mbuf *m, *n; 244 245 n = ifq->ifq_head; 246 while (m = n) { 247 n = m->m_act; 248 m_freem(m); 249 } 250 ifq->ifq_head = 0; 251 ifq->ifq_tail = 0; 252 ifq->ifq_len = 0; 253 } 254 255 /* 256 * Handle interface watchdog timer routines. Called 257 * from softclock, we decrement timers (if set) and 258 * call the appropriate interface routine on expiration. 259 */ 260 if_slowtimo() 261 { 262 register struct ifnet *ifp; 263 int s = splimp(); 264 265 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 266 if (ifp->if_timer == 0 || --ifp->if_timer) 267 continue; 268 if (ifp->if_watchdog) 269 (*ifp->if_watchdog)(ifp->if_unit); 270 } 271 splx(s); 272 timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); 273 } 274 275 /* 276 * Map interface name to 277 * interface structure pointer. 278 */ 279 struct ifnet * 280 ifunit(name) 281 register char *name; 282 { 283 register char *cp; 284 register struct ifnet *ifp; 285 int unit; 286 unsigned len; 287 char *ep, c; 288 289 for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 290 if (*cp >= '0' && *cp <= '9') 291 break; 292 if (*cp == '\0' || cp == name + IFNAMSIZ) 293 return ((struct ifnet *)0); 294 /* 295 * Save first char of unit, and pointer to it, 296 * so we can put a null there to avoid matching 297 * initial substrings of interface names. 298 */ 299 len = cp - name + 1; 300 c = *cp; 301 ep = cp; 302 for (unit = 0; *cp >= '0' && *cp <= '9'; ) 303 unit = unit * 10 + *cp++ - '0'; 304 *ep = 0; 305 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 306 if (bcmp(ifp->if_name, name, len)) 307 continue; 308 if (unit == ifp->if_unit) 309 break; 310 } 311 *ep = c; 312 return (ifp); 313 } 314 315 /* 316 * Interface ioctls. 317 */ 318 ifioctl(so, cmd, data) 319 struct socket *so; 320 int cmd; 321 caddr_t data; 322 { 323 register struct ifnet *ifp; 324 register struct ifreq *ifr; 325 int error; 326 327 switch (cmd) { 328 329 case SIOCGIFCONF: 330 case OSIOCGIFCONF: 331 return (ifconf(cmd, data)); 332 333 #if defined(INET) && NETHER > 0 334 case SIOCSARP: 335 case SIOCDARP: 336 if (error = suser(u.u_cred, &u.u_acflag)) 337 return (error); 338 /* FALL THROUGH */ 339 case SIOCGARP: 340 case OSIOCGARP: 341 return (arpioctl(cmd, data)); 342 #endif 343 } 344 ifr = (struct ifreq *)data; 345 ifp = ifunit(ifr->ifr_name); 346 if (ifp == 0) 347 return (ENXIO); 348 switch (cmd) { 349 350 case SIOCGIFFLAGS: 351 ifr->ifr_flags = ifp->if_flags; 352 break; 353 354 case SIOCGIFMETRIC: 355 ifr->ifr_metric = ifp->if_metric; 356 break; 357 358 case SIOCSIFFLAGS: 359 if (error = suser(u.u_cred, &u.u_acflag)) 360 return (error); 361 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 362 int s = splimp(); 363 if_down(ifp); 364 splx(s); 365 } 366 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 367 (ifr->ifr_flags &~ IFF_CANTCHANGE); 368 if (ifp->if_ioctl) 369 (void) (*ifp->if_ioctl)(ifp, cmd, data); 370 break; 371 372 case SIOCSIFMETRIC: 373 if (error = suser(u.u_cred, &u.u_acflag)) 374 return (error); 375 ifp->if_metric = ifr->ifr_metric; 376 break; 377 378 default: 379 if (so->so_proto == 0) 380 return (EOPNOTSUPP); 381 #ifndef COMPAT_43 382 return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 383 cmd, data, ifp)); 384 #else 385 { 386 int ocmd = cmd; 387 388 switch (cmd) { 389 390 case SIOCSIFDSTADDR: 391 case SIOCSIFADDR: 392 case SIOCSIFBRDADDR: 393 case SIOCSIFNETMASK: 394 #if BYTE_ORDER != BIG_ENDIAN 395 if (ifr->ifr_addr.sa_family == 0 && 396 ifr->ifr_addr.sa_len < 16) { 397 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 398 ifr->ifr_addr.sa_len = 16; 399 } 400 #else 401 if (ifr->ifr_addr.sa_len == 0) 402 ifr->ifr_addr.sa_len = 16; 403 #endif 404 break; 405 406 case OSIOCGIFADDR: 407 cmd = SIOCGIFADDR; 408 break; 409 410 case OSIOCGIFDSTADDR: 411 cmd = SIOCGIFDSTADDR; 412 break; 413 414 case OSIOCGIFBRDADDR: 415 cmd = SIOCGIFBRDADDR; 416 break; 417 418 case OSIOCGIFNETMASK: 419 cmd = SIOCGIFNETMASK; 420 } 421 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 422 cmd, data, ifp)); 423 switch (ocmd) { 424 425 case OSIOCGIFADDR: 426 case OSIOCGIFDSTADDR: 427 case OSIOCGIFBRDADDR: 428 case OSIOCGIFNETMASK: 429 *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 430 } 431 return (error); 432 433 } 434 #endif 435 } 436 return (0); 437 } 438 439 /* 440 * Return interface configuration 441 * of system. List may be used 442 * in later ioctl's (above) to get 443 * other information. 444 */ 445 /*ARGSUSED*/ 446 ifconf(cmd, data) 447 int cmd; 448 caddr_t data; 449 { 450 register struct ifconf *ifc = (struct ifconf *)data; 451 register struct ifnet *ifp = ifnet; 452 register struct ifaddr *ifa; 453 register char *cp, *ep; 454 struct ifreq ifr, *ifrp; 455 int space = ifc->ifc_len, error = 0; 456 457 ifrp = ifc->ifc_req; 458 ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 459 for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 460 bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); 461 for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 462 ; 463 *cp++ = '0' + ifp->if_unit; *cp = '\0'; 464 if ((ifa = ifp->if_addrlist) == 0) { 465 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 466 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 467 if (error) 468 break; 469 space -= sizeof (ifr), ifrp++; 470 } else 471 for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { 472 register struct sockaddr *sa = ifa->ifa_addr; 473 #ifdef COMPAT_43 474 if (cmd == OSIOCGIFCONF) { 475 struct osockaddr *osa = 476 (struct osockaddr *)&ifr.ifr_addr; 477 ifr.ifr_addr = *sa; 478 osa->sa_family = sa->sa_family; 479 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 480 sizeof (ifr)); 481 ifrp++; 482 } else 483 #endif 484 if (sa->sa_len <= sizeof(*sa)) { 485 ifr.ifr_addr = *sa; 486 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 487 sizeof (ifr)); 488 ifrp++; 489 } else { 490 space -= sa->sa_len - sizeof(*sa); 491 if (space < sizeof (ifr)) 492 break; 493 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 494 sizeof (ifr.ifr_name)); 495 if (error == 0) 496 error = copyout((caddr_t)sa, 497 (caddr_t)&ifrp->ifr_addr, sa->sa_len); 498 ifrp = (struct ifreq *) 499 (sa->sa_len + (caddr_t)&ifrp->ifr_addr); 500 } 501 if (error) 502 break; 503 space -= sizeof (ifr); 504 } 505 } 506 ifc->ifc_len -= space; 507 return (error); 508 } 509 510 static sprint_d(cp, n) 511 register char *cp; 512 u_short n; 513 { 514 register int q, m; 515 do { 516 if (n >= 10000) m = 10000; 517 else if (n >= 1000) m = 1000; 518 else if (n >= 100) m = 100; 519 else if (n >= 10) m = 10; 520 else m = 1; 521 q = n / m; 522 n -= m * q; 523 if (q > 9) q = 10; /* For crays with more than 100K interfaces */ 524 *cp++ = "0123456789Z"[q]; 525 } while (n > 0); 526 *cp++ = 0; 527 } 528