[SCM] Samba Shared Repository - branch master updated

Volker Lendecke vlendec at samba.org
Tue Feb 1 08:00:02 MST 2011


The branch, master has been updated
       via  23146f9 s3: Send a dropped_ip message if we lose an IP
       via  f71c032 s3: test addrchange
       via  80acca1 s3: Add support for AF_NETLINK addr notifications
      from  f9af242 s3-libnetapi: prefer dcerpc_samr_X functions in lib/netapi/user.c.

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


- Log -----------------------------------------------------------------
commit 23146f9912dd79d0ba5a50bf6bb5e36fd7d59565
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Jan 31 17:25:55 2011 +0100

    s3: Send a dropped_ip message if we lose an IP
    
    Autobuild-User: Volker Lendecke <vlendec at samba.org>
    Autobuild-Date: Tue Feb  1 15:59:17 CET 2011 on sn-devel-104

commit f71c032f166031381ab117b8beb0d94f73a895cd
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Jan 27 16:56:13 2011 +0100

    s3: test addrchange

commit 80acca1ebf8bd8d0350d63277e3143416372fb83
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Jan 27 12:58:22 2011 +0100

    s3: Add support for AF_NETLINK addr notifications
    
    Via an AF_NETLINK socket, the Linux kernel can inform us when IP addresses are
    added or dropped.
    
    This will first be used in winbind, it was triggered by clustering with ctdb.
    When winbind is connected to a domain controller and ctdb decides to move away
    the IP address that winbind used locally for the connection to the DC, the next
    request will run into a timeout. winbind sends out its request, but the
    response will never arrive: The IP is gone.
    
    It will also be interesting for more reliable online/offline detection, but
    this is something for future winbind refactoring.

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

Summary of changes:
 source3/Makefile.in                                |    2 +
 source3/configure.in                               |    9 +
 source3/lib/addrchange.c                           |  271 ++++++++++++++++++++
 .../net_registry_util.h => lib/addrchange.h}       |   40 ++--
 source3/torture/proto.h                            |    1 +
 source3/torture/test_addrchange.c                  |   93 +++++++
 source3/torture/torture.c                          |    1 +
 source3/winbindd/winbindd.c                        |   85 ++++++
 8 files changed, 484 insertions(+), 18 deletions(-)
 create mode 100644 source3/lib/addrchange.c
 copy source3/{utils/net_registry_util.h => lib/addrchange.h} (50%)
 create mode 100644 source3/torture/test_addrchange.c


Changeset truncated at 500 lines:

diff --git a/source3/Makefile.in b/source3/Makefile.in
index 4cb9a9f..0740133 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -436,6 +436,7 @@ LIB_OBJ = $(LIBSAMBAUTIL_OBJ) $(UTIL_OBJ) $(CRYPTO_OBJ) \
 	  lib/serverid.o \
 	  lib/util_sconn.o \
 	  lib/util_transfer_file.o ../lib/async_req/async_sock.o \
+	  lib/addrchange.o \
 	  $(TDB_LIB_OBJ) \
 	  $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \
 	  lib/interface.o lib/pidfile.o \
@@ -1193,6 +1194,7 @@ SMBTORTURE_OBJ1 = torture/torture.o torture/nbio.o torture/scanner.o torture/uta
 		torture/nbench.o \
 		torture/test_async_echo.o \
 		torture/test_smbsock_any_connect.o \
+		torture/test_addrchange.o \
 		torture/test_posix_append.o
 
 SMBTORTURE_OBJ = $(SMBTORTURE_OBJ1) $(PARAM_OBJ) $(TLDAP_OBJ) \
diff --git a/source3/configure.in b/source3/configure.in
index cfaf99b..b15bcf6 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -5547,6 +5547,15 @@ else
 fi
 
 #################################################
+# check for rtnetlink
+
+AC_CHECK_HEADERS([linux/netlink.h],
+  AC_CHECK_HEADERS([linux/rtnetlink.h],[],[],
+                   [#include <bits/sockaddr.h>
+                    #include <linux/netlink.h>]),
+  [],[#include <bits/sockaddr.h>])
+
+#################################################
 # check for ACL support
 
 AC_MSG_CHECKING(whether to support ACLs)
diff --git a/source3/lib/addrchange.c b/source3/lib/addrchange.c
new file mode 100644
index 0000000..cf415d8
--- /dev/null
+++ b/source3/lib/addrchange.c
@@ -0,0 +1,271 @@
+/*
+ * Samba Unix/Linux SMB client library
+ * Copyright (C) Volker Lendecke 2011
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include "lib/addrchange.h"
+
+#if HAVE_LINUX_RTNETLINK_H
+
+#include "linux/netlink.h"
+#include "linux/rtnetlink.h"
+#include "lib/async_req/async_sock.h"
+
+struct addrchange_context {
+	int sock;
+	uint8_t *buf;
+};
+
+static int addrchange_context_destructor(struct addrchange_context *c);
+
+NTSTATUS addrchange_context_create(TALLOC_CTX *mem_ctx,
+				   struct addrchange_context **pctx)
+{
+	struct addrchange_context *ctx;
+	struct sockaddr_nl addr;
+	NTSTATUS status;
+	int res;
+
+	ctx = talloc(mem_ctx, struct addrchange_context);
+	if (ctx == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	ctx->sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+	if (ctx->sock == -1) {
+		status = map_nt_error_from_unix(errno);
+		goto fail;
+	}
+	talloc_set_destructor(ctx, addrchange_context_destructor);
+
+	/*
+	 * We're interested in address changes
+	 */
+	ZERO_STRUCT(addr);
+	addr.nl_family = AF_NETLINK;
+	addr.nl_groups = RTMGRP_IPV6_IFADDR | RTMGRP_IPV4_IFADDR;
+
+	res = bind(ctx->sock, (struct sockaddr *)(void *)&addr, sizeof(addr));
+	if (res == -1) {
+		status = map_nt_error_from_unix(errno);
+		goto fail;
+	}
+
+	*pctx = ctx;
+	return NT_STATUS_OK;
+fail:
+	TALLOC_FREE(ctx);
+	return status;
+}
+
+static int addrchange_context_destructor(struct addrchange_context *c)
+{
+	if (c->sock != -1) {
+		close(c->sock);
+		c->sock = 0;
+	}
+	return 0;
+}
+
+struct addrchange_state {
+	uint8_t buf[8192];
+	struct sockaddr_storage fromaddr;
+	socklen_t fromaddr_len;
+
+	enum addrchange_type type;
+	struct sockaddr_storage addr;
+};
+
+static void addrchange_done(struct tevent_req *subreq);
+
+struct tevent_req *addrchange_send(TALLOC_CTX *mem_ctx,
+				   struct tevent_context *ev,
+				   struct addrchange_context *ctx)
+{
+	struct tevent_req *req, *subreq;
+	struct addrchange_state *state;
+
+	req = tevent_req_create(mem_ctx, &state, struct addrchange_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	state->fromaddr_len = sizeof(state->fromaddr);
+
+	subreq = recvfrom_send(state, ev, ctx->sock,
+			       state->buf, sizeof(state->buf), 0,
+			       &state->fromaddr, &state->fromaddr_len);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, addrchange_done, req);
+	return req;
+}
+
+static void addrchange_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct addrchange_state *state = tevent_req_data(
+		req, struct addrchange_state);
+	struct nlmsghdr *h;
+	struct ifaddrmsg *ifa;
+	struct rtattr *rta;
+	ssize_t received;
+	int len;
+	int err;
+	bool found;
+
+	received = recvfrom_recv(subreq, &err);
+	TALLOC_FREE(subreq);
+	if (received == -1) {
+		DEBUG(10, ("recvfrom returned %s\n", strerror(errno)));
+		tevent_req_nterror(req, map_nt_error_from_unix(err));
+		return;
+	}
+	if (received < sizeof(struct nlmsghdr)) {
+		DEBUG(10, ("received %d, expected at least %d\n",
+			   (int)received, (int)sizeof(struct nlmsghdr)));
+		tevent_req_nterror(req, NT_STATUS_UNEXPECTED_IO_ERROR);
+		return;
+	}
+
+	h = (struct nlmsghdr *)state->buf;
+	if (h->nlmsg_len < sizeof(struct nlmsghdr)) {
+		DEBUG(10, ("nlmsg_len=%d, expected at least %d\n",
+			   (int)h->nlmsg_len, (int)sizeof(struct nlmsghdr)));
+		tevent_req_nterror(req, NT_STATUS_UNEXPECTED_IO_ERROR);
+		return;
+	}
+	if (h->nlmsg_len > received) {
+		DEBUG(10, ("nlmsg_len=%d, expected at most %d\n",
+			   (int)h->nlmsg_len, (int)received));
+		tevent_req_nterror(req, NT_STATUS_UNEXPECTED_IO_ERROR);
+		return;
+	}
+	switch (h->nlmsg_type) {
+	case RTM_NEWADDR:
+		state->type = ADDRCHANGE_ADD;
+		break;
+	case RTM_DELADDR:
+		state->type = ADDRCHANGE_DEL;
+		break;
+	default:
+		DEBUG(10, ("Got unexpected type %d\n", h->nlmsg_type));
+		tevent_req_nterror(req, NT_STATUS_INVALID_ADDRESS);
+		return;
+	}
+
+	if (h->nlmsg_len < sizeof(struct nlmsghdr)+sizeof(struct ifaddrmsg)) {
+		DEBUG(10, ("nlmsg_len=%d, expected at least %d\n",
+			   (int)h->nlmsg_len,
+			   (int)(sizeof(struct nlmsghdr)
+				 +sizeof(struct ifaddrmsg))));
+		tevent_req_nterror(req, NT_STATUS_UNEXPECTED_IO_ERROR);
+		return;
+	}
+
+	ifa = (struct ifaddrmsg *)NLMSG_DATA(h);
+
+	state->addr.ss_family = ifa->ifa_family;
+
+	rta = IFA_RTA(ifa);
+	len = h->nlmsg_len - sizeof(struct nlmsghdr) + sizeof(struct ifaddrmsg);
+
+	found = false;
+
+	for (rta = IFA_RTA(ifa); RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
+
+		if ((rta->rta_type != IFA_LOCAL)
+		    && (rta->rta_type != IFA_ADDRESS)) {
+			continue;
+		}
+
+		switch (ifa->ifa_family) {
+		case AF_INET: {
+			struct sockaddr_in *v4_addr;
+			v4_addr = (struct sockaddr_in *)(void *)&state->addr;
+
+			if (RTA_PAYLOAD(rta) != sizeof(uint32_t)) {
+				continue;
+			}
+			v4_addr->sin_addr.s_addr = *(uint32_t *)RTA_DATA(rta);
+			found = true;
+			break;
+		}
+		case AF_INET6: {
+			struct sockaddr_in6 *v6_addr;
+			v6_addr = (struct sockaddr_in6 *)(void *)&state->addr;
+
+			if (RTA_PAYLOAD(rta) !=
+			    sizeof(v6_addr->sin6_addr.s6_addr)) {
+				continue;
+			}
+			memcpy(v6_addr->sin6_addr.s6_addr, RTA_DATA(rta),
+			       sizeof(v6_addr->sin6_addr.s6_addr));
+			found = true;
+			break;
+		}
+		}
+	}
+
+	if (!found) {
+		tevent_req_nterror(req, NT_STATUS_INVALID_ADDRESS);
+		return;
+	}
+
+	tevent_req_done(req);
+}
+
+NTSTATUS addrchange_recv(struct tevent_req *req, enum addrchange_type *type,
+			 struct sockaddr_storage *addr)
+{
+	struct addrchange_state *state = tevent_req_data(
+		req, struct addrchange_state);
+	NTSTATUS status;
+
+	if (tevent_req_is_nterror(req, &status)) {
+		return status;
+	}
+
+	*type = state->type;
+	*addr = state->addr;
+	return NT_STATUS_OK;
+}
+
+#else
+
+NTSTATUS addrchange_context_create(TALLOC_CTX *mem_ctx,
+				   struct addrchange_context **pctx)
+{
+	return NT_STATUS_NOT_SUPPORTED;
+}
+
+struct tevent_req *addrchange_send(TALLOC_CTX *mem_ctx,
+				   struct tevent_context *ev,
+				   struct addrchange_context *ctx)
+{
+	return NULL;
+}
+
+NTSTATUS addrchange_recv(struct tevent_req *req, enum addrchange_type *type,
+			 struct sockaddr_storage *addr)
+{
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+#endif
diff --git a/source3/utils/net_registry_util.h b/source3/lib/addrchange.h
similarity index 50%
copy from source3/utils/net_registry_util.h
copy to source3/lib/addrchange.h
index 61fd834..9587be7 100644
--- a/source3/utils/net_registry_util.h
+++ b/source3/lib/addrchange.h
@@ -1,9 +1,6 @@
 /*
  * Samba Unix/Linux SMB client library
- * Distributed SMB/CIFS Server Management Utility
- * registry utility functions
- *
- * Copyright (C) Michael Adam 2008
+ * Copyright (C) Volker Lendecke 2011
  *
  * 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
@@ -19,23 +16,30 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __NET_REGISTRY_UTIL_H__
-#define __NET_REGISTRY_UTIL_H__
+#ifndef __ADDRCHANGE_H__
+#define __ADDRCHANGE_H__
 
-void print_registry_key(const char *keyname, NTTIME *modtime);
+#include "lib/talloc/talloc.h"
+#include "lib/tevent/tevent.h"
+#include "libcli/util/ntstatus.h"
+#include "lib/replace/replace.h"
+#include "lib/replace/system/network.h"
 
-void print_registry_value(const struct registry_value *valvalue, bool raw);
+struct addrchange_context;
 
-void print_registry_value_with_name(const char *valname,
-				    const struct registry_value *valvalue);
+NTSTATUS addrchange_context_create(TALLOC_CTX *mem_ctx,
+				   struct addrchange_context **pctx);
 
-/**
- * Split path into hive name and subkeyname
- * normalizations performed:
- *  - convert '/' to '\\'
- *  - strip trailing '\\' chars
- */
-WERROR split_hive_key(TALLOC_CTX *ctx, const char *path, char **hivename,
-		      char **subkeyname);
+struct tevent_req *addrchange_send(TALLOC_CTX *mem_ctx,
+				   struct tevent_context *ev,
+				   struct addrchange_context *ctx);
+
+enum addrchange_type {
+	ADDRCHANGE_ADD,
+	ADDRCHANGE_DEL
+};
+
+NTSTATUS addrchange_recv(struct tevent_req *req, enum addrchange_type *type,
+			 struct sockaddr_storage *addr);
 
 #endif
diff --git a/source3/torture/proto.h b/source3/torture/proto.h
index a22113e..c7a4cbc 100644
--- a/source3/torture/proto.h
+++ b/source3/torture/proto.h
@@ -86,5 +86,6 @@ bool run_posix_append(int dummy);
 bool run_nbench2(int dummy);
 bool run_async_echo(int dummy);
 bool run_smb_any_connect(int dummy);
+bool run_addrchange(int dummy);
 
 #endif /* __TORTURE_H__ */
diff --git a/source3/torture/test_addrchange.c b/source3/torture/test_addrchange.c
new file mode 100644
index 0000000..003bea6
--- /dev/null
+++ b/source3/torture/test_addrchange.c
@@ -0,0 +1,93 @@
+/*
+   Unix SMB/CIFS implementation.
+   test for the addrchange functionality
+   Copyright (C) Volker Lendecke 2011
+
+   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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "lib/addrchange.h"
+#include "proto.h"
+
+extern int torture_numops;
+
+bool run_addrchange(int dummy)
+{
+	struct addrchange_context *ctx;
+	struct tevent_context *ev;
+	NTSTATUS status;
+	int i;
+
+	ev = tevent_context_init(talloc_tos());
+	if (ev == NULL) {
+		d_fprintf(stderr, "tevent_context_init failed\n");
+		return -1;
+	}
+
+	status = addrchange_context_create(talloc_tos(), &ctx);
+	if (!NT_STATUS_IS_OK(status)) {
+		d_fprintf(stderr, "addrchange_context_create failed: %s\n",
+			  nt_errstr(status));
+		return false;
+	}
+
+	for (i=0; i<torture_numops; i++) {
+		enum addrchange_type type;
+		struct sockaddr_storage addr;
+		struct tevent_req *req;
+		const char *typestr;
+		char addrstr[INET6_ADDRSTRLEN];
+
+		req = addrchange_send(talloc_tos(), ev, ctx);
+		if (req == NULL) {
+			d_fprintf(stderr, "addrchange_send failed\n");
+			return -1;
+		}
+
+		if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+			d_fprintf(stderr, "tevent_req_poll_ntstatus failed: "
+				  "%s\n", nt_errstr(status));
+			TALLOC_FREE(req);
+			return -1;
+		}
+
+		status = addrchange_recv(req, &type, &addr);
+		TALLOC_FREE(req);
+		if (!NT_STATUS_IS_OK(status)) {
+			d_fprintf(stderr, "addrchange_recv failed: %s\n",
+				  nt_errstr(status));
+			return -1;
+		}
+
+		switch(type) {
+		case ADDRCHANGE_ADD:
+			typestr = "add";
+			break;
+		case ADDRCHANGE_DEL:
+			typestr = "del";
+			break;
+		default:
+			typestr = talloc_asprintf(talloc_tos(), "unknown %d",
+						  (int)type);
+			break;
+		}
+
+		printf("Got %s %s\n", typestr,
+		       print_sockaddr(addrstr, sizeof(addrstr), &addr));
+	}
+	TALLOC_FREE(ctx);
+	TALLOC_FREE(ev);
+	return 0;
+}
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index df55940..48eb708 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -8074,6 +8074,7 @@ static struct {
 	{"ASYNC-ECHO", run_async_echo, 0},
 	{ "UID-REGRESSION-TEST", run_uid_regression_test, 0},
 	{ "SHORTNAME-TEST", run_shortname_test, 0},
+	{ "ADDRCHANGE", run_addrchange, 0},
 #if 1


-- 
Samba Shared Repository


More information about the samba-cvs mailing list