summaryrefslogtreecommitdiffstats
path: root/src/portmap.c
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin.dahyabhai@pobox.com>2009-02-12 18:22:39 -0500
committerNalin Dahyabhai <nalin.dahyabhai@pobox.com>2009-02-12 18:22:39 -0500
commitb314b3233a7ade5e3f5878051327e9d97b94be7d (patch)
tree9ae852a35f641714964f9b71fa73693f298e5525 /src/portmap.c
parentee5ac71048481de548ffb8fe810c1b567d9a7a2f (diff)
downloadslapi-nis-b314b3233a7ade5e3f5878051327e9d97b94be7d.tar.gz
slapi-nis-b314b3233a7ade5e3f5878051327e9d97b94be7d.tar.xz
slapi-nis-b314b3233a7ade5e3f5878051327e9d97b94be7d.zip
- move client socket creation here, so that we don't have to know how to
do it elsewhere - refactor the send/receive logic out so that it can be used for either rpcbind or portmap - try to connect to rpcbind over a local socket first, else assume we have to use portmap over IP - use our own rpcb encode/decode function to avoid mixing the one from libtirpc with the rest of libc's XDR functions -- THAT WOULD BE BAD
Diffstat (limited to 'src/portmap.c')
-rw-r--r--src/portmap.c554
1 files changed, 372 insertions, 182 deletions
diff --git a/src/portmap.c b/src/portmap.c
index 3d56971..3213ac3 100644
--- a/src/portmap.c
+++ b/src/portmap.c
@@ -28,6 +28,7 @@
#include <errno.h>
#include <poll.h>
#include <time.h>
+#include <unistd.h>
#ifdef HAVE_DIRSRV_SLAPI_PLUGIN_H
#include <nspr.h>
@@ -39,14 +40,26 @@
#include <rpcsvc/yp_prot.h>
#include <rpc/xdr.h>
-#ifdef HAVE_LIBTIRPC
-#include <rpc/rpcb_prot.h>
-#else
#include <rpc/pmap_prot.h>
-#endif
#include "portmap.h"
+#ifndef RPCBPROG
+#define RPCBPROG PMAPPROG
+#endif
+#ifndef RPCBVERS
+#define RPCBVERS 3
+#endif
+#ifndef RPCBPROC_SET
+#define RPCBPROC_SET 1
+#endif
+#ifndef RPCBPROC_UNSET
+#define RPCBPROC_UNSET 2
+#endif
+#ifndef _PATH_RPCBINDSOCK
+#define _PATH_RPCBINDSOCK "/var/run/rpcbind.sock"
+#endif
+
#ifdef PORTMAP_MAIN
#include <stdarg.h>
#include <stdlib.h>
@@ -63,142 +76,72 @@ slapi_log_error(int i, char *f, char *fmt, ...)
int
main(int argc, char **argv)
{
- int s, ret;
- struct sockaddr_in sin;
+ int s, ret, port;
struct sockaddr_un sunaddr;
s = socket(PF_INET, SOCK_DGRAM, 0);
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- if (bindresvport(s, &sin) != 0) {
- printf("error binding to reserved port\n");
+ if ((port = portmap_bind_resvport(s, AF_INET, 0)) < 0) {
+ printf("error binding to reserved port, using 541\n");
+ port = 541; /* arbitrary */
} else {
- printf("bound to reserved port %d\n", ntohs(sin.sin_port));
+ printf("bound to reserved port %d\n", port);
}
-#ifdef HAVE_LIBTIRPC
- s = socket(AF_LOCAL, SOCK_STREAM, 0);
- memset(&sunaddr, 0, sizeof(sunaddr));
- sunaddr.sun_family = AF_LOCAL;
- strcpy(sunaddr.sun_path, _PATH_RPCBINDSOCK);
- connect(s, (struct sockaddr *) &sunaddr, sizeof(sunaddr));
-#endif
+ s = portmap_create_client_socket("portmap", port);
+ setregid(2516, 2516);
setreuid(2510, 2510);
+ portmap_unregister("portmap", s, YPPROG, YPVERS, AF_INET, IPPROTO_TCP,
+ 0);
+ portmap_unregister("portmap", s, YPPROG, YPVERS, AF_INET, IPPROTO_UDP,
+ 0);
+ portmap_unregister("portmap", s, YPPROG, YPVERS, AF_INET6, IPPROTO_TCP,
+ 0);
+ portmap_unregister("portmap", s, YPPROG, YPVERS, AF_INET6, IPPROTO_UDP,
+ 0);
portmap_register("portmap", s, YPPROG, YPVERS, AF_INET, IPPROTO_TCP,
- ntohs(sin.sin_port));
+ port);
portmap_register("portmap", s, YPPROG, YPVERS, AF_INET, IPPROTO_UDP,
- ntohs(sin.sin_port));
+ port);
portmap_register("portmap", s, YPPROG, YPVERS, AF_INET6, IPPROTO_TCP,
- ntohs(sin.sin_port));
+ port);
portmap_register("portmap", s, YPPROG, YPVERS, AF_INET6, IPPROTO_UDP,
- ntohs(sin.sin_port));
+ port);
ret = system("rpcinfo | grep ypserv");
ret = system("rpcinfo -p | grep ypserv");
- portmap_unregister("portmap", s, YPPROG, YPVERS, AF_INET, IPPROTO_TCP);
- portmap_unregister("portmap", s, YPPROG, YPVERS, AF_INET, IPPROTO_UDP);
- portmap_unregister("portmap", s, YPPROG, YPVERS, AF_INET6, IPPROTO_TCP);
- portmap_unregister("portmap", s, YPPROG, YPVERS, AF_INET6, IPPROTO_UDP);
+ portmap_unregister("portmap", s, YPPROG, YPVERS, AF_INET, IPPROTO_TCP,
+ port);
+ portmap_unregister("portmap", s, YPPROG, YPVERS, AF_INET, IPPROTO_UDP,
+ port);
+ portmap_unregister("portmap", s, YPPROG, YPVERS, AF_INET6, IPPROTO_TCP,
+ port);
+ portmap_unregister("portmap", s, YPPROG, YPVERS, AF_INET6, IPPROTO_UDP,
+ port);
return 0;
}
#endif
static bool_t
-portmap_register_work(const char *module, int resv_sock,
- int program, int version,
- int family, int protocol, int port,
- bool_t create)
+portmap_register_work(const char *module, int client_sock,
+ bool_t stream,
+ struct sockaddr *dgram_address, socklen_t addrlen,
+ int prog, int vers, int proc,
+ void *args, xdrproc_t args_xdr)
{
char portmap_buf[4000], auth_buf[4000], reply_buf[8000], *log_id;
int portmap_length, reply_length;
AUTH *auth;
XDR portmap_xdrs, auth_xdrs;
struct rpc_msg msg;
-#ifdef HAVE_LIBTIRPC
- char address_buf[32];
- struct rpcb rpcb;
int fragment_length;
-#else
- struct pmap map;
-#endif
- int prog, vers, proc;
bool_t ret = FALSE;
struct sockaddr addr;
- struct sockaddr_in addr4;
- struct sockaddr_in6 addr6;
- struct sockaddr_un addrun;
- union {
- struct sockaddr_in addr4;
- } client_addr;
- socklen_t client_addrlen;
struct pollfd pollfd;
int i;
static u_long xid;
log_id = (char *) module;
- memset(&addr, 0, sizeof(addr));
- addr.sa_family = AF_UNSPEC;
-
- /* Populate the arguments for this request. */
-#ifdef HAVE_LIBTIRPC
- rpcb.r_prog = program;
- rpcb.r_vers = version;
- rpcb.r_owner = module;
- switch (family) {
- case AF_INET:
- snprintf(address_buf, sizeof(address_buf), "0.0.0.0.%d.%d",
- (port >> 8) & 0xff, port & 0xff);
- switch (protocol) {
- case IPPROTO_TCP:
- rpcb.r_netid = "tcp";
- rpcb.r_addr = address_buf;
- break;
- case IPPROTO_UDP:
- rpcb.r_netid = "udp";
- rpcb.r_addr = address_buf;
- break;
- default:
- rpcb.r_netid = NULL;
- rpcb.r_addr = NULL;
- break;
- }
- break;
- case AF_INET6:
- snprintf(address_buf, sizeof(address_buf), "::.%d.%d",
- (port >> 8) & 0xff, port & 0xff);
- switch (protocol) {
- case IPPROTO_TCP:
- rpcb.r_netid = "tcp6";
- rpcb.r_addr = address_buf;
- break;
- case IPPROTO_UDP:
- rpcb.r_netid = "udp6";
- rpcb.r_addr = address_buf;
- break;
- default:
- rpcb.r_netid = NULL;
- rpcb.r_addr = NULL;
- break;
- }
- break;
- default:
- rpcb.r_netid = NULL;
- rpcb.r_addr = NULL;
- break;
- }
- prog = RPCBPROG;
- vers = RPCBVERS;
- proc = create ? RPCBPROC_SET : RPCBPROC_UNSET;
-#else
- map.pm_prog = program;
- map.pm_vers = version;
- map.pm_prot = protocol;
- map.pm_port = port;
- prog = PMAPPROG;
- vers = PMAPVERS;
- proc = create ? PMAPPROC_SET : PMAPPROC_UNSET;
-#endif
/* Build the RPC header. */
memset(&msg, 0, sizeof(msg));
- msg.rm_xid = xid = (time(NULL) ^ port ^ protocol ^ proc);
+ msg.rm_xid = xid = (time(NULL) ^ prog ^ vers ^ proc ^ getpid());
msg.rm_direction = CALL;
msg.rm_call.cb_rpcvers = 2;
msg.rm_call.cb_prog = prog;
@@ -213,93 +156,102 @@ portmap_register_work(const char *module, int resv_sock,
msg.rm_call.cb_verf = auth->ah_verf;
/* Encode the header and the arguments, then clean up temporaries. */
-#ifdef HAVE_LIBTIRPC
- xdrmem_create(&portmap_xdrs, portmap_buf + 4, sizeof(portmap_buf) - 4,
- XDR_ENCODE);
-#else
- xdrmem_create(&portmap_xdrs, portmap_buf, sizeof(portmap_buf),
- XDR_ENCODE);
-#endif
+ if (stream) {
+ /* Leave room for the message length on a stream connection. */
+ xdrmem_create(&portmap_xdrs,
+ portmap_buf + 4, sizeof(portmap_buf) - 4,
+ XDR_ENCODE);
+ } else {
+ /* Straight-up datagram. */
+ xdrmem_create(&portmap_xdrs, portmap_buf, sizeof(portmap_buf),
+ XDR_ENCODE);
+ }
+
+ /* Encode the message header and the call itself. */
xdr_callmsg(&portmap_xdrs, &msg);
-#ifdef HAVE_LIBTIRPC
- xdr_rpcb(&portmap_xdrs, &rpcb);
-#else
- xdr_pmap(&portmap_xdrs, &map);
-#endif
+ portmap_length = xdr_getpos(&portmap_xdrs);
+ (*args_xdr)(&portmap_xdrs, args);
+ slapi_log_error(SLAPI_LOG_PLUGIN, log_id,
+ "encoded %d bytes of args\n",
+ xdr_getpos(&portmap_xdrs) - portmap_length);
portmap_length = xdr_getpos(&portmap_xdrs);
auth_destroy(auth);
xdr_destroy(&auth_xdrs);
xdr_destroy(&portmap_xdrs);
memset(&portmap_xdrs, 0, sizeof(portmap_xdrs));
-#ifdef HAVE_LIBTIRPC
- /* Compute the message length and prepend it. */
- fragment_length = portmap_length;
- fragment_length |= 0x80000000;
- portmap_buf[0] = (fragment_length >> 24) & 0xff;
- portmap_buf[1] = (fragment_length >> 16) & 0xff;
- portmap_buf[2] = (fragment_length >> 8) & 0xff;
- portmap_buf[3] = (fragment_length >> 0) & 0xff;
- portmap_length += 4;
-#else
- /* "Connect" to the local portmapper. */
- memset(&addr4, 0, sizeof(addr4));
- addr4.sin_family = AF_INET;
- addr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- addr4.sin_port = htons(PMAPPORT);
- i = connect(resv_sock, (struct sockaddr*) &addr4, sizeof(addr4));
- if (i != 0) {
- slapi_log_error(SLAPI_LOG_PLUGIN, log_id,
- "error targeting portmap with sock %d: %s\n",
- resv_sock, strerror(errno));
- return FALSE;
+ if (stream) {
+ /* Compute the request message length and prepend it. */
+ fragment_length = portmap_length;
+ fragment_length |= 0x80000000;
+ portmap_buf[0] = (fragment_length >> 24) & 0xff;
+ portmap_buf[1] = (fragment_length >> 16) & 0xff;
+ portmap_buf[2] = (fragment_length >> 8) & 0xff;
+ portmap_buf[3] = (fragment_length >> 0) & 0xff;
+ portmap_length += 4;
+ } else {
+ /* Point the datagram socket at the remote. */
+ if (connect(client_sock, dgram_address, addrlen) != 0) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, log_id,
+ "error targeting portmap: %s\n",
+ strerror(errno));
+ return FALSE;
+ }
}
-#endif
- /* Transmit our request. Retry a few times if it doesn't go through. */
+ /* Transmit our request. Be ready to retry a few times if it doesn't
+ * go through for datagram connections. */
for (i = 1; i < 32; i *= 2) {
/* Try to send our request. If there's any problem,
* immediately retry. */
- if (send(resv_sock, &portmap_buf, portmap_length,
+ if (send(client_sock, &portmap_buf, portmap_length,
0) != portmap_length) {
slapi_log_error(SLAPI_LOG_PLUGIN, log_id,
- "error sending request to portmap\n");
- continue;
+ "error sending request to portmap or "
+ "rpcbind on %d: %s\n", client_sock,
+ strerror(errno));
+ if (stream) {
+ break;
+ } else {
+ continue;
+ }
}
/* Wait for a response. */
- pollfd.fd = resv_sock;
+ pollfd.fd = client_sock;
pollfd.events = POLLIN | POLLERR;
- if ((poll(&pollfd, 1, i * 1000) > 0) &&
+ if ((poll(&pollfd, 1, stream ? -1 : i * 1000) > 0) &&
(pollfd.revents & POLLIN)) {
/* Read the response. */
- client_addrlen = sizeof(client_addr);
- reply_length = recvfrom(resv_sock,
- reply_buf, sizeof(reply_buf), 0,
- (struct sockaddr *)&client_addr,
- &client_addrlen);
+ reply_length = recv(client_sock,
+ reply_buf, sizeof(reply_buf), 0);
/* Decode the response. */
if (reply_length > 0) {
/* Decode an RPC header and the returned
* boolean from the buffer. */
memset(&msg, 0, sizeof(msg));
-#ifdef HAVE_LIBTIRPC
- fragment_length = ((reply_buf[0] << 24) |
- (reply_buf[1] << 16) |
- (reply_buf[2] << 8) |
- (reply_buf[3] << 0)) &
- 0x7fffffff;
- if (fragment_length != reply_length - 4) {
- fprintf(stderr, "Bad reply length!\n");
+ if (stream) {
+ /* Strip off the fragment length. */
+ fragment_length = (reply_buf[0] << 24) |
+ (reply_buf[1] << 16) |
+ (reply_buf[2] << 8) |
+ (reply_buf[3] << 0);
+ if ((fragment_length & 0x80000000) == 0) {
+ /* XXX - if it's not the whole
+ * message, then we're screwed.
+ * */;
+ }
+ fragment_length &= 0x7fffffff;
+ xdrmem_create(&portmap_xdrs,
+ reply_buf + 4,
+ reply_length - 4,
+ XDR_DECODE);
+ } else {
+ /* Straight-up datagram. */
+ xdrmem_create(&portmap_xdrs,
+ reply_buf, reply_length,
+ XDR_DECODE);
}
- xdrmem_create(&portmap_xdrs,
- reply_buf + 4, reply_length - 4,
- XDR_DECODE);
-#else
- xdrmem_create(&portmap_xdrs,
- reply_buf, reply_length,
- XDR_DECODE);
-#endif
msg.rm_reply.rp_acpt.ar_results.where =
(caddr_t) &ret;
msg.rm_reply.rp_acpt.ar_results.proc =
@@ -317,15 +269,20 @@ portmap_register_work(const char *module, int resv_sock,
}
}
-#ifndef HAVE_LIBTIRPC
- /* Disconnect from the portmapper, but keep our socket around. */
- connect(resv_sock, &addr, sizeof(addr));
- if (i == 32) {
- slapi_log_error(SLAPI_LOG_PLUGIN, log_id,
- "timeout registering with portmap service\n");
- return FALSE;
+ if (!stream) {
+ /* "Disconnect" from a datagram service, but keep our client
+ * socket around. */
+ memset(&addr, 0, sizeof(addr));
+ addr.sa_family = AF_UNSPEC;
+ connect(client_sock, &addr, sizeof(addr));
+ /* Check for a timeout. */
+ if (i == 32) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, log_id,
+ "timeout registering with portmap "
+ "service\n");
+ return FALSE;
+ }
}
-#endif
/* Check that the portmapper didn't just reject the request out of
* hand. */
@@ -410,18 +367,251 @@ portmap_register_work(const char *module, int resv_sock,
return ret;
}
+struct rpcbind_req {
+ int program;
+ int version;
+ char *network;
+ char *address;
+ char *owner;
+};
+
+static bool_t
+portmap_xdr_rpcbind_req(XDR *xdrs, struct rpcbind_req *req)
+{
+ return xdr_int(xdrs, &req->program) &&
+ xdr_int(xdrs, &req->version) &&
+ xdr_wrapstring(xdrs, &req->network) &&
+ xdr_wrapstring(xdrs, &req->address) &&
+ xdr_wrapstring(xdrs, &req->owner);
+}
+
+static bool_t
+portmap_register_rpcbind(const char *module, int client_sock,
+ bool_t create,
+ int family, int protocol, int port,
+ int program, int version)
+{
+ char address_buf[64];
+ struct rpcbind_req req;
+ req.program = program;
+ req.version = version;
+ req.owner = "superuser";
+ switch (family) {
+ case AF_INET:
+ snprintf(address_buf, sizeof(address_buf), "0.0.0.0.%d.%d",
+ (port >> 8) & 0xff, port & 0xff);
+ switch (protocol) {
+ case IPPROTO_TCP:
+ req.network = "tcp";
+ req.address = address_buf;
+ break;
+ case IPPROTO_UDP:
+ req.network = "udp";
+ req.address = address_buf;
+ break;
+ default:
+ req.network = NULL;
+ req.address = NULL;
+ break;
+ }
+ break;
+ case AF_INET6:
+ snprintf(address_buf, sizeof(address_buf), "::.%d.%d",
+ (port >> 8) & 0xff, port & 0xff);
+ switch (protocol) {
+ case IPPROTO_TCP:
+ req.network = "tcp6";
+ req.address = address_buf;
+ break;
+ case IPPROTO_UDP:
+ req.network = "udp6";
+ req.address = address_buf;
+ break;
+ default:
+ req.network = NULL;
+ req.address = NULL;
+ break;
+ }
+ break;
+ default:
+ req.network = NULL;
+ req.address = NULL;
+ break;
+ }
+ return portmap_register_work(module, client_sock, TRUE, NULL, 0,
+ RPCBPROG, RPCBVERS,
+ create ? RPCBPROC_SET : RPCBPROC_UNSET,
+ &req,
+ (xdrproc_t) &portmap_xdr_rpcbind_req);
+}
+
+static bool_t
+portmap_register_portmap(const char *module, int client_sock,
+ bool_t create,
+ int protocol, int port, int program, int version)
+{
+ struct pmap map;
+ struct sockaddr_in sin;
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = INADDR_LOOPBACK;
+ sin.sin_port = htons(PMAPPORT);
+ map.pm_prog = program;
+ map.pm_vers = version;
+ map.pm_prot = protocol;
+ map.pm_port = port;
+ return portmap_register_work(module, client_sock,
+ FALSE,
+ (struct sockaddr *) &sin, sizeof(sin),
+ PMAPPROG, PMAPVERS,
+ create ? PMAPPROC_SET : PMAPPROC_UNSET,
+ &map, (xdrproc_t) &xdr_pmap);
+}
+
+static bool_t
+portmap_is_stream(int sd)
+{
+ int socktype;
+ socklen_t socklen = sizeof(socktype);
+ if (getsockopt(sd, SOL_SOCKET, SO_TYPE, &socktype, &socklen) == 0) {
+ return (socklen == sizeof(int)) && (socktype == SOCK_STREAM);
+ }
+ return FALSE;
+}
+
bool_t
portmap_register(const char *log_id, int resv_sock,
- int program, int version, int family, int protocol, int port)
+ int program, int version,
+ int family, int protocol, int port)
{
- return portmap_register_work(log_id, resv_sock, program, version,
- family, protocol, port, TRUE);
+ return portmap_is_stream(resv_sock) ?
+ portmap_register_rpcbind(log_id, resv_sock,
+ TRUE,
+ family, protocol, port,
+ program, version) :
+ portmap_register_portmap(log_id, resv_sock,
+ TRUE,
+ protocol, port,
+ program, version);
}
bool_t
portmap_unregister(const char *log_id, int resv_sock,
- int program, int version, int family, int protocol)
+ int program, int version,
+ int family, int protocol, int port)
{
- return portmap_register_work(log_id, resv_sock, program, version,
- family, protocol, 0, FALSE);
+ return portmap_is_stream(resv_sock) ?
+ portmap_register_rpcbind(log_id, resv_sock,
+ FALSE,
+ family, protocol, port,
+ program, version) :
+ portmap_register_portmap(log_id, resv_sock,
+ FALSE,
+ protocol, port,
+ program, version);
+}
+
+int
+portmap_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 -1;
+}
+
+static int
+portmap_create_rpcbind_client_socket(char *module)
+{
+ int sockfd;
+ struct sockaddr_un sockun;
+
+ sockfd = socket(PF_LOCAL, SOCK_STREAM, 0);
+ if (sockfd == -1) {
+ slapi_log_error(SLAPI_LOG_FATAL, module,
+ "error allocating portmap client socket\n");
+ return -1;
+ }
+ 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) {
+ slapi_log_error(SLAPI_LOG_FATAL, module,
+ "error connecting rpcbind client "
+ "socket to the service\n");
+ close(sockfd);
+ return -1;
+ }
+ return sockfd;
+}
+
+static int
+portmap_create_portmap_client_socket(char *module, int but_not)
+{
+ int sockfd;
+ sockfd = socket(PF_INET, SOCK_DGRAM, 0);
+ if (sockfd == -1) {
+ slapi_log_error(SLAPI_LOG_FATAL, module,
+ "error allocating portmap client socket\n");
+ return -1;
+ }
+ if (portmap_bind_resvport(sockfd, AF_INET, but_not) <= 0) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, module,
+ "unable to bind portmap client socket to a "
+ "privileged port\n");
+ close(sockfd);
+ return -1;
+ }
+ return sockfd;
+}
+
+int
+portmap_create_client_socket(char *module, int but_not)
+{
+ int sock;
+ sock = portmap_create_rpcbind_client_socket(module);
+ if (sock == -1) {
+ sock = portmap_create_portmap_client_socket(module, but_not);
+ }
+ slapi_log_error(SLAPI_LOG_PLUGIN, module,
+ "created client socket %d for portmap client\n",
+ sock);
+ return sock;
}