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

📄 if_ethersubr.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
		break;#endif#ifdef NS	case ETHERTYPE_NS:		schednetisr(NETISR_NS);		inq = &nsintrq;		break;#endif	default:#if defined (ISO) || defined (LLC)		if (eh->ether_type > ETHERMTU)			goto dropanyway;		l = mtod(m, struct llc *);		switch (l->llc_dsap) {#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 > eh->ether_type)						m_adj(m, eh->ether_type - 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;					IFDEBUG(D_ETHER)						printf("clnp packet");					ENDDEBUG					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((caddr_t)ac->ac_enaddr,					      (caddr_t)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;			}			default:				m_freem(m);				return;			}			break;#endif /* ISO */#ifdef LLC		case LLC_X25_LSAP:		{			if (m->m_pkthdr.len > eh->ether_type)				m_adj(m, eh->ether_type - 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 = eh->ether_type;#ifdef LLC_DEBUG				printf("llc packet\n");#endif /* LLC_DEBUG */			schednetisr(NETISR_CCITT);			inq = &llcintrq;			break;		}#endif /* LLC */		dropanyway:		default:			m_freem(m);			return;		}#else /* ISO || LLC */	    m_freem(m);	    return;#endif /* ISO || LLC */	}	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 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;	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_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;		}}u_char	ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };u_char	ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };/* * 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;	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	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;	enm->enm_next = ac->ac_multiaddrs;	ac->ac_multiaddrs = enm;	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;	register struct ether_multi **p;	struct sockaddr_in *sin;	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	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.	 */	for (p = &enm->enm_ac->ac_multiaddrs;	     *p != enm;	     p = &(*p)->enm_next)		continue;	*p = (*p)->enm_next;	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 + -