Skip to content

Commit

Permalink
Merge pull request #247 from dmuhamedagic/sendarp
Browse files Browse the repository at this point in the history
Medium: tools: send_arp.libnet: reuse ARP packets (debian#701914)
  • Loading branch information
dmuhamedagic committed Jul 3, 2013
2 parents 1438420 + c72a755 commit 9c2420c
Showing 1 changed file with 115 additions and 59 deletions.
174 changes: 115 additions & 59 deletions tools/send_arp.libnet.c
Expand Up @@ -49,17 +49,18 @@

#ifdef HAVE_LIBNET_1_0_API
# define LTYPE struct libnet_link_int
static u_char *mk_packet(u_int32_t ip, u_char *device, u_char *macaddr, u_char *broadcast, u_char *netmask, u_short arptype);
static int send_arp(struct libnet_link_int *l, u_char *device, u_char *buf);
#endif
#ifdef HAVE_LIBNET_1_1_API
# define LTYPE libnet_t
static libnet_t *mk_packet(libnet_t* lntag, u_int32_t ip, u_char *device, u_char macaddr[6], u_char *broadcast, u_char *netmask, u_short arptype);
int send_arp(libnet_t* lntag);
#endif

#define PIDDIR HA_VARRUNDIR "/" PACKAGE
#define PIDFILE_BASE PIDDIR "/send_arp-"

static int send_arp(LTYPE* l, u_int32_t ip, u_char *device, u_char mac[6]
, u_char *broadcast, u_char *netmask, u_short arptype);

static char print_usage[]={
"send_arp: sends out custom ARP packet.\n"
" usage: send_arp [-i repeatinterval-ms] [-r repeatcount] [-p pidfile] \\\n"
Expand Down Expand Up @@ -135,14 +136,20 @@ main(int argc, char *argv[])
char* netmask;
u_int32_t ip;
u_char src_mac[6];
LTYPE* l;
int repeatcount = 1;
int j;
long msinterval = 1000;
int flag;
char pidfilenamebuf[64];
char *pidfilename = NULL;

#ifdef HAVE_LIBNET_1_0_API
LTYPE* l;
u_char *request, *reply;
#elif defined(HAVE_LIBNET_1_1_API)
LTYPE *request, *reply;
#endif

CL_SIGNAL(SIGTERM, byebye);
CL_SIGINTERRUPT(SIGTERM, 1);

Expand Down Expand Up @@ -201,6 +208,24 @@ main(int argc, char *argv[])
return EXIT_FAILURE;
}

if (!strcasecmp(macaddr, AUTO_MAC_ADDR)) {
if (get_hw_addr(device, src_mac) < 0) {
cl_log(LOG_ERR, "Cannot find mac address for %s",
device);
unlink(pidfilename);
return EXIT_FAILURE;
}
}
else {
convert_macaddr((unsigned char *)macaddr, src_mac);
}

/*
* We need to send both a broadcast ARP request as well as the ARP response we
* were already sending. All the interesting research work for this fix was
* done by Masaki Hasegawa <masaki-h@pp.iij4u.or.jp> and his colleagues.
*/

#if defined(HAVE_LIBNET_1_0_API)
#ifdef ON_DARWIN
if ((ip = libnet_name_resolve((unsigned char*)ipaddr, 1)) == -1UL) {
Expand All @@ -219,56 +244,75 @@ main(int argc, char *argv[])
unlink(pidfilename);
return EXIT_FAILURE;
}
request = mk_packet(ip, (unsigned char*)device, src_mac
, (unsigned char*)broadcast, (unsigned char*)netmask
, ARPOP_REQUEST);
reply = mk_packet(ip, (unsigned char*)device, src_mac
, (unsigned char *)broadcast
, (unsigned char *)netmask, ARPOP_REPLY);
if (!request || !reply) {
cl_log(LOG_ERR, "could not create packets");
unlink(pidfilename);
return EXIT_FAILURE;
}
for (j=0; j < repeatcount; ++j) {
c = send_arp(l, (unsigned char*)device, request);
if (c < 0) {
break;
}
mssleep(msinterval / 2);
c = send_arp(l, (unsigned char*)device, reply);
if (c < 0) {
break;
}
if (j != repeatcount-1) {
mssleep(msinterval / 2);
}
}
#elif defined(HAVE_LIBNET_1_1_API)
if ((l=libnet_init(LIBNET_LINK, device, errbuf)) == NULL) {
if ((request=libnet_init(LIBNET_LINK, device, errbuf)) == NULL) {
cl_log(LOG_ERR, "libnet_init failure on %s: %s", device, errbuf);
unlink(pidfilename);
return EXIT_FAILURE;
}
if ((signed)(ip = libnet_name2addr4(l, ipaddr, 1)) == -1) {
cl_log(LOG_ERR, "Cannot resolve IP address [%s]", ipaddr);
if ((reply=libnet_init(LIBNET_LINK, device, errbuf)) == NULL) {
cl_log(LOG_ERR, "libnet_init failure on %s: %s", device, errbuf);
unlink(pidfilename);
return EXIT_FAILURE;
}
#else
# error "Must have LIBNET API version defined."
#endif

if (!strcasecmp(macaddr, AUTO_MAC_ADDR)) {
if (get_hw_addr(device, src_mac) < 0) {
cl_log(LOG_ERR, "Cannot find mac address for %s",
device);
unlink(pidfilename);
return EXIT_FAILURE;
}
if ((signed)(ip = libnet_name2addr4(request, ipaddr, 1)) == -1) {
cl_log(LOG_ERR, "Cannot resolve IP address [%s]", ipaddr);
unlink(pidfilename);
return EXIT_FAILURE;
}
else {
convert_macaddr((unsigned char *)macaddr, src_mac);
request = mk_packet(request, ip, (unsigned char*)device, src_mac
, (unsigned char*)broadcast, (unsigned char*)netmask
, ARPOP_REQUEST);
reply = mk_packet(reply, ip, (unsigned char*)device, src_mac
, (unsigned char *)broadcast
, (unsigned char *)netmask, ARPOP_REPLY);
if (!request || !reply) {
cl_log(LOG_ERR, "could not create packets");
unlink(pidfilename);
return EXIT_FAILURE;
}

/*
* We need to send both a broadcast ARP request as well as the ARP response we
* were already sending. All the interesting research work for this fix was
* done by Masaki Hasegawa <masaki-h@pp.iij4u.or.jp> and his colleagues.
*/
for (j=0; j < repeatcount; ++j) {
c = send_arp(l, ip, (unsigned char*)device, src_mac
, (unsigned char*)broadcast, (unsigned char*)netmask
, ARPOP_REQUEST);
c = send_arp(request);
if (c < 0) {
break;
}
mssleep(msinterval / 2);
c = send_arp(l, ip, (unsigned char*)device, src_mac
, (unsigned char *)broadcast
, (unsigned char *)netmask, ARPOP_REPLY);
c = send_arp(reply);
if (c < 0) {
break;
}
if (j != repeatcount-1) {
mssleep(msinterval / 2);
}
}
#else
# error "Must have LIBNET API version defined."
#endif

unlink(pidfilename);
return c < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
Expand Down Expand Up @@ -387,10 +431,9 @@ get_hw_addr(char *device, u_char mac[6])
*/

#ifdef HAVE_LIBNET_1_0_API
int
send_arp(struct libnet_link_int *l, u_int32_t ip, u_char *device, u_char *macaddr, u_char *broadcast, u_char *netmask, u_short arptype)
u_char *
mk_packet(u_int32_t ip, u_char *device, u_char *macaddr, u_char *broadcast, u_char *netmask, u_short arptype)
{
int n;
u_char *buf;
u_char *target_mac;
u_char device_mac[6];
Expand All @@ -400,7 +443,7 @@ send_arp(struct libnet_link_int *l, u_int32_t ip, u_char *device, u_char *macadd

if (libnet_init_packet(LIBNET_ARP_H + LIBNET_ETH_H, &buf) == -1) {
cl_log(LOG_ERR, "libnet_init_packet memory:");
return -1;
return NULL;
}

/* Convert ASCII Mac Address to 6 Hex Digits. */
Expand All @@ -409,14 +452,14 @@ send_arp(struct libnet_link_int *l, u_int32_t ip, u_char *device, u_char *macadd
if (get_hw_addr((char*)device, device_mac) < 0) {
cl_log(LOG_ERR, "Cannot find mac address for %s",
device);
return -1;
return NULL;
}

if (libnet_build_ethernet(bcast_mac, device_mac, ETHERTYPE_ARP, NULL, 0
, buf) == -1) {
cl_log(LOG_ERR, "libnet_build_ethernet failed:");
libnet_destroy_packet(&buf);
return -1;
return NULL;
}

if (arptype == ARPOP_REQUEST) {
Expand All @@ -426,8 +469,8 @@ send_arp(struct libnet_link_int *l, u_int32_t ip, u_char *device, u_char *macadd
target_mac = macaddr;
}
else {
cl_log(LOG_ERR, "unkonwn arptype:");
return -1;
cl_log(LOG_ERR, "unknown arptype");
return NULL;
}

/*
Expand All @@ -447,27 +490,19 @@ send_arp(struct libnet_link_int *l, u_int32_t ip, u_char *device, u_char *macadd
buf + LIBNET_ETH_H) == -1) {
cl_log(LOG_ERR, "libnet_build_arp failed:");
libnet_destroy_packet(&buf);
return -1;
return NULL;
}

n = libnet_write_link_layer(l, (char*)device, buf, LIBNET_ARP_H + LIBNET_ETH_H);
if (n == -1) {
cl_log(LOG_ERR, "libnet_build_ethernet failed:");
}

libnet_destroy_packet(&buf);
return (n);
return buf;
}
#endif /* HAVE_LIBNET_1_0_API */




#ifdef HAVE_LIBNET_1_1_API
int
send_arp(libnet_t* lntag, u_int32_t ip, u_char *device, u_char macaddr[6], u_char *broadcast, u_char *netmask, u_short arptype)
libnet_t*
mk_packet(libnet_t* lntag, u_int32_t ip, u_char *device, u_char macaddr[6], u_char *broadcast, u_char *netmask, u_short arptype)
{
int n;
u_char *target_mac;
u_char device_mac[6];
u_char bcast_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Expand All @@ -481,7 +516,7 @@ send_arp(libnet_t* lntag, u_int32_t ip, u_char *device, u_char macaddr[6], u_cha
}
else {
cl_log(LOG_ERR, "unkonwn arptype:");
return -1;
return NULL;
}

/*
Expand All @@ -502,28 +537,49 @@ send_arp(libnet_t* lntag, u_int32_t ip, u_char *device, u_char macaddr[6], u_cha
0 /* packet id */
) == -1 ) {
cl_log(LOG_ERR, "libnet_build_arp failed:");
return -1;
return NULL;
}

/* Ethernet header */
if (get_hw_addr((char *)device, device_mac) < 0) {
cl_log(LOG_ERR, "Cannot find mac address for %s",
device);
return -1;
return NULL;
}

if (libnet_build_ethernet(bcast_mac, device_mac, ETHERTYPE_ARP, NULL, 0
, lntag, 0) == -1 ) {
cl_log(LOG_ERR, "libnet_build_ethernet failed:");
return -1;
return NULL;
}
return lntag;
}
#endif /* HAVE_LIBNET_1_1_API */

n = libnet_write(lntag);
#ifdef HAVE_LIBNET_1_0_API
int
send_arp(struct libnet_link_int *l, u_char *device, u_char *buf)
{
int n;

n = libnet_write_link_layer(l, (char*)device, buf, LIBNET_ARP_H + LIBNET_ETH_H);
if (n == -1) {
cl_log(LOG_ERR, "libnet_build_ethernet failed:");
cl_log(LOG_ERR, "libnet_write_link_layer failed");
}
libnet_clear_packet(lntag);
return (n);
}
#endif /* HAVE_LIBNET_1_0_API */

#ifdef HAVE_LIBNET_1_1_API
int
send_arp(libnet_t* lntag)
{
int n;

n = libnet_write(lntag);
if (n == -1) {
cl_log(LOG_ERR, "libnet_write failed");
}
return (n);
}
#endif /* HAVE_LIBNET_1_1_API */
Expand Down

0 comments on commit 9c2420c

Please sign in to comment.