l_size_t in linux.h was not correct size for 64-bit long

Signed-off-by: Charles Myers <[email protected]>
---
 bsd/sys/compat/linux/linux.h         |  12 +-
 bsd/sys/compat/linux/linux_socket.cc | 727 ++++++++++++++++++++++++++---------
 bsd/sys/compat/linux/linux_socket.h  | 101 ++++-
 bsd/sys/kern/uipc_syscalls.cc        |  45 ++-
 bsd/sys/kern/uipc_syscalls_wrap.cc   |   6 +-
 bsd/uipc_syscalls.h                  |   4 +-
 6 files changed, 673 insertions(+), 222 deletions(-)

diff --git a/bsd/sys/compat/linux/linux.h b/bsd/sys/compat/linux/linux.h
index 7bc8c50..b693d81 100644
--- a/bsd/sys/compat/linux/linux.h
+++ b/bsd/sys/compat/linux/linux.h
@@ -57,7 +57,8 @@ typedef l_longlong    l_loff_t;
 typedef l_ushort       l_mode_t;
 typedef l_long         l_off_t;
 typedef l_int          l_pid_t;
-typedef l_uint         l_size_t;
+typedef l_ulong                l_size_t;
+typedef l_long         l_ssize_t;
 typedef l_long         l_suseconds_t;
 typedef l_long         l_time_t;
 typedef l_uint         l_uid_t;
@@ -76,6 +77,8 @@ typedef struct {
 
 #define        l_fd_set        fd_set
 
+#define LINUX_SOL_SOCKET       1
+
 #define        LINUX_SO_DEBUG          1
 #define        LINUX_SO_REUSEADDR      2
 #define        LINUX_SO_TYPE           3
@@ -108,12 +111,6 @@ struct l_sockaddr {
        char            sa_data[14];
 } __packed;
 
-struct l_cmsghdr {
-       l_size_t        cmsg_len;
-       l_int           cmsg_level;
-       l_int           cmsg_type;
-};
-
 struct l_ifmap {
        l_ulong         mem_start;
        l_ulong         mem_end;
@@ -142,6 +139,7 @@ struct l_ifreq {
                l_int           ifru_mtu;
                struct l_ifmap  ifru_map;
                char            ifru_slave[LINUX_IFNAMSIZ];
+                char            ifru_newname[LINUX_IFNAMSIZ];
                l_uintptr_t     ifru_data;
        } ifr_ifru;
 } __packed;
diff --git a/bsd/sys/compat/linux/linux_socket.cc 
b/bsd/sys/compat/linux/linux_socket.cc
index 62bc709..9c49111 100644
--- a/bsd/sys/compat/linux/linux_socket.cc
+++ b/bsd/sys/compat/linux/linux_socket.cc
@@ -40,12 +40,14 @@
 #include <bsd/uipc_syscalls.h>
 
 #include <bsd/sys/sys/limits.h>
+#include <bsd/sys/sys/malloc.h>
 #include <bsd/sys/sys/mbuf.h>
 #include <bsd/sys/sys/socket.h>
 #include <bsd/sys/sys/socketvar.h>
 
 
 #include <bsd/sys/net/if.h>
+#include <bsd/sys/net/if_dl.h>
 #include <bsd/sys/netinet/in.h>
 #include <bsd/sys/netinet/in_systm.h>
 #include <bsd/sys/netinet/ip.h>
@@ -57,6 +59,7 @@
 
 #include <bsd/sys/compat/linux/linux.h>
 #include <bsd/sys/compat/linux/linux_socket.h>
+#include <bsd/sys/compat/linux/linux_netlink.h>
 
 #define __NEED_sa_family_t
 #include <bits/alltypes.h>
@@ -186,8 +189,8 @@ linux_getsockaddr(struct bsd_sockaddr **sap, const struct 
bsd_osockaddr *osa, in
                             !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) {
                                sin6->sin6_scope_id = 0;
                        } else {
-                               log(LOG_DEBUG,
-                                   "obsolete pre-RFC2553 bsd_sockaddr_in6 
rejected\n");
+                               bsd_log(LOG_DEBUG,
+                                       "obsolete pre-RFC2553 bsd_sockaddr_in6 
rejected\n");
                                error = EINVAL;
                                goto out;
                        }
@@ -288,6 +291,26 @@ bsd_to_linux_domain(int domain)
 }
 
 static int
+bsd_to_linux_sockopt_level(int level)
+{
+       switch (level) {
+       case SOL_SOCKET:
+               return (LINUX_SOL_SOCKET);
+       }
+       return (level);
+}
+
+static int
+linux_to_bsd_sockopt_level(int level)
+{
+       switch (level) {
+       case LINUX_SOL_SOCKET:
+               return (SOL_SOCKET);
+       }
+       return (level);
+}
+
+static int
 linux_to_bsd_ip_sockopt(int opt)
 {
 
@@ -314,6 +337,106 @@ linux_to_bsd_ip_sockopt(int opt)
        return (-1);
 }
 
+#ifdef INET6
+
+static int
+linux_to_bsd_ipv6_sockopt(int opt)
+{
+
+       switch (opt) {
+       case LINUX_IPV6_ADDRFORM:
+               return (IPV6_ADDRFORM);
+       case LINUX_IPV6_2292PKTINFO:
+               return (IPV6_2292PKTINFO);
+       case LINUX_IPV6_2292HOPOPTS:
+               return (IPV6_2292HOPOPTS);
+       case LINUX_IPV6_2292DSTOPTS:
+               return (IPV6_2292DSTOPTS);
+       case LINUX_IPV6_2292RTHDR:
+               return (IPV6_2292RTHDR);
+       case LINUX_IPV6_2292PKTOPTIONS:
+               return (IPV6_2292PKTOPTIONS);
+       case LINUX_IPV6_CHECKSUM:
+               return (IPV6_CHECKSUM);
+       case LINUX_IPV6_2292HOPLIMIT:
+               return (IPV6_2292HOPLIMIT);
+#ifdef LINUX_IPV6_RXSRCRT
+       case LINUX_IPV6_RXSRCRT:
+               return (IPV6_RXSRCRT);
+#endif
+       case LINUX_IPV6_NEXTHOP:
+               return (IPV6_NEXTHOP);
+       case LINUX_IPV6_AUTHHDR:
+               return (IPV6_AUTHHDR);
+       case LINUX_IPV6_UNICAST_HOPS:
+               return (IPV6_UNICAST_HOPS);
+       case LINUX_IPV6_MULTICAST_IF:
+               return (IPV6_MULTICAST_IF);
+       case LINUX_IPV6_MULTICAST_HOPS:
+               return (IPV6_MULTICAST_HOPS);
+       case LINUX_IPV6_MULTICAST_LOOP:
+               return (IPV6_MULTICAST_LOOP);
+       case LINUX_IPV6_JOIN_GROUP:
+               return (IPV6_JOIN_GROUP);
+       case LINUX_IPV6_LEAVE_GROUP:
+               return (IPV6_LEAVE_GROUP);
+       case LINUX_IPV6_ROUTER_ALERT:
+               return (IPV6_ROUTER_ALERT);
+       case LINUX_IPV6_MTU_DISCOVER:
+               return (IPV6_MTU_DISCOVER);
+       case LINUX_IPV6_MTU:
+               return (IPV6_MTU);
+       case LINUX_IPV6_RECVERR:
+               return (IPV6_RECVERR);
+       case LINUX_IPV6_V6ONLY:
+               return (IPV6_V6ONLY);
+       case LINUX_IPV6_JOIN_ANYCAST:
+               return (IPV6_JOIN_ANYCAST);
+       case LINUX_IPV6_LEAVE_ANYCAST:
+               return (IPV6_LEAVE_ANYCAST);
+       case LINUX_IPV6_IPSEC_POLICY:
+               return (IPV6_IPSEC_POLICY);
+       case LINUX_IPV6_XFRM_POLICY:
+               return (IPV6_XFRM_POLICY);
+       case LINUX_IPV6_RECVPKTINFO:
+               return (IPV6_RECVPKTINFO);
+       case LINUX_IPV6_PKTINFO:
+               return (IPV6_PKTINFO);
+       case LINUX_IPV6_RECVHOPLIMIT:
+               return (IPV6_RECVHOPLIMIT);
+       case LINUX_IPV6_HOPLIMIT:
+               return (IPV6_HOPLIMIT);
+       case LINUX_IPV6_RECVHOPOPTS:
+               return (IPV6_RECVHOPOPTS);
+       case LINUX_IPV6_HOPOPTS:
+               return (IPV6_HOPOPTS);
+       case LINUX_IPV6_RTHDRDSTOPTS:
+               return (IPV6_RTHDRDSTOPTS);
+       case LINUX_IPV6_RECVRTHDR:
+               return (IPV6_RECVRTHDR);
+       case LINUX_IPV6_RTHDR:
+               return (IPV6_RTHDR);
+       case LINUX_IPV6_RECVDSTOPTS:
+               return (IPV6_RECVDSTOPTS);
+       case LINUX_IPV6_DSTOPTS:
+               return (IPV6_DSTOPTS);
+       case LINUX_IPV6_RECVPATHMTU:
+               return (IPV6_RECVPATHMTU);
+       case LINUX_IPV6_PATHMTU:
+               return (IPV6_PATHMTU);
+       case LINUX_IPV6_DONTFRAG:
+               return (IPV6_DONTFRAG);
+       case LINUX_IPV6_RECVTCLASS:
+               return (IPV6_RECVTCLASS);
+       case LINUX_IPV6_TCLASS:
+               return (IPV6_TCLASS);
+       }
+       return (-1);
+}
+
+#endif // INET6
+
+
 static int
 linux_to_bsd_so_sockopt(int opt)
 {
@@ -407,7 +530,7 @@ bsd_to_linux_sockaddr(struct bsd_sockaddr *sa)
 
        u_short family = sa->sa_family;
        *(u_short *)sa = family;
-       
+
        return (0);
 }
 
@@ -438,47 +561,114 @@ linux_sa_put(struct bsd_osockaddr *osa)
        return (0);
 }
 
-#if 0
 static int
-linux_to_bsd_cmsg_type(int cmsg_type)
+linux_to_bsd_cmsg_type(int cmsg_level, int cmsg_type)
 {
-
-       switch (cmsg_type) {
-       case LINUX_SCM_RIGHTS:
-               return (SCM_RIGHTS);
-       case LINUX_SCM_CREDENTIALS:
-               return (SCM_CREDS);
+       switch(cmsg_level) {
+       case LINUX_SOL_SOCKET:
+               switch (cmsg_type) {
+#if 0
+               case LINUX_SCM_RIGHTS:
+                       return (SCM_RIGHTS);
+               case LINUX_SCM_CREDENTIALS:
+                       return (SCM_CREDS);
+#endif
+               case LINUX_SCM_TIMESTAMP:
+                       return (SCM_TIMESTAMP);
+               }
+               break;
+       case IPPROTO_IP:
+               switch (cmsg_type) {
+               case IP_PKTINFO:
+                       return cmsg_type;
+               }
+               break;
+#ifdef INET6
+       case IPPROTO_IPV6:
+               switch (cmsg_type) {
+               case IPV6_PKTINFO:
+                       return cmsg_type;
+               }
+               break;
+#endif
        }
        return (-1);
 }
 
 static int
-bsd_to_linux_cmsg_type(int cmsg_type)
+bsd_to_linux_cmsg_type(int cmsg_level, int cmsg_type)
 {
 
-       switch (cmsg_type) {
-       case SCM_RIGHTS:
-               return (LINUX_SCM_RIGHTS);
-       case SCM_CREDS:
-               return (LINUX_SCM_CREDENTIALS);
+       switch (cmsg_level) {
+       case SOL_SOCKET:
+               switch (cmsg_type) {
+#if 0
+               case SCM_RIGHTS:
+                       return (LINUX_SCM_RIGHTS);
+               case SCM_CREDS:
+                       return (LINUX_SCM_CREDENTIALS);
+#endif
+               case SCM_TIMESTAMP:
+                       return (LINUX_SCM_TIMESTAMP);
+               }
+               break;
+       case IPPROTO_IP:
+               switch (cmsg_type) {
+               case IP_RECVIF:
+               case IP_RECVDSTADDR:
+                       // IP_RECVIF and IP_RECVDSTADDR get combined into 
IP_PKTINFO
+                       return IP_PKTINFO;
+               case IP_PKTINFO:
+                       return cmsg_type;
+               }
+               break;
+#ifdef INET6
+       case IPPROTO_IPV6:
+               switch (cmsg_type) {
+               case IPV6_PKTINFO:
+                       return cmsg_type;
+               }
+               break;
+#endif
        }
+
        return (-1);
 }
 
-#endif
-
 static int
-linux_to_bsd_msghdr(struct msghdr *hdr)
+linux_to_bsd_msghdr(struct msghdr *bhdr, const struct l_msghdr *lhdr)
 {
-       /* Ignore msg_control in OSv */
-       hdr->msg_control = NULL;
-       hdr->msg_flags = linux_to_bsd_msg_flags(hdr->msg_flags);
+       if (lhdr->msg_controllen > INT_MAX)
+               return (ENOBUFS);
+
+       bhdr->msg_name          = (void *)lhdr->msg_name;
+       bhdr->msg_namelen = lhdr->msg_namelen;
+       bhdr->msg_iov                   = (iovec *)lhdr->msg_iov;
+       bhdr->msg_iovlen        = lhdr->msg_iovlen;
+       bhdr->msg_control = (void *)lhdr->msg_control;
+
+       /*
+        * msg_controllen is skipped since BSD and LINUX control messages
+        * are potentially different sizes (e.g. the cred structure used
+        * by SCM_CREDS is different between the two operating system).
+        *
+        * The caller can set it (if necessary) after converting all the
+        * control messages.
+        */
+
+       bhdr->msg_flags = linux_to_bsd_msg_flags(lhdr->msg_flags);
        return (0);
 }
 
 static int
-bsd_to_linux_msghdr(const struct msghdr *hdr)
+bsd_to_linux_msghdr(const struct msghdr *bhdr, struct l_msghdr *lhdr)
 {
+       lhdr->msg_name          = (l_uintptr_t)bhdr->msg_name;
+       lhdr->msg_namelen = bhdr->msg_namelen;
+       lhdr->msg_iov                   = (l_uintptr_t)bhdr->msg_iov;
+       lhdr->msg_iovlen        = bhdr->msg_iovlen;
+       lhdr->msg_control = (l_uintptr_t)bhdr->msg_control;
+
        /*
         * msg_controllen is skipped since BSD and LINUX control messages
         * are potentially different sizes (e.g. the cred structure used
@@ -519,8 +709,11 @@ linux_sendit(int s, struct msghdr *mp, int flags,
 
        if (mp->msg_name != NULL) {
                error = linux_getsockaddr(&to, (const 
bsd_osockaddr*)mp->msg_name, mp->msg_namelen);
-               if (error)
+               if (error) {
+                       if (control)
+                               m_freem(control);
                        return (error);
+               }
                mp->msg_name = to;
        } else
                to = NULL;
@@ -637,13 +830,13 @@ linux_socket(int domain, int type, int protocol, int 
*out_fd)
         * For simplicity we do this unconditionally of the net.inet6.ip6.v6only
         * sysctl value.
         */
-       if (bsd_args.domain == PF_INET6) {
+       if (domain == PF_INET6) {
                int v6only;
 
                v6only = 0;
                /* We ignore any error returned by setsockopt() */
-               kern_setsockopt(td, td->td_retval[0], IPPROTO_IPV6, IPV6_V6ONLY,
-                   &v6only, UIO_SYSSPACE, sizeof(v6only));
+               kern_setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
+                   &v6only, sizeof(v6only));
        }
 #endif
 
@@ -897,7 +1090,7 @@ linux_recvfrom(int s, void* buf, size_t len, int flags,
        error = sys_recvfrom(s, (caddr_t)buf, len, bsd_flags, from,
                fromlen, bytes);
        bsd_to_linux_sockaddr(from);
-       
+
        if (error)
                return (error);
        if (from) {
@@ -909,18 +1102,20 @@ linux_recvfrom(int s, void* buf, size_t len, int flags,
 }
 
 int
-linux_sendmsg(int s, struct msghdr* msg, int flags, ssize_t* bytes)
+linux_sendmsg(int s, struct l_msghdr* linux_msg, int flags, ssize_t* bytes)
 {
 #if 0
-       struct cmsghdr *cmsg;
-       struct mbuf *control;
+       sa_family_t sa_family;
+       struct bsd_sockaddr *sa;
        struct iovec *iov;
+#endif
+       struct l_cmsghdr *linux_cmsg;
+       struct cmsghdr *cmsg;
+       struct mbuf *control = 0;
        socklen_t datalen;
-       struct bsd_sockaddr *sa;
-       sa_family_t sa_family;
        void *data;
-#endif
 
+       struct msghdr msg;
        int error;
 
        /*
@@ -930,106 +1125,128 @@ linux_sendmsg(int s, struct msghdr* msg, int flags, 
ssize_t* bytes)
         * order to handle this case.  This should be checked, but allows the
         * Linux ping to work.
         */
-       if (msg->msg_control != NULL && msg->msg_controllen == 0)
-               msg->msg_control = NULL;
 
-       /* FIXME: Translate msg control */
-       assert(msg->msg_control == NULL);
+       if (linux_msg->msg_control != NULL && linux_msg->msg_controllen == 0)
+               linux_msg->msg_control = NULL;
 
-       error = linux_to_bsd_msghdr(msg);
+       error = linux_to_bsd_msghdr(&msg, linux_msg);
        if (error)
                return (error);
 
-       /* FIXME: OSv - cmsgs translation is done credentials and rights,
-          we ignore those in OSv. */
+       /* Linux to BSD cmsgs translation */
+       if ((linux_cmsg = LINUX_CMSG_FIRSTHDR(linux_msg)) != NULL) {
+               uint8_t cmsg_buf[CMSG_HDRSZ];
+
 #if 0
-       if ((ptr_cmsg = LINUX_CMSG_FIRSTHDR(&linux_msg)) != NULL) {
+               // TODO: This causes unnecessary malloc/free
+               //       Does this really need to be done?
                error = kern_getsockname(td, args->s, &sa, &datalen);
                if (error)
                        goto bad;
                sa_family = sa->sa_family;
-               free(sa, M_SONAME);
+               free(sa);
+#endif
 
+               cmsg = (struct cmsghdr*) cmsg_buf;
                error = ENOBUFS;
-               cmsg = malloc(CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO);
                control = m_get(M_WAIT, MT_CONTROL);
                if (control == NULL)
                        goto bad;
 
                do {
-                       error = copyin(ptr_cmsg, &linux_cmsg,
-                           sizeof(struct l_cmsghdr));
-                       if (error)
-                               goto bad;
-
                        error = EINVAL;
-                       if (linux_cmsg.cmsg_len < sizeof(struct l_cmsghdr))
+                       if (linux_cmsg->cmsg_len < sizeof(struct l_cmsghdr))
                                goto bad;
 
-                       /*
-                        * Now we support only SCM_RIGHTS and SCM_CRED,
-                        * so return EINVAL in any other cmsg_type
-                        */
                        cmsg->cmsg_type =
-                           linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type);
+                               linux_to_bsd_cmsg_type(linux_cmsg->cmsg_level, 
linux_cmsg->cmsg_type);
                        cmsg->cmsg_level =
-                           linux_cmsg.cmsg_level;
-                       if (cmsg->cmsg_type linux_sendmsg== -1
-                           || cmsg->cmsg_level != SOL_SOCKET)
+                               
linux_to_bsd_sockopt_level(linux_cmsg->cmsg_level);
+                       if (cmsg->cmsg_type == -1)
                                goto bad;
 
-                       /*
-                        * Some applications (e.g. pulseaudio) attempt to
-                        * send ancillary data even if the underlying protocol
-                        * doesn't support it which is not allowed in the
-                        * FreeBSD system call interface.
-                        */
-                       if (sa_family != AF_UNIX)
-                               continue;
-
-                       data = LINUX_CMSG_DATA(ptr_cmsg);
-                       datalen = linux_cmsg.cmsg_len - L_CMSG_HDRSZ;
-
-                       switch (cmsg->cmsg_type)
-                       {
-                       case SCM_RIGHTS:
-                               break;
-
-                       case SCM_CREDS:
-                               data = &cmcred;
-                               datalen = sizeof(cmcred);
+                       data = LINUX_CMSG_DATA(linux_cmsg);
+                       datalen = linux_cmsg->cmsg_len - L_CMSG_HDRSZ;
 
+                       if (cmsg->cmsg_level == SOL_SOCKET) {
+#if 0
                                /*
-                                * The lower levels will fill in the structure
+                                * Some applications (e.g. pulseaudio) attempt 
to
+                                * send ancillary data even if the underlying 
protocol
+                                * doesn't support it which is not allowed in 
the
+                                * FreeBSD system call interface.
                                 */
-                               bzero(data, datalen);
-                               break;
+                               if (sa_family != AF_UNIX)
+                                       continue;
+
+                               switch (cmsg->cmsg_type) {
+                               case SCM_RIGHTS:
+                                       break;
+
+                               case SCM_CREDS:
+                                       data = &cmcred;
+                                       datalen = sizeof(cmcred);
+
+                                       /*
+                                        * The lower levels will fill in the 
structure
+                                        */
+                                       bzero(data, datalen);
+                                       break;
+                               default:
+                                       goto bad;
+                               }
+#else
+                               goto bad;
+#endif
+                       }
+                       else if (cmsg->cmsg_level == IPPROTO_IP) {
+                               switch(cmsg->cmsg_type) {
+                               case IP_PKTINFO:
+                                       break;
+                               default:
+                                       goto bad;
+                               }
+                       }
+#ifdef INET6
+                       else if (cmsg->cmsg_level == IPPROTO_IPV6) {
+                               switch(cmsg->cmsg_type) {
+                               case IPV6_PKTINFO:
+                                       break;
+                               default:
+                                       goto bad;
+                               }
+                       }
+#endif /* INET6 */
+                       else {
+                               goto bad;
                        }
 
                        cmsg->cmsg_len = CMSG_LEN(datalen);
 
                        error = ENOBUFS;
-                       if (!m_append(control, CMSG_HDRSZ, (c_caddr_t)cmsg))
-                               goto bad;
-                       if (!m_append(control, datalen, (c_caddr_t)data))
+                       if (!m_append(control, CMSG_HDRSZ, (c_caddr_t)cmsg) ||
+                           !m_append(control, datalen, (c_caddr_t)data)) {
                                goto bad;
-               } while ((ptr_cmsg = LINUX_CMSG_NXTHDR(&linux_msg, ptr_cmsg)));
+                       }
+
+               } while ((linux_cmsg = LINUX_CMSG_NXTHDR(linux_msg, 
linux_cmsg)));
 
                if (m_length(control, NULL) == 0) {
                        m_freem(control);
                        control = NULL;
                }
        }
-#endif
-
-       error = linux_sendit(s, msg, flags, NULL, bytes);
 
-#if 0
+       error = linux_sendit(s, &msg, flags, control, bytes);
+       control = NULL; /* transfered ownership of control mbuf */
 bad:
+#if 0
        free(iov);
        if (cmsg)
                free(cmsg);
 #endif
+       if (control)
+               m_freem(control);
        return (error);
 }
 
@@ -1039,156 +1256,241 @@ struct linux_recvmsg_args {
        int flags;
 };
 
-/* FIXME: OSv - flags are ignored, the flags
- * inside the msghdr are used instead */
 int
-linux_recvmsg(int s, struct msghdr *msg, int flags, ssize_t* bytes)
+linux_recvmsg_append_cmsg(caddr_t buf, socklen_t buflen,
+                                                 struct l_cmsghdr *linux_cmsg, 
caddr_t data, socklen_t datalen)
 {
-#if 0
+       int error;
+       caddr_t dst = buf;
+
+       if (LINUX_CMSG_LEN(datalen) > buflen)
+               return EMSGSIZE;
+
+       error = copyout(linux_cmsg, dst, L_CMSG_HDRSZ);
+       if (error)
+               return error;
+       dst += L_CMSG_HDRSZ;
+
+       error = copyout(data, dst, datalen);
+       if (error)
+               return error; 
+
+       return 0;
+}
+
+int
+linux_recvmsg(int s, struct l_msghdr *linux_msg, int flags, ssize_t* bytes)
+{
+       struct cmsghdr *cm;
+       struct msghdr msg;
        socklen_t datalen, outlen;
        struct mbuf *control = NULL;
-       struct mbuf **controlp;
+       struct mbuf **controlp = NULL;
        caddr_t outbuf;
        void *data;
-       int error, i, fd, fds, *fdp;
-#endif
        int error;
-       error = linux_to_bsd_msghdr(msg);
+
+       error = linux_to_bsd_msghdr(&msg, linux_msg);
        if (error)
                return (error);
 
-       if (msg->msg_name) {
-               error = linux_to_bsd_sockaddr((struct bsd_sockaddr 
*)msg->msg_name,
-                   msg->msg_namelen);
+       /*
+        * Set msg_flags from flags parameter like sys_recvmsg() for standard 
behavior.
+        * msg_flags in msghdr passed to kern_recvit() are used as in/out.
+        * msg_flags in msghdr passed to recvmsg() are used for out only and the
+        * flags paramter is used for in.
+        *
+        */
+       msg.msg_flags = linux_to_bsd_msg_flags(flags);
+
+       if (msg.msg_name) {
+               error = linux_to_bsd_sockaddr((struct bsd_sockaddr 
*)msg.msg_name,
+                       msg.msg_namelen);
                if (error)
                        goto bad;
        }
 
-       assert(msg->msg_control == NULL);
-
-       error = kern_recvit(s, msg, NULL, bytes);
+       controlp = (msg.msg_control != NULL) ? &control : NULL;
+       error = kern_recvit(s, &msg, controlp, bytes);
        if (error)
                goto bad;
 
-       error = bsd_to_linux_msghdr(msg);
+       error = bsd_to_linux_msghdr(&msg, linux_msg);
        if (error)
                goto bad;
 
-       if (msg->msg_name) {
-               error = bsd_to_linux_sockaddr((struct bsd_sockaddr 
*)msg->msg_name);
+       if (linux_msg->msg_name) {
+               error = bsd_to_linux_sockaddr((struct bsd_sockaddr 
*)linux_msg->msg_name);
                if (error)
                        goto bad;
        }
-       if (msg->msg_name && msg->msg_namelen > 2) {
-               error = linux_sa_put((bsd_osockaddr*)msg->msg_name);
+       if (linux_msg->msg_name && linux_msg->msg_namelen > 2) {
+               error = linux_sa_put((bsd_osockaddr*)linux_msg->msg_name);
                if (error)
                        goto bad;
        }
 
-       assert(msg->msg_controllen == 0);
-       assert(msg->msg_control == NULL);
+       outbuf = (caddr_t)(linux_msg->msg_control);
+       outlen = 0;
 
-#if 0
-       if (control) {
-               linux_cmsg = malloc(L_CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO);
-
-               msg.msg_control = mtod(control, struct cmsghdr *);
-               msg.msg_controllen = control->m_hdr.mh_len;
-
-               cm = CMSG_FIRSTHDR(&msg);
-
-               while (cm != NULL) {
-                       linux_cmsg->cmsg_type =
-                           bsd_to_linux_cmsg_type(cm->cmsg_type);
-                       linux_cmsg->cmsg_level =
-                           bsd_to_linux_sockopt_level(cm->cmsg_level);
-                       if (linux_cmsg->cmsg_type == -1
-                           || cm->cmsg_level != SOL_SOCKET)
-                       {
-                               error = EINVAL;
-                               goto bad;
-                       }
+       if (control && outbuf) {
+               struct mbuf *c_mb;
+               uint8_t cmsg_buf[L_CMSG_HDRSZ];
+               struct l_cmsghdr *linux_cmsg = (struct l_cmsghdr *)cmsg_buf;
+               struct in_addr *ipv4_recv_addr = NULL;
+               struct bsd_sockaddr_dl *recv_addr_dl = NULL;
+               struct timeval *ftmvl;
+               l_timeval ltmvl;
 
-                       data = CMSG_DATA(cm);
-                       datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
-
-                       switch (cm->cmsg_type)
-                       {
-                       case SCM_RIGHTS:
-                               if (args->flags & LINUX_MSG_CMSG_CLOEXEC) {
-                                       fds = datalen / sizeof(int);
-                                       fdp = data;
-                                       for (i = 0; i < fds; i++) {
-                                               fd = *fdp++;
-                                               (void)kern_fcntl(td, fd,
-                                                   F_SETFD, FD_CLOEXEC);
-                                       }
+               for (c_mb = control; c_mb; c_mb = c_mb->m_hdr.mh_next) {
+
+                       msg.msg_control = mtod(c_mb, struct cmsghdr *);
+                       msg.msg_controllen = c_mb->m_hdr.mh_len;
+
+                       cm = CMSG_FIRSTHDR(&msg);
+
+                       while (cm != NULL) {
+                               linux_cmsg->cmsg_type =
+                                       bsd_to_linux_cmsg_type(cm->cmsg_level, 
cm->cmsg_type);
+                               linux_cmsg->cmsg_level =
+                                       
bsd_to_linux_sockopt_level(cm->cmsg_level);
+                               if (linux_cmsg->cmsg_type == -1) {
+                                       error = EINVAL;
+                                       goto bad;
                                }
-                               break;
 
-                       case SCM_CREDS:
-                               /*
-                                * Currently LOCAL_CREDS is never in
-                                * effect for Linux so no need to worry
-                                * about sockcred
-                                */
-                               if (datalen != sizeof(*cmcred)) {
-                                       error = EMSGSIZE;
+                               data = CMSG_DATA(cm);
+                               datalen = (caddr_t)cm + cm->cmsg_len - 
(caddr_t)data;
+
+                               if (cm->cmsg_level == SOL_SOCKET) {
+                                       switch (cm->cmsg_type) {
+#if 0
+                                       case SCM_RIGHTS:
+                                               if (args->flags & 
LINUX_MSG_CMSG_CLOEXEC) {
+                                                       fds = datalen / 
sizeof(int);
+                                                       fdp = data;
+                                                       for (i = 0; i < fds; 
i++) {
+                                                               fd = *fdp++;
+                                                               
(void)kern_fcntl(td, fd,
+                                                                               
                 F_SETFD, FD_CLOEXEC);
+                                                       }
+                                               }
+                                               break;
+
+                                       case SCM_CREDS:
+                                               /*
+                                                * Currently LOCAL_CREDS is 
never in
+                                                * effect for Linux so no need 
to worry
+                                                * about sockcred
+                                                */
+                                               if (datalen != sizeof(*cmcred)) 
{
+                                                       error = EMSGSIZE;
+                                                       goto bad;
+                                               }
+                                               cmcred = (struct cmsgcred 
*)data;
+                                               bzero(&linux_ucred, 
sizeof(linux_ucred));
+                                               linux_ucred.pid = 
cmcred->cmcred_pid;
+                                               linux_ucred.uid = 
cmcred->cmcred_uid;
+                                               linux_ucred.gid = 
cmcred->cmcred_gid;
+                                               data = &linux_ucred;
+                                               datalen = sizeof(linux_ucred);
+                                               break;
+#endif
+                                       case SCM_TIMESTAMP:
+                                               if (datalen != sizeof(struct 
timeval)) {
+                                                       error = EMSGSIZE;
+                                                       goto bad;
+                                               }
+                                               ftmvl = (struct timeval *)data;
+                                               ltmvl.tv_sec = ftmvl->tv_sec;
+                                               ltmvl.tv_usec = ftmvl->tv_usec;
+                                               data = &ltmvl;
+                                               datalen = sizeof(ltmvl);
+                                               break;
+                                       default:
+                                               error = EINVAL;
+                                               goto bad;
+                                       }
+                               }
+                               else if (cm->cmsg_level == IPPROTO_IP) {
+                                       switch (cm->cmsg_type) {
+                                       case IP_RECVIF:
+                                               recv_addr_dl = (struct 
bsd_sockaddr_dl *) data;
+                                               goto next;
+                                       case IP_RECVDSTADDR:
+                                               ipv4_recv_addr = (struct 
in_addr *) data;
+                                               goto next;
+                                       default:
+                                               error = EINVAL;
+                                               goto bad;
+                                       }
+                               }
+#ifdef INET6
+                               else if (cm->cmsg_level == IPPROTO_IPV6) {
+                                       switch (cm->cmsg_type) {
+                                       case IPV6_PKTINFO:
+                                               break;
+                                       default:
+                                               error = EINVAL;
+                                               goto bad;
+                                       }
+                               }
+#endif
+                               else {
+                                       error = EINVAL;
                                        goto bad;
                                }
-                               cmcred = (struct cmsgcred *)data;
-                               bzero(&linux_ucred, sizeof(linux_ucred));
-                               linux_ucred.pid = cmcred->cmcred_pid;
-                               linux_ucred.uid = cmcred->cmcred_uid;
-                               linux_ucred.gid = cmcred->cmcred_gid;
-                               data = &linux_ucred;
-                               datalen = sizeof(linux_ucred);
-                               break;
-                       }
 
-                       if (outlen + LINUX_CMSG_LEN(datalen) >
-                           linux_msg.msg_controllen) {
-                               if (outlen == 0) {
-                                       error = EMSGSIZE;
+                               linux_cmsg->cmsg_len = LINUX_CMSG_LEN(datalen);
+                               error = linux_recvmsg_append_cmsg(outbuf, 
linux_msg->msg_controllen - outlen,
+                                                                 linux_cmsg, 
(caddr_t)data, datalen);
+                               if (error) {
+                                       if (outlen) {
+                                               linux_msg->msg_flags |= 
LINUX_MSG_CTRUNC;
+                                               error = 0;
+                                               goto out;
+                                       }
                                        goto bad;
-                               } else {
-                                       linux_msg.msg_flags |=
-                                           LINUX_MSG_CTRUNC;
-                                       goto out;
                                }
-                       }
+                               outbuf += LINUX_CMSG_ALIGN(datalen);
+                               outlen += LINUX_CMSG_LEN(datalen);
 
-                       linux_cmsg->cmsg_len = LINUX_CMSG_LEN(datalen);
+next:
+                               cm = CMSG_NXTHDR(&msg, cm);
+                       }
+               }
 
-                       error = copyout(linux_cmsg, outbuf, L_CMSG_HDRSZ);
-                       if (error)
-                               goto bad;
-                       outbuf += L_CMSG_HDRSZ;
+               /* FreeBSD doesn't support IP_PKTINFO so build from IP_RECVIF 
and IP_RECVDSTADDR */
+               if (recv_addr_dl && ipv4_recv_addr) {
+                       struct l_in_pktinfo pktinfo;
+                       pktinfo.ipi_ifindex = recv_addr_dl->sdl_index;
+                       pktinfo.ipi_spec_dst.s_addr = 0;
+                       pktinfo.ipi_addr.s_addr = ipv4_recv_addr->s_addr;
+                       datalen = sizeof(pktinfo);
 
-                       error = copyout(data, outbuf, datalen);
-                       if (error)
+                       linux_cmsg->cmsg_type = LINUX_IP_PKTINFO;
+                       linux_cmsg->cmsg_len = LINUX_CMSG_LEN(datalen);
+                       error = linux_recvmsg_append_cmsg(outbuf, 
linux_msg->msg_controllen - outlen,
+                                                         linux_cmsg, 
(caddr_t)&pktinfo, datalen);
+                       if (error) {
+                               if (outlen) {
+                                       linux_msg->msg_flags |= 
LINUX_MSG_CTRUNC;
+                                       error = 0;
+                                       goto out;
+                               }
                                goto bad;
-
+                       }
                        outbuf += LINUX_CMSG_ALIGN(datalen);
                        outlen += LINUX_CMSG_LEN(datalen);
-
-                       cm = CMSG_NXTHDR(&msg, cm);
                }
        }
 
 out:
-       linux_msg.msg_controllen = outlen;
-       error = copyout(&linux_msg, PTRIN(args->msg), sizeof(linux_msg));
+       linux_msg->msg_controllen = outlen;
 
 bad:
-       free(iov);
        if (control != NULL)
                m_freem(control);
-       if (linux_cmsg != NULL)
-               free(linux_cmsg);
-#endif
-
-bad:
 
        return (error);
 }
@@ -1224,6 +1526,35 @@ int linux_to_bsd_tcp_sockopt(int name)
 }
 
 int
+linux_setsockopt_ip_pktinfo(int s, caddr_t val, int valsize)
+{
+       int error;
+
+       if ((error = sys_setsockopt(s, IPPROTO_IP, IP_RECVIF, val, valsize)))
+               return error;
+       return sys_setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, val, valsize);
+}
+
+int
+linux_getsockopt_ip_pktinfo(int s, void *val, socklen_t *valsize)
+{
+       int error;
+       int if_enable = 0, addr_enable = 0;
+       socklen_t optsize = sizeof(addr_enable);
+
+       if (*valsize < sizeof(addr_enable)) {
+               errno = EINVAL;
+               return -1;
+       }
+       if ((error = sys_getsockopt(s, IPPROTO_IP, IP_RECVIF, &if_enable, 
&optsize)))
+               return error;
+       if ((error = sys_getsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, 
&addr_enable, &optsize)))
+               return error;
+       *(int *) val = (if_enable && addr_enable);
+       return 0;
+}
+
+int
 linux_setsockopt(int s, int level, int name, caddr_t val, int valsize)
 {
        int error;
@@ -1233,8 +1564,16 @@ linux_setsockopt(int s, int level, int name, caddr_t 
val, int valsize)
                name = linux_to_bsd_so_sockopt(name);
                break;
        case IPPROTO_IP:
+               if (name == LINUX_IP_PKTINFO) {
+                       return linux_setsockopt_ip_pktinfo(s, val, valsize);
+               }
                name = linux_to_bsd_ip_sockopt(name);
                break;
+#ifdef INET6
+       case IPPROTO_IPV6:
+               name = linux_to_bsd_ipv6_sockopt(name);
+               break;
+#endif
        case IPPROTO_TCP:
                name = linux_to_bsd_tcp_sockopt(name);
                break;
@@ -1269,8 +1608,16 @@ linux_getsockopt(int s, int level, int name, void *val, 
socklen_t *valsize)
                name = linux_to_bsd_so_sockopt(name);
                break;
        case IPPROTO_IP:
+               if (name == LINUX_IP_PKTINFO) {
+                       return linux_getsockopt_ip_pktinfo(s, val, valsize);
+               }
                name = linux_to_bsd_ip_sockopt(name);
                break;
+#ifdef INET6
+       case IPPROTO_IPV6:
+               name = linux_to_bsd_ipv6_sockopt(name);
+               break;
+#endif
        case IPPROTO_TCP:
                name = linux_to_bsd_tcp_sockopt(name);
                break;
diff --git a/bsd/sys/compat/linux/linux_socket.h 
b/bsd/sys/compat/linux/linux_socket.h
index ff14200..e63ef9a 100644
--- a/bsd/sys/compat/linux/linux_socket.h
+++ b/bsd/sys/compat/linux/linux_socket.h
@@ -6,7 +6,7 @@
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer 
+ *    notice, this list of conditions and the following disclaimer
  *    in this position and unchanged.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
@@ -54,6 +54,29 @@
 
 #define LINUX_SCM_RIGHTS       0x01
 #define LINUX_SCM_CREDENTIALS   0x02
+#define LINUX_SCM_TIMESTAMP    0x1D
+
+struct l_msghdr {
+       l_uintptr_t     msg_name;
+       l_int           msg_namelen;
+       l_uintptr_t     msg_iov;
+       l_size_t        msg_iovlen;
+       l_uintptr_t     msg_control;
+       l_size_t        msg_controllen;
+       l_uint          msg_flags;
+};
+
+struct l_mmsghdr {
+       struct l_msghdr msg_hdr;
+       l_uint          msg_len;
+
+};
+
+struct l_cmsghdr {
+       l_size_t        cmsg_len;
+       l_int           cmsg_level;
+       l_int           cmsg_type;
+};
 
 /* Ancilliary data object information macros */
 
@@ -68,13 +91,13 @@
                                ((msg)->msg_controllen >= \
                                    sizeof(struct l_cmsghdr) ? \
                                    (struct l_cmsghdr *) \
-                                       PTRIN((msg)->msg_control) : \
+                                       ((msg)->msg_control) : \
                                    (struct l_cmsghdr *)(NULL))
 #define LINUX_CMSG_NXTHDR(msg, cmsg) \
                                ((((char *)(cmsg) + \
                                    LINUX_CMSG_ALIGN((cmsg)->cmsg_len) + \
                                    sizeof(*(cmsg))) > \
-                                   (((char *)PTRIN((msg)->msg_control)) + \
+                                   (((char *)((msg)->msg_control)) + \
                                    (msg)->msg_controllen)) ? \
                                    (struct l_cmsghdr *) NULL : \
                                    (struct l_cmsghdr *)((char *)(cmsg) + \
@@ -93,6 +116,7 @@
 #define        LINUX_AF_APPLETALK      5
 #define        LINUX_AF_INET6          10
 #define LINUX_AF_NETLINK       16
+#define LINUX_AF_PACKET                17
 
 /* Supported socket types */
 
@@ -117,11 +141,25 @@ struct l_ucred {
        uint32_t        gid;
 };
 
+struct l_in_addr {
+       uint32_t        s_addr;
+};
+
+struct l_in_pktinfo {
+       l_uint                  ipi_ifindex;
+       struct l_in_addr        ipi_spec_dst;
+       struct l_in_addr        ipi_addr;
+};
+
 /* Socket options */
 #define        LINUX_IP_TOS            1
 #define        LINUX_IP_TTL            2
 #define        LINUX_IP_HDRINCL        3
 #define        LINUX_IP_OPTIONS        4
+#define LINUX_IP_ROUTER_ALERT  5
+#define LINUX_IP_RECVOPTS      6
+#define LINUX_IP_RETOPTS       7
+#define LINUX_IP_PKTINFO       8
 
 #define        LINUX_IP_MULTICAST_IF           32
 #define        LINUX_IP_MULTICAST_TTL          33
@@ -129,4 +167,61 @@ struct l_ucred {
 #define        LINUX_IP_ADD_MEMBERSHIP         35
 #define        LINUX_IP_DROP_MEMBERSHIP        36
 
+
+#define LINUX_IPV6_ADDRFORM            1
+#define LINUX_IPV6_2292PKTINFO         2
+#define LINUX_IPV6_2292HOPOPTS         3
+#define LINUX_IPV6_2292DSTOPTS         4
+#define LINUX_IPV6_2292RTHDR           5
+#define LINUX_IPV6_2292PKTOPTIONS      6
+#define LINUX_IPV6_CHECKSUM            7
+#define LINUX_IPV6_2292HOPLIMIT                8
+
+#define LINUX_SCM_SRCRT                        LINUX_IPV6_RXSRCRT
+
+#define LINUX_IPV6_NEXTHOP             9
+#define LINUX_IPV6_AUTHHDR             10
+#define LINUX_IPV6_UNICAST_HOPS                16
+#define LINUX_IPV6_MULTICAST_IF                17
+#define LINUX_IPV6_MULTICAST_HOPS      18
+#define LINUX_IPV6_MULTICAST_LOOP      19
+#define LINUX_IPV6_JOIN_GROUP          20
+#define LINUX_IPV6_LEAVE_GROUP         21
+#define LINUX_IPV6_ROUTER_ALERT                22
+#define LINUX_IPV6_MTU_DISCOVER                23
+#define LINUX_IPV6_MTU                 24
+#define LINUX_IPV6_RECVERR             25
+#define LINUX_IPV6_V6ONLY              26
+#define LINUX_IPV6_JOIN_ANYCAST                27
+#define LINUX_IPV6_LEAVE_ANYCAST       28
+#define LINUX_IPV6_IPSEC_POLICY                34
+#define LINUX_IPV6_XFRM_POLICY         35
+
+/* Advanced API (RFC3542) (1).  */
+#define LINUX_IPV6_RECVPKTINFO         49
+#define LINUX_IPV6_PKTINFO             50
+#define LINUX_IPV6_RECVHOPLIMIT                51
+#define LINUX_IPV6_HOPLIMIT            52
+#define LINUX_IPV6_RECVHOPOPTS         53
+#define LINUX_IPV6_HOPOPTS             54
+#define LINUX_IPV6_RTHDRDSTOPTS                55
+#define LINUX_IPV6_RECVRTHDR           56
+#define LINUX_IPV6_RTHDR               57
+#define LINUX_IPV6_RECVDSTOPTS         58
+#define LINUX_IPV6_DSTOPTS             59
+#define LINUX_IPV6_RECVPATHMTU         60
+#define LINUX_IPV6_PATHMTU             61
+#define LINUX_IPV6_DONTFRAG            62
+
+/* Advanced API (RFC3542) (2).  */
+#define LINUX_IPV6_RECVTCLASS          66
+#define LINUX_IPV6_TCLASS              67
+
+/* Obsolete synonyms for the above.  */
+#define LINUX_IPV6_ADD_MEMBERSHIP      LINUX_IPV6_JOIN_GROUP
+#define LINUX_IPV6_DROP_MEMBERSHIP     LINUX_IPV6_LEAVE_GROUP
+#define LINUX_IPV6_RXHOPOPTS           LINUX_IPV6_HOPOPTS
+#define LINUX_IPV6_RXDSTOPTS           LINUX_IPV6_DSTOPTS
+
+
 #endif /* _LINUX_SOCKET_H_ */
diff --git a/bsd/sys/kern/uipc_syscalls.cc b/bsd/sys/kern/uipc_syscalls.cc
index 9f8db3f..21a9e89 100644
--- a/bsd/sys/kern/uipc_syscalls.cc
+++ b/bsd/sys/kern/uipc_syscalls.cc
@@ -443,7 +443,7 @@ sys_socketpair(int domain, int type, int protocol, int *rsv)
 static int
 sendit(int s, struct msghdr* mp, int flags, ssize_t* bytes)
 {
-       struct mbuf *control;
+       struct mbuf *control = NULL;
        struct bsd_sockaddr *to;
        int error;
 
@@ -480,7 +480,7 @@ kern_sendit(int s,
             struct mbuf *control,
             ssize_t *bytes)
 {
-       struct file *fp;
+       struct file *fp = NULL;
        struct uio auio = {};
        struct iovec *iov;
        struct socket *so;
@@ -488,16 +488,19 @@ kern_sendit(int s,
        int i, error;
        ssize_t len;
 
-       error = getsock_cap(s, &fp, NULL);
-       if (error)
-               return (error);
-       so = (struct socket *)file_data(fp);
 
        // Create a local copy of the user's iovec - sosend() is going to 
change it!
-       std::vector<iovec> uio_iov(mp->msg_iov, mp->msg_iov + mp->msg_iovlen);
+       assert(mp->msg_iovlen <= UIO_MAXIOV);
+       struct iovec uio_iov[mp->msg_iovlen];
+       memcpy(uio_iov, mp->msg_iov, sizeof(uio_iov));
+
+       error = getsock_cap(s, &fp, NULL);
+       if (error) goto bad;
+
+       so = (struct socket *)file_data(fp);
 
-       auio.uio_iov = uio_iov.data();
-       auio.uio_iovcnt = uio_iov.size();
+       auio.uio_iov = uio_iov;
+       auio.uio_iovcnt = mp->msg_iovlen;;
        auio.uio_rw = UIO_WRITE;
        auio.uio_offset = 0;                    /* XXX */
        auio.uio_resid = 0;
@@ -511,6 +514,7 @@ kern_sendit(int s,
        len = auio.uio_resid;
        from = (struct bsd_sockaddr*)mp->msg_name;
        error = sosend(so, from, &auio, 0, control, flags, 0);
+       control = NULL; /* transfered ownership of control mbuf */
        if (error) {
                if (auio.uio_resid != len && (error == ERESTART ||
                    error == EINTR || error == EWOULDBLOCK))
@@ -529,7 +533,10 @@ kern_sendit(int s,
        if (error == 0)
            *bytes = len - auio.uio_resid;
 bad:
-       fdrop(fp);
+       if (fp)
+               fdrop(fp);
+       if (control)
+               m_freem(control);
        return (error);
 }
 
@@ -585,10 +592,12 @@ kern_recvit(int s, struct msghdr *mp, struct mbuf 
**controlp, ssize_t* bytes)
        so = (socket*)file_data(fp);
 
        // Create a local copy of the user's iovec - sorecieve() is going to 
change it!
-       std::vector<iovec> uio_iov(mp->msg_iov, mp->msg_iov + mp->msg_iovlen);
+       assert(mp->msg_iovlen <= UIO_MAXIOV);
+       struct iovec uio_iov[mp->msg_iovlen];
+       memcpy(uio_iov, mp->msg_iov, sizeof(uio_iov));
 
-       auio.uio_iov = uio_iov.data();
-       auio.uio_iovcnt = uio_iov.size();
+       auio.uio_iov = uio_iov;
+       auio.uio_iovcnt = mp->msg_iovlen;
        auio.uio_rw = UIO_READ;
        auio.uio_offset = 0;                    /* XXX */
        auio.uio_resid = 0;
@@ -653,7 +662,7 @@ out:
        if (fromsa)
                free(fromsa);
 
-       if (error == 0 && controlp != NULL)  
+       if (error == 0 && controlp != NULL)
                *controlp = control;
        else  if (control)
                m_freem(control);
@@ -1038,10 +1047,12 @@ zcopy_tx(int s, struct zmsghdr *zm)
        if (so->so_type != SOCK_STREAM)
                return (EINVAL);
        // Create a local copy of the user's iovec - sosend() is going to 
change it!
-       std::vector<iovec> uio_iov(mp->msg_iov, mp->msg_iov + mp->msg_iovlen);
+       assert(mp->msg_iovlen <= UIO_MAXIOV);
+       struct iovec uio_iov[mp->msg_iovlen];
+       memcpy(uio_iov, mp->msg_iov, sizeof(uio_iov));
 
-       auio.uio_iov = uio_iov.data();
-       auio.uio_iovcnt = uio_iov.size();
+       auio.uio_iov = uio_iov;
+       auio.uio_iovcnt = mp->msg_iovlen;
        auio.uio_rw = UIO_WRITE;
        auio.uio_offset = 0;
        auio.uio_resid = 0;
diff --git a/bsd/sys/kern/uipc_syscalls_wrap.cc 
b/bsd/sys/kern/uipc_syscalls_wrap.cc
index ca666ca..9a46a84 100644
--- a/bsd/sys/kern/uipc_syscalls_wrap.cc
+++ b/bsd/sys/kern/uipc_syscalls_wrap.cc
@@ -190,7 +190,7 @@ ssize_t recv(int fd, void *buf, size_t len, int flags)
 }
 
 extern "C"
-ssize_t recvmsg(int fd, struct msghdr *msg, int flags)
+ssize_t recvmsg(int fd, struct l_msghdr *msg, int flags)
 {
        ssize_t bytes;
        int error;
@@ -246,14 +246,14 @@ ssize_t send(int fd, const void *buf, size_t len, int 
flags)
 }
 
 extern "C"
-ssize_t sendmsg(int fd, const struct msghdr *msg, int flags)
+ssize_t sendmsg(int fd, const struct l_msghdr *msg, int flags)
 {
        ssize_t bytes;
        int error;
 
        sock_d("sendmsg(fd=%d, msg=..., flags=0x%x)", fd, flags)
 
-       error = linux_sendmsg(fd, (struct msghdr *)msg, flags, &bytes);
+       error = linux_sendmsg(fd, (struct l_msghdr *)msg, flags, &bytes);
        if (error) {
                sock_d("sendmsg() failed, errno=%d", error);
                errno = error;
diff --git a/bsd/uipc_syscalls.h b/bsd/uipc_syscalls.h
index 9828b1e..359a4b9 100644
--- a/bsd/uipc_syscalls.h
+++ b/bsd/uipc_syscalls.h
@@ -56,10 +56,10 @@ int linux_listen(int s, int backlog);
 int linux_accept(int s, struct bsd_sockaddr* name, socklen_t* namelen, int 
*out_fd);
 int linux_accept4(int s, struct bsd_sockaddr * name, socklen_t * namelen, int 
*out_fd, int flags);
 int linux_connect(int s, void *name, int namelen);
-int linux_sendmsg(int s, struct msghdr* msg, int flags, ssize_t* bytes);
+int linux_sendmsg(int s, struct l_msghdr* msg, int flags, ssize_t* bytes);
 int linux_sendto(int s, void* buf, int len, int flags, void* to, int tolen, 
ssize_t *bytes);
 int linux_send(int s, caddr_t buf, size_t len, int flags, ssize_t* bytes);
-int linux_recvmsg(int s, struct msghdr *msg, int flags, ssize_t* bytes);
+int linux_recvmsg(int s, struct l_msghdr *msg, int flags, ssize_t* bytes);
 int linux_recv(int s, caddr_t buf, int len, int flags, ssize_t* bytes);
 int linux_recvfrom(int s, void* buf, size_t len, int flags,
        struct bsd_sockaddr * from, socklen_t * fromlen, ssize_t* bytes);
-- 
2.7.4

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to