summaryrefslogtreecommitdiffstats
path: root/src/plug-nis.c
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin.dahyabhai@pobox.com>2009-02-11 18:20:18 -0500
committerNalin Dahyabhai <nalin.dahyabhai@pobox.com>2009-02-11 18:20:18 -0500
commit4118a0c053531ed45299318a5fcececcab94a314 (patch)
tree31404e85a01469c959e4a28f0395aee0f227d756 /src/plug-nis.c
parent6b5ca0df76e9a76059e549f710e58589026ffe83 (diff)
downloadslapi-nis-4118a0c053531ed45299318a5fcececcab94a314.tar.gz
slapi-nis-4118a0c053531ed45299318a5fcececcab94a314.tar.xz
slapi-nis-4118a0c053531ed45299318a5fcececcab94a314.zip
- use our own bind-reserve-port helper, which should work with either
ipv4 or ipv6 sockets - make portmap_register()/portmap_unregister() require the address family
Diffstat (limited to 'src/plug-nis.c')
-rw-r--r--src/plug-nis.c124
1 files changed, 79 insertions, 45 deletions
diff --git a/src/plug-nis.c b/src/plug-nis.c
index ae01984..19ff1dc 100644
--- a/src/plug-nis.c
+++ b/src/plug-nis.c
@@ -36,7 +36,6 @@
#include <unistd.h>
#include <rpc/rpc.h>
-#include <rpc/pmap_clnt.h>
#include <rpcsvc/yp_prot.h>
#ifdef HAVE_TCPD_H
@@ -98,9 +97,12 @@ plugin_startup(Slapi_PBlock *pb)
/* Kick off any other NIS servers on the local box. */
portmap_unregister(plugin_description.spd_id,
state->pmap_client_socket,
- YPPROG, YPVERS);
+ YPPROG, YPVERS, AF_INET);
/* 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,12 +122,18 @@ plugin_startup(Slapi_PBlock *pb)
}
if (!portmap_register(plugin_description.spd_id,
state->pmap_client_socket,
- YPPROG, YPVERS, protocol,
+ YPPROG, YPVERS,
+ AF_INET, protocol,
state->listener[i].port)) {
slapi_log_error(SLAPI_LOG_PLUGIN,
plugin_description.spd_id,
"error registering %s service "
"with portmap\n", pname);
+ } else {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ plugin_description.spd_id,
+ "registered %s service "
+ "with portmap\n", pname);
}
}
}
@@ -143,12 +151,14 @@ plugin_shutdown(Slapi_PBlock *pb)
slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
for (i = 0; i < state->n_listeners; i++) {
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);
+ state->pmap_client_socket,
+ YPPROG, YPVERS, AF_INET);
}
wrap_stop_thread(state->tid);
map_done(state);
@@ -186,6 +196,53 @@ 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
@@ -238,9 +295,7 @@ plugin_state_init(Slapi_PBlock *pb, struct plugin_state **lstate)
"error allocating portmap client socket\n");
goto failed;
}
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- if (bindresvport(sockfd, &sin) != 0) {
+ 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,
@@ -248,6 +303,7 @@ plugin_state_init(Slapi_PBlock *pb, struct plugin_state **lstate)
"error binding portmap client socket "
"to a privileged port\n");
close(sockfd);
+ sockfd = -1;
goto failed;
} else {
slapi_log_error(SLAPI_LOG_PLUGIN,
@@ -268,10 +324,10 @@ plugin_state_init(Slapi_PBlock *pb, struct plugin_state **lstate)
const char *sock_desc;
/* Figure out what kind of socket we need, and a textual
* term to use in log messages. */
- pf = (i & 2) ? PF_INET6 : PF_INET;
+ pf = (i & 2) ? PF_INET : PF_INET6;
type = (i & 1) ? SOCK_STREAM : SOCK_DGRAM;
- sock_desc = (i & 2) ? ((i & 1) ? "tcp6" : "udp6") :
- ((i & 1) ? "tcp" : "udp");
+ sock_desc = (i & 2) ? ((i & 1) ? "tcp" : "udp") :
+ ((i & 1) ? "tcp6" : "udp6");
/* Allocate the socket. */
sockfd = socket(pf, type, 0);
if (sockfd == -1) {
@@ -290,19 +346,22 @@ plugin_state_init(Slapi_PBlock *pb, struct plugin_state **lstate)
"error marking %s socket for reuse, "
"continuing\n", sock_desc);
close(sockfd);
- goto failed;
+ continue;
}
- /* Bind to the server port, if one was specified, otherwise let
- * libc try to find an unused one for us. */
+ /* Bind to the server port, if one was specified, otherwise try
+ * to find an unused one. */
memset(&sin, 0, sizeof(sin));
memset(&sin6, 0, sizeof(sin6));
sin.sin_family = AF_INET;
sin6.sin6_family = AF_INET6;
if (port == 0) {
- ret = (pf == PF_INET6) ? bindresvport(sockfd,
- (struct sockaddr_in*) &sin6) :
- bindresvport(sockfd,
- &sin);
+ port = (pf == PF_INET6) ? plugin_bind_resvport(sockfd,
+ AF_INET6,
+ 0) :
+ plugin_bind_resvport(sockfd,
+ AF_INET,
+ 0);
+ ret = (port > 0) ? 0 : -1;
} else {
sin.sin_port = htons(port);
sin6.sin6_port = htons(port);
@@ -340,39 +399,12 @@ plugin_state_init(Slapi_PBlock *pb, struct plugin_state **lstate)
strerror(errno));
continue;
}
- } else {
- /* Try to read back the bound address. */
- socklen_t socklen;
- if (getsockname(sockfd,
- (pf == PF_INET6) ?
- (struct sockaddr*) &sin6 :
- (struct sockaddr*) &sin,
- &socklen) != 0) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "error retrieving local "
- "socket address: %s\n",
- strerror(errno));
- }
- if (socklen !=
- (pf == PF_INET6) ? sizeof(sin6) : sizeof(sin)) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "error retrieving local "
- "socket address: %s\n",
- strerror(errno));
- }
-
}
flags = fcntl(sockfd, F_GETFL);
if ((flags & O_NONBLOCK) == 0) {
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
}
- /* Read the port number that we ended up using, in case we used
- * bindresvport[6]. */
- port = (pf == PF_INET6) ? ntohs(sin6.sin6_port) :
- ntohs(sin.sin_port);
- /* If it's a listening socket, let the kernel know that we're
+ /* If it's a stream socket, let the kernel know that we're
* ready to accept client connections. */
if (type == SOCK_STREAM) {
if (listen(sockfd, 128) == -1) {
@@ -406,9 +438,11 @@ plugin_state_init(Slapi_PBlock *pb, struct plugin_state **lstate)
failed:
for (i = 0; i < state->n_listeners; i++) {
close(state->listener[i].fd);
+ state->listener[i].fd = -1;
}
if (state->pmap_client_socket != -1) {
close(state->pmap_client_socket);
+ state->pmap_client_socket = -1;
}
err = errno;
free(state);