Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / usrsctp / usrsctplib / user_socket.c
index abbccee..e4e886f 100755 (executable)
 #if !defined (__Userspace_os_Windows)
 #include <netinet/udp.h>
 #include <arpa/inet.h>
-/* Statically initializing accept_mtx and accept_cond since there is no call for ACCEPT_LOCK_INIT() */
-userland_mutex_t accept_mtx = PTHREAD_MUTEX_INITIALIZER;
-userland_cond_t accept_cond = PTHREAD_COND_INITIALIZER;
 #else
 #include <user_socketvar.h>
+#endif
 userland_mutex_t accept_mtx;
 userland_cond_t accept_cond;
-#endif
 #ifdef _WIN32
 #include <time.h>
 #include <sys/timeb.h>
@@ -725,7 +722,7 @@ userspace_sctp_sendmsg(struct socket *so,
                return (-1);
        }
        if ((tolen > 0) &&
-           ((to == NULL) || (tolen < sizeof(struct sockaddr)))) {
+           ((to == NULL) || (tolen < (socklen_t)sizeof(struct sockaddr)))) {
                errno = EINVAL;
                return (-1);
        }
@@ -895,7 +892,7 @@ userspace_sctp_sendmbuf(struct socket *so,
         error = (ENAMETOOLONG);
         goto sendmsg_return;
     }
-    if (tolen < offsetof(struct sockaddr, sa_data)){
+    if (tolen < (socklen_t)offsetof(struct sockaddr, sa_data)){
         error = (EINVAL);
         goto sendmsg_return;
     }
@@ -977,10 +974,15 @@ userspace_sctp_recvmsg(struct socket *so,
                    (struct sctp_sndrcvinfo *)sinfo, 1);
 
        if (error) {
-               if (auio.uio_resid != (int)ulen && (error == ERESTART ||
-                   error == EINTR || error == EWOULDBLOCK))
+               if (auio.uio_resid != (int)ulen &&
+                   (error == EINTR ||
+#if !defined(__Userspace_os_NetBSD)
+                    error == ERESTART ||
+#endif
+                    error == EWOULDBLOCK)) {
                        error = 0;
                }
+       }
        if ((fromlenp != NULL) && (fromlen > 0) && (from != NULL)) {
                switch (from->sa_family) {
 #if defined(INET)
@@ -1066,7 +1068,11 @@ usrsctp_recvv(struct socket *so,
                    (struct sctp_sndrcvinfo *)&seinfo, 1);
        if (errno) {
                if (auio.uio_resid != (int)ulen &&
-                   (errno == ERESTART || errno == EINTR || errno == EWOULDBLOCK)) {
+                   (errno == EINTR ||
+#if !defined(__Userspace_os_NetBSD)
+                    errno == ERESTART ||
+#endif
+                    errno == EWOULDBLOCK)) {
                        errno = 0;
                }
        }
@@ -1076,7 +1082,7 @@ usrsctp_recvv(struct socket *so,
                inp = (struct sctp_inpcb *)so->so_pcb;
                if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO) &&
                    sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO) &&
-                   *infolen >= sizeof(struct sctp_recvv_rn) &&
+                   *infolen >= (socklen_t)sizeof(struct sctp_recvv_rn) &&
                    seinfo.sreinfo_next_flags & SCTP_NEXT_MSG_AVAIL) {
                        rn = (struct sctp_recvv_rn *)info;
                        rn->recvv_rcvinfo.rcv_sid = seinfo.sinfo_stream;
@@ -1104,7 +1110,7 @@ usrsctp_recvv(struct socket *so,
                        *infolen = (socklen_t)sizeof(struct sctp_recvv_rn);
                        *infotype = SCTP_RECVV_RN;
                } else if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO) &&
-                          *infolen >= sizeof(struct sctp_rcvinfo)) {
+                          *infolen >= (socklen_t)sizeof(struct sctp_rcvinfo)) {
                        rcv = (struct sctp_rcvinfo *)info;
                        rcv->rcv_sid = seinfo.sinfo_stream;
                        rcv->rcv_ssn = seinfo.sinfo_ssn;
@@ -1747,8 +1753,33 @@ user_accept(struct socket *head,  struct sockaddr **name, socklen_t *namelen, st
        if (name) {
 #ifdef HAVE_SA_LEN
                /* check sa_len before it is destroyed */
-               if (*namelen > sa->sa_len)
+               if (*namelen > sa->sa_len) {
                        *namelen = sa->sa_len;
+               }
+#else
+               socklen_t sa_len;
+
+               switch (sa->sa_family) {
+#ifdef INET
+               case AF_INET:
+                       sa_len = sizeof(struct sockaddr_in);
+                       break;
+#endif
+#ifdef INET6
+               case AF_INET6:
+                       sa_len = sizeof(struct sockaddr_in6);
+                       break;
+#endif
+               case AF_CONN:
+                       sa_len = sizeof(struct sockaddr_conn);
+                       break;
+               default:
+                       sa_len = 0;
+                       break;
+               }
+               if (*namelen > sa_len) {
+                       *namelen = sa_len;
+               }
 #endif
                *name = sa;
                sa = NULL;
@@ -1989,8 +2020,13 @@ int user_connect(struct socket *so, struct sockaddr *sa)
                error = pthread_cond_wait(SOCK_COND(so), SOCK_MTX(so));
 #endif
                if (error) {
-                       if (error == EINTR || error == ERESTART)
+#if defined(__Userspace_os_NetBSD)
+                       if (error == EINTR) {
+#else
+                       if (error == EINTR || error == ERESTART) {
+#endif
                                interrupted = 1;
+                       }
                        break;
                }
        }
@@ -2001,10 +2037,14 @@ int user_connect(struct socket *so, struct sockaddr *sa)
        SOCK_UNLOCK(so);
 
 bad:
-       if (!interrupted)
+       if (!interrupted) {
                so->so_state &= ~SS_ISCONNECTING;
-       if (error == ERESTART)
+       }
+#if !defined(__Userspace_os_NetBSD)
+       if (error == ERESTART) {
                error = EINTR;
+       }
+#endif
 done1:
        return (error);
 }
@@ -2306,13 +2346,17 @@ usrsctp_bindx(struct socket *so, struct sockaddr *addrs, int addrcnt, int flags)
 {
        struct sctp_getaddresses *gaddrs;
        struct sockaddr *sa;
+#ifdef INET
        struct sockaddr_in *sin;
+#endif
 #ifdef INET6
        struct sockaddr_in6 *sin6;
 #endif
        int i;
        size_t argsz;
+#if defined(INET) || defined(INET6)
        uint16_t sport = 0;
+#endif
 
        /* validate the flags */
        if ((flags != SCTP_BINDX_ADD_ADDR) &&
@@ -2352,7 +2396,7 @@ usrsctp_bindx(struct socket *so, struct sockaddr *addrs, int addrcnt, int flags)
                                }
                        }
 #ifndef HAVE_SA_LEN
-               sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
+                       sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
 #endif
                        break;
 #endif
@@ -2379,27 +2423,19 @@ usrsctp_bindx(struct socket *so, struct sockaddr *addrs, int addrcnt, int flags)
                                }
                        }
 #ifndef HAVE_SA_LEN
-               sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6));
+                       sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6));
 #endif
                        break;
 #endif
                default:
                        /* Invalid address family specified. */
-                       errno = EINVAL;
+                       errno = EAFNOSUPPORT;
                        return (-1);
                }
 #ifdef HAVE_SA_LEN
                sa = (struct sockaddr *)((caddr_t)sa + sa->sa_len);
 #endif
        }
-       /*
-        * Now if there was a port mentioned, assure that the first address
-        * has that port to make sure it fails or succeeds correctly.
-        */
-       if (sport) {
-               sin = (struct sockaddr_in *)sa;
-               sin->sin_port = sport;
-       }
        argsz = sizeof(struct sctp_getaddresses) +
                sizeof(struct sockaddr_storage);
        if ((gaddrs = (struct sctp_getaddresses *)malloc(argsz)) == NULL) {
@@ -2437,6 +2473,29 @@ usrsctp_bindx(struct socket *so, struct sockaddr *addrs, int addrcnt, int flags)
                        break;
                }
                memcpy(gaddrs->addr, sa, sa_len);
+               /*
+                * Now, if there was a port mentioned, assure that the
+                * first address has that port to make sure it fails or
+                * succeeds correctly.
+                */
+#if defined(INET) || defined(INET6)
+               if ((i == 0) && (sport != 0)) {
+                       switch (gaddrs->addr->sa_family) {
+#ifdef INET
+                       case AF_INET:
+                               sin = (struct sockaddr_in *)gaddrs->addr;
+                               sin->sin_port = sport;
+                               break;
+#endif
+#ifdef INET6
+                       case AF_INET6:
+                               sin6 = (struct sockaddr_in6 *)gaddrs->addr;
+                               sin6->sin6_port = sport;
+                               break;
+#endif
+                       }
+               }
+#endif
                if (usrsctp_setsockopt(so, IPPROTO_SCTP, flags, gaddrs, (socklen_t)argsz) != 0) {
                        free(gaddrs);
                        return (-1);
@@ -2750,6 +2809,8 @@ sctp_userspace_ip_output(int *result, struct mbuf *o_pak,
                        ip = mtod(m, struct ip *);
                }
                udp = (struct udphdr *)(ip + 1);
+       } else {
+               udp = NULL;
        }
 
        if (!use_udp_tunneling) {
@@ -2906,6 +2967,8 @@ void sctp_userspace_ip6_output(int *result, struct mbuf *o_pak,
                        ip6 = mtod(m, struct ip6_hdr *);
                }
                udp = (struct udphdr *)(ip6 + 1);
+       } else {
+               udp = NULL;
        }
 
        if (!use_udp_tunneling) {
@@ -3238,6 +3301,7 @@ USRSCTP_SYSCTL_SET_DEF(sctp_udp_tunneling_port)
 USRSCTP_SYSCTL_SET_DEF(sctp_enable_sack_immediately)
 USRSCTP_SYSCTL_SET_DEF(sctp_vtag_time_wait)
 USRSCTP_SYSCTL_SET_DEF(sctp_blackhole)
+USRSCTP_SYSCTL_SET_DEF(sctp_diag_info_code)
 USRSCTP_SYSCTL_SET_DEF(sctp_fr_max_burst_default)
 USRSCTP_SYSCTL_SET_DEF(sctp_path_pf_threshold)
 USRSCTP_SYSCTL_SET_DEF(sctp_default_ss_module)
@@ -3316,6 +3380,7 @@ USRSCTP_SYSCTL_GET_DEF(sctp_udp_tunneling_port)
 USRSCTP_SYSCTL_GET_DEF(sctp_enable_sack_immediately)
 USRSCTP_SYSCTL_GET_DEF(sctp_vtag_time_wait)
 USRSCTP_SYSCTL_GET_DEF(sctp_blackhole)
+USRSCTP_SYSCTL_GET_DEF(sctp_diag_info_code)
 USRSCTP_SYSCTL_GET_DEF(sctp_fr_max_burst_default)
 USRSCTP_SYSCTL_GET_DEF(sctp_path_pf_threshold)
 USRSCTP_SYSCTL_GET_DEF(sctp_default_ss_module)