diff options
Diffstat (limited to 'src/portmap.c')
-rw-r--r-- | src/portmap.c | 130 |
1 files changed, 80 insertions, 50 deletions
diff --git a/src/portmap.c b/src/portmap.c index 5b463c0..f2e009e 100644 --- a/src/portmap.c +++ b/src/portmap.c @@ -96,38 +96,39 @@ main(int argc, char **argv) } 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, - port); - portmap_register("portmap", s, YPPROG, YPVERS, AF_INET, IPPROTO_UDP, - port); - portmap_register("portmap", s, YPPROG, YPVERS, AF_INET6, IPPROTO_TCP, - port); - portmap_register("portmap", s, YPPROG, YPVERS, AF_INET6, IPPROTO_UDP, - port); + sleep(60); + portmap_unregister("portmap", &s, port, YPPROG, YPVERS, + AF_INET, IPPROTO_TCP, 0); + portmap_unregister("portmap", &s, port, YPPROG, YPVERS, + AF_INET, IPPROTO_UDP, 0); + portmap_unregister("portmap", &s, port, YPPROG, YPVERS, + AF_INET6, IPPROTO_TCP, 0); + portmap_unregister("portmap", &s, port, YPPROG, YPVERS, + AF_INET6, IPPROTO_UDP, 0); + portmap_register("portmap", &s, port, YPPROG, YPVERS, + AF_INET, IPPROTO_TCP, port); + portmap_register("portmap", &s, port, YPPROG, YPVERS, + AF_INET, IPPROTO_UDP, port); + portmap_register("portmap", &s, port, YPPROG, YPVERS, + AF_INET6, IPPROTO_TCP, port); + portmap_register("portmap", &s, port, YPPROG, YPVERS, + AF_INET6, IPPROTO_UDP, port); ret = system("rpcinfo | grep ypserv"); ret = system("rpcinfo -p | grep ypserv"); - 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); + portmap_unregister("portmap", &s, port, YPPROG, YPVERS, + AF_INET, IPPROTO_TCP, port); + portmap_unregister("portmap", &s, port, YPPROG, YPVERS, + AF_INET, IPPROTO_UDP, port); + portmap_unregister("portmap", &s, port, YPPROG, YPVERS, + AF_INET6, IPPROTO_TCP, port); + portmap_unregister("portmap", &s, port, YPPROG, YPVERS, + AF_INET6, IPPROTO_UDP, port); return 0; } #endif static bool_t -portmap_register_work(const char *module, int client_sock, +portmap_register_work(const char *module, int *client_sock, int but_not, bool_t stream, struct sockaddr *dgram_address, socklen_t addrlen, int prog, int vers, int proc, @@ -142,7 +143,7 @@ portmap_register_work(const char *module, int client_sock, bool_t ret = FALSE; struct sockaddr addr; struct pollfd pollfd; - int i; + int i, err, sock2 = -1; static u_long xid; log_id = (char *) module; @@ -197,7 +198,7 @@ portmap_register_work(const char *module, int client_sock, portmap_length += 4; } else { /* Point the datagram socket at the remote. */ - if (connect(client_sock, dgram_address, addrlen) != 0) { + if (connect(*client_sock, dgram_address, addrlen) != 0) { slapi_log_error(SLAPI_LOG_FATAL, log_id, "error targeting portmap: %s\n", strerror(errno)); @@ -210,26 +211,56 @@ portmap_register_work(const char *module, int client_sock, for (i = 1; i < 32; i *= 2) { /* Try to send our request. If there's any problem, * immediately retry. */ - if (send(client_sock, &portmap_buf, portmap_length, + if (send(*client_sock, &portmap_buf, portmap_length, MSG_NOSIGNAL) != portmap_length) { + err = errno; slapi_log_error(SLAPI_LOG_FATAL, log_id, "error sending request to portmap or " - "rpcbind on %d: %s\n", client_sock, - strerror(errno)); + "rpcbind on %d: %s\n", *client_sock, + strerror(err)); if (stream) { - break; + if (err == EPIPE) { + /* Try again with a new client + * connection -- some RPC + * implementations will cause rpcbind + * to drop idle clients. */ + snprintf(reply_buf, sizeof(reply_buf), + "%s", module); + sock2 = portmap_create_client_socket(reply_buf, + but_not); + if (sock2 != -1) { + if (send(sock2, &portmap_buf, portmap_length, + MSG_NOSIGNAL) == portmap_length) { + slapi_log_error(SLAPI_LOG_FATAL, log_id, + "retried sending request " + "to portmap or rpcbind " + "on %d, and succeeded\n", + sock2); + close(*client_sock); + *client_sock = sock2; + } else { + /* Still got an error -- bail. */ + close(sock2); + break; + } + } else { + break; + } + } else { + break; + } } else { continue; } } /* Wait for a response. */ - pollfd.fd = client_sock; + pollfd.fd = *client_sock; pollfd.events = POLLIN | POLLERR; if ((poll(&pollfd, 1, stream ? -1 : i * 1000) > 0) && (pollfd.revents & POLLIN)) { /* Read the response. */ - reply_length = recv(client_sock, + reply_length = recv(*client_sock, reply_buf, sizeof(reply_buf), 0); /* Decode the response. */ if (reply_length > 0) { @@ -266,6 +297,8 @@ portmap_register_work(const char *module, int client_sock, if ((msg.rm_direction == REPLY) && (msg.rm_xid == xid)) { xdr_destroy(&portmap_xdrs); + memset(&portmap_xdrs, 0, + sizeof(portmap_xdrs)); break; } } @@ -280,7 +313,7 @@ portmap_register_work(const char *module, int client_sock, * socket around. */ memset(&addr, 0, sizeof(addr)); addr.sa_family = AF_UNSPEC; - connect(client_sock, &addr, sizeof(addr)); + connect(*client_sock, &addr, sizeof(addr)); /* Check for a timeout. */ if (i == 32) { slapi_log_error(SLAPI_LOG_FATAL, log_id, @@ -336,7 +369,6 @@ portmap_register_work(const char *module, int client_sock, "RPC mismatch\n"); break; } - xdr_destroy(&portmap_xdrs); return FALSE; } @@ -355,7 +387,6 @@ portmap_register_work(const char *module, int client_sock, if (msg.rm_reply.rp_acpt.ar_stat != SUCCESS) { slapi_log_error(SLAPI_LOG_FATAL, log_id, "portmap request not processed\n"); - xdr_destroy(&portmap_xdrs); return FALSE; } @@ -368,8 +399,6 @@ portmap_register_work(const char *module, int client_sock, "portmap request failed\n"); } - xdr_destroy(&portmap_xdrs); - return ret; } @@ -392,7 +421,7 @@ portmap_xdr_rpcbind_req(XDR *xdrs, struct rpcbind_req *req) } static bool_t -portmap_register_rpcbind(const char *module, int client_sock, +portmap_register_rpcbind(const char *module, int *client_sock, int but_not, bool_t create, int family, int protocol, int port, int program, int version) @@ -444,7 +473,8 @@ portmap_register_rpcbind(const char *module, int client_sock, req.address = NULL; break; } - return portmap_register_work(module, client_sock, TRUE, NULL, 0, + return portmap_register_work(module, client_sock, but_not, + TRUE, NULL, 0, RPCBPROG, RPCBVERS, create ? RPCBPROC_SET : RPCBPROC_UNSET, &req, @@ -452,7 +482,7 @@ portmap_register_rpcbind(const char *module, int client_sock, } static bool_t -portmap_register_portmap(const char *module, int client_sock, +portmap_register_portmap(const char *module, int *client_sock, int but_not, bool_t create, int protocol, int port, int program, int version) { @@ -466,7 +496,7 @@ portmap_register_portmap(const char *module, int client_sock, map.pm_vers = version; map.pm_prot = protocol; map.pm_port = port; - return portmap_register_work(module, client_sock, + return portmap_register_work(module, client_sock, but_not, FALSE, (struct sockaddr *) &sin, sizeof(sin), PMAPPROG, PMAPVERS, @@ -486,32 +516,32 @@ portmap_is_stream(int sd) } bool_t -portmap_register(const char *log_id, int resv_sock, +portmap_register(const char *log_id, int *resv_sock, int but_not, int program, int version, int family, int protocol, int port) { - return portmap_is_stream(resv_sock) ? - portmap_register_rpcbind(log_id, resv_sock, + return portmap_is_stream(*resv_sock) ? + portmap_register_rpcbind(log_id, resv_sock, but_not, TRUE, family, protocol, port, program, version) : - portmap_register_portmap(log_id, resv_sock, + portmap_register_portmap(log_id, resv_sock, but_not, TRUE, protocol, port, program, version); } bool_t -portmap_unregister(const char *log_id, int resv_sock, +portmap_unregister(const char *log_id, int *resv_sock, int but_not, int program, int version, int family, int protocol, int port) { - return portmap_is_stream(resv_sock) ? - portmap_register_rpcbind(log_id, resv_sock, + return portmap_is_stream(*resv_sock) ? + portmap_register_rpcbind(log_id, resv_sock, but_not, FALSE, family, protocol, port, program, version) : - portmap_register_portmap(log_id, resv_sock, + portmap_register_portmap(log_id, resv_sock, but_not, FALSE, protocol, port, program, version); |