summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac8
-rw-r--r--src/backend.c75
-rw-r--r--src/dispatch.c120
-rw-r--r--src/dispatch.h6
-rw-r--r--src/format.c23
-rw-r--r--src/nis.c96
-rw-r--r--src/nis.h1
-rw-r--r--src/plugin.c13
-rw-r--r--src/plugin.h1
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 *
diff --git a/src/nis.c b/src/nis.c
index 68129ae..aa75000 100644
--- a/src/nis.c
+++ b/src/nis.c
@@ -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);
diff --git a/src/nis.h b/src/nis.h
index 80c029f..f65462b 100644
--- a/src/nis.h
+++ b/src/nis.h
@@ -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;