diff options
-rw-r--r-- | configure.ac | 8 | ||||
-rw-r--r-- | src/backend.c | 75 | ||||
-rw-r--r-- | src/dispatch.c | 120 | ||||
-rw-r--r-- | src/dispatch.h | 6 | ||||
-rw-r--r-- | src/format.c | 23 | ||||
-rw-r--r-- | src/nis.c | 96 | ||||
-rw-r--r-- | src/nis.h | 1 | ||||
-rw-r--r-- | src/plugin.c | 13 | ||||
-rw-r--r-- | src/plugin.h | 1 |
9 files changed, 250 insertions, 93 deletions
diff --git a/configure.ac b/configure.ac index 664bb39..6307614 100644 --- a/configure.ac +++ b/configure.ac @@ -46,8 +46,8 @@ dirsrv) AC_DEFINE(USE_PTHREADS,1,[Define to use POSIX threading functions.]) esac -mylibdir=`eval echo "$libdir" | sed "s,NONE,$ac_default_prefix,g"` -mylibdir=`eval echo "$mylibdir" | sed "s,NONE,$ac_prefix,g"` +mylibdir=`eval echo "$libdir" | sed "s,NONE,${ac_default_prefix},g"` +mylibdir=`eval echo "$mylibdir" | sed "s,NONE,${ac_prefix},g"` case "$server" in dirsrv) myplugindir="$mylibdir/dirsrv/plugins" @@ -64,5 +64,9 @@ AC_SUBST(myplugindir) AC_SUBST(mydomain) AC_SUBST(mysuffix) +AC_DEFINE(DEFAULT_MAX_DGRAM_SIZE,YPMAXRECORD,[Define to the default maximum datagram reply size.]) +AC_DEFINE(DEFAULT_MAX_VALUE_SIZE,(256 * 1024),[Define to the default maximum map entry key and value size.]) +AC_DEFINE(DEFAULT_TARGET_REPLY_SIZE,(4 * 1024),[Define to the default target size for a connected reply fragment.]) + AC_CONFIG_HEADER(config.h) AC_OUTPUT(Makefile src/Makefile plugin.ldif) diff --git a/src/backend.c b/src/backend.c index a634c9f..9dc4a3e 100644 --- a/src/backend.c +++ b/src/backend.c @@ -37,6 +37,7 @@ #endif #include <rpc/xdr.h> +#include <rpcsvc/yp_prot.h> #include "backend.h" #include "defaults.h" @@ -416,12 +417,86 @@ backend_map_config_entry_cb(Slapi_Entry *e, void *callback_data) return 0; } +static void +backend_read_params(struct plugin_state *state) +{ + Slapi_DN *our_dn; + Slapi_Entry *our_entry; + Slapi_ValueSet *values; + Slapi_Value *value; + char *actual_attr, *cvalue; + int disposition, buffer_flags, ivalue, i; + unsigned int uvalue; + char *attrs[] = { + "max_value_size", + "max_dgram_size", + NULL, + }; + /* Try to read our name from the top-level configuration node. */ + our_dn = slapi_sdn_new_dn_byval(state->plugin_base); + if (our_dn == NULL) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "backend_read_params: " + "error parsing \"%s\"\n", state->plugin_base); + return; + } + slapi_search_internal_get_entry(our_dn, attrs, &our_entry, + state->plugin_identity); + slapi_sdn_free(&our_dn); + our_dn = NULL; + if (our_entry == NULL) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "backend_read_params: failure reading " + "\"%s\"", state->plugin_base); + return; + } + /* Pull out the attribute values. */ + for (i = 0; attrs[i] != NULL; i++) { + if (slapi_vattr_values_get(our_entry, attrs[i], &values, + &disposition, &actual_attr, + 0, &buffer_flags) == 0) { + if (slapi_valueset_first_value(values, &value) == 0) { + if (strcmp(attrs[i], "max_value_size") == 0) { + uvalue = slapi_value_get_uint(value); + if (uvalue != 0) { + state->max_value_size = uvalue; + } else { + state->max_value_size = + DEFAULT_MAX_VALUE_SIZE; + } + } else + if (strcmp(attrs[i], "max_dgram_size") == 0) { + uvalue = slapi_value_get_uint(value); + if (uvalue != 0) { + state->max_dgram_size = uvalue; + } else { + state->max_dgram_size = + DEFAULT_MAX_DGRAM_SIZE; + } + } + } + slapi_vattr_values_free(&values, &actual_attr, + buffer_flags); + } else { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "backend_read_params: no \"%s\" value " + "for \"%s\", using default\n", attrs[i], + state->plugin_base); + } + } + slapi_entry_free(our_entry); +} + /* Scan for the list of configured domains and maps. */ void backend_startup(struct plugin_state *state) { Slapi_PBlock *pb; char *attrs = NULL; + backend_read_params(state); pb = slapi_pblock_new(); slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, diff --git a/src/dispatch.c b/src/dispatch.c index 8a9c981..7ab93f0 100644 --- a/src/dispatch.c +++ b/src/dispatch.c @@ -74,9 +74,12 @@ struct dispatch_client { char *client_query; ssize_t client_query_size; void *client_query_cookie; - /* The reply to the client, when we're sending one. */ - char client_outbuf[4096]; - ssize_t client_outbuf_used; + /* The outgoing replies to the client, when we're sending one. */ + char *client_outbuf; + ssize_t client_outbuf_size, client_outbuf_used; + /* Working space for a client reply. */ + char *client_workbuf; + ssize_t client_workbuf_size; /* This is a linked list. */ struct dispatch_client *client_next; }; @@ -87,6 +90,8 @@ struct dispatch_client_data { int client_fd; struct sockaddr client_addr; socklen_t client_addrlen; + char *reply_buf; + size_t reply_buf_size; } dgram; }; @@ -95,33 +100,42 @@ static bool_t dispatch_reply_fragment_dgram(struct plugin_state *state, struct dispatch_client_data *cdata, struct rpc_msg *reply, - XDR *reply_xdrs, char *reply_buf, + XDR *reply_xdrs, bool_t first_fragment, bool_t last_fragment) { - xdr_replymsg(reply_xdrs, reply); - if (!first_fragment || !last_fragment) { - slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "trying to sending datagram reply (%d bytes), " - "even though the reply is not suitable for " - "transmission as a datagram\n", - xdr_getpos(reply_xdrs)); + if (xdr_replymsg(reply_xdrs, reply)) { + if (!first_fragment || !last_fragment) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "trying to sending datagram reply (%d " + "bytes), even though the reply is not " + "suitable for transmission as a " + "datagram\n", xdr_getpos(reply_xdrs)); + } else { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "sending datagram reply (%d bytes)\n", + xdr_getpos(reply_xdrs)); + } + sendto(cdata->dgram.client_fd, + cdata->dgram.reply_buf, xdr_getpos(reply_xdrs), + 0, + &cdata->dgram.client_addr, + cdata->dgram.client_addrlen); } else { - slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "sending datagram reply (%d bytes)\n", - xdr_getpos(reply_xdrs)); + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "error sending datagram reply -- too large?\n"); } - sendto(cdata->dgram.client_fd, reply_buf, xdr_getpos(reply_xdrs), - 0, &cdata->dgram.client_addr, cdata->dgram.client_addrlen); return TRUE; } static void dispatch_reply_dgram(struct plugin_state *state, struct dispatch_client_data *cdata, - struct rpc_msg *reply, - XDR *reply_xdrs, char *reply_buf) + struct rpc_msg *reply, XDR *reply_xdrs) { dispatch_reply_fragment_dgram(state, cdata, - reply, reply_xdrs, reply_buf, + reply, reply_xdrs, TRUE, TRUE); } @@ -129,11 +143,11 @@ static bool_t dispatch_reply_fragment_connected(struct plugin_state *state, struct dispatch_client_data *cdata, struct rpc_msg *reply, - XDR *reply_xdrs, char *reply_buf, + XDR *reply_xdrs, bool_t first_fragment, bool_t last_fragment) { uint32_t len; - size_t next_size; + ssize_t next_size; /* Record reply - first fragment. */ if (first_fragment) { xdr_replymsg(reply_xdrs, reply); @@ -141,10 +155,20 @@ dispatch_reply_fragment_connected(struct plugin_state *state, /* If we don't have space for the data, stop now. */ next_size = cdata->connected->client_outbuf_used + 4 + xdr_getpos(reply_xdrs); - if (next_size > sizeof(cdata->connected->client_outbuf)) { + if (next_size > cdata->connected->client_outbuf_size) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "failed to queue stream reply (4+%d bytes)!\n", + xdr_getpos(reply_xdrs)); + return FALSE; + } + /* If we already have data in the buffer, and this would put us over + * the target size, then punt it until next time. */ + if ((cdata->connected->client_outbuf_used > 4) && + (next_size > DEFAULT_TARGET_REPLY_SIZE)) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "failed to queue stream reply (4+%d bytes)!n", + "saving stream reply (4+%d bytes) for later\n", xdr_getpos(reply_xdrs)); return FALSE; } @@ -156,7 +180,7 @@ dispatch_reply_fragment_connected(struct plugin_state *state, &len, 4); memcpy(cdata->connected->client_outbuf + cdata->connected->client_outbuf_used + 4, - reply_buf, + cdata->connected->client_workbuf, xdr_getpos(reply_xdrs)); cdata->connected->client_outbuf_used += (4 + xdr_getpos(reply_xdrs)); slapi_log_error(SLAPI_LOG_PLUGIN, @@ -171,10 +195,10 @@ static void dispatch_reply_connected(struct plugin_state *state, struct dispatch_client_data *cdata, struct rpc_msg *reply, - XDR *reply_xdrs, char *reply_buf) + XDR *reply_xdrs) { dispatch_reply_fragment_connected(state, cdata, - reply, reply_xdrs, reply_buf, + reply, reply_xdrs, TRUE, TRUE); } @@ -189,6 +213,14 @@ dispatch_dgram(struct plugin_state *state, int fd) /* Read the request. */ cdata.dgram.client_fd = fd; cdata.dgram.client_addrlen = sizeof(cdata.dgram.client_addr); + cdata.dgram.reply_buf = malloc(state->max_dgram_size); + cdata.dgram.reply_buf_size = state->max_dgram_size; + if (cdata.dgram.reply_buf == NULL) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "error reading datagram request: " + "out of memory\n"); + return; + } reqsize = recvfrom(cdata.dgram.client_fd, dgram, sizeof(dgram), 0, &cdata.dgram.client_addr, &cdata.dgram.client_addrlen); @@ -199,7 +231,11 @@ dispatch_dgram(struct plugin_state *state, int fd) nis_process_request(state, dgram, reqsize, &dispatch_reply_fragment_dgram, &dispatch_reply_dgram, - &cdata, NULL); + &cdata, + cdata.dgram.reply_buf, + cdata.dgram.reply_buf_size, + NULL); + free(cdata.dgram.reply_buf); } /* Set the client's record up to start reading a new query. */ @@ -222,7 +258,13 @@ client_set_closing(struct plugin_state *state, struct dispatch_client *client) free(client->client_query); client->client_query = NULL; client->client_query_size = 0; + free(client->client_outbuf); + client->client_outbuf = NULL; + client->client_outbuf_size = 0; client->client_outbuf_used = 0; + free(client->client_workbuf); + client->client_workbuf = NULL; + client->client_workbuf_size = 0; client->client_state = client_closing; } @@ -232,10 +274,22 @@ dispatch_accept_client(struct plugin_state *state, int fd) { struct dispatch_client *client; int flags; + char *outbuf, *workbuf; client = malloc(sizeof(*client)); if (client == NULL) { return NULL; } + outbuf = malloc(state->max_dgram_size + state->max_value_size); + if (outbuf == NULL) { + free(client); + return NULL; + } + workbuf = malloc(state->max_dgram_size + state->max_value_size); + if (workbuf == NULL) { + free(outbuf); + free(client); + return NULL; + } fd = accept(fd, &client->client_addr, &client->client_addrlen); if (fd == -1) { free(client); @@ -249,6 +303,12 @@ dispatch_accept_client(struct plugin_state *state, int fd) "new connected client on %d\n", fd); memset(client, 0, sizeof(*client)); client->client_fd = fd; + client->client_outbuf = outbuf; + client->client_outbuf_size = state->max_dgram_size + + state->max_value_size; + client->client_workbuf = workbuf; + client->client_workbuf_size = state->max_dgram_size + + state->max_value_size; client_set_reading(state, client); return client; } @@ -369,6 +429,8 @@ client_read(struct plugin_state *state, struct dispatch_client *client) &dispatch_reply_fragment_connected, &dispatch_reply_connected, &client_data, + client->client_workbuf, + client->client_workbuf_size, &client->client_query_cookie); /* Decide what to do next. */ client_interpret_nis_result(state, client); @@ -420,7 +482,7 @@ client_write(struct plugin_state *state, struct dispatch_client *client) /* More to send, so ask for more reply data. */ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "waiting for more data for %d\n", + "fetching more data for %d\n", client->client_fd); client->client_outbuf_used = 0; memset(&client_data, 0, sizeof(client_data)); @@ -431,6 +493,8 @@ client_write(struct plugin_state *state, struct dispatch_client *client) &dispatch_reply_fragment_connected, &dispatch_reply_connected, &client_data, + client->client_workbuf, + client->client_workbuf_size, &client->client_query_cookie); client_interpret_nis_result(state, client); } diff --git a/src/dispatch.h b/src/dispatch.h index ea4813e..86af859 100644 --- a/src/dispatch.h +++ b/src/dispatch.h @@ -27,12 +27,10 @@ struct dispatch_client_data; void *dispatch_thread(struct wrapped_thread *t); typedef bool_t (dispatch_reply_fragment)(struct plugin_state *state, struct dispatch_client_data *cdata, - struct rpc_msg *reply, - XDR *reply_xdrs, char *reply_buf, + struct rpc_msg *reply, XDR *reply_xdrs, bool_t first_fragment, bool_t last_fragment); typedef void (dispatch_reply)(struct plugin_state *state, struct dispatch_client_data *cdata, - struct rpc_msg *reply, - XDR *reply_xdrs, char *reply_buf); + struct rpc_msg *reply, XDR *reply_xdrs); #endif diff --git a/src/format.c b/src/format.c index f738c44..6138207 100644 --- a/src/format.c +++ b/src/format.c @@ -1042,19 +1042,28 @@ static char * format_format(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, const char *fmt, char ***visited_ndns) { - char buf[YPMAXRECORD], *tmp; + char *buf, *tmp, *ret; const char *match, *fmtstart, *fmtend; - unsigned int i, j; + unsigned int i, j, buflen; int exp_len; - i = format_expand(state, pb, e, fmt, buf, sizeof(buf), - visited_ndns, TRUE); - if (i < sizeof(buf)) { + buflen = state->max_value_size; + buf = malloc(buflen); + if (buf == NULL) { + return NULL; + } + + i = format_expand(state, pb, e, fmt, buf, buflen, visited_ndns, TRUE); + if (i < buflen) { buf[i] = '\0'; - return strdup(buf); + ret = strdup(buf); } else { - return NULL; + ret = NULL; } + + free(buf); + + return ret; } char * @@ -56,7 +56,7 @@ nis_domain(struct plugin_state *state, 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, + struct rpc_msg *reply, XDR *reply_xdrs, bool_t *reply_bool) { char *domain = NULL; @@ -69,7 +69,7 @@ nis_domain(struct plugin_state *state, state->plugin_desc->spd_id, "domain(%s) -> %s\n", domain, *reply_bool ? "TRUE" : "FALSE"); - (*reply_fn)(state, cdata, reply, reply_xdrs, reply_buf); + (*reply_fn)(state, cdata, reply, reply_xdrs); } else { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, @@ -91,7 +91,7 @@ nis_match(struct plugin_state *state, dispatch_reply *reply_fn, struct dispatch_client_data *cdata, XDR *request_xdrs, - struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, + struct rpc_msg *reply, XDR *reply_xdrs, struct ypresp_val *reply_val) { struct ypreq_key req_key; @@ -121,7 +121,7 @@ nis_match(struct plugin_state *state, &map_supported); reply_val->status = map_supported ? YP_NOKEY : YP_NOMAP; } - (*reply_fn)(state, cdata, reply, reply_xdrs, reply_buf); + (*reply_fn)(state, cdata, reply, reply_xdrs); map_unlock(); } else { /* XXX */ @@ -134,7 +134,7 @@ nis_first(struct plugin_state *state, dispatch_reply *reply_fn, struct dispatch_client_data *cdata, XDR *request_xdrs, - struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, + struct rpc_msg *reply, XDR *reply_xdrs, struct ypresp_key_val *reply_key_val) { struct ypreq_nokey req_nokey; @@ -163,7 +163,7 @@ nis_first(struct plugin_state *state, reply_key_val->status = map_supported ? YP_NOKEY : YP_NOMAP; } - (*reply_fn)(state, cdata, reply, reply_xdrs, reply_buf); + (*reply_fn)(state, cdata, reply, reply_xdrs); map_unlock(); } else { /* XXX */ @@ -176,7 +176,7 @@ nis_next(struct plugin_state *state, dispatch_reply *reply_fn, struct dispatch_client_data *cdata, XDR *request_xdrs, - struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, + struct rpc_msg *reply, XDR *reply_xdrs, struct ypresp_key_val *reply_key_val) { struct ypreq_key req_key; @@ -220,7 +220,7 @@ nis_next(struct plugin_state *state, req_key.domain, req_key.map); } - (*reply_fn)(state, cdata, reply, reply_xdrs, reply_buf); + (*reply_fn)(state, cdata, reply, reply_xdrs); map_unlock(); } else { /* XXX */ @@ -233,7 +233,7 @@ nis_master(struct plugin_state *state, dispatch_reply *reply_fn, struct dispatch_client_data *cdata, XDR *request_xdrs, - struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, + struct rpc_msg *reply, XDR *reply_xdrs, struct ypresp_master *reply_master) { struct ypreq_nokey req_nokey; @@ -253,7 +253,7 @@ nis_master(struct plugin_state *state, req_nokey.domain, req_nokey.map, reply_master->master); - (*reply_fn)(state, cdata, reply, reply_xdrs, reply_buf); + (*reply_fn)(state, cdata, reply, reply_xdrs); map_unlock(); } else { /* XXX */ @@ -266,7 +266,7 @@ nis_order(struct plugin_state *state, dispatch_reply *reply_fn, struct dispatch_client_data *cdata, XDR *request_xdrs, - struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, + struct rpc_msg *reply, XDR *reply_xdrs, struct ypresp_order *reply_order) { struct ypreq_nokey req_nokey; @@ -292,7 +292,7 @@ nis_order(struct plugin_state *state, req_nokey.domain, req_nokey.map); } - (*reply_fn)(state, cdata, reply, reply_xdrs, reply_buf); + (*reply_fn)(state, cdata, reply, reply_xdrs); map_unlock(); } else { /* XXX */ @@ -336,7 +336,7 @@ nis_maplist(struct plugin_state *state, dispatch_reply *reply_fn, struct dispatch_client_data *cdata, XDR *request_xdrs, - struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, + struct rpc_msg *reply, XDR *reply_xdrs, struct ypresp_maplist *reply_maplist) { char *domain = NULL; @@ -363,7 +363,7 @@ nis_maplist(struct plugin_state *state, domain, list->map); } } - (*reply_fn)(state, cdata, reply, reply_xdrs, reply_buf); + (*reply_fn)(state, cdata, reply, reply_xdrs); nis_free_maplist_cb_result(&list); map_unlock(); } else { @@ -426,7 +426,7 @@ nis_all(struct plugin_state *state, dispatch_reply *reply_fn, struct dispatch_client_data *cdata, XDR *request_xdrs, - struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, + struct rpc_msg *reply, XDR *reply_xdrs, struct ypresp_all *reply_all, void **continuation_cookie) { struct ypreq_nokey req_nokey; @@ -472,7 +472,7 @@ nis_all(struct plugin_state *state, xdr_ypresp_all(reply_xdrs, reply_all); /* Queue the entire response. */ if (!(*reply_fragment_fn)(state, cdata, - reply, reply_xdrs, reply_buf, + reply, reply_xdrs, FALSE, TRUE)) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, @@ -535,7 +535,7 @@ nis_all(struct plugin_state *state, if (skip || (*reply_fragment_fn)(state, cdata, reply, - reply_xdrs, reply_buf, + reply_xdrs, TRUE, FALSE)) { /* Leave a note to choose the next * entry or send end1, whichever is @@ -594,7 +594,7 @@ nis_all(struct plugin_state *state, (xdr_ypresp_all(reply_xdrs, reply_all) && (*reply_fragment_fn)(state, cdata, reply, - reply_xdrs, reply_buf, + reply_xdrs, FALSE, FALSE))) { /* Leave a note to choose the next * entry or send end1, whichever is @@ -656,25 +656,22 @@ nis_all(struct plugin_state *state, 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; + if (!skip) { + if (xdr_ypresp_all(reply_xdrs, + reply_all)) { + (*reply_fragment_fn)(state, cdata, + reply, + reply_xdrs, + FALSE, FALSE); + } } + /* Leave a note to choose the next entry, even + * if we failed here, otherwise we can get + * stuck. */ + nis_all_free_cookie(cookie); + cookie = nis_all_make_cookie(next_state, + reply_key->keydat_len, + reply_key->keydat_val); break; case cookie_end1: /* Send the end-of-map message. */ @@ -690,7 +687,7 @@ nis_all(struct plugin_state *state, if (xdr_ypresp_all(reply_xdrs, reply_all) && (*reply_fragment_fn)(state, cdata, reply, - reply_xdrs, reply_buf, + reply_xdrs, FALSE, FALSE)) { /* Leave a note to finish the reply. */ nis_all_free_cookie(cookie); @@ -713,7 +710,7 @@ nis_all(struct plugin_state *state, if (xdr_ypresp_all(reply_xdrs, reply_all) && (*reply_fragment_fn)(state, cdata, reply, - reply_xdrs, reply_buf, + reply_xdrs, FALSE, TRUE)) { /* We're done. */ nis_all_free_cookie(cookie); @@ -747,11 +744,12 @@ nis_process_request(struct plugin_state *state, dispatch_reply_fragment *reply_fragment_fn, dispatch_reply *reply_fn, struct dispatch_client_data *cdata, + char *reply_buf, size_t reply_buf_size, void **continuation_cookie) { XDR request_xdrs, reply_xdrs, auth_xdrs; AUTH *request_auth, *reply_auth; - char reply_buf[64000], auth_buf[MAX_AUTH_BYTES]; + char auth_buf[MAX_AUTH_BYTES]; struct rpc_msg request, reply; int superuser, auth_flavor, auth_len; struct ypresp_val reply_val; @@ -790,7 +788,7 @@ nis_process_request(struct plugin_state *state, 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); + xdrmem_create(&reply_xdrs, reply_buf, reply_buf_size, XDR_ENCODE); /* Validate the client's credentials. */ auth_flavor = request.rm_call.cb_cred.oa_flavor; @@ -902,7 +900,7 @@ nis_process_request(struct plugin_state *state, 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); + &reply, &reply_xdrs, &reply_bool); goto sent_reply; break; case YPPROC_MATCH: @@ -916,7 +914,7 @@ nis_process_request(struct plugin_state *state, /* Call the real function. */ nis_match(state, reply_fragment_fn, reply_fn, cdata, &request_xdrs, - &reply, &reply_xdrs, reply_buf, &reply_val); + &reply, &reply_xdrs, &reply_val); goto sent_reply; break; case YPPROC_FIRST: @@ -930,7 +928,7 @@ nis_process_request(struct plugin_state *state, /* Call the real function. */ nis_first(state, reply_fragment_fn, reply_fn, cdata, &request_xdrs, - &reply, &reply_xdrs, reply_buf, &reply_key_val); + &reply, &reply_xdrs, &reply_key_val); goto sent_reply; break; case YPPROC_NEXT: @@ -944,7 +942,7 @@ nis_process_request(struct plugin_state *state, /* Call the real function. */ nis_next(state, reply_fragment_fn, reply_fn, cdata, &request_xdrs, - &reply, &reply_xdrs, reply_buf, &reply_key_val); + &reply, &reply_xdrs, &reply_key_val); goto sent_reply; break; case YPPROC_XFR: @@ -970,7 +968,7 @@ nis_process_request(struct plugin_state *state, /* Call the real function. */ nis_all(state, reply_fragment_fn, reply_fn, cdata, &request_xdrs, - &reply, &reply_xdrs, reply_buf, &reply_all, + &reply, &reply_xdrs, &reply_all, continuation_cookie); goto sent_reply; break; @@ -985,7 +983,7 @@ nis_process_request(struct plugin_state *state, /* Call the real function. */ nis_master(state, reply_fragment_fn, reply_fn, cdata, &request_xdrs, - &reply, &reply_xdrs, reply_buf, &reply_master); + &reply, &reply_xdrs, &reply_master); goto sent_reply; break; case YPPROC_ORDER: @@ -999,7 +997,7 @@ nis_process_request(struct plugin_state *state, /* Call the real function. */ nis_order(state, reply_fragment_fn, reply_fn, cdata, &request_xdrs, - &reply, &reply_xdrs, reply_buf, &reply_order); + &reply, &reply_xdrs, &reply_order); goto sent_reply; break; case YPPROC_MAPLIST: @@ -1013,7 +1011,7 @@ nis_process_request(struct plugin_state *state, /* Call the real function. */ nis_maplist(state, reply_fragment_fn, reply_fn, cdata, &request_xdrs, - &reply, &reply_xdrs, reply_buf, &reply_maplist); + &reply, &reply_xdrs, &reply_maplist); goto sent_reply; break; case YPPROC_NEWXFR: @@ -1026,7 +1024,7 @@ nis_process_request(struct plugin_state *state, } send_reply: - (*reply_fn)(state, cdata, &reply, &reply_xdrs, reply_buf); + (*reply_fn)(state, cdata, &reply, &reply_xdrs); sent_reply: xdr_destroy(&reply_xdrs); @@ -31,6 +31,7 @@ void nis_process_request(struct plugin_state *state, dispatch_reply_fragment *reply_fragment, dispatch_reply *reply, struct dispatch_client_data *cdata, + char *reply_buf, size_t reply_buf_size, void **continuation_cookie); #endif diff --git a/src/plugin.c b/src/plugin.c index 1b54d81..c35d0d7 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -28,6 +28,7 @@ #include <arpa/inet.h> #include <assert.h> #include <errno.h> +#include <fcntl.h> #include <netinet/in.h> #include <poll.h> #include <stdlib.h> @@ -155,6 +156,8 @@ plugin_state_init(Slapi_PBlock *pb, struct plugin_state **lstate) } state->plugin_base = NULL; state->plugin_desc = &plugin_description; + state->max_value_size = DEFAULT_MAX_VALUE_SIZE; + state->max_dgram_size = DEFAULT_MAX_DGRAM_SIZE; slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &state->plugin_identity); slapi_pblock_get(pb, SLAPI_TARGET_DN, &state->plugin_base); @@ -175,7 +178,7 @@ plugin_state_init(Slapi_PBlock *pb, struct plugin_state **lstate) * listeners, over both IPv4 and IPv6. */ state->n_listeners = 0; for (i = 0; i < 2; i++) { - int pf, type, one, port, ret; + int pf, type, one, flags, port, ret; const char *sock_desc; /* Before we do anything else, on our second trip through, make * sure that the first socket was created, because we'll need @@ -202,7 +205,7 @@ plugin_state_init(Slapi_PBlock *pb, struct plugin_state **lstate) sock_desc); continue; } - /* Mark the socket as reusable. */ + /* Mark the socket as reusable and non-blocking. */ one = 1; if (setsockopt(sockfd, IPPROTO_IP, SO_REUSEADDR, &one, sizeof(one)) != 0) { @@ -211,7 +214,11 @@ plugin_state_init(Slapi_PBlock *pb, struct plugin_state **lstate) "error marking %s socket for reuse, " "continuing\n", sock_desc); } - /* Bind to a reserved port. */ + flags = fcntl(sockfd, F_GETFL); + if ((flags & O_NONBLOCK) == 0) { + fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); + } + /* Bind to a reserved port, don't really care which one. */ memset(&sin, 0, sizeof(sin)); memset(&sin6, 0, sizeof(sin6)); sin.sin_family = AF_INET; diff --git a/src/plugin.h b/src/plugin.h index 13c06c0..3818c85 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -30,6 +30,7 @@ struct plugin_state { Slapi_ComponentId *plugin_identity; Slapi_PluginDesc *plugin_desc; int pmap_client_socket; + int max_dgram_size, max_value_size; int n_listeners; struct { int fd, port, pf, type; |