[SCM] Samba Shared Repository - branch master updated

Amitay Isaacs amitay at samba.org
Thu Aug 30 05:51:02 UTC 2018


The branch, master has been updated
       via  58b8f2a ctdb-common: Clean up comments in TCP packet parsing
       via  53ceac9 ctdb-common: Check the version field in IPv6 packets
       via  924a655 ctdb-common: Improve TCP packet size and offset calculations
       via  43a2022 ctdb-tests: Extend TCP packet test to also do packet extraction
       via  e2ac368 ctdb-common: Factor out TCP packet parsing code
       via  028fdc1 ctdb-common: Clean up types/declarations in TCP socket reading
       via  cb4848e ctdb-common: Fix error handling when parsing TCP packets
       via  f3a1f1e ctdb-common: Fix a bug in non-Linux (PCAP) TCP packet capturing
       via  0beb16f ctdb-common: Don't modify a const argument
       via  8fcf1af ctdb-common: Avoid magic numbers when building TCP packets
       via  a02cba1 ctdb-tests: Add tests for TCP packet marshalling
       via  d7d23e7 ctdb-common: Factor out TCP packet marshalling code
       via  a678995 ctdb-common: Avoid single line multi-assignment
       via  af5a42b ctdb-common: Set version more obviously in IPv6 NA packet
       via  ca0db67 ctdb-common: Clarify offset and packet length calculations
       via  6b1e9a4 ctdb-common: Use struct ether_arp to avoid manual offset calculations
       via  e2a00fe ctdb-common: Be more careful with packet sizes
       via  87088af ctdb-tests: Add tests for ARP and IPv6 NA marshalling
       via  39cfd51 ctdb-common: Separate ARP and IPv6 NA marshalling code
       via  50a6d15 ctdb-common: Fix error handling when sending ARPs
       via  2ebb25d ctdb-common: Factor out common ARP code
       via  172b87c ctdb-common: Initialise structures when declared
       via  0927b38 ctdb-tests: Add basic test to sanity check types in socket marshalling
       via  7c361f4 ctdb-common: Restore dropped copyright attributions
       via  0325934 ctdb-common: Fix CID 1414745 - Out-of-bounds access
       via  b430a1a ctdb-daemon: Do not retry connection to eventd
       via  62ec1ab ctdb-daemon: Wait for eventd to be ready before connecting
       via  c446ae5 ctdb-daemon: Open eventd pipe earlier
       via  e357b62 ctdb-daemon: Improve error handling consistency
       via  11ee92d ctdb-event: Add support to eventd for the startup notification FD
       via  dc6040c ctdb-common: Add support for sock daemon to notify of successful startup
      from  99d6237 pidl/tests: fix ndr_push_init_ctx() usage

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 58b8f2a31e30a9fe9180f3758acaebf7deffbd91
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Aug 17 21:33:39 2018 +1000

    ctdb-common: Clean up comments in TCP packet parsing
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>
    
    Autobuild-User(master): Amitay Isaacs <amitay at samba.org>
    Autobuild-Date(master): Thu Aug 30 07:50:04 CEST 2018 on sn-devel-144

commit 53ceac9694f2f530e875ec56ec15867205ae088e
Author: Martin Schwenke <martin at meltin.net>
Date:   Tue Aug 28 16:10:21 2018 +1000

    ctdb-common: Check the version field in IPv6 packets
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 924a655b2a56edea66064dd1fdf67d9b7e093b64
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Aug 17 21:26:04 2018 +1000

    ctdb-common: Improve TCP packet size and offset calculations
    
    The IPv4 check for short packets was strange.  It appeared to ensure
    that the capture included everything up to and including the window
    size.  The checksum field immediately follows the window size field,
    so just ensure that the packet is large enough to contain everything
    up to the start of the checksum.
    
    Add a similar check for IPv6 packets.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 43a2022596ed3bde1e2c833070b531a4b7289b84
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Aug 17 16:02:50 2018 +1000

    ctdb-tests: Extend TCP packet test to also do packet extraction
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit e2ac36867d616d06ac37498534ba89eb77f5d833
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Aug 17 15:00:31 2018 +1000

    ctdb-common: Factor out TCP packet parsing code
    
    This can be tested separately.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 028fdc12e7399dae23fec20deb3ec0284f9d0ce2
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Aug 17 14:35:07 2018 +1000

    ctdb-common: Clean up types/declarations in TCP socket reading
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit cb4848e35951d8dc232643b45116fb54655ffa30
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Aug 17 14:14:12 2018 +1000

    ctdb-common: Fix error handling when parsing TCP packets
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit f3a1f1e1fa9a8a0fe6ffd3809a64d8185cb561b7
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Aug 17 15:36:41 2018 +1000

    ctdb-common: Fix a bug in non-Linux (PCAP) TCP packet capturing
    
    Captured packets include a link-layer header, which is considered in
    the Linux code but not the PCAP code.  Also, the actual captured
    length is in caplen, not len.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 0beb16f34ea538519213bb2f81d2cd04467c5baa
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Aug 17 13:46:50 2018 +1000

    ctdb-common: Don't modify a const argument
    
    The current code might be slightly more efficient but
    intentionally (although temporarily) modifying a const argument just
    seems wrong.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 8fcf1af559f2a716ebcfb8277668d6539fd432f0
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Aug 17 12:30:19 2018 +1000

    ctdb-common: Avoid magic numbers when building TCP packets
    
    Most packet sizes and offsets are multiples of 32-bit words.  The IPv6
    payload length is in octets.  The IPv6 version is the top 4 bits of
    the relevant field.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit a02cba1c8a716d8e939d9bfb59e038e14f96e69a
Author: Martin Schwenke <martin at meltin.net>
Date:   Thu Aug 16 16:47:21 2018 +1000

    ctdb-tests: Add tests for TCP packet marshalling
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit d7d23e78ed2aa24d1807c2718d44afe3d8c70da6
Author: Martin Schwenke <martin at meltin.net>
Date:   Thu Aug 16 11:10:40 2018 +1000

    ctdb-common: Factor out TCP packet marshalling code
    
    This can be tested separately.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit a67899573a4386c212949303e26d0bed506abd8f
Author: Martin Schwenke <martin at meltin.net>
Date:   Tue Aug 14 13:49:25 2018 +1000

    ctdb-common: Avoid single line multi-assignment
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit af5a42bf028b2159eed740c1e7d8baae11eb4c06
Author: Martin Schwenke <martin at meltin.net>
Date:   Wed Aug 29 15:48:21 2018 +1000

    ctdb-common: Set version more obviously in IPv6 NA packet
    
    Version is the top 4 bits of this field.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit ca0db67df9a122528a37558ddfe8f9a34e7ff684
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Aug 10 18:38:23 2018 +1000

    ctdb-common: Clarify offset and packet length calculations
    
    Calculate each offset from the beginning of the buffer and explicitly
    use the sizes of structures.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 6b1e9a43dcd0e4aa158f1e03351b9fefc2db1162
Author: Martin Schwenke <martin at meltin.net>
Date:   Tue Aug 14 12:36:25 2018 +1000

    ctdb-common: Use struct ether_arp to avoid manual offset calculations
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit e2a00feca3565d3071424246bb25ad1623bdfe6c
Author: Martin Schwenke <martin at meltin.net>
Date:   Tue Aug 14 11:25:02 2018 +1000

    ctdb-common: Be more careful with packet sizes
    
    Ethernet packets must be at least 64 bytes.
    
    For ARP the packet size was limited to 64 bytes.  This is probably OK
    but the code might as well be a little more general.
    
    For IPv6 NA there was no guarantee that the packet is at least 64
    bytes.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 87088af6e49e9ce973cfe77d36cfbf42f9101854
Author: Martin Schwenke <martin at meltin.net>
Date:   Thu Aug 16 15:15:55 2018 +1000

    ctdb-tests: Add tests for ARP and IPv6 NA marshalling
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 39cfd51143b5bddc154b1d22b3768a2f4eef2161
Author: Martin Schwenke <martin at meltin.net>
Date:   Mon Aug 13 21:39:12 2018 +1000

    ctdb-common: Separate ARP and IPv6 NA marshalling code
    
    This can be tested separately.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 50a6d15256a22a8116b48b40c17c8c8620c2cd84
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Aug 10 17:23:56 2018 +1000

    ctdb-common: Fix error handling when sending ARPs
    
    There are numerous places in the code where errno can be lost causing
    the wrong error to be printed by a caller.  Change ctdb_sys_send_arp()
    to always return a useful errno on error instead of returning -1 and
    sometimes having errno set correctly.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 2ebb25dfc890923180ecb06d6e17ddb2948e7d2b
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Aug 10 17:04:32 2018 +1000

    ctdb-common: Factor out common ARP code
    
    Finding the interface and the MAC address are obvious.  Might as well
    set up the common parts of the destination address structure.
    
    Continue to open the socket and find the MAC address first.  This
    might seem odd because marshalling and other subsequent steps may
    fail.  However, in the future this code might be optimised to open a
    single socket to send ARPs for a list of addresses on each interface,
    so don't change the logic.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 172b87cb1be460a06b7bea0b598a5bf159d3faab
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Aug 10 16:14:40 2018 +1000

    ctdb-common: Initialise structures when declared
    
    Instead of using ZERO_STRUCT().
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 0927b382265191a756f131e7c81ac687d85353eb
Author: Martin Schwenke <martin at meltin.net>
Date:   Sat Aug 11 18:32:17 2018 +1000

    ctdb-tests: Add basic test to sanity check types in socket marshalling
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 7c361f4866ca9a2989d214cf132df56a78a8c638
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Aug 17 13:58:18 2018 +1000

    ctdb-common: Restore dropped copyright attributions
    
    Commit fa94a49dbbec4a65c368a533a534f952a9f147a7 accidentally dropped
    some copyright attributions.  The original version of system_socket.c
    was based on system_linux.c but many parts have been taking from
    system_freebsd.c, which had these additional copyright attributions.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 032593487f750b60f51462c4f5133ccdbbe1f78f
Author: Martin Schwenke <martin at meltin.net>
Date:   Tue Aug 14 13:18:01 2018 +1000

    ctdb-common: Fix CID 1414745 - Out-of-bounds access
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit b430a1ace69bcef3336907557ab5bf04271c1110
Author: Martin Schwenke <martin at meltin.net>
Date:   Mon Aug 27 14:53:37 2018 +1000

    ctdb-daemon: Do not retry connection to eventd
    
    Confirmation is now received from eventd that it is accepting
    connections, so this is no longer needed.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13592
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 62ec1ab1470206d6a2cf300f30ca0b4a39413a38
Author: Martin Schwenke <martin at meltin.net>
Date:   Mon Aug 27 14:47:38 2018 +1000

    ctdb-daemon: Wait for eventd to be ready before connecting
    
    The current method of retrying the connection to eventd means that
    messages get logged for each failure.
    
    Instead, pass a pipe file descriptor to eventd and wait for it to
    write 0 to the pipe to indicate that it is ready to accept client
    connections.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13592
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit c446ae5e1382d5e32c33ce92243daf6b4338e15a
Author: Martin Schwenke <martin at meltin.net>
Date:   Mon Aug 27 14:44:24 2018 +1000

    ctdb-daemon: Open eventd pipe earlier
    
    The pipe will soon be needed earlier, so initialise it earlier.
    Ensure the file descriptors are closed on error.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13592
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit e357b62fe556609750bdb8d27cf48dfb85c62ec8
Author: Martin Schwenke <martin at meltin.net>
Date:   Mon Aug 27 15:28:47 2018 +1000

    ctdb-daemon: Improve error handling consistency
    
    Other errors free argv, so do it here too.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13592
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 11ee92d1bfd73c509d90e7a7386af60a4e1a7fca
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Aug 24 14:52:29 2018 +1000

    ctdb-event: Add support to eventd for the startup notification FD
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13592
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit dc6040c121c65d5551c686f3f1be2891795f48aa
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Aug 24 14:44:12 2018 +1000

    ctdb-common: Add support for sock daemon to notify of successful startup
    
    The daemon writes 0 into the specified file descriptor when it is up
    and listening.  This can be used to avoid loops in clients that
    attempt to connect until they succeed.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13592
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

-----------------------------------------------------------------------

Summary of changes:
 ctdb/common/sock_daemon.c                  |   26 +
 ctdb/common/sock_daemon.h                  |   10 +
 ctdb/common/system_socket.c                | 1011 ++++++++++++++++------------
 ctdb/event/event_daemon.c                  |    8 +
 ctdb/server/ctdb_takeover.c                |    8 +-
 ctdb/server/eventscript.c                  |  139 +++-
 ctdb/tests/cunit/system_socket_test_001.sh |  129 ++++
 ctdb/tests/src/system_socket_test.c        |  245 +++++++
 ctdb/wscript                               |    5 +
 9 files changed, 1145 insertions(+), 436 deletions(-)
 create mode 100755 ctdb/tests/cunit/system_socket_test_001.sh
 create mode 100644 ctdb/tests/src/system_socket_test.c


Changeset truncated at 500 lines:

diff --git a/ctdb/common/sock_daemon.c b/ctdb/common/sock_daemon.c
index 3c17519..90f6bce 100644
--- a/ctdb/common/sock_daemon.c
+++ b/ctdb/common/sock_daemon.c
@@ -31,6 +31,7 @@
 #include "lib/util/dlinklist.h"
 #include "lib/util/tevent_unix.h"
 #include "lib/util/become_daemon.h"
+#include "lib/util/sys_rw.h"
 
 #include "common/logging.h"
 #include "common/reqid.h"
@@ -72,6 +73,7 @@ struct sock_daemon_context {
 
 	struct pidfile_context *pid_ctx;
 	struct sock_socket *socket_list;
+	int startup_fd;
 };
 
 /*
@@ -489,6 +491,7 @@ int sock_daemon_setup(TALLOC_CTX *mem_ctx, const char *daemon_name,
 
 	sockd->funcs = funcs;
 	sockd->private_data = private_data;
+	sockd->startup_fd = -1;
 
 	ret = logging_init(sockd, logging, debug_level, daemon_name);
 	if (ret != 0) {
@@ -520,6 +523,11 @@ int sock_daemon_add_unix(struct sock_daemon_context *sockd,
 	return 0;
 }
 
+void sock_daemon_set_startup_fd(struct sock_daemon_context *sockd, int fd)
+{
+	sockd->startup_fd = fd;
+}
+
 /*
  * Run socket daemon
  */
@@ -549,6 +557,7 @@ static void sock_daemon_run_socket_fail(struct tevent_req *subreq);
 static void sock_daemon_run_watch_pid(struct tevent_req *subreq);
 static void sock_daemon_run_wait(struct tevent_req *req);
 static void sock_daemon_run_wait_done(struct tevent_req *subreq);
+static void sock_daemon_startup_notify(struct sock_daemon_context *sockd);
 
 struct tevent_req *sock_daemon_run_send(TALLOC_CTX *mem_ctx,
 					struct tevent_context *ev,
@@ -675,6 +684,8 @@ static void sock_daemon_run_started(struct tevent_req *subreq)
 		return;
 	}
 	sock_daemon_run_wait(req);
+
+	sock_daemon_startup_notify(sockd);
 }
 
 static void sock_daemon_run_startup_done(struct tevent_req *subreq)
@@ -702,6 +713,8 @@ static void sock_daemon_run_startup_done(struct tevent_req *subreq)
 		return;
 	}
 	sock_daemon_run_wait(req);
+
+	sock_daemon_startup_notify(sockd);
 }
 
 static void sock_daemon_run_signal_handler(struct tevent_context *ev,
@@ -967,6 +980,19 @@ static void sock_daemon_run_wait_done(struct tevent_req *subreq)
 	sock_daemon_run_shutdown(req);
 }
 
+static void sock_daemon_startup_notify(struct sock_daemon_context *sockd)
+{
+	if (sockd->startup_fd != -1) {
+		unsigned int zero = 0;
+		ssize_t num;
+
+		num = sys_write(sockd->startup_fd, &zero, sizeof(zero));
+		if (num != sizeof(zero)) {
+			D_WARNING("Failed to write zero to pipe FD\n");
+		}
+	}
+}
+
 bool sock_daemon_run_recv(struct tevent_req *req, int *perr)
 {
 	int ret;
diff --git a/ctdb/common/sock_daemon.h b/ctdb/common/sock_daemon.h
index 705c4fa..972245a 100644
--- a/ctdb/common/sock_daemon.h
+++ b/ctdb/common/sock_daemon.h
@@ -210,6 +210,16 @@ int sock_daemon_add_unix(struct sock_daemon_context *sockd,
 			 void *private_data);
 
 /**
+ * @brief Set file descriptor for indicating startup success
+ *
+ * On successful completion, 0 (unsigned int) will be written to the fd.
+ *
+ * @param[in] sockd Socket daemon context
+ * @param[in] fd File descriptor
+ */
+void sock_daemon_set_startup_fd(struct sock_daemon_context *sockd, int fd);
+
+/**
  * @brief Async computation start to run a socket daemon
  *
  * @param[in] mem_ctx Talloc memory context
diff --git a/ctdb/common/system_socket.c b/ctdb/common/system_socket.c
index 4a7a8c8..668c045 100644
--- a/ctdb/common/system_socket.c
+++ b/ctdb/common/system_socket.c
@@ -3,6 +3,8 @@
 
    Copyright (C) Ronnie Sahlberg  2007
    Copyright (C) Andrew Tridgell  2007
+   Copyright (C) Marc Dequènes (Duck) 2009
+   Copyright (C) Volker Lendecke 2012
 
    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
@@ -168,226 +170,318 @@ static uint16_t ip6_checksum(uint16_t *data, size_t n, struct ip6_hdr *ip6)
 
 #ifdef HAVE_PACKETSOCKET
 
-int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface)
+/*
+ * Create IPv4 ARP requests/replies or IPv6 neighbour advertisement
+ * packets
+ */
+
+#define ARP_STRUCT_SIZE sizeof(struct ether_header) + \
+			sizeof(struct ether_arp)
+
+#define IP6_NA_STRUCT_SIZE sizeof(struct ether_header) + \
+			   sizeof(struct ip6_hdr) + \
+			   sizeof(struct nd_neighbor_advert) + \
+			   sizeof(struct nd_opt_hdr) + \
+			   sizeof(struct ether_addr)
+
+#define ARP_BUFFER_SIZE MAX(ARP_STRUCT_SIZE, 64)
+
+#define IP6_NA_BUFFER_SIZE MAX(IP6_NA_STRUCT_SIZE, 64)
+
+static int arp_build(uint8_t *buffer,
+		     size_t buflen,
+		     const struct sockaddr_in *addr,
+		     const struct ether_addr *hwaddr,
+		     bool reply,
+		     struct ether_addr **ether_dhost,
+		     size_t *len)
 {
-	int s, ret;
-	struct sockaddr_ll sall;
+	size_t l = ARP_BUFFER_SIZE;
 	struct ether_header *eh;
+	struct ether_arp *ea;
 	struct arphdr *ah;
+
+	if (addr->sin_family != AF_INET) {
+		return EINVAL;
+	}
+
+	if (buflen < l) {
+		return EMSGSIZE;
+	}
+
+	memset(buffer, 0 , l);
+
+	eh = (struct ether_header *)buffer;
+	memset(eh->ether_dhost, 0xff, ETH_ALEN);
+	memcpy(eh->ether_shost, hwaddr, ETH_ALEN);
+	eh->ether_type = htons(ETHERTYPE_ARP);
+
+	ea = (struct ether_arp *)(buffer + sizeof(struct ether_header));
+	ah = &ea->ea_hdr;
+	ah->ar_hrd = htons(ARPHRD_ETHER);
+	ah->ar_pro = htons(ETH_P_IP);
+	ah->ar_hln = ETH_ALEN;
+	ah->ar_pln = sizeof(ea->arp_spa);
+
+	if (! reply) {
+		ah->ar_op  = htons(ARPOP_REQUEST);
+		memcpy(ea->arp_sha, hwaddr, ETH_ALEN);
+		memcpy(ea->arp_spa, &addr->sin_addr, sizeof(ea->arp_spa));
+		memset(ea->arp_tha, 0, ETH_ALEN);
+		memcpy(ea->arp_tpa, &addr->sin_addr, sizeof(ea->arp_tpa));
+	} else {
+		ah->ar_op  = htons(ARPOP_REPLY);
+		memcpy(ea->arp_sha, hwaddr, ETH_ALEN);
+		memcpy(ea->arp_spa, &addr->sin_addr, sizeof(ea->arp_spa));
+		memcpy(ea->arp_tha, hwaddr, ETH_ALEN);
+		memcpy(ea->arp_tpa, &addr->sin_addr, sizeof(ea->arp_tpa));
+	}
+
+	*ether_dhost = (struct ether_addr *)eh->ether_dhost;
+	*len = l;
+	return 0;
+}
+
+static int ip6_na_build(uint8_t *buffer,
+			size_t buflen,
+			const struct sockaddr_in6 *addr,
+			const struct ether_addr *hwaddr,
+			struct ether_addr **ether_dhost,
+			size_t *len)
+{
+	size_t l = IP6_NA_BUFFER_SIZE;
+	struct ether_header *eh;
 	struct ip6_hdr *ip6;
 	struct nd_neighbor_advert *nd_na;
 	struct nd_opt_hdr *nd_oh;
-	struct ifreq if_hwaddr;
-	/* Size of IPv6 neighbor advertisement (with option) */
-	unsigned char buffer[sizeof(struct ether_header) +
-			     sizeof(struct ip6_hdr) +
-			     sizeof(struct nd_neighbor_advert) +
-			     sizeof(struct nd_opt_hdr) + ETH_ALEN];
-	char *ptr;
-	char bdcast[] = {0xff,0xff,0xff,0xff,0xff,0xff};
-	struct ifreq ifr;
-
-	ZERO_STRUCT(sall);
-	ZERO_STRUCT(ifr);
-	ZERO_STRUCT(if_hwaddr);
+	struct ether_addr *ea;
+	int ret;
 
-	switch (addr->ip.sin_family) {
-	case AF_INET:
-		s = socket(AF_PACKET, SOCK_RAW, 0);
-		if (s == -1){
-			DBG_ERR("Failed to open raw socket\n");
-			return -1;
-		}
+	if (addr->sin6_family != AF_INET6) {
+		return EINVAL;
+	}
 
-		DBG_DEBUG("Created SOCKET FD:%d for sending arp\n", s);
-		strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
-		if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
-			DBG_ERR("Interface '%s' not found\n", iface);
-			close(s);
-			return -1;
-		}
+	if (buflen < l) {
+		return EMSGSIZE;
+	}
 
-		/* get the mac address */
-		strlcpy(if_hwaddr.ifr_name, iface, sizeof(if_hwaddr.ifr_name));
-		ret = ioctl(s, SIOCGIFHWADDR, &if_hwaddr);
-		if ( ret < 0 ) {
-			close(s);
-			DBG_ERR("ioctl failed\n");
-			return -1;
-		}
-		if (ARPHRD_LOOPBACK == if_hwaddr.ifr_hwaddr.sa_family) {
-			D_DEBUG("Ignoring loopback arp request\n");
-			close(s);
-			return 0;
-		}
-		if (if_hwaddr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
-			close(s);
-			errno = EINVAL;
-			DBG_ERR("Not an ethernet address family (0x%x)\n",
-				if_hwaddr.ifr_hwaddr.sa_family);
-			return -1;
-		}
+	memset(buffer, 0 , l);
+
+	eh = (struct ether_header *)buffer;
+	/*
+	 * Ethernet multicast: 33:33:00:00:00:01 (see RFC2464,
+	 * section 7) - note memset 0 above!
+	 */
+	eh->ether_dhost[0] = 0x33;
+	eh->ether_dhost[1] = 0x33;
+	eh->ether_dhost[5] = 0x01;
+	memcpy(eh->ether_shost, hwaddr, ETH_ALEN);
+	eh->ether_type = htons(ETHERTYPE_IP6);
+
+	ip6 = (struct ip6_hdr *)(buffer + sizeof(struct ether_header));
+	ip6->ip6_vfc  = 6 << 4;
+	ip6->ip6_plen = htons(sizeof(struct nd_neighbor_advert) +
+			      sizeof(struct nd_opt_hdr) +
+			      ETH_ALEN);
+	ip6->ip6_nxt  = IPPROTO_ICMPV6;
+	ip6->ip6_hlim = 255;
+	ip6->ip6_src  = addr->sin6_addr;
+	/* all-nodes multicast */
+
+	ret = inet_pton(AF_INET6, "ff02::1", &ip6->ip6_dst);
+	if (ret != 1) {
+		return EIO;
+	}
 
+	nd_na = (struct nd_neighbor_advert *)(buffer +
+					      sizeof(struct ether_header) +
+					      sizeof(struct ip6_hdr));
+	nd_na->nd_na_type = ND_NEIGHBOR_ADVERT;
+	nd_na->nd_na_code = 0;
+	nd_na->nd_na_flags_reserved = ND_NA_FLAG_OVERRIDE;
+	nd_na->nd_na_target = addr->sin6_addr;
+
+	/* Option: Target link-layer address */
+	nd_oh = (struct nd_opt_hdr *)(buffer +
+				      sizeof(struct ether_header) +
+				      sizeof(struct ip6_hdr) +
+				      sizeof(struct nd_neighbor_advert));
+	nd_oh->nd_opt_type = ND_OPT_TARGET_LINKADDR;
+	nd_oh->nd_opt_len = 1;  /* multiple of 8 octets */
+
+	ea = (struct ether_addr *)(buffer +
+				   sizeof(struct ether_header) +
+				   sizeof(struct ip6_hdr) +
+				   sizeof(struct nd_neighbor_advert) +
+				   sizeof(struct nd_opt_hdr));
+	memcpy(ea, hwaddr, ETH_ALEN);
+
+	nd_na->nd_na_cksum = ip6_checksum((uint16_t *)nd_na,
+					  ntohs(ip6->ip6_plen),
+					  ip6);
+
+	*ether_dhost = (struct ether_addr *)eh->ether_dhost;
+	*len = l;
+	return 0;
+}
 
-		memset(buffer, 0 , 64);
-		eh = (struct ether_header *)buffer;
-		memset(eh->ether_dhost, 0xff, ETH_ALEN);
-		memcpy(eh->ether_shost, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN);
-		eh->ether_type = htons(ETHERTYPE_ARP);
+int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface)
+{
+	int s;
+	struct sockaddr_ll sall = {0};
+	struct ifreq if_hwaddr = {{{0}}};
+	uint8_t buffer[MAX(ARP_BUFFER_SIZE, IP6_NA_BUFFER_SIZE)];
+	struct ifreq ifr = {{{0}}};
+	struct ether_addr *hwaddr = NULL;
+	struct ether_addr *ether_dhost = NULL;
+	size_t len = 0;
+	int ret = 0;
+
+	s = socket(AF_PACKET, SOCK_RAW, 0);
+	if (s == -1) {
+		ret = errno;
+		DBG_ERR("Failed to open raw socket\n");
+		return ret;
+	}
+	DBG_DEBUG("Created SOCKET FD:%d for sending arp\n", s);
+
+	/* Find interface */
+	strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
+	if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
+		ret = errno;
+		DBG_ERR("Interface '%s' not found\n", iface);
+		goto fail;
+	}
 
-		ah = (struct arphdr *)&buffer[sizeof(struct ether_header)];
-		ah->ar_hrd = htons(ARPHRD_ETHER);
-		ah->ar_pro = htons(ETH_P_IP);
-		ah->ar_hln = ETH_ALEN;
-		ah->ar_pln = 4;
+	/* Get MAC address */
+	strlcpy(if_hwaddr.ifr_name, iface, sizeof(if_hwaddr.ifr_name));
+	ret = ioctl(s, SIOCGIFHWADDR, &if_hwaddr);
+	if ( ret < 0 ) {
+		ret = errno;
+		DBG_ERR("ioctl failed\n");
+		goto fail;
+	}
+	if (ARPHRD_LOOPBACK == if_hwaddr.ifr_hwaddr.sa_family) {
+		ret = 0;
+		D_DEBUG("Ignoring loopback arp request\n");
+		goto fail;
+	}
+	if (if_hwaddr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
+		ret = EINVAL;
+		DBG_ERR("Not an ethernet address family (0x%x)\n",
+			if_hwaddr.ifr_hwaddr.sa_family);
+		goto fail;;
+	}
 
-		/* send a gratious arp */
-		ah->ar_op  = htons(ARPOP_REQUEST);
-		ptr = (char *)&ah[1];
-		memcpy(ptr, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN);
-		ptr+=ETH_ALEN;
-		memcpy(ptr, &addr->ip.sin_addr, 4);
-		ptr+=4;
-		memset(ptr, 0, ETH_ALEN);
-		ptr+=ETH_ALEN;
-		memcpy(ptr, &addr->ip.sin_addr, 4);
-		ptr+=4;
-
-		sall.sll_family = AF_PACKET;
-		sall.sll_halen = 6;
-		memcpy(&sall.sll_addr[0], bdcast, sall.sll_halen);
-		sall.sll_protocol = htons(ETH_P_ALL);
-		sall.sll_ifindex = ifr.ifr_ifindex;
-		ret = sendto(s,buffer, 64, 0,
-			     (struct sockaddr *)&sall, sizeof(sall));
-		if (ret < 0 ){
-			close(s);
-			DBG_ERR("Failed sendto\n");
-			return -1;
+	/* Set up most of destination address structure */
+	sall.sll_family = AF_PACKET;
+	sall.sll_halen = sizeof(struct ether_addr);
+	sall.sll_protocol = htons(ETH_P_ALL);
+	sall.sll_ifindex = ifr.ifr_ifindex;
+
+	/* For clarity */
+	hwaddr = (struct ether_addr *)if_hwaddr.ifr_hwaddr.sa_data;
+
+	switch (addr->ip.sin_family) {
+	case AF_INET:
+		/* Send gratuitous ARP */
+		ret = arp_build(buffer,
+				sizeof(buffer),
+				&addr->ip,
+				hwaddr,
+				false,
+				&ether_dhost,
+				&len);
+		if (ret != 0) {
+			DBG_ERR("Failed to build ARP request\n");
+			goto fail;
 		}
 
-		/* send unsolicited arp reply broadcast */
-		ah->ar_op  = htons(ARPOP_REPLY);
-		ptr = (char *)&ah[1];
-		memcpy(ptr, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN);
-		ptr+=ETH_ALEN;
-		memcpy(ptr, &addr->ip.sin_addr, 4);
-		ptr+=4;
-		memcpy(ptr, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN);
-		ptr+=ETH_ALEN;
-		memcpy(ptr, &addr->ip.sin_addr, 4);
-		ptr+=4;
-
-		ret = sendto(s, buffer, 64, 0,
-			     (struct sockaddr *)&sall, sizeof(sall));
-		if (ret < 0 ){
+		memcpy(&sall.sll_addr[0], ether_dhost, sall.sll_halen);
+
+		ret = sendto(s,
+			     buffer,
+			     len,
+			     0,
+			     (struct sockaddr *)&sall,
+			     sizeof(sall));
+		if (ret < 0 ) {
+			ret = errno;
 			DBG_ERR("Failed sendto\n");
-			close(s);
-			return -1;
+			goto fail;
 		}
 
-		close(s);
-		break;
-	case AF_INET6:
-		s = socket(AF_PACKET, SOCK_RAW, 0);
-		if (s == -1){
-			DBG_ERR("Failed to open raw socket\n");
-			return -1;
+		/* Send unsolicited ARP reply */
+		ret = arp_build(buffer,
+				sizeof(buffer),
+				&addr->ip,
+				hwaddr,
+				true,
+				&ether_dhost,
+				&len);
+		if (ret != 0) {
+			DBG_ERR("Failed to build ARP reply\n");
+			goto fail;
 		}
 
-		DBG_DEBUG("Created SOCKET FD:%d for sending arp\n", s);
-		strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
-		if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
-			DBG_ERR("Interface '%s' not found\n", iface);
-			close(s);
-			return -1;
-		}
+		memcpy(&sall.sll_addr[0], ether_dhost, sall.sll_halen);
 
-		/* get the mac address */
-		strlcpy(if_hwaddr.ifr_name, iface, sizeof(if_hwaddr.ifr_name));
-		ret = ioctl(s, SIOCGIFHWADDR, &if_hwaddr);
-		if ( ret < 0 ) {
-			close(s);
-			DBG_ERR("ioctl failed\n");


-- 
Samba Shared Repository



More information about the samba-cvs mailing list