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

📄 if_ether.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
	register u_char *desten;	struct rtentry *rt0;{	register struct llinfo_arp *la;	struct sockaddr_dl *sdl;	if (m->m_flags & M_BCAST) {	/* broadcast */		(void)memcpy(desten, etherbroadcastaddr, sizeof(etherbroadcastaddr));		return (1);	}	if (m->m_flags & M_MCAST) {	/* multicast */		ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten);		return(1);	}	if (rt)		la = (struct llinfo_arp *)rt->rt_llinfo;	else {		la = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0);		if (la)			rt = la->la_rt;	}	if (la == 0 || rt == 0) {		log(LOG_DEBUG, "arpresolve: can't allocate llinfo for %s\n",			inet_ntoa(SIN(dst)->sin_addr));		m_freem(m);		return (0);	}	sdl = SDL(rt->rt_gateway);	/*	 * Check the address family and length is valid, the address	 * is resolved; otherwise, try to resolve.	 */	if ((rt->rt_expire == 0 || rt->rt_expire > rtems_bsdnet_seconds_since_boot()) &&	    sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) {		bcopy(LLADDR(sdl), desten, sdl->sdl_alen);		return 1;	}	/*	 * There is an arptab entry, but no ethernet address	 * response yet.  Replace the held mbuf with this	 * latest one.	 */	if (la->la_hold)		m_freem(la->la_hold);	la->la_hold = m;	if (rt->rt_expire) {		rt->rt_flags &= ~RTF_REJECT;		if (la->la_asked == 0 || rt->rt_expire != rtems_bsdnet_seconds_since_boot()) {			rt->rt_expire = rtems_bsdnet_seconds_since_boot();			if (la->la_asked++ < arp_maxtries)			    arprequest(ac,			        &(SIN(rt->rt_ifa->ifa_addr)->sin_addr.s_addr),				&(SIN(dst)->sin_addr.s_addr),				ac->ac_enaddr);			else {				rt->rt_flags |= RTF_REJECT;				rt->rt_expire += arpt_down;				la->la_asked = 0;			}		}	}	return (0);}/* * Common length and type checks are done here, * then the protocol-specific routine is called. */voidarpintr(void){	register struct mbuf *m;	register struct arphdr *ar;	int s;	while (arpintrq.ifq_head) {		s = splimp();		IF_DEQUEUE(&arpintrq, m);		splx(s);		if (m == 0 || (m->m_flags & M_PKTHDR) == 0)			panic("arpintr");		if (m->m_len >= sizeof(struct arphdr) &&		    (ar = mtod(m, struct arphdr *)) &&		    ntohs(ar->ar_hrd) == ARPHRD_ETHER &&		    m->m_len >=		      sizeof(struct arphdr) + 2 * ar->ar_hln + 2 * ar->ar_pln)			    switch (ntohs(ar->ar_pro)) {			    case ETHERTYPE_IP:				    in_arpinput(m);				    continue;			    }		m_freem(m);	}}NETISR_SET(NETISR_ARP, arpintr);/* * ARP for Internet protocols on 10 Mb/s Ethernet. * Algorithm is that given in RFC 826. * In addition, a sanity check is performed on the sender * protocol address, to catch impersonators. * We no longer handle negotiations for use of trailer protocol: * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent * along with IP replies if we wanted trailers sent to us, * and also sent them in response to IP replies. * This allowed either end to announce the desire to receive * trailer packets. * We no longer reply to requests for ETHERTYPE_TRAIL protocol either, * but formerly didn't normally send requests. */static voidin_arpinput(m)	struct mbuf *m;{	register struct ether_arp *ea;	register struct arpcom *ac = (struct arpcom *)m->m_pkthdr.rcvif;	struct ether_header *eh;	register struct llinfo_arp *la = 0;	register struct rtentry *rt;	struct in_ifaddr *ia, *maybe_ia = 0;	struct sockaddr_dl *sdl;	struct sockaddr sa;	struct in_addr isaddr, itaddr, myaddr;	int op;	ea = mtod(m, struct ether_arp *);	op = ntohs(ea->arp_op);	(void)memcpy(&isaddr, ea->arp_spa, sizeof (isaddr));	(void)memcpy(&itaddr, ea->arp_tpa, sizeof (itaddr));	for (ia = in_ifaddr; ia; ia = ia->ia_next)		if (ia->ia_ifp == &ac->ac_if) {			maybe_ia = ia;			if ((itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) ||			     (isaddr.s_addr == ia->ia_addr.sin_addr.s_addr))				break;		}	if (maybe_ia == 0) {		m_freem(m);		return;	}	myaddr = ia ? ia->ia_addr.sin_addr : maybe_ia->ia_addr.sin_addr;	if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr,	    sizeof (ea->arp_sha))) {		m_freem(m);	/* it's from me, ignore it. */		return;	}	if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)etherbroadcastaddr,	    sizeof (ea->arp_sha))) {		log(LOG_ERR,		    "arp: ether address is broadcast for IP address %s!\n",		    inet_ntoa(isaddr));		m_freem(m);		return;	}	if (isaddr.s_addr == myaddr.s_addr) {		log(LOG_ERR,		   "arp: %6D is using my IP address %s!\n",		   ea->arp_sha, ":", inet_ntoa(isaddr));		itaddr = myaddr;		goto reply;	}	la = arplookup(isaddr.s_addr, itaddr.s_addr == myaddr.s_addr, 0);	if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) {		if (sdl->sdl_alen &&		    bcmp((caddr_t)ea->arp_sha, LLADDR(sdl), sdl->sdl_alen))			log(LOG_INFO, "arp: %s moved from %6D to %6D\n",			    inet_ntoa(isaddr), (u_char *)LLADDR(sdl), ":",			    ea->arp_sha, ":");		(void)memcpy(LLADDR(sdl), ea->arp_sha, sizeof(ea->arp_sha));		sdl->sdl_alen = sizeof(ea->arp_sha);		if (rt->rt_expire)			rt->rt_expire = rtems_bsdnet_seconds_since_boot() + arpt_keep;		rt->rt_flags &= ~RTF_REJECT;		la->la_asked = 0;		if (la->la_hold) {			(*ac->ac_if.if_output)(&ac->ac_if, la->la_hold,				rt_key(rt), rt);			la->la_hold = 0;		}	}reply:	if (op != ARPOP_REQUEST) {		m_freem(m);		return;	}	if (itaddr.s_addr == myaddr.s_addr) {		/* I am the target */		(void)memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha));		(void)memcpy(ea->arp_sha, ac->ac_enaddr, sizeof(ea->arp_sha));	} else {		la = arplookup(itaddr.s_addr, 0, SIN_PROXY);		if (la == NULL) {			struct sockaddr_in sin;			if (!arp_proxyall) {				m_freem(m);				return;			}			bzero(&sin, sizeof sin);			sin.sin_family = AF_INET;			sin.sin_len = sizeof sin;			sin.sin_addr = itaddr;			rt = rtalloc1((struct sockaddr *)&sin, 0, 0UL);			if (!rt) {				m_freem(m);				return;			}			/*			 * Don't send proxies for nodes on the same interface			 * as this one came out of, or we'll get into a fight			 * over who claims what Ether address.			 */			if (rt->rt_ifp == &ac->ac_if) {				rtfree(rt);				m_freem(m);				return;			}			(void)memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha));			(void)memcpy(ea->arp_sha, ac->ac_enaddr, sizeof(ea->arp_sha));			rtfree(rt);#ifdef DEBUG_PROXY			printf("arp: proxying for %s\n",			       inet_ntoa(itaddr));#endif		} else {			rt = la->la_rt;			(void)memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha));			sdl = SDL(rt->rt_gateway);			(void)memcpy(ea->arp_sha, LLADDR(sdl), sizeof(ea->arp_sha));		}	}	(void)memcpy(ea->arp_tpa, ea->arp_spa, sizeof(ea->arp_spa));	(void)memcpy(ea->arp_spa, &itaddr, sizeof(ea->arp_spa));	ea->arp_op = htons(ARPOP_REPLY);	ea->arp_pro = htons(ETHERTYPE_IP); /* let's be sure! */	eh = (struct ether_header *)sa.sa_data;	(void)memcpy(eh->ether_dhost, ea->arp_tha, sizeof(eh->ether_dhost));	eh->ether_type = htons(ETHERTYPE_ARP);	sa.sa_family = AF_UNSPEC;	sa.sa_len = sizeof(sa);	(*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0);	return;}/* * Free an arp entry. */static voidarptfree(la)	register struct llinfo_arp *la;{	register struct rtentry *rt = la->la_rt;	register struct sockaddr_dl *sdl;	if (rt == 0)		panic("arptfree");	if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) &&	    sdl->sdl_family == AF_LINK) {		sdl->sdl_alen = 0;		la->la_asked = 0;		rt->rt_flags &= ~RTF_REJECT;		return;	}	rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, rt_mask(rt),			0, (struct rtentry **)0);}/* * Lookup or enter a new address in arptab. */static struct llinfo_arp *arplookup(addr, create, proxy)	u_long addr;	int create, proxy;{	register struct rtentry *rt;	static struct sockaddr_inarp sin = {sizeof(sin), AF_INET };	const char *why = 0;	sin.sin_addr.s_addr = addr;	sin.sin_other = proxy ? SIN_PROXY : 0;	rt = rtalloc1((struct sockaddr *)&sin, create, 0UL);	if (rt == 0)		return (0);	rt->rt_refcnt--;	if (rt->rt_flags & RTF_GATEWAY)		why = "host is not on local network";	else if ((rt->rt_flags & RTF_LLINFO) == 0)		why = "could not allocate llinfo";	else if (rt->rt_gateway->sa_family != AF_LINK)		why = "gateway route is not ours";	if (why && create) {		log(LOG_DEBUG, "arplookup %s failed: %s\n",		    inet_ntoa(sin.sin_addr), why);		return 0;	} else if (why) {		return 0;	}	return ((struct llinfo_arp *)rt->rt_llinfo);}voidarp_ifinit(ac, ifa)	struct arpcom *ac;	struct ifaddr *ifa;{	if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY)		arprequest(ac, &(IA_SIN(ifa)->sin_addr.s_addr),			       &(IA_SIN(ifa)->sin_addr.s_addr), ac->ac_enaddr);	ifa->ifa_rtrequest = arp_rtrequest;	ifa->ifa_flags |= RTF_CLONING;}

⌨️ 快捷键说明

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