📄 if_ethersubr.c
字号:
(*ng_ether_input_p)(ifp, &m, eh); if (m == NULL) return; }/* -------------------------------------------到此为止,这意味着可以加入自己的代码----------------------------------- */ ether_demux(ifp, eh, m);}/* * 真正处理以太网封包. */voidether_demux(ifp, eh, m) /*该三参数和ether_input()函数的参数一样*/ struct ifnet *ifp; struct ether_header *eh; struct mbuf *m;{ struct ifqueue *inq; /* * 结构定义了一个网络接口队列. struct ifqueue { struct mbuf *ifq_head; /*封包的队列头指针 struct mbuf *ifq_tail; /*尾指针 int ifq_len; /*队列长度 int ifq_maxlen; /*队列的最大长度 int ifq_drops; /*丢弃的数量 }; */ u_short ether_type; int s; if ((ifp->if_flags & IFF_PROMISC) != 0 /*不在混杂模式,目的主机硬件地址的第一字节的最后一位是0即非多播地址*/ && (eh->ether_dhost[0] & 1) == 0 /*不是本机地址.注意:在XIE_FIREWALL中不能使用之,应调用一函数*/ && bcmp(eh->ether_dhost, /*该函数功能是先将其转化为IP头部,取目的IP地址(是本地网吗?是),再查*/ IFP2AC(ifp)->ac_enaddr, ETHER_ADDR_LEN) != 0) {/*对应的硬件地址,该硬件地址如为空则发出ARP请求*/ m_freem(m); /*本地网络如下图:*/ return; } */ /* 如果接口没启动则放弃包 */ if ((ifp->if_flags & IFF_UP) == 0) { m_freem(m); return; } ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh); /*接口的接收到的字节数,eh为以太网包头*/ if (eh->ether_dhost[0] & 1) {/*以太网的包头的目的地址(硬件)的第一字节不为全0则为广播或多播包*/ if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,/*是广播还是多播*/ sizeof(etherbroadcastaddr)) == 0) m->m_flags |= M_BCAST; else m->m_flags |= M_MCAST; } if (m->m_flags & (M_BCAST|M_MCAST)) ifp->if_imcasts++; ether_type = ntohs(eh->ether_type);/*网络到主机字节方式*/ switch (ether_type) {#ifdef INET case ETHERTYPE_IP:/*是IP协议吗?*/ if (ipflow_fastforward(m)) return; schednetisr(NETISR_IP);/*调用软中断*/ inq = &ipintrq;/*IP对列*/ break; case ETHERTYPE_ARP:/*是ARP协议吗?*/ if (ifp->if_flags & IFF_NOARP) { /* 如果接口不支持ARP方式,释放包 */ m_freem(m); return; } schednetisr(NETISR_ARP); inq = &arpintrq; break;#endif default: } s = splimp();/*关网络中断*/ if (IF_QFULL(inq)) { /*#原型是define IF_QFULL(ifq) ((ifq)->ifq_len >= (ifq)->ifq_maxlen) 队列满*/ IF_DROP(inq); /*原型是#define IF_DROP(ifq) ((ifq)->ifq_drops++) 丢弃数加1*/ m_freem(m); } else IF_ENQUEUE(inq, m); /*以下是原型 #define IF_ENQUEUE(ifq, m) { \ (m)->m_nextpkt = 0; \ if ((ifq)->ifq_tail == 0) \ 如果队列尾巴为没有,则该队列没初始化 (ifq)->ifq_head = m; \ 初始化队列头为M else \ 有尾巴,即该队列已经有mbuf (ifq)->ifq_tail->m_nextpkt = m; \ 当前的尾巴mbuf的下一mbuf指向m (ifq)->ifq_tail = m; \ 队列的尾巴指向m (ifq)->ifq_len++; \ 队列长度加1} */ splx(s); /*开网络中断*/}/* * 当接口链入到接口列表时执行的普通动作 */void/*在我的网络设备驱动程序中有描写, 主要是由网卡驱动调用*/ether_ifattach(ifp, bpf) register struct ifnet *ifp; int bpf;{ register struct ifaddr *ifa; register struct sockaddr_dl *sdl; if_attach(ifp);/*调用if.c中的过程*/ ifp->if_type = IFT_ETHER; ifp->if_addrlen = 6; ifp->if_hdrlen = 14; ifp->if_mtu = ETHERMTU;/*1500*/ ifp->if_resolvemulti = ether_resolvemulti;/*解释多播的过程指针*/ if (ifp->if_baudrate == 0) /*初始化波特率*/ ifp->if_baudrate = 10000000; ifa = ifnet_addrs[ifp->if_index - 1]; KASSERT(ifa != NULL, ("%s: no lladdr!\n", __FUNCTION__)); sdl = (struct sockaddr_dl *)ifa->ifa_addr; sdl->sdl_type = IFT_ETHER; sdl->sdl_alen = ifp->if_addrlen; bcopy((IFP2AC(ifp))->ac_enaddr, LLADDR(sdl), ifp->if_addrlen); if (bpf)/*BPF支持*/ bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); if (ng_ether_attach_p != NULL)/*PPPoE支持即ADSL*/ (*ng_ether_attach_p)(ifp);}voidether_ifdetach(ifp, bpf) struct ifnet *ifp; int bpf;{ if (ng_ether_detach_p != NULL) (*ng_ether_detach_p)(ifp); if (bpf) bpfdetach(ifp); if_detach(ifp);}SYSCTL_DECL(_net_link);/*申明从哪个根接上*/SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");/*做一个节点*/int /*inctl控制代码和多播代码我就不写了,太平常了*/ether_ioctl(ifp, command, data) struct ifnet *ifp; int command; caddr_t data;{ struct ifaddr *ifa = (struct ifaddr *) data; struct ifreq *ifr = (struct ifreq *) data; int error = 0; switch (command) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; switch (ifa->ifa_addr->sa_family) {#ifdef INET case AF_INET: ifp->if_init(ifp->if_softc); /* before arpwhohas */ arp_ifinit(IFP2AC(ifp), ifa); break;#endif default: ifp->if_init(ifp->if_softc); break; } break; case SIOCGIFADDR: { struct sockaddr *sa; sa = (struct sockaddr *) & ifr->ifr_data; bcopy(IFP2AC(ifp)->ac_enaddr, (caddr_t) sa->sa_data, ETHER_ADDR_LEN); } break; case SIOCSIFMTU: /* * Set the interface MTU. */ if (ifr->ifr_mtu > ETHERMTU) { error = EINVAL; } else { ifp->if_mtu = ifr->ifr_mtu; } break; } return (error);}intether_resolvemulti(ifp, llsa, sa) struct ifnet *ifp; struct sockaddr **llsa; struct sockaddr *sa;{ struct sockaddr_dl *sdl; struct sockaddr_in *sin; u_char *e_addr; switch(sa->sa_family) { case AF_LINK: /* * No mapping needed. Just check that it's a valid MC address. */ sdl = (struct sockaddr_dl *)sa; e_addr = LLADDR(sdl); if ((e_addr[0] & 1) != 1) return EADDRNOTAVAIL; *llsa = 0; return 0;#ifdef INET case AF_INET: sin = (struct sockaddr_in *)sa; if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) return EADDRNOTAVAIL; MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, M_WAITOK|M_ZERO); sdl->sdl_len = sizeof *sdl; sdl->sdl_family = AF_LINK; sdl->sdl_index = ifp->if_index; sdl->sdl_type = IFT_ETHER; sdl->sdl_alen = ETHER_ADDR_LEN; e_addr = LLADDR(sdl); ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr); *llsa = (struct sockaddr *)sdl; return 0;#endif default: /* * Well, the text isn't quite right, but it's the name * that counts... */ return EAFNOSUPPORT; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -