/* * Copyright 2008 Red Hat, Inc. * * 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; version 2 of the License. * * 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. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include #include #include #include #include #include #include #include #ifdef HAVE_DIRSRV_SLAPI_PLUGIN_H #include #include #include #else #include #endif #include #include #include #include "dispatch.h" #include "map.h" #include "nis.h" #include "plugin.h" /* Indicate whether or not we serve the specified domain. */ static void nis_domain(struct plugin_state *state, dispatch_reply_fragment *reply_fragment_fn, dispatch_reply *reply_fn, struct dispatch_client_data *cdata, XDR *request_xdrs, bool_t reply_on_failure, struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, bool_t *reply_bool) { char *domain = NULL; *reply_bool = FALSE; if (xdr_string(request_xdrs, &domain, YPMAXDOMAIN)) { map_supports_domain(state, domain, reply_bool); if (*reply_bool || reply_on_failure) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "domain(%s) -> %s\n", domain, *reply_bool ? "TRUE" : "FALSE"); (*reply_fn)(state, cdata, reply, reply_xdrs, reply_buf); } else { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "domain(%s) -> %d (no reply)\n", domain, *reply_bool ? "TRUE" : "FALSE"); } } else { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "argument parsing error\n"); /* XXX */ } } static void nis_match(struct plugin_state *state, dispatch_reply_fragment *reply_fragment_fn, dispatch_reply *reply_fn, struct dispatch_client_data *cdata, XDR *request_xdrs, struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, struct ypresp_val *reply_val) { struct ypreq_key req_key; bool_t map_supported; memset(&req_key, 0, sizeof(req_key)); memset(reply_val, 0, sizeof(*reply_val)); if (xdr_ypreq_key(request_xdrs, &req_key)) { if (map_match(state, req_key.domain, req_key.map, req_key.keydat.keydat_len, req_key.keydat.keydat_val, &reply_val->valdat.valdat_len, &reply_val->valdat.valdat_val)) { reply_val->status = YP_TRUE; slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "match(%s/%s/%.*s) -> %d\n", req_key.domain, req_key.map, (int) req_key.keydat.keydat_len, req_key.keydat.keydat_val, reply_val->status); } else { map_supported = FALSE; map_supports_map(state, req_key.domain, req_key.map, &map_supported); reply_val->status = map_supported ? YP_NOKEY : YP_NOMAP; } (*reply_fn)(state, cdata, reply, reply_xdrs, reply_buf); } else { /* XXX */ } } static void nis_first(struct plugin_state *state, dispatch_reply_fragment *reply_fragment_fn, dispatch_reply *reply_fn, struct dispatch_client_data *cdata, XDR *request_xdrs, struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, struct ypresp_key_val *reply_key_val) { struct ypreq_nokey req_nokey; bool_t map_supported; memset(&req_nokey, 0, sizeof(req_nokey)); memset(reply_key_val, 0, sizeof(*reply_key_val)); if (xdr_ypreq_nokey(request_xdrs, &req_nokey)) { if (map_first(state, req_nokey.domain, req_nokey.map, &reply_key_val->keydat.keydat_len, &reply_key_val->keydat.keydat_val, &reply_key_val->valdat.valdat_len, &reply_key_val->valdat.valdat_val)) { reply_key_val->status = YP_TRUE; slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "first(%s/%s) -> %d\n", req_nokey.domain, req_nokey.map, reply_key_val->status); } else { map_supported = FALSE; map_supports_map(state, req_nokey.domain, req_nokey.map, &map_supported); reply_key_val->status = map_supported ? YP_NOKEY : YP_NOMAP; } (*reply_fn)(state, cdata, reply, reply_xdrs, reply_buf); } else { /* XXX */ } } static void nis_next(struct plugin_state *state, dispatch_reply_fragment *reply_fragment_fn, dispatch_reply *reply_fn, struct dispatch_client_data *cdata, XDR *request_xdrs, struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, struct ypresp_key_val *reply_key_val) { struct ypreq_key req_key; memset(&req_key, 0, sizeof(req_key)); memset(reply_key_val, 0, sizeof(*reply_key_val)); if (xdr_ypreq_key(request_xdrs, &req_key)) { if (map_next(state, req_key.domain, req_key.map, req_key.keydat.keydat_len, req_key.keydat.keydat_val, &reply_key_val->keydat.keydat_len, &reply_key_val->keydat.keydat_val, &reply_key_val->valdat.valdat_len, &reply_key_val->valdat.valdat_val)) { reply_key_val->status = YP_TRUE; slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "next(%.*s/%s/%s) -> %d\n", req_key.keydat.keydat_len, req_key.keydat.keydat_val, req_key.domain, req_key.map, reply_key_val->status); } else { if (map_match(state, req_key.domain, req_key.map, req_key.keydat.keydat_len, req_key.keydat.keydat_val, &reply_key_val->valdat.valdat_len, &reply_key_val->valdat.valdat_val)) { /* Have data for this key, but not the next. */ reply_key_val->status = YP_NOMORE; } else { /* No data for this key. */ reply_key_val->status = YP_NOKEY; } slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "next(%.*s/%s/%s) -> no more!\n", req_key.keydat.keydat_len, req_key.keydat.keydat_val, req_key.domain, req_key.map); } (*reply_fn)(state, cdata, reply, reply_xdrs, reply_buf); } else { /* XXX */ } } static void nis_master(struct plugin_state *state, dispatch_reply_fragment *reply_fragment_fn, dispatch_reply *reply_fn, struct dispatch_client_data *cdata, XDR *request_xdrs, struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, struct ypresp_master *reply_master) { struct ypreq_nokey req_nokey; const char *master; memset(&req_nokey, 0, sizeof(req_nokey)); memset(reply_master, 0, sizeof(*reply_master)); if (xdr_ypreq_nokey(request_xdrs, &req_nokey)) { reply_master->status = YP_TRUE; if (map_master_name(state, &master) != 0) { master = "localhost"; } reply_master->master = (char *) master; slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "master(%s/%s) -> %s\n", req_nokey.domain, req_nokey.map, reply_master->master); (*reply_fn)(state, cdata, reply, reply_xdrs, reply_buf); } else { /* XXX */ } } static void nis_order(struct plugin_state *state, dispatch_reply_fragment *reply_fragment_fn, dispatch_reply *reply_fn, struct dispatch_client_data *cdata, XDR *request_xdrs, struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, struct ypresp_order *reply_order) { struct ypreq_nokey req_nokey; memset(&req_nokey, 0, sizeof(req_nokey)); memset(reply_order, 0, sizeof(*reply_order)); if (xdr_ypreq_nokey(request_xdrs, &req_nokey)) { reply_order->status = YP_TRUE; if (map_order(state, req_nokey.domain, req_nokey.map, &reply_order->ordernum)) { reply_order->status = YP_TRUE; slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "order(%s/%s) -> %d\n", req_nokey.domain, req_nokey.map, reply_order->ordernum); } else { reply_order->status = YP_FALSE; slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "order(%s/%s) -> ?\n", req_nokey.domain, req_nokey.map); } (*reply_fn)(state, cdata, reply, reply_xdrs, reply_buf); } else { /* XXX */ } } static bool_t nis_maplist_cb(const char *domain, const char *mapname, void *backend_data, void *cbdata) { struct ypmaplist **list, *next; list = cbdata; next = malloc(sizeof(*next)); if (next != NULL) { memset(next, 0, sizeof(*next)); next->map = strdup(mapname); if (next->map == NULL) { free(next); return TRUE; } next->next = *list; *list = next; } return TRUE; } static void nis_free_maplist_cb_result(struct ypmaplist **list) { struct ypmaplist *node, *next; node = *list; while (node != NULL) { next = node->next; free(node->map); free(node); node = next; } } static void nis_maplist(struct plugin_state *state, dispatch_reply_fragment *reply_fragment_fn, dispatch_reply *reply_fn, struct dispatch_client_data *cdata, XDR *request_xdrs, struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, struct ypresp_maplist *reply_maplist) { char *domain = NULL; struct ypmaplist *list; memset(reply_maplist, 0, sizeof(*reply_maplist)); if (xdr_string(request_xdrs, &domain, YPMAXDOMAIN)) { list = NULL; map_data_foreach_map(state, domain, nis_maplist_cb, &list); reply_maplist->status = YP_TRUE; reply_maplist->list = list; if (reply_maplist->list == NULL) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "maplist(%s) -> (none)\n", domain); } else { for (list = reply_maplist->list; list != NULL; list = list->next) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "maplist(%s) -> %s\n", domain, list->map); } } (*reply_fn)(state, cdata, reply, reply_xdrs, reply_buf); nis_free_maplist_cb_result(&list); } else { /* XXX */ } } /* Enumeration, if we want to break it down into chunks, happens in a few * phases (given the protocol): * 1. we're sending the first entry in a map * 2. we're sending a not-the-first entry in a map * 3. we're sending an end-of-map */ struct nis_all_cookie { enum nis_all_cookie_state { cookie_bad, cookie_first, cookie_next, cookie_this, cookie_end1, cookie_end2, } state; unsigned int key_length; char key[1]; }; static void nis_all_free_cookie(struct nis_all_cookie *cookie) { free(cookie); } static struct nis_all_cookie * nis_all_make_cookie(enum nis_all_cookie_state state, unsigned int length, const char *value) { struct nis_all_cookie *cookie; cookie = malloc(sizeof(*cookie) + ((length > 0) ? length : 0)); if (cookie != NULL) { cookie->state = state; switch (cookie->state) { case cookie_bad: case cookie_first: case cookie_end1: case cookie_end2: break; case cookie_this: case cookie_next: cookie->key_length = length; if ((length > 0) && (value != NULL)) { memcpy(&cookie->key, value, length); } break; } } return cookie; } static void nis_all(struct plugin_state *state, dispatch_reply_fragment *reply_fragment_fn, dispatch_reply *reply_fn, struct dispatch_client_data *cdata, XDR *request_xdrs, struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, struct ypresp_all *reply_all, void **continuation_cookie) { struct ypreq_nokey req_nokey; keydat_t *reply_key; valdat_t *reply_val; struct nis_all_cookie *cookie; enum nis_all_cookie_state next_state; bool_t supported, stop; memset(&req_nokey, 0, sizeof(req_nokey)); reply_key = &reply_all->ypresp_all_u.val.keydat; reply_val = &reply_all->ypresp_all_u.val.valdat; if (xdr_ypreq_nokey(request_xdrs, &req_nokey)) { /* Take ownership of the cookie data. */ if (continuation_cookie) { if (*continuation_cookie != NULL) { cookie = *continuation_cookie; } else { cookie = nis_all_make_cookie(cookie_bad, 0, NULL); } *continuation_cookie = NULL; } else { cookie = nis_all_make_cookie(cookie_bad, 0, NULL); } /* Check if we even support the map. */ supported = FALSE; if (!map_supports_map(state, req_nokey.domain, req_nokey.map, &supported) || !supported) { /* No entries? No-such-map final status. */ reply_all->more = TRUE; reply_all->ypresp_all_u.val.status = YP_NOMAP; reply_key->keydat_len = 0; reply_val->valdat_len = 0; /* Encode the reply header so that we can queue the * entire reply as one block. */ xdr_replymsg(reply_xdrs, reply); /* End of data. */ reply_all->more = FALSE; xdr_ypresp_all(reply_xdrs, reply_all); /* Queue the entire response. */ if (!(*reply_fragment_fn)(state, cdata, reply, reply_xdrs, reply_buf, FALSE, TRUE)) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "all(%s/%s) - error queueing " "error response\n", req_nokey.domain, req_nokey.map); } /* Don't return a cookie, if one was passed to us. */ nis_all_free_cookie(cookie); cookie = NULL; } else for (stop = FALSE; stop == FALSE;) { bool_t found, skip; xdr_setpos(reply_xdrs, 0); memset(reply_all, 0, sizeof(reply_all)); /* Follow any instructions we left for this iteration. */ switch (cookie->state) { case cookie_bad: /* fall through */ case cookie_first: /* Read the first key in the map, and make the * next state either be queuing the first item * or queueing the end-of-map reply. */ found = map_first(state, req_nokey.domain, req_nokey.map, &reply_key->keydat_len, &reply_key->keydat_val, &reply_val->valdat_len, &reply_val->valdat_val); if (found) { /* Next time grab the entry after this * one. */ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "all(%s/%s) \"%.*s\"\n", req_nokey.domain, req_nokey.map, reply_key->keydat_len, reply_key->keydat_val); skip = FALSE; reply_all->more = TRUE; reply_all->ypresp_all_u.val.status = YP_TRUE; next_state = cookie_next; } else { /* Don't reply, just move to end-of-map * state. */ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "all(%s/%s) no-first\n", req_nokey.domain, req_nokey.map); skip = TRUE; next_state = cookie_end1; } /* Try to queue the packet. */ nis_all_free_cookie(cookie); if (skip || (*reply_fragment_fn)(state, cdata, reply, reply_xdrs, reply_buf, TRUE, FALSE)) { /* Leave a note to choose the next * entry or send end1, whichever is * appropriate. */ cookie = nis_all_make_cookie(next_state, reply_key->keydat_len, reply_key->keydat_val); } else { /* Leave a note to try sending the * first entry again. */ cookie = nis_all_make_cookie(cookie_first, 0, NULL); stop = TRUE; } break; case cookie_next: /* Read the next key in the map, and set up the * cookie to note that we're queuing a not- * first item. */ found = map_next(state, req_nokey.domain, req_nokey.map, cookie->key_length, cookie->key, &reply_key->keydat_len, &reply_key->keydat_val, &reply_val->valdat_len, &reply_val->valdat_val); if (found) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "all(%s/%s) \"%.*s\"\n", req_nokey.domain, req_nokey.map, reply_key->keydat_len, reply_key->keydat_val); /* Next time grab the entry after this * one. */ skip = FALSE; reply_all->more = TRUE; reply_all->ypresp_all_u.val.status = YP_TRUE; next_state = cookie_next; } else { /* Don't reply, just move to end-of-map * state. */ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "all(%s/%s) no-next\n", req_nokey.domain, req_nokey.map); skip = TRUE; next_state = cookie_end1; } /* Try to queue the packet. */ if (skip || (xdr_ypresp_all(reply_xdrs, reply_all) && (*reply_fragment_fn)(state, cdata, reply, reply_xdrs, reply_buf, FALSE, FALSE))) { /* Leave a note to choose the next * entry or send end1, whichever is * appropriate. */ nis_all_free_cookie(cookie); cookie = nis_all_make_cookie(next_state, reply_key->keydat_len, reply_key->keydat_val); } else { /* Leave a note to retry sending this * entry the next time. */ nis_all_free_cookie(cookie); cookie = nis_all_make_cookie(cookie_this, reply_key->keydat_len, reply_key->keydat_val); stop = TRUE; } break; case cookie_this: /* Read the matching key in the map, and set up * the cookie to note that we're queuing a not- * first item. */ reply_key->keydat_len = cookie->key_length; reply_key->keydat_val = cookie->key; found = map_match(state, req_nokey.domain, req_nokey.map, reply_key->keydat_len, reply_key->keydat_val, &reply_val->valdat_len, &reply_val->valdat_val); if (found) { /* Next time grab the entry after this * one. */ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "all(%s/%s) \"%.*s\" " "(retry)\n", req_nokey.domain, req_nokey.map, cookie->key_length, cookie->key); skip = FALSE; reply_all->more = TRUE; reply_all->ypresp_all_u.val.status = YP_TRUE; next_state = cookie_next; } else { /* Don't reply, just move to end-of-map * state. */ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "all(%s/%s) \"%.*s\" " "(disappeared?)\n", req_nokey.domain, req_nokey.map, cookie->key_length, cookie->key); skip = TRUE; next_state = cookie_end1; } /* Try to queue the packet. */ if (skip || (xdr_ypresp_all(reply_xdrs, reply_all) && (*reply_fragment_fn)(state, cdata, reply, reply_xdrs, reply_buf, FALSE, FALSE))) { /* Leave a note to choose the next * entry or send end1, whichever is * appropriate. */ nis_all_free_cookie(cookie); cookie = nis_all_make_cookie(next_state, reply_key->keydat_len, reply_key->keydat_val); } else { /* Leave a note to retry sending this * entry the next time. But that's how * we got here, so do nothing. */ stop = TRUE; } break; case cookie_end1: /* Send the end-of-map message. */ memset(reply_key, 0, sizeof(*reply_key)); memset(reply_val, 0, sizeof(*reply_key)); reply_all->more = TRUE; reply_all->ypresp_all_u.val.status = YP_NOMORE; slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "all(%s/%s) end-of-map\n", req_nokey.domain, req_nokey.map); if (xdr_ypresp_all(reply_xdrs, reply_all) && (*reply_fragment_fn)(state, cdata, reply, reply_xdrs, reply_buf, FALSE, FALSE)) { /* Leave a note to finish the reply. */ nis_all_free_cookie(cookie); cookie = nis_all_make_cookie(cookie_end2, 0, NULL); } else { /* Leave the note alone, so that we'll * have to try again. */ stop = TRUE; } break; case cookie_end2: /* Send the final message. */ reply_all->more = FALSE; slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "all(%s/%s) done\n", req_nokey.domain, req_nokey.map); if (xdr_ypresp_all(reply_xdrs, reply_all) && (*reply_fragment_fn)(state, cdata, reply, reply_xdrs, reply_buf, FALSE, TRUE)) { /* We're done. */ nis_all_free_cookie(cookie); cookie = NULL; } else { /* Leave the note alone, so that we'll * have to try again. */ } stop = TRUE; break; } } /* Return the cookie if we can, else destroy it. */ if (continuation_cookie) { *continuation_cookie = cookie; } else { nis_all_free_cookie(cookie); } } else { /* XXX */ } } /* Process a NIS request in the buffer. If we get a client address, then we * assume that the client is a datagram client, otherwise we assume it's a * stream client. */ void nis_process_request(struct plugin_state *state, char *request_buf, size_t request_buflen, dispatch_reply_fragment *reply_fragment_fn, dispatch_reply *reply_fn, struct dispatch_client_data *cdata, void **continuation_cookie) { XDR request_xdrs, reply_xdrs, auth_xdrs; AUTH *request_auth, *reply_auth; char reply_buf[64000], auth_buf[MAX_AUTH_BYTES]; struct rpc_msg request, reply; int superuser, auth_flavor, auth_len; struct ypresp_val reply_val; struct ypresp_key_val reply_key_val; struct ypresp_all reply_all; struct ypresp_master reply_master; struct ypresp_order reply_order; struct ypresp_maplist reply_maplist; struct accepted_reply *accepted; bool_t reply_bool; memset(&request_xdrs, 0, sizeof(request_xdrs)); memset(&reply_xdrs, 0, sizeof(reply_xdrs)); memset(&request, 0, sizeof(request)); memset(&reply, 0, sizeof(reply)); /* Parse the client request and make sure it looks like an RPC. */ xdrmem_create(&request_xdrs, request_buf, request_buflen, XDR_DECODE); if (!xdr_callmsg(&request_xdrs, &request)) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "error parsing client RPC request!\n"); return; } if (request.rm_direction != CALL) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "client didn't send us an actual request\n"); goto done; } /* Now we know we've got a request to respond to. */ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "client request prog=%d,ver=%d,proc=%d\n", request.rm_call.cb_prog, request.rm_call.cb_vers, request.rm_call.cb_proc); xdrmem_create(&reply_xdrs, reply_buf, sizeof(reply_buf), XDR_ENCODE); /* Validate the client's credentials. */ auth_flavor = request.rm_call.cb_cred.oa_flavor; switch (auth_flavor) { case AUTH_SYS: request_auth = authunix_create_default(); break; case AUTH_NONE: default: request_auth = authnone_create(); break; } if (auth_validate(request_auth, &request.rm_call.cb_cred)) { switch (auth_flavor) { case AUTH_SYS: slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "validated auth_sys creds\n"); superuser = 0; break; case AUTH_NONE: slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "validated \"none\" creds\n"); superuser = 0; break; default: slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "validated other creds\n"); superuser = 0; break; } } else { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "failed to validate client creds\n"); superuser = 0; } auth_destroy(request_auth); /* Build the authenticator for our response. */ xdrmem_create(&auth_xdrs, auth_buf, sizeof(auth_buf), XDR_ENCODE); switch (auth_flavor) { case AUTH_SYS: reply_auth = authunix_create_default(); break; case AUTH_NONE: default: reply_auth = authnone_create(); break; } auth_marshall(reply_auth, &auth_xdrs); auth_destroy(reply_auth); auth_len = xdr_getpos(&auth_xdrs); xdr_destroy(&auth_xdrs); slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "built reply authenticator\n"); /* Fill out the common RPC reply fields. */ reply.rm_xid = request.rm_xid; reply.rm_direction = REPLY; /* If the request isn't meant for us, return an error. */ if ((request.rm_direction != CALL) || (request.rm_call.cb_rpcvers != 2) || (request.rm_call.cb_prog != YPPROG) || (request.rm_call.cb_vers != YPVERS)) { reply.rm_reply.rp_stat = MSG_DENIED; reply.rm_reply.rp_rjct.rj_stat = RPC_MISMATCH; xdr_replymsg(&reply_xdrs, &reply); slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "program request mismatch\n"); goto send_reply; } /* Fill in the default reply - success, no data returned. */ reply.rm_reply.rp_stat = MSG_ACCEPTED; accepted = &reply.rm_reply.rp_acpt; accepted->ar_stat = SUCCESS; accepted->ar_results.where = (caddr_t) NULL; accepted->ar_results.proc = (xdrproc_t) xdr_void; /* Now figure out what we were asked to do. */ switch (request.rm_call.cb_proc) { default: /* If we don't know the specific request, we'll return a * mismatch error. */ reply.rm_reply.rp_stat = MSG_DENIED; reply.rm_reply.rp_rjct.rj_stat = RPC_MISMATCH; break; case YPPROC_NULL: slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "yp_null()\n"); /* Do nothing. The default successful reply is fine. */ break; case YPPROC_DOMAIN: case YPPROC_DOMAIN_NONACK: slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, request.rm_call.cb_proc == YPPROC_DOMAIN ? "yp_domain()\n" : "yp_domainnonack()\n"); /* Change the reply data to be a boolean. */ memset(&reply_bool, 0, sizeof(reply_bool)); accepted->ar_results.where = (caddr_t) &reply_bool; accepted->ar_results.proc = (xdrproc_t) xdr_bool; /* Call the real function. */ nis_domain(state, reply_fragment_fn, reply_fn, cdata, &request_xdrs, request.rm_call.cb_proc == YPPROC_DOMAIN, &reply, &reply_xdrs, reply_buf, &reply_bool); goto sent_reply; break; case YPPROC_MATCH: slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "yp_match()\n"); /* Change the reply data to be a resp_val. */ memset(&reply_val, 0, sizeof(reply_val)); accepted->ar_results.where = (caddr_t) &reply_val; accepted->ar_results.proc = (xdrproc_t) xdr_ypresp_val; /* Call the real function. */ nis_match(state, reply_fragment_fn, reply_fn, cdata, &request_xdrs, &reply, &reply_xdrs, reply_buf, &reply_val); goto sent_reply; break; case YPPROC_FIRST: slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "yp_first()\n"); /* Change the reply data to be a resp_key_val. */ memset(&reply_key_val, 0, sizeof(reply_key_val)); accepted->ar_results.where = (caddr_t) &reply_key_val; accepted->ar_results.proc = (xdrproc_t) xdr_ypresp_key_val; /* Call the real function. */ nis_first(state, reply_fragment_fn, reply_fn, cdata, &request_xdrs, &reply, &reply_xdrs, reply_buf, &reply_key_val); goto sent_reply; break; case YPPROC_NEXT: slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "yp_next()\n"); /* Change the reply data to be a resp_key_val. */ memset(&reply_key_val, 0, sizeof(reply_key_val)); accepted->ar_results.where = (caddr_t) &reply_key_val; accepted->ar_results.proc = (xdrproc_t) xdr_ypresp_key_val; /* Call the real function. */ nis_next(state, reply_fragment_fn, reply_fn, cdata, &request_xdrs, &reply, &reply_xdrs, reply_buf, &reply_key_val); goto sent_reply; break; case YPPROC_XFR: slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "yp_xfr()\n"); /* Do nothing. The default successful reply is fine. */ break; case YPPROC_CLEAR: slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "yp_clear()\n"); /* Do nothing. The default successful reply is fine. */ break; case YPPROC_ALL: slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "yp_all()\n"); /* Set the result type to a boolean. */ memset(&reply_all, 0, sizeof(reply_all)); accepted->ar_results.where = (caddr_t) &reply_all; accepted->ar_results.proc = (xdrproc_t) &xdr_ypresp_all; /* Call the real function. */ nis_all(state, reply_fragment_fn, reply_fn, cdata, &request_xdrs, &reply, &reply_xdrs, reply_buf, &reply_all, continuation_cookie); goto sent_reply; break; case YPPROC_MASTER: slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "yp_master()\n"); /* Change reply type to be a resp_master. */ memset(&reply_master, 0, sizeof(reply_master)); accepted->ar_results.where = (caddr_t) &reply_master; accepted->ar_results.proc = (xdrproc_t) xdr_ypresp_master; /* Call the real function. */ nis_master(state, reply_fragment_fn, reply_fn, cdata, &request_xdrs, &reply, &reply_xdrs, reply_buf, &reply_master); goto sent_reply; break; case YPPROC_ORDER: slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "yp_order()\n"); /* Change reply type to be a resp_order. */ memset(&reply_order, 0, sizeof(reply_order)); accepted->ar_results.where = (caddr_t) &reply_order; accepted->ar_results.proc = (xdrproc_t) xdr_ypresp_order; /* Call the real function. */ nis_order(state, reply_fragment_fn, reply_fn, cdata, &request_xdrs, &reply, &reply_xdrs, reply_buf, &reply_order); goto sent_reply; break; case YPPROC_MAPLIST: slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "yp_maplist()\n"); /* Change reply type to be a resp_maplist. */ memset(&reply_maplist, 0, sizeof(reply_maplist)); accepted->ar_results.where = (caddr_t) &reply_maplist; accepted->ar_results.proc = (xdrproc_t) xdr_ypresp_maplist; /* Call the real function. */ nis_maplist(state, reply_fragment_fn, reply_fn, cdata, &request_xdrs, &reply, &reply_xdrs, reply_buf, &reply_maplist); goto sent_reply; break; case YPPROC_NEWXFR: slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "yp_newxfr()\n"); reply.rm_reply.rp_stat = MSG_DENIED; reply.rm_reply.rp_rjct.rj_stat = RPC_MISMATCH; break; } send_reply: (*reply_fn)(state, cdata, &reply, &reply_xdrs, reply_buf); sent_reply: xdr_destroy(&reply_xdrs); done: xdr_destroy(&request_xdrs); return; }