diff options
author | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2009-02-11 21:29:55 -0500 |
---|---|---|
committer | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2009-02-11 21:29:55 -0500 |
commit | 689aeb76c0cf1a704499a790e8e9439b0395cb2d (patch) | |
tree | 7d847e2824ef58cbc8820a564fac0af0a1bdb5ea /src | |
parent | 13e818b9df6c15076ba9f6d23adaf480c98a6d93 (diff) | |
download | slapi-nis-689aeb76c0cf1a704499a790e8e9439b0395cb2d.tar.gz slapi-nis-689aeb76c0cf1a704499a790e8e9439b0395cb2d.tar.xz slapi-nis-689aeb76c0cf1a704499a790e8e9439b0395cb2d.zip |
- first (non-working) pass at registering with rpcbind
Diffstat (limited to 'src')
-rw-r--r-- | src/plug-nis.c | 35 | ||||
-rw-r--r-- | src/portmap.c | 155 | ||||
-rw-r--r-- | src/portmap.h | 3 |
3 files changed, 173 insertions, 20 deletions
diff --git a/src/plug-nis.c b/src/plug-nis.c index 19ff1dc..8e0b203 100644 --- a/src/plug-nis.c +++ b/src/plug-nis.c @@ -97,7 +97,10 @@ 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, AF_INET); + YPPROG, YPVERS, AF_INET, IPPROTO_TCP); + portmap_unregister(plugin_description.spd_id, + state->pmap_client_socket, + YPPROG, YPVERS, AF_INET, IPPROTO_UDP); /* Register our listening ports. */ for (i = 0; i < state->n_listeners; i++) { if (state->listener[i].pf != PF_INET) { @@ -158,7 +161,10 @@ plugin_shutdown(Slapi_PBlock *pb) /* Clear our registration with the portmapper. */ portmap_unregister(plugin_description.spd_id, state->pmap_client_socket, - YPPROG, YPVERS, AF_INET); + 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); @@ -252,6 +258,7 @@ plugin_state_init(Slapi_PBlock *pb, struct plugin_state **lstate) struct plugin_state *state = NULL; struct sockaddr_in sin; struct sockaddr_in6 sin6; + struct sockaddr_un sockun; state = malloc(sizeof(*state)); if (state == NULL) { @@ -289,6 +296,29 @@ 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); if (sockfd == -1) { slapi_log_error(SLAPI_LOG_FATAL, state->plugin_desc->spd_id, @@ -314,6 +344,7 @@ plugin_state_init(Slapi_PBlock *pb, struct plugin_state **lstate) close(sockfd); sockfd = -1; } +#endif state->pmap_client_socket = sockfd; /* We need to bind on privileged ports for both datagram and connected diff --git a/src/portmap.c b/src/portmap.c index bb5051f..3d56971 100644 --- a/src/portmap.c +++ b/src/portmap.c @@ -1,5 +1,5 @@ /* - * Copyright 2008 Red Hat, Inc. + * Copyright 2008,2009 Red Hat, Inc. * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -49,6 +49,7 @@ #ifdef PORTMAP_MAIN #include <stdarg.h> +#include <stdlib.h> #include <unistd.h> int slapi_log_error(int i, char *f, char *fmt, ...) @@ -62,18 +63,39 @@ slapi_log_error(int i, char *f, char *fmt, ...) int main(int argc, char **argv) { - int s; + int s, ret; struct sockaddr_in sin; + 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"); + } else { + printf("bound to reserved port %d\n", ntohs(sin.sin_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 setreuid(2510, 2510); - portmap_unregister("portmap", s, YPPROG, YPVERS, AF_INET); + portmap_register("portmap", s, YPPROG, YPVERS, AF_INET, IPPROTO_TCP, + ntohs(sin.sin_port)); portmap_register("portmap", s, YPPROG, YPVERS, AF_INET, IPPROTO_UDP, ntohs(sin.sin_port)); + portmap_register("portmap", s, YPPROG, YPVERS, AF_INET6, IPPROTO_TCP, + ntohs(sin.sin_port)); + portmap_register("portmap", s, YPPROG, YPVERS, AF_INET6, IPPROTO_UDP, + ntohs(sin.sin_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); return 0; } #endif @@ -82,17 +104,26 @@ static bool_t portmap_register_work(const char *module, int resv_sock, int program, int version, int family, int protocol, int port, - int proc) + bool_t create) { 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; @@ -105,13 +136,73 @@ portmap_register_work(const char *module, int resv_sock, 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_direction = CALL; msg.rm_call.cb_rpcvers = 2; - msg.rm_call.cb_prog = PMAPPROG; - msg.rm_call.cb_vers = PMAPVERS; + msg.rm_call.cb_prog = prog; + msg.rm_call.cb_vers = vers; msg.rm_call.cb_proc = proc; /* Build an authenticator. */ @@ -121,24 +212,37 @@ portmap_register_work(const char *module, int resv_sock, msg.rm_call.cb_cred = auth->ah_cred; msg.rm_call.cb_verf = auth->ah_verf; - /* Populate the arguments for this request. */ - map.pm_prog = program; - map.pm_vers = version; - map.pm_prot = protocol; - map.pm_port = port; - /* 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 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); auth_destroy(auth); xdr_destroy(&auth_xdrs); xdr_destroy(&portmap_xdrs); memset(&portmap_xdrs, 0, sizeof(portmap_xdrs)); - /* Connect to the local portmapper. */ +#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); @@ -150,6 +254,7 @@ portmap_register_work(const char *module, int resv_sock, resv_sock, strerror(errno)); return FALSE; } +#endif /* Transmit our request. Retry a few times if it doesn't go through. */ for (i = 1; i < 32; i *= 2) { @@ -178,9 +283,23 @@ portmap_register_work(const char *module, int resv_sock, /* 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"); + } + 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 = @@ -198,6 +317,7 @@ 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) { @@ -205,6 +325,7 @@ portmap_register_work(const char *module, int resv_sock, "timeout registering with portmap service\n"); return FALSE; } +#endif /* Check that the portmapper didn't just reject the request out of * hand. */ @@ -281,7 +402,7 @@ portmap_register_work(const char *module, int resv_sock, "portmap request succeeded\n"); } else { slapi_log_error(SLAPI_LOG_PLUGIN, log_id, - "portmap response did not include a reply\n"); + "portmap request failed\n"); } xdr_destroy(&portmap_xdrs); @@ -294,13 +415,13 @@ portmap_register(const char *log_id, int resv_sock, int program, int version, int family, int protocol, int port) { return portmap_register_work(log_id, resv_sock, program, version, - family, protocol, port, PMAPPROC_SET); + family, protocol, port, TRUE); } bool_t portmap_unregister(const char *log_id, int resv_sock, - int program, int version, int family) + int program, int version, int family, int protocol) { return portmap_register_work(log_id, resv_sock, program, version, - family, 0, 0, PMAPPROC_UNSET); + family, protocol, 0, FALSE); } diff --git a/src/portmap.h b/src/portmap.h index ed59b67..62c687c 100644 --- a/src/portmap.h +++ b/src/portmap.h @@ -26,6 +26,7 @@ bool_t portmap_register(const char *log_id, int resv_sock, int program, int version, int family, int protocol, int port); bool_t portmap_unregister(const char *log_id, int resv_sock, - int program, int version, int family); + int program, int version, + int family, int protocol); #endif |