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

📄 if_ethersubr.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			return (0);
		}

		/*
		 * ifaddr is the first thing in at_ifaddr
		 */
		aa = (struct at_ifaddr *)at_ifawithnet(
			(struct sockaddr_at *)dst,
			ifp->if_addrlist.tqh_first);
		if (aa == 0)
			goto bad;

		/*
		 * In the phase 2 case, we need to prepend an mbuf for the llc
		 * header. Since we must preserve the value of m, which is
		 * passed to us by value, we m_copy() the first mbuf,
		 * and use it for our llc header.
		 */
		if ( aa->aa_flags & AFA_PHASE2 ) {
			struct llc llc;

			/* XXX Really this should use netisr too */
			M_PREPEND(m, AT_LLC_SIZE, M_WAIT);
			/*
			 * FreeBSD doesn't count the LLC len in
			 * ifp->obytes, so they increment a length
			 * field here. We don't do this.
			 */
			llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
			llc.llc_control = LLC_UI;
			bcopy(at_org_code, llc.llc_snap_org_code,
				sizeof(at_org_code));
			llc.llc_snap_ether_type = htons( ETHERTYPE_AT );
			bcopy(&llc, mtod(m, caddr_t), AT_LLC_SIZE);
			etype = htons(m->m_pkthdr.len);
		} else {
			etype = htons(ETHERTYPE_AT);
		}
		} break;
#endif /* NETATALK */
#ifdef	ISO
	case AF_ISO: {
		int	snpalen;
		struct	llc *l;
		register struct sockaddr_dl *sdl;

		if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
		    sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
			bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
		} else {
			error = iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
						(char *)edst, &snpalen);
			if (error)
				goto bad; /* Not Resolved */
		}
		/* If broadcasting on a simplex interface, loopback a copy */
		if (*edst & 1)
			m->m_flags |= (M_BCAST|M_MCAST);
		if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
		    (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
			M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
			if (mcopy) {
				eh = mtod(mcopy, struct ether_header *);
				bcopy(edst, eh->ether_dhost, sizeof (edst));
				bcopy(ac->ac_enaddr, eh->ether_shost,
				    sizeof (edst));
			}
		}
		M_PREPEND(m, 3, M_DONTWAIT);
		if (m == NULL)
			return (0);
		etype = htons(m->m_pkthdr.len);
		l = mtod(m, struct llc *);
		l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
		l->llc_control = LLC_UI;
#ifdef ARGO_DEBUG
		if (argo_debug[D_ETHER]) {
			int i;
			printf("unoutput: sending pkt to: ");
			for (i=0; i<6; i++)
				printf("%x ", edst[i] & 0xff);
			printf("\n");
		}
#endif
		} break;
#endif /* ISO */
/*	case AF_NSAP: */
	case AF_CCITT: {
		register struct sockaddr_dl *sdl =
			(struct sockaddr_dl *) rt -> rt_gateway;

		if (sdl && sdl->sdl_family == AF_LINK
		    && sdl->sdl_alen > 0) {
			bcopy(LLADDR(sdl), (char *)edst,
				sizeof(edst));
		} else goto bad; /* Not a link interface ? Funny ... */
		if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
		    (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
			M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
			if (mcopy) {
				eh = mtod(mcopy, struct ether_header *);
				bcopy(edst, eh->ether_dhost, sizeof (edst));
				bcopy(ac->ac_enaddr, eh->ether_shost,
				    sizeof (edst));
			}
		}
		etype = htons(m->m_pkthdr.len);
#ifdef LLC_DEBUG
		{
			int i;
			register struct llc *l = mtod(m, struct llc *);

			printf("ether_output: sending LLC2 pkt to: ");
			for (i=0; i<6; i++)
				printf("%x ", edst[i] & 0xff);
			printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
			    m->m_pkthdr.len, l->llc_dsap & 0xff, l->llc_ssap &0xff,
			    l->llc_control & 0xff);

		}
#endif /* LLC_DEBUG */
		} break;

	case AF_UNSPEC:
		eh = (struct ether_header *)dst->sa_data;
 		bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
		/* AF_UNSPEC doesn't swap the byte order of the ether_type. */
		etype = eh->ether_type;
		break;

	default:
#ifdef __ECOS
//		diag_printf("%s: can't handle af%d\n", ifp->if_xname,
//                            dst->sa_family);
#else
		printf("%s: can't handle af%d\n", ifp->if_xname,
			dst->sa_family);
#endif
		senderr(EAFNOSUPPORT);
	}

	if (mcopy)
		(void) looutput(ifp, mcopy, dst, rt);

	/*
	 * Add local net header.  If no space in first mbuf,
	 * allocate another.
	 */
	M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
	if (m == 0)
		senderr(ENOBUFS);
	eh = mtod(m, struct ether_header *);
	bcopy((caddr_t)&etype,(caddr_t)&eh->ether_type,
		sizeof(eh->ether_type));
 	bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
 	bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost,
	    sizeof(eh->ether_shost));

#if NBRIDGE > 0
	/*
	 * Interfaces that are bridge members need special handling
	 * for output.
	 */
	if (ifp->if_bridge) {
		bridge_output(ifp, m, NULL, NULL);
		return (error);
	}
#endif

	s = splimp();
	/*
	 * Queue message on interface, and start output if interface
	 * not yet active.
	 */
	if (IF_QFULL(&ifp->if_snd)) {
                // Let the interface try a dequeue anyway, in case the
                // interface has "got better" from whatever made the queue
                // fill up - being unplugged for example.
                if ((ifp->if_flags & IFF_OACTIVE) == 0)
                    (*ifp->if_start)(ifp);
		IF_DROP(&ifp->if_snd);
		splx(s);
		senderr(ENOBUFS);
	}
	ifp->if_obytes += m->m_pkthdr.len;
	IF_ENQUEUE(&ifp->if_snd, m);
	if (m->m_flags & M_MCAST)
		ifp->if_omcasts++;
	if ((ifp->if_flags & IFF_OACTIVE) == 0)
		(*ifp->if_start)(ifp);
	splx(s);
	return (error);

bad:
	if (m)
		m_freem(m);
	return (error);
}

/*
 * Process a received Ethernet packet;
 * the packet is in the mbuf chain m without
 * the ether header, which is provided separately.
 */
void
ether_input(ifp, eh, m)
	struct ifnet *ifp;
	register struct ether_header *eh;
	struct mbuf *m;
{
	register struct ifqueue *inq;
	u_int16_t etype;
	int s, llcfound = 0;
	register struct llc *l;
	struct arpcom *ac = (struct arpcom *)ifp;
#ifdef __ECOS
	unsigned int sched_what;
#endif

	if ((ifp->if_flags & IFF_UP) == 0) {
		m_freem(m);
		return;
	}
	ifp->if_lastchange = time;
	ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
	if (eh->ether_dhost[0] & 1) {
		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++;

#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:
#ifdef __ECOS
		sched_what = NETISR_IP;
#else
		schednetisr(NETISR_IP);
#endif
		inq = &ipintrq;
		break;

	case ETHERTYPE_ARP:
		if (ifp->if_flags & IFF_NOARP)
			goto dropanyway;
#ifdef __ECOS
		sched_what = NETISR_ARP;
#else
		schednetisr(NETISR_ARP);
#endif
		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:
#ifdef __ECOS
		sched_what = NETISR_IPV6;
#else
		schednetisr(NETISR_IPV6);
#endif
		inq = &ip6intrq;
		break;
#endif /* INET6 */
#ifdef IPX
	case ETHERTYPE_IPX:
#ifdef __ECOS
		sched_what = NETISR_IPX;
#else
		schednetisr(NETISR_IPX);
#endif
		inq = &ipxintrq;
		break;
#endif
#ifdef NS
	case ETHERTYPE_NS:
#ifdef __ECOS
		sched_what = NETISR_NS;
#else
		schednetisr(NETISR_NS);
#endif
		inq = &nsintrq;
		break;
#endif
#ifdef NETATALK
	case ETHERTYPE_AT:
#ifdef __ECOS
		sched_what = NETISR_ATALK;
#else
		schednetisr(NETISR_ATALK);
#endif
		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);
#ifdef __ECOS
				sched_what = NETISR_ATALK;
#else
				schednetisr(NETISR_ATALK);
#endif
				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;

⌨️ 快捷键说明

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