summaryrefslogtreecommitdiffstats
path: root/src/plug-nis.c
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin.dahyabhai@pobox.com>2009-02-12 18:20:27 -0500
committerNalin Dahyabhai <nalin.dahyabhai@pobox.com>2009-02-12 18:20:27 -0500
commitd3891722e10fd0689577833b2d5e394a8fa78e1b (patch)
tree66833f485fe20187a96687ccdc9f94f04eae9d1d /src/plug-nis.c
parentcf84389cd2d9063467d8c5fa0b66b9487d59020c (diff)
downloadslapi-nis-d3891722e10fd0689577833b2d5e394a8fa78e1b.tar.gz
slapi-nis-d3891722e10fd0689577833b2d5e394a8fa78e1b.tar.xz
slapi-nis-d3891722e10fd0689577833b2d5e394a8fa78e1b.zip
- handle argument order and count changing for portmap registration functions
- pass IPPROTO_XXX instead of SOCK_XXX to registration function - if we're registering/unregistering IPv6, also register/unregister IPv4
Diffstat (limited to 'src/plug-nis.c')
-rw-r--r--src/plug-nis.c181
1 files changed, 66 insertions, 115 deletions
diff --git a/src/plug-nis.c b/src/plug-nis.c
index 8e0b203..1305cf9 100644
--- a/src/plug-nis.c
+++ b/src/plug-nis.c
@@ -94,18 +94,25 @@ plugin_startup(Slapi_PBlock *pb)
}
/* Register the listener sockets with the portmapper. */
if (state->pmap_client_socket != -1) {
- /* Kick off any other NIS servers on the local box. */
+ /* Try to kick off any other NIS servers on the local box. */
portmap_unregister(plugin_description.spd_id,
state->pmap_client_socket,
- YPPROG, YPVERS, AF_INET, IPPROTO_TCP);
+ YPPROG, YPVERS,
+ AF_INET6, IPPROTO_TCP, 0);
portmap_unregister(plugin_description.spd_id,
state->pmap_client_socket,
- YPPROG, YPVERS, AF_INET, IPPROTO_UDP);
+ YPPROG, YPVERS,
+ AF_INET6, IPPROTO_UDP, 0);
+ portmap_unregister(plugin_description.spd_id,
+ state->pmap_client_socket,
+ YPPROG, YPVERS,
+ AF_INET, IPPROTO_TCP, 0);
+ portmap_unregister(plugin_description.spd_id,
+ state->pmap_client_socket,
+ YPPROG, YPVERS,
+ AF_INET, IPPROTO_UDP, 0);
/* Register our listening ports. */
for (i = 0; i < state->n_listeners; i++) {
- if (state->listener[i].pf != PF_INET) {
- continue;
- }
switch (state->listener[i].type) {
case SOCK_DGRAM:
protocol = IPPROTO_UDP;
@@ -120,13 +127,11 @@ plugin_startup(Slapi_PBlock *pb)
assert(0);
break;
}
- if (protocol == IPPROTO_IP) {
- continue;
- }
if (!portmap_register(plugin_description.spd_id,
state->pmap_client_socket,
YPPROG, YPVERS,
- AF_INET, protocol,
+ state->listener[i].pf,
+ protocol,
state->listener[i].port)) {
slapi_log_error(SLAPI_LOG_PLUGIN,
plugin_description.spd_id,
@@ -137,6 +142,17 @@ plugin_startup(Slapi_PBlock *pb)
plugin_description.spd_id,
"registered %s service "
"with portmap\n", pname);
+ /* If it's an IPv6 service, then it can also
+ * accept connections from IPv4 clients, so
+ * register for them, too. */
+ if (state->listener[i].pf == AF_INET6) {
+ portmap_register(plugin_description.spd_id,
+ state->pmap_client_socket,
+ YPPROG, YPVERS,
+ AF_INET,
+ protocol,
+ state->listener[i].port);
+ }
}
}
}
@@ -150,22 +166,41 @@ static int
plugin_shutdown(Slapi_PBlock *pb)
{
struct plugin_state *state;
- int i;
+ int i, protocol;
slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
for (i = 0; i < state->n_listeners; i++) {
+ if (state->pmap_client_socket != -1) {
+ switch (state->listener[i].type) {
+ case SOCK_DGRAM:
+ protocol = IPPROTO_UDP;
+ break;
+ case SOCK_STREAM:
+ protocol = IPPROTO_TCP;
+ break;
+ default:
+ /* never reached */
+ assert(0);
+ break;
+ }
+ portmap_unregister(plugin_description.spd_id,
+ state->pmap_client_socket,
+ YPPROG, YPVERS,
+ state->listener[i].pf,
+ protocol,
+ state->listener[i].port);
+ if (state->listener[i].pf == AF_INET6) {
+ portmap_unregister(plugin_description.spd_id,
+ state->pmap_client_socket,
+ YPPROG, YPVERS,
+ AF_INET,
+ protocol,
+ state->listener[i].port);
+ }
+ }
close(state->listener[i].fd);
state->listener[i].fd = -1;
}
state->n_listeners = 0;
- if (state->pmap_client_socket != -1) {
- /* Clear our registration with the portmapper. */
- portmap_unregister(plugin_description.spd_id,
- state->pmap_client_socket,
- YPPROG, YPVERS, AF_INET, IPPROTO_TCP);
- portmap_unregister(plugin_description.spd_id,
- state->pmap_client_socket,
- YPPROG, YPVERS, AF_INET, IPPROTO_UDP);
- }
wrap_stop_thread(state->tid);
map_done(state);
#ifdef HAVE_TCPD_H
@@ -202,53 +237,6 @@ plugin_read_config(Slapi_PBlock *plugin_pb, int *port)
}
}
-/* Bind to a privileged port. We don't much care which one at this point. */
-static int
-plugin_bind_resvport(int fd, int family, int but_not)
-{
- int i, offset, port;
- struct sockaddr_in sin;
- struct sockaddr_in6 sin6;
- switch (family) {
- case AF_INET:
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- break;
- case AF_INET6:
- memset(&sin6, 0, sizeof(sin6));
- sin6.sin6_family = AF_INET6;
- break;
- default:
- return -1;
- }
- offset = getpid() % 512;
- for (i = 512; i < 1024; i++) {
- port = ((offset + i) % 512) + 512;
- if (port == but_not) {
- continue;
- }
- switch (family) {
- case AF_INET:
- sin.sin_port = htons(port);
- if (bind(fd, (struct sockaddr*) &sin,
- sizeof(sin)) == 0) {
- return port;
- }
- break;
- case AF_INET6:
- sin6.sin6_port = htons(port);
- if (bind(fd, (struct sockaddr*) &sin6,
- sizeof(sin6)) == 0) {
- return port;
- }
- break;
- default:
- return -1;
- }
- }
- return 0;
-}
-
/* Handle the part of startup that needs to be done before we drop privileges:
* bind to listening ports and one more for talking to the local portmapper. */
static int
@@ -296,55 +284,18 @@ plugin_state_init(Slapi_PBlock *pb, struct plugin_state **lstate)
#endif
/* Create a socket for use in communicating with the portmapper. */
-#ifdef HAVE_LIBTIRPC
- sockfd = socket(PF_LOCAL, SOCK_STREAM, 0);
- if (sockfd == -1) {
- slapi_log_error(SLAPI_LOG_FATAL, state->plugin_desc->spd_id,
- "error allocating portmap client socket\n");
- goto failed;
- }
- memset(&sockun, 0, sizeof(sockun));
- sockun.sun_family = AF_LOCAL;
- strcpy(sockun.sun_path, _PATH_RPCBINDSOCK);
- if (connect(sockfd, (struct sockaddr *) &sockun, sizeof(sockun)) != 0) {
- if ((getenv(NIS_PLUGIN_CONTINUE_WITHOUT_PORTMAP_ENV) == NULL) ||
- !atol(getenv(NIS_PLUGIN_CONTINUE_WITHOUT_PORTMAP_ENV))) {
- slapi_log_error(SLAPI_LOG_FATAL,
- state->plugin_desc->spd_id,
- "error connecting rpcbind client "
- "socket to the service\n");
- close(sockfd);
- sockfd = -1;
- goto failed;
- }
- }
-#else
- sockfd = socket(PF_INET, SOCK_DGRAM, 0);
+ sockfd = portmap_create_client_socket(state->plugin_desc->spd_id,
+ port);
if (sockfd == -1) {
- slapi_log_error(SLAPI_LOG_FATAL, state->plugin_desc->spd_id,
- "error allocating portmap client socket\n");
- goto failed;
- }
- if (plugin_bind_resvport(sockfd, AF_INET, port) <= 0) {
if ((getenv(NIS_PLUGIN_CONTINUE_WITHOUT_PORTMAP_ENV) == NULL) ||
!atol(getenv(NIS_PLUGIN_CONTINUE_WITHOUT_PORTMAP_ENV))) {
slapi_log_error(SLAPI_LOG_FATAL,
state->plugin_desc->spd_id,
- "error binding portmap client socket "
- "to a privileged port\n");
- close(sockfd);
- sockfd = -1;
+ "error creating portmap/rpcbind client "
+ "socket\n");
goto failed;
- } else {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "warning: unable to bind portmap "
- "client socket to a privileged port\n");
}
- close(sockfd);
- sockfd = -1;
}
-#endif
state->pmap_client_socket = sockfd;
/* We need to bind on privileged ports for both datagram and connected
@@ -356,7 +307,7 @@ plugin_state_init(Slapi_PBlock *pb, struct plugin_state **lstate)
/* Figure out what kind of socket we need, and a textual
* term to use in log messages. */
pf = (i & 2) ? PF_INET : PF_INET6;
- type = (i & 1) ? SOCK_STREAM : SOCK_DGRAM;
+ type = (i & 1) ? SOCK_DGRAM : SOCK_STREAM;
sock_desc = (i & 2) ? ((i & 1) ? "tcp" : "udp") :
((i & 1) ? "tcp6" : "udp6");
/* Allocate the socket. */
@@ -386,12 +337,12 @@ plugin_state_init(Slapi_PBlock *pb, struct plugin_state **lstate)
sin.sin_family = AF_INET;
sin6.sin6_family = AF_INET6;
if (port == 0) {
- port = (pf == PF_INET6) ? plugin_bind_resvport(sockfd,
- AF_INET6,
- 0) :
- plugin_bind_resvport(sockfd,
- AF_INET,
- 0);
+ port = (pf == PF_INET6) ? portmap_bind_resvport(sockfd,
+ AF_INET6,
+ 0) :
+ portmap_bind_resvport(sockfd,
+ AF_INET,
+ 0);
ret = (port > 0) ? 0 : -1;
} else {
sin.sin_port = htons(port);