#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <libnet.h>
#define MAX_IP_NUM 32
static char *pname = "";
static char *ifname = NULL;
static struct in_addr ipaddrs[MAX_IP_NUM];
static int timer = 5;
static int
get_hw_addr(char *dev, unsigned char macbuf[6])
{
libnet_t *l;
char errbuf[LIBNET_ERRBUF_SIZE] = "";
struct libnet_ether_addr *mac;
l = libnet_init(LIBNET_LINK, dev, errbuf);
if (!l) {
fprintf(stderr, "libnet_init: %s\n", errbuf);
return -1;
}
mac = libnet_get_hwaddr(l);
if (!mac) {
fprintf(stderr, "libnet_get_hwaddr: %s\n", libnet_geterror(l));
libnet_destroy(l);
return -1;
}
memcpy(macbuf, mac->ether_addr_octet, 6);
libnet_destroy(l);
return 0;
}
static int
send_garp(char *ifname, long ipaddr)
{
unsigned char bcast_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
unsigned char zero_mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char mymac[6] = {0x00};
libnet_t *l;
char errbuf[LIBNET_ERRBUF_SIZE] = "";
int i, ret = 0;
if (get_hw_addr(ifname, mymac) != 0) {
return -1;
}
l = libnet_init(LIBNET_LINK, ifname, errbuf);
if (!l) {
fprintf(stderr, "libnet_init: %s\n", errbuf);
return -1;
}
for (i = 0; i < 2; i++) {
if (libnet_build_arp(ARPHRD_ETHER, /* hardware address type */
ETHERTYPE_IP, /* protocol address type */
6, /* Hardware address length */
4, /* protocol address length */
(i == 0) ? ARPOP_REQUEST : ARPOP_REPLY, /* ARP operation type */
mymac, /* sender Hardware address */
(unsigned char *)&ipaddr, /* sender protocol address */
(i == 0) ? zero_mac : mymac, /* target hardware address */
(unsigned char *)&ipaddr, /* target protocol address */
NULL, /* Payload */
0, /* Length of payload */
l, /* libnet context pointer */
0 /* packet id */
) == -1 ) {
fprintf(stderr, "libnet_build_arp: %s\n", libnet_geterror(l));
ret = -1;
break;
}
if (libnet_build_ethernet(bcast_mac, mymac, ETHERTYPE_ARP, NULL, 0,
l, 0) == -1 ) {
fprintf(stderr, "libnet_build_ethernet: %s\n", libnet_geterror(l));
ret = -1;
break;
}
if (libnet_write(l) == -1) {
fprintf(stderr, "libnet_write: %s\n", libnet_geterror(l));
ret = -1;
break;
}
libnet_clear_packet(l);
if (i == 0) {
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 500 * 1000 * 1000; /* sleep 500 ms between the two frame. */
nanosleep(&ts, NULL);
}
}
libnet_destroy(l);
return ret;
}
static void
usage(void)
{
fprintf(stdout, "Usage:\n"
" %s [-h] [-f interface] [-t time] ipaddr1 [ipaddr2 ipaddr3 ...]\n",
pname);
}
int
main(int argc, char *argv[])
{
int ret, opt, i;
struct timeval tv;
int errnum;
pname = strrchr(argv[0], '/');
if (pname)
pname++;
else
pname = argv[0];
while ((opt = getopt(argc, argv, "hf:t:")) != -1) {
switch (opt) {
case 'h':
usage();
exit(0);
break;
case 'f':
ifname = strdup(optarg);
if (!ifname) {
fprintf(stderr, "strdup failed.\n");
exit(-1);
}
break;
case 't':
timer = atoi(optarg);
if (timer <= 0) {
fprintf(stderr, "timer value is invalid.\n");
exit(-1);
}
break;
default:
usage();
exit(0);
break;
}
}
if (optind >= argc) {
usage();
exit(-1);
}
i = 0;
while (optind < argc && i < MAX_IP_NUM) {
if (inet_aton(argv[optind], &ipaddrs[i]) == 0) {
fprintf(stderr, "ip addr error.\n");
exit(-1);
}
optind++;
i ++;
}
fprintf(stdout, "ifname: %s, timer: %d\n",
ifname ? ifname : "",
timer);
fprintf(stdout, "ip:\n");
i = 0;
while (ipaddrs[i].s_addr && i < MAX_IP_NUM) {
fprintf(stdout, " %s\n", inet_ntoa(ipaddrs[i]));
i++;
}
errnum = 0;
while (1) {
tv.tv_sec = timer;
tv.tv_usec = 0;
ret = select(0, NULL, NULL, NULL, &tv);
if (ret < 0) {
if (errno == EINTR || errno == EAGAIN)
continue;
perror("select");
exit(-1);
}
i = 0;
while (ipaddrs[i].s_addr && i < MAX_IP_NUM) {
if (send_garp(ifname, ipaddrs[i].s_addr) < 0)
errnum++;
i ++;
}
if (errnum >= 10)
break;
}
exit(0);
}
|