/* Authors: Pavel Březina Copyright (C) 2016 Red Hat 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 . */ #ifndef _DP_PRIVATE_H_ #define _DP_PRIVATE_H_ #include #include #include "sbus/sssd_dbus.h" #include "providers/data_provider/dp.h" #include "util/util.h" #define DP_REQ_DEBUG(level, name, fmt, ...) \ DEBUG(level, "DP Request [%s]: " fmt "\n", (name ?: "Unknown"), ##__VA_ARGS__) enum dp_clients { DPC_NSS, DPC_PAM, DPC_IFP, DPC_PAC, DPC_SUDO, DPC_HOST, DPC_AUTOFS, DP_CLIENT_SENTINEL }; struct dp_req; struct dp_client; struct dp_module { bool initialized; const char *name; void *module_data; void *libhandle; }; struct dp_target { const char *name; const char *module_name; bool explicitly_configured; bool initialized; enum dp_targets target; struct dp_module *module; struct dp_method *methods; }; struct dp_method { dp_req_send_fn send_fn; dp_req_recv_fn recv_fn; void *method_data; const char *method_dtype; const char *request_dtype; const char *output_dtype; uint32_t output_size; }; struct data_provider { uid_t uid; gid_t gid; struct be_ctx *be_ctx; struct tevent_context *ev; struct sbus_connection *srv_conn; struct dp_client *clients[DP_CLIENT_SENTINEL]; bool terminating; struct { /* Numeric identificator that will be assigned to next request. */ uint32_t index; /* List of all ongoing requests. */ uint32_t num_active; struct dp_req *active; /* Table containing list of sbus_requests where DP sends reply when * a request is finished. Value of this table is pair * */ hash_table_t *reply_table; } requests; struct dp_module **modules; struct dp_target **targets; }; errno_t dp_find_method(struct data_provider *provider, enum dp_targets target, enum dp_methods method, struct dp_method **_execute); struct dp_module *dp_load_module(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct data_provider *provider, struct dp_module **modules, const char *name); errno_t dp_init_modules(TALLOC_CTX *mem_ctx, struct dp_module ***_modules); const char *dp_target_to_string(enum dp_targets target); bool dp_target_initialized(struct dp_target **targets, enum dp_targets type); errno_t dp_init_targets(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct data_provider *provider, struct dp_module **modules); /* Reply callbacks. */ typedef void (*dp_req_post_fn)(const char *req_name, struct data_provider *provider, void *post_data, void *reply_data); typedef void (*dp_req_reply_fn)(const char *req_name, struct sbus_request *sbus_req, void *data); void dp_req_reply_default(const char *req_name, struct sbus_request *sbus_req, void *data); /* Data provider request table. */ struct dp_sbus_req_item; struct dp_table_value { hash_table_t *table; const char *key; struct tevent_req *req; struct dp_sbus_req_item *list; }; struct dp_sbus_req_item { struct dp_table_value *parent; struct sbus_request *sbus_req; struct dp_sbus_req_item *prev; struct dp_sbus_req_item *next; }; char *dp_req_table_key(TALLOC_CTX *mem_ctx, enum dp_targets target, enum dp_methods method, uint32_t dp_flags, const char *custom_part); errno_t dp_req_table_init(TALLOC_CTX *mem_ctx, hash_table_t **_table); struct dp_table_value *dp_req_table_lookup(hash_table_t *table, const char *key); errno_t dp_req_table_add(hash_table_t *table, const char *key, struct tevent_req *req, struct sbus_request *sbus_req); void dp_req_table_del(hash_table_t *table, const char *key); void dp_req_table_del_and_free(hash_table_t *table, const char *key); bool dp_req_table_has_key(hash_table_t *table, const char *key); /* Data provider request. */ void dp_terminate_active_requests(struct data_provider *provider); void dp_req_reply_error(struct sbus_request *sbus_req, const char *req_name, errno_t ret); void _dp_req_with_reply(struct dp_client *dp_cli, const char *domain, const char *request_name, const char *custom_key, struct sbus_request *sbus_req, enum dp_targets target, enum dp_methods method, uint32_t dp_flags, void *request_data, dp_req_post_fn postprocess_fn, void *postprocess_data, dp_req_reply_fn reply_fn, const char *output_dtype); /** * If @domain is NULL, be_ctx->domain is used. * If req_key is NULL, address of sbus_req is used. * * If @pp_fn (post process function) is set it is call on a successful * DP request before reply is sent. */ #define dp_req_with_reply_pp(dp_cli, domain, req_name, req_key, sbus_req, \ target, method, dp_flags, req_data, pp_fn, \ pp_data, pp_dtype, reply_fn, output_dtype) \ do { \ /* Check postprocess function parameter types. */ \ void (*__pp_fn)(const char *, struct data_provider *, \ pp_dtype *, output_dtype *) = (pp_fn); \ pp_dtype *__pp_data = (pp_data); \ \ /* Check reply function parameter types. */ \ void (*__reply_fn)(const char *, struct sbus_request *, \ output_dtype *) = (reply_fn); \ \ _dp_req_with_reply(dp_cli, domain, req_name, req_key, sbus_req, \ target, method, dp_flags, req_data, \ (dp_req_post_fn)__pp_fn, __pp_data, \ (dp_req_reply_fn)__reply_fn, #output_dtype); \ } while(0) #define dp_req_with_reply(dp_cli, domain, req_name, req_key, sbus_req, target,\ method, dp_flags, req_data, reply_fn, \ output_dtype) \ dp_req_with_reply_pp(dp_cli, domain, req_name, req_key, sbus_req, target, \ method, dp_flags, req_data, NULL, NULL, void, \ reply_fn, output_dtype) /* Client shared functions. */ errno_t dp_client_init(struct sbus_connection *conn, void *data); struct data_provider *dp_client_provider(struct dp_client *dp_cli); struct be_ctx *dp_client_be(struct dp_client *dp_cli); struct sbus_connection *dp_client_conn(struct dp_client *dp_cli); #endif /* _DP_PRIVATE_H_ */