summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/Makefile.in7
-rw-r--r--source3/include/includes.h1
-rw-r--r--source3/include/messages.h1
-rw-r--r--source3/include/proto.h1
-rw-r--r--source3/include/serverid.h66
-rw-r--r--source3/lib/messages.c21
-rw-r--r--source3/lib/serverid.c293
-rw-r--r--source3/lib/util.c9
-rw-r--r--source3/locking/brlock.c2
-rw-r--r--source3/locking/locking.c2
-rw-r--r--source3/nmbd/nmbd.c7
-rw-r--r--source3/printing/nt_printing.c2
-rw-r--r--source3/printing/printing.c6
-rw-r--r--source3/smbd/negprot.c4
-rw-r--r--source3/smbd/server.c39
-rw-r--r--source3/utils/net.c7
-rw-r--r--source3/utils/net_proto.h4
-rw-r--r--source3/utils/net_serverid.c153
-rw-r--r--source3/winbindd/winbindd.c7
-rw-r--r--source3/winbindd/winbindd_proto.h8
20 files changed, 602 insertions, 38 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 925f0be42e..9d42047a0b 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -385,6 +385,7 @@ LIB_OBJ = $(LIBSAMBAUTIL_OBJ) $(UTIL_OBJ) $(CRYPTO_OBJ) \
lib/messages_ctdbd.o lib/packet.o lib/ctdbd_conn.o \
lib/interfaces.o lib/memcache.o \
lib/talloc_dict.o \
+ lib/serverid.o \
lib/util_transfer_file.o ../lib/async_req/async_sock.o \
$(TDB_LIB_OBJ) \
$(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \
@@ -846,7 +847,7 @@ NMBD_OBJ1 = nmbd/asyncdns.o nmbd/nmbd.o nmbd/nmbd_become_dmb.o \
nmbd/nmbd_processlogon.o nmbd/nmbd_responserecordsdb.o \
nmbd/nmbd_sendannounce.o nmbd/nmbd_serverlistdb.o \
nmbd/nmbd_subnetdb.o nmbd/nmbd_winsproxy.o nmbd/nmbd_winsserver.o \
- nmbd/nmbd_workgroupdb.o nmbd/nmbd_synclists.o smbd/connection.o
+ nmbd/nmbd_workgroupdb.o nmbd/nmbd_synclists.o
NMBD_OBJ = $(NMBD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(LDB_OBJ) $(KRBCLIENT_OBJ) \
$(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \
@@ -1013,6 +1014,7 @@ NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_help.o \
utils/net_group.o utils/net_file.o utils/net_registry.o \
auth/token_util.o utils/net_dom.o utils/net_share.o \
utils/net_g_lock.o \
+ utils/net_serverid.o \
utils/net_eventlog.o
# these are not processed by make proto
@@ -1228,8 +1230,7 @@ WINBINDD_OBJ1 = \
winbindd/winbindd_remove_mapping.o \
winbindd/winbindd_set_hwm.o \
auth/token_util.o \
- ../nsswitch/libwbclient/wb_reqtrans.o \
- smbd/connection.o
+ ../nsswitch/libwbclient/wb_reqtrans.o
WINBINDD_OBJ = \
$(WINBINDD_OBJ1) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
diff --git a/source3/include/includes.h b/source3/include/includes.h
index dc0cbe182f..192b9a0bdb 100644
--- a/source3/include/includes.h
+++ b/source3/include/includes.h
@@ -687,6 +687,7 @@ struct ntlmssp_state;
#include "ctdbd_conn.h"
#include "../lib/util/talloc_stack.h"
#include "memcache.h"
+#include "serverid.h"
#include "async_smb.h"
#include "../lib/async_req/async_sock.h"
#include "talloc_dict.h"
diff --git a/source3/include/messages.h b/source3/include/messages.h
index 2e42fc6554..6063d358ea 100644
--- a/source3/include/messages.h
+++ b/source3/include/messages.h
@@ -72,6 +72,7 @@ struct server_id {
#ifdef CLUSTER_SUPPORT
uint32 vnn;
#endif
+ uint64_t unique_id;
};
#ifdef CLUSTER_SUPPORT
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 7c1f8fa92c..6ecf0a5542 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -1205,6 +1205,7 @@ uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options);
pid_t procid_to_pid(const struct server_id *proc);
void set_my_vnn(uint32 vnn);
uint32 get_my_vnn(void);
+void set_my_unique_id(uint64_t unique_id);
struct server_id pid_to_procid(pid_t pid);
struct server_id procid_self(void);
bool procid_equal(const struct server_id *p1, const struct server_id *p2);
diff --git a/source3/include/serverid.h b/source3/include/serverid.h
new file mode 100644
index 0000000000..9ef778cdc0
--- /dev/null
+++ b/source3/include/serverid.h
@@ -0,0 +1,66 @@
+/*
+ Unix SMB/CIFS implementation.
+ Implementation of a reliable server_exists()
+ Copyright (C) Volker Lendecke 2010
+
+ 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/>.
+*/
+
+#ifndef __SERVERID_H__
+#define __SERVERID_H__
+
+#include "includes.h"
+
+/*
+ * Register a server with its unique id
+ */
+bool serverid_register(const struct server_id *id, uint32_t msg_flags);
+
+/*
+ * Register ourselves with a unique id
+ */
+bool serverid_register_self(uint32_t msg_flags);
+
+/*
+ * De-register a server with its unique id
+ */
+bool serverid_deregister(const struct server_id *id);
+
+/*
+ * De-register ourself
+ */
+bool serverid_deregister_self(void);
+
+/*
+ * Check existence of a server id
+ */
+bool serverid_exists(const struct server_id *id);
+
+/*
+ * Walk the list of server_ids registered
+ */
+bool serverid_traverse(int (*fn)(struct db_record *rec,
+ const struct server_id *id,
+ uint32_t msg_flags,
+ void *private_data),
+ void *private_data);
+
+/*
+ * Walk the list of server_ids registered read-only
+ */
+bool serverid_traverse_read(int (*fn)(const struct server_id *id,
+ uint32_t msg_flags,
+ void *private_data),
+ void *private_data);
+#endif
diff --git a/source3/lib/messages.c b/source3/lib/messages.c
index 5e11dd4e25..2fcdc24179 100644
--- a/source3/lib/messages.c
+++ b/source3/lib/messages.c
@@ -95,36 +95,29 @@ struct msg_all {
Send one of the messages for the broadcast.
****************************************************************************/
-static int traverse_fn(struct db_record *rec,
- const struct connections_key *ckey,
- const struct connections_data *crec,
- void *state)
+static int traverse_fn(struct db_record *rec, const struct server_id *id,
+ uint32_t msg_flags, void *state)
{
struct msg_all *msg_all = (struct msg_all *)state;
NTSTATUS status;
- if (crec->cnum != -1)
- return 0;
-
/* Don't send if the receiver hasn't registered an interest. */
- if(!(crec->bcast_msg_flags & msg_all->msg_flag))
+ if((msg_flags & msg_all->msg_flag) == 0) {
return 0;
+ }
/* If the msg send fails because the pid was not found (i.e. smbd died),
* the msg has already been deleted from the messages.tdb.*/
- status = messaging_send_buf(msg_all->msg_ctx,
- crec->pid, msg_all->msg_type,
+ status = messaging_send_buf(msg_all->msg_ctx, *id, msg_all->msg_type,
(uint8 *)msg_all->buf, msg_all->len);
if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
/* If the pid was not found delete the entry from connections.tdb */
- DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n",
- procid_str_static(&crec->pid), crec->cnum,
- crec->servicename));
+ DEBUG(2, ("pid %s doesn't exist\n", procid_str_static(id)));
rec->delete_rec(rec);
}
@@ -172,7 +165,7 @@ bool message_send_all(struct messaging_context *msg_ctx,
msg_all.n_sent = 0;
msg_all.msg_ctx = msg_ctx;
- connections_forall(traverse_fn, &msg_all);
+ serverid_traverse(traverse_fn, &msg_all);
if (n_sent)
*n_sent = msg_all.n_sent;
return True;
diff --git a/source3/lib/serverid.c b/source3/lib/serverid.c
new file mode 100644
index 0000000000..9842ead103
--- /dev/null
+++ b/source3/lib/serverid.c
@@ -0,0 +1,293 @@
+/*
+ Unix SMB/CIFS implementation.
+ Implementation of a reliable server_exists()
+ Copyright (C) Volker Lendecke 2010
+
+ 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 "serverid.h"
+
+struct serverid_key {
+ pid_t pid;
+#ifdef CLUSTER_SUPPORT
+ uint32_t vnn;
+#endif
+};
+
+struct serverid_data {
+ uint64_t unique_id;
+ uint32_t msg_flags;
+};
+
+static struct db_context *serverid_db(void)
+{
+ static struct db_context *db;
+
+ if (db != NULL) {
+ return db;
+ }
+ db = db_open(talloc_autofree_context(), lock_path("serverid.tdb"),
+ 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT, 0644);
+ return db;
+}
+
+static void serverid_fill_key(const struct server_id *id,
+ struct serverid_key *key)
+{
+ ZERO_STRUCTP(key);
+ key->pid = id->pid;
+#ifdef CLUSTER_SUPPORT
+ key->vnn = id->vnn;
+#endif
+}
+
+bool serverid_register(const struct server_id *id, uint32_t msg_flags)
+{
+ struct db_context *db;
+ struct serverid_key key;
+ struct serverid_data data;
+ struct db_record *rec;
+ TDB_DATA tdbkey, tdbdata;
+ NTSTATUS status;
+ bool ret = false;
+
+ db = serverid_db();
+ if (db == NULL) {
+ return false;
+ }
+
+ serverid_fill_key(id, &key);
+ tdbkey = make_tdb_data((uint8_t *)&key, sizeof(key));
+
+ rec = db->fetch_locked(db, talloc_tos(), tdbkey);
+ if (rec == NULL) {
+ DEBUG(1, ("Could not fetch_lock serverid.tdb record\n"));
+ return false;
+ }
+
+ ZERO_STRUCT(data);
+ data.unique_id = id->unique_id;
+ data.msg_flags = msg_flags;
+
+ tdbdata = make_tdb_data((uint8_t *)&data, sizeof(data));
+ status = rec->store(rec, tdbdata, 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Storing serverid.tdb record failed: %s\n",
+ nt_errstr(status)));
+ goto done;
+ }
+ ret = true;
+done:
+ TALLOC_FREE(rec);
+ return ret;
+}
+
+bool serverid_register_self(uint32_t msg_flags)
+{
+ struct server_id pid;
+
+ pid = procid_self();
+ return serverid_register(&pid, msg_flags);
+}
+
+bool serverid_deregister(const struct server_id *id)
+{
+ struct db_context *db;
+ struct serverid_key key;
+ struct db_record *rec;
+ TDB_DATA tdbkey;
+ NTSTATUS status;
+ bool ret = false;
+
+ db = serverid_db();
+ if (db == NULL) {
+ return false;
+ }
+
+ serverid_fill_key(id, &key);
+ tdbkey = make_tdb_data((uint8_t *)&key, sizeof(key));
+
+ rec = db->fetch_locked(db, talloc_tos(), tdbkey);
+ if (rec == NULL) {
+ DEBUG(1, ("Could not fetch_lock serverid.tdb record\n"));
+ return false;
+ }
+
+ status = rec->delete_rec(rec);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Deleting serverid.tdb record failed: %s\n",
+ nt_errstr(status)));
+ goto done;
+ }
+ ret = true;
+done:
+ TALLOC_FREE(rec);
+ return ret;
+}
+
+bool serverid_deregister_self(void)
+{
+ struct server_id pid;
+
+ pid = procid_self();
+ return serverid_deregister(&pid);
+}
+
+struct serverid_exists_state {
+ const struct server_id *id;
+ bool exists;
+};
+
+static int server_exists_parse(TDB_DATA key, TDB_DATA data, void *priv)
+{
+ struct serverid_exists_state *state =
+ (struct serverid_exists_state *)priv;
+ uint64_t unique_id;
+
+ if (data.dsize != sizeof(struct serverid_data)) {
+ return -1;
+ }
+
+ /* memcpy, data.dptr might not be aligned */
+ memcpy(&unique_id, data.dptr, sizeof(unique_id));
+
+ state->exists = (state->id->unique_id == unique_id);
+ return 0;
+}
+
+bool serverid_exists(const struct server_id *id)
+{
+ struct db_context *db;
+ struct serverid_exists_state state;
+ struct serverid_key key;
+ TDB_DATA tdbkey;
+
+ db = serverid_db();
+ if (db == NULL) {
+ return false;
+ }
+
+ serverid_fill_key(id, &key);
+ tdbkey = make_tdb_data((uint8_t *)&key, sizeof(key));
+
+ state.id = id;
+ state.exists = false;
+
+ if (db->parse_record(db, tdbkey, server_exists_parse, &state) == -1) {
+ return false;
+ }
+ return state.exists;
+}
+
+static bool serverid_rec_parse(const struct db_record *rec,
+ struct server_id *id, uint32_t *msg_flags)
+{
+ struct serverid_key key;
+ struct serverid_data data;
+
+ if (rec->key.dsize != sizeof(key)) {
+ DEBUG(1, ("Found invalid key length %d in serverid.tdb\n",
+ (int)rec->key.dsize));
+ return false;
+ }
+ if (rec->value.dsize != sizeof(data)) {
+ DEBUG(1, ("Found invalid value length %d in serverid.tdb\n",
+ (int)rec->value.dsize));
+ return false;
+ }
+
+ memcpy(&key, rec->key.dptr, sizeof(key));
+ memcpy(&data, rec->value.dptr, sizeof(data));
+
+ id->pid = key.pid;
+#ifdef CLUSTER_SUPPORT
+ id->vnn = key.vnn;
+#endif
+ id->unique_id = data.unique_id;
+ *msg_flags = data.msg_flags;
+ return true;
+}
+
+struct serverid_traverse_read_state {
+ int (*fn)(const struct server_id *id, uint32_t msg_flags,
+ void *private_data);
+ void *private_data;
+};
+
+static int serverid_traverse_read_fn(struct db_record *rec, void *private_data)
+{
+ struct serverid_traverse_read_state *state =
+ (struct serverid_traverse_read_state *)private_data;
+ struct server_id id;
+ uint32_t msg_flags;
+
+ if (!serverid_rec_parse(rec, &id, &msg_flags)) {
+ return 0;
+ }
+ return state->fn(&id, msg_flags,state->private_data);
+}
+
+bool serverid_traverse_read(int (*fn)(const struct server_id *id,
+ uint32_t msg_flags, void *private_data),
+ void *private_data)
+{
+ struct db_context *db;
+ struct serverid_traverse_read_state state;
+
+ db = serverid_db();
+ if (db == NULL) {
+ return false;
+ }
+ state.fn = fn;
+ state.private_data = private_data;
+ return db->traverse_read(db, serverid_traverse_read_fn, &state);
+}
+
+struct serverid_traverse_state {
+ int (*fn)(struct db_record *rec, const struct server_id *id,
+ uint32_t msg_flags, void *private_data);
+ void *private_data;
+};
+
+static int serverid_traverse_fn(struct db_record *rec, void *private_data)
+{
+ struct serverid_traverse_state *state =
+ (struct serverid_traverse_state *)private_data;
+ struct server_id id;
+ uint32_t msg_flags;
+
+ if (!serverid_rec_parse(rec, &id, &msg_flags)) {
+ return 0;
+ }
+ return state->fn(rec, &id, msg_flags, state->private_data);
+}
+
+bool serverid_traverse(int (*fn)(struct db_record *rec,
+ const struct server_id *id,
+ uint32_t msg_flags, void *private_data),
+ void *private_data)
+{
+ struct db_context *db;
+ struct serverid_traverse_state state;
+
+ db = serverid_db();
+ if (db == NULL) {
+ return false;
+ }
+ state.fn = fn;
+ state.private_data = private_data;
+ return db->traverse(db, serverid_traverse_fn, &state);
+}
diff --git a/source3/lib/util.c b/source3/lib/util.c
index f35a55fbed..68f26b8393 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -2647,10 +2647,18 @@ uint32 get_my_vnn(void)
return my_vnn;
}
+static uint64_t my_unique_id = 0;
+
+void set_my_unique_id(uint64_t unique_id)
+{
+ my_unique_id = unique_id;
+}
+
struct server_id pid_to_procid(pid_t pid)
{
struct server_id result;
result.pid = pid;
+ result.unique_id = my_unique_id;
#ifdef CLUSTER_SUPPORT
result.vnn = my_vnn;
#endif
@@ -2720,6 +2728,7 @@ struct server_id interpret_pid(const char *pid_string)
if (result.pid < 0) {
result.pid = -1;
}
+ result.unique_id = 0;
return result;
}
diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c
index a90e1fd8d5..c7503ca43c 100644
--- a/source3/locking/brlock.c
+++ b/source3/locking/brlock.c
@@ -1620,7 +1620,7 @@ static bool validate_lock_entries(unsigned int *pnum_entries, struct lock_struct
for (i = 0; i < *pnum_entries; i++) {
struct lock_struct *lock_data = &locks[i];
- if (!process_exists(lock_data->context.pid)) {
+ if (!serverid_exists(&lock_data->context.pid)) {
/* This process no longer exists - mark this
entry as invalid by zeroing it. */
ZERO_STRUCTP(lock_data);
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index 095d0b17b9..6f1bc8cf8a 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -653,7 +653,7 @@ static bool parse_share_modes(const TDB_DATA dbuf, struct share_mode_lock *lck)
}
DEBUG(10,("parse_share_modes: %s\n",
str ? str : ""));
- if (!process_exists(entry_p->pid)) {
+ if (!serverid_exists(&entry_p->pid)) {
DEBUG(10,("parse_share_modes: deleted %s\n",
str ? str : ""));
entry_p->op_type = UNUSED_SHARE_MODE_ENTRY;
diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c
index 22f5b97116..4443dfae9f 100644
--- a/source3/nmbd/nmbd.c
+++ b/source3/nmbd/nmbd.c
@@ -83,6 +83,7 @@ static void terminate(void)
kill_async_dns_child();
gencache_stabilize();
+ serverid_deregister_self();
pidfile_unlink();
@@ -930,7 +931,11 @@ static bool open_sockets(bool isdaemon, int port)
exit(1);
/* get broadcast messages */
- claim_connection(NULL,"",FLAG_MSG_GENERAL|FLAG_MSG_DBWRAP);
+
+ if (!serverid_register_self(FLAG_MSG_GENERAL|FLAG_MSG_DBWRAP)) {
+ DEBUG(1, ("Could not register myself in serverid.tdb\n"));
+ exit(1);
+ }
messaging_register(nmbd_messaging_context(), NULL,
MSG_FORCE_ELECTION, nmbd_message_election);
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c
index d7fe272ea7..c080037111 100644
--- a/source3/printing/nt_printing.c
+++ b/source3/printing/nt_printing.c
@@ -618,7 +618,7 @@ bool nt_printing_init(struct messaging_context *msg_ctx)
/* of course, none of the message callbacks matter if you don't
tell messages.c that you interested in receiving PRINT_GENERAL
- msgs. This is done in claim_connection() */
+ msgs. This is done in serverid_register() */
if ( lp_security() == SEC_ADS ) {
diff --git a/source3/printing/printing.c b/source3/printing/printing.c
index a239fb2c54..50494e37dc 100644
--- a/source3/printing/printing.c
+++ b/source3/printing/printing.c
@@ -1464,8 +1464,10 @@ void start_background_queue(void)
smbd_setup_sig_term_handler();
smbd_setup_sig_hup_handler();
- claim_connection( NULL, "smbd lpq backend",
- FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
+ if (!serverid_register_self(FLAG_MSG_GENERAL|FLAG_MSG_SMBD
+ |FLAG_MSG_PRINT_GENERAL)) {
+ exit(1);
+ }
if (!locking_init()) {
exit(1);
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index 81d29d90f9..32714fd828 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -667,8 +667,8 @@ void reply_negprot(struct smb_request *req)
when the client connects to port 445. Of course there is a small
window where we are listening to messages -- jerry */
- claim_connection(
- NULL,"",FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
+ serverid_register_self(FLAG_MSG_GENERAL|FLAG_MSG_SMBD
+ |FLAG_MSG_PRINT_GENERAL);
/* Check for protocols, most desirable first */
for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index f685385043..5347bb9c03 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -249,6 +249,7 @@ static void remove_child_pid(pid_t pid, bool unclean_shutdown)
{
struct child_pid *child;
static struct timed_event *cleanup_te;
+ struct server_id child_id;
if (unclean_shutdown) {
/* a child terminated uncleanly so tickle all
@@ -268,6 +269,14 @@ static void remove_child_pid(pid_t pid, bool unclean_shutdown)
}
}
+ child_id = procid_self(); /* Just initialize pid and potentially vnn */
+ child_id.pid = pid;
+
+ if (!serverid_deregister(&child_id)) {
+ DEBUG(1, ("Could not remove pid %d from serverid.tdb\n",
+ (int)pid));
+ }
+
for (child = children; child != NULL; child = child->next) {
if (child->pid == pid) {
struct child_pid *tmp = child;
@@ -374,6 +383,7 @@ static void smbd_accept_connection(struct tevent_context *ev,
struct sockaddr_storage addr;
socklen_t in_addrlen = sizeof(addr);
pid_t pid = 0;
+ uint64_t unique_id;
smbd_set_server_fd(accept(s->fd,(struct sockaddr *)&addr,&in_addrlen));
@@ -398,12 +408,21 @@ static void smbd_accept_connection(struct tevent_context *ev,
return;
}
+ /*
+ * Generate a unique id in the parent process so that we use
+ * the global random state in the parent.
+ */
+ generate_random_buffer((uint8_t *)&unique_id, sizeof(unique_id));
+
pid = sys_fork();
if (pid == 0) {
NTSTATUS status = NT_STATUS_OK;
+
/* Child code ... */
am_parent = 0;
+ set_my_unique_id(unique_id);
+
/* Stop zombies, the parent explicitly handles
* them, counting worker smbds. */
CatchChild();
@@ -435,6 +454,13 @@ static void smbd_accept_connection(struct tevent_context *ev,
smbd_setup_sig_term_handler();
smbd_setup_sig_hup_handler();
+ if (!serverid_register_self(FLAG_MSG_GENERAL|FLAG_MSG_SMBD
+ |FLAG_MSG_DBWRAP
+ |FLAG_MSG_PRINT_GENERAL)) {
+ exit_server_cleanly("Could not register myself in "
+ "serverid.tdb");
+ }
+
smbd_process();
exit:
exit_server_cleanly("end of child");
@@ -665,8 +691,13 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent,
clustered mode, ctdb won't allow us to start doing database
operations until it has gone thru a full startup, which
includes checking to see that smbd is listening. */
- claim_connection(NULL,"",
- FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_DBWRAP);
+
+ if (!serverid_register_self(FLAG_MSG_GENERAL|FLAG_MSG_SMBD
+ |FLAG_MSG_DBWRAP)) {
+ DEBUG(0, ("open_sockets_smbd: Failed to register "
+ "myself in serverid.tdb\n"));
+ return false;
+ }
/* Listen to messages */
@@ -852,8 +883,8 @@ static void exit_server_common(enum server_exit_reason how,
/* 3 second timeout. */
print_notify_send_messages(smbd_messaging_context(), 3);
- /* delete our entry in the connections database. */
- yield_connection(NULL,"");
+ /* delete our entry in the serverid database. */
+ serverid_deregister_self();
#ifdef WITH_DFS
if (dcelogin_atmost_once) {
diff --git a/source3/utils/net.c b/source3/utils/net.c
index 6e39e26434..e19e0fe1c4 100644
--- a/source3/utils/net.c
+++ b/source3/utils/net.c
@@ -719,6 +719,13 @@ static struct functable net_func[] = {
N_(" Use 'net help eventlog' to get more information about "
"'net eventlog' commands.")
},
+ { "serverid",
+ net_serverid,
+ NET_TRANSPORT_LOCAL,
+ N_("Manage the serverid tdb"),
+ N_(" Use 'net help serverid' to get more information about "
+ "'net serverid' commands.")
+ },
#ifdef WITH_FAKE_KASERVER
{ "afs",
diff --git a/source3/utils/net_proto.h b/source3/utils/net_proto.h
index 540d31e6b1..ab8a29731f 100644
--- a/source3/utils/net_proto.h
+++ b/source3/utils/net_proto.h
@@ -427,6 +427,10 @@ int net_usershare(struct net_context *c, int argc, const char **argv);
int net_eventlog(struct net_context *c, int argc, const char **argv);
+/* The following definitions come from utils/net_serverid.c */
+
+int net_serverid(struct net_context *c, int argc, const char **argv);
+
/* The following definitions come from utils/net_util.c */
NTSTATUS net_rpc_lookup_name(struct net_context *c,
diff --git a/source3/utils/net_serverid.c b/source3/utils/net_serverid.c
new file mode 100644
index 0000000000..87974d2460
--- /dev/null
+++ b/source3/utils/net_serverid.c
@@ -0,0 +1,153 @@
+/*
+ Samba Unix/Linux SMB client library
+ net serverid commands
+ Copyright (C) Volker Lendecke 2010
+
+ 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 "utils/net.h"
+
+static int net_serverid_list_fn(const struct server_id *id,
+ uint32_t msg_flags, void *priv)
+{
+ char *str = procid_str(talloc_tos(), id);
+ d_printf("%s %llu 0x%x\n", str, (unsigned long long)id->unique_id,
+ (unsigned int)msg_flags);
+ TALLOC_FREE(str);
+ return 0;
+}
+
+static int net_serverid_list(struct net_context *c, int argc,
+ const char **argv)
+{
+ d_printf("pid unique_id msg_flags\n");
+ return serverid_traverse_read(net_serverid_list_fn, NULL) ? 0 : -1;
+}
+
+static int net_serverid_wipe_fn(struct db_record *rec,
+ const struct server_id *id,
+ uint32_t msg_flags, void *private_data)
+{
+ NTSTATUS status;
+
+#ifdef CLUSTER_SUPPORT
+ if (id->vnn != get_my_vnn()) {
+ return 0;
+ }
+#endif
+ status = rec->delete_rec(rec);
+ if (!NT_STATUS_IS_OK(status)) {
+ char *str = procid_str(talloc_tos(), id);
+ DEBUG(1, ("Could not delete serverid.tdb record %s: %s\n",
+ str, nt_errstr(status)));
+ TALLOC_FREE(str);
+ }
+ return 0;
+}
+
+static int net_serverid_wipe(struct net_context *c, int argc,
+ const char **argv)
+{
+ return serverid_traverse(net_serverid_wipe_fn, NULL) ? 0 : -1;
+}
+
+static int net_serverid_wipedbs_conn(
+ struct db_record *rec,
+ const struct connections_key *key,
+ const struct connections_data *data,
+ void *private_data)
+{
+ if (!serverid_exists(&key->pid)) {
+ NTSTATUS status;
+
+ DEBUG(10, ("Deleting connections.tdb record for pid %s\n",
+ procid_str(talloc_tos(), &key->pid)));
+
+ status = rec->delete_rec(rec);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Could not delete connections.tdb record "
+ "for pid %s: %s\n",
+ procid_str(talloc_tos(), &key->pid),
+ nt_errstr(status)));
+ }
+ }
+ return 0;
+}
+
+static int net_serverid_wipedbs_sessionid(struct db_record *rec,
+ const char *key,
+ struct sessionid *session,
+ void *private_data)
+{
+ if (!serverid_exists(&session->pid)) {
+ NTSTATUS status;
+
+ DEBUG(10, ("Deleting sessionid.tdb record for pid %s\n",
+ procid_str(talloc_tos(), &session->pid)));
+
+ status = rec->delete_rec(rec);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Could not delete session.tdb record "
+ "for pid %s: %s\n",
+ procid_str(talloc_tos(), &session->pid),
+ nt_errstr(status)));
+ }
+ }
+ return 0;
+}
+
+static int net_serverid_wipedbs(struct net_context *c, int argc,
+ const char **argv)
+{
+ connections_forall(net_serverid_wipedbs_conn, NULL);
+ sessionid_traverse(net_serverid_wipedbs_sessionid, NULL);
+ return 0;
+}
+
+int net_serverid(struct net_context *c, int argc, const char **argv)
+{
+ struct functable func[] = {
+ {
+ "list",
+ net_serverid_list,
+ NET_TRANSPORT_LOCAL,
+ N_("List all entries from serverid.tdb"),
+ N_("net serverid list\n"
+ " List all entries from serverid.tdb")
+ },
+ {
+ "wipe",
+ net_serverid_wipe,
+ NET_TRANSPORT_LOCAL,
+ N_("Wipe the serverid.tdb for the current node"),
+ N_("net serverid wipe\n"
+ " Wipe the serverid.tdb for the current node")
+ },
+ {
+ "wipedbs",
+ net_serverid_wipedbs,
+ NET_TRANSPORT_LOCAL,
+ N_("Clean dead entries from connections.tdb and "
+ "sessionid.tdb"),
+ N_("net serverid wipedbs\n"
+ " Clean dead entries from connections.tdb and "
+ "sessionid.tdb")
+ },
+ {NULL, NULL, 0, NULL, NULL}
+ };
+
+ return net_run_function(c, argc, argv, "net serverid", func);
+}
diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c
index 411f079137..afb1ba53fa 100644
--- a/source3/winbindd/winbindd.c
+++ b/source3/winbindd/winbindd.c
@@ -199,6 +199,7 @@ static void terminate(bool is_parent)
#endif
if (is_parent) {
+ serverid_deregister_self();
pidfile_unlink();
}
@@ -1232,7 +1233,11 @@ int main(int argc, char **argv, char **envp)
}
/* get broadcast messages */
- claim_connection(NULL,"",FLAG_MSG_GENERAL|FLAG_MSG_DBWRAP);
+
+ if (!serverid_register_self(FLAG_MSG_GENERAL|FLAG_MSG_DBWRAP)) {
+ DEBUG(1, ("Could not register myself in serverid.tdb\n"));
+ exit(1);
+ }
/* React on 'smbcontrol winbindd reload-config' in the same way
as to SIGHUP signal */
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index ae468436b6..7567eea770 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -40,14 +40,6 @@ void debug_nt_user_token(int dbg_class, int dbg_lev, NT_USER_TOKEN *token);
void debug_unix_user_token(int dbg_class, int dbg_lev, uid_t uid, gid_t gid,
int n_groups, gid_t *groups);
-/* The following definitions come from smbd/connection.c */
-
-bool yield_connection(connection_struct *conn, const char *name);
-int count_current_connections( const char *sharename, bool clear );
-bool claim_connection(connection_struct *conn, const char *name,
- uint32 msg_flags);
-bool register_message_flags(bool doreg, uint32 msg_flags);
-
/* The following definitions come from winbindd/winbindd.c */
struct event_context *winbind_event_context(void);