swrap: Support more socket options in getsockopt().
authorAndreas Schneider <asn@samba.org>
Thu, 22 May 2014 09:18:08 +0000 (11:18 +0200)
committerAndreas Schneider <asn@samba.org>
Mon, 26 May 2014 14:45:16 +0000 (16:45 +0200)
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Michael Adam <obnox@samba.org>
src/socket_wrapper.c

index c52f3d7182167c3297cded826573dd8c98efe718..19ac1840cdc48072b3ca0756be6d733735a9a4a7 100644 (file)
@@ -2844,6 +2844,12 @@ int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
  *   GETSOCKOPT
  ***************************************************************************/
 
+#ifndef SO_PROTOCOL
+# ifdef SO_PROTOTYPE /* The Solaris name */
+#  define SO_PROTOCOL SO_PROTOTYPE
+# endif /* SO_PROTOTYPE */
+#endif /* SO_PROTOCOL */
+
 static int swrap_getsockopt(int s, int level, int optname,
                            void *optval, socklen_t *optlen)
 {
@@ -2858,11 +2864,46 @@ static int swrap_getsockopt(int s, int level, int optname,
        }
 
        if (level == SOL_SOCKET) {
-               return libc_getsockopt(s,
-                                      level,
-                                      optname,
-                                      optval,
-                                      optlen);
+               switch (optname) {
+#ifdef SO_DOMAIN
+               case SO_DOMAIN:
+                       if (optval == NULL || optlen == NULL ||
+                           *optlen < (socklen_t)sizeof(int)) {
+                               errno = EINVAL;
+                               return -1;
+                       }
+
+                       *optlen = sizeof(int);
+                       *(int *)optval = si->family;
+                       return 0;
+#endif /* SO_DOMAIN */
+               case SO_PROTOCOL:
+                       if (optval == NULL || optlen == NULL ||
+                           *optlen < (socklen_t)sizeof(int)) {
+                               errno = EINVAL;
+                               return -1;
+                       }
+
+                       *optlen = sizeof(int);
+                       *(int *)optval = si->protocol;
+                       return 0;
+               case SO_TYPE:
+                       if (optval == NULL || optlen == NULL ||
+                           *optlen < (socklen_t)sizeof(int)) {
+                               errno = EINVAL;
+                               return -1;
+                       }
+
+                       *optlen = sizeof(int);
+                       *(int *)optval = si->type;
+                       return 0;
+               default:
+                       return libc_getsockopt(s,
+                                              level,
+                                              optname,
+                                              optval,
+                                              optlen);
+               }
        }
 
        errno = ENOPROTOOPT;