SO_PROTOCOL is platform-dependent
[sfrench/samba-autobuild/.git] / lib / socket_wrapper / socket_wrapper.c
index 0303b21043462a054fbcbc98c170f186be1d54db..903eec21537429fc69ea4979094888cf71c244a0 100644 (file)
@@ -1267,6 +1267,90 @@ static struct socket_info *find_socket_info(int fd)
        return NULL;
 }
 
+#if 0 /* FIXME */
+static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
+{
+       struct socket_info *s;
+
+       /* first catch invalid input */
+       switch (sa->sa_family) {
+       case AF_INET:
+               if (len < sizeof(struct sockaddr_in)) {
+                       return false;
+               }
+               break;
+#if HAVE_IPV6
+       case AF_INET6:
+               if (len < sizeof(struct sockaddr_in6)) {
+                       return false;
+               }
+               break;
+#endif
+       default:
+               return false;
+               break;
+       }
+
+       for (s = sockets; s != NULL; s = s->next) {
+               if (s->myname == NULL) {
+                       continue;
+               }
+               if (s->myname->sa_family != sa->sa_family) {
+                       continue;
+               }
+               switch (s->myname->sa_family) {
+               case AF_INET: {
+                       struct sockaddr_in *sin1, *sin2;
+
+                       sin1 = (struct sockaddr_in *)s->myname;
+                       sin2 = (struct sockaddr_in *)sa;
+
+                       if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
+                               continue;
+                       }
+                       if (sin1->sin_port != sin2->sin_port) {
+                               continue;
+                       }
+                       if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
+                               continue;
+                       }
+
+                       /* found */
+                       return true;
+                       break;
+               }
+#if HAVE_IPV6
+               case AF_INET6: {
+                       struct sockaddr_in6 *sin1, *sin2;
+
+                       sin1 = (struct sockaddr_in6 *)s->myname;
+                       sin2 = (struct sockaddr_in6 *)sa;
+
+                       if (sin1->sin6_port != sin2->sin6_port) {
+                               continue;
+                       }
+                       if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
+                                               &sin2->sin6_addr))
+                       {
+                               continue;
+                       }
+
+                       /* found */
+                       return true;
+                       break;
+               }
+#endif
+               default:
+                       continue;
+                       break;
+
+               }
+       }
+
+       return false;
+}
+#endif
+
 static void swrap_remove_stale(int fd)
 {
        struct socket_info *si = find_socket_info(fd);
@@ -1309,6 +1393,26 @@ static int sockaddr_convert_to_un(struct socket_info *si,
 #endif
 
        switch (in_addr->sa_family) {
+       case AF_UNSPEC: {
+               const struct sockaddr_in *sin;
+               if (si->family != AF_INET) {
+                       break;
+               }
+               if (in_len < sizeof(struct sockaddr_in)) {
+                       break;
+               }
+               sin = (const struct sockaddr_in *)in_addr;
+               if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
+                       break;
+               }
+
+               /*
+                * Note: in the special case of AF_UNSPEC and INADDR_ANY,
+                * AF_UNSPEC is mapped to AF_INET and must be treated here.
+                */
+
+               /* FALL THROUGH */
+       }
        case AF_INET:
 #ifdef HAVE_IPV6
        case AF_INET6:
@@ -2726,6 +2830,9 @@ static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
        struct sockaddr_un un_addr;
        struct socket_info *si = find_socket_info(s);
        int bind_error = 0;
+#if 0 /* FIXME */
+       bool in_use;
+#endif
 
        if (!si) {
                return libc_bind(s, myaddr, addrlen);
@@ -2739,7 +2846,7 @@ static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
                        break;
                }
 
-               sin = (struct sockaddr_in *)myaddr;
+               sin = (const struct sockaddr_in *)myaddr;
 
                if (sin->sin_family != AF_INET) {
                        bind_error = EAFNOSUPPORT;
@@ -2762,7 +2869,7 @@ static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
                        break;
                }
 
-               sin6 = (struct sockaddr_in6 *)myaddr;
+               sin6 = (const struct sockaddr_in6 *)myaddr;
 
                if (sin6->sin6_family != AF_INET6) {
                        bind_error = EAFNOSUPPORT;
@@ -2781,6 +2888,14 @@ static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
                return -1;
        }
 
+#if 0 /* FIXME */
+       in_use = check_addr_port_in_use(myaddr, addrlen);
+       if (in_use) {
+               errno = EADDRINUSE;
+               return -1;
+       }
+#endif
+
        free(si->myname);
        si->myname_len = addrlen;
        si->myname = sockaddr_dup(myaddr, addrlen);
@@ -3054,6 +3169,8 @@ static int swrap_getsockopt(int s, int level, int optname,
                        *(int *)optval = si->family;
                        return 0;
 #endif /* SO_DOMAIN */
+
+#ifdef SO_PROTOCOL
                case SO_PROTOCOL:
                        if (optval == NULL || optlen == NULL ||
                            *optlen < (socklen_t)sizeof(int)) {
@@ -3064,6 +3181,7 @@ static int swrap_getsockopt(int s, int level, int optname,
                        *optlen = sizeof(int);
                        *(int *)optval = si->protocol;
                        return 0;
+#endif /* SO_PROTOCOL */
                case SO_TYPE:
                        if (optval == NULL || optlen == NULL ||
                            *optlen < (socklen_t)sizeof(int)) {
@@ -3292,8 +3410,7 @@ static int swrap_msghdr_add_pktinfo(struct socket_info *si,
 {
        /* Add packet info */
        switch (si->pktinfo) {
-#if defined(IP_PKTINFO)
-/* && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR)) */
+#if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
        case AF_INET: {
                struct sockaddr_in *sin;
 #if defined(HAVE_STRUCT_IN_PKTINFO)