【转】busybox分析——arp设置ARP缓存表中的mac地址
【转】busybox分析——arp设置ARP缓存表中的mac地址
转自:http://blog.chinaunix.net/uid-26009923-id-5098083.html
1. 将arp缓存表中某一IP的MAC地址修改
cong@msi:/work/test/tcpip/busy/arp$ cat arp.c #include "utils.h" #include <net/if_arp.h> #include <linux/sockios.h> //usage: arp 192.168.4.111 78:6a:89:18:31:0c #define ETH_ALEN 6 int INET_resolve(const char *name, struct sockaddr_in *s_in) { struct hostent *hp; /* Grmpf. -FvK */ s_in->sin_family = AF_INET; s_in->sin_port = 0; /* Look to see if it's a dotted quad. */ if (inet_aton(name, &s_in->sin_addr)) { return 0; } hp = gethostbyname(name); if (hp == NULL) { return -1; } memcpy(&s_in->sin_addr, hp->h_addr_list[0], sizeof(struct in_addr)); return 0; } /* Convert Ethernet address from "XX[:]XX[:]XX[:]XX[:]XX[:]XX" to sockaddr. * Return nonzero on error. */ int in_ether(const char *bufp, struct sockaddr *sap) { char *ptr; int i, j; unsigned char val; unsigned char c; dbmsg(); sap->sa_family = ARPHRD_ETHER; ptr = (char *) sap->sa_data; i = ETH_ALEN; goto first; do { /* We might get a semicolon here */ if (*bufp == ':') bufp++; first: j = val = 0; do { c = *bufp; if (((unsigned char)(c - '0')) <= 9) { c -= '0'; } else if ((unsigned char)((c|0x20) - 'a') <= 5) { c = (unsigned char)((c|0x20) - 'a') + 10; } else { if (j && (c == ':' || c == '\0')) /* One-digit byte: __:X:__ */ break; return -1; } ++bufp; val <<= 4; val += c; j ^= 1; } while (j); *ptr++ = val; } while (--i); /* Error if we aren't at end of string */ return *bufp; } int main ( int argc, char *argv[] ) { struct arpreq req; struct sockaddr sa; int ret; if(argc != 3) { dbmsg("usage: ./arp "); exit(0); } int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if(sockfd < 0) return -1; memset(&req, 0, sizeof(req)); //a. put host IP to arp_p INET_resolve(argv[1], (struct sockaddr_in*)&sa); memcpy(&req.arp_pa, &sa, sizeof(struct sockaddr)); //b. put host MAC to arp_ha in_ether(argv[2], &req.arp_ha); //c. set flag req.arp_flags = ATF_PERM | ATF_COM; //d. invoke ioctl dbmsg("next invoke ioctl"); ret = ioctl(sockfd, SIOCSARP, &req); if(ret < 0) { dbmsg("error %s", strerror(errno)); exit(-1); } return EXIT_SUCCESS; }
3. 执行结果
cong@msi:/work/test/tcpip/busy/arp$ cat /proc/net/arp | grep "192.168.4.111" //查看arp缓存中的192.168.4.111的MAC地址 192.168.4.111 0x1 0x2 78:6a:89:18:31:0b * eth2 -->结尾是0b cong@msi:/work/test/tcpip/busy/arp$ ping 192.168.4.111 //可以ping通的 PING 192.168.4.111 (192.168.4.111) 56(84) bytes of data. 64 bytes from 192.168.4.111: icmp_seq=1 ttl=64 time=93.9 ms cong@msi:/work/test/tcpip/busy/arp$ sudo ./arp 192.168.4.111 78:6a:89:18:31:0c //修改arp缓存中的192.168.4.111的MAC地址 arp.c:in_ether[38]: arp.c:main[101]: next invoke ioctl cong@msi:/work/test/tcpip/busy/arp$ ping 192.168.4.111 //再次ping发现不通了 PING 192.168.4.111 (192.168.4.111) 56(84) bytes of data. From 192.168.4.62: icmp_seq=1 Redirect Network(New nexthop: 192.168.4.62) From 192.168.4.62: icmp_seq=2 Redirect Network(New nexthop: 192.168.4.62) From 192.168.4.62: icmp_seq=3 Redirect Network(New nexthop: 192.168.4.62) cong@msi:/work/test/tcpip/busy/arp$ cat /proc/net/arp | grep "192.168.4.111" //查看arp缓存中的192.168.4.111的MAC地址 192.168.4.111 0x1 0x6 78:6a:89:18:31:0c * eth2 -->将结尾的0b改成了0c