static TDB_DATA unparse_share_modes(struct share_mode_data *d) { DATA_BLOB blob; enum ndr_err_code ndr_err; if (DEBUGLEVEL >= 10) { DEBUG(10, ("unparse_share_modes:\n")); NDR_PRINT_DEBUG(share_mode_data, d); } remove_stale_share_mode_entries(d); if (d->num_share_modes == 0) { DEBUG(10, ("No used share mode found\n")); return make_tdb_data(NULL, 0); } ndr_err = ndr_push_struct_blob( &blob, d, d, (ndr_push_flags_fn_t)ndr_push_share_mode_data); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { smb_panic("ndr_push_share_mode_lock failed"); } return make_tdb_data(blob.data, blob.length); }
static int collect_sessions_fn(struct smbXsrv_session_global0 *global, void *connections_forall_state) { NTSTATUS status; struct connections_forall_state *state = (struct connections_forall_state*)connections_forall_state; uint32_t id = global->session_global_id; struct connections_forall_session sess; if (global->auth_session_info == NULL) { sess.uid = -1; sess.gid = -1; } else { sess.uid = global->auth_session_info->unix_token->uid; sess.gid = global->auth_session_info->unix_token->gid; } fstrcpy(sess.machine, global->channels[0].remote_name); fstrcpy(sess.addr, global->channels[0].remote_address); sess.cipher = global->channels[0].encryption_cipher; sess.dialect = global->connection_dialect; sess.signing_flags = global->signing_flags; status = dbwrap_store(state->session_by_pid, make_tdb_data((void*)&id, sizeof(id)), make_tdb_data((void*)&sess, sizeof(sess)), TDB_INSERT); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to store record: %s\n", nt_errstr(status))); } return 0; }
bool serverid_register(const struct server_id id, uint32_t msg_flags) { struct db_context *db; struct serverid_key key; struct serverid_data data; struct db_record *rec; TDB_DATA tdbkey, tdbdata; NTSTATUS status; bool ret = false; db = serverid_db(); if (db == NULL) { return false; } serverid_fill_key(&id, &key); tdbkey = make_tdb_data((uint8_t *)&key, sizeof(key)); rec = dbwrap_fetch_locked(db, talloc_tos(), tdbkey); if (rec == NULL) { DEBUG(1, ("Could not fetch_lock serverid.tdb record\n")); return false; } ZERO_STRUCT(data); data.unique_id = id.unique_id; data.msg_flags = msg_flags; tdbdata = make_tdb_data((uint8_t *)&data, sizeof(data)); status = dbwrap_record_store(rec, tdbdata, 0); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Storing serverid.tdb record failed: %s\n", nt_errstr(status))); goto done; } if (lp_clustering() && ctdb_serverids_exist_supported(messaging_ctdbd_connection())) { register_with_ctdbd(messaging_ctdbd_connection(), id.unique_id, NULL, NULL); } ret = true; done: TALLOC_FREE(rec); return ret; }
static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle, files_struct *fsp, DATA_BLOB *pblob) { uint8_t id_buf[16]; struct file_id id; TDB_DATA data; struct db_context *db = acl_db; struct db_record *rec; NTSTATUS status; DEBUG(10,("store_acl_blob_fsp: storing blob length %u on file %s\n", (unsigned int)pblob->length, fsp_str_dbg(fsp))); status = vfs_stat_fsp(fsp); if (!NT_STATUS_IS_OK(status)) { return status; } id = vfs_file_id_from_sbuf(handle->conn, &fsp->fsp_name->st); /* For backwards compatibility only store the dev/inode. */ push_file_id_16((char *)id_buf, &id); rec = dbwrap_fetch_locked(db, talloc_tos(), make_tdb_data(id_buf, sizeof(id_buf))); if (rec == NULL) { DEBUG(0, ("store_acl_blob_fsp_tdb: fetch_lock failed\n")); return NT_STATUS_INTERNAL_DB_CORRUPTION; } data.dptr = pblob->data; data.dsize = pblob->length; return dbwrap_record_store(rec, data, 0); }
void reduce_windows_lock_ref_count(files_struct *fsp, unsigned int dcount) { struct lock_ref_count_key tmp; struct db_record *rec; int lock_ref_count = 0; NTSTATUS status; rec = posix_pending_close_db->fetch_locked( posix_pending_close_db, talloc_tos(), locking_ref_count_key_fsp(fsp, &tmp)); SMB_ASSERT((rec != NULL) && (rec->value.dptr != NULL) && (rec->value.dsize == sizeof(lock_ref_count))); memcpy(&lock_ref_count, rec->value.dptr, sizeof(lock_ref_count)); SMB_ASSERT(lock_ref_count > 0); lock_ref_count -= dcount; status = rec->store(rec, make_tdb_data((uint8 *)&lock_ref_count, sizeof(lock_ref_count)), 0); SMB_ASSERT(NT_STATUS_IS_OK(status)); TALLOC_FREE(rec); DEBUG(10,("reduce_windows_lock_ref_count for file now %s = %d\n", fsp_str_dbg(fsp), lock_ref_count)); }
static bool add_mapping_entry(GROUP_MAP *map, int flag) { char *key, *buf; int len; NTSTATUS status; key = group_mapping_key(talloc_tos(), &map->sid); if (key == NULL) { return false; } len = tdb_pack(NULL, 0, "ddff", map->gid, map->sid_name_use, map->nt_name, map->comment); buf = talloc_array(key, char, len); if (!buf) { TALLOC_FREE(key); return false; } len = tdb_pack((uint8 *)buf, len, "ddff", map->gid, map->sid_name_use, map->nt_name, map->comment); status = dbwrap_trans_store( db, string_term_tdb_data(key), make_tdb_data((uint8_t *)buf, len), TDB_REPLACE); TALLOC_FREE(key); return NT_STATUS_IS_OK(status); }
static bool leases_db_key(TALLOC_CTX *mem_ctx, const struct GUID *client_guid, const struct smb2_lease_key *lease_key, TDB_DATA *key) { struct leases_db_key db_key = { .client_guid = *client_guid, .lease_key = *lease_key }; DATA_BLOB blob; enum ndr_err_code ndr_err; if (DEBUGLEVEL >= 10) { DEBUG(10, ("%s:\n", __func__)); NDR_PRINT_DEBUG(leases_db_key, &db_key); } ndr_err = ndr_push_struct_blob( &blob, mem_ctx, &db_key, (ndr_push_flags_fn_t)ndr_push_leases_db_key); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(10, ("%s: ndr_push_struct_blob_failed: %s\n", __func__, ndr_errstr(ndr_err))); return false; } *key = make_tdb_data(blob.data, blob.length); return true; }
static void add_fd_to_close_entry(files_struct *fsp) { struct db_record *rec; uint8_t *new_data; NTSTATUS status; rec = posix_pending_close_db->fetch_locked( posix_pending_close_db, talloc_tos(), fd_array_key_fsp(fsp)); SMB_ASSERT(rec != NULL); new_data = talloc_array( rec, uint8_t, rec->value.dsize + sizeof(fsp->fh->fd)); SMB_ASSERT(new_data != NULL); memcpy(new_data, rec->value.dptr, rec->value.dsize); memcpy(new_data + rec->value.dsize, &fsp->fh->fd, sizeof(fsp->fh->fd)); status = rec->store( rec, make_tdb_data(new_data, rec->value.dsize + sizeof(fsp->fh->fd)), 0); SMB_ASSERT(NT_STATUS_IS_OK(status)); TALLOC_FREE(rec); DEBUG(10,("add_fd_to_close_entry: added fd %d file %s\n", fsp->fh->fd, fsp_str_dbg(fsp))); }
bool serverid_deregister(struct server_id id) { struct db_context *db; struct serverid_key key; struct db_record *rec; TDB_DATA tdbkey; NTSTATUS status; bool ret = false; db = serverid_db(); if (db == NULL) { return false; } serverid_fill_key(&id, &key); tdbkey = make_tdb_data((uint8_t *)&key, sizeof(key)); rec = dbwrap_fetch_locked(db, talloc_tos(), tdbkey); if (rec == NULL) { DEBUG(1, ("Could not fetch_lock serverid.tdb record\n")); return false; } status = dbwrap_record_delete(rec); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Deleting serverid.tdb record failed: %s\n", nt_errstr(status))); goto done; } ret = true; done: TALLOC_FREE(rec); return ret; }
static TDB_DATA locking_ref_count_key_fsp(files_struct *fsp, struct lock_ref_count_key *tmp) { ZERO_STRUCTP(tmp); tmp->id = fsp->file_id; tmp->r = 'r'; return make_tdb_data((uint8_t *)tmp, sizeof(*tmp)); }
/* ------------------------ */ cnid_t cnid_tdb_add(struct _cnid_db *cdb, const struct stat *st, cnid_t did, const char *name, size_t len, cnid_t hint) { const struct stat *lstp; cnid_t id; struct _cnid_tdb_private *priv; TDB_DATA key, data; int rc; if (!cdb || !(priv = cdb->_private) || !st || !name) { errno = CNID_ERR_PARAM; return CNID_INVALID; } /* Do a lookup. */ id = cnid_tdb_lookup(cdb, st, did, name, len); /* ... Return id if it is valid, or if Rootinfo is read-only. */ if (id || (priv->flags & CNIDFLAG_DB_RO)) { return id; } #if 0 struct stat lst; lstp = lstat(name, &lst) < 0 ? st : &lst; #endif lstp = st; /* Initialize our DBT data structures. */ memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); key.dptr = (char *)&hint; key.dsize = sizeof(cnid_t); if ((data.dptr = make_tdb_data(cdb->flags, lstp, did, name, len)) == NULL) { LOG(log_error, logtype_default, "tdb_add: Path name is too long"); errno = CNID_ERR_PATH; return CNID_INVALID; } data.dsize = CNID_HEADER_LEN + len + 1; hint = get_cnid(priv); if (hint == 0) { errno = CNID_ERR_DB; return CNID_INVALID; } memcpy(data.dptr, &hint, sizeof(hint)); /* Now we need to add the CNID data to the databases. */ rc = add_cnid(priv, &key, &data); if (rc) { LOG(log_error, logtype_default, "tdb_add: Failed to add CNID for %s to database using hint %u", name, ntohl(hint)); errno = CNID_ERR_DB; return CNID_INVALID; } return hint; }
static NTSTATUS get_acl_blob(TALLOC_CTX *ctx, vfs_handle_struct *handle, files_struct *fsp, const struct smb_filename *smb_fname, DATA_BLOB *pblob) { uint8_t id_buf[16]; TDB_DATA data; struct file_id id; struct db_context *db = acl_db; NTSTATUS status = NT_STATUS_OK; SMB_STRUCT_STAT sbuf; ZERO_STRUCT(sbuf); if (fsp) { status = vfs_stat_fsp(fsp); sbuf = fsp->fsp_name->st; } else { int ret = vfs_stat_smb_basename(handle->conn, smb_fname, &sbuf); if (ret == -1) { status = map_nt_error_from_unix(errno); } } if (!NT_STATUS_IS_OK(status)) { return status; } id = vfs_file_id_from_sbuf(handle->conn, &sbuf); /* For backwards compatibility only store the dev/inode. */ push_file_id_16((char *)id_buf, &id); status = dbwrap_fetch(db, ctx, make_tdb_data(id_buf, sizeof(id_buf)), &data); if (!NT_STATUS_IS_OK(status)) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } pblob->data = data.dptr; pblob->length = data.dsize; DEBUG(10,("get_acl_blob: returned %u bytes from file %s\n", (unsigned int)data.dsize, smb_fname->base_name )); if (pblob->length == 0 || pblob->data == NULL) { return NT_STATUS_NOT_FOUND; } return NT_STATUS_OK; }
TDB_DATA dbwrap_fetch(struct db_context *db, TALLOC_CTX *mem_ctx, TDB_DATA key) { TDB_DATA result; if (db->fetch(db, mem_ctx, key, &result) != 0) { return make_tdb_data(NULL, 0); } return result; }
static TDB_DATA smbXsrv_tcon_global_id_to_key(uint32_t id, uint8_t *key_buf) { TDB_DATA key; RSIVAL(key_buf, 0, id); key = make_tdb_data(key_buf, SMBXSRV_TCON_GLOBAL_TDB_KEY_SIZE); return key; }
bool serverid_register_msg_flags(const struct server_id id, bool do_reg, uint32_t msg_flags) { struct db_context *db; struct serverid_key key; struct serverid_data *data; struct db_record *rec; TDB_DATA tdbkey; TDB_DATA value; NTSTATUS status; bool ret = false; db = serverid_db(); if (db == NULL) { return false; } serverid_fill_key(&id, &key); tdbkey = make_tdb_data((uint8_t *)&key, sizeof(key)); rec = dbwrap_fetch_locked(db, talloc_tos(), tdbkey); if (rec == NULL) { DEBUG(1, ("Could not fetch_lock serverid.tdb record\n")); return false; } value = dbwrap_record_get_value(rec); if (value.dsize != sizeof(struct serverid_data)) { DEBUG(1, ("serverid record has unexpected size %d " "(wanted %d)\n", (int)value.dsize, (int)sizeof(struct serverid_data))); goto done; } data = (struct serverid_data *)value.dptr; if (do_reg) { data->msg_flags |= msg_flags; } else { data->msg_flags &= ~msg_flags; } status = dbwrap_record_store(rec, value, 0); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Storing serverid.tdb record failed: %s\n", nt_errstr(status))); goto done; } ret = true; done: TALLOC_FREE(rec); return ret; }
static TDB_DATA smbXsrv_session_local_id_to_key(uint32_t id, uint8_t *key_buf) { TDB_DATA key; RSIVAL(key_buf, 0, id); key = make_tdb_data(key_buf, SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE); return key; }
TDB_DATA dbwrap_fetch_bystring(struct db_context *db, TALLOC_CTX *mem_ctx, const char *key) { TDB_DATA result; if (db->fetch(db, mem_ctx, string_term_tdb_data(key), &result) == -1) { return make_tdb_data(NULL, 0); } return result; }
static struct db_record *acl_tdb_lock(TALLOC_CTX *mem_ctx, struct db_context *db, const struct file_id *id) { uint8 id_buf[16]; push_file_id_16((char *)id_buf, id); return db->fetch_locked(db, mem_ctx, make_tdb_data(id_buf, sizeof(id_buf))); }
static NTSTATUS get_acl_blob(TALLOC_CTX *ctx, vfs_handle_struct *handle, files_struct *fsp, const char *name, DATA_BLOB *pblob) { uint8 id_buf[16]; TDB_DATA data; struct file_id id; struct db_context *db; int ret = -1; SMB_STRUCT_STAT sbuf; SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return NT_STATUS_INTERNAL_DB_CORRUPTION); if (fsp && fsp->fh->fd != -1) { ret = SMB_VFS_FSTAT(fsp, &sbuf); } else { if (fsp && fsp->posix_open) { ret = SMB_VFS_LSTAT(handle->conn, name, &sbuf); } else { ret = SMB_VFS_STAT(handle->conn, name, &sbuf); } } if (ret == -1) { return map_nt_error_from_unix(errno); } id = vfs_file_id_from_sbuf(handle->conn, &sbuf); /* For backwards compatibility only store the dev/inode. */ push_file_id_16((char *)id_buf, &id); if (db->fetch(db, ctx, make_tdb_data(id_buf, sizeof(id_buf)), &data) == -1) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } pblob->data = data.dptr; pblob->length = data.dsize; DEBUG(10,("get_acl_blob: returned %u bytes from file %s\n", (unsigned int)data.dsize, name )); if (pblob->length == 0 || pblob->data == NULL) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } return NT_STATUS_OK; }
NTSTATUS dbwrap_trans_store_uint32(struct db_context *db, const char *keystr, uint32_t v) { uint32 v_store; SIVAL(&v_store, 0, v); return dbwrap_trans_store(db, string_term_tdb_data(keystr), make_tdb_data((const uint8 *)&v_store, sizeof(v_store)), TDB_REPLACE); }
/* store a secrets entry */ bool secrets_store(const char *key, const void *data, size_t size) { NTSTATUS status; if (!secrets_init()) { return false; } status = dbwrap_trans_store(db_ctx, string_tdb_data(key), make_tdb_data((const uint8 *)data, size), TDB_REPLACE); return NT_STATUS_IS_OK(status); }
static struct db_record *acl_tdb_lock(TALLOC_CTX *mem_ctx, struct db_context *db, const struct file_id *id) { uint8_t id_buf[16]; /* For backwards compatibility only store the dev/inode. */ push_file_id_16((char *)id_buf, id); return dbwrap_fetch_locked(db, mem_ctx, make_tdb_data(id_buf, sizeof(id_buf))); }
static TDB_DATA unparse_share_modes(struct share_mode_data *d) { DATA_BLOB blob; enum ndr_err_code ndr_err; uint32_t i; if (DEBUGLEVEL >= 10) { DEBUG(10, ("unparse_share_modes:\n")); NDR_PRINT_DEBUG(share_mode_data, d); } i = 0; while (i < d->num_share_modes) { if (d->share_modes[i].stale) { /* * Remove the stale entries before storing */ struct share_mode_entry *m = d->share_modes; m[i] = m[d->num_share_modes-1]; d->num_share_modes -= 1; } else { i += 1; } } if (d->num_share_modes == 0) { DEBUG(10, ("No used share mode found\n")); return make_tdb_data(NULL, 0); } ndr_err = ndr_push_struct_blob( &blob, d, d, (ndr_push_flags_fn_t)ndr_push_share_mode_data); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { smb_panic("ndr_push_share_mode_lock failed"); } return make_tdb_data(blob.data, blob.length); }
TDB_DATA dbwrap_fetch_bystring_upper(struct db_context *db, TALLOC_CTX *mem_ctx, const char *key) { char *key_upper; TDB_DATA result; key_upper = talloc_strdup_upper(talloc_tos(), key); if (key_upper == NULL) { return make_tdb_data(NULL, 0); } result = dbwrap_fetch_bystring(db, mem_ctx, key_upper); talloc_free(key_upper); return result; }
static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle, files_struct *fsp, DATA_BLOB *pblob) { uint8 id_buf[16]; struct file_id id; SMB_STRUCT_STAT sbuf; TDB_DATA data; struct db_context *db; struct db_record *rec; int ret = -1; DEBUG(10,("store_acl_blob_fsp: storing blob length %u on file %s\n", (unsigned int)pblob->length, fsp->fsp_name)); SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return NT_STATUS_INTERNAL_DB_CORRUPTION); if (fsp->fh->fd != -1) { ret = SMB_VFS_FSTAT(fsp, &sbuf); } else { if (fsp->posix_open) { ret = SMB_VFS_LSTAT(handle->conn, fsp->fsp_name, &sbuf); } else { ret = SMB_VFS_STAT(handle->conn, fsp->fsp_name, &sbuf); } } if (ret == -1) { return map_nt_error_from_unix(errno); } id = vfs_file_id_from_sbuf(handle->conn, &sbuf); /* For backwards compatibility only store the dev/inode. */ push_file_id_16((char *)id_buf, &id); rec = db->fetch_locked(db, talloc_tos(), make_tdb_data(id_buf, sizeof(id_buf))); if (rec == NULL) { DEBUG(0, ("store_acl_blob_fsp_tdb: fetch_lock failed\n")); return NT_STATUS_INTERNAL_DB_CORRUPTION; } data.dptr = pblob->data; data.dsize = pblob->length; return rec->store(rec, data, 0); }
static int db_ctdb_ltdb_parser(TDB_DATA key, TDB_DATA data, void *private_data) { struct db_ctdb_ltdb_parse_state *state = (struct db_ctdb_ltdb_parse_state *)private_data; if (data.dsize < sizeof(struct ctdb_ltdb_header)) { return -1; } state->parser( key, (struct ctdb_ltdb_header *)data.dptr, make_tdb_data(data.dptr + sizeof(struct ctdb_ltdb_header), data.dsize - sizeof(struct ctdb_ltdb_header)), state->private_data); return 0; }
static NTSTATUS store_acl_blob_pathname(vfs_handle_struct *handle, const char *fname, DATA_BLOB *pblob) { uint8 id_buf[16]; struct file_id id; TDB_DATA data; SMB_STRUCT_STAT sbuf; struct db_context *db; struct db_record *rec; int ret = -1; DEBUG(10,("store_acl_blob_pathname: storing blob " "length %u on file %s\n", (unsigned int)pblob->length, fname)); SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return NT_STATUS_INTERNAL_DB_CORRUPTION); if (lp_posix_pathnames()) { ret = SMB_VFS_LSTAT(handle->conn, fname, &sbuf); } else { ret = SMB_VFS_STAT(handle->conn, fname, &sbuf); } if (ret == -1) { return map_nt_error_from_unix(errno); } id = vfs_file_id_from_sbuf(handle->conn, &sbuf); push_file_id_16((char *)id_buf, &id); rec = db->fetch_locked(db, talloc_tos(), make_tdb_data(id_buf, sizeof(id_buf))); if (rec == NULL) { DEBUG(0, ("store_acl_blob_pathname_tdb: fetch_lock failed\n")); return NT_STATUS_INTERNAL_DB_CORRUPTION; } data.dptr = pblob->data; data.dsize = pblob->length; return rec->store(rec, data, 0); }
bool serverids_exist(const struct server_id *ids, int num_ids, bool *results) { struct db_context *db; int i; #ifdef HAVE_CTDB_CONTROL_CHECK_SRVIDS_DECL if (lp_clustering()) { return ctdb_serverids_exist(messaging_ctdbd_connection(), ids, num_ids, results); } #endif if (!processes_exist(ids, num_ids, results)) { return false; } db = serverid_db(); if (db == NULL) { return false; } for (i=0; i<num_ids; i++) { struct serverid_exists_state state; struct serverid_key key; TDB_DATA tdbkey; if (ids[i].unique_id == SERVERID_UNIQUE_ID_NOT_TO_VERIFY) { results[i] = true; continue; } if (!results[i]) { continue; } serverid_fill_key(&ids[i], &key); tdbkey = make_tdb_data((uint8_t *)&key, sizeof(key)); state.id = &ids[i]; state.exists = false; dbwrap_parse_record(db, tdbkey, server_exists_parse, &state); results[i] = state.exists; } return true; }
static NTSTATUS dbwrap_change_uint32_atomic_action(struct db_context *db, void *private_data) { struct db_record *rec; uint32_t val = (uint32_t)-1; uint32_t v_store; NTSTATUS ret; struct dbwrap_change_uint32_atomic_context *state; TDB_DATA value; state = (struct dbwrap_change_uint32_atomic_context *)private_data; rec = dbwrap_fetch_locked(db, talloc_tos(), string_term_tdb_data(state->keystr)); if (!rec) { return NT_STATUS_UNSUCCESSFUL; } value = dbwrap_record_get_value(rec); if (value.dptr == NULL) { val = *(state->oldval); } else if (value.dsize == sizeof(val)) { val = IVAL(value.dptr, 0); *(state->oldval) = val; } else { ret = NT_STATUS_UNSUCCESSFUL; goto done; } val += state->change_val; SIVAL(&v_store, 0, val); ret = dbwrap_record_store(rec, make_tdb_data((const uint8_t *)&v_store, sizeof(v_store)), TDB_REPLACE); done: TALLOC_FREE(rec); return ret; }
int dbwrap_store_uint32(struct db_context *db, const char *keystr, uint32_t v) { struct db_record *rec; uint32 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; }