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

📄 if_ether.c

📁 vxworks源码源码解读是学习vxworks的最佳途径
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 sockaddr_dl *		sdl= NULL;    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:	    /* call arplookup with create flag */	    /* XXX should proxy flag be added here ??? investigate */	    if ((la = arplookup(soInAddr->sin_addr.s_addr, 1, 0)) == NULL)		return (ENETUNREACH); 	    rt = la->la_rt; 	    sdl = SDL(rt->rt_gateway); 	    bcopy((caddr_t)ar->arp_ha.sa_data, LLADDR(sdl),		  sdl->sdl_alen = sizeof(struct ether_addr)); 	    if (ar->arp_flags & ATF_PERM)		rt->rt_expire = 0; 	    else 		rt->rt_expire = tickGet() + (sysClkRateGet() * arpt_keep);	    rt->rt_flags &= ~RTF_REJECT;	    rt->rt_flags |= RTF_STATIC;	/* manually added route. */	    la->la_asked = 0;	    if (ar->arp_flags & ATF_PUBL)		{		rt->rt_flags |= RTF_ANNOUNCE;		arpwhohas ((struct arpcom *)rt->rt_ifp, &soInAddr->sin_addr); 		}	    break;	case SIOCDARP:		/* delete entry */	    if ((la = arplookup(soInAddr->sin_addr.s_addr, 0, 0)) == NULL)		return (EADDRNOTAVAIL); 	    arptfree(la);	    break;	case SIOCGARP:		/* get entry */	    if ((la = arplookup(soInAddr->sin_addr.s_addr, 0, 0)) == NULL)		return (EADDRNOTAVAIL); 	    rt = la->la_rt; 	    sdl = SDL(rt->rt_gateway); 	    ar->arp_flags = 0; 	/* initialize the flags */	    if (sdl->sdl_alen)		{		bcopy(LLADDR(sdl), (caddr_t)ar->arp_ha.sa_data, sdl->sdl_alen);		ar->arp_flags |= ATF_COM; 		}	    else		return (EADDRNOTAVAIL); 			    if (rt->rt_flags & RTF_UP)		ar->arp_flags |= ATF_INUSE; 	    if (rt->rt_flags & RTF_ANNOUNCE)		ar->arp_flags |= ATF_PUBL; 	    	    if (rt->rt_expire == 0) 		ar->arp_flags |= ATF_PERM;	    break;	default : 	    return (EINVAL); 	}    return (OK);     }/* * Convert Ethernet address to printable (loggable) representation. */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);}#ifdef INCLUDE_REVARP /* XXX currently not supported *//* * Called from 10 Mb/s Ethernet interrupt handlers * when ether packet type ETHERTYPE_REVARP * is received.  Common length and type checks are done here, * then the protocol-specific routine is called. */voidrevarpinput(m)	struct mbuf *m;{	struct arphdr *ar;	int op, s;	if (m->m_len < sizeof(struct arphdr))		goto out;	ar = mtod(m, struct arphdr *);	if (ntohs(ar->ar_hrd) != ARPHRD_ETHER)		goto out;	if (m->m_len < sizeof(struct arphdr) + 2 * (ar->ar_hln + ar->ar_pln))		goto out;	switch (ntohs(ar->ar_pro)) {	case ETHERTYPE_IP:	case ETHERTYPE_IPTRAILERS:		in_revarpinput(m);		return;	default:		break;	}out:	m_freem(m);}/* * RARP for Internet protocols on 10 Mb/s Ethernet. * Algorithm is that given in RFC 903. * We are only using for bootstrap purposes to get an ip address for one of * our interfaces.  Thus we support no user-interface. * * Since the contents of the RARP reply are specific to the interface that * sent the request, this code must ensure that they are properly associated. * * Note: also supports ARP via RARP packets, per the RFC. */in_revarpinput(m)	struct mbuf *m;{	struct ifnet *ifp;	struct ether_arp *ar;	int op, s;	ar = mtod(m, struct ether_arp *);	op = ntohs(ar->arp_op);	switch (op) {	case ARPOP_REQUEST:	case ARPOP_REPLY:	/* per RFC */		in_arpinput(m);		return;	case ARPOP_REVREPLY:		break;	case ARPOP_REVREQUEST:	/* handled by rarpd(8) */	default:		goto out;	}	if (!revarp_in_progress)		goto out;	ifp = m->m_pkthdr.rcvif;	if (ifp != myip_ifp) /* !same interface */		goto out;	if (myip_initialized)		goto wake;	if (bcmp((char *)ar->arp_tha, 		 (char *)((struct arpcom *)ifp)->ac_enaddr,		 sizeof(ar->arp_tha)))		goto out;	bcopy((caddr_t)ar->arp_spa, (caddr_t)&srv_ip, sizeof(srv_ip));	bcopy((caddr_t)ar->arp_tpa, (caddr_t)&myip, sizeof(myip));	myip_initialized = 1;wake:	/* Do wakeup every time in case it was missed. */#if 0 /* XXX to be checked */	wakeup((caddr_t)&myip);#endif /* XXX to be checked */out:	m_freem(m);}/* * Send a RARP request for the ip address of the specified interface. * The request should be RFC 903-compliant. */voidrevarprequest(ifp)	struct ifnet *ifp;{	struct sockaddr sa;	struct mbuf *m;	struct ether_header *eh;	struct ether_arp *ea;	struct arpcom *ac = (struct arpcom *)ifp;	if ((m = mHdrClGet(M_DONTWAIT, MT_DATA, 			   sizeof(*ea), TRUE)) == NULL)	    return; 	m->m_len = sizeof(*ea);	m->m_pkthdr.len = sizeof(*ea);	MH_ALIGN(m, sizeof(*ea));	ea = mtod(m, struct ether_arp *);	eh = (struct ether_header *)sa.sa_data;	bzero((caddr_t)ea, sizeof(*ea));	bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,	    sizeof(eh->ether_dhost));	eh->ether_type = htons(ETHERTYPE_REVARP);	ea->arp_hrd = htons(ARPHRD_ETHER);	ea->arp_pro = htons(ETHERTYPE_IP);	ea->arp_hln = sizeof(ea->arp_sha);	/* hardware address length */	ea->arp_pln = sizeof(ea->arp_spa);	/* protocol address length */	ea->arp_op = htons(ARPOP_REVREQUEST);	bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha,	   sizeof(ea->arp_sha));	bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_tha,	   sizeof(ea->arp_tha));	sa.sa_family = AF_UNSPEC;	sa.sa_len = sizeof(sa);	ifp->if_output(ifp, m, &sa, (struct rtentry *)0);}/* * RARP for the ip address of the specified interface, but also * save the ip address of the server that sent the answer. * Timeout if no response is received. */intrevarpwhoarewe(ifp, serv_in, clnt_in)	struct ifnet *ifp;	struct in_addr *serv_in;	struct in_addr *clnt_in;{	int result, count = 20;		if (myip_initialized) 		return EIO;	myip_ifp = ifp;	revarp_in_progress = 1;	while (count--) {		revarprequest(ifp);				/* one second delay */		taskDelay (sysClkRateGet());#if 0 /* XXX WORKAROUND with TAskDelay provided is it OK??? */		result = tsleep((caddr_t)&myip, PSOCK, "revarp", hz/2);		if (result != EWOULDBLOCK)			break;#endif  /* XXX */	}	revarp_in_progress = 0;	if (!myip_initialized)		return ENETUNREACH;		bcopy((caddr_t)&srv_ip, (char *)serv_in, sizeof(*serv_in));	bcopy((caddr_t)&myip, (char *)clnt_in, sizeof(*clnt_in));	return 0;}/* For compatibility: only saves interface address. */intrevarpwhoami(in, ifp)	struct in_addr *in;	struct ifnet *ifp;{	struct in_addr server;	return (revarpwhoarewe(ifp, &server, in));}#endif /* INCLUDE_REVARP XXX currently not supported */#ifdef	DDB#define db_printf	printfstatic voiddb_print_sa(sa)	struct sockaddr *sa;{	int len;	u_char *p;	if (sa == 0) {		db_printf("[NULL]");		return;	}	p = (u_char*)sa;	len = sa->sa_len;	db_printf("[");	while (len > 0) {		db_printf("%d", *p);		p++; len--;		if (len) db_printf(",");	}	db_printf("]\n");}static voiddb_print_ifa(ifa)	struct ifaddr *ifa;{	if (ifa == 0)		return;	db_printf("  ifa_addr=");	db_print_sa(ifa->ifa_addr);	db_printf("  ifa_dsta=");	db_print_sa(ifa->ifa_dstaddr);	db_printf("  ifa_mask=");	db_print_sa(ifa->ifa_netmask);	db_printf("  flags=0x%x,refcnt=%d,metric=%d\n",			  ifa->ifa_flags,			  ifa->ifa_refcnt,			  ifa->ifa_metric);}static voiddb_print_llinfo(li)	caddr_t li;{	struct llinfo_arp *la;	if (li == 0)		return;	la = (struct llinfo_arp *)li;	db_printf("  la_rt=0x%x la_hold=0x%x, la_asked=0x%x\n",			  la->la_rt, la->la_hold, la->la_asked);}/* * Function to pass to rn_walktree(). * Return non-zero error to abort walk. */static intdb_show_radix_node(rn, w)	struct radix_node *rn;	void *w;{	struct rtentry *rt = (struct rtentry *)rn;	db_printf("rtentry=0x%x", rt);	db_printf(" flags=0x%x refcnt=%d use=%d expire=%d\n",			  rt->rt_flags, rt->rt_refcnt,			  rt->rt_use, rt->rt_expire);	db_printf(" key="); db_print_sa(rt_key(rt));	db_printf(" mask="); db_print_sa(rt_mask(rt));	db_printf(" gw="); db_print_sa(rt->rt_gateway);	db_printf(" ifp=0x%x ", rt->rt_ifp);	if (rt->rt_ifp)		db_printf("(%s%d)",				  rt->rt_ifp->if_name,				  rt->rt_ifp->if_unit);	else		db_printf("(NULL)");	db_printf(" ifa=0x%x\n", rt->rt_ifa);	db_print_ifa(rt->rt_ifa);	db_printf(" genmask="); db_print_sa(rt->rt_genmask);	db_printf(" gwroute=0x%x llinfo=0x%x\n",			  rt->rt_gwroute, rt->rt_llinfo);	db_print_llinfo(rt->rt_llinfo);	return (0);}/* * Function to print all the route trees. * Use this from ddb:  "call db_show_arptab" */db_show_arptab(){	struct radix_node_head *rnh;	rnh = rt_tables[AF_INET];	db_printf("Route tree for AF_INET\n");	if (rnh == NULL) {		db_printf(" (not initialized)\n");		return (0);	}	rn_walktree(rnh, db_show_radix_node, NULL);	return (0);}#endif#endif /* INET */

⌨️ 快捷键说明

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