📄 if.c
字号:
#ifdef VIRTUAL_STACK virtualStackNumTaskIdSet(stackNum);#endif s = splnet();#ifdef VIRTUAL_STACK if (_ifnet != NULL)#else if (ifnet != NULL)#endif {#ifdef VIRTUAL_STACK for (ifp = _ifnet; ifp; ifp = ifp->if_next)#else for (ifp = ifnet; ifp; ifp = ifp->if_next)#endif { if (ifp->if_timer == 0 || --ifp->if_timer) continue; if (ifp->if_watchdog) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_INFO event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_INFO, 0, 6, WV_NETEVENT_IFWATCHDOG, ifp)#endif /* INCLUDE_WVNET */#endif (*ifp->if_watchdog)(ifp->if_unit); } } } splx (s); /* XXX using watchdogs good idea? calculate clock rate once only -gae */ wdStart (ifslowtimoWd, sysClkRateGet()/IFNET_SLOWHZ,#ifdef VIRTUAL_STACK (FUNCPTR) if_slowtimoRestart, (int) stackNum);#else (FUNCPTR) netJobAdd, (int) if_slowtimo);#endif }/* ifunit () has been moved to ifLib.c *//* * Interface ioctls. */intifioctl(so, cmd, data) struct socket *so; u_long cmd; caddr_t data;{ register struct ifnet *ifp; register struct ifreq *ifr;#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_INFO event */ WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_INFO, 1, 7, WV_NETEVENT_IFIOCTL_START, so->so_fd, cmd)#endif /* INCLUDE_WVNET */#endif switch (cmd) { case SIOCGIFCONF: case OSIOCGIFCONF: return (ifconf(cmd, data));#ifdef INET case SIOCSARP: case SIOCDARP: /* FALL THROUGH */ case SIOCGARP: return (arpioctl(cmd, data));#endif /* INET */ } ifr = (struct ifreq *)data; ifp = ifunit(ifr->ifr_name); if (ifp == 0) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_ERROR event */ WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 0, 3, WV_NETEVENT_IFIOCTL_BADIFNAME, so->so_fd, cmd)#endif /* INCLUDE_WVNET */#endif return (ENXIO); } switch (cmd) { case SIOCGIFFLAGS: ifr->ifr_flags = ifp->if_flags; break; case SIOCGIFMETRIC: ifr->ifr_metric = ifp->if_metric; break; case SIOCSIFASYNCFLAGS: /* * we got a asynchronous flag change report from the interface; */ /* FALL THROUGH */ case SIOCSIFFLAGS: if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { int s = splimp(); if_down(ifp); splx(s); if (_m2SetIfLastChange) _m2SetIfLastChange(ifp->if_index); } if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) { int s = splimp(); if_up(ifp); splx(s); if (_m2SetIfLastChange) _m2SetIfLastChange(ifp->if_index); } ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | (ifr->ifr_flags &~ IFF_CANTCHANGE); ifr->ifr_flags = ifp->if_flags; /* command the interface only if we are initiating the change */ if ((cmd == SIOCSIFFLAGS) && ifp->if_ioctl) (void) (*ifp->if_ioctl)(ifp, cmd, data); break; case SIOCSIFMETRIC: ifp->if_metric = ifr->ifr_metric; break; case SIOCADDMULTI: case SIOCDELMULTI: if (ifp->if_ioctl == 0) return (EOPNOTSUPP); return ((*ifp->if_ioctl)(ifp, cmd, data)); default: if (so->so_proto == 0) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_ERROR event */ WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 1, 4, WV_NETEVENT_IFIOCTL_NOPROTO, so->so_fd, cmd)#endif /* INCLUDE_WVNET */#endif return (EOPNOTSUPP); }#ifndef COMPAT_43 return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, cmd, data, ifp));#else { int error = 0; int 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; } error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, cmd, data, ifp)); switch (ocmd) { case OSIOCGIFADDR: case OSIOCGIFDSTADDR: case OSIOCGIFBRDADDR: case OSIOCGIFNETMASK: *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; } return (error); }#endif } return (0);}/* * Return interface configuration * of system. List may be used * in later ioctl's (above) to get * other information. *//*ARGSUSED*/intifconf(cmd, data) int cmd; caddr_t data;{ register struct ifconf *ifc = (struct ifconf *)data;#ifdef VIRTUAL_STACK register struct ifnet *ifp = _ifnet;#else register struct ifnet *ifp = ifnet;#endif register struct ifaddr *ifa; register char *cp, *ep; struct ifreq ifr, *ifrp; int space = ifc->ifc_len, error = 0; char workbuf[12], *unitname; ifrp = ifc->ifc_req; ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { strncpy(ifr.ifr_name, ifp->if_name, sizeof(ifr.ifr_name) - 2); for (cp = ifr.ifr_name; cp < ep && *cp; cp++) continue; unitname = sprint_d ((u_int)ifp->if_unit, workbuf, sizeof(workbuf)); for (; cp <= ep && *unitname != '\0'; *cp++ = *unitname++); if (*unitname != '\0') { error = ENAMETOOLONG; break; } *cp = '\0'; if ((ifa = ifp->if_addrlist) == 0) { bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof(ifr)); if (error) break; space -= sizeof (ifr), ifrp++; } else for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { register struct sockaddr *sa = ifa->ifa_addr;#ifdef COMPAT_43 if (cmd == OSIOCGIFCONF) { struct osockaddr *osa = (struct osockaddr *)&ifr.ifr_addr; ifr.ifr_addr = *sa; osa->sa_family = sa->sa_family; error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); ifrp++; } else#endif if (sa->sa_len <= sizeof(*sa)) { ifr.ifr_addr = *sa; error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); ifrp++; } else { space -= sa->sa_len - sizeof(*sa); if (space < sizeof (ifr)) break; error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr.ifr_name)); if (error == 0) error = copyout((caddr_t)sa, (caddr_t)&ifrp->ifr_addr, sa->sa_len); ifrp = (struct ifreq *) (sa->sa_len + (caddr_t)&ifrp->ifr_addr); } if (error) break; space -= sizeof (ifr); } } ifc->ifc_len -= space; return (error);}/* * Set/clear promiscuous mode on interface ifp based on the truth value * of pswitch. The calls are reference counted so that only the first * "on" request actually has an effect, as does the final "off" request. * Results are undefined if the "off" and "on" requests are not matched. */intifpromisc(ifp, pswitch) struct ifnet *ifp; int pswitch;{ struct ifreq ifr;#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_VERBOSE event */ WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_VERBOSE, 6, 14, WV_NETEVENT_IFPROMISC_START, ifp, pswitch)#endif /* INCLUDE_WVNET */#endif /* * If the device is not configured up, we cannot put it in * promiscuous mode. */ if ((ifp->if_flags & IFF_UP) == 0) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_CRITICAL event */ WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_CRITICAL, 0, 2, WV_NETEVENT_IFPROMISC_FAIL, ifp, pswitch)#endif /* INCLUDE_WVNET */#endif return (ENETDOWN); } if (pswitch) { if (ifp->if_pcount++ != 0) return (0); ifp->if_flags |= IFF_PROMISC; } else { if (--ifp->if_pcount > 0) return (0); ifp->if_flags &= ~IFF_PROMISC; } ifr.ifr_flags = ifp->if_flags; return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));}static char *sprint_d(n, buf, buflen) u_int n; char *buf; int buflen;{ register char *cp = buf + buflen - 1; *cp = 0; do { cp--; *cp = "0123456789"[n % 10]; n /= 10; } while (n != 0); return (cp);}/******************************************************************************** ifMultiDelete - deletes multicast membership based on interface** This routine takes an interface and deletes multicast group membership on* all sockets for the groups using the specified interface.** RETURNS: N/A** NOMANUAL**/void ifMultiDelete ( struct ifnet *pIf ) { struct inpcb *pInpcb; struct mBlk **ppMblk; struct mBlk *pInm; struct in_multi *inm; struct ip_moptions *pImo; /* Search all open UDP sockets */ for (pInpcb = udb.lh_first; pInpcb != NULL; pInpcb = pInpcb->inp_list.le_next) { pImo = pInpcb->inp_moptions; /* No multicast memberships on this socket. */ if ((pImo == NULL) || (pImo->imo_num_memberships == 0)) continue; ppMblk = &pImo->pInmMblk; /* Search list of multicast memberships on this socket */ while (*ppMblk) { inm = mtod (*ppMblk, struct in_multi *); if (inm->inm_ifp == pIf) { pInm = *ppMblk; *ppMblk = (*ppMblk)->mBlkHdr.mNext; /* delete from list */ in_delmulti (pInm, pInpcb); pImo->imo_num_memberships--; continue; } ppMblk = &(*ppMblk)->mBlkHdr.mNext; } /* If all options have default values, no need to keep ip_moptions. */ if (pImo->imo_num_memberships == 0 && pImo->imo_multicast_ifp == NULL && pImo->imo_multicast_ttl == IP_DEFAULT_MULTICAST_TTL && pImo->imo_multicast_loop == IP_DEFAULT_MULTICAST_LOOP) { FREE (pImo, MT_IPMOPTS); pInpcb->inp_moptions = NULL; } } return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -