|
|
1.1 ! root 1: /* if.c 6.2 83/09/27 */ ! 2: ! 3: #include "../h/param.h" ! 4: #include "../h/systm.h" ! 5: #include "../h/socket.h" ! 6: #include "../h/protosw.h" ! 7: #include "../h/dir.h" ! 8: #include "../h/user.h" ! 9: #include "../h/kernel.h" ! 10: #include "../h/ioctl.h" ! 11: #include "../h/errno.h" ! 12: ! 13: #include "../net/if.h" ! 14: #include "../net/af.h" ! 15: ! 16: int ifqmaxlen = IFQ_MAXLEN; ! 17: ! 18: /* ! 19: * Change: ! 20: * . Add the check to make sure that only superuser can ! 21: * assign Ethernet station address with ioctl(SIOCSETETADDR). ! 22: */ ! 23: ! 24: /* ! 25: * Network interface utility routines. ! 26: * ! 27: * Routines with if_ifwith* names take sockaddr *'s as ! 28: * parameters. Other routines take value parameters, ! 29: * e.g. if_ifwithnet takes the network number. ! 30: */ ! 31: ! 32: ifinit() ! 33: { ! 34: register struct ifnet *ifp; ! 35: ! 36: for (ifp = ifnet; ifp; ifp = ifp->if_next) ! 37: if (ifp->if_init) { ! 38: (*ifp->if_init)(ifp->if_unit); ! 39: if (ifp->if_snd.ifq_maxlen == 0) ! 40: ifp->if_snd.ifq_maxlen = ifqmaxlen; ! 41: } ! 42: if_slowtimo(); ! 43: } ! 44: ! 45: #ifdef vax ! 46: /* ! 47: * Call each interface on a Unibus reset. ! 48: */ ! 49: ifubareset(uban) ! 50: int uban; ! 51: { ! 52: register struct ifnet *ifp; ! 53: ! 54: for (ifp = ifnet; ifp; ifp = ifp->if_next) ! 55: if (ifp->if_reset) ! 56: (*ifp->if_reset)(ifp->if_unit, uban); ! 57: } ! 58: #endif ! 59: ! 60: /* ! 61: * Attach an interface to the ! 62: * list of "active" interfaces. ! 63: */ ! 64: if_attach(ifp) ! 65: struct ifnet *ifp; ! 66: { ! 67: register struct ifnet **p = &ifnet; ! 68: ! 69: while (*p) ! 70: p = &((*p)->if_next); ! 71: *p = ifp; ! 72: } ! 73: ! 74: /* ! 75: * Detach an interface from the ! 76: * list of "active" interfaces. ! 77: */ ! 78: if_detach(ifp) ! 79: struct ifnet *ifp; ! 80: { ! 81: short s = splimp(); ! 82: register struct ifnet **p = &ifnet; ! 83: ! 84: while (*p) { ! 85: if ((*p) == ifp) { ! 86: (*p) = (struct ifnet *)ifp->if_next; ! 87: ifp->if_next = (struct ifnet *)0; ! 88: break; ! 89: } ! 90: else p = &((*p)->if_next); ! 91: } ! 92: ! 93: splx(s); ! 94: } ! 95: ! 96: /* ! 97: * Locate an interface based on a complete address. ! 98: */ ! 99: /*ARGSUSED*/ ! 100: struct ifnet * ! 101: if_ifwithaddr(addr) ! 102: struct sockaddr *addr; ! 103: { ! 104: register struct ifnet *ifp; ! 105: ! 106: #define equal(a1, a2) \ ! 107: (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0) ! 108: for (ifp = ifnet; ifp; ifp = ifp->if_next) { ! 109: if (ifp->if_addr.sa_family != addr->sa_family) ! 110: continue; ! 111: if (equal(&ifp->if_addr, addr)) ! 112: break; ! 113: if ((ifp->if_flags & IFF_BROADCAST) && ! 114: equal(&ifp->if_broadaddr, addr)) ! 115: break; ! 116: } ! 117: return (ifp); ! 118: } ! 119: ! 120: /* ! 121: * Find an interface on a specific network. If many, choice ! 122: * is first found. ! 123: */ ! 124: struct ifnet * ! 125: if_ifwithnet(addr) ! 126: register struct sockaddr *addr; ! 127: { ! 128: register struct ifnet *ifp; ! 129: register u_int af = addr->sa_family; ! 130: register int (*netmatch)(); ! 131: ! 132: if (af >= AF_MAX) ! 133: return (0); ! 134: netmatch = afswitch[af].af_netmatch; ! 135: for (ifp = ifnet; ifp; ifp = ifp->if_next) { ! 136: if (af != ifp->if_addr.sa_family) ! 137: continue; ! 138: if ((*netmatch)(addr, &ifp->if_addr)) ! 139: break; ! 140: } ! 141: return (ifp); ! 142: } ! 143: ! 144: /* ! 145: * As above, but parameter is network number. ! 146: */ ! 147: struct ifnet * ! 148: if_ifonnetof(net) ! 149: register int net; ! 150: { ! 151: register struct ifnet *ifp; ! 152: ! 153: for (ifp = ifnet; ifp; ifp = ifp->if_next) ! 154: if (ifp->if_net == net) ! 155: break; ! 156: return (ifp); ! 157: } ! 158: ! 159: /* ! 160: * Find an interface using a specific address family ! 161: */ ! 162: struct ifnet * ! 163: if_ifwithaf(af) ! 164: register int af; ! 165: { ! 166: register struct ifnet *ifp; ! 167: ! 168: for (ifp = ifnet; ifp; ifp = ifp->if_next) ! 169: if (ifp->if_addr.sa_family == af) ! 170: break; ! 171: return (ifp); ! 172: } ! 173: ! 174: /* ! 175: * Mark an interface down and notify protocols of ! 176: * the transition. ! 177: * NOTE: must be called at splnet or eqivalent. ! 178: */ ! 179: if_down(ifp) ! 180: register struct ifnet *ifp; ! 181: { ! 182: ! 183: ifp->if_flags &= ~IFF_UP; ! 184: pfctlinput(PRC_IFDOWN, (caddr_t)&ifp->if_addr); ! 185: } ! 186: ! 187: /* ! 188: * Handle interface watchdog timer routines. Called ! 189: * from softclock, we decrement timers (if set) and ! 190: * call the appropriate interface routine on expiration. ! 191: */ ! 192: if_slowtimo() ! 193: { ! 194: register struct ifnet *ifp; ! 195: ! 196: for (ifp = ifnet; ifp; ifp = ifp->if_next) { ! 197: if (ifp->if_timer == 0 || --ifp->if_timer) ! 198: continue; ! 199: if (ifp->if_watchdog) ! 200: (*ifp->if_watchdog)(ifp->if_unit); ! 201: } ! 202: timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); ! 203: } ! 204: ! 205: /* ! 206: * Map interface name to ! 207: * interface structure pointer. ! 208: */ ! 209: struct ifnet * ! 210: ifunit(name) ! 211: register char *name; ! 212: { ! 213: register char *cp; ! 214: register struct ifnet *ifp; ! 215: int unit; ! 216: ! 217: for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) ! 218: if (*cp >= '0' && *cp <= '9') ! 219: break; ! 220: if (*cp == '\0' || cp == name + IFNAMSIZ) ! 221: return ((struct ifnet *)0); ! 222: unit = *cp - '0', *cp = 0; ! 223: for (ifp = ifnet; ifp; ifp = ifp->if_next) { ! 224: if (bcmp(ifp->if_name, name, (unsigned)(cp - name))) ! 225: continue; ! 226: if (unit == ifp->if_unit) ! 227: break; ! 228: } ! 229: return (ifp); ! 230: } ! 231: ! 232: /* ! 233: * Interface ioctls. ! 234: */ ! 235: ifioctl(cmd, data) ! 236: int cmd; ! 237: caddr_t data; ! 238: { ! 239: register struct ifnet *ifp; ! 240: register struct ifreq *ifr; ! 241: ! 242: switch (cmd) { ! 243: ! 244: case SIOCGIFCONF: ! 245: return (ifconf(cmd, data)); ! 246: ! 247: case SIOCSIFADDR: ! 248: case SIOCSIFFLAGS: ! 249: case SIOCSIFDSTADDR: ! 250: case SIOCSETETADDR: ! 251: if (!suser()) ! 252: return (u.u_error); ! 253: break; ! 254: } ! 255: ifr = (struct ifreq *)data; ! 256: ifp = ifunit(ifr->ifr_name); ! 257: if (ifp == 0) ! 258: return (ENXIO); ! 259: switch (cmd) { ! 260: ! 261: case SIOCGIFADDR: ! 262: ifr->ifr_addr = ifp->if_addr; ! 263: break; ! 264: ! 265: case SIOCGIFDSTADDR: ! 266: if ((ifp->if_flags & IFF_POINTOPOINT) == 0) ! 267: return (EINVAL); ! 268: ifr->ifr_dstaddr = ifp->if_dstaddr; ! 269: break; ! 270: ! 271: case SIOCGIFFLAGS: ! 272: ifr->ifr_flags = ifp->if_flags; ! 273: break; ! 274: ! 275: case SIOCSIFFLAGS: ! 276: if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { ! 277: int s = splimp(); ! 278: if_down(ifp); ! 279: splx(s); ! 280: } ! 281: ifp->if_flags = ifr->ifr_flags; ! 282: break; ! 283: ! 284: default: ! 285: if (ifp->if_ioctl == 0) ! 286: return (EOPNOTSUPP); ! 287: return ((*ifp->if_ioctl)(ifp, cmd, data)); ! 288: } ! 289: return (0); ! 290: } ! 291: ! 292: /* ! 293: * Return interface configuration ! 294: * of system. List may be used ! 295: * in later ioctl's (above) to get ! 296: * other information. ! 297: */ ! 298: /*ARGSUSED*/ ! 299: ifconf(cmd, data) ! 300: int cmd; ! 301: caddr_t data; ! 302: { ! 303: register struct ifconf *ifc = (struct ifconf *)data; ! 304: register struct ifnet *ifp = ifnet; ! 305: register char *cp, *ep; ! 306: struct ifreq ifr, *ifrp; ! 307: int space = ifc->ifc_len, error = 0; ! 308: ! 309: ifrp = ifc->ifc_req; ! 310: ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; ! 311: for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { ! 312: bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); ! 313: for (cp = ifr.ifr_name; cp < ep && *cp; cp++) ! 314: ; ! 315: *cp++ = '0' + ifp->if_unit; *cp = '\0'; ! 316: ifr.ifr_addr = ifp->if_addr; ! 317: error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); ! 318: if (error) ! 319: break; ! 320: space -= sizeof (ifr), ifrp++; ! 321: } ! 322: ifc->ifc_len -= space; ! 323: return (error); ! 324: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.