summaryrefslogtreecommitdiffstats
path: root/tools/send_arp.libnet.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tools/send_arp.libnet.c764
1 files changed, 764 insertions, 0 deletions
diff --git a/tools/send_arp.libnet.c b/tools/send_arp.libnet.c
new file mode 100644
index 0000000..d7bca99
--- /dev/null
+++ b/tools/send_arp.libnet.c
@@ -0,0 +1,764 @@
+/*
+ * 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];
+ int repeatcount = 1;
+ int j;
+ long msinterval = 1000;
+ int flag;
+ char pidfilenamebuf[64];
+ char *pidfilename = NULL;
+ 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;
+ }
+
+ 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;
+}
+
+