Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Medium: tools: send_arp.libnet: reuse ARP packets (debian#701914) #247

Merged
merged 1 commit into from Jul 3, 2013
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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