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

📄 if_ether.c

📁 vxworks下的实现网络TCPIP协议的原代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 * desten is filled in.  If there is no entry in arptab, * set one up and broadcast a request for the IP address. * Hold onto this mbuf and resend it once the address * is finally resolved.  A return value of 1 indicates * that desten has been filled in and the packet should be sent * normally; a 0 return indicates that the packet has been * taken over here, either now or for later transmission. */intarpresolve(ac, rt, m, dst, desten)	register struct arpcom *ac;	register struct rtentry *rt;	struct mbuf *m;	register struct sockaddr *dst;	register u_char *desten;{	register struct llinfo_arp *la;	struct sockaddr_dl *sdl;	int alen;                          /* Length of MAC address */	u_long lna;                        /* Host portion if IP address */	if (m != NULL)		/* check if mbuf is not null */	    {	    if (m->m_flags & M_BCAST)		{	/* broadcast */		bcopy((caddr_t)etherbroadcastaddr, (caddr_t)desten,		      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 {		if ((la = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0)))			rt = la->la_rt;	}	if (la == 0 || rt == 0) {		logMsg ("arpresolve: can't allocate llinfo",0,0,0,0,0,0);		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 > tickGet()) &&	    sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) {		bcopy(LLADDR(sdl), (char *)desten, sdl->sdl_alen);		return 1;	}	/* If IFF_NOARP then make LL addr from IP host addr */	 	if (ac->ac_if.if_flags & IFF_NOARP) 	    {	    /* Set expiration of Route/ARP entry */	    if (rt->rt_expire == 0)		{		rt->rt_expire = tickGet ();		}	    /* Set length of MAC address.  Default to Ethernet length. */	    alen = (sdl->sdl_alen > 0 ? sdl->sdl_alen : 		    sizeof (struct ether_addr));	    if (alen < 3)		{		return (0);		}	    bcopy((caddr_t)ac->ac_enaddr, (char *)desten, alen - 3);	    lna = in_lnaof(SIN(dst)->sin_addr);	    desten[alen - 1]     = lna & 0xff;	    desten[alen - 1 - 1] = (lna >> 8) & 0xff;	    desten[alen - 1 - 2] = (lna >> 16) & 0x7f;	    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 (arpRxmitTicks < 0)		    arpRxmitTicks = ARP_RXMIT_TICKS_DFLT;		if (la->la_asked == 0 || 		    (tickGet () - rt->rt_expire >= arpRxmitTicks)) {			rt->rt_expire = tickGet();			if (la->la_asked++ < arp_maxtries)				arpwhohas(ac, &(SIN(dst)->sin_addr));			else {				rt->rt_flags |= RTF_REJECT;				rt->rt_expire += (sysClkRateGet() * arpt_down);				la->la_asked = 0;			}		}	}	return (0);}/* * Common length and type checks are done here, * then the protocol-specific routine is called. */voidarpintr(){	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)        {            if ( m == 0 )                panic("arpintr: m is NULL\n");            if ( (m->m_flags & M_PKTHDR) == 0 )                panic("arpintr: M_PKTHDR is NOT set\n");			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 + ar->ar_pln))			switch (ntohs(ar->ar_pro)) {			case ETHERTYPE_IP:			case ETHERTYPE_IPTRAILERS:#ifdef PROXY_HOOK			        if (proxyArpHook != NULL)				    (* proxyArpHook)					((struct arpcom *)m->m_pkthdr.rcvif,m);#endif				in_arpinput(m);				continue;			}		m_freem(m);	}}/* * 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);	bcopy((caddr_t)ea->arp_spa, (caddr_t)&isaddr, sizeof (isaddr));	bcopy((caddr_t)ea->arp_tpa, (caddr_t)&itaddr, 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)		goto out;	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)))		goto out;	/* it's from me, ignore it. */	if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)etherbroadcastaddr,	    sizeof (ea->arp_sha))) {		logMsg (		    "arp: ether address is broadcast for IP address %x!\n",		    (int)ntohl(isaddr.s_addr), 0,0,0,0,0);		goto out;	}	if (isaddr.s_addr == myaddr.s_addr) {		logMsg(		   "duplicate IP address %08x sent from ethernet address %s\n",		   (int)ntohl(isaddr.s_addr), (int)ether_sprintf(ea->arp_sha),		   0,0,0,0);		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))			logMsg("arp info overwritten for %08x by %s\n",			    (int) ntohl(isaddr.s_addr), 			    (int) ether_sprintf(ea->arp_sha),0,0,0,0);		bcopy((caddr_t)ea->arp_sha, LLADDR(sdl),		    sdl->sdl_alen = sizeof(ea->arp_sha));		if (rt->rt_expire)			rt->rt_expire = tickGet() + (sysClkRateGet() * 						     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) {	out:		m_freem(m);		return;	}	if (itaddr.s_addr == myaddr.s_addr) {		/* I am the target */		bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha,		    sizeof(ea->arp_sha));		bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha,		    sizeof(ea->arp_sha));	} else {		la = arplookup(itaddr.s_addr, 0, SIN_PROXY);		if (la == 0)			goto out;		rt = la->la_rt;		bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha,		    sizeof(ea->arp_sha));		sdl = SDL(rt->rt_gateway);		bcopy(LLADDR(sdl), (caddr_t)ea->arp_sha, sizeof(ea->arp_sha));	}	bcopy((caddr_t)ea->arp_spa, (caddr_t)ea->arp_tpa, sizeof(ea->arp_spa));	bcopy((caddr_t)&itaddr, (caddr_t)ea->arp_spa, 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;	bcopy((caddr_t)ea->arp_tha, (caddr_t)eh->ether_dhost,	    sizeof(eh->ether_dhost));	eh->ether_type = 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. */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 };	sin.sin_addr.s_addr = addr;	sin.sin_other = proxy ? SIN_PROXY : 0;	rt = rtalloc1((struct sockaddr *)&sin, create);	if (rt == 0)		return (0);	rt->rt_refcnt--;	if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 ||	    rt->rt_gateway->sa_family != AF_LINK) {		if (create)			logMsg("arptnew failed on %x\n", (int)ntohl(addr),			0,0,0,0,0);		return (0);	}	return ((struct llinfo_arp *)rt->rt_llinfo);}int arpioctl    (    int 	cmd,    caddr_t	data    )    {    register struct arpreq *		ar = (struct arpreq *)data;    register struct sockaddr_in *	soInAddr;    register struct llinfo_arp *	la = NULL;    register struct rtentry *		rt = NULL;    struct rtentry * 			pNewRt;    struct sockaddr_dl * 		sdl;    struct sockaddr_in 			rtmask;    struct sockaddr_in * 		pMask;    struct sockaddr_inarp 		ipaddr;    struct sockaddr_dl 			arpaddr;    int error = OK;    int flags = 0;    BOOL proxy = FALSE;    BOOL export = FALSE;    if (ar->arp_pa.sa_family != AF_INET ||	ar->arp_ha.sa_family != AF_UNSPEC)	return (EAFNOSUPPORT);    soInAddr = (struct sockaddr_in *)&ar->arp_pa;    switch (cmd) 	{	case SIOCSARP:            if (ar->arp_flags & ATF_PUBL)                {                flags |= RTF_ANNOUNCE;                proxy = TRUE;                }            /* Search for existing entry with same address. */               bzero ( (char *)&ipaddr, sizeof (ipaddr));            ipaddr.sin_len = sizeof (ipaddr);            ipaddr.sin_family = AF_INET;            ipaddr.sin_addr.s_addr = soInAddr->sin_addr.s_addr;            rt = rtalloc1 ((struct sockaddr *)&ipaddr, 0);            if (rt)                {                rt->rt_refcnt--;                if (soInAddr->sin_addr.s_addr ==                        ((struct sockaddr_in *)rt_key (rt))->sin_addr.s_addr)                    {                    /* Matching entry found. Check address type. */                    if ( (rt->rt_flags & RTF_GATEWAY) ||                               (rt->rt_flags & RTF_LLINFO) == 0 ||                                      rt->rt_gateway->sa_family != AF_LINK)                        {                        /* Host entry found: must create proxy entry. */                        if ( !(ar->arp_flags & ATF_PUBL))                            return (EINVAL);                        /*                          * Set flag to prevent replacement of current entry                          * by creating entry which includes SIN_PROXY flag.                         */                        export = TRUE;                        }                    }                }            /*             * Search completed. Get the interface type and index value             * from the parent route.             */            if (rt)                {                /*                 * For remote hosts or networks, the gateway's associated                 * route entry contains the interface values.                 */                if (rt->rt_flags & RTF_GATEWAY)                    {                    if (rt->rt_gwroute == 0)                        return (EHOSTUNREACH);                    else

⌨️ 快捷键说明

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