ldb_tdb: Use braces in ltdb_dn_list_find_val()
[Samba.git] / source3 / lib / serverid.c
blobca4bb27180705321eb3a8ef94a434f6f394bcef5
1 /*
2 Unix SMB/CIFS implementation.
3 Implementation of a reliable server_exists()
4 Copyright (C) Volker Lendecke 2010
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "system/filesys.h"
22 #include "lib/util/server_id.h"
23 #include "serverid.h"
24 #include "util_tdb.h"
25 #include "dbwrap/dbwrap.h"
26 #include "dbwrap/dbwrap_open.h"
27 #include "lib/tdb_wrap/tdb_wrap.h"
28 #include "lib/param/param.h"
29 #include "ctdbd_conn.h"
30 #include "messages.h"
31 #include "lib/messages_ctdb.h"
32 #include "lib/messages_dgm.h"
34 struct serverid_key {
35 pid_t pid;
36 uint32_t task_id;
37 uint32_t vnn;
40 struct serverid_data {
41 uint64_t unique_id;
42 uint32_t msg_flags;
45 static struct db_context *serverid_db(void)
47 static struct db_context *db;
48 char *db_path;
50 if (db != NULL) {
51 return db;
54 db_path = lock_path("serverid.tdb");
55 if (db_path == NULL) {
56 return NULL;
59 db = db_open(NULL, db_path, 0,
60 TDB_DEFAULT|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
61 O_RDWR|O_CREAT, 0644, DBWRAP_LOCK_ORDER_2,
62 DBWRAP_FLAG_NONE);
63 TALLOC_FREE(db_path);
64 return db;
67 bool serverid_parent_init(TALLOC_CTX *mem_ctx)
69 struct db_context *db;
71 db = serverid_db();
72 if (db == NULL) {
73 DEBUG(1, ("could not open serverid.tdb: %s\n",
74 strerror(errno)));
75 return false;
78 return true;
81 static void serverid_fill_key(const struct server_id *id,
82 struct serverid_key *key)
84 ZERO_STRUCTP(key);
85 key->pid = id->pid;
86 key->task_id = id->task_id;
87 key->vnn = id->vnn;
90 bool serverid_register(const struct server_id id, uint32_t msg_flags)
92 struct db_context *db;
93 struct serverid_key key;
94 struct serverid_data data;
95 struct db_record *rec;
96 TDB_DATA tdbkey, tdbdata;
97 NTSTATUS status;
98 bool ret = false;
100 db = serverid_db();
101 if (db == NULL) {
102 return false;
105 serverid_fill_key(&id, &key);
106 tdbkey = make_tdb_data((uint8_t *)&key, sizeof(key));
108 rec = dbwrap_fetch_locked(db, talloc_tos(), tdbkey);
109 if (rec == NULL) {
110 DEBUG(1, ("Could not fetch_lock serverid.tdb record\n"));
111 return false;
114 ZERO_STRUCT(data);
115 data.unique_id = id.unique_id;
116 data.msg_flags = msg_flags;
118 tdbdata = make_tdb_data((uint8_t *)&data, sizeof(data));
119 status = dbwrap_record_store(rec, tdbdata, 0);
120 if (!NT_STATUS_IS_OK(status)) {
121 DEBUG(1, ("Storing serverid.tdb record failed: %s\n",
122 nt_errstr(status)));
123 goto done;
126 if (lp_clustering()) {
127 register_with_ctdbd(messaging_ctdb_connection(), id.unique_id,
128 NULL, NULL);
131 ret = true;
132 done:
133 TALLOC_FREE(rec);
134 return ret;
137 bool serverid_deregister(struct server_id id)
139 struct db_context *db;
140 struct serverid_key key;
141 struct db_record *rec;
142 TDB_DATA tdbkey;
143 NTSTATUS status;
144 bool ret = false;
146 db = serverid_db();
147 if (db == NULL) {
148 return false;
151 serverid_fill_key(&id, &key);
152 tdbkey = make_tdb_data((uint8_t *)&key, sizeof(key));
154 rec = dbwrap_fetch_locked(db, talloc_tos(), tdbkey);
155 if (rec == NULL) {
156 DEBUG(1, ("Could not fetch_lock serverid.tdb record\n"));
157 return false;
160 status = dbwrap_record_delete(rec);
161 if (!NT_STATUS_IS_OK(status)) {
162 DEBUG(1, ("Deleting serverid.tdb record failed: %s\n",
163 nt_errstr(status)));
164 goto done;
166 ret = true;
167 done:
168 TALLOC_FREE(rec);
169 return ret;
172 static bool serverid_exists_local(const struct server_id *id)
174 bool exists = process_exists_by_pid(id->pid);
175 uint64_t unique;
176 int ret;
178 if (!exists) {
179 return false;
182 if (id->unique_id == SERVERID_UNIQUE_ID_NOT_TO_VERIFY) {
183 return true;
186 ret = messaging_dgm_get_unique(id->pid, &unique);
187 if (ret != 0) {
188 return false;
191 return (unique == id->unique_id);
194 bool serverid_exists(const struct server_id *id)
196 if (procid_is_local(id)) {
197 return serverid_exists_local(id);
200 if (lp_clustering()) {
201 return ctdbd_process_exists(messaging_ctdb_connection(),
202 id->vnn, id->pid);
205 return false;
208 static bool serverid_rec_parse(const struct db_record *rec,
209 struct server_id *id, uint32_t *msg_flags)
211 struct serverid_key key;
212 struct serverid_data data;
213 TDB_DATA tdbkey;
214 TDB_DATA tdbdata;
216 tdbkey = dbwrap_record_get_key(rec);
217 tdbdata = dbwrap_record_get_value(rec);
219 if (tdbkey.dsize != sizeof(key)) {
220 DEBUG(1, ("Found invalid key length %d in serverid.tdb\n",
221 (int)tdbkey.dsize));
222 return false;
224 if (tdbdata.dsize != sizeof(data)) {
225 DEBUG(1, ("Found invalid value length %d in serverid.tdb\n",
226 (int)tdbdata.dsize));
227 return false;
230 memcpy(&key, tdbkey.dptr, sizeof(key));
231 memcpy(&data, tdbdata.dptr, sizeof(data));
233 id->pid = key.pid;
234 id->task_id = key.task_id;
235 id->vnn = key.vnn;
236 id->unique_id = data.unique_id;
237 *msg_flags = data.msg_flags;
238 return true;
241 struct serverid_traverse_read_state {
242 int (*fn)(const struct server_id *id, uint32_t msg_flags,
243 void *private_data);
244 void *private_data;
247 static int serverid_traverse_read_fn(struct db_record *rec, void *private_data)
249 struct serverid_traverse_read_state *state =
250 (struct serverid_traverse_read_state *)private_data;
251 struct server_id id;
252 uint32_t msg_flags;
254 if (!serverid_rec_parse(rec, &id, &msg_flags)) {
255 return 0;
257 return state->fn(&id, msg_flags,state->private_data);
260 bool serverid_traverse_read(int (*fn)(const struct server_id *id,
261 uint32_t msg_flags, void *private_data),
262 void *private_data)
264 struct db_context *db;
265 struct serverid_traverse_read_state state;
266 NTSTATUS status;
268 db = serverid_db();
269 if (db == NULL) {
270 return false;
272 state.fn = fn;
273 state.private_data = private_data;
275 status = dbwrap_traverse_read(db, serverid_traverse_read_fn, &state,
276 NULL);
277 return NT_STATUS_IS_OK(status);
280 struct serverid_traverse_state {
281 int (*fn)(struct db_record *rec, const struct server_id *id,
282 uint32_t msg_flags, void *private_data);
283 void *private_data;
286 static int serverid_traverse_fn(struct db_record *rec, void *private_data)
288 struct serverid_traverse_state *state =
289 (struct serverid_traverse_state *)private_data;
290 struct server_id id;
291 uint32_t msg_flags;
293 if (!serverid_rec_parse(rec, &id, &msg_flags)) {
294 return 0;
296 return state->fn(rec, &id, msg_flags, state->private_data);
299 bool serverid_traverse(int (*fn)(struct db_record *rec,
300 const struct server_id *id,
301 uint32_t msg_flags, void *private_data),
302 void *private_data)
304 struct db_context *db;
305 struct serverid_traverse_state state;
306 NTSTATUS status;
308 db = serverid_db();
309 if (db == NULL) {
310 return false;
312 state.fn = fn;
313 state.private_data = private_data;
315 status = dbwrap_traverse(db, serverid_traverse_fn, &state, NULL);
316 return NT_STATUS_IS_OK(status);
319 struct msg_all {
320 struct messaging_context *msg_ctx;
321 int msg_type;
322 uint32_t msg_flag;
323 const void *buf;
324 size_t len;
325 int n_sent;
328 /****************************************************************************
329 Send one of the messages for the broadcast.
330 ****************************************************************************/
332 static int traverse_fn(struct db_record *rec, const struct server_id *id,
333 uint32_t msg_flags, void *state)
335 struct msg_all *msg_all = (struct msg_all *)state;
336 NTSTATUS status;
338 /* Don't send if the receiver hasn't registered an interest. */
340 if((msg_flags & msg_all->msg_flag) == 0) {
341 return 0;
344 /* If the msg send fails because the pid was not found (i.e. smbd died),
345 * the msg has already been deleted from the messages.tdb.*/
347 status = messaging_send_buf(msg_all->msg_ctx, *id, msg_all->msg_type,
348 (const uint8_t *)msg_all->buf, msg_all->len);
350 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
351 struct server_id_buf idbuf;
354 * If the pid was not found delete the entry from
355 * serverid.tdb
358 DEBUG(2, ("pid %s doesn't exist\n",
359 server_id_str_buf(*id, &idbuf)));
361 dbwrap_record_delete(rec);
363 msg_all->n_sent++;
364 return 0;
368 * Send a message to all smbd processes.
370 * It isn't very efficient, but should be OK for the sorts of
371 * applications that use it. When we need efficient broadcast we can add
372 * it.
374 * @param n_sent Set to the number of messages sent. This should be
375 * equal to the number of processes, but be careful for races.
377 * @retval True for success.
379 bool message_send_all(struct messaging_context *msg_ctx,
380 int msg_type,
381 const void *buf, size_t len,
382 int *n_sent)
384 struct msg_all msg_all;
386 msg_all.msg_type = msg_type;
387 if (msg_type < 0x100) {
388 msg_all.msg_flag = FLAG_MSG_GENERAL;
389 } else if (msg_type > 0x100 && msg_type < 0x200) {
390 msg_all.msg_flag = FLAG_MSG_NMBD;
391 } else if (msg_type > 0x200 && msg_type < 0x300) {
392 msg_all.msg_flag = FLAG_MSG_PRINT_GENERAL;
393 } else if (msg_type > 0x300 && msg_type < 0x400) {
394 msg_all.msg_flag = FLAG_MSG_SMBD;
395 } else if (msg_type > 0x400 && msg_type < 0x600) {
396 msg_all.msg_flag = FLAG_MSG_WINBIND;
397 } else if (msg_type > 4000 && msg_type < 5000) {
398 msg_all.msg_flag = FLAG_MSG_DBWRAP;
399 } else {
400 return false;
403 msg_all.buf = buf;
404 msg_all.len = len;
405 msg_all.n_sent = 0;
406 msg_all.msg_ctx = msg_ctx;
408 serverid_traverse(traverse_fn, &msg_all);
409 if (n_sent)
410 *n_sent = msg_all.n_sent;
411 return true;