if_ethersubr.c

来自「eCos操作系统源码」· C语言 代码 · 共 954 行 · 第 1/2 页

C
954
字号
		}		if (bif != BDG_LOCAL) {			struct mbuf *oldm = m ;			save_eh = *eh ; /* because it might change */			m = bdg_forward(m, eh, bif);	/* needs forwarding */			/*			 * Do not continue if bdg_forward() processed our			 * packet (and cleared the mbuf pointer m) or if			 * it dropped (m_free'd) the packet itself.			 */			if (m == NULL) {			    if (bif == BDG_BCAST || bif == BDG_MCAST)				printf("bdg_forward drop MULTICAST PKT\n");			    return;			}			if (m != oldm) /* m changed! */			    eh = &save_eh ;		}		if (bif == BDG_LOCAL		    || bif == BDG_BCAST		    || bif == BDG_MCAST)			goto recvLocal;			/* receive locally */		/* If not local and not multicast, just drop it */		if (m != NULL)			m_freem(m);		return;       }#endif#ifdef BRIDGErecvLocal:#endif	/* Continue with upper layer processing */	ether_demux(ifp, eh, m);}/* * Upper layer processing for a received Ethernet packet. */voidether_demux(ifp, eh, m)	struct ifnet *ifp;	struct ether_header *eh;	struct mbuf *m;{	struct ifqueue *inq;	u_short ether_type;	int s;#if defined(NETATALK)	register struct llc *l;#endif#ifdef BRIDGE    if (! (do_bridge && BDG_USED(ifp) ) )#endif	/* Discard packet if upper layers shouldn't see it because it was	   unicast to a different Ethernet address. If the driver is working	   properly, then this situation can only happen when the interface	   is in promiscuous mode. */	if ((ifp->if_flags & IFF_PROMISC) != 0	    && (eh->ether_dhost[0] & 1) == 0	    && bcmp(eh->ether_dhost,	      IFP2AC(ifp)->ac_enaddr, ETHER_ADDR_LEN) != 0) {		m_freem(m);		return;	}	/* Discard packet if interface is not up */	if ((ifp->if_flags & IFF_UP) == 0) {		m_freem(m);		return;	}	if (eh->ether_dhost[0] & 1) {		/*		 * If this is not a simplex interface, drop the packet		 * if it came from us.		 */		if ((ifp->if_flags & IFF_SIMPLEX) == 0) {			struct ifaddr *ifa;			struct sockaddr_dl *sdl = NULL;			/* find link-layer address */			TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)				if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&				    sdl->sdl_family == AF_LINK)					break;			if (sdl && bcmp(LLADDR(sdl), eh->ether_shost,			    ETHER_ADDR_LEN) == 0) {				m_freem(m);				return;			}		}		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++;	ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);	ether_type = ntohs(eh->ether_type);#if NVLAN > 0	if (ether_type == vlan_proto) {		if (vlan_input(eh, m) < 0)			ifp->if_data.ifi_noproto++;		return;	}#endif /* NVLAN > 0 */	switch (ether_type) {#ifdef INET	case ETHERTYPE_IP:		if (ipflow_fastforward(m))			return;		schednetisr(NETISR_IP);		inq = &ipintrq;		break;	case ETHERTYPE_ARP:		if (ifp->if_flags & IFF_NOARP) {			/* Discard packet if ARP is disabled on interface */			m_freem(m);			return;		}		schednetisr(NETISR_ARP);		inq = &arpintrq;		break;#endif#ifdef IPX	case ETHERTYPE_IPX:		if (ef_inputp && ef_inputp(ifp, eh, m) == 0)			return;		schednetisr(NETISR_IPX);		inq = &ipxintrq;		break;#endif#ifdef INET6	case ETHERTYPE_IPV6:		schednetisr(NETISR_IPV6);		inq = &ip6intrq;		break;#endif#ifdef NS	case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */		schednetisr(NETISR_NS);		inq = &nsintrq;		break;#endif /* NS */#ifdef NETATALK        case ETHERTYPE_AT:                schednetisr(NETISR_ATALK);                inq = &atintrq1;                break;        case ETHERTYPE_AARP:		/* probably this should be done with a NETISR as well */                aarpinput(IFP2AC(ifp), m); /* XXX */                return;#endif /* NETATALK */	default:#ifdef IPX		if (ef_inputp && ef_inputp(ifp, eh, m) == 0)			return;#endif /* IPX */#ifdef NS		checksum = mtod(m, ushort *);		/* Novell 802.3 */		if ((ether_type <= ETHERMTU) &&			((*checksum == 0xffff) || (*checksum == 0xE0E0))){			if(*checksum == 0xE0E0) {				m->m_pkthdr.len -= 3;				m->m_len -= 3;				m->m_data += 3;			}				schednetisr(NETISR_NS);				inq = &nsintrq;				break;		}#endif /* NS */#if defined(NETATALK)		if (ether_type > ETHERMTU)			goto dropanyway;		l = mtod(m, struct llc *);		switch (l->llc_dsap) {		case LLC_SNAP_LSAP:		    switch (l->llc_control) {		    case LLC_UI:			if (l->llc_ssap != LLC_SNAP_LSAP)			    goto dropanyway;				if (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, sizeof( struct llc ));			    schednetisr(NETISR_ATALK);			    break;			}			if (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, sizeof( struct llc ));			    aarpinput(IFP2AC(ifp), m); /* XXX */			    return;			}				    default:			goto dropanyway;		    }		    break;		dropanyway:		default:			if (ng_ether_input_orphan_p != NULL)				(*ng_ether_input_orphan_p)(ifp, m, eh);			else				m_freem(m);			return;		}#else /* NETATALK */		if (ng_ether_input_orphan_p != NULL)			(*ng_ether_input_orphan_p)(ifp, m, eh);		else			m_freem(m);		return;#endif /* NETATALK */	}	s = splimp();	if (IF_QFULL(inq)) {		IF_DROP(inq);		m_freem(m);	} else		IF_ENQUEUE(inq, m);	splx(s);}/* * Perform common duties while attaching to interface list */voidether_ifattach(ifp, bpf)	register struct ifnet *ifp;	int bpf;{	register struct ifaddr *ifa;	register struct sockaddr_dl *sdl;	if_attach(ifp);	ifp->if_type = IFT_ETHER;	ifp->if_addrlen = 6;	ifp->if_hdrlen = 14;	ifp->if_mtu = ETHERMTU;	ifp->if_resolvemulti = ether_resolvemulti;	if (ifp->if_baudrate == 0)	    ifp->if_baudrate = 10000000;	ifa = ifnet_addrs[ifp->if_index - 1];	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);#ifdef BPF	if (bpf)		bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));#endif	if (ng_ether_attach_p != NULL)		(*ng_ether_attach_p)(ifp);}/* * Perform common duties while detaching an Ethernet interface */voidether_ifdetach(ifp, bpf)	struct ifnet *ifp;	int bpf;{	if (ng_ether_detach_p != NULL)		(*ng_ether_detach_p)(ifp);#ifdef BPF	if (bpf)		bpfdetach(ifp);#endif	if_detach(ifp);}SYSCTL_DECL(_net_link);SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");intether_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#ifdef IPX		/*		 * XXX - This code is probably wrong		 */		case AF_IPX:			{			register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);			struct arpcom *ac = IFP2AC(ifp);			if (ipx_nullhost(*ina))				ina->x_host =				    *(union ipx_host *)			            ac->ac_enaddr;			else {				bcopy((caddr_t) ina->x_host.c_host,				      (caddr_t) ac->ac_enaddr,				      sizeof(ac->ac_enaddr));			}			/*			 * Set new address			 */			ifp->if_init(ifp->if_softc);			break;			}#endif#ifdef NS		/*		 * XXX - This code is probably wrong		 */		case AF_NS:		{			register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);			struct arpcom *ac = IFP2AC(ifp);			if (ns_nullhost(*ina))				ina->x_host =				    *(union ns_host *) (ac->ac_enaddr);			else {				bcopy((caddr_t) ina->x_host.c_host,				      (caddr_t) ac->ac_enaddr,				      sizeof(ac->ac_enaddr));			}			/*			 * Set new address			 */			ifp->if_init(ifp->if_softc);			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;#ifdef INET6	struct sockaddr_in6 *sin6;#endif	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#ifdef INET6	case AF_INET6:		sin6 = (struct sockaddr_in6 *)sa;		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {			/*			 * An IP6 address of 0 means listen to all			 * of the Ethernet multicast address used for IP6.			 * (This is used for multicast routers.)			 */			ifp->if_flags |= IFF_ALLMULTI;			*llsa = 0;			return 0;		}		if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_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_IPV6_MULTICAST(&sin6->sin6_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 + =
减小字号Ctrl + -
显示快捷键?