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

📄 if_ethersubr.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
📖 第 1 页 / 共 2 页
字号:
		    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++;#if NBRIDGE > 0	/*	 * Tap the packet off here for a bridge, if configured and	 * active for this interface.  bridge_input returns	 * NULL if it has consumed the packet, otherwise, it	 * gets processed as normal.	 */	if (ifp->if_bridge) {		m = bridge_input(ifp, eh, m);		if (m == NULL)			return;		/* The bridge has determined it's for us. */		goto decapsulate;	}#endif	/*	 * If packet is unicast and we're in promiscuous mode, make sure it	 * is for us.  Drop otherwise.	 */	if ((m->m_flags & (M_BCAST|M_MCAST)) == 0 &&	    (ifp->if_flags & IFF_PROMISC)) {		if (bcmp(ac->ac_enaddr, (caddr_t)eh->ether_dhost,		    ETHER_ADDR_LEN)) {			m_freem(m);			return;		}	}decapsulate:	etype = ntohs(eh->ether_type);	switch (etype) {#ifdef INET	case ETHERTYPE_IP:		schednetisr(NETISR_IP);		inq = &ipintrq;		break;	case ETHERTYPE_ARP:		if (ifp->if_flags & IFF_NOARP)			goto dropanyway;		schednetisr(NETISR_ARP);		inq = &arpintrq;		break;	case ETHERTYPE_REVARP:		if (ifp->if_flags & IFF_NOARP)			goto dropanyway;		revarpinput(m);	/* XXX queue? */		return;#endif#ifdef INET6	/*	 * Schedule IPv6 software interrupt for incoming IPv6 packet.	 */	case ETHERTYPE_IPV6:		schednetisr(NETISR_IPV6);		inq = &ipv6intrq;		break;#endif /* INET6 */#ifdef IPX	case ETHERTYPE_IPX:		schednetisr(NETISR_IPX);		inq = &ipxintrq;		break;#endif#ifdef NS	case ETHERTYPE_NS:		schednetisr(NETISR_NS);		inq = &nsintrq;		break;#endif#ifdef NETATALK	case ETHERTYPE_AT:		schednetisr(NETISR_ATALK);		inq = &atintrq1;		break;	case ETHERTYPE_AARP:		/* probably this should be done with a NETISR as well */		/* XXX queue this */		aarpinput((struct arpcom *)ifp, m);		return;#endif	default:		if (llcfound || etype > ETHERMTU)			goto dropanyway;		llcfound = 1;		l = mtod(m, struct llc *);		switch (l->llc_dsap) {		case LLC_SNAP_LSAP:#ifdef NETATALK			/*			 * Some protocols (like Appletalk) need special			 * handling depending on if they are type II			 * or SNAP encapsulated. Everything else			 * gets handled by stripping off the SNAP header			 * and going back up to decapsulate.			 */			if (l->llc_control == LLC_UI &&			    l->llc_ssap == LLC_SNAP_LSAP &&			    Bcmp(&(l->llc_snap_org_code)[0],			    at_org_code, sizeof(at_org_code)) == 0 &&			    ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) {				inq = &atintrq2;				m_adj(m, AT_LLC_SIZE);				schednetisr(NETISR_ATALK);				break;			}			if (l->llc_control == LLC_UI &&			    l->llc_ssap == LLC_SNAP_LSAP &&			    Bcmp(&(l->llc_snap_org_code)[0],			    aarp_org_code, sizeof(aarp_org_code)) == 0 &&			    ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) {				m_adj(m, AT_LLC_SIZE);				/* XXX Really this should use netisr too */				aarpinput((struct arpcom *)ifp, m);				return;			}#endif /* NETATALK */			if (l->llc_control == LLC_UI &&			    l->llc_dsap == LLC_SNAP_LSAP &&			    l->llc_ssap == LLC_SNAP_LSAP) {				/* SNAP */				if (m->m_pkthdr.len > etype)					m_adj(m, etype - m->m_pkthdr.len);				m->m_data += 6;		/* XXX */				m->m_len -= 6;		/* XXX */				m->m_pkthdr.len -= 6;	/* XXX */				M_PREPEND(m, sizeof *eh, M_DONTWAIT);				if (m == 0)					return;				*mtod(m, struct ether_header *) = *eh;				goto decapsulate;			}			goto dropanyway;#ifdef	ISO		case LLC_ISO_LSAP:			switch (l->llc_control) {			case LLC_UI:				/* LLC_UI_P forbidden in class 1 service */				if ((l->llc_dsap == LLC_ISO_LSAP) &&				    (l->llc_ssap == LLC_ISO_LSAP)) {					/* LSAP for ISO */					if (m->m_pkthdr.len > etype)						m_adj(m, etype - m->m_pkthdr.len);					m->m_data += 3;		/* XXX */					m->m_len -= 3;		/* XXX */					m->m_pkthdr.len -= 3;	/* XXX */					M_PREPEND(m, sizeof *eh, M_DONTWAIT);					if (m == 0)						return;					*mtod(m, struct ether_header *) = *eh;#ifdef ARGO_DEBUG					if (argo_debug[D_ETHER])						printf("clnp packet");#endif					schednetisr(NETISR_ISO);					inq = &clnlintrq;					break;				}				goto dropanyway;			case LLC_XID:			case LLC_XID_P:				if(m->m_len < 6)					goto dropanyway;				l->llc_window = 0;				l->llc_fid = 9;				l->llc_class = 1;				l->llc_dsap = l->llc_ssap = 0;				/* Fall through to */			case LLC_TEST:			case LLC_TEST_P:			{				struct sockaddr sa;				register struct ether_header *eh2;				int i;				u_char c = l->llc_dsap;				l->llc_dsap = l->llc_ssap;				l->llc_ssap = c;				if (m->m_flags & (M_BCAST | M_MCAST))					bcopy(ac->ac_enaddr,					    eh->ether_dhost, 6);				sa.sa_family = AF_UNSPEC;				sa.sa_len = sizeof(sa);				eh2 = (struct ether_header *)sa.sa_data;				for (i = 0; i < 6; i++) {					eh2->ether_shost[i] = c = eh->ether_dhost[i];					eh2->ether_dhost[i] =						eh->ether_dhost[i] = eh->ether_shost[i];					eh->ether_shost[i] = c;				}				ifp->if_output(ifp, m, &sa, NULL);				return;			}			break;			}#endif /* ISO */#ifdef CCITT		case LLC_X25_LSAP:			if (m->m_pkthdr.len > etype)				m_adj(m, etype - m->m_pkthdr.len);			M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);			if (m == 0)				return;			if (!sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP,			    eh->ether_dhost, LLC_X25_LSAP, 6,			    mtod(m, struct sdl_hdr *)))				panic("ETHER cons addr failure");			mtod(m, struct sdl_hdr *)->sdlhdr_len = etype;#ifdef LLC_DEBUG			printf("llc packet\n");#endif /* LLC_DEBUG */			schednetisr(NETISR_CCITT);			inq = &llcintrq;			break;#endif /* CCITT */		dropanyway:		default:			m_freem(m);			return;		}	}	s = splimp();	if (IF_QFULL(inq)) {		IF_DROP(inq);		m_freem(m);	} else		IF_ENQUEUE(inq, m);	splx(s);}/* * Convert Ethernet address to printable (loggable) representation. */static char digits[] = "0123456789abcdef";char *ether_sprintf(ap)	register u_char *ap;{	register int i;	static char etherbuf[18];	register char *cp = etherbuf;	for (i = 0; i < 6; i++) {		*cp++ = digits[*ap >> 4];		*cp++ = digits[*ap++ & 0xf];		*cp++ = ':';	}	*--cp = 0;	return (etherbuf);}/* * Perform common duties while attaching to interface list */voidether_ifattach(ifp)	register struct ifnet *ifp;{	register struct ifaddr *ifa;	register struct sockaddr_dl *sdl;	ifp->if_type = IFT_ETHER;	ifp->if_addrlen = 6;	ifp->if_hdrlen = 14;	ifp->if_mtu = ETHERMTU;	ifp->if_output = ether_output;	for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;	    ifa = ifa->ifa_list.tqe_next)		if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&		    sdl->sdl_family == AF_LINK) {			sdl->sdl_type = IFT_ETHER;			sdl->sdl_alen = ifp->if_addrlen;			bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,			    LLADDR(sdl), ifp->if_addrlen);			break;		}	LIST_INIT(&((struct arpcom *)ifp)->ac_multiaddrs);}voidether_ifdetach(ifp)	struct ifnet *ifp;{	struct arpcom *ac = (struct arpcom *)ifp;	struct ether_multi *enm;	for (enm = LIST_FIRST(&ac->ac_multiaddrs); enm;	    enm = LIST_FIRST(&ac->ac_multiaddrs)) {		LIST_REMOVE(enm, enm_list);		free(enm, M_IFMADDR);	}}u_char	ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };u_char	ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };#ifdef INET6u_char	ether_ipv6multicast_min[6] = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 };u_char	ether_ipv6multicast_max[6] = { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff };#endif /* INET6 *//* * Add an Ethernet multicast address or range of addresses to the list for a * given interface. */intether_addmulti(ifr, ac)	struct ifreq *ifr;	register struct arpcom *ac;{	register struct ether_multi *enm;	struct sockaddr_in *sin;#ifdef INET6	struct sockaddr_in6 *sin6;#endif /* INET6 */	u_char addrlo[6];	u_char addrhi[6];	int s = splimp();	switch (ifr->ifr_addr.sa_family) {	case AF_UNSPEC:		bcopy(ifr->ifr_addr.sa_data, addrlo, 6);		bcopy(addrlo, addrhi, 6);		break;#ifdef INET	case AF_INET:		sin = (struct sockaddr_in *)&(ifr->ifr_addr);		if (sin->sin_addr.s_addr == INADDR_ANY) {			/*			 * An IP address of INADDR_ANY means listen to all			 * of the Ethernet multicast addresses used for IP.			 * (This is for the sake of IP multicast routers.)			 */			bcopy(ether_ipmulticast_min, addrlo, 6);			bcopy(ether_ipmulticast_max, addrhi, 6);		}		else {			ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);			bcopy(addrlo, addrhi, 6);		}		break;#endif#ifdef INET6	case AF_INET6:		sin6 = (struct sockaddr_in6 *)&(ifr->ifr_addr);		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {			/*			 * An unspecified IPv6 address means listen to all			 * of the IPv6 multicast addresses on this Ethernet.			 * (Multicast routers like this.)			 */			bcopy(ether_ipv6multicast_min, addrlo, ETHER_ADDR_LEN);			bcopy(ether_ipv6multicast_max, addrhi, ETHER_ADDR_LEN);		} else {			ETHER_MAP_IN6_MULTICAST(sin6->sin6_addr, addrlo);			bcopy(addrlo, addrhi, ETHER_ADDR_LEN);		}		break;#endif /* INET6 */	default:		splx(s);		return (EAFNOSUPPORT);	}	/*	 * Verify that we have valid Ethernet multicast addresses.	 */	if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {		splx(s);		return (EINVAL);	}	/*	 * See if the address range is already in the list.	 */	ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);	if (enm != NULL) {		/*		 * Found it; just increment the reference count.		 */		++enm->enm_refcount;		splx(s);		return (0);	}	/*	 * New address or range; malloc a new multicast record	 * and link it into the interface's multicast list.	 */	enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT);	if (enm == NULL) {		splx(s);		return (ENOBUFS);	}	bcopy(addrlo, enm->enm_addrlo, 6);	bcopy(addrhi, enm->enm_addrhi, 6);	enm->enm_ac = ac;	enm->enm_refcount = 1;	LIST_INSERT_HEAD(&ac->ac_multiaddrs, enm, enm_list);	ac->ac_multicnt++;	splx(s);	/*	 * Return ENETRESET to inform the driver that the list has changed	 * and its reception filter should be adjusted accordingly.	 */	return (ENETRESET);}/* * Delete a multicast address record. */intether_delmulti(ifr, ac)	struct ifreq *ifr;	register struct arpcom *ac;{	register struct ether_multi *enm;	struct sockaddr_in *sin;#ifdef INET6	struct sockaddr_in6 *sin6;#endif /* INET6 */	u_char addrlo[6];	u_char addrhi[6];	int s = splimp();	switch (ifr->ifr_addr.sa_family) {	case AF_UNSPEC:		bcopy(ifr->ifr_addr.sa_data, addrlo, 6);		bcopy(addrlo, addrhi, 6);		break;#ifdef INET	case AF_INET:		sin = (struct sockaddr_in *)&(ifr->ifr_addr);		if (sin->sin_addr.s_addr == INADDR_ANY) {			/*			 * An IP address of INADDR_ANY means stop listening			 * to the range of Ethernet multicast addresses used			 * for IP.			 */			bcopy(ether_ipmulticast_min, addrlo, 6);			bcopy(ether_ipmulticast_max, addrhi, 6);		}		else {			ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);			bcopy(addrlo, addrhi, 6);		}		break;#endif#ifdef INET6	case AF_INET6:		sin6 = (struct sockaddr_in6 *)&(ifr->ifr_addr);		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {			/*			 * An unspecified IPv6 address means stop listening to			 * all IPv6 multicast addresses on this Ethernet.'			 *			 * (This might not be healthy, given IPv6's reliance on			 * multicast for things like neighbor discovery.			 * Perhaps initializing all-nodes, solicited nodes, and			 * possibly all-routers for this interface afterwards			 * is not a bad idea.)			 */			bcopy(ether_ipv6multicast_min, addrlo, ETHER_ADDR_LEN);			bcopy(ether_ipv6multicast_max, addrhi, ETHER_ADDR_LEN);		} else {			ETHER_MAP_IN6_MULTICAST(sin6->sin6_addr, addrlo);			bcopy(addrlo, addrhi, ETHER_ADDR_LEN);		}		break;#endif /* INET6 */	default:		splx(s);		return (EAFNOSUPPORT);	}	/*	 * Look up the address in our list.	 */	ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);	if (enm == NULL) {		splx(s);		return (ENXIO);	}	if (--enm->enm_refcount != 0) {		/*		 * Still some claims to this record.		 */		splx(s);		return (0);	}	/*	 * No remaining claims to this record; unlink and free it.	 */	LIST_REMOVE(enm, enm_list);	free(enm, M_IFMADDR);	ac->ac_multicnt--;	splx(s);	/*	 * Return ENETRESET to inform the driver that the list has changed	 * and its reception filter should be adjusted accordingly.	 */	return (ENETRESET);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -