+ }
+ splx(s);
+ timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ);
+}
+
+/*
+ * Map interface name to
+ * interface structure pointer.
+ */
+struct ifnet *
+ifunit(name)
+ register char *name;
+{
+ register char *cp;
+ register struct ifnet *ifp;
+ int unit;
+ unsigned len;
+ char *ep, c;
+
+ for (cp = name; cp < name + IFNAMSIZ && *cp; cp++)
+ if (*cp >= '0' && *cp <= '9')
+ break;
+ if (*cp == '\0' || cp == name + IFNAMSIZ)
+ return ((struct ifnet *)0);
+ /*
+ * Save first char of unit, and pointer to it,
+ * so we can put a null there to avoid matching
+ * initial substrings of interface names.
+ */
+ len = cp - name + 1;
+ c = *cp;
+ ep = cp;
+ for (unit = 0; *cp >= '0' && *cp <= '9'; )
+ unit = unit * 10 + *cp++ - '0';
+ *ep = 0;
+ for (ifp = ifnet; ifp; ifp = ifp->if_next) {
+ if (bcmp(ifp->if_name, name, len))
+ continue;
+ if (unit == ifp->if_unit)
+ break;
+ }
+ *ep = c;
+ return (ifp);
+}
+
+/*
+ * Interface ioctls.
+ */
+ifioctl(so, cmd, data)
+ struct socket *so;
+ int cmd;
+ caddr_t data;
+{
+ register struct ifnet *ifp;
+ register struct ifreq *ifr;
+ int error;
+
+ switch (cmd) {
+
+ case SIOCGIFCONF:
+ case OSIOCGIFCONF:
+ return (ifconf(cmd, data));
+
+#if defined(INET) && NETHER > 0
+ case SIOCSARP:
+ case SIOCDARP:
+ if (error = suser(u.u_cred, &u.u_acflag))
+ return (error);
+ /* FALL THROUGH */
+ case SIOCGARP:
+ case OSIOCGARP:
+ return (arpioctl(cmd, data));
+#endif
+ }
+ ifr = (struct ifreq *)data;
+ ifp = ifunit(ifr->ifr_name);
+ if (ifp == 0)
+ return (ENXIO);
+ switch (cmd) {
+
+ case SIOCGIFFLAGS:
+ ifr->ifr_flags = ifp->if_flags;
+ break;
+
+ case SIOCGIFMETRIC:
+ ifr->ifr_metric = ifp->if_metric;
+ break;
+
+ case SIOCSIFFLAGS:
+ if (error = suser(u.u_cred, &u.u_acflag))
+ return (error);
+ if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
+ int s = splimp();
+ if_down(ifp);
+ splx(s);
+ }
+ ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
+ (ifr->ifr_flags &~ IFF_CANTCHANGE);
+ if (ifp->if_ioctl)
+ (void) (*ifp->if_ioctl)(ifp, cmd, data);
+ break;
+
+ case SIOCSIFMETRIC:
+ if (error = suser(u.u_cred, &u.u_acflag))
+ return (error);
+ ifp->if_metric = ifr->ifr_metric;
+ break;
+
+ default:
+ if (so->so_proto == 0)
+ return (EOPNOTSUPP);
+#ifndef COMPAT_43
+ return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
+ cmd, data, ifp));
+#else
+ {
+ int error, ocmd = cmd;
+
+ switch (cmd) {
+
+ case SIOCSIFDSTADDR:
+ case SIOCSIFADDR:
+ case SIOCSIFBRDADDR:
+ case SIOCSIFNETMASK:
+#if BYTE_ORDER != BIG_ENDIAN
+ if (ifr->ifr_addr.sa_family == 0 &&
+ ifr->ifr_addr.sa_len < 16) {
+ ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
+ ifr->ifr_addr.sa_len = 16;
+ }
+#else
+ if (ifr->ifr_addr.sa_len == 0)
+ ifr->ifr_addr.sa_len = 16;
+#endif
+ break;
+
+ case OSIOCGIFADDR:
+ cmd = SIOCGIFADDR;
+ break;
+
+ case OSIOCGIFDSTADDR:
+ cmd = SIOCGIFDSTADDR;
+ break;
+
+ case OSIOCGIFBRDADDR:
+ cmd = SIOCGIFBRDADDR;
+ break;
+
+ case OSIOCGIFNETMASK:
+ cmd = SIOCGIFNETMASK;