diff options
Diffstat (limited to 'src/plugin.c')
-rw-r--r-- | src/plugin.c | 318 |
1 files changed, 157 insertions, 161 deletions
diff --git a/src/plugin.c b/src/plugin.c index 885ccde..333dbee 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -22,155 +22,37 @@ #include <plarenas.h> #include <dirsrv/slapi-plugin.h> +#include "portmap.h" +#include "schema.h" + #define PACKAGE_VERSION "0.0" #define PORT 388 /* the module initialization function */ static Slapi_PluginDesc plugin_description = { - .spd_id = "my-plugin", + .spd_id = "nis-plugin", .spd_vendor = "hamdingers.org", .spd_version = PACKAGE_VERSION, - .spd_description = "sample plugin", -}; -struct domain { - char *domain; - struct map { - char *name; - char *key; - char *format; - } *maps; - int n_maps; + .spd_description = "NIS Service Plugin", }; -struct state { + +struct plugin_state { + PLArenaPool *arena; pthread_t tid; Slapi_ComponentId *plugin_identity; - PLArenaPool *arena; - int listeners; + int resvport; + int n_listeners; int listenfd[4]; int sock_pf[4]; int sock_type[4]; }; + struct search_stream_data { - struct state *state; + struct plugin_state *state; int client; }; -struct map default_maps[] = { - {"passwd.byname", "uid", "uid"}, - {"passwd.bynumber", "uidNumber", "uid"}, -}; -struct domain local_domains = { - ".local", - default_maps, - sizeof(default_maps) / sizeof(default_maps[0]), -}; - -static int -setup_listeners(struct state **lstate) -{ - int sockfd = -1, err, i; - struct sockaddr_in addr4; - struct sockaddr_in6 addr6; - struct state *state; - PLArenaPool *arena = NULL; - - arena = PORT_NewArena(sizeof(double)); - if (arena == NULL) { - goto failed; - } - state = PORT_ArenaZAlloc(arena, sizeof(*state)); - if (state == NULL) { - goto failed; - } - state->arena = arena; - - for (i = 0; i < 4; i++) { - int sock_pf, sock_type, one = 1; - struct sockaddr *addr; - socklen_t addrlen; - switch (i) { - case 0: - sock_pf = PF_INET; - sock_type = SOCK_DGRAM; - addr = (struct sockaddr *) &addr4; - addrlen = sizeof(addr4); - break; - case 1: - sock_pf = PF_INET; - sock_type = SOCK_STREAM; - addr = (struct sockaddr *) &addr4; - addrlen = sizeof(addr4); - break; - case 2: - sock_pf = PF_INET6; - sock_type = SOCK_DGRAM; - addr = (struct sockaddr *) &addr6; - addrlen = sizeof(addr6); - break; - case 3: - sock_pf = PF_INET6; - sock_type = SOCK_STREAM; - addr = (struct sockaddr *) &addr6; - addrlen = sizeof(addr6); - break; - } - memset(&addr4, 0, sizeof(addr4)); - addr4.sin_port = htons(PORT); - memset(&addr6, 0, sizeof(addr6)); - addr6.sin6_port = htons(PORT); - sockfd = socket(sock_pf, sock_type, 0); - if (sockfd == -1) { - slapi_log_error(SLAPI_LOG_PLUGIN, - plugin_description.spd_id, - "error creating a listening socket\n"); - continue; - } - if (setsockopt(sockfd, IPPROTO_IP, SO_REUSEADDR, - &one, sizeof(one)) != 0) { - slapi_log_error(SLAPI_LOG_PLUGIN, - plugin_description.spd_id, - "error marking socket for reuse\n"); - } - if (bind(sockfd, addr, addrlen) != 0) { - slapi_log_error(SLAPI_LOG_PLUGIN, - plugin_description.spd_id, - "error binding to listening port\n"); - close(sockfd); - continue; - } - if ((sock_type == SOCK_STREAM) && (listen(sockfd, 128) == -1)) { - slapi_log_error(SLAPI_LOG_PLUGIN, - plugin_description.spd_id, - "error marking socket for listening\n"); - close(sockfd); - continue; - } - state->listenfd[state->listeners] = sockfd; - state->sock_pf[state->listeners] = sock_pf; - state->sock_type[state->listeners] = sock_type; - slapi_log_error(SLAPI_LOG_PLUGIN, - plugin_description.spd_id, - "listening on port %d for %s%s clients\n", - PORT, - sock_type == SOCK_STREAM ? "tcp" : "udp", - sock_pf == PF_INET6 ? "6" : ""); - state->listeners++; - } - slapi_log_error(SLAPI_LOG_PLUGIN, - plugin_description.spd_id, - "set up %d listening sockets\n", state->listeners); - *lstate = state; - return 0; -failed: - err = errno; - if (arena != NULL) { - PORT_FreeArena(arena, PR_TRUE); - } - errno = err; - return -1; -} - static void cb_stream_result(int rc, void *callback_data) { @@ -231,7 +113,7 @@ cb_stream_referral(char *referral, void *callback_data) } static void -handle_stream_client(struct state *state, int client) +handle_stream_client(struct plugin_state *state, int client) { Slapi_PBlock *pblock; int i; @@ -262,7 +144,7 @@ handle_stream_client(struct state *state, int client) } static void -handle_dgram_client(struct state *state, int sockfd, +handle_dgram_client(struct plugin_state *state, int sockfd, char *dgram, int dgram_size, struct sockaddr *client_addr, socklen_t client_addrlen) { @@ -375,7 +257,7 @@ handle_dgram_client(struct state *state, int sockfd, "domain(%s)? ", p); reply.rm_reply.rp_stat = MSG_ACCEPTED; reply.rm_reply.rp_acpt.ar_stat = SUCCESS; - bool_ret = strcmp(p, ".local") == 0; + bool_ret = schema_supports_domain(p); reply.rm_reply.rp_acpt.ar_results.where = &bool_ret; reply.rm_reply.rp_acpt.ar_results.proc = xdr_bool; if ((request.rm_call.cb_proc == YPPROC_DOMAIN_NONACK) && @@ -580,7 +462,7 @@ handle_dgram_client(struct state *state, int sockfd, } static void -handle_stream_client_new(struct state *state, int client) +handle_stream_client_new(struct plugin_state *state, int client) { int i, last, ret; int32_t len; @@ -623,7 +505,7 @@ handle_stream_client_new(struct state *state, int client) static void * process_requests(void *p) { - struct state *state = p; + struct plugin_state *state = p; struct pollfd fds[4]; int client, i; char dgram[65536]; @@ -631,18 +513,18 @@ process_requests(void *p) socklen_t client_addrlen; for (;;) { memset(&fds, 0, sizeof(fds)); - for (i = 0; i < state->listeners; i++) { + for (i = 0; i < state->n_listeners; i++) { fds[i].fd = state->listenfd[i]; fds[i].events = POLLIN; } - switch (poll(fds, state->listeners, -1) != -1) { + switch (poll(fds, state->n_listeners, -1) != -1) { case -1: return NULL; break; case 0: continue; default: - for (i = 0; i < state->listeners; i++) { + for (i = 0; i < state->n_listeners; i++) { if ((fds[i].revents & POLLIN) == 0) { continue; } @@ -683,14 +565,24 @@ process_requests(void *p) return state; } -/* Set up the plugin. */ +/* Start the plugin's work thread. */ static int plugin_start(Slapi_PBlock *pb) { - struct state *state; + struct plugin_state *state; slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state); slapi_log_error(SLAPI_LOG_PLUGIN, "plugin_start", "plugin starting\n"); + if (portmap_register(state->resvport, YPPROG, YPVERS, + IPPROTO_TCP, PORT)) { + slapi_log_error(SLAPI_LOG_PLUGIN, plugin_description.spd_id, + "error registering with portmap\n"); + } + if (portmap_register(state->resvport, YPPROG, YPVERS, + IPPROTO_UDP, PORT)) { + slapi_log_error(SLAPI_LOG_PLUGIN, plugin_description.spd_id, + "error registering with portmap\n"); + } if (pthread_create(&state->tid, NULL, &process_requests, state) != 0) { slapi_log_error(SLAPI_LOG_PLUGIN, plugin_description.spd_id, "error starting listener thread\n"); @@ -700,23 +592,139 @@ plugin_start(Slapi_PBlock *pb) "plugin started\n"); return 0; } -/* Prepare for shutdown. */ + +/* Stop the plugin's work thread. */ static int plugin_close(Slapi_PBlock *pb) { - if (pmap_unset(YPPROG, YPVERS) != 1) { - slapi_log_error(SLAPI_LOG_PLUGIN, "plugin_start", - "error unregistering ports, continuing\n"); + struct plugin_state *state; + slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state); + portmap_unregister(state->resvport, YPPROG, YPVERS); + return 0; +} + +static int +setup_listeners(struct plugin_state **lstate) +{ + int sockfd = -1, err, i; + struct sockaddr_in addr4; + struct sockaddr_in6 addr6; + struct plugin_state *state; + PLArenaPool *arena = NULL; + + arena = PORT_NewArena(sizeof(double)); + if (arena == NULL) { + goto failed; } - slapi_log_error(SLAPI_LOG_PLUGIN, "my_init_function", - "plugin closing\n"); + state = PORT_ArenaZAlloc(arena, sizeof(*state)); + if (state == NULL) { + goto failed; + } + state->arena = arena; + state->resvport = -1; + + for (i = 0; i < 4; i++) { + int sock_pf, sock_type, one = 1; + struct sockaddr *addr; + socklen_t addrlen; + const char *sock_desc; + switch (i) { + case 0: + sock_pf = PF_INET; + sock_type = SOCK_DGRAM; + addr = (struct sockaddr *) &addr4; + addrlen = sizeof(addr4); + sock_desc = "udp"; + break; + case 1: + sock_pf = PF_INET; + sock_type = SOCK_STREAM; + addr = (struct sockaddr *) &addr4; + addrlen = sizeof(addr4); + sock_desc = "tcp"; + break; + case 2: + sock_pf = PF_INET6; + sock_type = SOCK_DGRAM; + addr = (struct sockaddr *) &addr6; + addrlen = sizeof(addr6); + sock_desc = "udp6"; + break; + case 3: + sock_pf = PF_INET6; + sock_type = SOCK_STREAM; + addr = (struct sockaddr *) &addr6; + addrlen = sizeof(addr6); + sock_desc = "tcp6"; + break; + } + memset(&addr4, 0, sizeof(addr4)); + addr4.sin_port = htons(PORT); + memset(&addr6, 0, sizeof(addr6)); + addr6.sin6_port = htons(PORT); + sockfd = socket(sock_pf, sock_type, 0); + if (sockfd == -1) { + slapi_log_error(SLAPI_LOG_PLUGIN, + plugin_description.spd_id, + "error creating a %s socket\n", + sock_desc); + continue; + } + if (setsockopt(sockfd, IPPROTO_IP, SO_REUSEADDR, + &one, sizeof(one)) != 0) { + slapi_log_error(SLAPI_LOG_PLUGIN, + plugin_description.spd_id, + "error marking %s socket for reuse\n", + sock_desc); + } + if (bind(sockfd, addr, addrlen) != 0) { + slapi_log_error(SLAPI_LOG_PLUGIN, + plugin_description.spd_id, + "error binding %s socket to port\n", + sock_desc); + close(sockfd); + continue; + } + if ((sock_type == SOCK_STREAM) && (listen(sockfd, 128) == -1)) { + slapi_log_error(SLAPI_LOG_PLUGIN, + plugin_description.spd_id, + "error marking %s socket for " + "listening\n", sock_desc); + close(sockfd); + continue; + } + if (i == 0) { + state->resvport = sockfd; + } + state->listenfd[state->n_listeners] = sockfd; + state->sock_pf[state->n_listeners] = sock_pf; + state->sock_type[state->n_listeners] = sock_type; + slapi_log_error(SLAPI_LOG_PLUGIN, + plugin_description.spd_id, + "listening on port %d for %s%s clients\n", + PORT, + sock_type == SOCK_STREAM ? "tcp" : "udp", + sock_pf == PF_INET6 ? "6" : ""); + state->n_listeners++; + } + slapi_log_error(SLAPI_LOG_PLUGIN, + plugin_description.spd_id, + "set up %d listening sockets\n", state->n_listeners); + *lstate = state; return 0; +failed: + err = errno; + if (arena != NULL) { + PORT_FreeArena(arena, PR_TRUE); + } + errno = err; + return -1; } int -my_init_function(Slapi_PBlock *pb) +nis_plugin_init(Slapi_PBlock *pb) { - struct state *state; + struct plugin_state *state = NULL; if (setup_listeners(&state) == -1) { slapi_log_error(SLAPI_LOG_PLUGIN, plugin_description.spd_id, "error setting up listening sockets\n"); @@ -728,19 +736,7 @@ my_init_function(Slapi_PBlock *pb) slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN, &plugin_close); slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &state->plugin_identity); slapi_pblock_set(pb, SLAPI_PLUGIN_PRIVATE, state); - if (pmap_unset(YPPROG, YPVERS) != 1) { - slapi_log_error(SLAPI_LOG_PLUGIN, "plugin_start", - "error clearing registrations, continuing\n"); - } - if (pmap_set(YPPROG, YPVERS, IPPROTO_TCP, PORT) != 1) { - slapi_log_error(SLAPI_LOG_PLUGIN, "plugin_start", - "error registering TCP port, continuing\n"); - } - if (pmap_set(YPPROG, YPVERS, IPPROTO_UDP, PORT) != 1) { - slapi_log_error(SLAPI_LOG_PLUGIN, "plugin_start", - "error registering UDP port, continuing\n"); - } slapi_log_error(SLAPI_LOG_PLUGIN, plugin_description.spd_id, - "registering plugin hooks\n"); + "registered plugin hooks\n"); return 0; } |