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

Signed-off-by: Charles Myers <charles.my...@spirent.com>
---
 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 osv-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to