From 9b8e4c72933306216507ea869081632fa83a902d Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 12 Feb 2009 15:57:52 -0500 Subject: Make backend requests async --- server/providers/data_provider.c | 6 - server/providers/data_provider_be.c | 237 +++++++++++++++++++-- server/providers/dp_backend.h | 31 ++- server/providers/proxy.c | 397 +++++++++++++++++++++++++++++++----- 4 files changed, 599 insertions(+), 72 deletions(-) (limited to 'server') diff --git a/server/providers/data_provider.c b/server/providers/data_provider.c index e361dfc87..aa66c8e51 100644 --- a/server/providers/data_provider.c +++ b/server/providers/data_provider.c @@ -194,7 +194,6 @@ static int dp_monitor_init(struct dp_ctx *dpctx) } static void be_identity_check(DBusPendingCall *pending, void *data); -static void be_online_check(DBusPendingCall *pending, void *data); static void be_got_account_info(DBusPendingCall *pending, void *data); static int dbus_dp_init(struct sbus_conn_ctx *conn_ctx, void *data) @@ -385,11 +384,6 @@ done: dbus_message_unref(reply); } -static void be_online_check(DBusPendingCall *pending, void *data) -{ - return; -} - static void be_got_account_info(DBusPendingCall *pending, void *data) { struct dp_be_request *bereq; diff --git a/server/providers/data_provider_be.c b/server/providers/data_provider_be.c index ad551c23e..7b491ce78 100644 --- a/server/providers/data_provider_be.c +++ b/server/providers/data_provider_be.c @@ -147,15 +147,110 @@ static int be_identity(DBusMessage *message, void *data, DBusMessage **r) return EOK; } +struct be_async_req { + be_req_fn_t fn; + struct be_req *req; +}; + +static void be_async_req_handler(struct event_context *ev, + struct timed_event *te, + struct timeval tv, void *pvt) +{ + struct be_async_req *async_req; + + async_req = talloc_get_type(pvt, struct be_async_req); + + async_req->fn(async_req->req); +} + +static int be_file_request(struct be_ctx *ctx, + be_req_fn_t fn, + struct be_req *req) +{ + struct be_async_req *areq; + struct timed_event *te; + struct timeval tv; + + areq = talloc(req, struct be_async_req); + if (!areq) { + return ENOMEM; + } + areq->fn = fn; + areq->req = req; + + /* fire immediately */ + tv.tv_sec = 0; + tv.tv_usec = 0; + + te = event_add_timed(ctx->ev, req, tv, be_async_req_handler, areq); + if (te == NULL) { + return EIO; + } + + return EOK; +} + +static void online_chk_callback(struct be_req *req, int status, + const char *errstr) +{ + struct be_online_req *oreq; + DBusMessage *reply; + DBusConnection *conn; + dbus_bool_t dbret; + dbus_uint16_t online; + dbus_uint16_t err_maj = 0; + dbus_uint32_t err_min = 0; + const char *err_msg = "Success"; + + oreq = talloc_get_type(req->req_data, struct be_online_req); + + if (status != EOK) { + online = MOD_OFFLINE; + err_maj = DP_ERR_FATAL; + err_min = status; + err_msg = errstr; + } + + online = oreq->online; + reply = (DBusMessage *)req->pvt; + + dbret = dbus_message_append_args(reply, + DBUS_TYPE_UINT16, &online, + DBUS_TYPE_UINT16, &err_maj, + DBUS_TYPE_UINT32, &err_min, + DBUS_TYPE_STRING, &err_msg, + DBUS_TYPE_INVALID); + if (!dbret) { + DEBUG(1, ("Failed to generate dbus reply\n")); + return; + } + + conn = sbus_get_connection(req->be_ctx->dp_ctx->scon_ctx); + dbus_connection_send(conn, reply, NULL); + dbus_message_unref(reply); + + DEBUG(4, ("Request processed. Returned %d,%d,%s\n", + err_maj, err_min, err_msg)); + + /* finally free the request */ + talloc_free(req); +} + + static int be_check_online(DBusMessage *message, void *data, DBusMessage **r) { struct sbus_message_handler_ctx *smh_ctx; + struct be_online_req *req; + struct be_req *be_req; struct be_ctx *ctx; DBusMessage *reply; dbus_bool_t dbret; void *user_data; - int online = 0; int ret; + dbus_uint16_t online; + dbus_uint16_t err_maj; + dbus_uint32_t err_min; + const char *err_msg; if (!data) return EINVAL; smh_ctx = talloc_get_type(data, struct sbus_message_handler_ctx); @@ -165,12 +260,54 @@ static int be_check_online(DBusMessage *message, void *data, DBusMessage **r) ctx = talloc_get_type(user_data, struct be_ctx); if (!ctx) return EINVAL; - ret = ctx->ops->check_online(ctx, &online); - if (ret != EOK) return ret; - reply = dbus_message_new_method_return(message); + + /* process request */ + be_req = talloc(ctx, struct be_req); + if (!be_req) { + online = MOD_OFFLINE; + err_maj = DP_ERR_FATAL; + err_min = ENOMEM; + err_msg = "Out of memory"; + goto done; + } + be_req->be_ctx = ctx; + be_req->fn = online_chk_callback; + be_req->pvt = reply; + + req = talloc(be_req, struct be_online_req); + if (!req) { + online = MOD_OFFLINE; + err_maj = DP_ERR_FATAL; + err_min = ENOMEM; + err_msg = "Out of memory"; + goto done; + } + req->online = 0; + + be_req->req_data = req; + + ret = be_file_request(ctx, ctx->ops->check_online, be_req); + if (ret != EOK) { + online = MOD_OFFLINE; + err_maj = DP_ERR_FATAL; + err_min = ret; + err_msg = "Failed to file request"; + goto done; + } + + return EOK; + +done: + if (be_req) { + talloc_free(be_req); + } + dbret = dbus_message_append_args(reply, DBUS_TYPE_UINT16, &online, + DBUS_TYPE_UINT16, &err_maj, + DBUS_TYPE_UINT32, &err_min, + DBUS_TYPE_STRING, &err_msg, DBUS_TYPE_INVALID); if (!dbret) return EIO; @@ -178,9 +315,51 @@ static int be_check_online(DBusMessage *message, void *data, DBusMessage **r) return EOK; } + +static void acctinfo_callback(struct be_req *req, int status, + const char *errstr) +{ + DBusMessage *reply; + DBusConnection *conn; + dbus_bool_t dbret; + dbus_uint16_t err_maj = 0; + dbus_uint32_t err_min = 0; + const char *err_msg = "Success"; + + if (status != EOK) { + err_maj = DP_ERR_FATAL; + err_min = status; + err_msg = errstr; + } + + reply = (DBusMessage *)req->pvt; + + dbret = dbus_message_append_args(reply, + DBUS_TYPE_UINT16, &err_maj, + DBUS_TYPE_UINT32, &err_min, + DBUS_TYPE_STRING, &err_msg, + DBUS_TYPE_INVALID); + if (!dbret) { + DEBUG(1, ("Failed to generate dbus reply\n")); + return; + } + + conn = sbus_get_connection(req->be_ctx->dp_ctx->scon_ctx); + dbus_connection_send(conn, reply, NULL); + dbus_message_unref(reply); + + DEBUG(4, ("Request processed. Returned %d,%d,%s\n", + err_maj, err_min, err_msg)); + + /* finally free the request */ + talloc_free(req); +} + static int be_get_account_info(DBusMessage *message, void *data, DBusMessage **r) { struct sbus_message_handler_ctx *smh_ctx; + struct be_acct_req *req; + struct be_req *be_req; struct be_ctx *ctx; DBusMessage *reply; DBusError dbus_error; @@ -191,10 +370,11 @@ static int be_get_account_info(DBusMessage *message, void *data, DBusMessage **r int attr_type, filter_type; char *filter_val; int ret; - dbus_uint16_t err_maj = 0; - dbus_uint32_t err_min = 0; - const char *err_msg = "Success"; + dbus_uint16_t err_maj; + dbus_uint32_t err_min; + const char *err_msg; + be_req = NULL; *r = NULL; if (!data) return EINVAL; @@ -259,16 +439,46 @@ static int be_get_account_info(DBusMessage *message, void *data, DBusMessage **r } /* process request */ - ret = ctx->ops->get_account_info(ctx, type, attr_type, - filter_type, filter_val); + be_req = talloc(ctx, struct be_req); + if (!be_req) { + err_maj = DP_ERR_FATAL; + err_min = ENOMEM; + err_msg = "Out of memory"; + goto done; + } + be_req->be_ctx = ctx; + be_req->fn = acctinfo_callback; + be_req->pvt = reply; + + req = talloc(be_req, struct be_acct_req); + if (!req) { + err_maj = DP_ERR_FATAL; + err_min = ENOMEM; + err_msg = "Out of memory"; + goto done; + } + req->entry_type = type; + req->attr_type = attr_type; + req->filter_type = filter_type; + req->filter_value = talloc_strdup(req, filter_val); + + be_req->req_data = req; + + ret = be_file_request(ctx, ctx->ops->get_account_info, be_req); if (ret != EOK) { err_maj = DP_ERR_FATAL; err_min = ret; - err_msg = "Backend error"; + err_msg = "Failed to file request"; goto done; } + return EOK; + done: + if (be_req) { + talloc_free(be_req); + } + dbret = dbus_message_append_args(reply, DBUS_TYPE_UINT16, &err_maj, DBUS_TYPE_UINT32, &err_min, @@ -283,13 +493,14 @@ done: return EOK; } + + /* mon_cli_init * sbus channel to the monitor daemon */ static int mon_cli_init(struct be_ctx *ctx) { int ret; char *sbus_address; - struct service_sbus_ctx *ss_ctx; struct sbus_method_ctx *sm_ctx; /* Set up SBUS connection to the monitor */ @@ -309,14 +520,12 @@ static int mon_cli_init(struct be_ctx *ctx) sbus_address, sm_ctx, ctx /* Private Data */, NULL /* Destructor */, - &ss_ctx); + &ctx->ss_ctx); if (ret != EOK) { DEBUG(0, ("Failed to connect to monitor services.\n")); return ret; } - ctx->ss_ctx = ss_ctx; - return EOK; } diff --git a/server/providers/dp_backend.h b/server/providers/dp_backend.h index 219df957c..765c16ee7 100644 --- a/server/providers/dp_backend.h +++ b/server/providers/dp_backend.h @@ -41,11 +41,34 @@ struct be_ctx { void *pvt_data; }; +struct be_req; + +typedef void (*be_async_callback_t)(struct be_req *, int, const char *); + +struct be_req { + struct be_ctx *be_ctx; + void *req_data; + + be_async_callback_t fn; + void *pvt; +}; + +struct be_acct_req { + int entry_type; + int attr_type; + int filter_type; + char *filter_value; +}; + +struct be_online_req { + int online; +}; + +typedef void (*be_req_fn_t)(struct be_req *); + struct be_mod_ops { - int (*check_online)(struct be_ctx *, int *reply); - int (*get_account_info)(struct be_ctx *, - int entry_type, int attr_type, - int filter_type, char *filter_value); + be_req_fn_t check_online; + be_req_fn_t get_account_info; }; #endif /* __DP_BACKEND_H___ */ diff --git a/server/providers/proxy.c b/server/providers/proxy.c index a9469219f..62638c1ff 100644 --- a/server/providers/proxy.c +++ b/server/providers/proxy.c @@ -55,67 +55,82 @@ struct proxy_ctx { struct proxy_nss_ops ops; }; -static int get_pw_name(struct be_ctx *be_ctx, struct proxy_ctx *proxy_ctx, char *name) +static void proxy_reply(struct be_req *req, int error, const char *errstr) { - struct proxy_nss_ops *ops = &proxy_ctx->ops; + return req->fn(req, error, errstr); +} + +static void get_pw_name(struct be_req *req, char *name) +{ + struct proxy_ctx *ctx; enum nss_status status; struct passwd result; char *buffer; int ret; + ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx); + buffer = talloc_size(NULL, 4096); - if (!buffer) return ENOMEM; + if (!buffer) + return proxy_reply(req, ENOMEM, "Out of memory"); - status = ops->getpwnam_r(name, &result, buffer, 4096, &ret); + status = ctx->ops.getpwnam_r(name, &result, buffer, 4096, &ret); switch (status) { case NSS_STATUS_NOTFOUND: - ret = sysdb_posix_remove_user(be_ctx, be_ctx->sysdb, - be_ctx->domain, name); + ret = sysdb_posix_remove_user(req, req->be_ctx->sysdb, + req->be_ctx->domain, name); break; case NSS_STATUS_SUCCESS: - ret = sysdb_posix_store_user(be_ctx, be_ctx->sysdb, be_ctx->domain, + ret = sysdb_posix_store_user(req, req->be_ctx->sysdb, + req->be_ctx->domain, result.pw_name, result.pw_passwd, result.pw_uid, result.pw_gid, - result.pw_gecos, result.pw_dir, - result.pw_shell); + result.pw_gecos, result.pw_dir, + result.pw_shell); break; default: DEBUG(2, ("proxy -> getpwnam_r failed for '%s' (%d)[%s]\n", name, ret, strerror(ret))); talloc_free(buffer); - return ret; + return proxy_reply(req, ret, "Operation failed"); } if (ret != EOK) { DEBUG(1, ("Failed to update LDB Cache for '%s' (%d) !?\n", name, ret)); + talloc_free(buffer); + return proxy_reply(req, ret, "Operation failed"); } talloc_free(buffer); - return ret; + return proxy_reply(req, EOK, NULL); } -static int get_pw_uid(struct be_ctx *be_ctx, struct proxy_ctx *proxy_ctx, uid_t uid) +static void get_pw_uid(struct be_req *req, uid_t uid) { - struct proxy_nss_ops *ops = &proxy_ctx->ops; + struct proxy_ctx *ctx; enum nss_status status; struct passwd result; char *buffer; int ret; + ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx); + buffer = talloc_size(NULL, 4096); - if (!buffer) return ENOMEM; + if (!buffer) + return proxy_reply(req, ENOMEM, "Out of memory"); - status = ops->getpwuid_r(uid, &result, buffer, 4096, &ret); + status = ctx->ops.getpwuid_r(uid, &result, buffer, 4096, &ret); switch (status) { case NSS_STATUS_NOTFOUND: - ret = sysdb_posix_remove_user_by_uid(be_ctx, be_ctx->sysdb, - be_ctx->domain,uid); + ret = sysdb_posix_remove_user_by_uid(req, req->be_ctx->sysdb, + req->be_ctx->domain,uid); break; case NSS_STATUS_SUCCESS: - ret = sysdb_posix_store_user(be_ctx, be_ctx->sysdb, be_ctx->domain, + ret = sysdb_posix_store_user(req, req->be_ctx->sysdb, + req->be_ctx->domain, result.pw_name, result.pw_passwd, result.pw_uid, result.pw_gid, result.pw_gecos, result.pw_dir, @@ -125,82 +140,368 @@ static int get_pw_uid(struct be_ctx *be_ctx, struct proxy_ctx *proxy_ctx, uid_t DEBUG(2, ("proxy -> getpwuid_r failed for '%lu' (%d)[%s]\n", (unsigned long)uid, ret, strerror(ret))); talloc_free(buffer); - return ret; + return proxy_reply(req, ret, "Operation failed"); } if (ret != EOK) { DEBUG(1, ("Failed to update LDB Cache for '%lu' (%d) !?\n", (unsigned long)uid, ret)); + talloc_free(buffer); + return proxy_reply(req, ret, "Operation failed"); } talloc_free(buffer); - return ret; + return proxy_reply(req, EOK, NULL); } -static int proxy_check_online(struct be_ctx *be_ctx, int *reply) +#define MAX_BUF_SIZE 1024*1024 /* max 1MiB */ + +static void enum_users(struct be_req *req) { - *reply = MOD_ONLINE; - return EOK; + struct proxy_ctx *ctx; + enum nss_status status; + struct passwd result; + char *buffer, *newb; + size_t buflen; + const char *errstr; + int ret; + + ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx); + + buflen = 4096; + buffer = talloc_size(NULL, buflen); + if (!buffer) + return proxy_reply(req, ENOMEM, "Out of memory"); + + status = ctx->ops.setpwent(); + if (status != NSS_STATUS_SUCCESS) + return proxy_reply(req, EIO, "Operation failed"); + + while (status == NSS_STATUS_SUCCESS) { + + status = ctx->ops.getpwent_r(&result, buffer, buflen, &ret); + + switch (status) { + case NSS_STATUS_TRYAGAIN: + /* buffer too small ? */ + if (buflen < MAX_BUF_SIZE) { + buflen *= 2; + } + if (buflen > MAX_BUF_SIZE) { + buflen = MAX_BUF_SIZE; + } + newb = talloc_realloc_size(NULL, buffer, buflen); + if (!newb) { + errstr = "Out of memory"; + ret = ENOMEM; + goto done; + } + buffer = newb; + status = NSS_STATUS_SUCCESS; + break; + + case NSS_STATUS_NOTFOUND: + /* we got last one */ + break; + + case NSS_STATUS_SUCCESS: + ret = sysdb_posix_store_user(req, req->be_ctx->sysdb, + req->be_ctx->domain, + result.pw_name, result.pw_passwd, + result.pw_uid, result.pw_gid, + result.pw_gecos, result.pw_dir, + result.pw_shell); + if (ret != EOK) { + DEBUG(1, ("Failed to update LDB Cache for '%s' (%d)[%s] !?\n", + (unsigned long)result.pw_name, ret, strerror(ret))); + } + break; + + default: + DEBUG(2, ("proxy -> getpwent_r failed (%d)[%s]\n", + ret, strerror(ret))); + errstr = "Operation failed"; + goto done; + } + } + + errstr = NULL; + ret = EOK; + +done: + talloc_free(buffer); + ctx->ops.endpwent(); + return proxy_reply(req, ret, errstr); +} + +static void get_gr_name(struct be_req *req, char *name) +{ + struct proxy_ctx *ctx; + enum nss_status status; + struct group result; + char *buffer; + int ret; + + ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx); + + buffer = talloc_size(NULL, 4096); + if (!buffer) + return proxy_reply(req, ENOMEM, "Out of memory"); + + status = ctx->ops.getgrnam_r(name, &result, buffer, 4096, &ret); + + switch (status) { + case NSS_STATUS_NOTFOUND: + ret = sysdb_posix_remove_group(req, req->be_ctx->sysdb, + req->be_ctx->domain, name); + break; + case NSS_STATUS_SUCCESS: + /* FIXME: check members are all available or fetch them */ + ret = sysdb_posix_store_group(req, req->be_ctx->sysdb, + req->be_ctx->domain, result.gr_name, + result.gr_gid, result.gr_mem); + break; + default: + DEBUG(2, ("proxy -> getpwnam_r failed for '%s' (%d)[%s]\n", + name, ret, strerror(ret))); + talloc_free(buffer); + return proxy_reply(req, ret, "Operation failed"); + } + + if (ret != EOK) { + DEBUG(1, ("Failed to update LDB Cache for '%s' (%d) !?\n", + name, ret)); + talloc_free(buffer); + return proxy_reply(req, ret, "Operation failed"); + } + + talloc_free(buffer); + return proxy_reply(req, EOK, NULL); +} + +static void get_gr_gid(struct be_req *req, gid_t gid) +{ + struct proxy_ctx *ctx; + enum nss_status status; + struct group result; + char *buffer; + int ret; + + ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx); + + buffer = talloc_size(NULL, 4096); + if (!buffer) + return proxy_reply(req, ENOMEM, "Out of memory"); + + status = ctx->ops.getgrgid_r(gid, &result, buffer, 4096, &ret); + + switch (status) { + case NSS_STATUS_NOTFOUND: + ret = sysdb_posix_remove_group_by_gid(req, req->be_ctx->sysdb, + req->be_ctx->domain, gid); + break; + case NSS_STATUS_SUCCESS: + ret = sysdb_posix_store_group(req, req->be_ctx->sysdb, + req->be_ctx->domain, result.gr_name, + result.gr_gid, result.gr_mem); + break; + default: + DEBUG(2, ("proxy -> getgrgid_r failed for '%lu' (%d)[%s]\n", + (unsigned long)gid, ret, strerror(ret))); + talloc_free(buffer); + return proxy_reply(req, ret, "Operation failed"); + } + + if (ret != EOK) { + DEBUG(1, ("Failed to update LDB Cache for '%lu' (%d) !?\n", + (unsigned long)gid, ret)); + talloc_free(buffer); + return proxy_reply(req, ret, "Operation failed"); + } + + talloc_free(buffer); + return proxy_reply(req, EOK, NULL); } -static int proxy_get_account_info(struct be_ctx *be_ctx, - int entry_type, int attr_type, - int filter_type, char *filter_value) +static void enum_groups(struct be_req *req) { struct proxy_ctx *ctx; + enum nss_status status; + struct group result; + char *buffer, *newb; + size_t buflen; + const char * errstr; + int ret; + + ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx); + + buflen = 4096; + buffer = talloc_size(NULL, buflen); + if (!buffer) + return proxy_reply(req, ENOMEM, "Out of memory"); + + status = ctx->ops.setgrent(); + if (status != NSS_STATUS_SUCCESS) + return proxy_reply(req, EIO, "Operation failed"); + + while (status == NSS_STATUS_SUCCESS) { + + status = ctx->ops.getgrent_r(&result, buffer, buflen, &ret); + + switch (status) { + case NSS_STATUS_TRYAGAIN: + /* buffer too small ? */ + if (buflen < MAX_BUF_SIZE) { + buflen *= 2; + } + if (buflen > MAX_BUF_SIZE) { + buflen = MAX_BUF_SIZE; + } + newb = talloc_realloc_size(NULL, buffer, buflen); + if (!newb) { + errstr = "Out of memory"; + ret = ENOMEM; + goto done; + } + buffer = newb; + status = NSS_STATUS_SUCCESS; + break; + + case NSS_STATUS_NOTFOUND: + /* we got last one */ + break; + + case NSS_STATUS_SUCCESS: + ret = sysdb_posix_store_group(req, req->be_ctx->sysdb, + req->be_ctx->domain, result.gr_name, + result.gr_gid, result.gr_mem); + if (ret != EOK) { + DEBUG(1, ("Failed to update LDB Cache for '%s' (%d)[%s] !?\n", + (unsigned long)result.gr_name, ret, strerror(ret))); + } + break; + + default: + DEBUG(2, ("proxy -> getgrent_r failed (%d)[%s]\n", + ret, strerror(ret))); + errstr = "Operation failed"; + goto done; + } + } + + errstr = NULL; + ret = EOK; + +done: + talloc_free(buffer); + ctx->ops.endgrent(); + return proxy_reply(req, ret, errstr); +} + +/* TODO: actually do check something */ +static void proxy_check_online(struct be_req *req) +{ + struct be_online_req *oreq; + + oreq = talloc_get_type(req->req_data, struct be_online_req); + + oreq->online = MOD_ONLINE; + + req->fn(req, EOK, NULL); +} + +/* TODO: See if we can use async_req code */ +static void proxy_get_account_info(struct be_req *req) +{ + struct be_acct_req *ar; uid_t uid; + gid_t gid; - ctx = talloc_get_type(be_ctx->pvt_data, struct proxy_ctx); + ar = talloc_get_type(req->req_data, struct be_acct_req); - switch (entry_type) { + switch (ar->entry_type) { case BE_REQ_USER: /* user */ - switch (filter_type) { + switch (ar->filter_type) { case BE_FILTER_NAME: - switch (attr_type) { + switch (ar->attr_type) { case BE_ATTR_CORE: - if (strchr(filter_value, '*')) { - /* TODO */ + if (strchr(ar->filter_value, '*')) { + return enum_users(req); } else { - return get_pw_name(be_ctx, ctx, filter_value); + return get_pw_name(req, ar->filter_value); } break; default: - return EINVAL; + return proxy_reply(req, EINVAL, "Invalid attr type"); } break; case BE_FILTER_IDNUM: - switch (attr_type) { + switch (ar->attr_type) { case BE_ATTR_CORE: - if (strchr(filter_value, '*')) { - return EINVAL; + if (strchr(ar->filter_value, '*')) { + return proxy_reply(req, EINVAL, "Invalid attr type"); } else { char *endptr; errno = 0; - uid = (uid_t)strtol(filter_value, &endptr, 0); - if (errno || *endptr || (filter_value == endptr)) { - return EINVAL; + uid = (uid_t)strtol(ar->filter_value, &endptr, 0); + if (errno || *endptr || (ar->filter_value == endptr)) { + return proxy_reply(req, EINVAL, "Invalid attr type"); } - return get_pw_uid(be_ctx, ctx, uid); + return get_pw_uid(req, uid); } break; default: - return EINVAL; + return proxy_reply(req, EINVAL, "Invalid attr type"); } break; default: - return EINVAL; + return proxy_reply(req, EINVAL, "Invalid filter type"); } break; case BE_REQ_GROUP: /* group */ - /* TODO */ - return EOK; + switch (ar->filter_type) { + case BE_FILTER_NAME: + switch (ar->attr_type) { + case BE_ATTR_CORE: + if (strchr(ar->filter_value, '*')) { + return enum_groups(req); + } else { + return get_gr_name(req, ar->filter_value); + } + break; + default: + return proxy_reply(req, EINVAL, "Invalid attr type"); + } + break; + case BE_FILTER_IDNUM: + switch (ar->attr_type) { + case BE_ATTR_CORE: + if (strchr(ar->filter_value, '*')) { + return proxy_reply(req, EINVAL, "Invalid attr type"); + } else { + char *endptr; + errno = 0; + gid = (gid_t)strtol(ar->filter_value, &endptr, 0); + if (errno || *endptr || (ar->filter_value == endptr)) { + return proxy_reply(req, EINVAL, "Invalid attr type"); + } + return get_gr_gid(req, gid); + } + break; + default: + return proxy_reply(req, EINVAL, "Invalid attr type"); + } + break; + default: + return proxy_reply(req, EINVAL, "Invalid filter type"); + } + break; + default: /*fail*/ - return EINVAL; + return proxy_reply(req, EINVAL, "Invalid request type"); } - - return EOK; } struct be_mod_ops proxy_mod_ops = { -- cgit