Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/tools/send_arp.libnet.c b/tools/send_arp.libnet.c
index d7bca99e3..68facd53e 100644
--- a/tools/send_arp.libnet.c
+++ b/tools/send_arp.libnet.c
@@ -1,764 +1,761 @@
/*
* send_arp
*
* This program sends out one ARP packet with source/target IP and Ethernet
* hardware addresses suuplied by the user. It uses the libnet libary from
* Packet Factory (http://www.packetfactory.net/libnet/ ). It has been tested
* on Linux, FreeBSD, and on Solaris.
*
* This inspired by the sample application supplied by Packet Factory.
* Matt Soffen
* Copyright (C) 2001 Matt Soffen <matt@soffen.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* Needs to be defined before any other includes, otherwise some system
* headers do not behave as expected! Major black magic... */
#undef _GNU_SOURCE /* in case it was defined on the command line */
#define _GNU_SOURCE
#include <config.h>
#include <sys/param.h>
#define USE_GNU
#if defined(ANSI_ONLY) && !defined(inline)
# define inline /* nothing */
#endif
#include <limits.h>
#include <libnet.h>
#include <libgen.h>
#include <clplumbing/timers.h>
#include <clplumbing/cl_signal.h>
#include <clplumbing/cl_log.h>
#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 char print_usage[]={
"send_arp: sends out custom ARP packet.\n"
" usage: send_arp [-i repeatinterval-ms] [-r repeatcount] [-p pidfile] \\\n"
" device src_ip_addr src_hw_addr broadcast_ip_addr netmask\n"
"\n"
" where:\n"
" repeatinterval-ms: timing, in milliseconds of sending arp packets\n"
" For each ARP announcement requested, a pair of ARP packets is sent,\n"
" an ARP request, and an ARP reply. This is because some systems\n"
" ignore one or the other, and this combination gives the greatest\n"
" chance of success.\n"
"\n"
" Each time an ARP is sent, if another ARP will be sent then\n"
" the code sleeps for half of repeatinterval-ms.\n"
"\n"
" repeatcount: how many pairs of ARP packets to send.\n"
" See above for why pairs are sent\n"
"\n"
" pidfile: pid file to use\n"
"\n"
" device: network interface to use\n"
"\n"
" src_ip_addr: source ip address\n"
"\n"
" src_hw_addr: source hardware address.\n"
" If \"auto\" then the address of device\n"
"\n"
" broadcast_ip_addr: ignored\n"
"\n"
" netmask: ignored\n"
};
static const char * SENDARPNAME = "send_arp";
static void convert_macaddr (u_char *macaddr, u_char enet_src[6]);
static int get_hw_addr(char *device, u_char mac[6]);
int write_pid_file(const char *pidfilename);
int create_pid_directory(const char *piddirectory);
#define AUTO_MAC_ADDR "auto"
#ifndef LIBNET_ERRBUF_SIZE
# define LIBNET_ERRBUF_SIZE 256
#endif
/*
* For use logd, should keep identical with the same const variables defined
* in heartbeat.h.
*/
#define ENV_PREFIX "HA_"
#define KEY_LOGDAEMON "use_logd"
static void
byebye(int nsig)
{
(void)nsig;
/* Avoid an "error exit" log message if we're killed */
exit(0);
}
int
main(int argc, char *argv[])
{
int c = -1;
char errbuf[LIBNET_ERRBUF_SIZE];
char* device;
char* ipaddr;
char* macaddr;
char* broadcast;
char* netmask;
u_int32_t ip;
- u_char src_mac[6];
+ u_char src_mac[6];
int repeatcount = 1;
int j;
long msinterval = 1000;
int flag;
- char pidfilenamebuf[64];
- char *pidfilename = NULL;
+ char *pidfilename = NULL;
+ int pidflen;
struct sigaction act;
#ifdef HAVE_LIBNET_1_0_API
LTYPE* l;
u_char *request, *reply;
#elif defined(HAVE_LIBNET_1_1_API)
LTYPE *request, *reply;
#endif
memset(&act, 0, sizeof(struct sigaction));
act.sa_flags &= ~SA_RESTART; /* redundant - to stress syscalls should fail */
act.sa_handler = byebye;
if ((sigemptyset(&act.sa_mask) < 0) || (sigaction(SIGTERM, &act, NULL) < 0)) {
cl_log(LOG_ERR, "Could not set handler for signal: %s", strerror(errno));
return 1;
}
cl_log_set_entity(SENDARPNAME);
cl_log_enable_stderr(TRUE);
cl_log_set_facility(LOG_USER);
cl_inherit_logging_environment(0);
while ((flag = getopt(argc, argv, "i:r:p:")) != EOF) {
switch(flag) {
case 'i': msinterval= atol(optarg);
break;
case 'r': repeatcount= atoi(optarg);
break;
case 'p': pidfilename= optarg;
break;
default: fprintf(stderr, "%s\n\n", print_usage);
return 1;
break;
}
}
if (argc-optind != 5) {
fprintf(stderr, "%s\n\n", print_usage);
return 1;
}
/*
* argv[optind+1] DEVICE dc0,eth0:0,hme0:0,
* argv[optind+2] IP 192.168.195.186
* argv[optind+3] MAC ADDR 00a0cc34a878
* argv[optind+4] BROADCAST 192.168.195.186
* argv[optind+5] NETMASK ffffffffffff
*/
device = argv[optind];
ipaddr = argv[optind+1];
macaddr = argv[optind+2];
broadcast = argv[optind+3];
netmask = argv[optind+4];
if (!pidfilename) {
- if (snprintf(pidfilenamebuf, sizeof(pidfilenamebuf), "%s%s",
- PIDFILE_BASE, ipaddr) >=
- (int)sizeof(pidfilenamebuf)) {
- cl_log(LOG_INFO, "Pid file truncated");
- return EXIT_FAILURE;
- }
- pidfilename = pidfilenamebuf;
+ pidflen = strlen(PIDFILE_BASE) + strlen(ipaddr);
+ pidfilename = calloc(1, pidflen);
+ snprintf(pidfilename, pidflen, "%s%s",
+ PIDFILE_BASE, ipaddr);
}
if(write_pid_file(pidfilename) < 0) {
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) {
#else
if ((ip = libnet_name_resolve(ipaddr, 1)) == -1UL) {
#endif
cl_log(LOG_ERR, "Cannot resolve IP address [%s]", ipaddr);
unlink(pidfilename);
return EXIT_FAILURE;
}
l = libnet_open_link_interface(device, errbuf);
if (!l) {
cl_log(LOG_ERR, "libnet_open_link_interface on %s: %s"
, device, errbuf);
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 ((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 ((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;
}
if ((signed)(ip = libnet_name2addr4(request, ipaddr, 1)) == -1) {
cl_log(LOG_ERR, "Cannot resolve IP address [%s]", ipaddr);
unlink(pidfilename);
return EXIT_FAILURE;
}
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;
}
for (j=0; j < repeatcount; ++j) {
c = send_arp(request);
if (c < 0) {
break;
}
mssleep(msinterval / 2);
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;
}
void
convert_macaddr (u_char *macaddr, u_char enet_src[6])
{
int i, pos;
u_char bits[3];
pos = 0;
for (i = 0; i < 6; i++) {
/* Inserted to allow old-style MAC addresses */
if (*macaddr == ':') {
pos++;
}
bits[0] = macaddr[pos++];
bits[1] = macaddr[pos++];
bits[2] = '\0';
enet_src[i] = strtol((const char *)bits, (char **)NULL, 16);
}
}
#ifdef HAVE_LIBNET_1_0_API
int
get_hw_addr(char *device, u_char mac[6])
{
struct ether_addr *mac_address;
struct libnet_link_int *network;
char err_buf[LIBNET_ERRBUF_SIZE];
network = libnet_open_link_interface(device, err_buf);
if (!network) {
fprintf(stderr, "libnet_open_link_interface: %s\n", err_buf);
return -1;
}
mac_address = libnet_get_hwaddr(network, device, err_buf);
if (!mac_address) {
fprintf(stderr, "libnet_get_hwaddr: %s\n", err_buf);
return -1;
}
memcpy(mac, mac_address->ether_addr_octet, 6);
return 0;
}
#endif
#ifdef HAVE_LIBNET_1_1_API
int
get_hw_addr(char *device, u_char mac[6])
{
struct libnet_ether_addr *mac_address;
libnet_t *ln;
char err_buf[LIBNET_ERRBUF_SIZE];
ln = libnet_init(LIBNET_LINK, device, err_buf);
if (!ln) {
fprintf(stderr, "libnet_open_link_interface: %s\n", err_buf);
return -1;
}
mac_address = libnet_get_hwaddr(ln);
if (!mac_address) {
fprintf(stderr, "libnet_get_hwaddr: %s\n", err_buf);
return -1;
}
memcpy(mac, mac_address->ether_addr_octet, 6);
return 0;
}
#endif
/*
* Notes on send_arp() behaviour. Horms, 15th June 2004
*
* 1. Target Hardware Address
* (In the ARP portion of the packet)
*
* a) ARP Reply
*
* Set to the MAC address we want associated with the VIP,
* as per RFC2002 (4.6).
*
* Previously set to ff:ff:ff:ff:ff:ff
*
* b) ARP Request
*
* Set to 00:00:00:00:00:00. According to RFC2002 (4.6)
* this value is not used in an ARP request, so the value should
* not matter. However, I observed that typically (always?) this value
* is set to 00:00:00:00:00:00. It seems harmless enough to follow
* this trend.
*
* Previously set to ff:ff:ff:ff:ff:ff
*
* 2. Source Hardware Address
* (Ethernet Header, not in the ARP portion of the packet)
*
* Set to the MAC address of the interface that the packet is being
* sent to. Actually, due to the way that send_arp is called this would
* usually (always?) be the case anyway. Although this value should not
* really matter, it seems sensible to set the source address to where
* the packet is really coming from. The other obvious choice would be
* the MAC address that is being associated for the VIP. Which was the
* previous values. Again, these are typically the same thing.
*
* Previously set to MAC address being associated with the VIP
*/
#ifdef HAVE_LIBNET_1_0_API
u_char *
mk_packet(u_int32_t ip, u_char *device, u_char *macaddr, u_char *broadcast, u_char *netmask, u_short arptype)
{
u_char *buf;
u_char *target_mac;
u_char device_mac[6];
u_char bcast_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
u_char zero_mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
if (libnet_init_packet(LIBNET_ARP_H + LIBNET_ETH_H, &buf) == -1) {
cl_log(LOG_ERR, "libnet_init_packet memory:");
return NULL;
}
/* Convert ASCII Mac Address to 6 Hex Digits. */
/* Ethernet header */
if (get_hw_addr((char*)device, device_mac) < 0) {
cl_log(LOG_ERR, "Cannot find mac address for %s",
device);
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 NULL;
}
if (arptype == ARPOP_REQUEST) {
target_mac = zero_mac;
}
else if (arptype == ARPOP_REPLY) {
target_mac = macaddr;
}
else {
cl_log(LOG_ERR, "unknown arptype");
return NULL;
}
/*
* ARP header
*/
if (libnet_build_arp(ARPHRD_ETHER, /* Hardware address type */
ETHERTYPE_IP, /* Protocol address type */
6, /* Hardware address length */
4, /* Protocol address length */
arptype, /* ARP operation */
macaddr, /* Source hardware addr */
(u_char *)&ip, /* Target hardware addr */
target_mac, /* Destination hw addr */
(u_char *)&ip, /* Target protocol address */
NULL, /* Payload */
0, /* Payload length */
buf + LIBNET_ETH_H) == -1) {
cl_log(LOG_ERR, "libnet_build_arp failed:");
libnet_destroy_packet(&buf);
return NULL;
}
return buf;
}
#endif /* HAVE_LIBNET_1_0_API */
#ifdef HAVE_LIBNET_1_1_API
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)
{
u_char *target_mac;
u_char device_mac[6];
u_char bcast_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
u_char zero_mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
if (arptype == ARPOP_REQUEST) {
target_mac = zero_mac;
}
else if (arptype == ARPOP_REPLY) {
target_mac = macaddr;
}
else {
cl_log(LOG_ERR, "unkonwn arptype:");
return NULL;
}
/*
* ARP header
*/
if (libnet_build_arp(ARPHRD_ETHER, /* hardware address type */
ETHERTYPE_IP, /* protocol address type */
6, /* Hardware address length */
4, /* protocol address length */
arptype, /* ARP operation type */
macaddr, /* sender Hardware address */
(u_int8_t *)&ip, /* sender protocol address */
target_mac, /* target hardware address */
(u_int8_t *)&ip, /* target protocol address */
NULL, /* Payload */
0, /* Length of payload */
lntag, /* libnet context pointer */
0 /* packet id */
) == -1 ) {
cl_log(LOG_ERR, "libnet_build_arp failed:");
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 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 NULL;
}
return lntag;
}
#endif /* HAVE_LIBNET_1_1_API */
#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_write_link_layer failed");
}
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 */
int
create_pid_directory(const char *pidfilename)
{
int status;
struct stat stat_buf;
char *pidfilename_cpy;
char *dir;
pidfilename_cpy = strdup(pidfilename);
if (!pidfilename_cpy) {
cl_log(LOG_INFO, "Memory allocation failure: %s\n",
strerror(errno));
return -1;
}
dir = dirname(pidfilename_cpy);
status = stat(dir, &stat_buf);
if (status < 0 && errno != ENOENT && errno != ENOTDIR) {
cl_log(LOG_INFO, "Could not stat pid-file directory "
"[%s]: %s", dir, strerror(errno));
free(pidfilename_cpy);
return -1;
}
if (status >= 0) {
if (S_ISDIR(stat_buf.st_mode)) {
return 0;
}
cl_log(LOG_INFO, "Pid-File directory exists but is "
"not a directory [%s]", dir);
free(pidfilename_cpy);
return -1;
}
if (mkdir(dir, S_IRUSR|S_IWUSR|S_IXUSR | S_IRGRP|S_IXGRP) < 0) {
/* Did someone else make it while we were trying ? */
if (errno == EEXIST && stat(dir, &stat_buf) >= 0
&& S_ISDIR(stat_buf.st_mode)) {
return 0;
}
cl_log(LOG_INFO, "Could not create pid-file directory "
"[%s]: %s", dir, strerror(errno));
free(pidfilename_cpy);
return -1;
}
free(pidfilename_cpy);
return 0;
}
int
write_pid_file(const char *pidfilename)
{
int pidfilefd;
char pidbuf[11];
unsigned long pid;
ssize_t bytes;
if (*pidfilename != '/') {
cl_log(LOG_INFO, "Invalid pid-file name, must begin with a "
"'/' [%s]\n", pidfilename);
return -1;
}
if (create_pid_directory(pidfilename) < 0) {
return -1;
}
while (1) {
pidfilefd = open(pidfilename, O_CREAT|O_EXCL|O_RDWR,
S_IRUSR|S_IWUSR);
if (pidfilefd < 0) {
if (errno != EEXIST) { /* Old PID file */
cl_log(LOG_INFO, "Could not open pid-file "
"[%s]: %s", pidfilename,
strerror(errno));
return -1;
}
}
else {
break;
}
pidfilefd = open(pidfilename, O_RDONLY, S_IRUSR|S_IWUSR);
if (pidfilefd < 0) {
cl_log(LOG_INFO, "Could not open pid-file "
"[%s]: %s", pidfilename,
strerror(errno));
return -1;
}
while (1) {
bytes = read(pidfilefd, pidbuf, sizeof(pidbuf)-1);
if (bytes < 0) {
if (errno == EINTR) {
continue;
}
cl_log(LOG_INFO, "Could not read pid-file "
"[%s]: %s", pidfilename,
strerror(errno));
return -1;
}
pidbuf[bytes] = '\0';
break;
}
if(unlink(pidfilename) < 0) {
cl_log(LOG_INFO, "Could not delete pid-file "
"[%s]: %s", pidfilename,
strerror(errno));
return -1;
}
if (!bytes) {
cl_log(LOG_INFO, "Invalid pid in pid-file "
"[%s]: %s", pidfilename,
strerror(errno));
return -1;
}
close(pidfilefd);
pid = strtoul(pidbuf, NULL, 10);
if (pid == ULONG_MAX && errno == ERANGE) {
cl_log(LOG_INFO, "Invalid pid in pid-file "
"[%s]: %s", pidfilename,
strerror(errno));
return -1;
}
if (kill(pid, SIGKILL) < 0 && errno != ESRCH) {
cl_log(LOG_INFO, "Error killing old process [%lu] "
"from pid-file [%s]: %s", pid,
pidfilename, strerror(errno));
return -1;
}
cl_log(LOG_INFO, "Killed old send_arp process [%lu]\n",
pid);
}
if (snprintf(pidbuf, sizeof(pidbuf), "%u"
, getpid()) >= (int)sizeof(pidbuf)) {
cl_log(LOG_INFO, "Pid too long for buffer [%u]", getpid());
return -1;
}
while (1) {
bytes = write(pidfilefd, pidbuf, strlen(pidbuf));
if (bytes != (ssize_t)strlen(pidbuf)) {
if (bytes < 0 && errno == EINTR) {
continue;
}
cl_log(LOG_INFO, "Could not write pid-file "
"[%s]: %s", pidfilename,
strerror(errno));
return -1;
}
break;
}
close(pidfilefd);
return 0;
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Feb 27, 12:40 AM (17 h, 31 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1465960
Default Alt Text
(19 KB)

Event Timeline