📄 if.c
字号:
count = (if_cloners_count < ifcr->ifcr_count) ? if_cloners_count : ifcr->ifcr_count; for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0; ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) { strncpy(outbuf, ifc->ifc_name, IFNAMSIZ); outbuf[IFNAMSIZ - 1] = '\0'; /* sanity */ error = copyout(outbuf, dst, IFNAMSIZ); if (error) break; } return (error);}/* * Locate an interface based on a complete address. *//*ARGSUSED*/struct ifaddr *ifa_ifwithaddr(addr) register struct sockaddr *addr;{ register struct ifnet *ifp; register struct ifaddr *ifa;#define equal(a1, a2) \ (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) for (ifa = ifp->if_addrhead.tqh_first; ifa; ifa = ifa->ifa_link.tqe_next) { if (ifa->ifa_addr->sa_family != addr->sa_family) continue; if (equal(addr, ifa->ifa_addr)) return (ifa); if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && /* IP6 doesn't have broadcast */ ifa->ifa_broadaddr->sa_len != 0 && equal(ifa->ifa_broadaddr, addr)) return (ifa); } return ((struct ifaddr *)0);}/* * Locate the point to point interface with a given destination address. *//*ARGSUSED*/struct ifaddr *ifa_ifwithdstaddr(addr) register struct sockaddr *addr;{ register struct ifnet *ifp; register struct ifaddr *ifa; for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) if (ifp->if_flags & IFF_POINTOPOINT) for (ifa = ifp->if_addrhead.tqh_first; ifa; ifa = ifa->ifa_link.tqe_next) { if (ifa->ifa_addr->sa_family != addr->sa_family) continue; if (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)) return (ifa); } return ((struct ifaddr *)0);}/* * Find an interface on a specific network. If many, choice * is most specific found. */struct ifaddr *ifa_ifwithnet(addr) struct sockaddr *addr;{ register struct ifnet *ifp; register struct ifaddr *ifa; struct ifaddr *ifa_maybe = (struct ifaddr *) 0; u_int af = addr->sa_family; char *addr_data = addr->sa_data, *cplim; /* * AF_LINK addresses can be looked up directly by their index number, * so do that if we can. */ if (af == AF_LINK) { register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr; if (sdl->sdl_index && sdl->sdl_index <= if_index) return (ifnet_addrs[sdl->sdl_index - 1]); } /* * Scan though each interface, looking for ones that have * addresses in this address family. */ for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) { for (ifa = ifp->if_addrhead.tqh_first; ifa; ifa = ifa->ifa_link.tqe_next) { register char *cp, *cp2, *cp3; if (ifa->ifa_addr->sa_family != af)next: continue; if (#ifdef INET6 /* XXX: for maching gif tunnel dst as routing entry gateway */ addr->sa_family != AF_INET6 &&#endif ifp->if_flags & IFF_POINTOPOINT) { /* * This is a bit broken as it doesn't * take into account that the remote end may * be a single node in the network we are * looking for. * The trouble is that we don't know the * netmask for the remote end. */ if (ifa->ifa_dstaddr != 0 && equal(addr, ifa->ifa_dstaddr)) return (ifa); } else { /* * if we have a special address handler, * then use it instead of the generic one. */ if (ifa->ifa_claim_addr) { if ((*ifa->ifa_claim_addr)(ifa, addr)) { return (ifa); } else { continue; } } /* * Scan all the bits in the ifa's address. * If a bit dissagrees with what we are * looking for, mask it with the netmask * to see if it really matters. * (A byte at a time) */ if (ifa->ifa_netmask == 0) continue; cp = addr_data; cp2 = ifa->ifa_addr->sa_data; cp3 = ifa->ifa_netmask->sa_data; cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; while (cp3 < cplim) if ((*cp++ ^ *cp2++) & *cp3++) goto next; /* next address! */ /* * If the netmask of what we just found * is more specific than what we had before * (if we had one) then remember the new one * before continuing to search * for an even better one. */ if (ifa_maybe == 0 || rn_refines((caddr_t)ifa->ifa_netmask, (caddr_t)ifa_maybe->ifa_netmask)) ifa_maybe = ifa; } } } return (ifa_maybe);}/* * Find an interface address specific to an interface best matching * a given address. */struct ifaddr *ifaof_ifpforaddr(addr, ifp) struct sockaddr *addr; register struct ifnet *ifp;{ register struct ifaddr *ifa; register char *cp, *cp2, *cp3; register char *cplim; struct ifaddr *ifa_maybe = 0; u_int af = addr->sa_family; if (af >= AF_MAX) return (0); for (ifa = ifp->if_addrhead.tqh_first; ifa; ifa = ifa->ifa_link.tqe_next) { if (ifa->ifa_addr->sa_family != af) continue; if (ifa_maybe == 0) ifa_maybe = ifa; if (ifa->ifa_netmask == 0) { if (equal(addr, ifa->ifa_addr) || (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))) return (ifa); continue; } if (ifp->if_flags & IFF_POINTOPOINT) { if (equal(addr, ifa->ifa_dstaddr)) return (ifa); } else { cp = addr->sa_data; cp2 = ifa->ifa_addr->sa_data; cp3 = ifa->ifa_netmask->sa_data; cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; for (; cp3 < cplim; cp3++) if ((*cp++ ^ *cp2++) & *cp3) break; if (cp3 == cplim) return (ifa); } } return (ifa_maybe);}/* * Default action when installing a route with a Link Level gateway. * Lookup an appropriate real ifa to point to. * This should be moved to /sys/net/link.c eventually. */static voidlink_rtrequest(cmd, rt, sa) int cmd; register struct rtentry *rt; struct sockaddr *sa;{ register struct ifaddr *ifa; struct sockaddr *dst; struct ifnet *ifp; if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) return; ifa = ifaof_ifpforaddr(dst, ifp); if (ifa) { IFAFREE(rt->rt_ifa); rt->rt_ifa = ifa; ifa->ifa_refcnt++; if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) ifa->ifa_rtrequest(cmd, rt, sa); }}/* * Mark an interface down and notify protocols of * the transition. * NOTE: must be called at splnet or eqivalent. */voidif_unroute(ifp, flag, fam) register struct ifnet *ifp; int flag, fam;{ register struct ifaddr *ifa; ifp->if_flags &= ~flag; getmicrotime(&ifp->if_lastchange); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family)) pfctlinput(PRC_IFDOWN, ifa->ifa_addr); if_qflush(&ifp->if_snd); rt_ifmsg(ifp);}/* * Mark an interface up and notify protocols of * the transition. * NOTE: must be called at splnet or eqivalent. */voidif_route(ifp, flag, fam) register struct ifnet *ifp; int flag, fam;{ register struct ifaddr *ifa; ifp->if_flags |= flag; getmicrotime(&ifp->if_lastchange); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family)) pfctlinput(PRC_IFUP, ifa->ifa_addr); rt_ifmsg(ifp);#ifdef INET6 in6_if_up(ifp);#endif}/* * Mark an interface down and notify protocols of * the transition. * NOTE: must be called at splnet or eqivalent. */voidif_down(ifp) register struct ifnet *ifp;{ if_unroute(ifp, IFF_UP, AF_UNSPEC);}/* * Mark an interface up and notify protocols of * the transition. * NOTE: must be called at splnet or eqivalent. */voidif_up(ifp) register struct ifnet *ifp;{ if_route(ifp, IFF_UP, AF_UNSPEC);}/* * Flush an interface queue. */static voidif_qflush(ifq)#ifdef ALTQ struct ifaltq *ifq;#else register struct ifqueue *ifq;#endif{ register struct mbuf *m, *n;#ifdef ALTQ if (ALTQ_IS_ENABLED(ifq)) ALTQ_PURGE(ifq);#endif n = ifq->ifq_head; while ((m = n) != 0) { n = m->m_act; m_freem(m); } ifq->ifq_head = 0; ifq->ifq_tail = 0; ifq->ifq_len = 0;}/* * Handle interface watchdog timer routines. Called * from softclock, we decrement timers (if set) and * call the appropriate interface routine on expiration. */static voidif_slowtimo(arg) void *arg;{ register struct ifnet *ifp; int s = splimp(); for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) { if (ifp->if_timer == 0 || --ifp->if_timer) continue; if (ifp->if_watchdog) (*ifp->if_watchdog)(ifp); } splx(s); timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);}/* * Map interface name to * interface structure pointer. */struct ifnet *ifunit(const char *name){ char namebuf[IFNAMSIZ + 1]; const char *cp; struct ifnet *ifp; int unit; unsigned len, m; char c; len = strlen(name); if (len < 2 || len > IFNAMSIZ) return NULL; cp = name + len - 1; c = *cp; if (c < '0' || c > '9') return NULL; /* trailing garbage */ unit = 0; m = 1; do { if (cp == name) return NULL; /* no interface name */ unit += (c - '0') * m; if (unit > 1000000) return NULL; /* number is unreasonable */ m *= 10; c = *--cp; } while (c >= '0' && c <= '9'); len = cp - name + 1; bcopy(name, namebuf, len); namebuf[len] = '\0'; /* * Now search all the interfaces for this name/number */ for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) { if (strcmp(ifp->if_name, namebuf)) continue; if (unit == ifp->if_unit) break; } return (ifp);}/* * Map interface name in a sockaddr_dl to * interface structure pointer. */struct ifnet *if_withname(sa) struct sockaddr *sa;{ char ifname[IFNAMSIZ+1]; struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; if ( (sa->sa_family != AF_LINK) || (sdl->sdl_nlen == 0) || (sdl->sdl_nlen > IFNAMSIZ) ) return NULL; /* * ifunit wants a null-terminated name. It may not be null-terminated * in the sockaddr. We don't want to change the caller's sockaddr, * and there might not be room to put the trailing null anyway, so we * make a local copy that we know we can null terminate safely. */ bcopy(sdl->sdl_data, ifname, sdl->sdl_nlen); ifname[sdl->sdl_nlen] = '\0'; return ifunit(ifname);}// TEMP?#define _NAME(s) \ case s: return #s; break; char *_ioctl_name(u_long cmd){ static char unknown[32]; switch (cmd) { _NAME(SIOCSHIWAT); _NAME(SIOCGHIWAT); _NAME(SIOCSLOWAT); _NAME(SIOCGLOWAT); _NAME(SIOCATMARK); _NAME(SIOCSPGRP); _NAME(SIOCGPGRP); _NAME(SIOCADDRT); _NAME(SIOCDELRT);//_NAME(SIOCGETVIFCNT);//_NAME(SIOCGETSGCNT); _NAME(SIOCSIFADDR); _NAME(OSIOCGIFADDR); _NAME(SIOCGIFADDR); _NAME(SIOCSIFDSTADDR); _NAME(OSIOCGIFDSTADDR); _NAME(SIOCGIFDSTADDR); _NAME(SIOCSIFFLAGS); _NAME(SIOCGIFFLAGS); _NAME(OSIOCGIFBRDADDR); _NAME(SIOCGIFBRDADDR); _NAME(SIOCSIFBRDADDR); _NAME(OSIOCGIFCONF); _NAME(SIOCGIFCONF); _NAME(OSIOCGIFNETMASK); _NAME(SIOCGIFNETMASK); _NAME(SIOCSIFNETMASK); _NAME(SIOCGIFMETRIC); _NAME(SIOCSIFMETRIC); _NAME(SIOCDIFADDR); _NAME(SIOCAIFADDR); _NAME(SIOCALIFADDR); _NAME(SIOCGLIFADDR); _NAME(SIOCDLIFADDR); _NAME(SIOCADDMULTI); _NAME(SIOCDELMULTI); _NAME(SIOCGIFMTU); _NAME(SIOCSIFMTU); _NAME(SIOCGIFPHYS); _NAME(SIOCSIFPHYS); _NAME(SIOCSIFMEDIA); _NAME(SIOCGIFMEDIA); _NAME(SIOCSIFPHYADDR ); _NAME(SIOCGIFPSRCADDR); _NAME(SIOCGIFPDSTADDR); _NAME(SIOCDIFPHYADDR); _NAME(SIOCSLIFPHYADDR); _NAME(SIOCGLIFPHYADDR); _NAME(SIOCSIFGENERIC); _NAME(SIOCGIFGENERIC); _NAME(SIOCGIFSTATUS); _NAME(SIOCSIFLLADDR); _NAME(SIOCIFCREATE); _NAME(SIOCIFDESTROY); _NAME(SIOCIFGCLONERS); _NAME(FIONBIO); _NAME(FIOASYNC); _NAME(FIONREAD); _NAME(SIOCGIFHWADDR); _NAME(SIOCSIFHWADDR); _NAME(SIOCGIFSTATSUD); _NAME(SIOCGIFSTATS); default: diag_sprintf(unknown, "0x%08x", cmd); return unknown; }}// TEMP?/* * Interface ioctls. */intifioctl(so, cmd, data, p) struct socket *so; u_long cmd; caddr_t data; struct proc *p;{ register struct ifnet *ifp; register struct ifreq *ifr; struct ifstat *ifs; int error; short oif_flags; log(LOG_IOCTL, "%s: cmd: %s, data:\n", __FUNCTION__, _ioctl_name(cmd)); switch (cmd) { case SIOCGIFCONF: case OSIOCGIFCONF: return (ifconf(cmd, data)); } ifr = (struct ifreq *)data; switch (cmd) { case SIOCIFCREATE: case SIOCIFDESTROY: return ((cmd == SIOCIFCREATE) ? if_clone_create(ifr->ifr_name, sizeof(ifr->ifr_name)) : if_clone_destroy(ifr->ifr_name)); case SIOCIFGCLONERS: return (if_clone_list((struct if_clonereq *)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 SIOCGIFMTU: ifr->ifr_mtu = ifp->if_mtu; break; case SIOCGIFPHYS: ifr->ifr_phys = ifp->if_physical; break; case SIOCSIFFLAGS: ifr->ifr_prevflags = ifp->if_flags; if (ifp->if_flags & IFF_SMART) { /* Smart drivers twiddle their own routes */ } else if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { int s = splimp(); if_down(ifp); splx(s);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -