diff options
author | Karolin Seeger <kseeger@samba.org> | 2008-02-29 10:44:38 +0100 |
---|---|---|
committer | Karolin Seeger <kseeger@samba.org> | 2008-02-29 10:44:38 +0100 |
commit | c4fbe2846231a6b322c1094c6a1dbf93b7305768 (patch) | |
tree | 09eb77a294f4acda131b41fe4c9bec4ed175eb16 /source3/lib | |
parent | 1a6415fc77c708b87c8e2ce6e7828f486ffc87ac (diff) | |
parent | 695b6662abe64a40061bfa05ede12173fc4b1945 (diff) | |
download | samba-c4fbe2846231a6b322c1094c6a1dbf93b7305768.tar.gz samba-c4fbe2846231a6b322c1094c6a1dbf93b7305768.tar.bz2 samba-c4fbe2846231a6b322c1094c6a1dbf93b7305768.zip |
Merge commit 'origin/v3-2-test' into v3-2-stable
Conflicts:
WHATSNEW.txt
(This used to be commit a390bcf9403df4cf4d5eef42b35ebccbe253882e)
Diffstat (limited to 'source3/lib')
81 files changed, 2481 insertions, 1616 deletions
diff --git a/source3/lib/afs.c b/source3/lib/afs.c index a7d6f6c9f7..9f5d81f442 100644 --- a/source3/lib/afs.c +++ b/source3/lib/afs.c @@ -42,20 +42,23 @@ static char *afs_encode_token(const char *cell, const DATA_BLOB ticket, const struct ClearToken *ct) { char *base64_ticket; - char *result; + char *result = NULL; DATA_BLOB key = data_blob(ct->HandShakeKey, 8); char *base64_key; + TALLOC_CTX *mem_ctx; + + mem_ctx = talloc_stackframe(); + if (mem_ctx == NULL) + goto done; - base64_ticket = base64_encode_data_blob(ticket); + base64_ticket = base64_encode_data_blob(mem_ctx, ticket); if (base64_ticket == NULL) - return NULL; + goto done; - base64_key = base64_encode_data_blob(key); - if (base64_key == NULL) { - TALLOC_FREE(base64_ticket); - return NULL; - } + base64_key = base64_encode_data_blob(mem_ctx, key); + if (base64_key == NULL) + goto done; asprintf(&result, "%s\n%u\n%s\n%u\n%u\n%u\n%s\n", cell, ct->AuthHandle, base64_key, ct->ViceId, ct->BeginTimestamp, @@ -63,8 +66,8 @@ static char *afs_encode_token(const char *cell, const DATA_BLOB ticket, DEBUG(10, ("Got ticket string:\n%s\n", result)); - TALLOC_FREE(base64_ticket); - TALLOC_FREE(base64_key); +done: + TALLOC_FREE(mem_ctx); return result; } diff --git a/source3/lib/afs_settoken.c b/source3/lib/afs_settoken.c index aeef1c3520..444f09efca 100644 --- a/source3/lib/afs_settoken.c +++ b/source3/lib/afs_settoken.c @@ -53,20 +53,21 @@ static bool afs_decode_token(const char *string, char **cell, { DATA_BLOB blob; struct ClearToken result_ct; + char *saveptr; char *s = SMB_STRDUP(string); char *t; - if ((t = strtok(s, "\n")) == NULL) { - DEBUG(10, ("strtok failed\n")); + if ((t = strtok_r(s, "\n", &saveptr)) == NULL) { + DEBUG(10, ("strtok_r failed\n")); return False; } *cell = SMB_STRDUP(t); - if ((t = strtok(NULL, "\n")) == NULL) { - DEBUG(10, ("strtok failed\n")); + if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) { + DEBUG(10, ("strtok_r failed\n")); return False; } @@ -75,8 +76,8 @@ static bool afs_decode_token(const char *string, char **cell, return False; } - if ((t = strtok(NULL, "\n")) == NULL) { - DEBUG(10, ("strtok failed\n")); + if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) { + DEBUG(10, ("strtok_r failed\n")); return False; } @@ -93,8 +94,8 @@ static bool afs_decode_token(const char *string, char **cell, data_blob_free(&blob); - if ((t = strtok(NULL, "\n")) == NULL) { - DEBUG(10, ("strtok failed\n")); + if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) { + DEBUG(10, ("strtok_r failed\n")); return False; } @@ -103,8 +104,8 @@ static bool afs_decode_token(const char *string, char **cell, return False; } - if ((t = strtok(NULL, "\n")) == NULL) { - DEBUG(10, ("strtok failed\n")); + if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) { + DEBUG(10, ("strtok_r failed\n")); return False; } @@ -113,8 +114,8 @@ static bool afs_decode_token(const char *string, char **cell, return False; } - if ((t = strtok(NULL, "\n")) == NULL) { - DEBUG(10, ("strtok failed\n")); + if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) { + DEBUG(10, ("strtok_r failed\n")); return False; } @@ -123,8 +124,8 @@ static bool afs_decode_token(const char *string, char **cell, return False; } - if ((t = strtok(NULL, "\n")) == NULL) { - DEBUG(10, ("strtok failed\n")); + if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) { + DEBUG(10, ("strtok_r failed\n")); return False; } diff --git a/source3/lib/async_req.c b/source3/lib/async_req.c new file mode 100644 index 0000000000..01154ca436 --- /dev/null +++ b/source3/lib/async_req.c @@ -0,0 +1,68 @@ +/* + Unix SMB/CIFS implementation. + Infrastructure for async requests + Copyright (C) Volker Lendecke 2008 + + 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" + +char *async_req_print(TALLOC_CTX *mem_ctx, struct async_req *req) +{ + return talloc_asprintf(mem_ctx, "async_req: state=%d, status=%s, " + "priv=%s", req->state, nt_errstr(req->status), + talloc_get_name(req->private_data)); +} + +struct async_req *async_req_new(TALLOC_CTX *mem_ctx, struct event_context *ev) +{ + struct async_req *result; + + result = TALLOC_ZERO_P(mem_ctx, struct async_req); + if (result == NULL) { + return NULL; + } + result->state = ASYNC_REQ_IN_PROGRESS; + result->event_ctx = ev; + result->print = async_req_print; + return result; +} + +void async_req_done(struct async_req *req) +{ + req->status = NT_STATUS_OK; + req->state = ASYNC_REQ_DONE; + if (req->async.fn != NULL) { + req->async.fn(req); + } +} + +void async_req_error(struct async_req *req, NTSTATUS status) +{ + req->status = status; + req->state = ASYNC_REQ_ERROR; + if (req->async.fn != NULL) { + req->async.fn(req); + } +} + +bool async_req_nomem(const void *p, struct async_req *req) +{ + if (p != NULL) { + return false; + } + async_req_error(req, NT_STATUS_NO_MEMORY); + return true; +} diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index eeff805459..d11620ecd7 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -524,7 +524,7 @@ size_t convert_string(charset_t from, charset_t to, size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, void const *src, size_t srclen, void *dst, bool allow_bad_conv) { - size_t i_len, o_len, destlen = MAX(srclen, 512); + size_t i_len, o_len, destlen = (srclen * 3) / 2; size_t retval; const char *inbuf = (const char *)src; char *outbuf = NULL, *ob = NULL; @@ -550,7 +550,8 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, convert: - if ((destlen*2) < destlen) { + /* +2 is for ucs2 null termination. */ + if ((destlen*2)+2 < destlen) { /* wrapped ! abort. */ if (!conv_silent) DEBUG(0, ("convert_string_allocate: destlen wrapped !\n")); @@ -561,10 +562,11 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, destlen = destlen * 2; } + /* +2 is for ucs2 null termination. */ if (ctx) { - ob = (char *)TALLOC_REALLOC(ctx, ob, destlen); + ob = (char *)TALLOC_REALLOC(ctx, ob, destlen + 2); } else { - ob = (char *)SMB_REALLOC(ob, destlen); + ob = (char *)SMB_REALLOC(ob, destlen + 2); } if (!ob) { @@ -619,10 +621,11 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, * reallocs *cost*. JRA. */ if (o_len > 1024) { + /* We're shrinking here so we know the +2 is safe from wrap. */ if (ctx) { - ob = (char *)TALLOC_REALLOC(ctx,ob,destlen); + ob = (char *)TALLOC_REALLOC(ctx,ob,destlen + 2); } else { - ob = (char *)SMB_REALLOC(ob,destlen); + ob = (char *)SMB_REALLOC(ob,destlen + 2); } } @@ -632,6 +635,11 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, } *dest = ob; + + /* Must ucs2 null terminate in the extra space we allocated. */ + ob[destlen] = '\0'; + ob[destlen+1] = '\0'; + return destlen; use_as_is: diff --git a/source3/lib/conn_tdb.c b/source3/lib/conn_tdb.c index dd0a354a85..22d85c873d 100644 --- a/source3/lib/conn_tdb.c +++ b/source3/lib/conn_tdb.c @@ -34,7 +34,7 @@ static struct db_context *connections_db_ctx(bool rw) } else { db_ctx = db_open(NULL, lock_path("connections.tdb"), 0, - TDB_DEFAULT, O_RDONLY, 0); + TDB_CLEAR_IF_FIRST|TDB_DEFAULT, O_RDONLY, 0); } return db_ctx; diff --git a/source3/lib/ctdbd_conn.c b/source3/lib/ctdbd_conn.c index 899bbcfcce..18e9879601 100644 --- a/source3/lib/ctdbd_conn.c +++ b/source3/lib/ctdbd_conn.c @@ -1203,6 +1203,42 @@ NTSTATUS ctdbd_register_reconfigure(struct ctdbd_connection *conn) return register_with_ctdbd(conn, CTDB_SRVID_RECONFIGURE); } +/* + persstent store. Used when we update a record in a persistent database + */ +NTSTATUS ctdbd_persistent_store(struct ctdbd_connection *conn, uint32_t db_id, TDB_DATA key, TDB_DATA data) +{ + int cstatus=0; + struct ctdb_rec_data *rec; + TDB_DATA recdata; + size_t length; + NTSTATUS status; + + length = offsetof(struct ctdb_rec_data, data) + key.dsize + data.dsize; + + rec = (struct ctdb_rec_data *)talloc_size(conn, length); + NT_STATUS_HAVE_NO_MEMORY(rec); + + rec->length = length; + rec->reqid = db_id; + rec->keylen = key.dsize; + rec->datalen= data.dsize; + memcpy(&rec->data[0], key.dptr, key.dsize); + memcpy(&rec->data[key.dsize], data.dptr, data.dsize); + + recdata.dptr = (uint8_t *)rec; + recdata.dsize = length; + + status = ctdbd_control(conn, CTDB_CURRENT_NODE, + CTDB_CONTROL_PERSISTENT_STORE, + 0, recdata, NULL, NULL, &cstatus); + if (cstatus != 0) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + return status; +} + + #else NTSTATUS ctdbd_init_connection(TALLOC_CTX *mem_ctx, diff --git a/source3/lib/data_blob.c b/source3/lib/data_blob.c index 8bbbc32d7b..daba17df14 100644 --- a/source3/lib/data_blob.c +++ b/source3/lib/data_blob.c @@ -144,3 +144,15 @@ DATA_BLOB data_blob_const(const void *p, size_t length) blob.free = NULL; return blob; } + +/** + construct a zero data blob, using supplied TALLOC_CTX. + use this sparingly as it initialises data - better to initialise + yourself if you want specific data in the blob +**/ +DATA_BLOB data_blob_talloc_zero(TALLOC_CTX *mem_ctx, size_t length) +{ + DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, length); + data_blob_clear(&blob); + return blob; +} diff --git a/source3/lib/dbwrap.c b/source3/lib/dbwrap.c index 4e16d18682..001424a6c0 100644 --- a/source3/lib/dbwrap.c +++ b/source3/lib/dbwrap.c @@ -20,7 +20,9 @@ */ #include "includes.h" - +#ifdef CLUSTER_SUPPORT +#include "ctdb_private.h" +#endif /* * Fall back using fetch_locked if no genuine fetch operation is provided */ @@ -46,10 +48,16 @@ struct db_context *db_open(TALLOC_CTX *mem_ctx, int open_flags, mode_t mode) { struct db_context *result = NULL; +#ifdef CLUSTER_SUPPORT + const char *sockname = lp_ctdbd_socket(); +#endif #ifdef CLUSTER_SUPPORT + if(!sockname || !*sockname) { + sockname = CTDB_PATH; + } - if (lp_clustering()) { + if (lp_clustering() && socket_exist(sockname)) { const char *partname; /* ctdb only wants the file part of the name */ partname = strrchr(name, '/'); diff --git a/source3/lib/dbwrap_ctdb.c b/source3/lib/dbwrap_ctdb.c index 90d0b260c5..f497f871d2 100644 --- a/source3/lib/dbwrap_ctdb.c +++ b/source3/lib/dbwrap_ctdb.c @@ -18,16 +18,14 @@ */ #include "includes.h" - #ifdef CLUSTER_SUPPORT - #include "ctdb.h" #include "ctdb_private.h" +#include "ctdbd_conn.h" struct db_ctdb_ctx { struct tdb_wrap *wtdb; uint32 db_id; - struct ctdbd_connection *conn; }; struct db_ctdb_rec { @@ -35,8 +33,6 @@ struct db_ctdb_rec { struct ctdb_ltdb_header header; }; -static struct ctdbd_connection *db_ctdbd_conn(struct db_ctdb_ctx *ctx); - static NTSTATUS db_ctdb_store(struct db_record *rec, TDB_DATA data, int flag) { struct db_ctdb_rec *crec = talloc_get_type_abort( @@ -60,6 +56,42 @@ static NTSTATUS db_ctdb_store(struct db_record *rec, TDB_DATA data, int flag) return (ret == 0) ? NT_STATUS_OK : NT_STATUS_INTERNAL_DB_CORRUPTION; } + +/* for persistent databases the store is a bit different. We have to + ask the ctdb daemon to push the record to all nodes after the + store */ +static NTSTATUS db_ctdb_store_persistent(struct db_record *rec, TDB_DATA data, int flag) +{ + struct db_ctdb_rec *crec = talloc_get_type_abort( + rec->private_data, struct db_ctdb_rec); + TDB_DATA cdata; + int ret; + NTSTATUS status; + + cdata.dsize = sizeof(crec->header) + data.dsize; + + if (!(cdata.dptr = SMB_MALLOC_ARRAY(uint8, cdata.dsize))) { + return NT_STATUS_NO_MEMORY; + } + + crec->header.rsn++; + + memcpy(cdata.dptr, &crec->header, sizeof(crec->header)); + memcpy(cdata.dptr + sizeof(crec->header), data.dptr, data.dsize); + + ret = tdb_store(crec->ctdb_ctx->wtdb->tdb, rec->key, cdata, TDB_REPLACE); + status = (ret == 0) ? NT_STATUS_OK : NT_STATUS_INTERNAL_DB_CORRUPTION; + + /* now tell ctdbd to update this record on all other nodes */ + if (NT_STATUS_IS_OK(status)) { + status = ctdbd_persistent_store(messaging_ctdbd_connection(), crec->ctdb_ctx->db_id, rec->key, cdata); + } + + SAFE_FREE(cdata.dptr); + + return status; +} + static NTSTATUS db_ctdb_delete(struct db_record *rec) { struct db_ctdb_rec *crec = talloc_get_type_abort( @@ -110,6 +142,7 @@ static struct db_record *db_ctdb_fetch_locked(struct db_context *db, struct db_ctdb_rec *crec; NTSTATUS status; TDB_DATA ctdb_data; + int migrate_attempts = 0; if (!(result = talloc(mem_ctx, struct db_record))) { DEBUG(0, ("talloc failed\n")); @@ -153,7 +186,11 @@ again: return NULL; } - result->store = db_ctdb_store; + if (db->persistent) { + result->store = db_ctdb_store_persistent; + } else { + result->store = db_ctdb_store; + } result->delete_rec = db_ctdb_delete; talloc_set_destructor(result, db_ctdb_record_destr); @@ -175,12 +212,14 @@ again: tdb_chainunlock(ctx->wtdb->tdb, key); talloc_set_destructor(result, NULL); + migrate_attempts += 1; + DEBUG(10, ("ctdb_data.dptr = %p, dmaster = %u (%u)\n", ctdb_data.dptr, ctdb_data.dptr ? ((struct ctdb_ltdb_header *)ctdb_data.dptr)->dmaster : -1, get_my_vnn())); - status = ctdbd_migrate(db_ctdbd_conn(ctx), ctx->db_id, key); + status = ctdbd_migrate(messaging_ctdbd_connection(),ctx->db_id, key); if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("ctdb_migrate failed: %s\n", nt_errstr(status))); @@ -191,6 +230,11 @@ again: goto again; } + if (migrate_attempts > 10) { + DEBUG(0, ("db_ctdb_fetch_locked needed %d attempts\n", + migrate_attempts)); + } + memcpy(&crec->header, ctdb_data.dptr, sizeof(crec->header)); result->value.dsize = ctdb_data.dsize - sizeof(crec->header); @@ -226,10 +270,12 @@ static int db_ctdb_fetch(struct db_context *db, TALLOC_CTX *mem_ctx, /* * See if we have a valid record and we are the dmaster. If so, we can * take the shortcut and just return it. + * we bypass the dmaster check for persistent databases */ if ((ctdb_data.dptr != NULL) && (ctdb_data.dsize >= sizeof(struct ctdb_ltdb_header)) && - ((struct ctdb_ltdb_header *)ctdb_data.dptr)->dmaster == get_my_vnn()) { + (db->persistent || + ((struct ctdb_ltdb_header *)ctdb_data.dptr)->dmaster == get_my_vnn())) { /* we are the dmaster - avoid the ctdb protocol op */ data->dsize = ctdb_data.dsize - sizeof(struct ctdb_ltdb_header); @@ -254,8 +300,7 @@ static int db_ctdb_fetch(struct db_context *db, TALLOC_CTX *mem_ctx, SAFE_FREE(ctdb_data.dptr); /* we weren't able to get it locally - ask ctdb to fetch it for us */ - status = ctdbd_fetch(db_ctdbd_conn(ctx), ctx->db_id, key, mem_ctx, - data); + status = ctdbd_fetch(messaging_ctdbd_connection(),ctx->db_id, key, mem_ctx, data); if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("ctdbd_fetch failed: %s\n", nt_errstr(status))); return -1; @@ -283,6 +328,22 @@ static void traverse_callback(TDB_DATA key, TDB_DATA data, void *private_data) talloc_free(tmp_ctx); } +static int traverse_persistent_callback(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, + void *private_data) +{ + struct traverse_state *state = (struct traverse_state *)private_data; + struct db_record *rec; + TALLOC_CTX *tmp_ctx = talloc_new(state->db); + int ret = 0; + /* we have to give them a locked record to prevent races */ + rec = db_ctdb_fetch_locked(state->db, tmp_ctx, kbuf); + if (rec && rec->value.dsize > 0) { + ret = state->fn(rec, state->private_data); + } + talloc_free(tmp_ctx); + return ret; +} + static int db_ctdb_traverse(struct db_context *db, int (*fn)(struct db_record *rec, void *private_data), @@ -296,6 +357,13 @@ static int db_ctdb_traverse(struct db_context *db, state.fn = fn; state.private_data = private_data; + if (db->persistent) { + /* for persistent databases we don't need to do a ctdb traverse, + we can do a faster local traverse */ + return tdb_traverse(ctx->wtdb->tdb, traverse_persistent_callback, &state); + } + + ctdbd_traverse(ctx->db_id, traverse_callback, &state); return 0; } @@ -322,6 +390,27 @@ static void traverse_read_callback(TDB_DATA key, TDB_DATA data, void *private_da state->fn(&rec, state->private_data); } +static int traverse_persistent_callback_read(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, + void *private_data) +{ + struct traverse_state *state = (struct traverse_state *)private_data; + struct db_record rec; + rec.key = kbuf; + rec.value = dbuf; + rec.store = db_ctdb_store_deny; + rec.delete_rec = db_ctdb_delete_deny; + rec.private_data = state->db; + + if (rec.value.dsize <= sizeof(struct ctdb_ltdb_header)) { + /* a deleted record */ + return 0; + } + rec.value.dsize -= sizeof(struct ctdb_ltdb_header); + rec.value.dptr += sizeof(struct ctdb_ltdb_header); + + return state->fn(&rec, state->private_data); +} + static int db_ctdb_traverse_read(struct db_context *db, int (*fn)(struct db_record *rec, void *private_data), @@ -335,6 +424,12 @@ static int db_ctdb_traverse_read(struct db_context *db, state.fn = fn; state.private_data = private_data; + if (db->persistent) { + /* for persistent databases we don't need to do a ctdb traverse, + we can do a faster local traverse */ + return tdb_traverse_read(ctx->wtdb->tdb, traverse_persistent_callback_read, &state); + } + ctdbd_traverse(ctx->db_id, traverse_read_callback, &state); return 0; } @@ -346,41 +441,6 @@ static int db_ctdb_get_seqnum(struct db_context *db) return tdb_get_seqnum(ctx->wtdb->tdb); } -/* - * Get the ctdbd connection for a database. If possible, re-use the messaging - * ctdbd connection - */ -static struct ctdbd_connection *db_ctdbd_conn(struct db_ctdb_ctx *ctx) -{ - struct ctdbd_connection *result; - - result = messaging_ctdbd_connection(); - - if (result != NULL) { - - if (ctx->conn == NULL) { - /* - * Someone has initialized messaging since we - * initialized our own connection, we don't need it - * anymore. - */ - TALLOC_FREE(ctx->conn); - } - - return result; - } - - if (ctx->conn == NULL) { - NTSTATUS status; - status = ctdbd_init_connection(ctx, &ctx->conn); - if (!NT_STATUS_IS_OK(status)) { - return NULL; - } - set_my_vnn(ctdbd_vnn(ctx->conn)); - } - - return ctx->conn; -} struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx, const char *name, @@ -390,7 +450,6 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx, struct db_context *result; struct db_ctdb_ctx *db_ctdb; char *db_path; - NTSTATUS status; if (!lp_clustering()) { DEBUG(10, ("Clustering disabled -- no ctdb\n")); @@ -409,20 +468,15 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx, return NULL; } - db_ctdb->conn = NULL; - - status = ctdbd_db_attach(db_ctdbd_conn(db_ctdb), name, - &db_ctdb->db_id, tdb_flags); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("ctdbd_db_attach failed for %s: %s\n", name, - nt_errstr(status))); + if (!NT_STATUS_IS_OK(ctdbd_db_attach(messaging_ctdbd_connection(),name, &db_ctdb->db_id, tdb_flags))) { + DEBUG(0, ("ctdbd_db_attach failed for %s\n", name)); TALLOC_FREE(result); return NULL; } - db_path = ctdbd_dbpath(db_ctdbd_conn(db_ctdb), db_ctdb, - db_ctdb->db_id); + db_path = ctdbd_dbpath(messaging_ctdbd_connection(), db_ctdb, db_ctdb->db_id); + + result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0); /* only pass through specific flags */ tdb_flags &= TDB_SEQNUM; @@ -447,16 +501,4 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx, return result; } - -#else - -struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx, - const char *name, - int hash_size, int tdb_flags, - int open_flags, mode_t mode) -{ - DEBUG(0, ("no clustering compiled in\n")); - return NULL; -} - #endif diff --git a/source3/lib/dbwrap_file.c b/source3/lib/dbwrap_file.c index 5b41f5941b..e3779de1e4 100644 --- a/source3/lib/dbwrap_file.c +++ b/source3/lib/dbwrap_file.c @@ -17,10 +17,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* - * Be aware that this is just sample code that has not seen too much testing - */ - #include "includes.h" struct db_file_ctx { @@ -367,6 +363,7 @@ struct db_context *db_open_file(TALLOC_CTX *mem_ctx, result->fetch_locked = db_file_fetch_locked; result->traverse = db_file_traverse; result->traverse_read = db_file_traverse; + result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0); ctx->locked_record = NULL; if (!(ctx->dirname = talloc_strdup(ctx, name))) { diff --git a/source3/lib/dbwrap_tdb.c b/source3/lib/dbwrap_tdb.c index 710e45de6b..da55049e52 100644 --- a/source3/lib/dbwrap_tdb.c +++ b/source3/lib/dbwrap_tdb.c @@ -31,6 +31,11 @@ static int db_tdb_record_destr(struct db_record* data) struct db_tdb_ctx *ctx = talloc_get_type_abort(data->private_data, struct db_tdb_ctx); + /* This hex_encode() call allocates memory on data context. By way how current + __talloc_free() code works, it is OK to allocate in the destructor as + the children of data will be freed after call to the destructor and this + new 'child' will be caught and freed correctly. + */ DEBUG(10, (DEBUGLEVEL > 10 ? "Unlocking key %s\n" : "Unlocking key %.20s\n", hex_encode(data, (unsigned char *)data->key.dptr, @@ -86,10 +91,10 @@ static struct db_record *db_tdb_fetch_locked(struct db_context *db, struct db_tdb_ctx *ctx = talloc_get_type_abort(db->private_data, struct db_tdb_ctx); struct tdb_fetch_locked_state state; - int res; - if (DEBUGLEVEL >= 10) { - char *keystr = hex_encode(NULL, key.dptr, key.dsize); + /* Do not accidently allocate/deallocate w/o need when debug level is lower than needed */ + if(DEBUGLEVEL >= 10) { + char *keystr = hex_encode(NULL, (unsigned char*)key.dptr, key.dsize); DEBUG(10, (DEBUGLEVEL > 10 ? "Locking key %s\n" : "Locking key %.20s\n", keystr)); @@ -104,8 +109,7 @@ static struct db_record *db_tdb_fetch_locked(struct db_context *db, state.mem_ctx = mem_ctx; state.result = NULL; - res = tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetchlock_parse, - &state); + tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetchlock_parse, &state); if (state.result == NULL) { db_tdb_fetchlock_parse(key, tdb_null, &state); @@ -191,15 +195,16 @@ static NTSTATUS db_tdb_delete(struct db_record *rec) { struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data, struct db_tdb_ctx); - int res; - - res = tdb_delete(ctx->wtdb->tdb, rec->key); - if (res == 0) { + if (tdb_delete(ctx->wtdb->tdb, rec->key) == 0) { return NT_STATUS_OK; } - return map_nt_error_from_tdb(tdb_error(ctx->wtdb->tdb)); + if (tdb_error(ctx->wtdb->tdb) == TDB_ERR_NOEXIST) { + return NT_STATUS_NOT_FOUND; + } + + return NT_STATUS_UNSUCCESSFUL; } struct db_tdb_traverse_ctx { @@ -318,6 +323,7 @@ struct db_context *db_open_tdb(TALLOC_CTX *mem_ctx, result->traverse = db_tdb_traverse; result->traverse_read = db_tdb_traverse_read; result->get_seqnum = db_tdb_get_seqnum; + result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0); return result; fail: diff --git a/source3/lib/dbwrap_util.c b/source3/lib/dbwrap_util.c new file mode 100644 index 0000000000..002d572019 --- /dev/null +++ b/source3/lib/dbwrap_util.c @@ -0,0 +1,90 @@ +/* + Unix SMB/CIFS implementation. + Utility functions for the dbwrap API + Copyright (C) Volker Lendecke 2007 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +int32_t dbwrap_fetch_int32(struct db_context *db, const char *keystr) +{ + TDB_DATA dbuf; + int32 ret; + + if (db->fetch(db, NULL, string_term_tdb_data(keystr), &dbuf) != 0) { + return -1; + } + + if ((dbuf.dptr == NULL) || (dbuf.dsize != sizeof(int32_t))) { + TALLOC_FREE(dbuf.dptr); + return -1; + } + + ret = IVAL(dbuf.dptr, 0); + TALLOC_FREE(dbuf.dptr); + return ret; +} + +int dbwrap_store_int32(struct db_context *db, const char *keystr, int32_t v) +{ + struct db_record *rec; + int32 v_store; + NTSTATUS status; + + rec = db->fetch_locked(db, NULL, string_term_tdb_data(keystr)); + if (rec == NULL) { + return -1; + } + + SIVAL(&v_store, 0, v); + + status = rec->store(rec, make_tdb_data((const uint8 *)&v_store, + sizeof(v_store)), + TDB_REPLACE); + TALLOC_FREE(rec); + return NT_STATUS_IS_OK(status) ? 0 : -1; +} + +uint32_t dbwrap_change_uint32_atomic(struct db_context *db, const char *keystr, + uint32_t *oldval, uint32_t change_val) +{ + struct db_record *rec; + uint32 val = -1; + TDB_DATA data; + + if (!(rec = db->fetch_locked(db, NULL, + string_term_tdb_data(keystr)))) { + return -1; + } + + if ((rec->value.dptr != NULL) + && (rec->value.dsize == sizeof(val))) { + val = IVAL(rec->value.dptr, 0); + } + + val += change_val; + + data.dsize = sizeof(val); + data.dptr = (uint8 *)&val; + + rec->store(rec, data, TDB_REPLACE); + + TALLOC_FREE(rec); + + return 0; +} + diff --git a/source3/lib/debug.c b/source3/lib/debug.c index 6c1bfea04f..c4a0d1b47b 100644 --- a/source3/lib/debug.c +++ b/source3/lib/debug.c @@ -429,8 +429,9 @@ static bool debug_parse_params(char **params) /* Fill in new debug class levels */ for (; i < debug_num_classes && params[i]; i++) { - if ((class_name=strtok(params[i],":")) && - (class_level=strtok(NULL, "\0")) && + char *saveptr; + if ((class_name = strtok_r(params[i],":", &saveptr)) && + (class_level = strtok_r(NULL, "\0", &saveptr)) && ((ndx = debug_lookup_classname(class_name)) != -1)) { DEBUGLEVEL_CLASS[ndx] = atoi(class_level); DEBUGLEVEL_CLASS_ISSET[ndx] = True; @@ -459,14 +460,14 @@ bool debug_parse_levels(const char *params_str) if (AllowDebugChange == False) return True; - params = str_list_make(params_str, NULL); + params = str_list_make(talloc_tos(), params_str, NULL); if (debug_parse_params(params)) { debug_dump_status(5); - str_list_free(¶ms); + TALLOC_FREE(params); return True; } else { - str_list_free(¶ms); + TALLOC_FREE(params); return False; } } @@ -826,6 +827,7 @@ void check_log_size( void ) }; int priority; char *msgbuf = NULL; + int ret; if( syslog_level >= ( sizeof(priority_map) / sizeof(priority_map[0]) ) || syslog_level < 0) priority = LOG_DEBUG; @@ -833,10 +835,10 @@ void check_log_size( void ) priority = priority_map[syslog_level]; va_start(ap, format_str); - vasprintf(&msgbuf, format_str, ap); + ret = vasprintf(&msgbuf, format_str, ap); va_end(ap); - if (msgbuf) { + if (ret == -1) { syslog(priority, "%s", msgbuf); } SAFE_FREE(msgbuf); @@ -1058,12 +1060,13 @@ bool dbghdr(int level, int cls, const char *file, const char *func, int line) va_list ap; char *msgbuf = NULL; bool ret = true; + int res; va_start(ap, format_str); - vasprintf(&msgbuf, format_str, ap); + res = vasprintf(&msgbuf, format_str, ap); va_end(ap); - if (msgbuf) { + if (res != -1) { format_debug_text(msgbuf); } else { ret = false; diff --git a/source3/lib/display_dsdcinfo.c b/source3/lib/display_dsdcinfo.c deleted file mode 100644 index dcb05297a1..0000000000 --- a/source3/lib/display_dsdcinfo.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Copyright (C) Guenther Deschner 2007 - - 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" - -/**************************************************************** -****************************************************************/ - -void display_ds_domain_controller_info(TALLOC_CTX *mem_ctx, - const struct DS_DOMAIN_CONTROLLER_INFO *info) -{ - d_printf("domain_controller_name: %s\n", - info->domain_controller_name); - d_printf("domain_controller_address: %s\n", - info->domain_controller_address); - d_printf("domain_controller_address_type: %d\n", - info->domain_controller_address_type); - d_printf("domain_guid: %s\n", - GUID_string(mem_ctx, info->domain_guid)); - d_printf("domain_name: %s\n", - info->domain_name); - d_printf("dns_forest_name: %s\n", - info->dns_forest_name); - - d_printf("flags: 0x%08x\n" - "\tIs a PDC: %s\n" - "\tIs a GC of the forest: %s\n" - "\tIs an LDAP server: %s\n" - "\tSupports DS: %s\n" - "\tIs running a KDC: %s\n" - "\tIs running time services: %s\n" - "\tIs the closest DC: %s\n" - "\tIs writable: %s\n" - "\tHas a hardware clock: %s\n" - "\tIs a non-domain NC serviced by LDAP server: %s\n" - "\tDomainControllerName is a DNS name: %s\n" - "\tDomainName is a DNS name: %s\n" - "\tDnsForestName is a DNS name: %s\n", - info->flags, - (info->flags & ADS_PDC) ? "yes" : "no", - (info->flags & ADS_GC) ? "yes" : "no", - (info->flags & ADS_LDAP) ? "yes" : "no", - (info->flags & ADS_DS) ? "yes" : "no", - (info->flags & ADS_KDC) ? "yes" : "no", - (info->flags & ADS_TIMESERV) ? "yes" : "no", - (info->flags & ADS_CLOSEST) ? "yes" : "no", - (info->flags & ADS_WRITABLE) ? "yes" : "no", - (info->flags & ADS_GOOD_TIMESERV) ? "yes" : "no", - (info->flags & ADS_NDNC) ? "yes" : "no", - (info->flags & ADS_DNS_CONTROLLER) ? "yes":"no", - (info->flags & ADS_DNS_DOMAIN) ? "yes":"no", - (info->flags & ADS_DNS_FOREST) ? "yes":"no"); - - d_printf("dc_site_name: %s\n", info->dc_site_name); - d_printf("client_site_name: %s\n", info->client_site_name); -} diff --git a/source3/lib/dprintf.c b/source3/lib/dprintf.c index 18b261623e..a3bb5be43a 100644 --- a/source3/lib/dprintf.c +++ b/source3/lib/dprintf.c @@ -47,7 +47,10 @@ lang_msg_free(msgstr); - if (ret <= 0) return ret; + if (ret <= 0) { + va_end(ap2); + return ret; + } /* now we have the string in unix format, convert it to the display charset, but beware of it growing */ @@ -56,6 +59,7 @@ again: p2 = (char *)SMB_MALLOC(maxlen); if (!p2) { SAFE_FREE(p); + va_end(ap2); return -1; } clen = convert_string(CH_UNIX, CH_DISPLAY, p, ret, p2, maxlen, True); @@ -72,6 +76,8 @@ again: ret = fwrite(p2, 1, clen, f); SAFE_FREE(p2); + va_end(ap2); + return ret; } diff --git a/source3/lib/errmap_unix.c b/source3/lib/errmap_unix.c index 885a1c55b2..8194cf80cc 100644 --- a/source3/lib/errmap_unix.c +++ b/source3/lib/errmap_unix.c @@ -92,6 +92,9 @@ const struct unix_error_map unix_dos_nt_errmap[] = { #ifdef EWOULDBLOCK { EWOULDBLOCK, ERRDOS, 111, NT_STATUS_NETWORK_BUSY }, #endif +#ifdef ENOATTR + { ENOATTR, ERRDOS, ERRbadfile, NT_STATUS_NOT_FOUND }, +#endif { 0, 0, 0, NT_STATUS_OK } }; diff --git a/source3/lib/fault.c b/source3/lib/fault.c index 33e1401d7a..1964955f1b 100644 --- a/source3/lib/fault.c +++ b/source3/lib/fault.c @@ -132,7 +132,6 @@ void dump_core_setup(const char *progname) sys_chown(corepath,getuid(),getgid()); chmod(corepath,0700); - SAFE_FREE(corepath); SAFE_FREE(logbase); #ifdef HAVE_GETRLIMIT diff --git a/source3/lib/gencache.c b/source3/lib/gencache.c index 663385cfe3..6131269adb 100644 --- a/source3/lib/gencache.c +++ b/source3/lib/gencache.c @@ -120,9 +120,9 @@ bool gencache_set(const char *keystr, const char *value, time_t timeout) if (!gencache_init()) return False; - asprintf(&valstr, CACHE_DATA_FMT, (int)timeout, value); - if (!valstr) + if (asprintf(&valstr, CACHE_DATA_FMT, (int)timeout, value) == -1) { return False; + } databuf = string_term_tdb_data(valstr); DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" @@ -340,8 +340,7 @@ bool gencache_set_data_blob(const char *keystr, DATA_BLOB *blob, time_t timeout) return False; } - asprintf(&valstr, "%12u/%s", (int)timeout, BLOB_TYPE); - if (!valstr) { + if (asprintf(&valstr, "%12u/%s", (int)timeout, BLOB_TYPE) == -1) { return False; } @@ -452,8 +451,9 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time break; } - asprintf(&fmt, READ_CACHE_DATA_FMT_TEMPLATE, (unsigned int)databuf.dsize - TIMEOUT_LEN); - if (!fmt) { + if (asprintf(&fmt, READ_CACHE_DATA_FMT_TEMPLATE, + (unsigned int)databuf.dsize - TIMEOUT_LEN) + == -1) { SAFE_FREE(valstr); SAFE_FREE(entry); SAFE_FREE(keystr); diff --git a/source3/lib/interfaces.c b/source3/lib/interfaces.c index 3797fc679d..dd857ae672 100644 --- a/source3/lib/interfaces.c +++ b/source3/lib/interfaces.c @@ -191,7 +191,6 @@ void make_net(struct sockaddr_storage *pss_out, Also gets IPv6 interfaces. ****************************************************************************/ -#if HAVE_IFACE_GETIFADDRS /**************************************************************************** Get the netmask address for a local interface. ****************************************************************************/ @@ -237,19 +236,9 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) memcpy(&ifaces[total].netmask, ifptr->ifa_netmask, copy_size); if (ifaces[total].flags & (IFF_BROADCAST|IFF_LOOPBACK)) { - if (ifptr->ifa_broadaddr) { - memcpy(&ifaces[total].bcast, - ifptr->ifa_broadaddr, - copy_size); - } else { - /* For some reason ifptr->ifa_broadaddr - * is null. Make one from ifa_addr and - * ifa_netmask. - */ - make_bcast(&ifaces[total].bcast, - &ifaces[total].ip, - &ifaces[total].netmask); - } + make_bcast(&ifaces[total].bcast, + &ifaces[total].ip, + &ifaces[total].netmask); } else if ((ifaces[total].flags & IFF_POINTOPOINT) && ifptr->ifa_dstaddr ) { memcpy(&ifaces[total].bcast, @@ -269,339 +258,6 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) return total; } -#define _FOUND_IFACE_ANY -#endif /* HAVE_IFACE_GETIFADDRS */ -#if HAVE_IFACE_IFCONF - -/* this works for Linux 2.2, Solaris 2.5, SunOS4, HPUX 10.20, OSF1 - V4.0, Ultrix 4.4, SCO Unix 3.2, IRIX 6.4 and FreeBSD 3.2. - - It probably also works on any BSD style system. */ - -/**************************************************************************** - Get the netmask address for a local interface. -****************************************************************************/ - -static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) -{ - struct ifconf ifc; - char buff[8192]; - int fd, i, n; - struct ifreq *ifr=NULL; - int total = 0; - - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { - return -1; - } - - ifc.ifc_len = sizeof(buff); - ifc.ifc_buf = buff; - - if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { - close(fd); - return -1; - } - - ifr = ifc.ifc_req; - - n = ifc.ifc_len / sizeof(struct ifreq); - - /* Loop through interfaces, looking for given IP address */ - for (i=n-1;i>=0 && total < max_interfaces;i--) { - - memset(&ifaces[total], '\0', sizeof(ifaces[total])); - - /* Check the interface is up. */ - if (ioctl(fd, SIOCGIFFLAGS, &ifr[i]) != 0) { - continue; - } - - ifaces[total].flags = ifr[i].ifr_flags; - - if (!(ifaces[total].flags & IFF_UP)) { - continue; - } - - if (ioctl(fd, SIOCGIFADDR, &ifr[i]) != 0) { - continue; - } - - strlcpy(ifaces[total].name, ifr[i].ifr_name, - sizeof(ifaces[total].name)); - - memcpy(&ifaces[total].ip, &ifr[i].ifr_addr, - sizeof(struct sockaddr_in)); - - if (ioctl(fd, SIOCGIFNETMASK, &ifr[i]) != 0) { - continue; - } - - memcpy(&ifaces[total].netmask, &ifr[i].ifr_netmask, - sizeof(struct sockaddr_in)); - - if (ifaces[total].flags & IFF_BROADCAST) { - if (ioctl(fd, SIOCGIFBRDADDR, &ifr[i]) != 0) { - continue; - } - memcpy(&ifaces[total].bcast, &ifr[i].ifr_broadaddr, - sizeof(struct sockaddr_in)); - } else if (ifaces[total].flags & IFF_POINTOPOINT) { - if (ioctl(fd, SIOCGIFDSTADDR, &ifr[i]) != 0) { - continue; - } - memcpy(&ifaces[total].bcast, &ifr[i].ifr_dstaddr, - sizeof(struct sockaddr_in)); - } else { - continue; - } - - total++; - } - - close(fd); - - return total; -} - -#define _FOUND_IFACE_ANY -#endif /* HAVE_IFACE_IFCONF */ -#ifdef HAVE_IFACE_IFREQ - -#ifndef I_STR -#include <sys/stropts.h> -#endif - -/**************************************************************************** - This should cover most of the streams based systems. - Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code. -****************************************************************************/ - -static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) -{ - struct ifreq ifreq; - struct strioctl strioctl; - char buff[8192]; - int fd, i, n; - struct ifreq *ifr=NULL; - int total = 0; - - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { - return -1; - } - - strioctl.ic_cmd = SIOCGIFCONF; - strioctl.ic_dp = buff; - strioctl.ic_len = sizeof(buff); - if (ioctl(fd, I_STR, &strioctl) < 0) { - close(fd); - return -1; - } - - /* we can ignore the possible sizeof(int) here as the resulting - number of interface structures won't change */ - n = strioctl.ic_len / sizeof(struct ifreq); - - /* we will assume that the kernel returns the length as an int - at the start of the buffer if the offered size is a - multiple of the structure size plus an int */ - if (n*sizeof(struct ifreq) + sizeof(int) == strioctl.ic_len) { - ifr = (struct ifreq *)(buff + sizeof(int)); - } else { - ifr = (struct ifreq *)buff; - } - - /* Loop through interfaces */ - - for (i = 0; i<n && total < max_interfaces; i++) { - - memset(&ifaces[total], '\0', sizeof(ifaces[total])); - - ifreq = ifr[i]; - - strioctl.ic_cmd = SIOCGIFFLAGS; - strioctl.ic_dp = (char *)&ifreq; - strioctl.ic_len = sizeof(struct ifreq); - if (ioctl(fd, I_STR, &strioctl) != 0) { - continue; - } - - ifaces[total].flags = ifreq.ifr_flags; - - if (!(ifaces[total].flags & IFF_UP)) { - continue; - } - - strioctl.ic_cmd = SIOCGIFADDR; - strioctl.ic_dp = (char *)&ifreq; - strioctl.ic_len = sizeof(struct ifreq); - if (ioctl(fd, I_STR, &strioctl) != 0) { - continue; - } - - strlcpy(ifaces[total].name, - ifreq.ifr_name, - sizeof(ifaces[total].name)); - - memcpy(&ifaces[total].ip, &ifreq.ifr_addr, - sizeof(struct sockaddr_in)); - - strioctl.ic_cmd = SIOCGIFNETMASK; - strioctl.ic_dp = (char *)&ifreq; - strioctl.ic_len = sizeof(struct ifreq); - if (ioctl(fd, I_STR, &strioctl) != 0) { - continue; - } - - memcpy(&ifaces[total].netmask, &ifreq.ifr_addr, - sizeof(struct sockaddr_in)); - - if (ifaces[total].flags & IFF_BROADCAST) { - strioctl.ic_cmd = SIOCGIFBRDADDR; - strioctl.ic_dp = (char *)&ifreq; - strioctl.ic_len = sizeof(struct ifreq); - if (ioctl(fd, I_STR, &strioctl) != 0) { - continue; - } - memcpy(&ifaces[total].bcast, &ifreq.ifr_broadaddr, - sizeof(struct sockaddr_in)); - } else if (ifaces[total].flags & IFF_POINTOPOINT) { - strioctl.ic_cmd = SIOCGIFDSTADDR; - strioctl.ic_dp = (char *)&ifreq; - strioctl.ic_len = sizeof(struct ifreq); - if (ioctl(fd, I_STR, &strioctl) != 0) { - continue; - } - memcpy(&ifaces[total].bcast, &ifreq.ifr_dstaddr, - sizeof(struct sockaddr_in)); - } else { - continue; - } - - total++; - } - - close(fd); - - return total; -} - -#define _FOUND_IFACE_ANY -#endif /* HAVE_IFACE_IFREQ */ -#ifdef HAVE_IFACE_AIX - -/**************************************************************************** - This one is for AIX (tested on 4.2). -****************************************************************************/ - -static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) -{ - char buff[8192]; - int fd, i; - struct ifconf ifc; - struct ifreq *ifr=NULL; - int total = 0; - - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { - return -1; - } - - - ifc.ifc_len = sizeof(buff); - ifc.ifc_buf = buff; - - if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { - close(fd); - return -1; - } - - ifr = ifc.ifc_req; - - /* Loop through interfaces */ - i = ifc.ifc_len; - - while (i > 0 && total < max_interfaces) { - uint_t inc; - - memset(&ifaces[total], '\0', sizeof(ifaces[total])); - - inc = ifr->ifr_addr.sa_len; - - if (ioctl(fd, SIOCGIFFLAGS, ifr) != 0) { - goto next; - } - - ifaces[total].flags = ifr->ifr_flags; - - if (!(ifaces[total].flags & IFF_UP)) { - goto next; - } - - if (ioctl(fd, SIOCGIFADDR, ifr) != 0) { - goto next; - } - - memcpy(&ifaces[total].ip, &ifr->ifr_addr, - sizeof(struct sockaddr_in)); - - strlcpy(ifaces[total].name, ifr->ifr_name, - sizeof(ifaces[total].name)); - - if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) { - goto next; - } - - memcpy(&ifaces[total].netmask, &ifr->ifr_addr, - sizeof(struct sockaddr_in)); - - if (ifaces[total].flags & IFF_BROADCAST) { - if (ioctl(fd, SIOCGIFBRDADDR, ifr) != 0) { - goto next; - } - memcpy(&ifaces[total].bcast, &ifr->ifr_broadaddr, - sizeof(struct sockaddr_in)); - } else if (ifaces[total].flags & IFF_POINTOPOINT) { - if (ioctl(fd, SIOCGIFDSTADDR, ifr) != 0) { - goto next; - } - memcpy(&ifaces[total].bcast, &ifr->ifr_dstaddr, - sizeof(struct sockaddr_in)); - } else { - goto next; - } - - - total++; - - next: - /* - * Patch from Archie Cobbs (archie@whistle.com). The - * addresses in the SIOCGIFCONF interface list have a - * minimum size. Usually this doesn't matter, but if - * your machine has tunnel interfaces, etc. that have - * a zero length "link address", this does matter. */ - - if (inc < sizeof(ifr->ifr_addr)) - inc = sizeof(ifr->ifr_addr); - inc += IFNAMSIZ; - - ifr = (struct ifreq*) (((char*) ifr) + inc); - i -= inc; - } - - close(fd); - return total; -} - -#define _FOUND_IFACE_ANY -#endif /* HAVE_IFACE_AIX */ -#ifndef _FOUND_IFACE_ANY -static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) -{ - return -1; -} -#endif - - static int iface_comp(struct iface_struct *i1, struct iface_struct *i2) { int r; @@ -693,55 +349,3 @@ int get_interfaces(struct iface_struct *ifaces, int max_interfaces) return total; } - -#ifdef AUTOCONF_TEST -/* this is the autoconf driver to test get_interfaces() */ - -static socklen_t calc_sa_size(struct sockaddr *psa) -{ - socklen_t sl = sizeof(struct sockaddr_in); -#if defined(HAVE_IPV6) - if (psa->sa_family == AF_INET6) { - sl = sizeof(struct sockaddr_in6); - } -#endif - return sl; -} - - int main() -{ - struct iface_struct ifaces[MAX_INTERFACES]; - int total = get_interfaces(ifaces, MAX_INTERFACES); - int i; - - printf("got %d interfaces:\n", total); - if (total <= 0) { - exit(1); - } - - for (i=0;i<total;i++) { - char addr[INET6_ADDRSTRLEN]; - int ret; - printf("%-10s ", ifaces[i].name); - addr[0] = '\0'; - ret = getnameinfo((struct sockaddr *)&ifaces[i].ip, - calc_sa_size(&ifaces[i].ip), - addr, sizeof(addr), - NULL, 0, NI_NUMERICHOST); - printf("IP=%s ", addr); - addr[0] = '\0'; - ret = getnameinfo((struct sockaddr *)&ifaces[i].netmask, - calc_sa_size(&ifaces[i].netmask), - addr, sizeof(addr), - NULL, 0, NI_NUMERICHOST); - printf("NETMASK=%s ", addr); - addr[0] = '\0'; - ret = getnameinfo((struct sockaddr *)&ifaces[i].bcast, - calc_sa_size(&ifaces[i].bcast), - addr, sizeof(addr), - NULL, 0, NI_NUMERICHOST); - printf("BCAST=%s\n", addr); - } - return 0; -} -#endif diff --git a/source3/lib/ldap_debug_handler.c b/source3/lib/ldap_debug_handler.c new file mode 100644 index 0000000000..2181ff014d --- /dev/null +++ b/source3/lib/ldap_debug_handler.c @@ -0,0 +1,52 @@ +/* + * Unix SMB/CIFS implementation. + * Intercept libldap debug output. + * Copyright (C) Michael Adam 2008 + * + * 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" + +#if HAVE_LDAP + +static void samba_ldap_log_print_fn(LDAP_CONST char *data) +{ + DEBUG(lp_ldap_debug_threshold(), ("[LDAP] %s", data)); +} + +#endif + +void init_ldap_debugging(void) +{ +#if defined(HAVE_LDAP) && defined(HAVE_LBER_LOG_PRINT_FN) + int ret; + int ldap_debug_level = lp_ldap_debug_level(); + + ret = ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &ldap_debug_level); + if (ret != LDAP_OPT_SUCCESS) { + DEBUG(10, ("Error setting LDAP debug level.\n")); + } + + if (ldap_debug_level == 0) { + return; + } + + ret = ber_set_option(NULL, LBER_OPT_LOG_PRINT_FN, + (void *)samba_ldap_log_print_fn); + if (ret != LBER_OPT_SUCCESS) { + DEBUG(10, ("Error setting LBER log print function.\n")); + } +#endif /* HAVE_LDAP && HAVE_LBER_LOG_PRINT_FN */ +} diff --git a/source3/lib/messages_ctdbd.c b/source3/lib/messages_ctdbd.c index 6e9b934a75..f1a02e6af9 100644 --- a/source3/lib/messages_ctdbd.c +++ b/source3/lib/messages_ctdbd.c @@ -22,6 +22,10 @@ #ifdef CLUSTER_SUPPORT #include "librpc/gen_ndr/messaging.h" +#include "ctdb.h" +#include "ctdb_private.h" +#include "ctdbd_conn.h" + struct messaging_ctdbd_context { struct ctdbd_connection *conn; diff --git a/source3/lib/netapi/examples/Makefile.in b/source3/lib/netapi/examples/Makefile.in index c2f453dedc..6de3e65546 100644 --- a/source3/lib/netapi/examples/Makefile.in +++ b/source3/lib/netapi/examples/Makefile.in @@ -3,9 +3,9 @@ GTK_LIBS=`pkg-config gtk+-2.0 --libs` KRB5LIBS=@KRB5_LIBS@ LDAP_LIBS=@LDAP_LIBS@ -LIBS=@LIBS@ -lnetapi +LIBS=@LIBS@ -lnetapi -ltdb -ltalloc DEVELOPER_CFLAGS=@DEVELOPER_CFLAGS@ -FLAGS=@CFLAGS@ $(GTK_FLAGS) +FLAGS=-I../ -L../../../bin @CFLAGS@ $(GTK_FLAGS) CC=@CC@ LDFLAGS=@PIE_LDFLAGS@ @LDFLAGS@ DYNEXP=@DYNEXP@ @@ -14,7 +14,12 @@ DYNEXP=@DYNEXP@ COMPILE_CC = $(CC) -I. $(FLAGS) $(PICFLAG) -c $< -o $@ COMPILE = $(COMPILE_CC) -BINARY_PREREQS = proto_exists bin/.dummy +PROGS = bin/getdc@EXEEXT@ \ + bin/netdomjoin@EXEEXT@ \ + bin/netdomjoin-gui@EXEEXT@ \ + bin/getjoinableous@EXEEXT@ + +all: $(PROGS) MAKEDIR = || exec false; \ if test -d "$$dir"; then :; else \ @@ -24,6 +29,13 @@ MAKEDIR = || exec false; \ mkdir "$$dir" || \ exec false; fi || exec false +BINARY_PREREQS = bin/.dummy + +bin/.dummy: + @if (: >> $@ || : > $@) >/dev/null 2>&1; then :; else \ + dir=bin $(MAKEDIR); fi + @: >> $@ || : > $@ # what a fancy emoticon! + .c.o: @if (: >> $@ || : > $@) >/dev/null 2>&1; then rm -f $@; else \ dir=`echo $@ | sed 's,/[^/]*$$,,;s,^$$,.,'` $(MAKEDIR); fi @@ -36,22 +48,25 @@ MAKEDIR = || exec false; \ GETDC_OBJ = getdc/getdc.o NETDOMJOIN_OBJ = netdomjoin/netdomjoin.o NETDOMJOIN_GUI_OBJ = netdomjoin-gui/netdomjoin-gui.o +GETJOINABLEOUS_OBJ = getjoinableous/getjoinableous.o -PROGS = bin/getdc@EXEEXT@ bin/netdomjoin@EXEEXT@ bin/netdomjoin-gui@EXEEXT@ - -all: $(PROGS) - -bin/getdc@EXEEXT@: $(GETDC_OBJ) +bin/getdc@EXEEXT@: $(BINARY_PREREQS) $(GETDC_OBJ) @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(GETDC_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) -bin/netdomjoin@EXEEXT@: $(NETDOMJOIN_OBJ) +bin/getjoinableous@EXEEXT@: $(BINARY_PREREQS) $(GETJOINABLEOUS_OBJ) + @echo Linking $@ + @$(CC) $(FLAGS) -o $@ $(GETJOINABLEOUS_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) + +bin/netdomjoin@EXEEXT@: $(BINARY_PREREQS) $(NETDOMJOIN_OBJ) @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(NETDOMJOIN_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) -bin/netdomjoin-gui@EXEEXT@: $(NETDOMJOIN_GUI_OBJ) +bin/netdomjoin-gui@EXEEXT@: $(BINARY_PREREQS) $(NETDOMJOIN_GUI_OBJ) @echo Linking $@ @$(CC) $(FLAGS) $(GTK_FLAGS) -o $@ $(NETDOMJOIN_GUI_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(GTK_LIBS) clean: - @rm -f $(PROGS) + -rm -f $(PROGS) + -rm -f core */*~ *~ \ + */*.o */*/*.o */*/*/*.o diff --git a/source3/lib/netapi/examples/getdc/getdc.c b/source3/lib/netapi/examples/getdc/getdc.c index cdd4d0b3b4..272ba1088e 100644 --- a/source3/lib/netapi/examples/getdc/getdc.c +++ b/source3/lib/netapi/examples/getdc/getdc.c @@ -29,7 +29,7 @@ int main(int argc, char **argv) { NET_API_STATUS status; struct libnetapi_ctx *ctx = NULL; - uint8_t *buffer; + uint8_t *buffer = NULL; if (argc < 3) { printf("usage: getdc <hostname> <domain>\n"); @@ -50,7 +50,7 @@ int main(int argc, char **argv) } else { printf("%s\n", (char *)buffer); } - + NetApiBufferFree(buffer); libnetapi_free(ctx); return status; diff --git a/source3/lib/netapi/examples/getjoinableous/getjoinableous.c b/source3/lib/netapi/examples/getjoinableous/getjoinableous.c new file mode 100644 index 0000000000..5a3366c9dc --- /dev/null +++ b/source3/lib/netapi/examples/getjoinableous/getjoinableous.c @@ -0,0 +1,104 @@ +/* + * Unix SMB/CIFS implementation. + * Join Support (cmdline + netapi) + * Copyright (C) Guenther Deschner 2008 + * + * 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 <string.h> +#include <stdio.h> + +#include <netapi.h> + +char *get_string_param(const char *param) +{ + char *p; + + p = strchr(param, '='); + if (!p) { + return NULL; + } + + return (p+1); +} + +int main(int argc, char **argv) +{ + NET_API_STATUS status; + const char *server_name = NULL; + const char *domain_name = NULL; + const char *account = NULL; + const char *password = NULL; + const char **ous = NULL; + uint32_t num_ous = 0; + struct libnetapi_ctx *ctx = NULL; + int i; + + status = libnetapi_init(&ctx); + if (status != 0) { + return status; + } + + if (argc < 2) { + printf("usage: getjoinableous\n"); + printf("\t<hostname> [domain=DOMAIN] <user=USER> <password=PASSWORD>\n"); + return 0; + } + + if (argc > 2) { + server_name = argv[1]; + } + + for (i=0; i<argc; i++) { + if (strncasecmp(argv[i], "domain", strlen("domain"))== 0) { + domain_name = get_string_param(argv[i]); + } + if (strncasecmp(argv[i], "user", strlen("user"))== 0) { + account = get_string_param(argv[i]); + libnetapi_set_username(ctx, account); + } + if (strncasecmp(argv[i], "password", strlen("password"))== 0) { + password = get_string_param(argv[i]); + libnetapi_set_password(ctx, password); + } + if (strncasecmp(argv[i], "debug", strlen("debug"))== 0) { + const char *str = NULL; + str = get_string_param(argv[i]); + libnetapi_set_debuglevel(ctx, str); + } + } + + status = NetGetJoinableOUs(server_name, + domain_name, + account, + password, + &num_ous, + &ous); + if (status != 0) { + printf("failed with: %s\n", + libnetapi_get_error_string(ctx, status)); + } else { + printf("Successfully queried joinable ous:\n"); + for (i=0; i<num_ous; i++) { + printf("ou: %s\n", ous[i]); + } + } + + NetApiBufferFree(ous); + + libnetapi_free(ctx); + + return status; +} diff --git a/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c b/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c index 9dc2a18138..73b14d4d87 100644 --- a/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c +++ b/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c @@ -24,6 +24,7 @@ #include <stdlib.h> #include <unistd.h> #include <string.h> +#include <netdb.h> #include <gtk/gtk.h> #include <glib/gprintf.h> @@ -439,7 +440,7 @@ static void callback_do_join(GtkWidget *widget, state->password, unjoin_flags); if (status != 0) { - err_str = libnetapi_errstr(status); + err_str = libnetapi_get_error_string(state->ctx, status); g_print("callback_do_join: failed to unjoin (%s)\n", err_str); @@ -463,7 +464,7 @@ static void callback_do_join(GtkWidget *widget, state->password, join_flags); if (status != 0) { - err_str = libnetapi_errstr(status); + err_str = libnetapi_get_error_string(state->ctx, status); g_print("callback_do_join: failed to join (%s)\n", err_str); dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent), @@ -1263,37 +1264,56 @@ static int initialize_join_state(struct join_state *state, { char my_hostname[HOST_NAME_MAX]; const char *p = NULL; + struct hostent *hp = NULL; + if (gethostname(my_hostname, sizeof(my_hostname)) == -1) { return -1; } - state->my_fqdn = strdup(my_hostname); + p = strchr(my_hostname, '.'); + if (p) { + my_hostname[strlen(my_hostname)-strlen(p)] = '\0'; + } + state->my_hostname = strdup(my_hostname); + if (!state->my_hostname) { + return -1; + } + debug("state->my_hostname: %s\n", state->my_hostname); + + hp = gethostbyname(my_hostname); + if (!hp || !hp->h_name || !*hp->h_name) { + return -1; + } + + state->my_fqdn = strdup(hp->h_name); if (!state->my_fqdn) { return -1; } + debug("state->my_fqdn: %s\n", state->my_fqdn); - p = strchr(my_hostname, '.'); + p = strchr(state->my_fqdn, '.'); if (p) { - my_hostname[strlen(my_hostname) - strlen(p)] = '\0'; - state->my_hostname = strdup(my_hostname); - if (!state->my_hostname) { - return -1; - } p++; state->my_dnsdomain = strdup(p); - if (!state->my_dnsdomain) { - return -1; - } + } else { + state->my_dnsdomain = strdup(""); + } + if (!state->my_dnsdomain) { + return -1; } + debug("state->my_dnsdomain: %s\n", state->my_dnsdomain); } { const char *buffer = NULL; uint16_t type = 0; status = NetGetJoinInformation(NULL, &buffer, &type); - if (status) { + if (status != 0) { + printf("NetGetJoinInformation failed with: %s\n", + libnetapi_get_error_string(state->ctx, status)); return status; } + debug("NetGetJoinInformation gave: %s and %d\n", buffer, type); state->name_buffer_initial = strdup(buffer); if (!state->name_buffer_initial) { return -1; @@ -1307,7 +1327,9 @@ static int initialize_join_state(struct join_state *state, uint8_t *buffer = NULL; status = NetServerGetInfo(NULL, 1005, &buffer); - if (status) { + if (status != 0) { + printf("NetServerGetInfo failed with: %s\n", + libnetapi_get_error_string(state->ctx, status)); return status; } diff --git a/source3/lib/netapi/getdc.c b/source3/lib/netapi/getdc.c index 85a0ae52ef..2626eb0af4 100644 --- a/source3/lib/netapi/getdc.c +++ b/source3/lib/netapi/getdc.c @@ -22,21 +22,8 @@ #include "lib/netapi/netapi.h" #include "libnet/libnet.h" -#if 0 -#include "librpc/gen_ndr/cli_netlogon.h" -#endif - -NTSTATUS rpccli_netr_GetDcName(struct rpc_pipe_client *cli, - TALLOC_CTX *mem_ctx, - const char *logon_server, - const char *domainname, - const char **dcname); -NTSTATUS rpccli_netr_GetAnyDCName(struct rpc_pipe_client *cli, - TALLOC_CTX *mem_ctx, - const char *logon_server, - const char *domainname, - const char **dcname, - WERROR *werror); +/******************************************************************** +********************************************************************/ static WERROR NetGetDCNameLocal(struct libnetapi_ctx *ctx, const char *server_name, @@ -46,6 +33,9 @@ static WERROR NetGetDCNameLocal(struct libnetapi_ctx *ctx, return WERR_NOT_SUPPORTED; } +/******************************************************************** +********************************************************************/ + static WERROR NetGetDCNameRemote(struct libnetapi_ctx *ctx, const char *server_name, const char *domain_name, @@ -76,17 +66,11 @@ static WERROR NetGetDCNameRemote(struct libnetapi_ctx *ctx, goto done; }; -#if 0 - werr = rpccli_netr_GetDcName(pipe_cli, ctx, - server_name, - domain_name, - (const char **)&buffer); -#else - werr = rpccli_netlogon_getdcname(pipe_cli, ctx, - server_name, - domain_name, - (char **)buffer); -#endif + status = rpccli_netr_GetDcName(pipe_cli, ctx, + server_name, + domain_name, + (const char **)buffer, + &werr); done: if (cli) { cli_shutdown(cli); @@ -95,6 +79,9 @@ static WERROR NetGetDCNameRemote(struct libnetapi_ctx *ctx, return werr; } +/******************************************************************** +********************************************************************/ + static WERROR libnetapi_NetGetDCName(struct libnetapi_ctx *ctx, const char *server_name, const char *domain_name, @@ -113,6 +100,10 @@ static WERROR libnetapi_NetGetDCName(struct libnetapi_ctx *ctx, buffer); } +/**************************************************************** + NetGetDCName +****************************************************************/ + NET_API_STATUS NetGetDCName(const char *server_name, const char *domain_name, uint8_t **buffer) @@ -134,9 +125,12 @@ NET_API_STATUS NetGetDCName(const char *server_name, return W_ERROR_V(werr); } - return 0; + return NET_API_STATUS_SUCCESS; } +/******************************************************************** +********************************************************************/ + static WERROR NetGetAnyDCNameLocal(struct libnetapi_ctx *ctx, const char *server_name, const char *domain_name, @@ -145,6 +139,9 @@ static WERROR NetGetAnyDCNameLocal(struct libnetapi_ctx *ctx, return WERR_NOT_SUPPORTED; } +/******************************************************************** +********************************************************************/ + static WERROR NetGetAnyDCNameRemote(struct libnetapi_ctx *ctx, const char *server_name, const char *domain_name, @@ -175,22 +172,14 @@ static WERROR NetGetAnyDCNameRemote(struct libnetapi_ctx *ctx, goto done; }; -#if 0 status = rpccli_netr_GetAnyDCName(pipe_cli, ctx, server_name, domain_name, - (const char **)&buffer, + (const char **)buffer, &werr); if (!NT_STATUS_IS_OK(status)) { - werr = ntstatus_to_werror(status); goto done; } -#else - werr = rpccli_netlogon_getanydcname(pipe_cli, ctx, - server_name, - domain_name, - (char **)buffer); -#endif done: if (cli) { cli_shutdown(cli); @@ -200,6 +189,9 @@ static WERROR NetGetAnyDCNameRemote(struct libnetapi_ctx *ctx, } +/******************************************************************** +********************************************************************/ + static WERROR libnetapi_NetGetAnyDCName(struct libnetapi_ctx *ctx, const char *server_name, const char *domain_name, @@ -218,6 +210,10 @@ static WERROR libnetapi_NetGetAnyDCName(struct libnetapi_ctx *ctx, buffer); } +/**************************************************************** + NetGetAnyDCName +****************************************************************/ + NET_API_STATUS NetGetAnyDCName(const char *server_name, const char *domain_name, uint8_t **buffer) @@ -239,5 +235,5 @@ NET_API_STATUS NetGetAnyDCName(const char *server_name, return W_ERROR_V(werr); } - return 0; + return NET_API_STATUS_SUCCESS; } diff --git a/source3/lib/netapi/joindomain.c b/source3/lib/netapi/joindomain.c index b268e41a2a..405f96a87e 100644 --- a/source3/lib/netapi/joindomain.c +++ b/source3/lib/netapi/joindomain.c @@ -22,6 +22,9 @@ #include "lib/netapi/netapi.h" #include "libnet/libnet.h" +/**************************************************************** +****************************************************************/ + static WERROR NetJoinDomainLocal(struct libnetapi_ctx *mem_ctx, const char *server_name, const char *domain_name, @@ -45,17 +48,19 @@ static WERROR NetJoinDomainLocal(struct libnetapi_ctx *mem_ctx, if (join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) { NTSTATUS status; - struct DS_DOMAIN_CONTROLLER_INFO *info = NULL; + struct netr_DsRGetDCNameInfo *info = NULL; uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED | DS_WRITABLE_REQUIRED | DS_RETURN_DNS_NAME; - status = dsgetdcname(mem_ctx, NULL, domain_name, + status = dsgetdcname(mem_ctx, domain_name, NULL, NULL, flags, &info); if (!NT_STATUS_IS_OK(status)) { + libnetapi_set_error_string(mem_ctx, + "%s", get_friendly_nt_error_msg(status)); return ntstatus_to_werror(status); } r->in.dc_name = talloc_strdup(mem_ctx, - info->domain_controller_name); + info->dc_unc); W_ERROR_HAVE_NO_MEMORY(r->in.dc_name); } @@ -79,13 +84,16 @@ static WERROR NetJoinDomainLocal(struct libnetapi_ctx *mem_ctx, werr = libnet_Join(mem_ctx, r); if (!W_ERROR_IS_OK(werr) && r->out.error_string) { - libnetapi_set_error_string(mem_ctx, r->out.error_string); + libnetapi_set_error_string(mem_ctx, "%s", r->out.error_string); } TALLOC_FREE(r); return werr; } +/**************************************************************** +****************************************************************/ + static WERROR NetJoinDomainRemote(struct libnetapi_ctx *ctx, const char *server_name, const char *domain_name, @@ -149,6 +157,9 @@ static WERROR NetJoinDomainRemote(struct libnetapi_ctx *ctx, return werr; } +/**************************************************************** +****************************************************************/ + static WERROR libnetapi_NetJoinDomain(struct libnetapi_ctx *ctx, const char *server_name, const char *domain_name, @@ -181,6 +192,10 @@ static WERROR libnetapi_NetJoinDomain(struct libnetapi_ctx *ctx, join_flags); } +/**************************************************************** + NetJoinDomain +****************************************************************/ + NET_API_STATUS NetJoinDomain(const char *server_name, const char *domain_name, const char *account_ou, @@ -208,9 +223,12 @@ NET_API_STATUS NetJoinDomain(const char *server_name, return W_ERROR_V(werr); } - return 0; + return NET_API_STATUS_SUCCESS; } +/**************************************************************** +****************************************************************/ + static WERROR NetUnjoinDomainLocal(struct libnetapi_ctx *mem_ctx, const char *server_name, const char *account, @@ -232,10 +250,9 @@ static WERROR NetUnjoinDomainLocal(struct libnetapi_ctx *mem_ctx, r->in.dc_name = talloc_strdup(mem_ctx, server_name); W_ERROR_HAVE_NO_MEMORY(r->in.dc_name); } else { - NTSTATUS status; const char *domain = NULL; - struct DS_DOMAIN_CONTROLLER_INFO *info = NULL; + struct netr_DsRGetDCNameInfo *info = NULL; uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED | DS_WRITABLE_REQUIRED | DS_RETURN_DNS_NAME; @@ -244,13 +261,15 @@ static WERROR NetUnjoinDomainLocal(struct libnetapi_ctx *mem_ctx, } else { domain = lp_workgroup(); } - status = dsgetdcname(mem_ctx, NULL, domain, + status = dsgetdcname(mem_ctx, domain, NULL, NULL, flags, &info); if (!NT_STATUS_IS_OK(status)) { + libnetapi_set_error_string(mem_ctx, + "%s", get_friendly_nt_error_msg(status)); return ntstatus_to_werror(status); } r->in.dc_name = talloc_strdup(mem_ctx, - info->domain_controller_name); + info->dc_unc); W_ERROR_HAVE_NO_MEMORY(r->in.dc_name); } @@ -266,13 +285,22 @@ static WERROR NetUnjoinDomainLocal(struct libnetapi_ctx *mem_ctx, r->in.unjoin_flags = unjoin_flags; r->in.modify_config = true; + r->in.debug = true; r->in.domain_sid = &domain_sid; - return libnet_Unjoin(mem_ctx, r); + werr = libnet_Unjoin(mem_ctx, r); + if (!W_ERROR_IS_OK(werr) && r->out.error_string) { + libnetapi_set_error_string(mem_ctx, "%s", r->out.error_string); + } + TALLOC_FREE(r); + return werr; } +/**************************************************************** +****************************************************************/ + static WERROR NetUnjoinDomainRemote(struct libnetapi_ctx *ctx, const char *server_name, const char *account, @@ -335,6 +363,9 @@ static WERROR NetUnjoinDomainRemote(struct libnetapi_ctx *ctx, return werr; } +/**************************************************************** +****************************************************************/ + static WERROR libnetapi_NetUnjoinDomain(struct libnetapi_ctx *ctx, const char *server_name, const char *account, @@ -357,6 +388,10 @@ static WERROR libnetapi_NetUnjoinDomain(struct libnetapi_ctx *ctx, unjoin_flags); } +/**************************************************************** + NetUnjoinDomain +****************************************************************/ + NET_API_STATUS NetUnjoinDomain(const char *server_name, const char *account, const char *password, @@ -380,9 +415,12 @@ NET_API_STATUS NetUnjoinDomain(const char *server_name, return W_ERROR_V(werr); } - return 0; + return NET_API_STATUS_SUCCESS; } +/**************************************************************** +****************************************************************/ + static WERROR NetGetJoinInformationRemote(struct libnetapi_ctx *ctx, const char *server_name, const char **name_buffer, @@ -431,6 +469,9 @@ static WERROR NetGetJoinInformationRemote(struct libnetapi_ctx *ctx, return werr; } +/**************************************************************** +****************************************************************/ + static WERROR NetGetJoinInformationLocal(struct libnetapi_ctx *ctx, const char *server_name, const char **name_buffer, @@ -478,6 +519,10 @@ static WERROR libnetapi_NetGetJoinInformation(struct libnetapi_ctx *ctx, name_type); } +/**************************************************************** + NetGetJoinInformation +****************************************************************/ + NET_API_STATUS NetGetJoinInformation(const char *server_name, const char **name_buffer, uint16_t *name_type) @@ -499,5 +544,201 @@ NET_API_STATUS NetGetJoinInformation(const char *server_name, return W_ERROR_V(werr); } - return 0; + return NET_API_STATUS_SUCCESS; +} + +/**************************************************************** +****************************************************************/ + +static WERROR NetGetJoinableOUsLocal(struct libnetapi_ctx *ctx, + const char *server_name, + const char *domain, + const char *account, + const char *password, + uint32_t *ou_count, + const char ***ous) +{ +#ifdef WITH_ADS + NTSTATUS status; + ADS_STATUS ads_status; + ADS_STRUCT *ads = NULL; + struct netr_DsRGetDCNameInfo *info = NULL; + uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED | + DS_RETURN_DNS_NAME; + + status = dsgetdcname(ctx, domain, + NULL, NULL, flags, &info); + if (!NT_STATUS_IS_OK(status)) { + libnetapi_set_error_string(ctx, "%s", + get_friendly_nt_error_msg(status)); + return ntstatus_to_werror(status); + } + + ads = ads_init(domain, domain, info->dc_unc); + if (!ads) { + return WERR_GENERAL_FAILURE; + } + + SAFE_FREE(ads->auth.user_name); + if (account) { + ads->auth.user_name = SMB_STRDUP(account); + } else if (ctx->username) { + ads->auth.user_name = SMB_STRDUP(ctx->username); + } + + SAFE_FREE(ads->auth.password); + if (password) { + ads->auth.password = SMB_STRDUP(password); + } else if (ctx->password) { + ads->auth.password = SMB_STRDUP(ctx->password); + } + + ads_status = ads_connect(ads); + if (!ADS_ERR_OK(ads_status)) { + ads_destroy(&ads); + return WERR_DEFAULT_JOIN_REQUIRED; + } + + ads_status = ads_get_joinable_ous(ads, ctx, + (char ***)ous, + (size_t *)ou_count); + if (!ADS_ERR_OK(ads_status)) { + ads_destroy(&ads); + return WERR_DEFAULT_JOIN_REQUIRED; + } + + ads_destroy(&ads); + return WERR_OK; +#else + return WERR_NOT_SUPPORTED; +#endif +} + +/**************************************************************** +****************************************************************/ + +static WERROR NetGetJoinableOUsRemote(struct libnetapi_ctx *ctx, + const char *server_name, + const char *domain, + const char *account, + const char *password, + uint32_t *ou_count, + const char ***ous) +{ + struct cli_state *cli = NULL; + struct rpc_pipe_client *pipe_cli = NULL; + struct wkssvc_PasswordBuffer *encrypted_password = NULL; + NTSTATUS status; + WERROR werr; + + status = cli_full_connection(&cli, NULL, server_name, + NULL, 0, + "IPC$", "IPC", + ctx->username, + ctx->workgroup, + ctx->password, + 0, Undefined, NULL); + + if (!NT_STATUS_IS_OK(status)) { + werr = ntstatus_to_werror(status); + goto done; + } + + pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC, + &status); + if (!pipe_cli) { + werr = ntstatus_to_werror(status); + goto done; + } + + if (password) { + encode_wkssvc_join_password_buffer(ctx, + password, + &cli->user_session_key, + &encrypted_password); + } + + status = rpccli_wkssvc_NetrGetJoinableOus2(pipe_cli, ctx, + server_name, + domain, + account, + encrypted_password, + ou_count, + ous, + &werr); + if (!NT_STATUS_IS_OK(status)) { + werr = ntstatus_to_werror(status); + goto done; + } + + done: + if (cli) { + cli_shutdown(cli); + } + + return werr; +} + +/**************************************************************** +****************************************************************/ + +static WERROR libnetapi_NetGetJoinableOUs(struct libnetapi_ctx *ctx, + const char *server_name, + const char *domain, + const char *account, + const char *password, + uint32_t *ou_count, + const char ***ous) +{ + if (!server_name || is_myname_or_ipaddr(server_name)) { + return NetGetJoinableOUsLocal(ctx, + server_name, + domain, + account, + password, + ou_count, + ous); + } + + return NetGetJoinableOUsRemote(ctx, + server_name, + domain, + account, + password, + ou_count, + ous); +} + +/**************************************************************** + NetGetJoinableOUs +****************************************************************/ + +NET_API_STATUS NetGetJoinableOUs(const char *server_name, + const char *domain, + const char *account, + const char *password, + uint32_t *ou_count, + const char ***ous) +{ + struct libnetapi_ctx *ctx = NULL; + NET_API_STATUS status; + WERROR werr; + + status = libnetapi_getctx(&ctx); + if (status != 0) { + return status; + } + + werr = libnetapi_NetGetJoinableOUs(ctx, + server_name, + domain, + account, + password, + ou_count, + ous); + if (!W_ERROR_IS_OK(werr)) { + return W_ERROR_V(werr); + } + + return NET_API_STATUS_SUCCESS; } diff --git a/source3/lib/netapi/netapi.c b/source3/lib/netapi/netapi.c index ce00054e6e..fb091f6e0b 100644 --- a/source3/lib/netapi/netapi.c +++ b/source3/lib/netapi/netapi.c @@ -50,7 +50,9 @@ NET_API_STATUS libnetapi_init(struct libnetapi_ctx **context) return W_ERROR_V(WERR_NOMEM); } - DEBUGLEVEL = 0; + if (!DEBUGLEVEL) { + DEBUGLEVEL = 0; + } setup_logging("libnetapi", true); dbf = x_stderr; @@ -119,7 +121,6 @@ NET_API_STATUS libnetapi_free(struct libnetapi_ctx *ctx) gencache_shutdown(); secrets_shutdown(); - regdb_close(); TALLOC_FREE(ctx); TALLOC_FREE(frame); @@ -205,15 +206,20 @@ const char *libnetapi_errstr(NET_API_STATUS status) ****************************************************************/ NET_API_STATUS libnetapi_set_error_string(struct libnetapi_ctx *ctx, - const char *error_string) + const char *format, ...) { + va_list args; + TALLOC_FREE(ctx->error_string); - ctx->error_string = talloc_strdup(ctx, error_string); + + va_start(args, format); + ctx->error_string = talloc_vasprintf(ctx, format, args); + va_end(args); + if (!ctx->error_string) { return W_ERROR_V(WERR_NOMEM); } return NET_API_STATUS_SUCCESS; - } /**************************************************************** diff --git a/source3/lib/netapi/netapi.h b/source3/lib/netapi/netapi.h index 274a167d53..002fc37762 100644 --- a/source3/lib/netapi/netapi.h +++ b/source3/lib/netapi/netapi.h @@ -36,6 +36,11 @@ /**************************************************************** ****************************************************************/ +#define LIBNETAPI_LOCAL_SERVER(x) (!x || is_myname_or_ipaddr(x)) + +/**************************************************************** +****************************************************************/ + struct libnetapi_ctx { char *debuglevel; char *error_string; @@ -57,46 +62,84 @@ NET_API_STATUS libnetapi_set_username(struct libnetapi_ctx *ctx, const char *use NET_API_STATUS libnetapi_set_password(struct libnetapi_ctx *ctx, const char *password); NET_API_STATUS libnetapi_set_workgroup(struct libnetapi_ctx *ctx, const char *workgroup); const char *libnetapi_errstr(NET_API_STATUS status); -NET_API_STATUS libnetapi_set_error_string(struct libnetapi_ctx *ctx, const char *error_string); +NET_API_STATUS libnetapi_set_error_string(struct libnetapi_ctx *ctx, const char *format, ...); const char *libnetapi_get_error_string(struct libnetapi_ctx *ctx, NET_API_STATUS status); /**************************************************************** + NetApiBufferFree ****************************************************************/ NET_API_STATUS NetApiBufferFree(void *buffer); /**************************************************************** + NetJoinDomain ****************************************************************/ -/* wkssvc */ NET_API_STATUS NetJoinDomain(const char *server, const char *domain, const char *account_ou, const char *account, const char *password, uint32_t join_options); + +/**************************************************************** + NetUnjoinDomain +****************************************************************/ + NET_API_STATUS NetUnjoinDomain(const char *server_name, const char *account, const char *password, uint32_t unjoin_flags); + +/**************************************************************** + NetGetJoinInformation +****************************************************************/ + NET_API_STATUS NetGetJoinInformation(const char *server_name, const char **name_buffer, uint16_t *name_type); -/* srvsvc */ +/**************************************************************** + NetGetJoinableOUs +****************************************************************/ + +NET_API_STATUS NetGetJoinableOUs(const char *server_name, + const char *domain, + const char *account, + const char *password, + uint32_t *ou_count, + const char ***ous); + +/**************************************************************** + NetServerGetInfo +****************************************************************/ + NET_API_STATUS NetServerGetInfo(const char *server_name, uint32_t level, uint8_t **buffer); + +/**************************************************************** + NetServerSetInfo +****************************************************************/ + NET_API_STATUS NetServerSetInfo(const char *server_name, uint32_t level, uint8_t *buffer, uint32_t *parm_error); -/* netlogon */ +/**************************************************************** + NetGetDCName +****************************************************************/ + NET_API_STATUS NetGetDCName(const char *server_name, const char *domain_name, uint8_t **buffer); + +/**************************************************************** + NetGetAnyDCName +****************************************************************/ + NET_API_STATUS NetGetAnyDCName(const char *server_name, const char *domain_name, uint8_t **buffer); diff --git a/source3/lib/netapi/serverinfo.c b/source3/lib/netapi/serverinfo.c index 67680ba55a..7fa166e411 100644 --- a/source3/lib/netapi/serverinfo.c +++ b/source3/lib/netapi/serverinfo.c @@ -22,6 +22,9 @@ #include "lib/netapi/netapi.h" #include "libnet/libnet.h" +/**************************************************************** +****************************************************************/ + static WERROR NetServerGetInfoLocal_1005(struct libnetapi_ctx *ctx, uint8_t **buffer) { @@ -36,6 +39,9 @@ static WERROR NetServerGetInfoLocal_1005(struct libnetapi_ctx *ctx, return WERR_OK; } +/**************************************************************** +****************************************************************/ + static WERROR NetServerGetInfoLocal(struct libnetapi_ctx *ctx, const char *server_name, uint32_t level, @@ -51,6 +57,9 @@ static WERROR NetServerGetInfoLocal(struct libnetapi_ctx *ctx, return WERR_UNKNOWN_LEVEL; } +/**************************************************************** +****************************************************************/ + static WERROR NetServerGetInfoRemote(struct libnetapi_ctx *ctx, const char *server_name, uint32_t level, @@ -102,6 +111,9 @@ static WERROR NetServerGetInfoRemote(struct libnetapi_ctx *ctx, return werr; } +/**************************************************************** +****************************************************************/ + static WERROR libnetapi_NetServerGetInfo(struct libnetapi_ctx *ctx, const char *server_name, uint32_t level, @@ -121,6 +133,10 @@ static WERROR libnetapi_NetServerGetInfo(struct libnetapi_ctx *ctx, } +/**************************************************************** + NetServerGetInfo +****************************************************************/ + NET_API_STATUS NetServerGetInfo(const char *server_name, uint32_t level, uint8_t **buffer) @@ -142,17 +158,18 @@ NET_API_STATUS NetServerGetInfo(const char *server_name, return W_ERROR_V(werr); } - return 0; + return NET_API_STATUS_SUCCESS; } +/**************************************************************** +****************************************************************/ + static WERROR NetServerSetInfoLocal_1005(struct libnetapi_ctx *ctx, uint8_t *buffer, uint32_t *parm_error) { WERROR werr; struct libnet_conf_ctx *conf_ctx; - TALLOC_CTX *mem_ctx; - struct srvsvc_NetSrvInfo1005 *info1005; if (!buffer) { @@ -167,12 +184,11 @@ static WERROR NetServerSetInfoLocal_1005(struct libnetapi_ctx *ctx, return WERR_INVALID_PARAM; } - if (!lp_include_registry_globals()) { + if (!lp_config_backend_is_registry()) { return WERR_NOT_SUPPORTED; } - mem_ctx = talloc_stackframe(); - werr = libnet_conf_open(mem_ctx, &conf_ctx); + werr = libnet_conf_open(ctx, &conf_ctx); if (!W_ERROR_IS_OK(werr)) { goto done; } @@ -181,12 +197,14 @@ static WERROR NetServerSetInfoLocal_1005(struct libnetapi_ctx *ctx, "server string", info1005->comment); -done: + done: libnet_conf_close(conf_ctx); - TALLOC_FREE(mem_ctx); return werr; } +/**************************************************************** +****************************************************************/ + static WERROR NetServerSetInfoLocal(struct libnetapi_ctx *ctx, const char *server_name, uint32_t level, @@ -203,6 +221,9 @@ static WERROR NetServerSetInfoLocal(struct libnetapi_ctx *ctx, return WERR_UNKNOWN_LEVEL; } +/**************************************************************** +****************************************************************/ + static WERROR NetServerSetInfoRemote(struct libnetapi_ctx *ctx, const char *server_name, uint32_t level, @@ -263,6 +284,9 @@ static WERROR NetServerSetInfoRemote(struct libnetapi_ctx *ctx, return werr; } +/**************************************************************** +****************************************************************/ + static WERROR libnetapi_NetServerSetInfo(struct libnetapi_ctx *ctx, const char *server_name, uint32_t level, @@ -284,6 +308,9 @@ static WERROR libnetapi_NetServerSetInfo(struct libnetapi_ctx *ctx, parm_error); } +/**************************************************************** + NetServerSetInfo +****************************************************************/ NET_API_STATUS NetServerSetInfo(const char *server_name, uint32_t level, @@ -308,5 +335,5 @@ NET_API_STATUS NetServerSetInfo(const char *server_name, return W_ERROR_V(werr); } - return 0; + return NET_API_STATUS_SUCCESS; } diff --git a/source3/lib/popt_common.c b/source3/lib/popt_common.c index 5a9d39d181..7f7d23fa00 100644 --- a/source3/lib/popt_common.c +++ b/source3/lib/popt_common.c @@ -71,10 +71,19 @@ static void popt_common_callback(poptContext con, } if (reason == POPT_CALLBACK_REASON_POST) { - if (!PrintSambaVersionString) return; - printf( "Version %s\n", SAMBA_VERSION_STRING); - exit(0); + if (PrintSambaVersionString) { + printf( "Version %s\n", SAMBA_VERSION_STRING); + exit(0); + } + + if (is_default_dyn_CONFIGFILE()) { + if(getenv("SMB_CONF_PATH")) { + set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH")); + } + } + + /* Further 'every Samba program must do this' hooks here. */ return; } diff --git a/source3/lib/privileges_basic.c b/source3/lib/privileges_basic.c index ea566c71eb..865c1f655c 100644 --- a/source3/lib/privileges_basic.c +++ b/source3/lib/privileges_basic.c @@ -317,6 +317,10 @@ const char* get_privilege_dispname( const char *name ) { int i; + if (!name) { + return NULL; + } + for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) { if ( strequal( privs[i].name, name ) ) { @@ -469,7 +473,7 @@ bool se_priv_to_privilege_set( PRIVILEGE_SET *set, SE_PRIV *mask ) /******************************************************************* *******************************************************************/ -static bool luid_to_se_priv( LUID *luid, SE_PRIV *mask ) +static bool luid_to_se_priv( struct lsa_LUID *luid, SE_PRIV *mask ) { int i; uint32 num_privs = count_all_privileges(); @@ -487,7 +491,7 @@ static bool luid_to_se_priv( LUID *luid, SE_PRIV *mask ) /******************************************************************* *******************************************************************/ -bool privilege_set_to_se_priv( SE_PRIV *mask, PRIVILEGE_SET *privset ) +bool privilege_set_to_se_priv( SE_PRIV *mask, struct lsa_PrivilegeSet *privset ) { int i; diff --git a/source3/lib/repdir.c b/source3/lib/repdir.c deleted file mode 100644 index 08f7d16a81..0000000000 --- a/source3/lib/repdir.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Copyright (C) Andrew Tridgell 2005 - Updated for Samba3 64-bit cleanliness (C) Jeremy Allison 2006 - - 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/>. -*/ -/* - a replacement for opendir/readdir/telldir/seekdir/closedir for BSD systems - - This is needed because the existing directory handling in FreeBSD - and OpenBSD (and possibly NetBSD) doesn't correctly handle unlink() - on files in a directory where telldir() has been used. On a block - boundary it will occasionally miss a file when seekdir() is used to - return to a position previously recorded with telldir(). - - This also fixes a severe performance and memory usage problem with - telldir() on BSD systems. Each call to telldir() in BSD adds an - entry to a linked list, and those entries are cleaned up on - closedir(). This means with a large directory closedir() can take an - arbitrary amount of time, causing network timeouts as millions of - telldir() entries are freed - - Note! This replacement code is not portable. It relies on getdents() - always leaving the file descriptor at a seek offset that is a - multiple of DIR_BUF_SIZE. If the code detects that this doesn't - happen then it will abort(). It also does not handle directories - with offsets larger than can be stored in a long, - - This code is available under other free software licenses as - well. Contact the author. -*/ - -#include <include/includes.h> - - void replace_readdir_dummy(void); - void replace_readdir_dummy(void) {} - -#if defined(REPLACE_READDIR) - -#if defined(PARANOID_MALLOC_CHECKER) -#ifdef malloc -#undef malloc -#endif -#endif - -#define DIR_BUF_BITS 9 -#define DIR_BUF_SIZE (1<<DIR_BUF_BITS) - -struct dir_buf { - int fd; - int nbytes, ofs; - SMB_OFF_T seekpos; - char buf[DIR_BUF_SIZE]; -}; - -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64) - SMB_STRUCT_DIR *opendir64(const char *dname) -#else - SMB_STRUCT_DIR *opendir(const char *dname) -#endif -{ - struct dir_buf *d; - d = malloc(sizeof(*d)); - if (d == NULL) { - errno = ENOMEM; - return NULL; - } -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64) - d->fd = open64(dname, O_RDONLY); -#else - d->fd = open(dname, O_RDONLY); -#endif - - if (d->fd == -1) { - free(d); - return NULL; - } - d->ofs = 0; - d->seekpos = 0; - d->nbytes = 0; - return (SMB_STRUCT_DIR *)d; -} - -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64) - SMB_STRUCT_DIRENT *readdir64(SMB_STRUCT_DIR *dir) -#else - SMB_STRUCT_DIRENT *readdir(SMB_STRUCT_DIR *dir) -#endif -{ - struct dir_buf *d = (struct dir_buf *)dir; - SMB_STRUCT_DIRENT *de; - - if (d->ofs >= d->nbytes) { -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_LSEEK64) - d->seekpos = lseek64(d->fd, 0, SEEK_CUR); -#else - d->seekpos = lseek(d->fd, 0, SEEK_CUR); -#endif - -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_GETDENTS64) - d->nbytes = getdents64(d->fd, d->buf, DIR_BUF_SIZE); -#else - d->nbytes = getdents(d->fd, d->buf, DIR_BUF_SIZE); -#endif - d->ofs = 0; - } - if (d->ofs >= d->nbytes) { - return NULL; - } - de = (SMB_STRUCT_DIRENT *)&d->buf[d->ofs]; - d->ofs += de->d_reclen; - return de; -} - -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64) - long telldir64(SMB_STRUCT_DIR *dir) -#else - long telldir(SMB_STRUCT_DIR *dir) -#endif -{ - struct dir_buf *d = (struct dir_buf *)dir; - if (d->ofs >= d->nbytes) { -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_LSEEK64) - d->seekpos = lseek64(d->fd, 0, SEEK_CUR); -#else - d->seekpos = lseek(d->fd, 0, SEEK_CUR); -#endif - d->ofs = 0; - d->nbytes = 0; - } - /* this relies on seekpos always being a multiple of - DIR_BUF_SIZE. Is that always true on BSD systems? */ - if (d->seekpos & (DIR_BUF_SIZE-1)) { - abort(); - } - return d->seekpos + d->ofs; -} - -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64) - void seekdir64(SMB_STRUCT_DIR *dir, long ofs) -#else - void seekdir(SMB_STRUCT_DIR *dir, long ofs) -#endif -{ - struct dir_buf *d = (struct dir_buf *)dir; -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_LSEEK64) - d->seekpos = lseek64(d->fd, ofs & ~(DIR_BUF_SIZE-1), SEEK_SET); -#else - d->seekpos = lseek(d->fd, ofs & ~(DIR_BUF_SIZE-1), SEEK_SET); -#endif - -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_GETDENTS64) - d->nbytes = getdents64(d->fd, d->buf, DIR_BUF_SIZE); -#else - d->nbytes = getdents(d->fd, d->buf, DIR_BUF_SIZE); -#endif - - d->ofs = 0; - while (d->ofs < (ofs & (DIR_BUF_SIZE-1))) { -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64) - if (readdir64(dir) == NULL) break; -#else - if (readdir(dir) == NULL) break; -#endif - } -} - -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64) - void rewinddir64(SMB_STRUCT_DIR *dir) -#else - void rewinddir(SMB_STRUCT_DIR *dir) -#endif -{ -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64) - seekdir64(dir, 0); -#else - seekdir(dir, 0); -#endif -} - -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64) - int closedir64(SMB_STRUCT_DIR *dir) -#else - int closedir(SMB_STRUCT_DIR *dir) -#endif -{ - struct dir_buf *d = (struct dir_buf *)dir; - int r = close(d->fd); - if (r != 0) { - return r; - } - free(d); - return 0; -} - -#ifndef dirfd -/* darn, this is a macro on some systems. */ - int dirfd(SMB_STRUCT_DIR *dir) -{ - struct dir_buf *d = (struct dir_buf *)dir; - return d->fd; -} -#endif -#endif /* REPLACE_READDIR */ diff --git a/source3/lib/replace/Makefile.in b/source3/lib/replace/Makefile.in index 30f39ac6cb..c989835a8d 100644 --- a/source3/lib/replace/Makefile.in +++ b/source3/lib/replace/Makefile.in @@ -10,6 +10,7 @@ VPATH = @libreplacedir@ srcdir = @srcdir@ builddir = @builddir@ INSTALL = @INSTALL@ +LIBS = @LIBS@ .PHONY: test all showflags install installcheck clean distclean realdistclean @@ -25,6 +26,7 @@ showflags: @echo ' CC = $(CC)' @echo ' CFLAGS = $(CFLAGS)' @echo ' LDFLAGS= $(LDFLAGS)' + @echo ' LIBS = $(LIBS)' install: all mkdir -p $(libdir) @@ -38,10 +40,10 @@ test: all installcheck: install test -TEST_OBJS = test/testsuite.o test/os2_delete.o test/strptime.o +TEST_OBJS = test/testsuite.o test/os2_delete.o test/strptime.o test/getifaddrs.o testsuite: libreplace.a $(TEST_OBJS) - $(CC) -o testsuite $(TEST_OBJS) -L. -lreplace $(LDFLAGS) + $(CC) -o testsuite $(TEST_OBJS) -L. -lreplace $(LDFLAGS) $(LIBS) .c.o: @echo Compiling $*.c diff --git a/source3/lib/replace/README b/source3/lib/replace/README index c61f78a951..268a1b15cf 100644 --- a/source3/lib/replace/README +++ b/source3/lib/replace/README @@ -60,6 +60,8 @@ getaddrinfo freeaddrinfo getnameinfo gai_strerror +getifaddrs +freeifaddrs Types: bool diff --git a/source3/lib/replace/configure.ac b/source3/lib/replace/configure.ac index beeb77e152..f5e054f476 100644 --- a/source3/lib/replace/configure.ac +++ b/source3/lib/replace/configure.ac @@ -3,6 +3,8 @@ AC_INIT(replace.c) AC_CONFIG_SRCDIR([replace.c]) AC_CONFIG_HEADER(config.h) +CFLAGS="$CFLAGS -I$srcdir" + AC_LIBREPLACE_ALL_CHECKS if test "$ac_cv_prog_gcc" = yes; then diff --git a/source3/lib/replace/dlfcn.c b/source3/lib/replace/dlfcn.c index 42848848e8..3b109d7e40 100644 --- a/source3/lib/replace/dlfcn.c +++ b/source3/lib/replace/dlfcn.c @@ -35,6 +35,8 @@ void *rep_dlopen(const char *name, int flags) #endif { #ifdef HAVE_SHL_LOAD + if (name == NULL) + return PROG_HANDLE; return (void *)shl_load(name, flags, 0); #else return NULL; diff --git a/source3/lib/replace/getifaddrs.c b/source3/lib/replace/getifaddrs.c new file mode 100644 index 0000000000..f6f0ec080c --- /dev/null +++ b/source3/lib/replace/getifaddrs.c @@ -0,0 +1,361 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Jeremy Allison 2007 + Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007 + + 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/>. +*/ + +#define SOCKET_WRAPPER_NOT_REPLACE + +#include "replace.h" +#include "system/network.h" + +#include <unistd.h> +#include <stdio.h> +#include <sys/types.h> + +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +#ifndef SIOCGIFCONF +#ifdef HAVE_SYS_SOCKIO_H +#include <sys/sockio.h> +#endif +#endif + +#ifdef HAVE_IFACE_GETIFADDRS +#define _FOUND_IFACE_ANY +#else + +void rep_freeifaddrs(struct ifaddrs *ifp) +{ + if (ifp != NULL) { + free(ifp->ifa_name); + free(ifp->ifa_addr); + free(ifp->ifa_netmask); + free(ifp->ifa_dstaddr); + freeifaddrs(ifp->ifa_next); + free(ifp); + } +} + +static struct sockaddr *sockaddr_dup(struct sockaddr *sa) +{ + struct sockaddr *ret; + socklen_t socklen; +#ifdef HAVE_SOCKADDR_SA_LEN + socklen = sa->sa_len; +#else + socklen = sizeof(struct sockaddr_storage); +#endif + ret = calloc(1, socklen); + if (ret == NULL) + return NULL; + memcpy(ret, sa, socklen); + return ret; +} +#endif + +#if HAVE_IFACE_IFCONF + +/* this works for Linux 2.2, Solaris 2.5, SunOS4, HPUX 10.20, OSF1 + V4.0, Ultrix 4.4, SCO Unix 3.2, IRIX 6.4 and FreeBSD 3.2. + + It probably also works on any BSD style system. */ + +int rep_getifaddrs(struct ifaddrs **ifap) +{ + struct ifconf ifc; + char buff[8192]; + int fd, i, n; + struct ifreq *ifr=NULL; + struct in_addr ipaddr; + struct in_addr nmask; + char *iname; + struct ifaddrs *curif; + struct ifaddrs *lastif = NULL; + + *ifap = NULL; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + return -1; + } + + ifc.ifc_len = sizeof(buff); + ifc.ifc_buf = buff; + + if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { + close(fd); + return -1; + } + + ifr = ifc.ifc_req; + + n = ifc.ifc_len / sizeof(struct ifreq); + + /* Loop through interfaces, looking for given IP address */ + for (i=n-1; i>=0; i--) { + if (ioctl(fd, SIOCGIFFLAGS, &ifr[i]) == -1) { + freeifaddrs(*ifap); + return -1; + } + + curif = calloc(1, sizeof(struct ifaddrs)); + curif->ifa_name = strdup(ifr[i].ifr_name); + curif->ifa_flags = ifr[i].ifr_flags; + curif->ifa_dstaddr = NULL; + curif->ifa_data = NULL; + curif->ifa_next = NULL; + + curif->ifa_addr = NULL; + if (ioctl(fd, SIOCGIFADDR, &ifr[i]) != -1) { + curif->ifa_addr = sockaddr_dup(&ifr[i].ifr_addr); + } + + curif->ifa_netmask = NULL; + if (ioctl(fd, SIOCGIFNETMASK, &ifr[i]) != -1) { + curif->ifa_netmask = sockaddr_dup(&ifr[i].ifr_addr); + } + + if (lastif == NULL) { + *ifap = curif; + } else { + lastif->ifa_next = curif; + } + lastif = curif; + } + + close(fd); + + return 0; +} + +#define _FOUND_IFACE_ANY +#endif /* HAVE_IFACE_IFCONF */ +#ifdef HAVE_IFACE_IFREQ + +#ifndef I_STR +#include <sys/stropts.h> +#endif + +/**************************************************************************** +this should cover most of the streams based systems +Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code +****************************************************************************/ +int rep_getifaddrs(struct ifaddrs **ifap) +{ + struct ifreq ifreq; + struct strioctl strioctl; + char buff[8192]; + int fd, i, n; + struct ifreq *ifr=NULL; + struct in_addr ipaddr; + struct in_addr nmask; + char *iname; + struct ifaddrs *curif; + struct ifaddrs *lastif = NULL; + + *ifap = NULL; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + return -1; + } + + strioctl.ic_cmd = SIOCGIFCONF; + strioctl.ic_dp = buff; + strioctl.ic_len = sizeof(buff); + if (ioctl(fd, I_STR, &strioctl) < 0) { + close(fd); + return -1; + } + + /* we can ignore the possible sizeof(int) here as the resulting + number of interface structures won't change */ + n = strioctl.ic_len / sizeof(struct ifreq); + + /* we will assume that the kernel returns the length as an int + at the start of the buffer if the offered size is a + multiple of the structure size plus an int */ + if (n*sizeof(struct ifreq) + sizeof(int) == strioctl.ic_len) { + ifr = (struct ifreq *)(buff + sizeof(int)); + } else { + ifr = (struct ifreq *)buff; + } + + /* Loop through interfaces */ + + for (i = 0; i<n; i++) { + ifreq = ifr[i]; + + curif = calloc(1, sizeof(struct ifaddrs)); + if (lastif == NULL) { + *ifap = curif; + } else { + lastif->ifa_next = curif; + } + + strioctl.ic_cmd = SIOCGIFFLAGS; + strioctl.ic_dp = (char *)&ifreq; + strioctl.ic_len = sizeof(struct ifreq); + if (ioctl(fd, I_STR, &strioctl) != 0) { + freeifaddrs(*ifap); + return -1; + } + + curif->ifa_flags = ifreq.ifr_flags; + + strioctl.ic_cmd = SIOCGIFADDR; + strioctl.ic_dp = (char *)&ifreq; + strioctl.ic_len = sizeof(struct ifreq); + if (ioctl(fd, I_STR, &strioctl) != 0) { + freeifaddrs(*ifap); + return -1; + } + + curif->ifa_name = strdup(ifreq.ifr_name); + curif->ifa_addr = sockaddr_dup(&ifreq.ifr_addr); + curif->ifa_dstaddr = NULL; + curif->ifa_data = NULL; + curif->ifa_next = NULL; + curif->ifa_netmask = NULL; + + strioctl.ic_cmd = SIOCGIFNETMASK; + strioctl.ic_dp = (char *)&ifreq; + strioctl.ic_len = sizeof(struct ifreq); + if (ioctl(fd, I_STR, &strioctl) != 0) { + freeifaddrs(*ifap); + return -1; + } + + curif->ifa_netmask = sockaddr_dup(&ifreq.ifr_addr); + + lastif = curif; + } + + close(fd); + + return 0; +} + +#define _FOUND_IFACE_ANY +#endif /* HAVE_IFACE_IFREQ */ +#ifdef HAVE_IFACE_AIX + +/**************************************************************************** +this one is for AIX (tested on 4.2) +****************************************************************************/ +int rep_getifaddrs(struct ifaddrs **ifap) +{ + char buff[8192]; + int fd, i; + struct ifconf ifc; + struct ifreq *ifr=NULL; + struct in_addr ipaddr; + struct in_addr nmask; + char *iname; + struct ifaddrs *curif; + struct ifaddrs *lastif = NULL; + + *ifap = NULL; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + return -1; + } + + ifc.ifc_len = sizeof(buff); + ifc.ifc_buf = buff; + + if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { + close(fd); + return -1; + } + + ifr = ifc.ifc_req; + + /* Loop through interfaces */ + i = ifc.ifc_len; + + while (i > 0) { + uint_t inc; + + inc = ifr->ifr_addr.sa_len; + + if (ioctl(fd, SIOCGIFADDR, ifr) != 0) { + freeaddrinfo(*ifap); + return -1; + } + + curif = calloc(1, sizeof(struct ifaddrs)); + if (lastif == NULL) { + *ifap = curif; + } else { + lastif->ifa_next = curif; + } + + curif->ifa_name = strdup(ifr->ifr_name); + curif->ifa_addr = sockaddr_dup(&ifr->ifr_addr); + curif->ifa_dstaddr = NULL; + curif->ifa_data = NULL; + curif->ifa_netmask = NULL; + curif->ifa_next = NULL; + + if (ioctl(fd, SIOCGIFFLAGS, ifr) != 0) { + freeaddrinfo(*ifap); + return -1; + } + + curif->ifa_flags = ifr->ifr_flags; + + if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) { + freeaddrinfo(*ifap); + return -1; + } + + curif->ifa_netmask = sockaddr_dup(&ifr->ifr_addr); + + lastif = curif; + + next: + /* + * Patch from Archie Cobbs (archie@whistle.com). The + * addresses in the SIOCGIFCONF interface list have a + * minimum size. Usually this doesn't matter, but if + * your machine has tunnel interfaces, etc. that have + * a zero length "link address", this does matter. */ + + if (inc < sizeof(ifr->ifr_addr)) + inc = sizeof(ifr->ifr_addr); + inc += IFNAMSIZ; + + ifr = (struct ifreq*) (((char*) ifr) + inc); + i -= inc; + } + + close(fd); + return 0; +} + +#define _FOUND_IFACE_ANY +#endif /* HAVE_IFACE_AIX */ +#ifndef _FOUND_IFACE_ANY +int rep_getifaddrs(struct ifaddrs **ifap) +{ + errno = ENOSYS; + return -1; +} +#endif diff --git a/source3/lib/replace/getifaddrs.m4 b/source3/lib/replace/getifaddrs.m4 new file mode 100644 index 0000000000..6cca155de3 --- /dev/null +++ b/source3/lib/replace/getifaddrs.m4 @@ -0,0 +1,127 @@ +AC_CHECK_HEADERS([ifaddrs.h]) + +dnl Used when getifaddrs is not available +AC_CHECK_MEMBERS([struct sockaddr.sa_len], + [AC_DEFINE(HAVE_SOCKADDR_SA_LEN, 1, [Whether struct sockaddr has a sa_len member])], + [], + [#include <sys/socket.h>]) + +dnl test for getifaddrs and freeifaddrs +AC_CACHE_CHECK([for getifaddrs and freeifaddrs],libreplace_cv_HAVE_GETIFADDRS,[ +AC_TRY_COMPILE([ +#include <sys/types.h> +#if STDC_HEADERS +#include <stdlib.h> +#include <stddef.h> +#endif +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <ifaddrs.h> +#include <netdb.h>], +[ +struct ifaddrs *ifp = NULL; +int ret = getifaddrs (&ifp); +freeifaddrs(ifp); +], +libreplace_cv_HAVE_GETIFADDRS=yes,libreplace_cv_HAVE_GETIFADDRS=no)]) +if test x"$libreplace_cv_HAVE_GETIFADDRS" = x"yes"; then + AC_DEFINE(HAVE_GETIFADDRS,1,[Whether the system has getifaddrs]) + AC_DEFINE(HAVE_FREEIFADDRS,1,[Whether the system has freeifaddrs]) + AC_DEFINE(HAVE_STRUCT_IFADDRS,1,[Whether struct ifaddrs is available]) +fi + +################## +# look for a method of finding the list of network interfaces +# +# This tests need LIBS="$NSL_LIBS $SOCKET_LIBS" +# +old_LIBS=$LIBS +LIBS="$NSL_LIBS $SOCKET_LIBS" +iface=no; +################## +# look for a method of finding the list of network interfaces +iface=no; +AC_CACHE_CHECK([for iface getifaddrs],libreplace_cv_HAVE_IFACE_GETIFADDRS,[ +AC_TRY_RUN([ +#define HAVE_IFACE_GETIFADDRS 1 +#define NO_CONFIG_H 1 +#define AUTOCONF_TEST 1 +#define SOCKET_WRAPPER_NOT_REPLACE +#include "$libreplacedir/replace.c" +#include "$libreplacedir/inet_ntop.c" +#include "$libreplacedir/snprintf.c" +#include "$libreplacedir/getifaddrs.c" +#define getifaddrs_test main +#include "$libreplacedir/test/getifaddrs.c"], + libreplace_cv_HAVE_IFACE_GETIFADDRS=yes,libreplace_cv_HAVE_IFACE_GETIFADDRS=no,libreplace_cv_HAVE_IFACE_GETIFADDRS=cross)]) +if test x"$libreplace_cv_HAVE_IFACE_GETIFADDRS" = x"yes"; then + iface=yes;AC_DEFINE(HAVE_IFACE_GETIFADDRS,1,[Whether iface getifaddrs is available]) +else + LIBREPLACEOBJ="${LIBREPLACEOBJ} getifaddrs.o" +fi + + +if test $iface = no; then +AC_CACHE_CHECK([for iface AIX],libreplace_cv_HAVE_IFACE_AIX,[ +AC_TRY_RUN([ +#define HAVE_IFACE_AIX 1 +#define NO_CONFIG_H 1 +#define AUTOCONF_TEST 1 +#undef _XOPEN_SOURCE_EXTENDED +#define SOCKET_WRAPPER_NOT_REPLACE +#include "$libreplacedir/replace.c" +#include "$libreplacedir/inet_ntop.c" +#include "$libreplacedir/snprintf.c" +#include "$libreplacedir/getifaddrs.c" +#define getifaddrs_test main +#include "$libreplacedir/test/getifaddrs.c"], + libreplace_cv_HAVE_IFACE_AIX=yes,libreplace_cv_HAVE_IFACE_AIX=no,libreplace_cv_HAVE_IFACE_AIX=cross)]) +if test x"$libreplace_cv_HAVE_IFACE_AIX" = x"yes"; then + iface=yes;AC_DEFINE(HAVE_IFACE_AIX,1,[Whether iface AIX is available]) + old_LIBS="$old_LIBS $LIBS" +fi +fi + + +if test $iface = no; then +AC_CACHE_CHECK([for iface ifconf],libreplace_cv_HAVE_IFACE_IFCONF,[ +AC_TRY_RUN([ +#define HAVE_IFACE_IFCONF 1 +#define NO_CONFIG_H 1 +#define AUTOCONF_TEST 1 +#define SOCKET_WRAPPER_NOT_REPLACE +#include "$libreplacedir/replace.c" +#include "$libreplacedir/inet_ntop.c" +#include "$libreplacedir/snprintf.c" +#include "$libreplacedir/getifaddrs.c" +#define getifaddrs_test main +#include "$libreplacedir/test/getifaddrs.c"], + libreplace_cv_HAVE_IFACE_IFCONF=yes,libreplace_cv_HAVE_IFACE_IFCONF=no,libreplace_cv_HAVE_IFACE_IFCONF=cross)]) +if test x"$libreplace_cv_HAVE_IFACE_IFCONF" = x"yes"; then + iface=yes;AC_DEFINE(HAVE_IFACE_IFCONF,1,[Whether iface ifconf is available]) + old_LIBS="$old_LIBS $LIBS" +fi +fi + +if test $iface = no; then +AC_CACHE_CHECK([for iface ifreq],libreplace_cv_HAVE_IFACE_IFREQ,[ +AC_TRY_RUN([ +#define HAVE_IFACE_IFREQ 1 +#define NO_CONFIG_H 1 +#define AUTOCONF_TEST 1 +#define SOCKET_WRAPPER_NOT_REPLACE +#include "$libreplacedir/replace.c" +#include "$libreplacedir/inet_ntop.c" +#include "$libreplacedir/snprintf.c" +#include "$libreplacedir/getifaddrs.c" +#define getifaddrs_test main +#include "$libreplacedir/test/getifaddrs.c"], + libreplace_cv_HAVE_IFACE_IFREQ=yes,libreplace_cv_HAVE_IFACE_IFREQ=no,libreplace_cv_HAVE_IFACE_IFREQ=cross)]) +if test x"$libreplace_cv_HAVE_IFACE_IFREQ" = x"yes"; then + iface=yes;AC_DEFINE(HAVE_IFACE_IFREQ,1,[Whether iface ifreq is available]) + old_LIBS="$old_LIBS $LIBS" +fi +fi + +LIBS=$old_LIBS diff --git a/source3/lib/replace/getpass.c b/source3/lib/replace/getpass.c index d91d029f6a..57e28eb981 100644 --- a/source3/lib/replace/getpass.c +++ b/source3/lib/replace/getpass.c @@ -185,7 +185,10 @@ char *rep_getpass(const char *prompt) buf[0] = 0; if (!gotintr) { in_fd = fileno(in); - fgets(buf, bufsize, in); + if (fgets(buf, bufsize, in) == NULL) { + buf[0] = 0; + return buf; + } } nread = strlen(buf); if (nread) { diff --git a/source3/lib/replace/getpass.m4 b/source3/lib/replace/getpass.m4 index c4da9aae59..b93817f9d3 100644 --- a/source3/lib/replace/getpass.m4 +++ b/source3/lib/replace/getpass.m4 @@ -1,22 +1,22 @@ -AC_CHECK_FUNC(getpass, samba_cv_HAVE_GETPASS=yes) -AC_CHECK_FUNC(getpassphrase, samba_cv_HAVE_GETPASSPHRASE=yes) -if test x"$samba_cv_HAVE_GETPASS" = x"yes" -a x"$samba_cv_HAVE_GETPASSPHRASE" = x"yes"; then +AC_CHECK_FUNC(getpass, libreplace_cv_HAVE_GETPASS=yes) +AC_CHECK_FUNC(getpassphrase, libreplace_cv_HAVE_GETPASSPHRASE=yes) +if test x"$libreplace_cv_HAVE_GETPASS" = x"yes" -a x"$libreplace_cv_HAVE_GETPASSPHRASE" = x"yes"; then AC_DEFINE(REPLACE_GETPASS_BY_GETPASSPHRASE, 1, [getpass returns <9 chars where getpassphrase returns <265 chars]) AC_DEFINE(REPLACE_GETPASS,1,[Whether getpass should be replaced]) LIBREPLACEOBJ="${LIBREPLACEOBJ} getpass.o" else -AC_CACHE_CHECK([whether getpass should be replaced],samba_cv_REPLACE_GETPASS,[ +AC_CACHE_CHECK([whether getpass should be replaced],libreplace_cv_REPLACE_GETPASS,[ SAVE_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -I$libreplacedir/" AC_TRY_COMPILE([ #include "confdefs.h" #define NO_CONFIG_H #include "$libreplacedir/getpass.c" -],[],samba_cv_REPLACE_GETPASS=yes,samba_cv_REPLACE_GETPASS=no) +],[],libreplace_cv_REPLACE_GETPASS=yes,libreplace_cv_REPLACE_GETPASS=no) CPPFLAGS="$SAVE_CPPFLAGS" ]) -if test x"$samba_cv_REPLACE_GETPASS" = x"yes"; then +if test x"$libreplace_cv_REPLACE_GETPASS" = x"yes"; then AC_DEFINE(REPLACE_GETPASS,1,[Whether getpass should be replaced]) LIBREPLACEOBJ="${LIBREPLACEOBJ} getpass.o" fi diff --git a/source3/lib/replace/libreplace.m4 b/source3/lib/replace/libreplace.m4 index 7a5283a4d6..e0cc57f4c8 100644 --- a/source3/lib/replace/libreplace.m4 +++ b/source3/lib/replace/libreplace.m4 @@ -85,10 +85,10 @@ AC_INCLUDES_DEFAULT #endif] ) -AC_CACHE_CHECK([for working mmap],samba_cv_HAVE_MMAP,[ +AC_CACHE_CHECK([for working mmap],libreplace_cv_HAVE_MMAP,[ AC_TRY_RUN([#include "$libreplacedir/test/shared_mmap.c"], - samba_cv_HAVE_MMAP=yes,samba_cv_HAVE_MMAP=no,samba_cv_HAVE_MMAP=cross)]) -if test x"$samba_cv_HAVE_MMAP" = x"yes"; then + libreplace_cv_HAVE_MMAP=yes,libreplace_cv_HAVE_MMAP=no,libreplace_cv_HAVE_MMAP=cross)]) +if test x"$libreplace_cv_HAVE_MMAP" = x"yes"; then AC_DEFINE(HAVE_MMAP,1,[Whether mmap works]) fi @@ -120,7 +120,7 @@ if test x"$libreplace_cv_USABLE_NET_IF_H" = x"yes";then AC_DEFINE(HAVE_NET_IF_H, 1, usability of net/if.h) fi -AC_CACHE_CHECK([for broken inet_ntoa],samba_cv_REPLACE_INET_NTOA,[ +AC_CACHE_CHECK([for broken inet_ntoa],libreplace_cv_REPLACE_INET_NTOA,[ AC_TRY_RUN([ #include <stdio.h> #include <unistd.h> @@ -133,8 +133,8 @@ main() { struct in_addr ip; ip.s_addr = 0x12345678; if (strcmp(inet_ntoa(ip),"18.52.86.120") && strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(0); } exit(1);}], - samba_cv_REPLACE_INET_NTOA=yes,samba_cv_REPLACE_INET_NTOA=no,samba_cv_REPLACE_INET_NTOA=cross)]) -if test x"$samba_cv_REPLACE_INET_NTOA" = x"yes"; then + libreplace_cv_REPLACE_INET_NTOA=yes,libreplace_cv_REPLACE_INET_NTOA=no,libreplace_cv_REPLACE_INET_NTOA=cross)]) +if test x"$libreplace_cv_REPLACE_INET_NTOA" = x"yes"; then AC_DEFINE(REPLACE_INET_NTOA,1,[Whether inet_ntoa should be replaced]) fi @@ -153,6 +153,26 @@ AC_HAVE_TYPE([struct sockaddr_in6], [ #include <netinet/in.h> ]) +if test x"$ac_cv_type_struct_sockaddr_storage" = x"yes"; then +AC_CHECK_MEMBER(struct sockaddr_storage.ss_family, + AC_DEFINE(HAVE_SS_FAMILY, 1, [Defined if struct sockaddr_storage has ss_family field]),, + [ +#include <sys/socket.h> +#include <sys/types.h> +#include <netinet/in.h> + ]) + +if test x"$ac_cv_member_struct_sockaddr_storage_ss_family" != x"yes"; then +AC_CHECK_MEMBER(struct sockaddr_storage.__ss_family, + AC_DEFINE(HAVE___SS_FAMILY, 1, [Defined if struct sockaddr_storage has __ss_family field]),, + [ +#include <sys/socket.h> +#include <sys/types.h> +#include <netinet/in.h> + ]) +fi +fi + AC_CHECK_FUNCS(seteuid setresuid setegid setresgid chroot bzero strerror) AC_CHECK_FUNCS(vsyslog setlinebuf mktime ftruncate chsize rename) AC_CHECK_FUNCS(waitpid strlcpy strlcat initgroups memmove strdup) @@ -162,7 +182,7 @@ AC_HAVE_DECL(setresuid, [#include <unistd.h>]) AC_HAVE_DECL(setresgid, [#include <unistd.h>]) AC_HAVE_DECL(errno, [#include <errno.h>]) -AC_CACHE_CHECK([for secure mkstemp],samba_cv_HAVE_SECURE_MKSTEMP,[ +AC_CACHE_CHECK([for secure mkstemp],libreplace_cv_HAVE_SECURE_MKSTEMP,[ AC_TRY_RUN([#include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> @@ -177,10 +197,10 @@ main() { if ((st.st_mode & 0777) != 0600) exit(1); exit(0); }], -samba_cv_HAVE_SECURE_MKSTEMP=yes, -samba_cv_HAVE_SECURE_MKSTEMP=no, -samba_cv_HAVE_SECURE_MKSTEMP=cross)]) -if test x"$samba_cv_HAVE_SECURE_MKSTEMP" = x"yes"; then +libreplace_cv_HAVE_SECURE_MKSTEMP=yes, +libreplace_cv_HAVE_SECURE_MKSTEMP=no, +libreplace_cv_HAVE_SECURE_MKSTEMP=cross)]) +if test x"$libreplace_cv_HAVE_SECURE_MKSTEMP" = x"yes"; then AC_DEFINE(HAVE_SECURE_MKSTEMP,1,[Whether mkstemp is secure]) fi @@ -189,7 +209,7 @@ AC_CHECK_HEADERS(stdio.h strings.h) AC_CHECK_DECLS([snprintf, vsnprintf, asprintf, vasprintf]) AC_CHECK_FUNCS(snprintf vsnprintf asprintf vasprintf) -AC_CACHE_CHECK([for C99 vsnprintf],samba_cv_HAVE_C99_VSNPRINTF,[ +AC_CACHE_CHECK([for C99 vsnprintf],libreplace_cv_HAVE_C99_VSNPRINTF,[ AC_TRY_RUN([ #include <sys/types.h> #include <stdio.h> @@ -223,43 +243,43 @@ void foo(const char *format, ...) { } main() { foo("hello"); } ], -samba_cv_HAVE_C99_VSNPRINTF=yes,samba_cv_HAVE_C99_VSNPRINTF=no,samba_cv_HAVE_C99_VSNPRINTF=cross)]) -if test x"$samba_cv_HAVE_C99_VSNPRINTF" = x"yes"; then +libreplace_cv_HAVE_C99_VSNPRINTF=yes,libreplace_cv_HAVE_C99_VSNPRINTF=no,libreplace_cv_HAVE_C99_VSNPRINTF=cross)]) +if test x"$libreplace_cv_HAVE_C99_VSNPRINTF" = x"yes"; then AC_DEFINE(HAVE_C99_VSNPRINTF,1,[Whether there is a C99 compliant vsnprintf]) fi dnl VA_COPY -AC_CACHE_CHECK([for va_copy],samba_cv_HAVE_VA_COPY,[ +AC_CACHE_CHECK([for va_copy],libreplace_cv_HAVE_VA_COPY,[ AC_TRY_LINK([#include <stdarg.h> va_list ap1,ap2;], [va_copy(ap1,ap2);], -samba_cv_HAVE_VA_COPY=yes,samba_cv_HAVE_VA_COPY=no)]) -if test x"$samba_cv_HAVE_VA_COPY" = x"yes"; then +libreplace_cv_HAVE_VA_COPY=yes,libreplace_cv_HAVE_VA_COPY=no)]) +if test x"$libreplace_cv_HAVE_VA_COPY" = x"yes"; then AC_DEFINE(HAVE_VA_COPY,1,[Whether va_copy() is available]) fi -if test x"$samba_cv_HAVE_VA_COPY" != x"yes"; then -AC_CACHE_CHECK([for __va_copy],samba_cv_HAVE___VA_COPY,[ +if test x"$libreplace_cv_HAVE_VA_COPY" != x"yes"; then +AC_CACHE_CHECK([for __va_copy],libreplace_cv_HAVE___VA_COPY,[ AC_TRY_LINK([#include <stdarg.h> va_list ap1,ap2;], [__va_copy(ap1,ap2);], -samba_cv_HAVE___VA_COPY=yes,samba_cv_HAVE___VA_COPY=no)]) -if test x"$samba_cv_HAVE___VA_COPY" = x"yes"; then +libreplace_cv_HAVE___VA_COPY=yes,libreplace_cv_HAVE___VA_COPY=no)]) +if test x"$libreplace_cv_HAVE___VA_COPY" = x"yes"; then AC_DEFINE(HAVE___VA_COPY,1,[Whether __va_copy() is available]) fi fi dnl __FUNCTION__ macro -AC_CACHE_CHECK([for __FUNCTION__ macro],samba_cv_HAVE_FUNCTION_MACRO,[ +AC_CACHE_CHECK([for __FUNCTION__ macro],libreplace_cv_HAVE_FUNCTION_MACRO,[ AC_TRY_COMPILE([#include <stdio.h>], [printf("%s\n", __FUNCTION__);], -samba_cv_HAVE_FUNCTION_MACRO=yes,samba_cv_HAVE_FUNCTION_MACRO=no)]) -if test x"$samba_cv_HAVE_FUNCTION_MACRO" = x"yes"; then +libreplace_cv_HAVE_FUNCTION_MACRO=yes,libreplace_cv_HAVE_FUNCTION_MACRO=no)]) +if test x"$libreplace_cv_HAVE_FUNCTION_MACRO" = x"yes"; then AC_DEFINE(HAVE_FUNCTION_MACRO,1,[Whether there is a __FUNCTION__ macro]) else dnl __func__ macro - AC_CACHE_CHECK([for __func__ macro],samba_cv_HAVE_func_MACRO,[ + AC_CACHE_CHECK([for __func__ macro],libreplace_cv_HAVE_func_MACRO,[ AC_TRY_COMPILE([#include <stdio.h>], [printf("%s\n", __func__);], - samba_cv_HAVE_func_MACRO=yes,samba_cv_HAVE_func_MACRO=no)]) - if test x"$samba_cv_HAVE_func_MACRO" = x"yes"; then + libreplace_cv_HAVE_func_MACRO=yes,libreplace_cv_HAVE_func_MACRO=no)]) + if test x"$libreplace_cv_HAVE_func_MACRO" = x"yes"; then AC_DEFINE(HAVE_func_MACRO,1,[Whether there is a __func__ macro]) fi fi @@ -282,7 +302,7 @@ eprintf("bla", "bar"); ], AC_DEFINE(HAVE__VA_ARGS__MACRO, 1, [Whether the __VA_ARGS__ macro is available])) -AC_CACHE_CHECK([for sig_atomic_t type],samba_cv_sig_atomic_t, [ +AC_CACHE_CHECK([for sig_atomic_t type],libreplace_cv_sig_atomic_t, [ AC_TRY_COMPILE([ #include <sys/types.h> #if STDC_HEADERS @@ -290,30 +310,30 @@ AC_CACHE_CHECK([for sig_atomic_t type],samba_cv_sig_atomic_t, [ #include <stddef.h> #endif #include <signal.h>],[sig_atomic_t i = 0], - samba_cv_sig_atomic_t=yes,samba_cv_sig_atomic_t=no)]) -if test x"$samba_cv_sig_atomic_t" = x"yes"; then + libreplace_cv_sig_atomic_t=yes,libreplace_cv_sig_atomic_t=no)]) +if test x"$libreplace_cv_sig_atomic_t" = x"yes"; then AC_DEFINE(HAVE_SIG_ATOMIC_T_TYPE,1,[Whether we have the atomic_t variable type]) fi -AC_CACHE_CHECK([for O_DIRECT flag to open(2)],samba_cv_HAVE_OPEN_O_DIRECT,[ +AC_CACHE_CHECK([for O_DIRECT flag to open(2)],libreplace_cv_HAVE_OPEN_O_DIRECT,[ AC_TRY_COMPILE([ #include <unistd.h> #ifdef HAVE_FCNTL_H #include <fcntl.h> #endif], [int fd = open("/dev/null", O_DIRECT);], -samba_cv_HAVE_OPEN_O_DIRECT=yes,samba_cv_HAVE_OPEN_O_DIRECT=no)]) -if test x"$samba_cv_HAVE_OPEN_O_DIRECT" = x"yes"; then +libreplace_cv_HAVE_OPEN_O_DIRECT=yes,libreplace_cv_HAVE_OPEN_O_DIRECT=no)]) +if test x"$libreplace_cv_HAVE_OPEN_O_DIRECT" = x"yes"; then AC_DEFINE(HAVE_OPEN_O_DIRECT,1,[Whether the open(2) accepts O_DIRECT]) fi dnl Check if the C compiler understands volatile (it should, being ANSI). -AC_CACHE_CHECK([that the C compiler understands volatile],samba_cv_volatile, [ +AC_CACHE_CHECK([that the C compiler understands volatile],libreplace_cv_volatile, [ AC_TRY_COMPILE([#include <sys/types.h>],[volatile int i = 0], - samba_cv_volatile=yes,samba_cv_volatile=no)]) -if test x"$samba_cv_volatile" = x"yes"; then + libreplace_cv_volatile=yes,libreplace_cv_volatile=no)]) +if test x"$libreplace_cv_volatile" = x"yes"; then AC_DEFINE(HAVE_VOLATILE, 1, [Whether the C compiler understands volatile]) fi @@ -324,10 +344,12 @@ m4_include(getpass.m4) m4_include(strptime.m4) m4_include(win32.m4) m4_include(timegm.m4) +m4_include(socket.m4) m4_include(inet_ntop.m4) m4_include(inet_pton.m4) m4_include(getaddrinfo.m4) m4_include(repdir.m4) +m4_include(getifaddrs.m4) AC_CHECK_FUNCS([syslog printf memset memcpy],,[AC_MSG_ERROR([Required function not found])]) diff --git a/source3/lib/replace/libreplace_cc.m4 b/source3/lib/replace/libreplace_cc.m4 index a01bf1b290..bf5056838d 100644 --- a/source3/lib/replace/libreplace_cc.m4 +++ b/source3/lib/replace/libreplace_cc.m4 @@ -48,8 +48,7 @@ LIBREPLACE_C99_STRUCT_INIT([],[AC_MSG_WARN([c99 structure initializer are not su AC_PROG_INSTALL AC_ISC_POSIX -AC_EXTENSION_FLAG(_XOPEN_SOURCE_EXTENDED) -AC_EXTENSION_FLAG(_OSF_SOURCE) +AC_N_DEFINE(_XOPEN_SOURCE_EXTENDED) AC_SYS_LARGEFILE @@ -77,6 +76,11 @@ case "$host_os" in CFLAGS="$CFLAGS -D_LINUX_SOURCE_COMPAT -qmaxmem=32000" fi ;; + *osf*) + # this brings in socklen_t + AC_N_DEFINE(_XOPEN_SOURCE,600) + AC_N_DEFINE(_OSF_SOURCE) + ;; # # VOS may need to have POSIX support and System V compatibility enabled. # diff --git a/source3/lib/replace/libreplace_ld.m4 b/source3/lib/replace/libreplace_ld.m4 index cb8e21434e..f0d10c1e3e 100644 --- a/source3/lib/replace/libreplace_ld.m4 +++ b/source3/lib/replace/libreplace_ld.m4 @@ -265,7 +265,7 @@ AC_DEFUN([AC_LIBREPLACE_LD_SHLIB_ALLOW_UNDEF_FLAG], LD_SHLIB_ALLOW_UNDEF_FLAG="-Wl,--allow-shlib-undefined" ;; *osf*) - LD_SHLIB_ALLOW_UNDEF_FLAG="-expect_unresolved '*'" + LD_SHLIB_ALLOW_UNDEF_FLAG="-Wl,-expect_unresolved,\"*\"" ;; *darwin*) LD_SHLIB_ALLOW_UNDEF_FLAG="-undefined dynamic_lookup" @@ -289,6 +289,9 @@ AC_DEFUN([AC_LIBREPLACE_RUNTIME_LIB_PATH_VAR], *linux*) LIB_PATH_VAR=LD_LIBRARY_PATH ;; + *netbsd*) + LIB_PATH_VAR=LD_LIBRARY_PATH + ;; *solaris*) LIB_PATH_VAR=LD_LIBRARY_PATH ;; diff --git a/source3/lib/replace/libreplace_macros.m4 b/source3/lib/replace/libreplace_macros.m4 index 92fecd3db8..1856eacf66 100644 --- a/source3/lib/replace/libreplace_macros.m4 +++ b/source3/lib/replace/libreplace_macros.m4 @@ -87,19 +87,6 @@ fi rm -f conftest* ])]) -AC_DEFUN([AC_EXTENSION_FLAG], -[ - cat >>confdefs.h <<\EOF -#ifndef $1 -# define $1 1 -#endif -EOF -AH_VERBATIM([$1], [#ifndef $1 -# define $1 1 -#endif]) -]) - - dnl see if a declaration exists for a function or variable dnl defines HAVE_function_DECL if it exists dnl AC_HAVE_DECL(var, includes) @@ -248,11 +235,18 @@ m4_define([AH_CHECK_FUNC_EXT], dnl Define an AC_DEFINE with ifndef guard. dnl AC_N_DEFINE(VARIABLE [, VALUE]) -define(AC_N_DEFINE, -[cat >> confdefs.h <<\EOF -[#ifndef] $1 -[#define] $1 ifelse($#, 2, [$2], $#, 3, [$2], 1) -[#endif] +AC_DEFUN([AC_N_DEFINE], +[ +AH_VERBATIM([$1], [ +#ifndef $1 +# undef $1 +#endif +]) + + cat >>confdefs.h <<\EOF +#ifndef $1 +[#define] $1 m4_if($#, 1, 1, [$2]) +#endif EOF ]) diff --git a/source3/lib/replace/replace.h b/source3/lib/replace/replace.h index 1d1cbc2cd2..0d16f4ffd0 100644 --- a/source3/lib/replace/replace.h +++ b/source3/lib/replace/replace.h @@ -340,6 +340,26 @@ ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset) /* prototype is in "system/network.h" */ #endif +#ifndef HAVE_CONNECT +#define connect rep_connect +/* prototype is in "system/network.h" */ +#endif + +#ifndef HAVE_GETHOSTBYNAME +#define gethostbyname rep_gethostbyname +/* prototype is in "system/network.h" */ +#endif + +#ifndef HAVE_GETIFADDRS +#define getifaddrs rep_getifaddrs +/* prototype is in "system/network.h" */ +#endif + +#ifndef HAVE_FREEIFADDRS +#define freeifaddrs rep_freeifaddrs +/* prototype is in "system/network.h" */ +#endif + #ifdef HAVE_LIMITS_H #include <limits.h> #endif diff --git a/source3/lib/replace/socket.c b/source3/lib/replace/socket.c new file mode 100644 index 0000000000..35e975fce7 --- /dev/null +++ b/source3/lib/replace/socket.c @@ -0,0 +1,35 @@ +/* + * Unix SMB/CIFS implementation. + * + * Dummy replacements for socket functions. + * + * Copyright (C) Michael Adam <obnox@samba.org> 2008 + * + * 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 "replace.h" +#include "system/network.h" + +int rep_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) +{ + errno = ENOSYS; + return -1; +} + +struct hostent *rep_gethostbyname(const char *name) +{ + errno = ENOSYS; + return NULL; +} diff --git a/source3/lib/replace/socket.m4 b/source3/lib/replace/socket.m4 new file mode 100644 index 0000000000..c0c8f93e81 --- /dev/null +++ b/source3/lib/replace/socket.m4 @@ -0,0 +1,40 @@ +dnl The following test is roughl taken from the cvs sources. +dnl +dnl If we can't find connect, try looking in -lsocket, -lnsl, and -linet. +dnl The Irix 5 libc.so has connect and gethostbyname, but Irix 5 also has +dnl libsocket.so which has a bad implementation of gethostbyname (it +dnl only looks in /etc/hosts), so we only look for -lsocket if we need +dnl it. +AC_CHECK_FUNCS(connect) +if test x"$ac_cv_func_connect" = x"no"; then + AC_CHECK_LIB_EXT(nsl_s, SOCKET_LIBS, connect) + AC_CHECK_LIB_EXT(nsl, SOCKET_LIBS, connect) + AC_CHECK_LIB_EXT(socket, SOCKET_LIBS, connect) + AC_CHECK_LIB_EXT(inet, SOCKET_LIBS, connect) + dnl We can't just call AC_CHECK_FUNCS(connect) here, + dnl because the value has been cached. + if test x"$ac_cv_lib_ext_nsl_s_connect" = x"yes" || + test x"$ac_cv_lib_ext_nsl_connect" = x"yes" || + test x"$ac_cv_lib_ext_socket_connect" = x"yes" || + test x"$ac_cv_lib_ext_inet_connect" = x"yes" + then + AC_DEFINE(HAVE_CONNECT,1,[Whether the system has connect()]) + fi +fi + +AC_CHECK_FUNCS(gethostbyname) +if test x"$ac_cv_func_gethostbyname" = x"no"; then + AC_CHECK_LIB_EXT(nsl_s, NSL_LIBS, gethostbyname) + AC_CHECK_LIB_EXT(nsl, NSL_LIBS, gethostbyname) + AC_CHECK_LIB_EXT(socket, NSL_LIBS, gethostbyname) + dnl We can't just call AC_CHECK_FUNCS(gethostbyname) here, + dnl because the value has been cached. + if test x"$ac_cv_lib_ext_nsl_s_gethostbyname" = x"yes" || + test x"$ac_cv_lib_ext_nsl_gethostbyname" = x"yes" || + test x"$ac_cv_lib_ext_socket_gethostbyname" = x"yes" + then + AC_DEFINE(HAVE_GETHOSTBYNAME,1, + [Whether the system has gethostbyname()]) + fi +fi + diff --git a/source3/lib/replace/system/config.m4 b/source3/lib/replace/system/config.m4 index 799187af7d..66c2bd652a 100644 --- a/source3/lib/replace/system/config.m4 +++ b/source3/lib/replace/system/config.m4 @@ -18,7 +18,7 @@ AC_CHECK_HEADERS(sys/capability.h) case "$host_os" in *linux*) -AC_CACHE_CHECK([for broken RedHat 7.2 system header files],samba_cv_BROKEN_REDHAT_7_SYSTEM_HEADERS,[ +AC_CACHE_CHECK([for broken RedHat 7.2 system header files],libreplace_cv_BROKEN_REDHAT_7_SYSTEM_HEADERS,[ AC_TRY_COMPILE([ #ifdef HAVE_SYS_VFS_H #include <sys/vfs.h> @@ -29,14 +29,14 @@ AC_TRY_COMPILE([ ],[ int i; ], - samba_cv_BROKEN_REDHAT_7_SYSTEM_HEADERS=no, - samba_cv_BROKEN_REDHAT_7_SYSTEM_HEADERS=yes + libreplace_cv_BROKEN_REDHAT_7_SYSTEM_HEADERS=no, + libreplace_cv_BROKEN_REDHAT_7_SYSTEM_HEADERS=yes )]) -if test x"$samba_cv_BROKEN_REDHAT_7_SYSTEM_HEADERS" = x"yes"; then +if test x"$libreplace_cv_BROKEN_REDHAT_7_SYSTEM_HEADERS" = x"yes"; then AC_DEFINE(BROKEN_REDHAT_7_SYSTEM_HEADERS,1,[Broken RedHat 7.2 system header files]) fi -AC_CACHE_CHECK([for broken RHEL5 sys/capability.h],samba_cv_BROKEN_RHEL5_SYS_CAP_HEADER,[ +AC_CACHE_CHECK([for broken RHEL5 sys/capability.h],libreplace_cv_BROKEN_RHEL5_SYS_CAP_HEADER,[ AC_TRY_COMPILE([ #ifdef HAVE_SYS_CAPABILITY_H #include <sys/capability.h> @@ -45,10 +45,10 @@ AC_TRY_COMPILE([ ],[ __s8 i; ], - samba_cv_BROKEN_RHEL5_SYS_CAP_HEADER=no, - samba_cv_BROKEN_RHEL5_SYS_CAP_HEADER=yes + libreplace_cv_BROKEN_RHEL5_SYS_CAP_HEADER=no, + libreplace_cv_BROKEN_RHEL5_SYS_CAP_HEADER=yes )]) -if test x"$samba_cv_BROKEN_RHEL5_SYS_CAP_HEADER" = x"yes"; then +if test x"$libreplace_cv_BROKEN_RHEL5_SYS_CAP_HEADER" = x"yes"; then AC_DEFINE(BROKEN_RHEL5_SYS_CAP_HEADER,1,[Broken RHEL5 sys/capability.h]) fi ;; @@ -73,6 +73,18 @@ AC_VERIFY_C_PROTOTYPE([struct passwd *getpwent_r(struct passwd *src, char *buf, #include <unistd.h> #include <pwd.h> ]) +AC_VERIFY_C_PROTOTYPE([struct passwd *getpwent_r(struct passwd *src, char *buf, size_t buflen)], + [ + #ifndef HAVE_GETPWENT_R_DECL + #error missing getpwent_r prototype + #endif + return NULL; + ],[ + AC_DEFINE(SOLARIS_GETPWENT_R, 1, [getpwent_r irix (similar to solaris) function prototype]) + ],[],[ + #include <unistd.h> + #include <pwd.h> + ]) AC_CHECK_FUNCS(getgrnam_r getgrgid_r getgrent_r) AC_HAVE_DECL(getgrent_r, [ #include <unistd.h> @@ -91,6 +103,19 @@ AC_VERIFY_C_PROTOTYPE([struct group *getgrent_r(struct group *src, char *buf, in #include <grp.h> ]) +AC_VERIFY_C_PROTOTYPE([struct group *getgrent_r(struct group *src, char *buf, size_t buflen)], + [ + #ifndef HAVE_GETGRENT_R_DECL + #error missing getgrent_r prototype + #endif + return NULL; + ],[ + AC_DEFINE(SOLARIS_GETGRENT_R, 1, [getgrent_r irix (similar to solaris) function prototype]) + ],[],[ + #include <unistd.h> + #include <grp.h> + ]) + # locale AC_CHECK_HEADERS(ctype.h locale.h) diff --git a/source3/lib/replace/system/network.h b/source3/lib/replace/system/network.h index b6ae3c7c6f..796df2d1da 100644 --- a/source3/lib/replace/system/network.h +++ b/source3/lib/replace/system/network.h @@ -6,6 +6,7 @@ networking system include wrappers Copyright (C) Andrew Tridgell 2004 + Copyright (C) Jelmer Vernooij 2007 ** NOTE! The following LGPL license applies to the replace ** library. This does NOT imply that all of Samba is released @@ -82,6 +83,11 @@ #include <stropts.h> #endif +#ifndef HAVE_SOCKLEN_T +#define HAVE_SOCKLEN_T +typedef int socklen_t; +#endif + #ifdef REPLACE_INET_NTOA /* define is in "replace.h" */ char *rep_inet_ntoa(struct in_addr ip); @@ -97,6 +103,41 @@ int rep_inet_pton(int af, const char *src, void *dst); const char *rep_inet_ntop(int af, const void *src, char *dst, socklen_t size); #endif +#ifndef HAVE_CONNECT +/* define is in "replace.h" */ +int rep_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); +#endif + +#ifndef HAVE_GETHOSTBYNAME +/* define is in "replace.h" */ +struct hostent *rep_gethostbyname(const char *name); +#endif + +#ifdef HAVE_IFADDRS_H +#include <ifaddrs.h> +#endif + +#ifndef HAVE_STRUCT_IFADDRS +struct ifaddrs { + struct ifaddrs *ifa_next; /* Pointer to next struct */ + char *ifa_name; /* Interface name */ + unsigned int ifa_flags; /* Interface flags */ + struct sockaddr *ifa_addr; /* Interface address */ + struct sockaddr *ifa_netmask; /* Interface netmask */ +#undef ifa_dstaddr + struct sockaddr *ifa_dstaddr; /* P2P interface destination */ + void *ifa_data; /* Address specific data */ +}; +#endif + +#ifndef HAVE_GETIFADDRS +int rep_getifaddrs(struct ifaddrs **); +#endif + +#ifndef HAVE_FREEIFADDRS +void rep_freeifaddrs(struct ifaddrs *); +#endif + /* * Some systems have getaddrinfo but not the * defines needed to use it. @@ -137,8 +178,15 @@ const char *rep_inet_ntop(int af, const void *src, char *dst, socklen_t size); #endif #ifndef AI_ADDRCONFIG +/* + * logic copied from AI_NUMERICHOST + */ +#if defined(HAVE_STRUCT_ADDRINFO) && defined(HAVE_GETADDRINFO) +#define AI_ADDRCONFIG 0 +#else #define AI_ADDRCONFIG 0x0020 #endif +#endif #ifndef AI_NUMERICSERV /* @@ -212,11 +260,6 @@ const char *rep_inet_ntop(int af, const void *src, char *dst, socklen_t size); #define HOST_NAME_MAX 256 #endif -#ifndef HAVE_SOCKLEN_T -#define HAVE_SOCKLEN_T -typedef int socklen_t; -#endif - #ifndef HAVE_SA_FAMILY_T #define HAVE_SA_FAMILY_T typedef unsigned short int sa_family_t; @@ -227,14 +270,19 @@ typedef unsigned short int sa_family_t; #ifdef HAVE_STRUCT_SOCKADDR_IN6 #define sockaddr_storage sockaddr_in6 #define ss_family sin6_family +#define HAVE_SS_FAMILY 1 #else #define sockaddr_storage sockaddr_in #define ss_family sin_family +#define HAVE_SS_FAMILY 1 #endif #endif -#ifdef HAVE_AIX_SOCKADDR_STORAGE +#ifndef HAVE_SS_FAMILY +#ifdef HAVE___SS_FAMILY #define ss_family __ss_family +#define HAVE_SS_FAMILY 1 +#endif #endif #ifndef HAVE_STRUCT_ADDRINFO @@ -257,7 +305,7 @@ struct addrinfo { /* Needed for some systems that don't define it (Solaris). */ #ifndef ifr_netmask -#define ifr_netmask ifr_addrs +#define ifr_netmask ifr_addr #endif #ifdef SOCKET_WRAPPER diff --git a/source3/lib/replace/system/printing.h b/source3/lib/replace/system/printing.h deleted file mode 100644 index 7eb02d004a..0000000000 --- a/source3/lib/replace/system/printing.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef _system_printing_h -#define _system_printing_h - -/* - Unix SMB/CIFS implementation. - - printing system include wrappers - - Copyright (C) Andrew Tridgell 2004 - - ** NOTE! The following LGPL license applies to the replace - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#ifdef AIX -#define DEFAULT_PRINTING PRINT_AIX -#define PRINTCAP_NAME "/etc/qconfig" -#endif - -#ifdef HPUX -#define DEFAULT_PRINTING PRINT_HPUX -#endif - -#ifdef QNX -#define DEFAULT_PRINTING PRINT_QNX -#endif - -#ifndef DEFAULT_PRINTING -#define DEFAULT_PRINTING PRINT_BSD -#endif -#ifndef PRINTCAP_NAME -#define PRINTCAP_NAME "/etc/printcap" -#endif - -#endif diff --git a/source3/lib/replace/test/getifaddrs.c b/source3/lib/replace/test/getifaddrs.c new file mode 100644 index 0000000000..8b00ac2f40 --- /dev/null +++ b/source3/lib/replace/test/getifaddrs.c @@ -0,0 +1,100 @@ +/* + * Unix SMB/CIFS implementation. + * + * libreplace getifaddrs test + * + * Copyright (C) Michael Adam <obnox@samba.org> 2008 + * + * 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 AUTOCONF_TEST +#include "replace.h" +#include "system/network.h" +#endif + +#ifdef HAVE_INET_NTOP +#define rep_inet_ntop inet_ntop +#endif + +static const char *format_sockaddr(struct sockaddr *addr, + char *addrstring, + socklen_t addrlen) +{ + const char *result = NULL; + + if (addr->sa_family == AF_INET) { + result = rep_inet_ntop(AF_INET, + &((struct sockaddr_in *)addr)->sin_addr, + addrstring, + addrlen); +#ifdef HAVE_STRUCT_SOCKADDR_IN6 + } else if (addr->sa_family == AF_INET6) { + result = rep_inet_ntop(AF_INET6, + &((struct sockaddr_in6 *)addr)->sin6_addr, + addrstring, + addrlen); +#endif + } + return result; +} + +int getifaddrs_test(void) +{ + struct ifaddrs *ifs = NULL; + struct ifaddrs *ifs_head = NULL; + int ret; + + ret = getifaddrs(&ifs); + ifs_head = ifs; + if (ret != 0) { + fprintf(stderr, "getifaddrs() failed: %s\n", strerror(errno)); + return 1; + } + + while (ifs) { + printf("%-10s ", ifs->ifa_name); + if (ifs->ifa_addr != NULL) { + char addrstring[INET6_ADDRSTRLEN]; + const char *result; + + result = format_sockaddr(ifs->ifa_addr, + addrstring, + sizeof(addrstring)); + if (result != NULL) { + printf("IP=%s ", addrstring); + } + + if (ifs->ifa_netmask != NULL) { + result = format_sockaddr(ifs->ifa_netmask, + addrstring, + sizeof(addrstring)); + if (result != NULL) { + printf("NETMASK=%s", addrstring); + } + } else { + printf("AF=%d ", ifs->ifa_addr->sa_family); + } + } else { + printf("<no address>"); + } + + printf("\n"); + ifs = ifs->ifa_next; + } + + freeifaddrs(ifs_head); + + return 0; +} diff --git a/source3/lib/replace/test/testsuite.c b/source3/lib/replace/test/testsuite.c index 269a2ff5d6..b538360365 100644 --- a/source3/lib/replace/test/testsuite.c +++ b/source3/lib/replace/test/testsuite.c @@ -37,7 +37,6 @@ #include "system/locale.h" #include "system/network.h" #include "system/passwd.h" -#include "system/printing.h" #include "system/readline.h" #include "system/select.h" #include "system/shmem.h" @@ -857,6 +856,22 @@ static int test_strptime(void) return libreplace_test_strptime(); } +extern int getifaddrs_test(void); + +static int test_getifaddrs(void) +{ + + printf("test: getifaddrs\n"); + + if (getifaddrs_test() != 0) { + printf("failure: getifaddrs\n"); + return false; + } + + printf("success: getifaddrs\n"); + return true; +} + struct torture_context; bool torture_local_replace(struct torture_context *ctx) { @@ -904,6 +919,7 @@ bool torture_local_replace(struct torture_context *ctx) ret &= test_MAX(); ret &= test_socketpair(); ret &= test_strptime(); + ret &= test_getifaddrs(); return ret; } diff --git a/source3/lib/select.c b/source3/lib/select.c index d5e4ba68f2..c3da6a9bba 100644 --- a/source3/lib/select.c +++ b/source3/lib/select.c @@ -58,7 +58,8 @@ int sys_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *errorfds, s fd_set *readfds2, readfds_buf; if (initialised != sys_getpid()) { - pipe(select_pipe); + if (pipe(select_pipe) == -1) + smb_panic("Could not create select pipe"); /* * These next two lines seem to fix a bug with the Linux diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c index 662a5a948a..65a039b119 100644 --- a/source3/lib/smbldap.c +++ b/source3/lib/smbldap.c @@ -980,7 +980,7 @@ static int smbldap_connect_system(struct smbldap_state *ldap_state, LDAP * ldap_ ldap_state->paged_results = True; } - DEBUG(3, ("ldap_connect_system: succesful connection to the LDAP server\n")); + DEBUG(3, ("ldap_connect_system: successful connection to the LDAP server\n")); DEBUGADD(10, ("ldap_connect_system: LDAP server %s support paged results\n", ldap_state->paged_results ? "does" : "does not")); return rc; @@ -1063,7 +1063,7 @@ static int smbldap_open(struct smbldap_state *ldap_state) "smbldap_idle_fn", smbldap_idle_fn, ldap_state); } - DEBUG(4,("The LDAP server is succesfully connected\n")); + DEBUG(4,("The LDAP server is successfully connected\n")); return LDAP_SUCCESS; } diff --git a/source3/lib/sock_exec.c b/source3/lib/sock_exec.c index 203d7e93b3..278a174663 100644 --- a/source3/lib/sock_exec.c +++ b/source3/lib/sock_exec.c @@ -105,8 +105,12 @@ int sock_exec(const char *prog) close(fd[0]); close(0); close(1); - dup(fd[1]); - dup(fd[1]); + if (dup(fd[1]) == -1) { + exit(1); + } + if (dup(fd[1]) == -1) { + exit(1); + } exit(system(prog)); } close(fd[1]); diff --git a/source3/lib/system.c b/source3/lib/system.c index eb6dcae6fb..fa50955ef6 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -1917,11 +1917,6 @@ int sys_fremovexattr (int filedes, const char *name) #endif } -#if !defined(HAVE_SETXATTR) -#define XATTR_CREATE 0x1 /* set value, fail if attr already exists */ -#define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */ -#endif - int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags) { #if defined(HAVE_SETXATTR) diff --git a/source3/lib/system_smbd.c b/source3/lib/system_smbd.c index 9d3eb95664..1f5dd3172f 100644 --- a/source3/lib/system_smbd.c +++ b/source3/lib/system_smbd.c @@ -125,7 +125,7 @@ static int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grp * always determined by the info3 coming back from auth3 or the * PAC. */ winbind_env = winbind_env_set(); - winbind_off(); + (void)winbind_off(); #ifdef HAVE_GETGROUPLIST retval = getgrouplist(user, gid, groups, grpcnt); @@ -137,7 +137,7 @@ static int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grp /* allow winbindd lookups, but only if they were not already disabled */ if (!winbind_env) { - winbind_on(); + (void)winbind_on(); } return retval; diff --git a/source3/lib/talloc/Makefile.in b/source3/lib/talloc/Makefile.in index 18b48c3459..851dc81aea 100644 --- a/source3/lib/talloc/Makefile.in +++ b/source3/lib/talloc/Makefile.in @@ -14,59 +14,29 @@ INSTALLCMD = @INSTALL@ CC = @CC@ CFLAGS = @CFLAGS@ -DHAVE_CONFIG_H= -I. -I@srcdir@ EXTRA_TARGETS = @DOC_TARGET@ +PICFLAG = @PICFLAG@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +SHLIBEXT = @SHLIBEXT@ +SHLD_FLAGS = @SHLD_FLAGS@ +tallocdir = @tallocdir@ -.SUFFIXES: .c .o .3 .3.xml .xml .html +LIBOBJ = $(TALLOC_OBJ) @LIBREPLACEOBJ@ -LIBOBJ = @TALLOC_OBJ@ @LIBREPLACEOBJ@ +all:: showflags $(EXTRA_TARGETS) -all: showflags libtalloc.a testsuite $(EXTRA_TARGETS) +include $(tallocdir)/rules.mk +include $(tallocdir)/talloc.mk -showflags: - @echo 'talloc will be compiled with flags:' - @echo ' CFLAGS = $(CFLAGS)' - @echo ' LIBS = $(LIBS)' +$(SOLIB): $(LIBOBJ) + $(CC) $(SHLD_FLAGS) -o $@ $(LIBOBJ) @SONAMEFLAG@$(SONAME) -testsuite: $(LIBOBJ) testsuite.o - $(CC) $(CFLAGS) -o testsuite testsuite.o $(LIBOBJ) $(LIBS) +check: test -libtalloc.a: $(LIBOBJ) - ar -rv $@ $(LIBOBJ) - @-ranlib $@ +installcheck:: test install -install: all - ${INSTALLCMD} -d $(DESTDIR)$(libdir) - ${INSTALLCMD} -d $(DESTDIR)$(libdir)/pkgconfig - ${INSTALLCMD} -m 755 libtalloc.a $(DESTDIR)$(libdir) - ${INSTALLCMD} -d $(DESTDIR)${includedir} - ${INSTALLCMD} -m 644 $(srcdir)/talloc.h $(DESTDIR)$(includedir) - ${INSTALLCMD} -m 644 talloc.pc $(DESTDIR)$(libdir)/pkgconfig - if [ -f talloc.3 ];then ${INSTALLCMD} -d $(DESTDIR)$(mandir)/man3; fi - if [ -f talloc.3 ];then ${INSTALLCMD} -m 644 talloc.3 $(DESTDIR)$(mandir)/man3; fi - -doc: talloc.3 talloc.3.html - -.3.xml.3: - -test -z "$(XSLTPROC)" || $(XSLTPROC) --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $< - -.xml.html: - -test -z "$(XSLTPROC)" || $(XSLTPROC) --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $< - -clean: - rm -f *~ $(LIBOBJ) libtalloc.a testsuite testsuite.o *.gc?? talloc.3 talloc.3.html - -test: testsuite - ./testsuite - -gcov: - gcov talloc.c - -installcheck: - $(MAKE) test - -distclean: clean - rm -f *~ */*~ +distclean:: clean rm -f Makefile rm -f config.log config.status config.h config.cache -realdistclean: distclean +realdistclean:: distclean rm -f configure config.h.in diff --git a/source3/lib/talloc/config.mk b/source3/lib/talloc/config.mk index 714ad72d1c..540a05d100 100644 --- a/source3/lib/talloc/config.mk +++ b/source3/lib/talloc/config.mk @@ -1,13 +1,8 @@ -################################################ -# Start LIBRARY LIBTALLOC [LIBRARY::LIBTALLOC] -VERSION = 0.0.1 -SO_VERSION = 0 +VERSION = 1.2.0 +SO_VERSION = 1 OBJ_FILES = talloc.o +PC_FILE = talloc.pc MANPAGE = talloc.3 CFLAGS = -Ilib/talloc PUBLIC_HEADERS = talloc.h -DESCRIPTION = A hierarchical pool based memory system with destructors -# -# End LIBRARY LIBTALLOC -################################################ diff --git a/source3/lib/talloc/configure.ac b/source3/lib/talloc/configure.ac index afc2a944f0..3dcf74ba25 100644 --- a/source3/lib/talloc/configure.ac +++ b/source3/lib/talloc/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.50) -AC_INIT(talloc, 1.1.0) +AC_INIT(talloc, 1.2.0) AC_CONFIG_SRCDIR([talloc.c]) AC_SUBST(datarootdir) AC_CONFIG_HEADER(config.h) @@ -15,4 +15,9 @@ if test -n "$XSLTPROC"; then fi AC_SUBST(DOC_TARGET) +AC_LD_PICFLAG +AC_LD_SHLIBEXT +AC_LD_SONAMEFLAG +AC_LIBREPLACE_SHLD_FLAGS + AC_OUTPUT(Makefile talloc.pc) diff --git a/source3/lib/talloc/rules.mk b/source3/lib/talloc/rules.mk new file mode 100644 index 0000000000..6cee126529 --- /dev/null +++ b/source3/lib/talloc/rules.mk @@ -0,0 +1,18 @@ +.SUFFIXES: .c .o .3 .3.xml .xml .html + +showflags:: + @echo 'talloc will be compiled with flags:' + @echo ' CFLAGS = $(CFLAGS)' + @echo ' LIBS = $(LIBS)' + +.c.o: + $(CC) $(PICFLAG) -o $@ -c $< $(CFLAGS) + +.3.xml.3: + -test -z "$(XSLTPROC)" || $(XSLTPROC) --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $< + +.xml.html: + -test -z "$(XSLTPROC)" || $(XSLTPROC) --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $< + +distclean:: + rm -f *~ */*~ diff --git a/source3/lib/talloc/talloc.i b/source3/lib/talloc/talloc.i new file mode 100644 index 0000000000..a9afb97ed7 --- /dev/null +++ b/source3/lib/talloc/talloc.i @@ -0,0 +1,31 @@ +/* + Unix SMB/CIFS implementation. + Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007 + + 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/>. +*/ + +/* Don't expose talloc contexts in Python code. Python does reference + counting for us, so just create a new top-level talloc context. + */ +%typemap(in, numinputs=0, noblock=1) TALLOC_CTX * { + $1 = NULL; +} + +%define %talloctype(TYPE) +%nodefaultctor TYPE; +%extend TYPE { + ~TYPE() { talloc_free($self); } +} +%enddef diff --git a/source3/lib/talloc/talloc.mk b/source3/lib/talloc/talloc.mk new file mode 100644 index 0000000000..590adc74f2 --- /dev/null +++ b/source3/lib/talloc/talloc.mk @@ -0,0 +1,37 @@ +TALLOC_OBJ = $(tallocdir)/talloc.o + +SOLIB = libtalloc.$(SHLIBEXT).$(PACKAGE_VERSION) +SONAME = libtalloc.$(SHLIBEXT).1 + +all:: libtalloc.a $(SOLIB) testsuite + +testsuite:: $(LIBOBJ) testsuite.o + $(CC) $(CFLAGS) -o testsuite testsuite.o $(LIBOBJ) $(LIBS) + +libtalloc.a: $(LIBOBJ) + ar -rv $@ $(LIBOBJ) + @-ranlib $@ + +install:: all + ${INSTALLCMD} -d $(DESTDIR)$(libdir) + ${INSTALLCMD} -d $(DESTDIR)$(libdir)/pkgconfig + ${INSTALLCMD} -m 755 libtalloc.a $(DESTDIR)$(libdir) + ${INSTALLCMD} -m 755 $(SOLIB) $(DESTDIR)$(libdir) + ${INSTALLCMD} -d $(DESTDIR)${includedir} + ${INSTALLCMD} -m 644 $(srcdir)/talloc.h $(DESTDIR)$(includedir) + ${INSTALLCMD} -m 644 talloc.pc $(DESTDIR)$(libdir)/pkgconfig + if [ -f talloc.3 ];then ${INSTALLCMD} -d $(DESTDIR)$(mandir)/man3; fi + if [ -f talloc.3 ];then ${INSTALLCMD} -m 644 talloc.3 $(DESTDIR)$(mandir)/man3; fi + which swig >/dev/null 2>&1 && ${INSTALLCMD} -d $(DESTDIR)`swig -swiglib` || true + which swig >/dev/null 2>&1 && ${INSTALLCMD} -m 644 talloc.i $(DESTDIR)`swig -swiglib` || true + +doc:: talloc.3 talloc.3.html + +clean:: + rm -f *~ $(LIBOBJ) $(SOLIB) libtalloc.a testsuite testsuite.o *.gc?? talloc.3 talloc.3.html + +test:: testsuite + ./testsuite + +gcov:: + gcov talloc.c diff --git a/source3/lib/tdb/Makefile.in b/source3/lib/tdb/Makefile.in index e1ecbb30ec..fd36ed078e 100644 --- a/source3/lib/tdb/Makefile.in +++ b/source3/lib/tdb/Makefile.in @@ -74,7 +74,7 @@ $(SONAME): $(SOLIB) ln -s $< $@ $(SOLIB): $(TDB_OBJ) - $(CC) $(SHLD_FLAGS) $(SONAMEFLAG)$(SONAME) -o $@ $^ + $(CC) $(SHLD_FLAGS) -o $@ $(TDB_OBJ) $(SONAMEFLAG)$(SONAME) TDB_LIB = libtdb.a diff --git a/source3/lib/tdb/common/freelist.c b/source3/lib/tdb/common/freelist.c index c086c151fa..2f2a4c379b 100644 --- a/source3/lib/tdb/common/freelist.c +++ b/source3/lib/tdb/common/freelist.c @@ -208,62 +208,61 @@ update: } + /* the core of tdb_allocate - called when we have decided which free list entry to use + + Note that we try to allocate by grabbing data from the end of an existing record, + not the beginning. This is so the left merge in a free is more likely to be + able to free up the record without fragmentation */ -static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb, tdb_len_t length, tdb_off_t rec_ptr, - struct list_struct *rec, tdb_off_t last_ptr) +static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb, + tdb_len_t length, tdb_off_t rec_ptr, + struct list_struct *rec, tdb_off_t last_ptr) { - struct list_struct newrec; - tdb_off_t newrec_ptr; +#define MIN_REC_SIZE (sizeof(struct list_struct) + sizeof(tdb_off_t) + 8) - memset(&newrec, '\0', sizeof(newrec)); + if (rec->rec_len < length + MIN_REC_SIZE) { + /* we have to grab the whole record */ - /* found it - now possibly split it up */ - if (rec->rec_len > length + MIN_REC_SIZE) { - /* Length of left piece */ - length = TDB_ALIGN(length, TDB_ALIGNMENT); - - /* Right piece to go on free list */ - newrec.rec_len = rec->rec_len - (sizeof(*rec) + length); - newrec_ptr = rec_ptr + sizeof(*rec) + length; - - /* And left record is shortened */ - rec->rec_len = length; - } else { - newrec_ptr = 0; + /* unlink it from the previous record */ + if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) { + return 0; + } + + /* mark it not free */ + rec->magic = TDB_MAGIC; + if (tdb_rec_write(tdb, rec_ptr, rec) == -1) { + return 0; + } + return rec_ptr; + } + + /* we're going to just shorten the existing record */ + rec->rec_len -= (length + sizeof(*rec)); + if (tdb_rec_write(tdb, rec_ptr, rec) == -1) { + return 0; } - - /* Remove allocated record from the free list */ - if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) { + if (update_tailer(tdb, rec_ptr, rec) == -1) { return 0; } - - /* Update header: do this before we drop alloc - lock, otherwise tdb_free() might try to - merge with us, thinking we're free. - (Thanks Jeremy Allison). */ + + /* and setup the new record */ + rec_ptr += sizeof(*rec) + rec->rec_len; + + memset(rec, '\0', sizeof(*rec)); + rec->rec_len = length; rec->magic = TDB_MAGIC; + if (tdb_rec_write(tdb, rec_ptr, rec) == -1) { return 0; } - - /* Did we create new block? */ - if (newrec_ptr) { - /* Update allocated record tailer (we - shortened it). */ - if (update_tailer(tdb, rec_ptr, rec) == -1) { - return 0; - } - - /* Free new record */ - if (tdb_free(tdb, newrec_ptr, &newrec) == -1) { - return 0; - } + + if (update_tailer(tdb, rec_ptr, rec) == -1) { + return 0; } - - /* all done - return the new record offset */ + return rec_ptr; } @@ -287,6 +286,7 @@ tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_st /* Extra bytes required for tailer */ length += sizeof(tdb_off_t); + length = TDB_ALIGN(length, TDB_ALIGNMENT); again: last_ptr = FREELIST_TOP; @@ -343,7 +343,8 @@ tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_st goto fail; } - newrec_ptr = tdb_allocate_ofs(tdb, length, bestfit.rec_ptr, rec, bestfit.last_ptr); + newrec_ptr = tdb_allocate_ofs(tdb, length, bestfit.rec_ptr, + rec, bestfit.last_ptr); tdb_unlock(tdb, -1, F_WRLCK); return newrec_ptr; } diff --git a/source3/lib/tdb/common/open.c b/source3/lib/tdb/common/open.c index 94140a4baa..b19e4cea29 100644 --- a/source3/lib/tdb/common/open.c +++ b/source3/lib/tdb/common/open.c @@ -179,7 +179,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, tdb->page_size = 0x2000; } - tdb->max_dead_records = (open_flags & TDB_VOLATILE) ? 5 : 0; + tdb->max_dead_records = (tdb_flags & TDB_VOLATILE) ? 5 : 0; if ((open_flags & O_ACCMODE) == O_WRONLY) { TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: can't open tdb %s write-only\n", @@ -227,6 +227,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, /* we need to zero database if we are the only one with it open */ if ((tdb_flags & TDB_CLEAR_IF_FIRST) && + (!tdb->read_only) && (locked = (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0, 1) == 0))) { open_flags |= O_CREAT; if (ftruncate(tdb->fd, 0) == -1) { diff --git a/source3/lib/tdb/common/tdb.c b/source3/lib/tdb/common/tdb.c index ea5d9ccc60..767452c9b3 100644 --- a/source3/lib/tdb/common/tdb.c +++ b/source3/lib/tdb/common/tdb.c @@ -687,20 +687,66 @@ void tdb_enable_seqnum(struct tdb_context *tdb) /* + add a region of the file to the freelist. Length is the size of the region in bytes, + which includes the free list header that needs to be added + */ +static int tdb_free_region(struct tdb_context *tdb, tdb_off_t offset, ssize_t length) +{ + struct list_struct rec; + if (length <= sizeof(rec)) { + /* the region is not worth adding */ + return 0; + } + if (length + offset > tdb->map_size) { + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_free_region: adding region beyond end of file\n")); + return -1; + } + memset(&rec,'\0',sizeof(rec)); + rec.rec_len = length - sizeof(rec); + if (tdb_free(tdb, offset, &rec) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_free_region: failed to add free record\n")); + return -1; + } + return 0; +} + +/* wipe the entire database, deleting all records. This can be done very fast by using a global lock. The entire data portion of the file becomes a single entry in the freelist. + + This code carefully steps around the recovery area, leaving it alone */ int tdb_wipe_all(struct tdb_context *tdb) { int i; tdb_off_t offset = 0; ssize_t data_len; + tdb_off_t recovery_head; + tdb_len_t recovery_size = 0; if (tdb_lockall(tdb) != 0) { return -1; } + /* see if the tdb has a recovery area, and remember its size + if so. We don't want to lose this as otherwise each + tdb_wipe_all() in a transaction will increase the size of + the tdb by the size of the recovery area */ + if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_wipe_all: failed to read recovery head\n")); + goto failed; + } + + if (recovery_head != 0) { + struct list_struct rec; + if (tdb->methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_wipe_all: failed to read recovery record\n")); + return -1; + } + recovery_size = rec.rec_len + sizeof(rec); + } + /* wipe the hashes */ for (i=0;i<tdb->header.hash_size;i++) { if (tdb_ofs_write(tdb, TDB_HASH_TOP(i), &offset) == -1) { @@ -715,19 +761,30 @@ int tdb_wipe_all(struct tdb_context *tdb) goto failed; } - if (tdb_ofs_write(tdb, TDB_RECOVERY_HEAD, &offset) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_wipe_all: failed to write recovery head\n")); - goto failed; - } - - /* add all the rest of the file to the freelist */ - data_len = (tdb->map_size - TDB_DATA_START(tdb->header.hash_size)) - sizeof(struct list_struct); - if (data_len > 0) { - struct list_struct rec; - memset(&rec,'\0',sizeof(rec)); - rec.rec_len = data_len; - if (tdb_free(tdb, TDB_DATA_START(tdb->header.hash_size), &rec) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_wipe_all: failed to add free record\n")); + /* add all the rest of the file to the freelist, possibly leaving a gap + for the recovery area */ + if (recovery_size == 0) { + /* the simple case - the whole file can be used as a freelist */ + data_len = (tdb->map_size - TDB_DATA_START(tdb->header.hash_size)); + if (tdb_free_region(tdb, TDB_DATA_START(tdb->header.hash_size), data_len) != 0) { + goto failed; + } + } else { + /* we need to add two freelist entries - one on either + side of the recovery area + + Note that we cannot shift the recovery area during + this operation. Only the transaction.c code may + move the recovery area or we risk subtle data + corruption + */ + data_len = (recovery_head - TDB_DATA_START(tdb->header.hash_size)); + if (tdb_free_region(tdb, TDB_DATA_START(tdb->header.hash_size), data_len) != 0) { + goto failed; + } + /* and the 2nd free list entry after the recovery area - if any */ + data_len = tdb->map_size - (recovery_head+recovery_size); + if (tdb_free_region(tdb, recovery_head+recovery_size, data_len) != 0) { goto failed; } } diff --git a/source3/lib/tdb/common/tdb_private.h b/source3/lib/tdb/common/tdb_private.h index 63a6d04e72..ffac89ff0e 100644 --- a/source3/lib/tdb/common/tdb_private.h +++ b/source3/lib/tdb/common/tdb_private.h @@ -49,7 +49,6 @@ typedef uint32_t tdb_off_t; #define TDB_DEAD_MAGIC (0xFEE1DEAD) #define TDB_RECOVERY_MAGIC (0xf53bc0e7U) #define TDB_ALIGNMENT 4 -#define MIN_REC_SIZE (2*sizeof(struct list_struct) + TDB_ALIGNMENT) #define DEFAULT_HASH_SIZE 131 #define FREELIST_TOP (sizeof(struct tdb_header)) #define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1)) @@ -178,6 +177,7 @@ struct tdb_context { int tdb_munmap(struct tdb_context *tdb); void tdb_mmap(struct tdb_context *tdb); int tdb_lock(struct tdb_context *tdb, int list, int ltype); +int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype); int tdb_unlock(struct tdb_context *tdb, int list, int ltype); int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe, size_t len); int tdb_transaction_lock(struct tdb_context *tdb, int ltype); diff --git a/source3/lib/tdb/common/transaction.c b/source3/lib/tdb/common/transaction.c index 0ecfb9b7ff..4e2127be64 100644 --- a/source3/lib/tdb/common/transaction.c +++ b/source3/lib/tdb/common/transaction.c @@ -219,9 +219,12 @@ static int transaction_write(struct tdb_context *tdb, tdb_off_t off, uint8_t **new_blocks; /* expand the blocks array */ if (tdb->transaction->blocks == NULL) { - new_blocks = malloc((blk+1)*sizeof(uint8_t *)); + new_blocks = (uint8_t **)malloc( + (blk+1)*sizeof(uint8_t *)); } else { - new_blocks = realloc(tdb->transaction->blocks, (blk+1)*sizeof(uint8_t *)); + new_blocks = (uint8_t **)realloc( + tdb->transaction->blocks, + (blk+1)*sizeof(uint8_t *)); } if (new_blocks == NULL) { tdb->ecode = TDB_ERR_OOM; @@ -316,25 +319,18 @@ static int transaction_write_existing(struct tdb_context *tdb, tdb_off_t off, return 0; } - /* overwrite part of an existing block */ - if (buf == NULL) { - memset(tdb->transaction->blocks[blk] + off, 0, len); - } else { - memcpy(tdb->transaction->blocks[blk] + off, buf, len); - } - if (blk == tdb->transaction->num_blocks-1) { - if (len + off > tdb->transaction->last_block_size) { - tdb->transaction->last_block_size = len + off; + if (blk == tdb->transaction->num_blocks-1 && + off + len > tdb->transaction->last_block_size) { + if (off >= tdb->transaction->last_block_size) { + return 0; } + len = tdb->transaction->last_block_size - off; } - return 0; + /* overwrite part of an existing block */ + memcpy(tdb->transaction->blocks[blk] + off, buf, len); -fail: - TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_write: failed at off=%d len=%d\n", - (blk*tdb->transaction->block_size) + off, len)); - tdb->transaction->transaction_error = 1; - return -1; + return 0; } diff --git a/source3/lib/tdb/config.mk b/source3/lib/tdb/config.mk index ab90ed728d..01a23f00de 100644 --- a/source3/lib/tdb/config.mk +++ b/source3/lib/tdb/config.mk @@ -3,7 +3,7 @@ [LIBRARY::LIBTDB] VERSION = 0.0.1 SO_VERSION = 0 -DESCRIPTION = Trivial Database Library +PC_FILE = tdb.pc OBJ_FILES = \ common/tdb.o common/dump.o common/io.o common/lock.o \ common/open.o common/traverse.o common/freelist.o \ diff --git a/source3/lib/tdb/configure.ac b/source3/lib/tdb/configure.ac index 1085055bc9..14761bcc1a 100644 --- a/source3/lib/tdb/configure.ac +++ b/source3/lib/tdb/configure.ac @@ -8,7 +8,7 @@ AC_CONFIG_HEADER(include/config.h) AC_LIBREPLACE_ALL_CHECKS AC_LD_SONAMEFLAG AC_LD_PICFLAG -AC_LD_SHLDFLAGS AC_LD_SHLIBEXT +AC_LIBREPLACE_SHLD_FLAGS m4_include(libtdb.m4) AC_OUTPUT(Makefile tdb.pc) diff --git a/source3/lib/util.c b/source3/lib/util.c index 0653fc9d3f..dba7142bad 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -506,6 +506,19 @@ bool file_exist(const char *fname,SMB_STRUCT_STAT *sbuf) } /******************************************************************* + Check if a unix domain socket exists - call vfs_file_exist for samba files. +********************************************************************/ + +bool socket_exist(const char *fname) +{ + SMB_STRUCT_STAT st; + if (sys_stat(fname,&st) != 0) + return(False); + + return S_ISSOCK(st.st_mode); +} + +/******************************************************************* Check a files mod time. ********************************************************************/ @@ -2169,7 +2182,7 @@ void dump_data_pw(const char *msg, const uchar * data, size_t len) const char *tab_depth(int level, int depth) { - if( DEBUGLVL(level) ) { + if( CHECK_DEBUGLVL(level) ) { dbgtext("%*s", depth*4, ""); } return ""; @@ -2418,6 +2431,7 @@ char *smb_xstrndup(const char *s, size_t n) if (n == -1 || ! *ptr) { smb_panic("smb_xvasprintf: out of memory"); } + va_end(ap2); return n; } @@ -3260,3 +3274,93 @@ void *talloc_zeronull(const void *context, size_t size, const char *name) return talloc_named_const(context, size, name); } #endif + +/* Split a path name into filename and stream name components. Canonicalise + * such that an implicit $DATA token is always explicit. + * + * The "specification" of this function can be found in the + * run_local_stream_name() function in torture.c, I've tried those + * combinations against a W2k3 server. + */ + +NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname, + char **pbase, char **pstream) +{ + char *base = NULL; + char *stream = NULL; + char *sname; /* stream name */ + const char *stype; /* stream type */ + + DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname)); + + sname = strchr_m(fname, ':'); + + if (lp_posix_pathnames() || (sname == NULL)) { + if (pbase != NULL) { + base = talloc_strdup(mem_ctx, fname); + NT_STATUS_HAVE_NO_MEMORY(base); + } + goto done; + } + + if (pbase != NULL) { + base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname)); + NT_STATUS_HAVE_NO_MEMORY(base); + } + + sname += 1; + + stype = strchr_m(sname, ':'); + + if (stype == NULL) { + sname = talloc_strdup(mem_ctx, sname); + stype = "$DATA"; + } + else { + if (StrCaseCmp(stype, ":$DATA") != 0) { + /* + * If there is an explicit stream type, so far we only + * allow $DATA. Is there anything else allowed? -- vl + */ + DEBUG(10, ("[%s] is an invalid stream type\n", stype)); + TALLOC_FREE(base); + return NT_STATUS_OBJECT_NAME_INVALID; + } + sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname)); + stype += 1; + } + + if (sname == NULL) { + TALLOC_FREE(base); + return NT_STATUS_NO_MEMORY; + } + + if (sname[0] == '\0') { + /* + * no stream name, so no stream + */ + goto done; + } + + if (pstream != NULL) { + stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype); + if (stream == NULL) { + TALLOC_FREE(sname); + TALLOC_FREE(base); + return NT_STATUS_NO_MEMORY; + } + /* + * upper-case the type field + */ + strupper_m(strchr_m(stream, ':')+1); + } + + done: + if (pbase != NULL) { + *pbase = base; + } + if (pstream != NULL) { + *pstream = stream; + } + return NT_STATUS_OK; +} diff --git a/source3/lib/util_reg.c b/source3/lib/util_reg.c index 956f0475a5..2475dca040 100644 --- a/source3/lib/util_reg.c +++ b/source3/lib/util_reg.c @@ -95,7 +95,7 @@ WERROR reg_pull_multi_sz(TALLOC_CTX *mem_ctx, const void *buf, size_t len, thislen = strnlen_w(p, len) + 1; dstlen = convert_string_allocate(*values, CH_UTF16LE, CH_UNIX, p, thislen*2, (void *)&val, - True); + true); if (dstlen == (size_t)-1) { TALLOC_FREE(*values); return WERR_NOMEM; @@ -130,14 +130,15 @@ bool registry_smbconf_valname_forbidden(const char *valname) "include", "lock directory", "lock dir", + "config backend", NULL }; const char **forbidden = NULL; for (forbidden = forbidden_valnames; *forbidden != NULL; forbidden++) { if (strwicmp(valname, *forbidden) == 0) { - return True; + return true; } } - return False; + return false; } diff --git a/source3/lib/util_reg_smbconf.c b/source3/lib/util_reg_smbconf.c deleted file mode 100644 index 6452b0b15b..0000000000 --- a/source3/lib/util_reg_smbconf.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * Registry helper routines - * Copyright (C) Michael Adam 2007 - * - * 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" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_REGISTRY - -extern REGISTRY_OPS smbconf_reg_ops; - -/* - * create a fake token just with enough rights to - * locally access the registry: - * - * - builtin administrators sid - * - disk operators privilege - */ -NTSTATUS registry_create_admin_token(TALLOC_CTX *mem_ctx, - NT_USER_TOKEN **ptoken) -{ - NTSTATUS status; - NT_USER_TOKEN *token = NULL; - - if (ptoken == NULL) { - return NT_STATUS_INVALID_PARAMETER; - } - - token = TALLOC_ZERO_P(mem_ctx, NT_USER_TOKEN); - if (token == NULL) { - DEBUG(1, ("talloc failed\n")); - status = NT_STATUS_NO_MEMORY; - goto done; - } - token->privileges = se_disk_operators; - status = add_sid_to_array(token, &global_sid_Builtin_Administrators, - &token->user_sids, &token->num_sids); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Error adding builtin administrators sid " - "to fake token.\n")); - goto done; - } - - *ptoken = token; - -done: - return status; -} - -/* - * init the smbconf portion of the registry. - * for use in places where not the whole registry is needed, - * e.g. utils/net_conf.c and loadparm.c - */ -bool registry_init_regdb(void) -{ - bool ret = false; - int saved_errno = 0; - static REGISTRY_HOOK smbconf_reg_hook = {KEY_SMBCONF, &smbconf_reg_ops}; - - DEBUG(10, ("registry_init_regdb called\n")); - - if (!regdb_init()) { - saved_errno = errno; - DEBUG(1, ("Can't open the registry")); - if (saved_errno) { - DEBUGADD(1, (": %s", strerror(saved_errno))); - } - DEBUGADD(1, (".\n")); - goto done; - } - reghook_cache_init(); - if (!reghook_cache_add(&smbconf_reg_hook)) { - DEBUG(1, ("Error adding smbconf reghooks to reghook cache.\n")); - goto done; - } - - ret = true; - -done: - return ret; -} diff --git a/source3/lib/util_sid.c b/source3/lib/util_sid.c index 37865238a5..fd2e93a697 100644 --- a/source3/lib/util_sid.c +++ b/source3/lib/util_sid.c @@ -665,7 +665,7 @@ bool is_null_sid(const DOM_SID *sid) } NTSTATUS sid_array_from_info3(TALLOC_CTX *mem_ctx, - const NET_USER_INFO_3 *info3, + const struct netr_SamInfo3 *info3, DOM_SID **user_sids, size_t *num_user_sids, bool include_user_group_rid) @@ -678,45 +678,45 @@ NTSTATUS sid_array_from_info3(TALLOC_CTX *mem_ctx, if (include_user_group_rid) { - if (!sid_compose(&sid, &(info3->dom_sid.sid), info3->user_rid)) + if (!sid_compose(&sid, info3->base.domain_sid, info3->base.rid)) { DEBUG(3, ("could not compose user SID from rid 0x%x\n", - info3->user_rid)); + info3->base.rid)); return NT_STATUS_INVALID_PARAMETER; } status = add_sid_to_array(mem_ctx, &sid, &sid_array, &num_sids); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("could not append user SID from rid 0x%x\n", - info3->user_rid)); + info3->base.rid)); return status; } - if (!sid_compose(&sid, &(info3->dom_sid.sid), info3->group_rid)) + if (!sid_compose(&sid, info3->base.domain_sid, info3->base.primary_gid)) { DEBUG(3, ("could not compose group SID from rid 0x%x\n", - info3->group_rid)); + info3->base.primary_gid)); return NT_STATUS_INVALID_PARAMETER; } status = add_sid_to_array(mem_ctx, &sid, &sid_array, &num_sids); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("could not append group SID from rid 0x%x\n", - info3->group_rid)); + info3->base.rid)); return status; } } - for (i = 0; i < info3->num_groups2; i++) { - if (!sid_compose(&sid, &(info3->dom_sid.sid), - info3->gids[i].g_rid)) + for (i = 0; i < info3->base.groups.count; i++) { + if (!sid_compose(&sid, info3->base.domain_sid, + info3->base.groups.rids[i].rid)) { DEBUG(3, ("could not compose SID from additional group " - "rid 0x%x\n", info3->gids[i].g_rid)); + "rid 0x%x\n", info3->base.groups.rids[i].rid)); return NT_STATUS_INVALID_PARAMETER; } status = add_sid_to_array(mem_ctx, &sid, &sid_array, &num_sids); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("could not append SID from additional group " - "rid 0x%x\n", info3->gids[i].g_rid)); + "rid 0x%x\n", info3->base.groups.rids[i].rid)); return status; } } @@ -727,12 +727,12 @@ NTSTATUS sid_array_from_info3(TALLOC_CTX *mem_ctx, http://www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp */ - for (i = 0; i < info3->num_other_sids; i++) { - status = add_sid_to_array(mem_ctx, &info3->other_sids[i].sid, + for (i = 0; i < info3->sidcount; i++) { + status = add_sid_to_array(mem_ctx, info3->sids[i].sid, &sid_array, &num_sids); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("could not add SID to array: %s\n", - sid_string_dbg(&info3->other_sids[i].sid))); + sid_string_dbg(info3->sids[i].sid))); return status; } } diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index 945506ea77..a7c35c4887 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -112,7 +112,7 @@ static bool interpret_string_addr_internal(struct addrinfo **ppres, &hints, ppres); if (ret) { - DEBUG(3,("interpret_string_addr_interal: getaddrinfo failed " + DEBUG(3,("interpret_string_addr_internal: getaddrinfo failed " "for name %s [%s]\n", str, gai_strerror(ret) )); @@ -476,6 +476,29 @@ bool is_address_any(const struct sockaddr_storage *psa) } /**************************************************************************** + Get a port number in host byte order from a sockaddr_storage. +****************************************************************************/ + +uint16_t get_sockaddr_port(const struct sockaddr_storage *pss) +{ + uint16_t port = 0; + + if (pss->ss_family != AF_INET) { +#if defined(HAVE_IPV6) + /* IPv6 */ + const struct sockaddr_in6 *sa6 = + (const struct sockaddr_in6 *)pss; + port = ntohs(sa6->sin6_port); +#endif + } else { + const struct sockaddr_in *sa = + (const struct sockaddr_in *)pss; + port = ntohs(sa->sin_port); + } + return port; +} + +/**************************************************************************** Print out an IPv4 or IPv6 address from a struct sockaddr_storage. ****************************************************************************/ @@ -518,7 +541,7 @@ char *print_canonical_sockaddr(TALLOC_CTX *ctx, char *dest = NULL; int ret; - ret = getnameinfo((const struct sockaddr *)pss, + ret = sys_getnameinfo((const struct sockaddr *)pss, sizeof(struct sockaddr_storage), addr, sizeof(addr), NULL, 0, @@ -890,12 +913,10 @@ ssize_t read_udp_v4_socket(int fd, time_out = timeout in milliseconds ****************************************************************************/ -ssize_t read_socket_with_timeout(int fd, - char *buf, - size_t mincnt, - size_t maxcnt, - unsigned int time_out, - enum smb_read_errors *pre) +NTSTATUS read_socket_with_timeout(int fd, char *buf, + size_t mincnt, size_t maxcnt, + unsigned int time_out, + size_t *size_ret) { fd_set fds; int selrtn; @@ -906,9 +927,7 @@ ssize_t read_socket_with_timeout(int fd, /* just checking .... */ if (maxcnt <= 0) - return(0); - - set_smb_read_error(pre,SMB_READ_OK); + return NT_STATUS_OK; /* Blocking read */ if (time_out == 0) { @@ -922,8 +941,7 @@ ssize_t read_socket_with_timeout(int fd, if (readret == 0) { DEBUG(5,("read_socket_with_timeout: " "blocking read. EOF from client.\n")); - set_smb_read_error(pre,SMB_READ_EOF); - return -1; + return NT_STATUS_END_OF_FILE; } if (readret == -1) { @@ -939,12 +957,11 @@ ssize_t read_socket_with_timeout(int fd, "read error = %s.\n", strerror(errno) )); } - set_smb_read_error(pre,SMB_READ_ERROR); - return -1; + return map_nt_error_from_unix(errno); } nread += readret; } - return((ssize_t)nread); + goto done; } /* Most difficult - timeout read */ @@ -978,16 +995,14 @@ ssize_t read_socket_with_timeout(int fd, "read. select error = %s.\n", strerror(errno) )); } - set_smb_read_error(pre,SMB_READ_ERROR); - return -1; + return map_nt_error_from_unix(errno); } /* Did we timeout ? */ if (selrtn == 0) { DEBUG(10,("read_socket_with_timeout: timeout read. " "select timed out.\n")); - set_smb_read_error(pre,SMB_READ_TIMEOUT); - return -1; + return NT_STATUS_IO_TIMEOUT; } readret = sys_read(fd, buf+nread, maxcnt-nread); @@ -996,8 +1011,7 @@ ssize_t read_socket_with_timeout(int fd, /* we got EOF on the file descriptor */ DEBUG(5,("read_socket_with_timeout: timeout read. " "EOF from client.\n")); - set_smb_read_error(pre,SMB_READ_EOF); - return -1; + return NT_STATUS_END_OF_FILE; } if (readret == -1) { @@ -1014,61 +1028,27 @@ ssize_t read_socket_with_timeout(int fd, "read. read error = %s.\n", strerror(errno) )); } - set_smb_read_error(pre,SMB_READ_ERROR); - return -1; + return map_nt_error_from_unix(errno); } nread += readret; } + done: /* Return the number we got */ - return (ssize_t)nread; + if (size_ret) { + *size_ret = nread; + } + return NT_STATUS_OK; } /**************************************************************************** Read data from the client, reading exactly N bytes. ****************************************************************************/ -ssize_t read_data(int fd,char *buffer,size_t N, enum smb_read_errors *pre) +NTSTATUS read_data(int fd, char *buffer, size_t N) { - ssize_t ret; - size_t total=0; - char addr[INET6_ADDRSTRLEN]; - - set_smb_read_error(pre,SMB_READ_OK); - - while (total < N) { - ret = sys_read(fd,buffer + total,N - total); - - if (ret == 0) { - DEBUG(10,("read_data: read of %d returned 0. " - "Error = %s\n", - (int)(N - total), strerror(errno) )); - set_smb_read_error(pre,SMB_READ_EOF); - return 0; - } - - if (ret == -1) { - if (fd == get_client_fd()) { - /* Try and give an error message saying - * what client failed. */ - DEBUG(0,("read_data: read failure for %d " - "bytes to client %s. Error = %s\n", - (int)(N - total), - get_peer_addr(fd,addr,sizeof(addr)), - strerror(errno) )); - } else { - DEBUG(0,("read_data: read failure for %d. " - "Error = %s\n", - (int)(N - total), - strerror(errno) )); - } - set_smb_read_error(pre,SMB_READ_ERROR); - return -1; - } - total += ret; - } - return (ssize_t)total; + return read_socket_with_timeout(fd, buffer, N, N, 0, NULL); } /**************************************************************************** @@ -1130,37 +1110,29 @@ bool send_keepalive(int client) Timeout is in milliseconds. ****************************************************************************/ -ssize_t read_smb_length_return_keepalive(int fd, - char *inbuf, - unsigned int timeout, - enum smb_read_errors *pre) +NTSTATUS read_smb_length_return_keepalive(int fd, char *inbuf, + unsigned int timeout, + size_t *len) { - ssize_t len=0; int msg_type; - bool ok = false; + NTSTATUS status; - while (!ok) { - if (timeout > 0) { - ok = (read_socket_with_timeout(fd,inbuf,4,4, - timeout,pre) == 4); - } else { - ok = (read_data(fd,inbuf,4,pre) == 4); - } - if (!ok) { - return -1; - } + status = read_socket_with_timeout(fd, inbuf, 4, 4, timeout, NULL); + + if (!NT_STATUS_IS_OK(status)) { + return status; + } - len = smb_len(inbuf); - msg_type = CVAL(inbuf,0); + *len = smb_len(inbuf); + msg_type = CVAL(inbuf,0); - if (msg_type == SMBkeepalive) { - DEBUG(5,("Got keepalive packet\n")); - } + if (msg_type == SMBkeepalive) { + DEBUG(5,("Got keepalive packet\n")); } - DEBUG(10,("got smb length of %lu\n",(unsigned long)len)); + DEBUG(10,("got smb length of %lu\n",(unsigned long)(*len))); - return len; + return NT_STATUS_OK; } /**************************************************************************** @@ -1170,25 +1142,27 @@ ssize_t read_smb_length_return_keepalive(int fd, Timeout is in milliseconds. ****************************************************************************/ -ssize_t read_smb_length(int fd, char *inbuf, unsigned int timeout, enum smb_read_errors *pre) +NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout, + size_t *len) { - ssize_t len; + uint8_t msgtype = SMBkeepalive; - for(;;) { - len = read_smb_length_return_keepalive(fd, inbuf, timeout, pre); + while (msgtype == SMBkeepalive) { + NTSTATUS status; - if(len < 0) - return len; + status = read_smb_length_return_keepalive(fd, inbuf, timeout, + len); + if (!NT_STATUS_IS_OK(status)) { + return status; + } - /* Ignore session keepalives. */ - if(CVAL(inbuf,0) != SMBkeepalive) - break; + msgtype = CVAL(inbuf, 0); } DEBUG(10,("read_smb_length: got smb length of %lu\n", (unsigned long)len)); - return len; + return NT_STATUS_OK; } /**************************************************************************** @@ -1201,28 +1175,17 @@ ssize_t read_smb_length(int fd, char *inbuf, unsigned int timeout, enum smb_read Doesn't check the MAC on signed packets. ****************************************************************************/ -ssize_t receive_smb_raw(int fd, - char *buffer, - unsigned int timeout, - size_t maxlen, - enum smb_read_errors *pre) +NTSTATUS receive_smb_raw(int fd, char *buffer, unsigned int timeout, + size_t maxlen, size_t *p_len) { - ssize_t len,ret; - - set_smb_read_error(pre,SMB_READ_OK); + size_t len; + NTSTATUS status; - len = read_smb_length_return_keepalive(fd,buffer,timeout,pre); - if (len < 0) { - DEBUG(10,("receive_smb_raw: length < 0!\n")); + status = read_smb_length_return_keepalive(fd,buffer,timeout,&len); - /* - * Correct fix. smb_read_error may have already been - * set. Only set it here if not already set. Global - * variables still suck :-). JRA. - */ - - cond_set_smb_read_error(pre,SMB_READ_ERROR); - return -1; + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("receive_smb_raw: %s!\n", nt_errstr(status))); + return status; } /* @@ -1234,15 +1197,7 @@ ssize_t receive_smb_raw(int fd, DEBUG(0,("Invalid packet length! (%lu bytes).\n", (unsigned long)len)); if (len > BUFFER_SIZE + (SAFETY_MARGIN/2)) { - - /* - * Correct fix. smb_read_error may have already been - * set. Only set it here if not already set. Global - * variables still suck :-). JRA. - */ - - cond_set_smb_read_error(pre,SMB_READ_ERROR); - return -1; + return NT_STATUS_INVALID_PARAMETER; } } @@ -1251,20 +1206,11 @@ ssize_t receive_smb_raw(int fd, len = MIN(len,maxlen); } - if (timeout > 0) { - ret = read_socket_with_timeout(fd, - buffer+4, - len, - len, - timeout, - pre); - } else { - ret = read_data(fd,buffer+4,len,pre); - } + status = read_socket_with_timeout( + fd, buffer+4, len, len, timeout, &len); - if (ret != len) { - cond_set_smb_read_error(pre,SMB_READ_ERROR); - return -1; + if (!NT_STATUS_IS_OK(status)) { + return status; } /* not all of samba3 properly checks for packet-termination @@ -1273,7 +1219,8 @@ ssize_t receive_smb_raw(int fd, SSVAL(buffer+4,len, 0); } - return len; + *p_len = len; + return NT_STATUS_OK; } /**************************************************************************** @@ -1847,7 +1794,7 @@ const char *get_peer_name(int fd, bool force_lookup) } /* Look up the remote host name. */ - ret = getnameinfo((struct sockaddr *)&ss, + ret = sys_getnameinfo((struct sockaddr *)&ss, length, name_buf, sizeof(name_buf), @@ -1957,8 +1904,7 @@ int create_pipe_sock(const char *socket_dir, goto out_close; } - asprintf(&path, "%s/%s", socket_dir, socket_name); - if (!path) { + if (asprintf(&path, "%s/%s", socket_dir, socket_name) == -1) { goto out_close; } @@ -1986,7 +1932,8 @@ int create_pipe_sock(const char *socket_dir, out_close: SAFE_FREE(path); - close(sock); + if (sock != -1) + close(sock); out_umask: umask(old_umask); @@ -2057,14 +2004,15 @@ const char *get_mydnsfullname(void) data_blob_string_const("get_mydnsfullname"), data_blob_string_const(res->ai_canonname)); - freeaddrinfo(res); - if (!memcache_lookup(NULL, SINGLETON_CACHE, data_blob_string_const("get_mydnsfullname"), &tmp)) { - return NULL; + tmp = data_blob_talloc(talloc_tos(), res->ai_canonname, + strlen(res->ai_canonname) + 1); } + freeaddrinfo(res); + return (const char *)tmp.data; } diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c index 3e3268104c..cb8a100fa7 100644 --- a/source3/lib/util_str.c +++ b/source3/lib/util_str.c @@ -1841,149 +1841,93 @@ int fstr_sprintf(fstring s, const char *fmt, ...) #define S_LIST_ABS 16 /* List Allocation Block Size */ -static char **str_list_make_internal(TALLOC_CTX *mem_ctx, - const char *string, - const char *sep) +char **str_list_make(TALLOC_CTX *mem_ctx, const char *string, const char *sep) { - char **list, **rlist; + char **list; const char *str; char *s; int num, lsize; char *tok; - TALLOC_CTX *frame = NULL; if (!string || !*string) return NULL; - if (mem_ctx) { - s = talloc_strdup(mem_ctx, string); - } else { - s = SMB_STRDUP(string); + + list = TALLOC_ARRAY(mem_ctx, char *, S_LIST_ABS+1); + if (list == NULL) { + return NULL; } - if (!s) { + lsize = S_LIST_ABS; + + s = talloc_strdup(list, string); + if (s == NULL) { DEBUG(0,("str_list_make: Unable to allocate memory")); + TALLOC_FREE(list); return NULL; } if (!sep) sep = LIST_SEP; - num = lsize = 0; - list = NULL; - + num = 0; str = s; - frame = talloc_stackframe(); - while (next_token_talloc(frame, &str, &tok, sep)) { + + while (next_token_talloc(list, &str, &tok, sep)) { + if (num == lsize) { + char **tmp; + lsize += S_LIST_ABS; - if (mem_ctx) { - rlist = TALLOC_REALLOC_ARRAY(mem_ctx, list, - char *, lsize +1); - } else { - /* We need to keep the old list on - * error so we can free the elements - if the realloc fails. */ - rlist =SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(list, - char *, lsize +1); - } - if (!rlist) { + + tmp = TALLOC_REALLOC_ARRAY(mem_ctx, list, char *, + lsize + 1); + if (tmp == NULL) { DEBUG(0,("str_list_make: " "Unable to allocate memory")); - str_list_free(&list); - if (mem_ctx) { - TALLOC_FREE(s); - } else { - SAFE_FREE(s); - } - TALLOC_FREE(frame); + TALLOC_FREE(list); return NULL; - } else { - list = rlist; } - memset (&list[num], 0, - ((sizeof(char**)) * (S_LIST_ABS +1))); - } - if (mem_ctx) { - list[num] = talloc_strdup(mem_ctx, tok); - } else { - list[num] = SMB_STRDUP(tok); - } + list = tmp; - if (!list[num]) { - DEBUG(0,("str_list_make: Unable to allocate memory")); - str_list_free(&list); - if (mem_ctx) { - TALLOC_FREE(s); - } else { - SAFE_FREE(s); - } - TALLOC_FREE(frame); - return NULL; + memset (&list[num], 0, + ((sizeof(char**)) * (S_LIST_ABS +1))); } - num++; + list[num] = tok; + num += 1; } - TALLOC_FREE(frame); - - if (mem_ctx) { - TALLOC_FREE(s); - } else { - SAFE_FREE(s); - } + list[num] = NULL; + TALLOC_FREE(s); return list; } -char **str_list_make_talloc(TALLOC_CTX *mem_ctx, - const char *string, - const char *sep) -{ - return str_list_make_internal(mem_ctx, string, sep); -} - -char **str_list_make(const char *string, const char *sep) +bool str_list_copy(TALLOC_CTX *mem_ctx, char ***dest, const char **src) { - return str_list_make_internal(NULL, string, sep); -} - -bool str_list_copy(char ***dest, const char **src) -{ - char **list, **rlist; - int num, lsize; + char **list; + int i, num; *dest = NULL; if (!src) return false; - num = lsize = 0; - list = NULL; + num = 0; + while (src[num] != NULL) { + num += 1; + } - while (src[num]) { - if (num == lsize) { - lsize += S_LIST_ABS; - rlist = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(list, - char *, lsize +1); - if (!rlist) { - DEBUG(0,("str_list_copy: " - "Unable to re-allocate memory")); - str_list_free(&list); - return false; - } else { - list = rlist; - } - memset (&list[num], 0, - ((sizeof(char **)) * (S_LIST_ABS +1))); - } + list = TALLOC_ARRAY(mem_ctx, char *, num+1); + if (list == NULL) { + return false; + } - list[num] = SMB_STRDUP(src[num]); - if (!list[num]) { - DEBUG(0,("str_list_copy: Unable to allocate memory")); - str_list_free(&list); + for (i=0; i<num; i++) { + list[i] = talloc_strdup(list, src[i]); + if (list[i] == NULL) { + TALLOC_FREE(list); return false; } - - num++; } - + list[i] = NULL; *dest = list; return true; } @@ -2010,37 +1954,6 @@ bool str_list_compare(char **list1, char **list2) return true; } -static void str_list_free_internal(TALLOC_CTX *mem_ctx, char ***list) -{ - char **tlist; - - if (!list || !*list) - return; - tlist = *list; - for(; *tlist; tlist++) { - if (mem_ctx) { - TALLOC_FREE(*tlist); - } else { - SAFE_FREE(*tlist); - } - } - if (mem_ctx) { - TALLOC_FREE(*tlist); - } else { - SAFE_FREE(*list); - } -} - -void str_list_free_talloc(TALLOC_CTX *mem_ctx, char ***list) -{ - str_list_free_internal(mem_ctx, list); -} - -void str_list_free(char ***list) -{ - str_list_free_internal(NULL, list); -} - /****************************************************************************** *****************************************************************************/ @@ -2173,6 +2086,7 @@ static char *ipstr_list_add(char **ipstr_list, const struct ip_service *service) { char *new_ipstr = NULL; char addr_buf[INET6_ADDRSTRLEN]; + int ret; /* arguments checking */ if (!ipstr_list || !service) { @@ -2187,33 +2101,30 @@ static char *ipstr_list_add(char **ipstr_list, const struct ip_service *service) if (*ipstr_list) { if (service->ss.ss_family == AF_INET) { /* IPv4 */ - asprintf(&new_ipstr, "%s%s%s:%d", - *ipstr_list, - IPSTR_LIST_SEP, - addr_buf, - service->port); + ret = asprintf(&new_ipstr, "%s%s%s:%d", *ipstr_list, + IPSTR_LIST_SEP, addr_buf, + service->port); } else { /* IPv6 */ - asprintf(&new_ipstr, "%s%s[%s]:%d", - *ipstr_list, - IPSTR_LIST_SEP, - addr_buf, - service->port); + ret = asprintf(&new_ipstr, "%s%s[%s]:%d", *ipstr_list, + IPSTR_LIST_SEP, addr_buf, + service->port); } SAFE_FREE(*ipstr_list); } else { if (service->ss.ss_family == AF_INET) { /* IPv4 */ - asprintf(&new_ipstr, "%s:%d", - addr_buf, - service->port); + ret = asprintf(&new_ipstr, "%s:%d", addr_buf, + service->port); } else { /* IPv6 */ - asprintf(&new_ipstr, "[%s]:%d", - addr_buf, - service->port); + ret = asprintf(&new_ipstr, "[%s]:%d", addr_buf, + service->port); } } + if (ret == -1) { + return NULL; + } *ipstr_list = new_ipstr; return *ipstr_list; } @@ -2258,7 +2169,7 @@ char *ipstr_list_make(char **ipstr_list, * @param ipstr ip string list to be parsed * @param ip_list pointer to array of ip addresses which is * allocated by this function and must be freed by caller - * @return number of succesfully parsed addresses + * @return number of successfully parsed addresses **/ int ipstr_list_parse(const char *ipstr_list, struct ip_service **ip_list) @@ -2415,13 +2326,13 @@ void base64_decode_inplace(char *s) } /** - * Encode a base64 string into a malloc()ed string caller to free. + * Encode a base64 string into a talloc()ed string caller to free. * * From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c * with adjustments **/ -char *base64_encode_data_blob(DATA_BLOB data) +char *base64_encode_data_blob(TALLOC_CTX *mem_ctx, DATA_BLOB data) { int bits = 0; int char_count = 0; @@ -2434,7 +2345,7 @@ char *base64_encode_data_blob(DATA_BLOB data) out_cnt = 0; len = data.length; output_len = data.length * 2; - result = TALLOC_ARRAY(talloc_tos(), char, output_len); /* get us plenty of space */ + result = TALLOC_ARRAY(mem_ctx, char, output_len); /* get us plenty of space */ SMB_ASSERT(result != NULL); while (len-- && out_cnt < (data.length * 2) - 5) { diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index ce2cb427d1..724832ea5b 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -656,6 +656,7 @@ int tdb_unpack(const uint8 *buf, int bufsize, const char *fmt, ...) return PTR_DIFF(buf, buf0); no_space: + va_end(ap); return -1; } @@ -668,12 +669,13 @@ static void tdb_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, const char *fo { va_list ap; char *ptr = NULL; + int ret; va_start(ap, format); - vasprintf(&ptr, format, ap); + ret = vasprintf(&ptr, format, ap); va_end(ap); - if (!ptr || !*ptr) + if ((ret == -1) || !*ptr) return; DEBUG((int)level, ("tdb(%s): %s", tdb_name(tdb) ? tdb_name(tdb) : "unnamed", ptr)); @@ -866,11 +868,8 @@ static void tdb_wrap_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, va_list ap; char *ptr = NULL; int debuglevel = 0; + int ret; - va_start(ap, format); - vasprintf(&ptr, format, ap); - va_end(ap); - switch (level) { case TDB_DEBUG_FATAL: debug_level = 0; @@ -888,7 +887,11 @@ static void tdb_wrap_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, debuglevel = 0; } - if (ptr != NULL) { + va_start(ap, format); + ret = vasprintf(&ptr, format, ap); + va_end(ap); + + if (ret != -1) { const char *name = tdb_name(tdb); DEBUG(debuglevel, ("tdb(%s): %s", name ? name : "unnamed", ptr)); free(ptr); diff --git a/source3/lib/version.c b/source3/lib/version.c index 204c2044a8..3cae02ad2e 100644 --- a/source3/lib/version.c +++ b/source3/lib/version.c @@ -51,6 +51,8 @@ const char *samba_version_string(void) */ assert(res != -1); + SAFE_FREE(samba_version); + samba_version = tmp_version; #endif diff --git a/source3/lib/xfile.c b/source3/lib/xfile.c index c98522200b..ee6e581332 100644 --- a/source3/lib/xfile.c +++ b/source3/lib/xfile.c @@ -223,9 +223,15 @@ size_t x_fwrite(const void *p, size_t size, size_t nmemb, XFILE *f) VA_COPY(ap2, ap); len = vasprintf(&p, format, ap2); - if (len <= 0) return len; + if (len <= 0) { + va_end(ap2); + return len; + } ret = x_fwrite(p, 1, len, f); SAFE_FREE(p); + + va_end(ap2); + return ret; } |