/* * Send gratuitous ARP, based on send_arp from the Linux fake package. */ /* send_arp.c This program sends out one ARP packet with source/target IP and Ethernet hardware addresses suuplied by the user. It compiles and works on Linux and will probably work on any Unix that has SOCK_PACKET. The idea behind this program is a proof of a concept, nothing more. It comes as is, no warranty. However, you're allowed to use it under one condition: you must use your brain simultaneously. If this condition is not met, you shall forget about this program and go RTFM immediately. yuri volobuev'97 volobuev@t1.chem.umn.edu */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* the L2 protocols */ #define ETH_HW_ADDR_LEN 6 #define IP_ADDR_LEN 4 #define ARP_FRAME_TYPE 0x0806 #define ETHER_HW_TYPE 1 #define IP_PROTO_TYPE 0x0800 #define OP_ARP_REQUEST 1 #define OP_ARP_REPLY 2 struct arp_packet { u_char targ_hw_addr[ETH_HW_ADDR_LEN]; u_char src_hw_addr[ETH_HW_ADDR_LEN]; u_short frame_type; u_short hw_type; u_short prot_type; u_char hw_addr_size; u_char prot_addr_size; u_short op; u_char sndr_hw_addr[ETH_HW_ADDR_LEN]; u_char sndr_ip_addr[IP_ADDR_LEN]; u_char rcpt_hw_addr[ETH_HW_ADDR_LEN]; u_char rcpt_ip_addr[IP_ADDR_LEN]; u_char padding[18]; }; int main(int argc,char** argv) { struct arp_packet pkt = { { 0, }, }; struct sockaddr_ll sa = { .sll_family = AF_PACKET, }; struct ifreq ifr; int sock; if (argc != 2 && argc != 3) { fprintf(stderr, "usage: gratarp ifname [target_mac_address]\n"); return 1; } sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_RARP)); if (sock<0){ perror("socket"); exit(1); } pkt.frame_type = htons(ARP_FRAME_TYPE); pkt.hw_type = htons(ETHER_HW_TYPE); pkt.prot_type = htons(IP_PROTO_TYPE); pkt.hw_addr_size = ETH_HW_ADDR_LEN; pkt.prot_addr_size = IP_ADDR_LEN; memset (&ifr, 0, sizeof(ifr)); memcpy (&ifr.ifr_name, argv[1], strlen(argv[1])); if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) perror("SIOCGIFINDEX"); sa.sll_ifindex = ifr.ifr_ifindex; if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) { perror("SIOCGIFHWADDR"); return 2; } memcpy(pkt.src_hw_addr, ifr.ifr_hwaddr.sa_data, 6); memcpy(pkt.sndr_hw_addr, ifr.ifr_hwaddr.sa_data, 6); /* pickup the target mac address */ if (argc > 2) { struct ether_addr *eth_addr = ether_aton(argv[2]); if (!eth_addr) { perror("ether_aton\n"); return 4; } memcpy(pkt.targ_hw_addr, eth_addr, 6); memcpy(pkt.rcpt_hw_addr, eth_addr, 6); memcpy(sa.sll_addr, eth_addr, 6); pkt.op = htons(OP_ARP_REPLY); } else { pkt.op = htons(OP_ARP_REQUEST); memset(pkt.targ_hw_addr, 0xff, 6); } sa.sll_halen = 6; if (ioctl(sock, SIOCGIFADDR, &ifr) < 0) { perror("SIOCGIFADDR"); return 5; } memcpy(pkt.sndr_ip_addr, &((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr, 4); memcpy(pkt.rcpt_ip_addr, &((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr, 4); if (sendto(sock, &pkt, sizeof(pkt), 0, (struct sockaddr*)&sa, sizeof(sa)) < 0){ perror("sendto"); return 4; } return 0; }