⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_ethersubr.c

📁 Details description of Free BSD network source code.Those documents have explained each line of code
💻 C
📖 第 1 页 / 共 2 页
字号:
		(*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 + -