#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_arp.h>
#include <netpacket/packet.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <sys/select.h>
#include <arpa/nameser_compat.h>
#include <arpa/inet.h>
#include <resolv.h>
#include <netdb.h>
#include <time.h>
#include <unistd.h>
#define SENDNUM 3
#define SENDWAIT 100000
struct arpdata {
unsigned char ar_sha[ETH_ALEN];
unsigned long ar_sip;
unsigned char ar_tha[ETH_ALEN];
unsigned long ar_tip;
};
extern int errno;
int yes = 1;
unsigned char bcast_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
unsigned char zero_mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
void
convert_mac(char *macaddr_str, unsigned char macaddr[6]) {
int i, pos;
char bits[3], *endbits = bits + 3;
bits[2] = '\0';
pos = 0;
for (i = 0; i < 6; i++) {
if (macaddr_str[pos] == ':') {
pos++;
}
bits[0] = macaddr_str[pos++];
bits[1] = macaddr_str[pos++];
macaddr[i] = strtol(bits, &endbits, 16);
}
}
unsigned long
convert_ip(char *ip_str) {
struct in_addr inp;
inet_aton(ip_str, &inp);
return inp.s_addr;
}
int
build_packet(unsigned char *packet, unsigned long ip, unsigned char *macaddr, unsigned short arptype,
char *device, int sockfd) {
struct ether_header *ethhdr = (struct ether_header *)packet;
struct ether_arp *arphdr = (struct ether_arp *)(packet + sizeof *ethhdr);
unsigned char *target_mac;
unsigned char device_mac[6];
struct ifreq ifr;
int i;
target_mac = bcast_mac;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, device, IF_NAMESIZE);
if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) == -1) {
fprintf(stderr, "cannot get source mac addr: %s\n", strerror(errno));
return -1;
}
for (i = 0; i < 6; i++) {
device_mac[i] = ifr.ifr_ifru.ifru_hwaddr.sa_data[i];
}
memcpy(ethhdr->ether_dhost, bcast_mac, ETH_ALEN);
memcpy(ethhdr->ether_shost, device_mac, ETH_ALEN);
ethhdr->ether_type = htons(ETHERTYPE_ARP);
arphdr->ea_hdr.ar_hrd = htons(ARPHRD_ETHER);
arphdr->ea_hdr.ar_pro = htons(ETHERTYPE_IP);
arphdr->ea_hdr.ar_hln = ETH_ALEN;
arphdr->ea_hdr.ar_pln = 4;
arphdr->ea_hdr.ar_op = htons(arptype);
memcpy(arphdr->arp_sha, macaddr, ETH_ALEN);
memcpy(arphdr->arp_tha, target_mac, ETH_ALEN);
for (i = 0; i < 4; i++) {
arphdr->arp_spa[i] = ip & 0x000000ff;
arphdr->arp_tpa[i] = ip & 0x000000ff;;
ip = ip >> 8;
}
return 0;
}
int
send_arp(char *ip_str, char *macaddr_str, char *device) {
int packetsize = sizeof(struct ether_header) + sizeof(struct ether_arp);
unsigned char packet[sizeof(struct ether_header) + sizeof(struct ether_arp)];
int sockfd;
struct sockaddr_ll sa;
struct ifreq ifr;
unsigned char macaddr[6];
unsigned long ip;
int i;
convert_mac(macaddr_str, macaddr);
ip = convert_ip(ip_str);
sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sockfd == -1) {
fprintf(stderr, "Cannot create socket: %s\n", strerror(errno));
return 1;
}
if (setsockopt(sockfd, SOL_SOCKET,
#ifdef SO_REUSEPORT
SO_REUSEPORT,
#else
SO_REUSEADDR,
#endif
&yes, sizeof yes) == -1) {
fprintf(stderr, "Cannot set socket options: %s\n", strerror(errno));
close(sockfd);
return 1;
}
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, device, IF_NAMESIZE);
if (ioctl(sockfd, SIOCGIFINDEX, &ifr) == -1) {
fprintf(stderr, "Cannot get ifindex: %s\n", strerror(errno));
close(sockfd);
return -1;
}
memset(&sa, 0, sizeof(sa));
sa.sll_family = AF_PACKET;
sa.sll_protocol = htons(ETH_P_ALL);
sa.sll_ifindex = ifr.ifr_ifindex;
if (bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
fprintf(stderr, "Cannot bind address: %s\n", strerror(errno));
close(sockfd);
return -1;
}
for (i = 0; i < SENDNUM; i++) {
if (build_packet(packet, ip, macaddr, ARPOP_REQUEST, device, sockfd)) {
fprintf(stderr, "Could not build packet\n");
return 1;
}
if (sendto(sockfd, packet, packetsize, 0, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
fprintf(stderr, "Could not send data: %s\n", strerror(errno));
close(sockfd);
return -1;
}
if (build_packet(packet, ip, macaddr, ARPOP_REPLY, device, sockfd)) {
fprintf(stderr, "Could not build packet\n");
return 1;
}
if (sendto(sockfd, packet, packetsize, 0, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
fprintf(stderr, "Could not send data: %s\n", strerror(errno));
close(sockfd);
return -1;
}
usleep(SENDWAIT);
}
close(sockfd);
return 0;
}
int
main(int argc, char **argv) {
if (argc < 4) {
fprintf(stderr, "error - bad arguments\n");
fprintf(stderr, "Usage: %s <device> <ip> <mac>\n", argv[0]);
return EXIT_FAILURE;
}
send_arp(argv[2], argv[3], argv[1]);
return EXIT_SUCCESS;
}