ARP请求和使用C套接字编程回复

我试图在Linux(Ubuntu)中使用c编程接收和发送ARP数据包
我的程序工作正常(即运行没有任何错误),但我不能使用Wireshark跟踪数据包。

源代码

#include <sys/socket.h> #include <sys/ioctl.h> #include <sys/time.h> #include <asm/types.h> #include <math.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <linux/if_packet.h> #include <linux/if_ether.h> #include <linux/if_arp.h> #define BUF_SIZE 42 #define DEVICE "eth0" #define ETH_P_NULL 0x0 #define ETH_MAC_LEN ETH_ALEN #define ETH_ARP 0x0806 int s = 0; /*Socketdescriptor*/ void* buffer = NULL; long total_packets = 0; long answered_packets = 0; void sigint(int signum); struct __attribute__((packed)) arp_header { unsigned short arp_hd; unsigned short arp_pr; unsigned char arp_hdl; unsigned char arp_prl; unsigned short arp_op; unsigned char arp_sha[6]; unsigned char arp_spa[4]; unsigned char arp_dha[6]; unsigned char arp_dpa[4]; }; int main(void) { buffer = (void*)malloc(BUF_SIZE); /*Buffer for Ethernet Frame*/ unsigned char* etherhead = buffer; /*Pointer to Ethenet Header*/ struct ethhdr *eh = (struct ethhdr *)etherhead; /*Another pointer to ethernet header*/ unsigned char* arphead = buffer + 14; struct arp_header *ah; unsigned char src_mac[6]; /*our MAC address*/ struct ifreq ifr; struct sockaddr_ll socket_address; int ifindex = 0; /*Ethernet Interface index*/ int i; int length; /*length of received packet*/ int sent; printf("Server started, entering initialiation phase...\n"); /*open socket*/ s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (s == -1) { perror("socket():"); exit(1); } printf("Successfully opened socket: %i\n", s); /*retrieve ethernet interface index*/ strncpy(ifr.ifr_name, DEVICE, IFNAMSIZ); if (ioctl(s, SIOCGIFINDEX, &ifr) == -1) { perror("SIOCGIFINDEX"); exit(1); } ifindex = ifr.ifr_ifindex; printf("Successfully got interface index: %i\n", ifindex); /*retrieve corresponding MAC*/ if (ioctl(s, SIOCGIFHWADDR, &ifr) == -1) { perror("SIOCGIFINDEX"); exit(1); } for (i = 0; i < 6; i++) { src_mac[i] = ifr.ifr_hwaddr.sa_data[i]; } printf("Successfully got our MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", src_mac[0],src_mac[1],src_mac[2],src_mac[3],src_mac[4],src_mac[5]); /*prepare sockaddr_ll*/ socket_address.sll_family = PF_PACKET; socket_address.sll_protocol = htons(ETH_P_IP); socket_address.sll_ifindex = ifindex; socket_address.sll_hatype = ARPHRD_ETHER; socket_address.sll_pkttype = PACKET_OTHERHOST; socket_address.sll_halen = 0; socket_address.sll_addr[6] = 0x00; socket_address.sll_addr[7] = 0x00; /*establish signal handler*/ signal(SIGINT, sigint); printf("Successfully established signal handler for SIGINT\n"); printf("We are in production state, waiting for incoming packets....\n"); while (1) { /*Wait for incoming packet...*/ length = recvfrom(s, buffer, BUF_SIZE, 0, NULL, NULL); if (length == -1) { perror("recvfrom():"); exit(1); } if(htons(eh->h_proto) == 0x806) { unsigned char buf_arp_dha[6]; unsigned char buf_arp_dpa[4]; ah = (struct arp_header *)arphead; if(htons(ah->arp_op) != 0x0001) continue; printf("buffer is---------------- %s \n",(char*)ah); printf("H/D TYPE : %x PROTO TYPE : %x \n",ah->arp_hd,ah->arp_pr); printf("H/D leng : %x PROTO leng : %x \n",ah->arp_hdl,ah->arp_prl); printf("OPERATION : %x \n", ah->arp_op); printf("SENDER MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", ah->arp_sha[0], ah->arp_sha[1], ah->arp_sha[2], ah->arp_sha[3], ah->arp_sha[4], ah->arp_sha[5] ); printf("SENDER IP address: %02d:%02d:%02d:%02d\n", ah->arp_spa[0], ah->arp_spa[1], ah->arp_spa[2], ah->arp_spa[3] ); if(ah->arp_spa[0]==10&&ah->arp_spa[1]==00&&ah->arp_spa[2]==00&&ah->arp_spa[3]==01) { printf("Sender ip is .............bam bam..........................................\n"); system("sudo arp -s 10.0.0.1 00:1e:73:91:04:0d"); } printf("TARGET MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", ah->arp_dha[0], ah->arp_dha[1], ah->arp_dha[2], ah->arp_dha[3], ah->arp_dha[4], ah->arp_dha[5] ); printf("TARGET IP address: %02d:%02d:%02d:%02d\n", ah->arp_dpa[0], ah->arp_dpa[1], ah->arp_dpa[2], ah->arp_dpa[3] ); printf("+++++++++++++++++++++++++++++++++++++++\n" ); printf("ETHER DST MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", eh->h_dest[0], eh->h_dest[1], eh->h_dest[2], eh->h_dest[3], eh->h_dest[4], eh->h_dest[5] ); printf("ETHER SRC MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", eh->h_source[0], eh->h_source[1], eh->h_source[2], eh->h_source[3], eh->h_source[4], eh->h_source[5] ); memcpy( (void*)etherhead, (const void*)(etherhead+ETH_MAC_LEN), ETH_MAC_LEN); memcpy( (void*)(etherhead+ETH_MAC_LEN), (const void*)src_mac, ETH_MAC_LEN); eh->h_proto = ETH_ARP; printf("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& \n"); printf("ETHER DST MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", eh->h_dest[0], eh->h_dest[1], eh->h_dest[2], eh->h_dest[3], eh->h_dest[4], eh->h_dest[5] ); printf("ETHER SRC MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", eh->h_source[0], eh->h_source[1], eh->h_source[2], eh->h_source[3], eh->h_source[4], eh->h_source[5] ); ah->arp_hd = ntohs(ah->arp_hd); ah->arp_pr = ntohs(ah->arp_pr); ah->arp_op = 0x0002; buf_arp_dpa[0] = ah->arp_dpa[0]; buf_arp_dpa[1] = ah->arp_dpa[1]; buf_arp_dpa[2] = ah->arp_dpa[2]; buf_arp_dpa[3] = ah->arp_dpa[3]; ah->arp_dha[0] = ah->arp_sha[0]; ah->arp_dha[1] = ah->arp_sha[1]; ah->arp_dha[2] = ah->arp_sha[2]; ah->arp_dha[3] = ah->arp_sha[3]; ah->arp_dha[4] = ah->arp_sha[4]; ah->arp_dha[5] = ah->arp_sha[5]; ah->arp_dpa[0] = ah->arp_spa[0]; ah->arp_dpa[1] = ah->arp_spa[1]; ah->arp_dpa[2] = ah->arp_spa[2]; ah->arp_dpa[3] = ah->arp_spa[3]; ah->arp_spa[0] = buf_arp_dpa[0]; ah->arp_spa[1] = buf_arp_dpa[1]; ah->arp_spa[2] = buf_arp_dpa[2]; ah->arp_spa[3] = buf_arp_dpa[3]; //change the sender mac address ah->arp_sha[0] = 0x00; ah->arp_sha[1] = 0x1e; ah->arp_sha[2] = 0x73; ah->arp_sha[3] = 0x78; ah->arp_sha[4] = 0x9a; ah->arp_sha[5] = 0x0d; socket_address.sll_addr[0] = eh->h_dest[0]; socket_address.sll_addr[1] = eh->h_dest[1]; socket_address.sll_addr[2] = eh->h_dest[2]; socket_address.sll_addr[3] = eh->h_dest[3]; socket_address.sll_addr[4] = eh->h_dest[4]; socket_address.sll_addr[5] = eh->h_dest[5]; printf("=======================================\n" ); printf("SENDER MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", ah->arp_sha[0], ah->arp_sha[1], ah->arp_sha[2], ah->arp_sha[3], ah->arp_sha[4], ah->arp_sha[5] ); printf("SENDER IP address: %02d:%02d:%02d:%02d\n", ah->arp_spa[0], ah->arp_spa[1], ah->arp_spa[2], ah->arp_spa[3] ); if((ah->arp_spa[0]==10 && ah->arp_spa[1]==0 && ah->arp_spa[2]==0 && ah->arp_spa[3]==1)) printf("------------------------------------------10.0.0.1-----------------------------------------\n"); printf("TARGET MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", ah->arp_dha[0], ah->arp_dha[1], ah->arp_dha[2], ah->arp_dha[3], ah->arp_dha[4], ah->arp_dha[5] ); printf("TARGET IP address: %02d:%02d:%02d:%02d\n", ah->arp_dpa[0], ah->arp_dpa[1], ah->arp_dpa[2], ah->arp_dpa[3] ); printf("H/D TYPE : %x PROTO TYPE : %x \n",ah->arp_hd,ah->arp_pr); printf("H/D leng : %x PROTO leng : %x \n",ah->arp_hdl,ah->arp_prl); printf("OPERATION : %x \n", ah->arp_op); sent = sendto(s, buffer, BUF_SIZE, 0, (struct sockaddr*)&socket_address, sizeof(socket_address)); if (sent == -1) { perror("sendto():"); exit(1); } answered_packets++; } total_packets++; } } void sigint(int signum) { /*Clean up.......*/ struct ifreq ifr; if (s == -1) return; strncpy(ifr.ifr_name, DEVICE, IFNAMSIZ); ioctl(s, SIOCGIFFLAGS, &ifr); ifr.ifr_flags &= ~IFF_PROMISC; ioctl(s, SIOCSIFFLAGS, &ifr); close(s); free(buffer); printf("Server terminating....\n"); printf("Totally received: %ld packets\n", total_packets); printf("Answered %ld packets\n", answered_packets); exit(0); } 

Solutions Collecting From Web of "ARP请求和使用C套接字编程回复"

一些东西让你的数据包在电线/空气。

  • arp答复的正确.sll_protocol是ETH_P_ARP,来自<linux/if_ether.h>
  • 当设置ah-> arp_op时,在字节序中出现错误。 这是一个2字节的网络字节序字段,所以使用htons()。

  • 一般来说,代码对于网络和主机字节顺序有点困惑。 它目前发出的这个回复非常糟糕,但我不清楚这是代码的恶意,还是意外。 如果您想要发送真实的,正确的IP地址,请在构建回复时使用htonl和htons。

要确定排序:

  • 正确包含<arpa/inet.h>
  • 总是使用htons(),htonl(),ntohs()和ntohl()。 如果在您的平台上不需要它们,它们的实现将使其成为NOP。
  • 当设置从主机发出的数据时,总是用hton *()
  • 在解释来自网络的数据时,总是在ntoh *()之前比较局部变量。

总之,我做的改变是1).sll_protocol = htons(ETH_P_ARP)。 (发送数据的时候)2)ah-> arp_op = htons(ARPOP_REPLY)(在回复arp里)3)删除ah-> arp_hd和ah-> arp_pr上的荒谬的ntohs()。 你不想在填充发送缓冲区时将数据转换为主机字节序(除非你确实真的这样做)4)在一些比较中添加了ntohs()转换和适当的定义5)一些其他的小修复6) ( “须藤…”)!

完整的代码在pastebin 。 这是一个差异:

 thuovila@glx:~/src/so/arp$ diff arp2.c arp_orig.c 13d12 < #include <arpa/inet.h> 20c19 < #define DEVICE "eth1" --- > #define DEVICE "eth0" 25c24 < int s = -1; /*Socketdescriptor*/ --- > int s = 0; /*Socketdescriptor*/ 92c91 < socket_address.sll_protocol = htons(ETH_P_ARP); --- > socket_address.sll_protocol = htons(ETH_P_IP); 95c94 < socket_address.sll_pkttype = 0; //PACKET_OTHERHOST; --- > socket_address.sll_pkttype = PACKET_OTHERHOST; 112c111 < if(ntohs(eh->h_proto) == ETH_P_ARP) --- > if(htons(eh->h_proto) == 0x806) 119c118 < if(ntohs(ah->arp_op) != ARPOP_REQUEST) --- > if(htons(ah->arp_op) != 0x0001) 139d137 < #if 0 145d142 < #endif 182c179 < eh->h_proto = htons(ETH_P_ARP); --- > eh->h_proto = ETH_ARP; 200,201c197,198 < //ah->arp_hd = ntohs(ah->arp_hd); < //ah->arp_pr = ntohs(ah->arp_pr); --- > ah->arp_hd = ntohs(ah->arp_hd); > ah->arp_pr = ntohs(ah->arp_pr); 203c200 < ah->arp_op = htons(ARPOP_REPLY); --- > ah->arp_op = 0x0002; 

编辑一些wireshark建议。 捕获ether proto 0x0806 (简称arp )。 使用捕获任何数据包的伪设备。 你的数据包应该可见。

在linux上,如果你想阻止网络堆栈干扰,使用:echo“8”> / proc / sys / net / ipv4 / conf / all / arp_ignore

编辑#2我不完全确定ETH_P_ARP。 对我而言,这可能是一个简单的判断。 使用ETH_P_IP在ARP头字段是正确的,但我不知道哪一个用于数据包套接字sll_protocol。 另请注意, socket_address.sll_pkttype = PACKET_OTHERHOST; 发送时没有效果(见man 7包)。 也是强制性的SO观察,你应该总是至少使用-Wall(当使用gcc或clang)作为编译标志。

编辑#3我改变了一点点的程序。 并相应地更新了答案和差异。 令人惊讶的是,确实看来,.sll_protocol需要是ETH_P_ARP。 我的男人7包的副本甚至不说它用于任何东西,但数据包不会出现在电线上作为ARP没有它。

我拿了user6343961的代码,做了一些清理和拼接,并实现了自动获取接口IP地址的支持。 此外,参数来自CLI而不是硬编码。 bind()也被用来从我们想要的接口获取ARP。 玩的开心。 这段代码适用于我。

 #include <sys/socket.h> #include <sys/ioctl.h> #include <asm/types.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <linux/if_packet.h> #include <linux/if_ether.h> #include <linux/if_arp.h> #include <arpa/inet.h> //htons etc #define PROTO_ARP 0x0806 #define ETH2_HEADER_LEN 14 #define HW_TYPE 1 #define MAC_LENGTH 6 #define IPV4_LENGTH 4 #define ARP_REQUEST 0x01 #define ARP_REPLY 0x02 #define BUF_SIZE 60 #define debug(x...) printf(x);printf("\n"); #define info(x...) printf(x);printf("\n"); #define warn(x...) printf(x);printf("\n"); #define err(x...) printf(x);printf("\n"); struct arp_header { unsigned short hardware_type; unsigned short protocol_type; unsigned char hardware_len; unsigned char protocol_len; unsigned short opcode; unsigned char sender_mac[MAC_LENGTH]; unsigned char sender_ip[IPV4_LENGTH]; unsigned char target_mac[MAC_LENGTH]; unsigned char target_ip[IPV4_LENGTH]; }; /* * Converts struct sockaddr with an IPv4 address to network byte order uin32_t. * Returns 0 on success. */ int int_ip4(struct sockaddr *addr, uint32_t *ip) { if (addr->sa_family == AF_INET) { struct sockaddr_in *i = (struct sockaddr_in *) addr; *ip = i->sin_addr.s_addr; return 0; } else { err("Not AF_INET"); return 1; } } /* * Formats sockaddr containing IPv4 address as human readable string. * Returns 0 on success. */ int format_ip4(struct sockaddr *addr, char *out) { if (addr->sa_family == AF_INET) { struct sockaddr_in *i = (struct sockaddr_in *) addr; const char *ip = inet_ntoa(i->sin_addr); if (!ip) { return -2; } else { strcpy(out, ip); return 0; } } else { return -1; } } /* * Writes interface IPv4 address as network byte order to ip. * Returns 0 on success. */ int get_if_ip4(int fd, const char *ifname, uint32_t *ip) { int err = -1; struct ifreq ifr; memset(&ifr, 0, sizeof(struct ifreq)); if (strlen(ifname) > (IFNAMSIZ - 1)) { err("Too long interface name"); goto out; } strcpy(ifr.ifr_name, ifname); if (ioctl(fd, SIOCGIFADDR, &ifr) == -1) { perror("SIOCGIFADDR"); goto out; } if (int_ip4(&ifr.ifr_addr, ip)) { goto out; } err = 0; out: return err; } /* * Sends an ARP who-has request to dst_ip * on interface ifindex, using source mac src_mac and source ip src_ip. */ int send_arp(int fd, int ifindex, const unsigned char *src_mac, uint32_t src_ip, uint32_t dst_ip) { int err = -1; unsigned char buffer[BUF_SIZE]; memset(buffer, 0, sizeof(buffer)); struct sockaddr_ll socket_address; socket_address.sll_family = AF_PACKET; socket_address.sll_protocol = htons(ETH_P_ARP); socket_address.sll_ifindex = ifindex; socket_address.sll_hatype = htons(ARPHRD_ETHER); socket_address.sll_pkttype = (PACKET_BROADCAST); socket_address.sll_halen = MAC_LENGTH; socket_address.sll_addr[6] = 0x00; socket_address.sll_addr[7] = 0x00; struct ethhdr *send_req = (struct ethhdr *) buffer; struct arp_header *arp_req = (struct arp_header *) (buffer + ETH2_HEADER_LEN); int index; ssize_t ret, length = 0; //Broadcast memset(send_req->h_dest, 0xff, MAC_LENGTH); //Target MAC zero memset(arp_req->target_mac, 0x00, MAC_LENGTH); //Set source mac to our MAC address memcpy(send_req->h_source, src_mac, MAC_LENGTH); memcpy(arp_req->sender_mac, src_mac, MAC_LENGTH); memcpy(socket_address.sll_addr, src_mac, MAC_LENGTH); /* Setting protocol of the packet */ send_req->h_proto = htons(ETH_P_ARP); /* Creating ARP request */ arp_req->hardware_type = htons(HW_TYPE); arp_req->protocol_type = htons(ETH_P_IP); arp_req->hardware_len = MAC_LENGTH; arp_req->protocol_len = IPV4_LENGTH; arp_req->opcode = htons(ARP_REQUEST); debug("Copy IP address to arp_req"); memcpy(arp_req->sender_ip, &src_ip, sizeof(uint32_t)); memcpy(arp_req->target_ip, &dst_ip, sizeof(uint32_t)); ret = sendto(fd, buffer, 42, 0, (struct sockaddr *) &socket_address, sizeof(socket_address)); if (ret == -1) { perror("sendto():"); goto out; } err = 0; out: return err; } /* * Gets interface information by name: * IPv4 * MAC * ifindex */ int get_if_info(const char *ifname, uint32_t *ip, char *mac, int *ifindex) { debug("get_if_info for %s", ifname); int err = -1; struct ifreq ifr; int sd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (sd <= 0) { perror("socket()"); goto out; } if (strlen(ifname) > (IFNAMSIZ - 1)) { printf("Too long interface name, MAX=%i\n", IFNAMSIZ - 1); goto out; } strcpy(ifr.ifr_name, ifname); //Get interface index using name if (ioctl(sd, SIOCGIFINDEX, &ifr) == -1) { perror("SIOCGIFINDEX"); goto out; } *ifindex = ifr.ifr_ifindex; printf("interface index is %d\n", *ifindex); //Get MAC address of the interface if (ioctl(sd, SIOCGIFHWADDR, &ifr) == -1) { perror("SIOCGIFINDEX"); goto out; } //Copy mac address to output memcpy(mac, ifr.ifr_hwaddr.sa_data, MAC_LENGTH); if (get_if_ip4(sd, ifname, ip)) { goto out; } debug("get_if_info OK"); err = 0; out: if (sd > 0) { debug("Clean up temporary socket"); close(sd); } return err; } /* * Creates a raw socket that listens for ARP traffic on specific ifindex. * Writes out the socket's FD. * Return 0 on success. */ int bind_arp(int ifindex, int *fd) { debug("bind_arp: ifindex=%i", ifindex); int ret = -1; // Submit request for a raw socket descriptor. *fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (*fd < 1) { perror("socket()"); goto out; } debug("Binding to ifindex %i", ifindex); struct sockaddr_ll sll; memset(&sll, 0, sizeof(struct sockaddr_ll)); sll.sll_family = AF_PACKET; sll.sll_ifindex = ifindex; if (bind(*fd, (struct sockaddr*) &sll, sizeof(struct sockaddr_ll)) < 0) { perror("bind"); goto out; } ret = 0; out: if (ret && *fd > 0) { debug("Cleanup socket"); close(*fd); } return ret; } /* * Reads a single ARP reply from fd. * Return 0 on success. */ int read_arp(int fd) { debug("read_arp"); int ret = -1; unsigned char buffer[BUF_SIZE]; ssize_t length = recvfrom(fd, buffer, BUF_SIZE, 0, NULL, NULL); int index; if (length == -1) { perror("recvfrom()"); goto out; } struct ethhdr *rcv_resp = (struct ethhdr *) buffer; struct arp_header *arp_resp = (struct arp_header *) (buffer + ETH2_HEADER_LEN); if (ntohs(rcv_resp->h_proto) != PROTO_ARP) { debug("Not an ARP packet"); goto out; } if (ntohs(arp_resp->opcode) != ARP_REPLY) { debug("Not an ARP reply"); goto out; } debug("received ARP len=%ld", length); struct in_addr sender_a; memset(&sender_a, 0, sizeof(struct in_addr)); memcpy(&sender_a.s_addr, arp_resp->sender_ip, sizeof(uint32_t)); debug("Sender IP: %s", inet_ntoa(sender_a)); debug("Sender MAC: %02X:%02X:%02X:%02X:%02X:%02X", arp_resp->sender_mac[0], arp_resp->sender_mac[1], arp_resp->sender_mac[2], arp_resp->sender_mac[3], arp_resp->sender_mac[4], arp_resp->sender_mac[5]); ret = 0; out: return ret; } /* * * Sample code that sends an ARP who-has request on * interface <ifname> to IPv4 address <ip>. * Returns 0 on success. */ int test_arping(const char *ifname, const char *ip) { int ret = -1; uint32_t dst = inet_addr(ip); if (dst == 0 || dst == 0xffffffff) { printf("Invalid source IP\n"); return 1; } int src; int ifindex; char mac[MAC_LENGTH]; if (get_if_info(ifname, &src, mac, &ifindex)) { err("get_if_info failed, interface %s not found or no IP set?", ifname); goto out; } int arp_fd; if (bind_arp(ifindex, &arp_fd)) { err("Failed to bind_arp()"); goto out; } if (send_arp(arp_fd, ifindex, mac, src, dst)) { err("Failed to send_arp"); goto out; } while(1) { int r = read_arp(arp_fd); if (r == 0) { info("Got reply, break out"); break; } } ret = 0; out: if (arp_fd) { close(arp_fd); arp_fd = 0; } return ret; } int main(int argc, const char **argv) { int ret = -1; if (argc != 3) { printf("Usage: %s <INTERFACE> <DEST_IP>\n", argv[0]); return 1; } const char *ifname = argv[1]; const char *ip = argv[2]; return test_arping(ifname, ip); } 

我知道这是一个很老的帖子。 这段代码帮了我很多。 我修改了代码发送一个ARP请求到一个IP,并从答复中提取MAC地址。 请在下面找到我的代码

 #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/time.h> #include <asm/types.h> #include <math.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <linux/if_packet.h> #include <linux/if_ether.h> #include <linux/if_arp.h> #define PROTO_ARP 0x0806 #define ETH2_HEADER_LEN 14 #define HW_TYPE 1 #define PROTOCOL_TYPE 0x800 #define MAC_LENGTH 6 #define IPV4_LENGTH 4 #define ARP_REQUEST 0x01 #define ARP_REPLY 0x02 #define BUF_SIZE 60 struct arp_header { unsigned short hardware_type; unsigned short protocol_type; unsigned char hardware_len; unsigned char protocol_len; unsigned short opcode; unsigned char sender_mac[MAC_LENGTH]; unsigned char sender_ip[IPV4_LENGTH]; unsigned char target_mac[MAC_LENGTH]; unsigned char target_ip[IPV4_LENGTH]; }; int main() { int sd; unsigned char buffer[BUF_SIZE]; unsigned char source_ip[4] = {10,222,190,160}; unsigned char target_ip[4] = {10,222,190,139}; struct ifreq ifr; struct ethhdr *send_req = (struct ethhdr *)buffer; struct ethhdr *rcv_resp= (struct ethhdr *)buffer; struct arp_header *arp_req = (struct arp_header *)(buffer+ETH2_HEADER_LEN); struct arp_header *arp_resp = (struct arp_header *)(buffer+ETH2_HEADER_LEN); struct sockaddr_ll socket_address; int index,ret,length=0,ifindex; memset(buffer,0x00,60); /*open socket*/ sd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (sd == -1) { perror("socket():"); exit(1); } strcpy(ifr.ifr_name,"eth1.30"); /*retrieve ethernet interface index*/ if (ioctl(sd, SIOCGIFINDEX, &ifr) == -1) { perror("SIOCGIFINDEX"); exit(1); } ifindex = ifr.ifr_ifindex; printf("interface index is %d\n",ifindex); /*retrieve corresponding MAC*/ if (ioctl(sd, SIOCGIFHWADDR, &ifr) == -1) { perror("SIOCGIFINDEX"); exit(1); } close (sd); for (index = 0; index < 6; index++) { send_req->h_dest[index] = (unsigned char)0xff; arp_req->target_mac[index] = (unsigned char)0x00; /* Filling the source mac address in the header*/ send_req->h_source[index] = (unsigned char)ifr.ifr_hwaddr.sa_data[index]; arp_req->sender_mac[index] = (unsigned char)ifr.ifr_hwaddr.sa_data[index]; socket_address.sll_addr[index] = (unsigned char)ifr.ifr_hwaddr.sa_data[index]; } printf("Successfully got eth1 MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", send_req->h_source[0],send_req->h_source[1],send_req->h_source[2], send_req->h_source[3],send_req->h_source[4],send_req->h_source[5]); printf(" arp_reqMAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", arp_req->sender_mac[0],arp_req->sender_mac[1],arp_req->sender_mac[2], arp_req->sender_mac[3],arp_req->sender_mac[4],arp_req->sender_mac[5]); printf("socket_address MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", socket_address.sll_addr[0],socket_address.sll_addr[1],socket_address.sll_addr[2], socket_address.sll_addr[3],socket_address.sll_addr[4],socket_address.sll_addr[5]); /*prepare sockaddr_ll*/ socket_address.sll_family = AF_PACKET; socket_address.sll_protocol = htons(ETH_P_ARP); socket_address.sll_ifindex = ifindex; socket_address.sll_hatype = htons(ARPHRD_ETHER); socket_address.sll_pkttype = (PACKET_BROADCAST); socket_address.sll_halen = MAC_LENGTH; socket_address.sll_addr[6] = 0x00; socket_address.sll_addr[7] = 0x00; /* Setting protocol of the packet */ send_req->h_proto = htons(ETH_P_ARP); /* Creating ARP request */ arp_req->hardware_type = htons(HW_TYPE); arp_req->protocol_type = htons(ETH_P_IP); arp_req->hardware_len = MAC_LENGTH; arp_req->protocol_len =IPV4_LENGTH; arp_req->opcode = htons(ARP_REQUEST); for(index=0;index<5;index++) { arp_req->sender_ip[index]=(unsigned char)source_ip[index]; arp_req->target_ip[index]=(unsigned char)target_ip[index]; } // Submit request for a raw socket descriptor. if ((sd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) { perror ("socket() failed "); exit (EXIT_FAILURE); } buffer[32]=0x00; ret = sendto(sd, buffer, 42, 0, (struct sockaddr*)&socket_address, sizeof(socket_address)); if (ret == -1) { perror("sendto():"); exit(1); } else { printf(" Sent the ARP REQ \n\t"); for(index=0;index<42;index++) { printf("%02X ",buffer[index]); if(index % 16 ==0 && index !=0) {printf("\n\t");} } } printf("\n\t"); memset(buffer,0x00,60); while(1) { length = recvfrom(sd, buffer, BUF_SIZE, 0, NULL, NULL); if (length == -1) { perror("recvfrom():"); exit(1); } if(htons(rcv_resp->h_proto) == PROTO_ARP) { //if( arp_resp->opcode == ARP_REPLY ) printf(" RECEIVED ARP RESP len=%d \n",length); printf(" Sender IP :"); for(index=0;index<4;index++) printf("%u.",(unsigned int)arp_resp->sender_ip[index]); printf("\n Sender MAC :"); for(index=0;index<6;index++) printf(" %02X:",arp_resp->sender_mac[index]); printf("\nReceiver IP :"); for(index=0;index<4;index++) printf(" %u.",arp_resp->target_ip[index]); printf("\n Self MAC :"); for(index=0;index<6;index++) printf(" %02X:",arp_resp->target_mac[index]); printf("\n :"); break; } } return 0; } 

再次感谢Arun Kumar P