diff options
-rw-r--r-- | source3/Makefile.in | 7 | ||||
-rw-r--r-- | source3/include/includes.h | 1 | ||||
-rw-r--r-- | source3/include/messages.h | 1 | ||||
-rw-r--r-- | source3/include/proto.h | 1 | ||||
-rw-r--r-- | source3/include/serverid.h | 66 | ||||
-rw-r--r-- | source3/lib/messages.c | 21 | ||||
-rw-r--r-- | source3/lib/serverid.c | 293 | ||||
-rw-r--r-- | source3/lib/util.c | 9 | ||||
-rw-r--r-- | source3/locking/brlock.c | 2 | ||||
-rw-r--r-- | source3/locking/locking.c | 2 | ||||
-rw-r--r-- | source3/nmbd/nmbd.c | 7 | ||||
-rw-r--r-- | source3/printing/nt_printing.c | 2 | ||||
-rw-r--r-- | source3/printing/printing.c | 6 | ||||
-rw-r--r-- | source3/smbd/negprot.c | 4 | ||||
-rw-r--r-- | source3/smbd/server.c | 39 | ||||
-rw-r--r-- | source3/utils/net.c | 7 | ||||
-rw-r--r-- | source3/utils/net_proto.h | 4 | ||||
-rw-r--r-- | source3/utils/net_serverid.c | 153 | ||||
-rw-r--r-- | source3/winbindd/winbindd.c | 7 | ||||
-rw-r--r-- | source3/winbindd/winbindd_proto.h | 8 |
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); |