diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dispatch.c | 139 | ||||
-rw-r--r-- | src/dispatch.h | 10 | ||||
-rw-r--r-- | src/nis.c | 134 | ||||
-rw-r--r-- | src/nis.h | 5 |
4 files changed, 138 insertions, 150 deletions
diff --git a/src/dispatch.c b/src/dispatch.c index 51de9f3..34932f1 100644 --- a/src/dispatch.c +++ b/src/dispatch.c @@ -31,23 +31,80 @@ struct dispatch_stream_client_params { struct plugin_state *state; }; +struct dispatch_client_data { + int client; + struct sockaddr client_addr; + socklen_t client_addrlen; +}; + +static ssize_t +dispatch_write_with_retry(struct plugin_state *state, int fd, + const void *buffer1, ssize_t length1, + const void *buffer2, ssize_t length2) +{ + ssize_t sent, i; + struct iovec iov[2]; + int iovc; + sent = 0; + while ((sent != -1) && (sent < (length1 + length2))) { + if (sent < length1) { + iov[0].iov_base = ((char *) buffer1) + sent; + iov[0].iov_len = length1 - sent; + iov[1].iov_base = (char *) buffer2; + iov[1].iov_len = length2; + iovc = 2; + } else { + iov[0].iov_base = ((char *) buffer2) + (sent - length1); + iov[0].iov_len = length2 - (sent - length1); + iovc = 1; + } + i = writev(fd, &iov[0], iovc); + switch (i) { + case 0: + sent = -1; + break; + case -1: + switch (errno) { + case EAGAIN: + continue; + break; + default: + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "Got error %s sending " + "%d bytes (at %d) to %d.\n", + strerror(errno), + length1 + length2, + sent, fd); + sent = -1; + break; + } + break; + default: + sent += i; + break; + } + } + return sent; +} + /* Send a reply which _could_ be sent over a datagram. */ void -dispatch_reply_fragment(struct plugin_state *state, int client, - struct sockaddr *client_addr, socklen_t client_addrlen, +dispatch_reply_fragment(struct plugin_state *state, + struct dispatch_client_data *cdata, struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, bool_t first_fragment, bool_t last_fragment) { uint32_t len; - if (client_addr != NULL) { + if (cdata->client_addrlen != 0) { /* It's a datagram socket, so there's nothing to do but send * the data by itself. */ xdr_replymsg(reply_xdrs, reply); slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "Sending datagram reply (%d bytes).\n", xdr_getpos(reply_xdrs)); - sendto(client, reply_buf, xdr_getpos(reply_xdrs), - 0, client_addr, client_addrlen); + sendto(cdata->client, reply_buf, xdr_getpos(reply_xdrs), + 0, &cdata->client_addr, cdata->client_addrlen); } else { /* Record reply - one fragment. */ if (first_fragment) { @@ -57,9 +114,10 @@ dispatch_reply_fragment(struct plugin_state *state, int client, len = htonl(xdr_getpos(reply_xdrs) | (last_fragment ? 0x80000000 : 0)); /* Send the data to the client. */ - if (nis_write_with_retry(state, client, - &len, 4, - reply_buf, xdr_getpos(reply_xdrs)) == + if (dispatch_write_with_retry(state, cdata->client, + &len, 4, + reply_buf, + xdr_getpos(reply_xdrs)) == 4 + xdr_getpos(reply_xdrs)) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, @@ -76,11 +134,10 @@ dispatch_reply_fragment(struct plugin_state *state, int client, /* Send an entire reply datagram or record at once. */ void -dispatch_reply(struct plugin_state *state, int client, - struct sockaddr *client_addr, socklen_t client_addrlen, +dispatch_reply(struct plugin_state *state, struct dispatch_client_data *cdata, struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf) { - dispatch_reply_fragment(state, client, client_addr, client_addrlen, + dispatch_reply_fragment(state, cdata, reply, reply_xdrs, reply_buf, TRUE, TRUE); } @@ -88,35 +145,38 @@ dispatch_reply(struct plugin_state *state, int client, static void * dispatch_stream_handler_thread(void *arg) { - int flags, frag_len, record_len, client; + int flags, frag_len, record_len; ssize_t i; int32_t len, nlen; char fragment[65540], record[65536]; struct pollfd pollfd; struct dispatch_stream_client_params *params; + struct dispatch_client_data cdata; struct plugin_state *state; bool_t last; /* Recover the full set of parameters. */ params = arg; state = params->state; - client = params->client; + cdata.client = params->client; + memset(&cdata.client_addr, 0, sizeof(cdata.client_addr)); + cdata.client_addrlen = 0; free(arg); slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "opened client connection %d, thread started\n", - client); + cdata.client); /* Set the connection to be non-blocking. */ - flags = fcntl(client, F_GETFD); + flags = fcntl(cdata.client, F_GETFD); if ((flags == -1) || - (fcntl(client, F_SETFD, flags | O_NONBLOCK) == -1)) { + (fcntl(cdata.client, F_SETFD, flags | O_NONBLOCK) == -1)) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "error setting new client connection to be " "non-blocking\n"); - close(client); + close(cdata.client); return NULL; } slapi_log_error(SLAPI_LOG_PLUGIN, @@ -128,7 +188,7 @@ dispatch_stream_handler_thread(void *arg) record_len = 0; for (;;) { /* Wait for incoming data. */ - pollfd.fd = client; + pollfd.fd = cdata.client; pollfd.events = POLLIN | POLLHUP; switch (poll(&pollfd, 1, MAX_CLIENT_IDLE)) { case -1: @@ -147,7 +207,7 @@ dispatch_stream_handler_thread(void *arg) break; } /* Try to read as much data as we have space to hold. */ - i = read(client, fragment + frag_len, + i = read(cdata.client, fragment + frag_len, sizeof(fragment) - frag_len); switch (i) { case -1: @@ -210,7 +270,7 @@ dispatch_stream_handler_thread(void *arg) } slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "got whole record (%d bytes)\n", record_len); - nis_process_request(state, client, NULL, 0, record, record_len); + nis_process_request(state, &cdata, record, record_len); record_len = 0; /* Note that we did it! */ slapi_log_error(SLAPI_LOG_PLUGIN, @@ -219,11 +279,11 @@ dispatch_stream_handler_thread(void *arg) frag_len, record_len); } done: - close(client); + close(cdata.client); slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "closed client connection %d, thread ending\n", - client); + cdata.client); return NULL; } @@ -232,24 +292,23 @@ done: static void dispatch_stream(struct plugin_state *state, int fd) { - struct sockaddr_storage client_addr; - socklen_t client_addrlen; - int client, flags; + int flags; pthread_t thread; + struct dispatch_client_data cdata; struct dispatch_stream_client_params *params; /* Answer the connection request. */ - client = accept(fd, (struct sockaddr *) &client_addr, &client_addrlen); - if (client == -1) { + cdata.client = accept(fd, &cdata.client_addr, &cdata.client_addrlen); + if (cdata.client == -1) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "failed to answer new stream request\n"); return; } else { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "new stream client on %d\n", client); - flags = fcntl(client, F_GETFL); + "new stream client on %d\n", cdata.client); + flags = fcntl(cdata.client, F_GETFL); flags |= O_NONBLOCK; - if (fcntl(client, F_SETFL, flags) != 0) { + if (fcntl(cdata.client, F_SETFL, flags) != 0) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "error setting client to " @@ -262,10 +321,10 @@ dispatch_stream(struct plugin_state *state, int fd) if (params == NULL) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "out of memory\n"); - close(client); + close(cdata.client); return; } - params->client = client; + params->client = cdata.client; params->state = state; /* Kick off the thread. */ @@ -273,11 +332,11 @@ dispatch_stream(struct plugin_state *state, int fd) &dispatch_stream_handler_thread, params) != 0) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "error starting thread\n"); - close(client); + close(cdata.client); } slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "started client-specific thread for client on %d\n", - client); + cdata.client); return; } @@ -285,22 +344,20 @@ dispatch_stream(struct plugin_state *state, int fd) static void dispatch_dgram(struct plugin_state *state, int fd) { - struct sockaddr_storage client_addr; - socklen_t client_addrlen; + struct dispatch_client_data cdata; char dgram[65536]; int reqsize; /* Read the request. */ - client_addrlen = sizeof(client_addr); + cdata.client = fd; + cdata.client_addrlen = sizeof(cdata.client_addr); reqsize = recvfrom(fd, dgram, sizeof(dgram), 0, - (struct sockaddr *) &client_addr, &client_addrlen); + &cdata.client_addr, &cdata.client_addrlen); slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "datagram request (%d bytes)\n", reqsize); /* Handle the request. */ - nis_process_request(state, fd, - (struct sockaddr *) &client_addr, client_addrlen, - dgram, reqsize); + nis_process_request(state, &cdata, dgram, reqsize); } diff --git a/src/dispatch.h b/src/dispatch.h index 1dad354..14ea795 100644 --- a/src/dispatch.h +++ b/src/dispatch.h @@ -1,11 +1,11 @@ struct plugin_state; +struct dispatch_client_data; void *dispatch_thread(void *p); -void dispatch_reply_fragment(struct plugin_state *state, int client, - struct sockaddr *client_addr, - socklen_t client_addrlen, +void dispatch_reply_fragment(struct plugin_state *state, + struct dispatch_client_data *cdata, struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, bool_t first_fragment, bool_t last_fragment); -void dispatch_reply(struct plugin_state *state, int client, - struct sockaddr *client_addr, socklen_t client_addrlen, +void dispatch_reply(struct plugin_state *state, + struct dispatch_client_data *cdata, struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf); @@ -17,65 +17,15 @@ #include <nspr.h> +#include "dispatch.h" #include "map.h" #include "nis.h" #include "plugin.h" -static ssize_t -nis_write_with_retry(struct plugin_state *state, int fd, - const void *buffer1, ssize_t length1, - const void *buffer2, ssize_t length2) -{ - ssize_t sent, i; - struct iovec iov[2]; - int iovc; - sent = 0; - while ((sent != -1) && (sent < (length1 + length2))) { - if (sent < length1) { - iov[0].iov_base = ((char *) buffer1) + sent; - iov[0].iov_len = length1 - sent; - iov[1].iov_base = (char *) buffer2; - iov[1].iov_len = length2; - iovc = 2; - } else { - iov[0].iov_base = ((char *) buffer2) + (sent - length1); - iov[0].iov_len = length2 - (sent - length1); - iovc = 1; - } - i = writev(fd, &iov[0], iovc); - switch (i) { - case 0: - sent = -1; - break; - case -1: - switch (errno) { - case EAGAIN: - continue; - break; - default: - slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc->spd_id, - "Got error %s sending " - "%d bytes (at %d) to %d.\n", - strerror(errno), - length1 + length2, - sent, fd); - sent = -1; - break; - } - break; - default: - sent += i; - break; - } - } - return sent; -} - /* Indicate whether or not we serve the specified domain. */ static void nis_domain(struct plugin_state *state, - int client, struct sockaddr *client_addr, socklen_t client_addrlen, + struct dispatch_client_data *cdata, XDR *request_xdrs, PRBool reply_on_failure, struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, bool_t *reply_bool) @@ -89,8 +39,7 @@ nis_domain(struct plugin_state *state, state->plugin_desc->spd_id, "domain(%s) -> %s\n", domain, *reply_bool ? "TRUE" : "FALSE"); - dispatch_reply(state, client, - client_addr, client_addrlen, + dispatch_reply(state, cdata, reply, reply_xdrs, reply_buf); } else { slapi_log_error(SLAPI_LOG_PLUGIN, @@ -108,7 +57,7 @@ nis_domain(struct plugin_state *state, static void nis_match(struct plugin_state *state, - int client, struct sockaddr *client_addr, socklen_t client_addrlen, + struct dispatch_client_data *cdata, XDR *request_xdrs, struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, struct ypresp_val *reply_val) @@ -135,8 +84,7 @@ nis_match(struct plugin_state *state, } else { reply_val->status = YP_NOKEY; } - dispatch_reply(state, client, client_addr, client_addrlen, - reply, reply_xdrs, reply_buf); + dispatch_reply(state, cdata, reply, reply_xdrs, reply_buf); } else { /* XXX */ } @@ -144,7 +92,7 @@ nis_match(struct plugin_state *state, static void nis_first(struct plugin_state *state, - int client, struct sockaddr *client_addr, socklen_t client_addrlen, + 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) @@ -174,8 +122,7 @@ nis_first(struct plugin_state *state, reply_key_val->status = map_supported ? YP_NOKEY : YP_NOMAP; } - dispatch_reply(state, client, client_addr, client_addrlen, - reply, reply_xdrs, reply_buf); + dispatch_reply(state, cdata, reply, reply_xdrs, reply_buf); } else { /* XXX */ } @@ -183,7 +130,7 @@ nis_first(struct plugin_state *state, static void nis_next(struct plugin_state *state, - int client, struct sockaddr *client_addr, socklen_t client_addrlen, + 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) @@ -209,7 +156,7 @@ nis_next(struct plugin_state *state, req_key.map, reply_key_val->status); } else { - reply_key_val->status = YP_NOKEY; + reply_key_val->status = YP_NOKEY; /* XXX: YP_NOMORE? */ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "next(%.*s/%s/%s) -> no more!\n", @@ -218,8 +165,7 @@ nis_next(struct plugin_state *state, req_key.domain, req_key.map); } - dispatch_reply(state, client, client_addr, client_addrlen, - reply, reply_xdrs, reply_buf); + dispatch_reply(state, cdata, reply, reply_xdrs, reply_buf); } else { /* XXX */ } @@ -227,7 +173,7 @@ nis_next(struct plugin_state *state, static void nis_master(struct plugin_state *state, - int client, struct sockaddr *client_addr, socklen_t client_addrlen, + struct dispatch_client_data *cdata, XDR *request_xdrs, struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, struct ypresp_master *reply_master) @@ -248,8 +194,7 @@ nis_master(struct plugin_state *state, req_nokey.domain, req_nokey.map, reply_master->master); - dispatch_reply(state, client, client_addr, client_addrlen, - reply, reply_xdrs, reply_buf); + dispatch_reply(state, cdata, reply, reply_xdrs, reply_buf); } else { /* XXX */ } @@ -257,7 +202,7 @@ nis_master(struct plugin_state *state, static void nis_order(struct plugin_state *state, - int client, struct sockaddr *client_addr, socklen_t client_addrlen, + struct dispatch_client_data *cdata, XDR *request_xdrs, struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, struct ypresp_order *reply_order) @@ -284,8 +229,7 @@ nis_order(struct plugin_state *state, req_nokey.domain, req_nokey.map); } - dispatch_reply(state, client, client_addr, client_addrlen, - reply, reply_xdrs, reply_buf); + dispatch_reply(state, cdata, reply, reply_xdrs, reply_buf); } else { /* XXX */ } @@ -324,7 +268,7 @@ nis_free_maplist_cb_result(struct ypmaplist **list) } static void nis_maplist(struct plugin_state *state, - int client, struct sockaddr *client_addr, socklen_t client_addrlen, + struct dispatch_client_data *cdata, XDR *request_xdrs, struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, struct ypresp_maplist *reply_maplist) @@ -352,8 +296,7 @@ nis_maplist(struct plugin_state *state, domain, list->map); } } - dispatch_reply(state, client, client_addr, client_addrlen, - reply, reply_xdrs, reply_buf); + dispatch_reply(state, cdata, reply, reply_xdrs, reply_buf); nis_free_maplist_cb_result(&list); } else { /* XXX */ @@ -362,7 +305,7 @@ nis_maplist(struct plugin_state *state, static void nis_all(struct plugin_state *state, - int client, struct sockaddr *client_addr, socklen_t client_addrlen, + struct dispatch_client_data *cdata, XDR *request_xdrs, struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, struct ypresp_all *reply_all) @@ -384,16 +327,14 @@ nis_all(struct plugin_state *state, reply_all->ypresp_all_u.val.status = YP_NOMAP; reply_key->keydat_len = 0; reply_val->valdat_len = 0; - dispatch_reply_fragment(state, client, - client_addr, client_addrlen, + dispatch_reply_fragment(state, cdata, reply, reply_xdrs, reply_buf, TRUE, FALSE); /* End of data. */ reply_all->more = FALSE; xdr_setpos(reply_xdrs, 0); xdr_ypresp_all(reply_xdrs, reply_all); - dispatch_reply_fragment(state, client, - client_addr, client_addrlen, + dispatch_reply_fragment(state, cdata, reply, reply_xdrs, reply_buf, FALSE, TRUE); } else { @@ -419,9 +360,7 @@ nis_all(struct plugin_state *state, reply_key->keydat_len, reply_key->keydat_val, reply_all->more); - dispatch_reply_fragment(state, client, - client_addr, - client_addrlen, + dispatch_reply_fragment(state, cdata, reply, reply_xdrs, reply_buf, first, FALSE); @@ -453,8 +392,7 @@ nis_all(struct plugin_state *state, reply_all->more = FALSE; xdr_ypresp_all(reply_xdrs, reply_all); /* Bundle those two chunks into one reply. */ - dispatch_reply_fragment(state, client, - client_addr, client_addrlen, + dispatch_reply_fragment(state, cdata, reply, reply_xdrs, reply_buf, FALSE, TRUE); slapi_log_error(SLAPI_LOG_PLUGIN, @@ -471,8 +409,8 @@ nis_all(struct plugin_state *state, * assume that the client is a datagram client, otherwise we assume it's a * stream client. */ void -nis_process_request(struct plugin_state *state, int client, - struct sockaddr *client_addr, socklen_t client_addrlen, +nis_process_request(struct plugin_state *state, + struct dispatch_client_data *cdata, char *request_buf, size_t request_buflen) { XDR request_xdrs, reply_xdrs, auth_xdrs; @@ -625,8 +563,7 @@ nis_process_request(struct plugin_state *state, int client, accepted->ar_results.where = (caddr_t) &reply_bool; accepted->ar_results.proc = (xdrproc_t) xdr_bool; /* Call the real function. */ - nis_domain(state, client, client_addr, client_addrlen, - &request_xdrs, + nis_domain(state, cdata, &request_xdrs, request.rm_call.cb_proc == YPPROC_DOMAIN, &reply, &reply_xdrs, reply_buf, &reply_bool); goto sent_reply; @@ -640,8 +577,7 @@ nis_process_request(struct plugin_state *state, int client, accepted->ar_results.where = (caddr_t) &reply_val; accepted->ar_results.proc = (xdrproc_t) xdr_ypresp_val; /* Call the real function. */ - nis_match(state, client, client_addr, client_addrlen, - &request_xdrs, + nis_match(state, cdata, &request_xdrs, &reply, &reply_xdrs, reply_buf, &reply_val); goto sent_reply; break; @@ -654,8 +590,7 @@ nis_process_request(struct plugin_state *state, int client, 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, client, client_addr, client_addrlen, - &request_xdrs, + nis_first(state, cdata, &request_xdrs, &reply, &reply_xdrs, reply_buf, &reply_key_val); goto sent_reply; break; @@ -668,8 +603,7 @@ nis_process_request(struct plugin_state *state, int client, 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, client, client_addr, client_addrlen, - &request_xdrs, + nis_next(state, cdata, &request_xdrs, &reply, &reply_xdrs, reply_buf, &reply_key_val); goto sent_reply; break; @@ -694,8 +628,7 @@ nis_process_request(struct plugin_state *state, int client, accepted->ar_results.where = (caddr_t) &reply_all; accepted->ar_results.proc = (xdrproc_t) &xdr_ypresp_all; /* Call the real function. */ - nis_all(state, client, client_addr, client_addrlen, - &request_xdrs, + nis_all(state, cdata, &request_xdrs, &reply, &reply_xdrs, reply_buf, &reply_all); goto sent_reply; break; @@ -708,8 +641,7 @@ nis_process_request(struct plugin_state *state, int client, accepted->ar_results.where = (caddr_t) &reply_master; accepted->ar_results.proc = (xdrproc_t) xdr_ypresp_master; /* Call the real function. */ - nis_master(state, client, client_addr, client_addrlen, - &request_xdrs, + nis_master(state, cdata, &request_xdrs, &reply, &reply_xdrs, reply_buf, &reply_master); goto sent_reply; break; @@ -722,7 +654,7 @@ nis_process_request(struct plugin_state *state, int client, accepted->ar_results.where = (caddr_t) &reply_order; accepted->ar_results.proc = (xdrproc_t) xdr_ypresp_order; /* Call the real function. */ - nis_order(state, client, client_addr, client_addrlen, + nis_order(state, cdata, &request_xdrs, &reply, &reply_xdrs, reply_buf, &reply_order); goto sent_reply; @@ -736,8 +668,7 @@ nis_process_request(struct plugin_state *state, int client, accepted->ar_results.where = (caddr_t) &reply_maplist; accepted->ar_results.proc = (xdrproc_t) xdr_ypresp_maplist; /* Call the real function. */ - nis_maplist(state, client, client_addr, client_addrlen, - &request_xdrs, + nis_maplist(state, cdata, &request_xdrs, &reply, &reply_xdrs, reply_buf, &reply_maplist); goto sent_reply; break; @@ -751,8 +682,7 @@ nis_process_request(struct plugin_state *state, int client, } send_reply: - dispatch_reply(state, client, client_addr, client_addrlen, - &reply, &reply_xdrs, reply_buf); + dispatch_reply(state, cdata, &reply, &reply_xdrs, reply_buf); sent_reply: xdr_destroy(&reply_xdrs); @@ -5,8 +5,9 @@ #include <sys/socket.h> #include "plugin.h" -void nis_process_request(struct plugin_state *state, int client, - struct sockaddr *client_addr, socklen_t client_addrlen, +struct dispatch_client_data; +void nis_process_request(struct plugin_state *state, + struct dispatch_client_data *cdata, char *request_buf, size_t request_buflen); #endif |