[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,
+ ðer_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,
+ ðer_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