]> granicus.if.org Git - libtirpc/commitdiff
Automount with nis maps crashes and generates a core
authorUlrich Drepper <drepper@redhat.com>
Tue, 18 May 2010 23:18:38 +0000 (19:18 -0400)
committerSteve Dickson <steved@redhat.com>
Tue, 18 May 2010 23:18:38 +0000 (19:18 -0400)
I think I added the appropriate backward compatibility support to handle
old kernels.  And certainly the existing libtirpc functions are unchanged.
Only one additional extenal interface (__libc_clntudp_bufcreate) is added.
The remaining changes are necessary to implement it.  The changes are
straightforward.

See https://bugzilla.redhat.com/show_bug.cgi?id=519430

Signed-off-by: Ulrich Drepper <drepper@redhat.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
src/rpc_generic.c
src/rpc_soc.c
tirpc/rpc/rpc.h

index 541275cad501b0deb0d37249e49fb74bb6b52812..509fb36d5ae5ffbdf5e48d0aaab4880be262f104 100644 (file)
@@ -523,7 +523,7 @@ __rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip)
 }
 
 int
-__rpc_nconf2fd(const struct netconfig *nconf)
+__rpc_nconf2fd_flags(const struct netconfig *nconf, int flags)
 {
        struct __rpc_sockinfo si;
        int fd;
@@ -531,7 +531,7 @@ __rpc_nconf2fd(const struct netconfig *nconf)
        if (!__rpc_nconf2sockinfo(nconf, &si))
                return 0;
 
-       if ((fd = socket(si.si_af, si.si_socktype, si.si_proto)) >= 0 &&
+       if ((fd = socket(si.si_af, si.si_socktype | flags, si.si_proto)) >= 0 &&
            si.si_af == AF_INET6) {
                int val = 1;
 
@@ -540,6 +540,12 @@ __rpc_nconf2fd(const struct netconfig *nconf)
        return fd;
 }
 
+int
+__rpc_nconf2fd(const struct netconfig *nconf)
+{
+       return __rpc_nconf2fd_flags(nconf, 0);
+}
+
 int
 __rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid)
 {
index 709a8a8e59a9751d2219ace1cdfab0e0e0d861ed..c67842909d3610c452d525664f109dccf0b9186c 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <fcntl.h>
 
 #include "rpc_com.h"
 
 extern mutex_t rpcsoc_lock;
 
 static CLIENT *clnt_com_create(struct sockaddr_in *, rpcprog_t, rpcvers_t,
-    int *, u_int, u_int, char *);
+    int *, u_int, u_int, char *, int);
 static SVCXPRT *svc_com_create(int, u_int, u_int, char *);
 static bool_t rpc_wrap_bcast(char *, struct netbuf *, struct netconfig *);
 
@@ -78,7 +79,7 @@ static bool_t rpc_wrap_bcast(char *, struct netbuf *, struct netconfig *);
  * A common clnt create routine
  */
 static CLIENT *
-clnt_com_create(raddr, prog, vers, sockp, sendsz, recvsz, tp)
+clnt_com_create(raddr, prog, vers, sockp, sendsz, recvsz, tp, flags)
        struct sockaddr_in *raddr;
        rpcprog_t prog;
        rpcvers_t vers;
@@ -86,6 +87,7 @@ clnt_com_create(raddr, prog, vers, sockp, sendsz, recvsz, tp)
        u_int sendsz;
        u_int recvsz;
        char *tp;
+       int flags;
 {
        CLIENT *cl;
        int madefd = FALSE;
@@ -100,9 +102,21 @@ clnt_com_create(raddr, prog, vers, sockp, sendsz, recvsz, tp)
                return (NULL);
        }
        if (fd == RPC_ANYSOCK) {
-               fd = __rpc_nconf2fd(nconf);
-               if (fd == -1)
-                       goto syserror;
+               static int have_cloexec;
+               fd = __rpc_nconf2fd_flags(nconf, flags);
+               if (fd == -1) {
+                       if ((flags & SOCK_CLOEXEC) && have_cloexec <= 0) {
+                               fd = __rpc_nconf2fd(nconf);
+                               if (fd == -1)
+                                       goto syserror;
+                               if (flags & SOCK_CLOEXEC) {
+                                       have_cloexec = -1;
+                                       fcntl(fd, F_SETFD, FD_CLOEXEC);
+                               }
+                       } else
+                               goto syserror;
+               } else if (flags & SOCK_CLOEXEC)
+                       have_cloexec = 1;
                madefd = TRUE;
        }
 
@@ -153,6 +167,28 @@ err:       if (madefd == TRUE)
        return (NULL);
 }
 
+CLIENT *
+__libc_clntudp_bufcreate(raddr, prog, vers, wait, sockp, sendsz, recvsz, flags)
+       struct sockaddr_in *raddr;
+       u_long prog;
+       u_long vers;
+       struct timeval wait;
+       int *sockp;
+       u_int sendsz;
+       u_int recvsz;
+       int flags;
+{
+       CLIENT *cl;
+
+       cl = clnt_com_create(raddr, (rpcprog_t)prog, (rpcvers_t)vers, sockp,
+           sendsz, recvsz, "udp", flags);
+       if (cl == NULL) {
+               return (NULL);
+       }
+       (void) CLNT_CONTROL(cl, CLSET_RETRY_TIMEOUT, &wait);
+       return (cl);
+}
+
 CLIENT *
 clntudp_bufcreate(raddr, prog, vers, wait, sockp, sendsz, recvsz)
        struct sockaddr_in *raddr;
@@ -166,7 +202,7 @@ clntudp_bufcreate(raddr, prog, vers, wait, sockp, sendsz, recvsz)
        CLIENT *cl;
 
        cl = clnt_com_create(raddr, (rpcprog_t)prog, (rpcvers_t)vers, sockp,
-           sendsz, recvsz, "udp");
+           sendsz, recvsz, "udp", 0);
        if (cl == NULL) {
                return (NULL);
        }
@@ -195,7 +231,7 @@ clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
        u_int recvsz;
 {
        return clnt_com_create(raddr, (rpcprog_t)prog, (rpcvers_t)vers, sockp,
-           sendsz, recvsz, "tcp");
+           sendsz, recvsz, "tcp", 0);
 }
 
 /* IPv6 version of clnt*_*create */
@@ -215,7 +251,7 @@ clntudp6_bufcreate(raddr, prog, vers, wait, sockp, sendsz, recvsz)
        CLIENT *cl;
 
        cl = clnt_com_create(raddr, (rpcprog_t)prog, (rpcvers_t)vers, sockp,
-           sendsz, recvsz, "udp6");
+           sendsz, recvsz, "udp6", 0);
        if (cl == NULL) {
                return (NULL);
        }
@@ -244,7 +280,7 @@ clnttcp6_create(raddr, prog, vers, sockp, sendsz, recvsz)
        u_int recvsz;
 {
        return clnt_com_create(raddr, (rpcprog_t)prog, (rpcvers_t)vers, sockp,
-           sendsz, recvsz, "tcp6");
+           sendsz, recvsz, "tcp6", 0);
 }
 
 #endif
index 29e29e97c472f0a9cf5cd24df551f382b82951ff..6c0222eb810725ed44ed7b1045d3e815fc7acf83 100644 (file)
@@ -101,6 +101,7 @@ __END_DECLS
  */
 __BEGIN_DECLS
 int __rpc_nconf2fd(const struct netconfig *);
+int __rpc_nconf2fd_flags(const struct netconfig *, int);
 int __rpc_nconf2sockinfo(const struct netconfig *, struct __rpc_sockinfo *);
 int __rpc_fd2sockinfo(int, struct __rpc_sockinfo *);
 u_int __rpc_get_t_size(int, int, int);