swrap: Fix access to struct members in log messages.
[sfrench/samba-autobuild/.git] / lib / socket_wrapper / socket_wrapper.c
index bf84dbe516954f3ec94a33164a73d032c1c6377a..430904d5a0f3e4a5d1fa31a874399589875672e8 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * Copyright (C) Jelmer Vernooij 2005,2008 <jelmer@samba.org>
- * Copyright (C) Stefan Metzmacher 2006-2009 <metze@samba.org>
- * Copyright (C) Andreas Schneider 2013 <asn@samba.org>
+ * Copyright (c) 2005-2008 Jelmer Vernooij <jelmer@samba.org>
+ * Copyright (C) 2006-2014 Stefan Metzmacher <metze@samba.org>
+ * Copyright (C) 2013-2014 Andreas Schneider <asn@samba.org>
  *
  * All rights reserved.
  *
@@ -76,6 +76,9 @@
 #ifdef HAVE_GNU_LIB_NAMES_H
 #include <gnu/lib-names.h>
 #endif
+#ifdef HAVE_RPC_RPC_H
+#include <rpc/rpc.h>
+#endif
 
 enum swrap_dbglvl_e {
        SWRAP_LOG_ERROR = 0,
@@ -207,6 +210,19 @@ enum swrap_dbglvl_e {
  * without changing the format above */
 #define MAX_WRAPPED_INTERFACES 40
 
+struct swrap_address {
+       socklen_t sa_socklen;
+       union {
+               struct sockaddr s;
+               struct sockaddr_in in;
+#ifdef HAVE_IPV6
+               struct sockaddr_in6 in6;
+#endif
+               struct sockaddr_un un;
+               struct sockaddr_storage ss;
+       } sa;
+};
+
 struct socket_info_fd {
        struct socket_info_fd *prev, *next;
        int fd;
@@ -226,16 +242,12 @@ struct socket_info
        int defer_connect;
        int pktinfo;
 
-       char *tmp_path;
-
-       struct sockaddr *bindname;
-       socklen_t bindname_len;
-
-       struct sockaddr *myname;
-       socklen_t myname_len;
+       /* The unix path so we can unlink it on close() */
+       struct sockaddr_un un_addr;
 
-       struct sockaddr *peername;
-       socklen_t peername_len;
+       struct swrap_address bindname;
+       struct swrap_address myname;
+       struct swrap_address peername;
 
        struct {
                unsigned long pck_snd;
@@ -325,6 +337,7 @@ struct swrap_libc_fns {
                            socklen_t addrlen);
        int (*libc_dup)(int fd);
        int (*libc_dup2)(int oldfd, int newfd);
+       FILE *(*libc_fopen)(const char *name, const char *mode);
 #ifdef HAVE_EVENTFD
        int (*libc_eventfd)(int count, int flags);
 #endif
@@ -633,6 +646,13 @@ static int libc_listen(int sockfd, int backlog)
        return swrap.fns.libc_listen(sockfd, backlog);
 }
 
+static FILE *libc_fopen(const char *name, const char *mode)
+{
+       swrap_load_lib_function(SWRAP_LIBC, fopen);
+
+       return swrap.fns.libc_fopen(name, mode);
+}
+
 static int libc_vopen(const char *pathname, int flags, va_list ap)
 {
        long int mode = 0;
@@ -810,22 +830,15 @@ static const struct in6_addr *swrap_ipv6(void)
 }
 #endif
 
-static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
-{
-       struct sockaddr *ret = (struct sockaddr *)malloc(len);
-       memcpy(ret, data, len);
-       return ret;
-}
-
-static void set_port(int family, int prt, struct sockaddr *addr)
+static void set_port(int family, int prt, struct swrap_address *addr)
 {
        switch (family) {
        case AF_INET:
-               ((struct sockaddr_in *)addr)->sin_port = htons(prt);
+               addr->sa.in.sin_port = htons(prt);
                break;
 #ifdef HAVE_IPV6
        case AF_INET6:
-               ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
+               addr->sa.in6.sin6_port = htons(prt);
                break;
 #endif
        }
@@ -850,6 +863,7 @@ static const char *socket_wrapper_dir(void)
        if (s == NULL) {
                return NULL;
        }
+       /* TODO use realpath(3) here, when we add support for threads */
        if (strncmp(s, "./", 2) == 0) {
                s += 2;
        }
@@ -966,7 +980,7 @@ static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *i
 
        switch (inaddr->sa_family) {
        case AF_INET: {
-               const struct sockaddr_in *in = 
+               const struct sockaddr_in *in =
                    (const struct sockaddr_in *)(const void *)inaddr;
                unsigned int addr = ntohl(in->sin_addr.s_addr);
                char u_type = '\0';
@@ -1013,7 +1027,7 @@ static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *i
        }
 #ifdef HAVE_IPV6
        case AF_INET6: {
-               const struct sockaddr_in6 *in = 
+               const struct sockaddr_in6 *in =
                    (const struct sockaddr_in6 *)(const void *)inaddr;
                struct in6_addr cmp1, cmp2;
 
@@ -1060,14 +1074,14 @@ static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *i
        }
 
        if (is_bcast) {
-               snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL", 
+               snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
                         socket_wrapper_dir());
                SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
                /* the caller need to do more processing */
                return 0;
        }
 
-       snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 
+       snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
                 socket_wrapper_dir(), type, iface, prt);
        SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
 
@@ -1087,7 +1101,7 @@ static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *in
 
        switch (si->family) {
        case AF_INET: {
-               const struct sockaddr_in *in = 
+               const struct sockaddr_in *in =
                    (const struct sockaddr_in *)(const void *)inaddr;
                unsigned int addr = ntohl(in->sin_addr.s_addr);
                char u_type = '\0';
@@ -1140,7 +1154,7 @@ static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *in
                }
 
                /* Store the bind address for connect() */
-               if (si->bindname == NULL) {
+               if (si->bindname.sa_socklen == 0) {
                        struct sockaddr_in bind_in;
                        socklen_t blen = sizeof(struct sockaddr_in);
 
@@ -1149,15 +1163,15 @@ static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *in
                        bind_in.sin_port = in->sin_port;
                        bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
 
-                       si->bindname = sockaddr_dup(&bind_in, blen);
-                       si->bindname_len = blen;
+                       si->bindname.sa_socklen = blen;
+                       memcpy(&si->bindname.sa.in, &bind_in, blen);
                }
 
                break;
        }
 #ifdef HAVE_IPV6
        case AF_INET6: {
-               const struct sockaddr_in6 *in = 
+               const struct sockaddr_in6 *in =
                    (const struct sockaddr_in6 *)(const void *)inaddr;
                struct in6_addr cmp1, cmp2;
 
@@ -1191,7 +1205,7 @@ static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *in
                }
 
                /* Store the bind address for connect() */
-               if (si->bindname == NULL) {
+               if (si->bindname.sa_socklen == 0) {
                        struct sockaddr_in6 bind_in;
                        socklen_t blen = sizeof(struct sockaddr_in6);
 
@@ -1202,8 +1216,8 @@ static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *in
                        bind_in.sin6_addr = *swrap_ipv6();
                        bind_in.sin6_addr.s6_addr[15] = iface;
 
-                       si->bindname = sockaddr_dup(&bind_in, blen);
-                       si->bindname_len = blen;
+                       memcpy(&si->bindname.sa.in6, &bind_in, blen);
+                       si->bindname.sa_socklen = blen;
                }
 
                break;
@@ -1226,12 +1240,12 @@ static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *in
        if (prt == 0) {
                /* handle auto-allocation of ephemeral ports */
                for (prt = 5001; prt < 10000; prt++) {
-                       snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 
+                       snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
                                 socket_wrapper_dir(), type, iface, prt);
                        if (stat(un->sun_path, &st) == 0) continue;
 
-                       set_port(si->family, prt, si->myname);
-                       set_port(si->family, prt, si->bindname);
+                       set_port(si->family, prt, &si->myname);
+                       set_port(si->family, prt, &si->bindname);
 
                        break;
                }
@@ -1241,7 +1255,7 @@ static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *in
                }
        }
 
-       snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 
+       snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
                 socket_wrapper_dir(), type, iface, prt);
        SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
        return 0;
@@ -1263,6 +1277,90 @@ static struct socket_info *find_socket_info(int fd)
        return NULL;
 }
 
+#if 0 /* FIXME */
+static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
+{
+       struct socket_info *s;
+
+       /* first catch invalid input */
+       switch (sa->sa_family) {
+       case AF_INET:
+               if (len < sizeof(struct sockaddr_in)) {
+                       return false;
+               }
+               break;
+#if HAVE_IPV6
+       case AF_INET6:
+               if (len < sizeof(struct sockaddr_in6)) {
+                       return false;
+               }
+               break;
+#endif
+       default:
+               return false;
+               break;
+       }
+
+       for (s = sockets; s != NULL; s = s->next) {
+               if (s->myname == NULL) {
+                       continue;
+               }
+               if (s->myname->sa_family != sa->sa_family) {
+                       continue;
+               }
+               switch (s->myname->sa_family) {
+               case AF_INET: {
+                       struct sockaddr_in *sin1, *sin2;
+
+                       sin1 = (struct sockaddr_in *)s->myname;
+                       sin2 = (struct sockaddr_in *)sa;
+
+                       if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
+                               continue;
+                       }
+                       if (sin1->sin_port != sin2->sin_port) {
+                               continue;
+                       }
+                       if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
+                               continue;
+                       }
+
+                       /* found */
+                       return true;
+                       break;
+               }
+#if HAVE_IPV6
+               case AF_INET6: {
+                       struct sockaddr_in6 *sin1, *sin2;
+
+                       sin1 = (struct sockaddr_in6 *)s->myname;
+                       sin2 = (struct sockaddr_in6 *)sa;
+
+                       if (sin1->sin6_port != sin2->sin6_port) {
+                               continue;
+                       }
+                       if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
+                                               &sin2->sin6_addr))
+                       {
+                               continue;
+                       }
+
+                       /* found */
+                       return true;
+                       break;
+               }
+#endif
+               default:
+                       continue;
+                       break;
+
+               }
+       }
+
+       return false;
+}
+#endif
+
 static void swrap_remove_stale(int fd)
 {
        struct socket_info *si = find_socket_info(fd);
@@ -1305,6 +1403,26 @@ static int sockaddr_convert_to_un(struct socket_info *si,
 #endif
 
        switch (in_addr->sa_family) {
+       case AF_UNSPEC: {
+               const struct sockaddr_in *sin;
+               if (si->family != AF_INET) {
+                       break;
+               }
+               if (in_len < sizeof(struct sockaddr_in)) {
+                       break;
+               }
+               sin = (const struct sockaddr_in *)in_addr;
+               if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
+                       break;
+               }
+
+               /*
+                * Note: in the special case of AF_UNSPEC and INADDR_ANY,
+                * AF_UNSPEC is mapped to AF_INET and must be treated here.
+                */
+
+               /* FALL THROUGH */
+       }
        case AF_INET:
 #ifdef HAVE_IPV6
        case AF_INET6:
@@ -1332,8 +1450,8 @@ static int sockaddr_convert_to_un(struct socket_info *si,
        return -1;
 }
 
-static int sockaddr_convert_from_un(const struct socket_info *si, 
-                                   const struct sockaddr_un *in_addr, 
+static int sockaddr_convert_from_un(const struct socket_info *si,
+                                   const struct sockaddr_un *in_addr,
                                    socklen_t un_addrlen,
                                    int family,
                                    struct sockaddr *out_addr,
@@ -1341,7 +1459,7 @@ static int sockaddr_convert_from_un(const struct socket_info *si,
 {
        int ret;
 
-       if (out_addr == NULL || out_addrlen == NULL) 
+       if (out_addr == NULL || out_addrlen == NULL)
                return 0;
 
        if (un_addrlen == 0) {
@@ -1489,7 +1607,7 @@ union swrap_packet_payload {
         SWRAP_PACKET_IP_SIZE + \
         SWRAP_PACKET_PAYLOAD_SIZE)
 
-static const char *socket_wrapper_pcap_file(void)
+static const char *swrap_pcap_init_file(void)
 {
        static int initialized = 0;
        static const char *s = NULL;
@@ -1506,7 +1624,7 @@ static const char *socket_wrapper_pcap_file(void)
        /*
         * TODO: don't use the structs use plain buffer offsets
         *       and PUSH_U8(), PUSH_U16() and PUSH_U32()
-        * 
+        *
         * for now make sure we disable PCAP support
         * if the struct has alignment!
         */
@@ -1551,17 +1669,17 @@ static const char *socket_wrapper_pcap_file(void)
        return s;
 }
 
-static uint8_t *swrap_packet_init(struct timeval *tval,
-                                 const struct sockaddr *src,
-                                 const struct sockaddr *dest,
-                                 int socket_type,
-                                 const uint8_t *payload,
-                                 size_t payload_len,
-                                 unsigned long tcp_seqno,
-                                 unsigned long tcp_ack,
-                                 unsigned char tcp_ctl,
-                                 int unreachable,
-                                 size_t *_packet_len)
+static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
+                                      const struct sockaddr *src,
+                                      const struct sockaddr *dest,
+                                      int socket_type,
+                                      const uint8_t *payload,
+                                      size_t payload_len,
+                                      unsigned long tcp_seqno,
+                                      unsigned long tcp_ack,
+                                      unsigned char tcp_ctl,
+                                      int unreachable,
+                                      size_t *_packet_len)
 {
        uint8_t *base;
        uint8_t *buf;
@@ -1785,7 +1903,7 @@ static uint8_t *swrap_packet_init(struct timeval *tval,
        return base;
 }
 
-static int swrap_get_pcap_fd(const char *fname)
+static int swrap_pcap_get_fd(const char *fname)
 {
        static int fd = -1;
 
@@ -1814,11 +1932,11 @@ static int swrap_get_pcap_fd(const char *fname)
        return fd;
 }
 
-static uint8_t *swrap_marshall_packet(struct socket_info *si,
-                                     const struct sockaddr *addr,
-                                     enum swrap_packet_type type,
-                                     const void *buf, size_t len,
-                                     size_t *packet_len)
+static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
+                                          const struct sockaddr *addr,
+                                          enum swrap_packet_type type,
+                                          const void *buf, size_t len,
+                                          size_t *packet_len)
 {
        const struct sockaddr *src_addr;
        const struct sockaddr *dest_addr;
@@ -1844,7 +1962,7 @@ static uint8_t *swrap_marshall_packet(struct socket_info *si,
        case SWRAP_CONNECT_SEND:
                if (si->type != SOCK_STREAM) return NULL;
 
-               src_addr = si->myname;
+               src_addr  = &si->myname.sa.s;
                dest_addr = addr;
 
                tcp_seqno = si->io.pck_snd;
@@ -1858,7 +1976,7 @@ static uint8_t *swrap_marshall_packet(struct socket_info *si,
        case SWRAP_CONNECT_RECV:
                if (si->type != SOCK_STREAM) return NULL;
 
-               dest_addr = si->myname;
+               dest_addr = &si->myname.sa.s;
                src_addr = addr;
 
                tcp_seqno = si->io.pck_rcv;
@@ -1872,8 +1990,8 @@ static uint8_t *swrap_marshall_packet(struct socket_info *si,
        case SWRAP_CONNECT_UNREACH:
                if (si->type != SOCK_STREAM) return NULL;
 
-               dest_addr = si->myname;
-               src_addr = addr;
+               dest_addr = &si->myname.sa.s;
+               src_addr  = addr;
 
                /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
                tcp_seqno = si->io.pck_snd - 1;
@@ -1886,7 +2004,7 @@ static uint8_t *swrap_marshall_packet(struct socket_info *si,
        case SWRAP_CONNECT_ACK:
                if (si->type != SOCK_STREAM) return NULL;
 
-               src_addr = si->myname;
+               src_addr  = &si->myname.sa.s;
                dest_addr = addr;
 
                tcp_seqno = si->io.pck_snd;
@@ -1898,7 +2016,7 @@ static uint8_t *swrap_marshall_packet(struct socket_info *si,
        case SWRAP_ACCEPT_SEND:
                if (si->type != SOCK_STREAM) return NULL;
 
-               dest_addr = si->myname;
+               dest_addr = &si->myname.sa.s;
                src_addr = addr;
 
                tcp_seqno = si->io.pck_rcv;
@@ -1912,7 +2030,7 @@ static uint8_t *swrap_marshall_packet(struct socket_info *si,
        case SWRAP_ACCEPT_RECV:
                if (si->type != SOCK_STREAM) return NULL;
 
-               src_addr = si->myname;
+               src_addr = &si->myname.sa.s;
                dest_addr = addr;
 
                tcp_seqno = si->io.pck_snd;
@@ -1926,7 +2044,7 @@ static uint8_t *swrap_marshall_packet(struct socket_info *si,
        case SWRAP_ACCEPT_ACK:
                if (si->type != SOCK_STREAM) return NULL;
 
-               dest_addr = si->myname;
+               dest_addr = &si->myname.sa.s;
                src_addr = addr;
 
                tcp_seqno = si->io.pck_rcv;
@@ -1936,8 +2054,8 @@ static uint8_t *swrap_marshall_packet(struct socket_info *si,
                break;
 
        case SWRAP_SEND:
-               src_addr = si->myname;
-               dest_addr = si->peername;
+               src_addr  = &si->myname.sa.s;
+               dest_addr = &si->peername.sa.s;
 
                tcp_seqno = si->io.pck_snd;
                tcp_ack = si->io.pck_rcv;
@@ -1948,13 +2066,16 @@ static uint8_t *swrap_marshall_packet(struct socket_info *si,
                break;
 
        case SWRAP_SEND_RST:
-               dest_addr = si->myname;
-               src_addr = si->peername;
+               dest_addr = &si->myname.sa.s;
+               src_addr  = &si->peername.sa.s;
 
                if (si->type == SOCK_DGRAM) {
-                       return swrap_marshall_packet(si, si->peername,
-                                         SWRAP_SENDTO_UNREACH,
-                                         buf, len, packet_len);
+                       return swrap_pcap_marshall_packet(si,
+                                                         &si->peername.sa.s,
+                                                         SWRAP_SENDTO_UNREACH,
+                                                         buf,
+                                                         len,
+                                                         packet_len);
                }
 
                tcp_seqno = si->io.pck_rcv;
@@ -1964,8 +2085,8 @@ static uint8_t *swrap_marshall_packet(struct socket_info *si,
                break;
 
        case SWRAP_PENDING_RST:
-               dest_addr = si->myname;
-               src_addr = si->peername;
+               dest_addr = &si->myname.sa.s;
+               src_addr  = &si->peername.sa.s;
 
                if (si->type == SOCK_DGRAM) {
                        return NULL;
@@ -1978,8 +2099,8 @@ static uint8_t *swrap_marshall_packet(struct socket_info *si,
                break;
 
        case SWRAP_RECV:
-               dest_addr = si->myname;
-               src_addr = si->peername;
+               dest_addr = &si->myname.sa.s;
+               src_addr  = &si->peername.sa.s;
 
                tcp_seqno = si->io.pck_rcv;
                tcp_ack = si->io.pck_snd;
@@ -1990,8 +2111,8 @@ static uint8_t *swrap_marshall_packet(struct socket_info *si,
                break;
 
        case SWRAP_RECV_RST:
-               dest_addr = si->myname;
-               src_addr = si->peername;
+               dest_addr = &si->myname.sa.s;
+               src_addr  = &si->peername.sa.s;
 
                if (si->type == SOCK_DGRAM) {
                        return NULL;
@@ -2004,7 +2125,7 @@ static uint8_t *swrap_marshall_packet(struct socket_info *si,
                break;
 
        case SWRAP_SENDTO:
-               src_addr = si->myname;
+               src_addr = &si->myname.sa.s;
                dest_addr = addr;
 
                si->io.pck_snd += len;
@@ -2012,7 +2133,7 @@ static uint8_t *swrap_marshall_packet(struct socket_info *si,
                break;
 
        case SWRAP_SENDTO_UNREACH:
-               dest_addr = si->myname;
+               dest_addr = &si->myname.sa.s;
                src_addr = addr;
 
                unreachable = 1;
@@ -2020,7 +2141,7 @@ static uint8_t *swrap_marshall_packet(struct socket_info *si,
                break;
 
        case SWRAP_RECVFROM:
-               dest_addr = si->myname;
+               dest_addr = &si->myname.sa.s;
                src_addr = addr;
 
                si->io.pck_rcv += len;
@@ -2030,8 +2151,8 @@ static uint8_t *swrap_marshall_packet(struct socket_info *si,
        case SWRAP_CLOSE_SEND:
                if (si->type != SOCK_STREAM) return NULL;
 
-               src_addr = si->myname;
-               dest_addr = si->peername;
+               src_addr  = &si->myname.sa.s;
+               dest_addr = &si->peername.sa.s;
 
                tcp_seqno = si->io.pck_snd;
                tcp_ack = si->io.pck_rcv;
@@ -2044,8 +2165,8 @@ static uint8_t *swrap_marshall_packet(struct socket_info *si,
        case SWRAP_CLOSE_RECV:
                if (si->type != SOCK_STREAM) return NULL;
 
-               dest_addr = si->myname;
-               src_addr = si->peername;
+               dest_addr = &si->myname.sa.s;
+               src_addr  = &si->peername.sa.s;
 
                tcp_seqno = si->io.pck_rcv;
                tcp_ack = si->io.pck_snd;
@@ -2058,8 +2179,8 @@ static uint8_t *swrap_marshall_packet(struct socket_info *si,
        case SWRAP_CLOSE_ACK:
                if (si->type != SOCK_STREAM) return NULL;
 
-               src_addr = si->myname;
-               dest_addr = si->peername;
+               src_addr  = &si->myname.sa.s;
+               dest_addr = &si->peername.sa.s;
 
                tcp_seqno = si->io.pck_snd;
                tcp_ack = si->io.pck_rcv;
@@ -2072,33 +2193,45 @@ static uint8_t *swrap_marshall_packet(struct socket_info *si,
 
        swrapGetTimeOfDay(&tv);
 
-       return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
-                                (const uint8_t *)buf, len,
-                                tcp_seqno, tcp_ack, tcp_ctl, unreachable,
-                                packet_len);
+       return swrap_pcap_packet_init(&tv,
+                                     src_addr,
+                                     dest_addr,
+                                     si->type,
+                                     (const uint8_t *)buf,
+                                     len,
+                                     tcp_seqno,
+                                     tcp_ack,
+                                     tcp_ctl,
+                                     unreachable,
+                                     packet_len);
 }
 
-static void swrap_dump_packet(struct socket_info *si,
-                             const struct sockaddr *addr,
-                             enum swrap_packet_type type,
-                             const void *buf, size_t len)
+static void swrap_pcap_dump_packet(struct socket_info *si,
+                                  const struct sockaddr *addr,
+                                  enum swrap_packet_type type,
+                                  const void *buf, size_t len)
 {
        const char *file_name;
        uint8_t *packet;
        size_t packet_len = 0;
        int fd;
 
-       file_name = socket_wrapper_pcap_file();
+       file_name = swrap_pcap_init_file();
        if (!file_name) {
                return;
        }
 
-       packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
-       if (!packet) {
+       packet = swrap_pcap_marshall_packet(si,
+                                           addr,
+                                           type,
+                                           buf,
+                                           len,
+                                           &packet_len);
+       if (packet == NULL) {
                return;
        }
 
-       fd = swrap_get_pcap_fd(file_name);
+       fd = swrap_pcap_get_fd(file_name);
        if (fd != -1) {
                if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
                        free(packet);
@@ -2240,8 +2373,8 @@ static int swrap_socket(int family, int type, int protocol)
                        .sin_family = AF_INET,
                };
 
-               si->myname_len = sizeof(struct sockaddr_in);
-               si->myname = sockaddr_dup(&sin, si->myname_len);
+               si->myname.sa_socklen = sizeof(struct sockaddr_in);
+               memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
                break;
        }
        case AF_INET6: {
@@ -2249,8 +2382,8 @@ static int swrap_socket(int family, int type, int protocol)
                        .sin6_family = AF_INET6,
                };
 
-               si->myname_len = sizeof(struct sockaddr_in6);
-               si->myname = sockaddr_dup(&sin6, si->myname_len);
+               si->myname.sa_socklen = sizeof(struct sockaddr_in6);
+               memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
                break;
        }
        default:
@@ -2261,9 +2394,6 @@ static int swrap_socket(int family, int type, int protocol)
 
        fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
        if (fi == NULL) {
-               if (si->myname != NULL) {
-                       free (si->myname);
-               }
                free(si);
                errno = ENOMEM;
                return -1;
@@ -2358,12 +2488,18 @@ static int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
        struct socket_info *parent_si, *child_si;
        struct socket_info_fd *child_fi;
        int fd;
-       struct sockaddr_un un_addr;
-       socklen_t un_addrlen = sizeof(un_addr);
-       struct sockaddr_un un_my_addr;
-       socklen_t un_my_addrlen = sizeof(un_my_addr);
-       struct sockaddr *my_addr;
-       socklen_t my_addrlen, len;
+       struct swrap_address un_addr = {
+               .sa_socklen = sizeof(struct sockaddr_un),
+       };
+       struct swrap_address un_my_addr = {
+               .sa_socklen = sizeof(struct sockaddr_un),
+       };
+       struct swrap_address in_addr = {
+               .sa_socklen = sizeof(struct sockaddr_storage),
+       };
+       struct swrap_address in_my_addr = {
+               .sa_socklen = sizeof(struct sockaddr_storage),
+       };
        int ret;
 
        parent_si = find_socket_info(s);
@@ -2371,41 +2507,34 @@ static int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
                return libc_accept(s, addr, addrlen);
        }
 
-       /* 
+       /*
         * assume out sockaddr have the same size as the in parent
         * socket family
         */
-       my_addrlen = socket_length(parent_si->family);
-       if (my_addrlen <= 0) {
+       in_addr.sa_socklen = socket_length(parent_si->family);
+       if (in_addr.sa_socklen <= 0) {
                errno = EINVAL;
                return -1;
        }
 
-       my_addr = (struct sockaddr *)malloc(my_addrlen);
-       if (my_addr == NULL) {
-               return -1;
-       }
-
-       memset(&un_addr, 0, sizeof(un_addr));
-       memset(&un_my_addr, 0, sizeof(un_my_addr));
-
-       ret = libc_accept(s, (struct sockaddr *)(void *)&un_addr, &un_addrlen);
+       ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
        if (ret == -1) {
                if (errno == ENOTSOCK) {
                        /* Remove stale fds */
                        swrap_remove_stale(s);
                }
-               free(my_addr);
                return ret;
        }
 
        fd = ret;
 
-       len = my_addrlen;
-       ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
-                                      parent_si->family, my_addr, &len);
+       ret = sockaddr_convert_from_un(parent_si,
+                                      &un_addr.sa.un,
+                                      un_addr.sa_socklen,
+                                      parent_si->family,
+                                      &in_addr.sa.s,
+                                      &in_addr.sa_socklen);
        if (ret == -1) {
-               free(my_addr);
                close(fd);
                return ret;
        }
@@ -2416,7 +2545,6 @@ static int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
        child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
        if (child_fi == NULL) {
                free(child_si);
-               free(my_addr);
                close(fd);
                errno = ENOMEM;
                return -1;
@@ -2433,53 +2561,57 @@ static int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
        child_si->is_server = 1;
        child_si->connected = 1;
 
-       child_si->peername_len = len;
-       child_si->peername = sockaddr_dup(my_addr, len);
+       child_si->peername = (struct swrap_address) {
+               .sa_socklen = in_addr.sa_socklen,
+       };
+       memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
 
        if (addr != NULL && addrlen != NULL) {
-               size_t copy_len = MIN(*addrlen, len);
+               size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
                if (copy_len > 0) {
-                       memcpy(addr, my_addr, copy_len);
+                       memcpy(addr, &in_addr.sa.ss, copy_len);
                }
-               *addrlen = len;
+               *addrlen = in_addr.sa_socklen;
        }
 
        ret = libc_getsockname(fd,
-                              (struct sockaddr *)(void *)&un_my_addr,
-                              &un_my_addrlen);
+                              &un_my_addr.sa.s,
+                              &un_my_addr.sa_socklen);
        if (ret == -1) {
                free(child_fi);
                free(child_si);
-               free(my_addr);
                close(fd);
                return ret;
        }
 
-       len = my_addrlen;
-       ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
-                                      child_si->family, my_addr, &len);
+       ret = sockaddr_convert_from_un(child_si,
+                                      &un_my_addr.sa.un,
+                                      un_my_addr.sa_socklen,
+                                      child_si->family,
+                                      &in_my_addr.sa.s,
+                                      &in_my_addr.sa_socklen);
        if (ret == -1) {
                free(child_fi);
                free(child_si);
-               free(my_addr);
                close(fd);
                return ret;
        }
 
        SWRAP_LOG(SWRAP_LOG_TRACE,
                  "accept() path=%s, fd=%d",
-                 un_my_addr.sun_path, s);
+                 un_my_addr.sa.un.sun_path, s);
 
-       child_si->myname_len = len;
-       child_si->myname = sockaddr_dup(my_addr, len);
-       free(my_addr);
+       child_si->myname = (struct swrap_address) {
+               .sa_socklen = in_my_addr.sa_socklen,
+       };
+       memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
 
        SWRAP_DLIST_ADD(sockets, child_si);
 
        if (addr != NULL) {
-               swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
-               swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
-               swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
+               swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
+               swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
+               swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
        }
 
        return fd;
@@ -2505,7 +2637,9 @@ static int autobind_start;
 */
 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
 {
-       struct sockaddr_un un_addr;
+       struct swrap_address un_addr = {
+               .sa_socklen = sizeof(struct sockaddr_un),
+       };
        int i;
        char type;
        int ret;
@@ -2519,7 +2653,7 @@ static int swrap_auto_bind(int fd, struct socket_info *si, int family)
                autobind_start += 10000;
        }
 
-       un_addr.sun_family = AF_UNIX;
+       un_addr.sa.un.sun_family = AF_UNIX;
 
        switch (family) {
        case AF_INET: {
@@ -2530,7 +2664,7 @@ static int swrap_auto_bind(int fd, struct socket_info *si, int family)
                        type = SOCKET_TYPE_CHAR_TCP;
                        break;
                case SOCK_DGRAM:
-                       type = SOCKET_TYPE_CHAR_UDP;
+                       type = SOCKET_TYPE_CHAR_UDP;
                        break;
                default:
                    errno = ESOCKTNOSUPPORT;
@@ -2539,12 +2673,13 @@ static int swrap_auto_bind(int fd, struct socket_info *si, int family)
 
                memset(&in, 0, sizeof(in));
                in.sin_family = AF_INET;
-               in.sin_addr.s_addr = htonl(127<<24 | 
+               in.sin_addr.s_addr = htonl(127<<24 |
                                           socket_wrapper_default_iface());
 
-               free(si->myname);
-               si->myname_len = sizeof(in);
-               si->myname = sockaddr_dup(&in, si->myname_len);
+               si->myname = (struct swrap_address) {
+                       .sa_socklen = sizeof(in),
+               };
+               memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
                break;
        }
 #ifdef HAVE_IPV6
@@ -2561,7 +2696,7 @@ static int swrap_auto_bind(int fd, struct socket_info *si, int family)
                        type = SOCKET_TYPE_CHAR_TCP_V6;
                        break;
                case SOCK_DGRAM:
-                       type = SOCKET_TYPE_CHAR_UDP_V6;
+                       type = SOCKET_TYPE_CHAR_UDP_V6;
                        break;
                default:
                        errno = ESOCKTNOSUPPORT;
@@ -2572,9 +2707,11 @@ static int swrap_auto_bind(int fd, struct socket_info *si, int family)
                in6.sin6_family = AF_INET6;
                in6.sin6_addr = *swrap_ipv6();
                in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
-               free(si->myname);
-               si->myname_len = sizeof(in6);
-               si->myname = sockaddr_dup(&in6, si->myname_len);
+
+               si->myname = (struct swrap_address) {
+                       .sa_socklen = sizeof(in6),
+               };
+               memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
                break;
        }
 #endif
@@ -2589,16 +2726,16 @@ static int swrap_auto_bind(int fd, struct socket_info *si, int family)
 
        for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
                port = autobind_start + i;
-               snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), 
+               snprintf(un_addr.sa.un.sun_path, un_addr.sa_socklen,
                         "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
                         type, socket_wrapper_default_iface(), port);
-               if (stat(un_addr.sun_path, &st) == 0) continue;
+               if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
 
-               ret = libc_bind(fd, (struct sockaddr *)(void *)&un_addr,
-                               sizeof(un_addr));
+               ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
                if (ret == -1) return ret;
 
-               si->tmp_path = strdup(un_addr.sun_path);
+               si->un_addr = un_addr.sa.un;
+
                si->bound = 1;
                autobind_start = port + 1;
                break;
@@ -2615,7 +2752,7 @@ static int swrap_auto_bind(int fd, struct socket_info *si, int family)
        }
 
        si->family = family;
-       set_port(si->family, port, si->myname);
+       set_port(si->family, port, &si->myname);
 
        return 0;
 }
@@ -2628,7 +2765,9 @@ static int swrap_connect(int s, const struct sockaddr *serv_addr,
                         socklen_t addrlen)
 {
        int ret;
-       struct sockaddr_un un_addr;
+       struct swrap_address un_addr = {
+               .sa_socklen = sizeof(struct sockaddr_un),
+       };
        struct socket_info *si = find_socket_info(s);
        int bcast = 0;
 
@@ -2647,7 +2786,7 @@ static int swrap_connect(int s, const struct sockaddr *serv_addr,
        }
 
        ret = sockaddr_convert_to_un(si, serv_addr,
-                                    addrlen, &un_addr, 0, &bcast);
+                                    addrlen, &un_addr.sa.un, 0, &bcast);
        if (ret == -1) return -1;
 
        if (bcast) {
@@ -2659,16 +2798,16 @@ static int swrap_connect(int s, const struct sockaddr *serv_addr,
                si->defer_connect = 1;
                ret = 0;
        } else {
-               swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
+               swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
 
                ret = libc_connect(s,
-                                  (struct sockaddr *)(void *)&un_addr,
-                                  sizeof(struct sockaddr_un));
+                                  &un_addr.sa.s,
+                                  un_addr.sa_socklen);
        }
 
        SWRAP_LOG(SWRAP_LOG_TRACE,
                  "connect() path=%s, fd=%d",
-                 un_addr.sun_path, s);
+                 un_addr.sa.un.sun_path, s);
 
 
        /* to give better errors */
@@ -2677,8 +2816,11 @@ static int swrap_connect(int s, const struct sockaddr *serv_addr,
        }
 
        if (ret == 0) {
-               si->peername_len = addrlen;
-               si->peername = sockaddr_dup(serv_addr, addrlen);
+               si->peername = (struct swrap_address) {
+                       .sa_socklen = addrlen,
+               };
+
+               memcpy(&si->peername.sa.ss, serv_addr, addrlen);
                si->connected = 1;
 
                /*
@@ -2688,20 +2830,25 @@ static int swrap_connect(int s, const struct sockaddr *serv_addr,
                 * but here we have to update the name so getsockname()
                 * returns correct information.
                 */
-               if (si->bindname != NULL) {
-                       free(si->myname);
-
-                       si->myname = si->bindname;
-                       si->myname_len = si->bindname_len;
-
-                       si->bindname = NULL;
-                       si->bindname_len = 0;
+               if (si->bindname.sa_socklen > 0) {
+                       si->myname = (struct swrap_address) {
+                               .sa_socklen = si->bindname.sa_socklen,
+                       };
+
+                       memcpy(&si->myname.sa.ss,
+                              &si->bindname.sa.ss,
+                              si->bindname.sa_socklen);
+
+                       /* Cleanup bindname */
+                       si->bindname = (struct swrap_address) {
+                               .sa_socklen = 0,
+                       };
                }
 
-               swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
-               swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
+               swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
+               swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
        } else {
-               swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
+               swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
        }
 
        return ret;
@@ -2719,33 +2866,95 @@ int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
 {
        int ret;
-       struct sockaddr_un un_addr;
+       struct swrap_address un_addr = {
+               .sa_socklen = sizeof(struct sockaddr_un),
+       };
        struct socket_info *si = find_socket_info(s);
+       int bind_error = 0;
+#if 0 /* FIXME */
+       bool in_use;
+#endif
 
        if (!si) {
                return libc_bind(s, myaddr, addrlen);
        }
 
-       if (si->family != myaddr->sa_family) {
-               errno = EAFNOSUPPORT;
+       switch (si->family) {
+       case AF_INET: {
+               const struct sockaddr_in *sin;
+               if (addrlen < sizeof(struct sockaddr_in)) {
+                       bind_error = EINVAL;
+                       break;
+               }
+
+               sin = (const struct sockaddr_in *)myaddr;
+
+               if (sin->sin_family != AF_INET) {
+                       bind_error = EAFNOSUPPORT;
+               }
+
+               /* special case for AF_UNSPEC */
+               if (sin->sin_family == AF_UNSPEC &&
+                   (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
+               {
+                       bind_error = 0;
+               }
+
+               break;
+       }
+#ifdef HAVE_IPV6
+       case AF_INET6: {
+               const struct sockaddr_in6 *sin6;
+               if (addrlen < sizeof(struct sockaddr_in6)) {
+                       bind_error = EINVAL;
+                       break;
+               }
+
+               sin6 = (const struct sockaddr_in6 *)myaddr;
+
+               if (sin6->sin6_family != AF_INET6) {
+                       bind_error = EAFNOSUPPORT;
+               }
+
+               break;
+       }
+#endif
+       default:
+               bind_error = EINVAL;
+               break;
+       }
+
+       if (bind_error != 0) {
+               errno = bind_error;
                return -1;
        }
 
-       free(si->myname);
-       si->myname_len = addrlen;
-       si->myname = sockaddr_dup(myaddr, addrlen);
+#if 0 /* FIXME */
+       in_use = check_addr_port_in_use(myaddr, addrlen);
+       if (in_use) {
+               errno = EADDRINUSE;
+               return -1;
+       }
+#endif
+
+       si->myname.sa_socklen = addrlen;
+       memcpy(&si->myname.sa.ss, myaddr, addrlen);
 
-       ret = sockaddr_convert_to_un(si, myaddr, addrlen, &un_addr, 1, &si->bcast);
+       ret = sockaddr_convert_to_un(si,
+                                    myaddr,
+                                    addrlen,
+                                    &un_addr.sa.un,
+                                    1,
+                                    &si->bcast);
        if (ret == -1) return -1;
 
-       unlink(un_addr.sun_path);
+       unlink(un_addr.sa.un.sun_path);
 
-       ret = libc_bind(s, (struct sockaddr *)(void *)&un_addr,
-                       sizeof(struct sockaddr_un));
+       ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
 
        SWRAP_LOG(SWRAP_LOG_TRACE,
                  "bind() path=%s, fd=%d",
-                 un_addr.sun_path, s);
+                 un_addr.sa.un.sun_path, s);
 
        if (ret == 0) {
                si->bound = 1;
@@ -2768,7 +2977,9 @@ static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
 
 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
 {
-       struct sockaddr_storage myaddr;
+       struct swrap_address myaddr = {
+               .sa_socklen = sizeof(struct sockaddr_storage),
+       };
        socklen_t salen;
        static uint16_t port;
        uint16_t i;
@@ -2784,16 +2995,16 @@ static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
        }
 
        if (sa == NULL) {
-               salen = sizeof(struct sockaddr);
-               sa = (struct sockaddr *)&myaddr;
+               salen = myaddr.sa_socklen;
+               sa = &myaddr.sa.s;
 
-               rc = swrap_getsockname(sd, (struct sockaddr *)&myaddr, &salen);
+               rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
                if (rc < 0) {
                        return -1;
                }
 
                af = sa->sa_family;
-               memset(&myaddr, 0, salen);
+               memset(&myaddr.sa.ss, 0, salen);
        } else {
                af = sa->sa_family;
        }
@@ -2801,7 +3012,7 @@ static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
        for (i = 0; i < SWRAP_NPORTS; i++, port++) {
                switch(af) {
                case AF_INET: {
-                       struct sockaddr_in *sinp = (struct sockaddr_in *)sa;
+                       struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
 
                        salen = sizeof(struct sockaddr_in);
                        sinp->sin_port = htons(port);
@@ -2862,6 +3073,29 @@ int listen(int s, int backlog)
        return swrap_listen(s, backlog);
 }
 
+/****************************************************************************
+ *   FOPEN
+ ***************************************************************************/
+
+static FILE *swrap_fopen(const char *name, const char *mode)
+{
+       FILE *fp;
+
+       fp = libc_fopen(name, mode);
+       if (fp != NULL) {
+               int fd = fileno(fp);
+
+               swrap_remove_stale(fd);
+       }
+
+       return fp;
+}
+
+FILE *fopen(const char *name, const char *mode)
+{
+       return swrap_fopen(name, mode);
+}
+
 /****************************************************************************
  *   OPEN
  ***************************************************************************/
@@ -2908,19 +3142,19 @@ static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
                return libc_getpeername(s, name, addrlen);
        }
 
-       if (!si->peername)
+       if (si->peername.sa_socklen == 0)
        {
                errno = ENOTCONN;
                return -1;
        }
 
-       len = MIN(*addrlen, si->peername_len);
+       len = MIN(*addrlen, si->peername.sa_socklen);
        if (len == 0) {
                return 0;
        }
 
-       memcpy(name, si->peername, len);
-       *addrlen = si->peername_len;
+       memcpy(name, &si->peername.sa.ss, len);
+       *addrlen = si->peername.sa_socklen;
 
        return 0;
 }
@@ -2947,13 +3181,13 @@ static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
                return libc_getsockname(s, name, addrlen);
        }
 
-       len = MIN(*addrlen, si->myname_len);
+       len = MIN(*addrlen, si->myname.sa_socklen);
        if (len == 0) {
                return 0;
        }
 
-       memcpy(name, si->myname, len);
-       *addrlen = si->myname_len;
+       memcpy(name, &si->myname.sa.ss, len);
+       *addrlen = si->myname.sa_socklen;
 
        return 0;
 }
@@ -3004,6 +3238,8 @@ static int swrap_getsockopt(int s, int level, int optname,
                        *(int *)optval = si->family;
                        return 0;
 #endif /* SO_DOMAIN */
+
+#ifdef SO_PROTOCOL
                case SO_PROTOCOL:
                        if (optval == NULL || optlen == NULL ||
                            *optlen < (socklen_t)sizeof(int)) {
@@ -3014,6 +3250,7 @@ static int swrap_getsockopt(int s, int level, int optname,
                        *optlen = sizeof(int);
                        *(int *)optval = si->protocol;
                        return 0;
+#endif /* SO_PROTOCOL */
                case SO_TYPE:
                        if (optval == NULL || optlen == NULL ||
                            *optlen < (socklen_t)sizeof(int)) {
@@ -3128,9 +3365,9 @@ static int swrap_vioctl(int s, unsigned long int r, va_list va)
                value = *((int *)va_arg(ap, int *));
 
                if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
-                       swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
+                       swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
                } else if (value == 0) { /* END OF FILE */
-                       swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
+                       swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
                }
                break;
        }
@@ -3168,7 +3405,7 @@ int ioctl(int s, unsigned long int r, ...)
 # ifdef _ALIGN /* BSD */
 #define CMSG_ALIGN _ALIGN
 # else
-#error NO_CMSG_ALIGN
+#define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
 # endif /* _ALIGN */
 #endif /* CMSG_ALIGN */
 
@@ -3200,7 +3437,8 @@ static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
        size_t cmlen = CMSG_LEN(len);
        size_t cmspace = CMSG_SPACE(len);
        uint8_t cmbuf[cmspace];
-       struct cmsghdr *cm = (struct cmsghdr *)cmbuf;
+       void *cast_ptr = (void *)cmbuf;
+       struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
        uint8_t *p;
 
        memset(cmbuf, 0, cmspace);
@@ -3242,8 +3480,7 @@ static int swrap_msghdr_add_pktinfo(struct socket_info *si,
 {
        /* Add packet info */
        switch (si->pktinfo) {
-#if defined(IP_PKTINFO)
-/* && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR)) */
+#if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
        case AF_INET: {
                struct sockaddr_in *sin;
 #if defined(HAVE_STRUCT_IN_PKTINFO)
@@ -3252,13 +3489,13 @@ static int swrap_msghdr_add_pktinfo(struct socket_info *si,
                struct in_addr pkt;
 #endif
 
-               if (si->bindname_len == sizeof(struct sockaddr_in)) {
-                       sin = (struct sockaddr_in*)si->bindname;
+               if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
+                       sin = &si->bindname.sa.in;
                } else {
-                       if (si->myname_len != sizeof(struct sockaddr_in)) {
+                       if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
                                return 0;
                        }
-                       sin = (struct sockaddr_in*)si->myname;
+                       sin = &si->myname.sa.in;
                }
 
                ZERO_STRUCT(pkt);
@@ -3282,13 +3519,13 @@ static int swrap_msghdr_add_pktinfo(struct socket_info *si,
                struct sockaddr_in6 *sin6;
                struct in6_pktinfo pkt6;
 
-               if (si->bindname_len == sizeof(struct sockaddr_in6)) {
-                       sin6 = (struct sockaddr_in6*)si->bindname;
+               if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
+                       sin6 = &si->bindname.sa.in6;
                } else {
-                       if (si->myname_len != sizeof(struct sockaddr_in6)) {
+                       if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
                                return 0;
                        }
-                       sin6 = (struct sockaddr_in6*)si->myname;
+                       sin6 = &si->myname.sa.in6;
                }
 
                ZERO_STRUCT(pkt6);
@@ -3530,8 +3767,12 @@ static ssize_t swrap_sendmsg_before(int fd,
                        break;
                }
 
-               ret = sockaddr_convert_to_un(si, si->peername, si->peername_len,
-                                            tmp_un, 0, NULL);
+               ret = sockaddr_convert_to_un(si,
+                                            &si->peername.sa.s,
+                                            si->peername.sa_socklen,
+                                            tmp_un,
+                                            0,
+                                            NULL);
                if (ret == -1) return -1;
 
                ret = libc_connect(fd,
@@ -3633,22 +3874,22 @@ static void swrap_sendmsg_after(int fd,
        switch (si->type) {
        case SOCK_STREAM:
                if (ret == -1) {
-                       swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
-                       swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
+                       swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
+                       swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
                } else {
-                       swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
+                       swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
                }
                break;
 
        case SOCK_DGRAM:
                if (si->connected) {
-                       to = si->peername;
+                       to = &si->peername.sa.s;
                }
                if (ret == -1) {
-                       swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
-                       swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
+                       swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
+                       swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
                } else {
-                       swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
+                       swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
                }
                break;
        }
@@ -3792,11 +4033,11 @@ static int swrap_recvmsg_after(int fd,
        switch (si->type) {
        case SOCK_STREAM:
                if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
-                       swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
+                       swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
                } else if (ret == 0) { /* END OF FILE */
-                       swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
+                       swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
                } else if (ret > 0) {
-                       swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
+                       swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
                }
                break;
 
@@ -3816,13 +4057,13 @@ static int swrap_recvmsg_after(int fd,
                                goto done;
                        }
 
-                       swrap_dump_packet(si,
+                       swrap_pcap_dump_packet(si,
                                          msg->msg_name,
                                          SWRAP_RECVFROM,
                                          buf,
                                          ret);
                } else {
-                       swrap_dump_packet(si,
+                       swrap_pcap_dump_packet(si,
                                          msg->msg_name,
                                          SWRAP_RECV,
                                          buf,
@@ -3858,12 +4099,14 @@ done:
 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
                              struct sockaddr *from, socklen_t *fromlen)
 {
-       struct sockaddr_un from_addr;
-       socklen_t from_addrlen = sizeof(from_addr);
+       struct swrap_address from_addr = {
+               .sa_socklen = sizeof(struct sockaddr_un),
+       };
        ssize_t ret;
        struct socket_info *si = find_socket_info(s);
-       struct sockaddr_storage ss;
-       socklen_t ss_len = sizeof(ss);
+       struct swrap_address saddr = {
+               .sa_socklen = sizeof(struct sockaddr_storage),
+       };
        struct msghdr msg;
        struct iovec tmp;
        int tret;
@@ -3885,8 +4128,8 @@ static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
                msg.msg_name = from;   /* optional address */
                msg.msg_namelen = *fromlen; /* size of address */
        } else {
-               msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
-               msg.msg_namelen = ss_len; /* size of address */
+               msg.msg_name = &saddr.sa.s; /* optional address */
+               msg.msg_namelen = saddr.sa_socklen; /* size of address */
        }
        msg.msg_iov = &tmp;            /* scatter/gather array */
        msg.msg_iovlen = 1;            /* # elements in msg_iov */
@@ -3904,14 +4147,12 @@ static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
        buf = msg.msg_iov[0].iov_base;
        len = msg.msg_iov[0].iov_len;
 
-       /* irix 6.4 forgets to null terminate the sun_path string :-( */
-       memset(&from_addr, 0, sizeof(from_addr));
        ret = libc_recvfrom(s,
                            buf,
                            len,
                            flags,
-                           (struct sockaddr *)(void *)&from_addr,
-                           &from_addrlen);
+                           &from_addr.sa.s,
+                           &from_addr.sa_socklen);
        if (ret == -1) {
                return ret;
        }
@@ -3919,8 +4160,8 @@ static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
        tret = swrap_recvmsg_after(s,
                                   si,
                                   &msg,
-                                  &from_addr,
-                                  from_addrlen,
+                                  &from_addr.sa.un,
+                                  from_addr.sa_socklen,
                                   ret);
        if (tret != 0) {
                return tret;
@@ -3953,7 +4194,9 @@ static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
 {
        struct msghdr msg;
        struct iovec tmp;
-       struct sockaddr_un un_addr;
+       struct swrap_address un_addr = {
+               .sa_socklen = sizeof(struct sockaddr_un),
+       };
        const struct sockaddr_un *to_un = NULL;
        ssize_t ret;
        int rc;
@@ -3978,7 +4221,14 @@ static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
        msg.msg_flags = 0;             /* flags on received message */
 #endif
 
-       rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
+       rc = swrap_sendmsg_before(s,
+                                 si,
+                                 &msg,
+                                 &tmp,
+                                 &un_addr.sa.un,
+                                 &to_un,
+                                 &to,
+                                 &bcast);
        if (rc < 0) {
                return -1;
        }
@@ -3995,20 +4245,22 @@ static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
                type = SOCKET_TYPE_CHAR_UDP;
 
                for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
-                       snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
+                       snprintf(un_addr.sa.un.sun_path,
+                                sizeof(un_addr.sa.un.sun_path),
+                                "%s/"SOCKET_FORMAT,
                                 socket_wrapper_dir(), type, iface, prt);
-                       if (stat(un_addr.sun_path, &st) != 0) continue;
+                       if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
 
                        /* ignore the any errors in broadcast sends */
                        libc_sendto(s,
                                    buf,
                                    len,
                                    flags,
-                                   (struct sockaddr *)(void *)&un_addr,
-                                   sizeof(un_addr));
+                                   &un_addr.sa.s,
+                                   un_addr.sa_socklen);
                }
 
-               swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
+               swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
 
                return len;
        }
@@ -4039,8 +4291,9 @@ static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
 {
        struct socket_info *si;
        struct msghdr msg;
-       struct sockaddr_storage ss;
-       socklen_t ss_len = sizeof(ss);
+       struct swrap_address saddr = {
+               .sa_socklen = sizeof(struct sockaddr_storage),
+       };
        struct iovec tmp;
        ssize_t ret;
        int tret;
@@ -4054,8 +4307,8 @@ static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
        tmp.iov_len = len;
 
        ZERO_STRUCT(msg);
-       msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
-       msg.msg_namelen = ss_len;      /* size of address */
+       msg.msg_name = &saddr.sa.s;    /* optional address */
+       msg.msg_namelen = saddr.sa_socklen; /* size of address */
        msg.msg_iov = &tmp;            /* scatter/gather array */
        msg.msg_iovlen = 1;            /* # elements in msg_iov */
 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
@@ -4096,8 +4349,9 @@ static ssize_t swrap_read(int s, void *buf, size_t len)
        struct socket_info *si;
        struct msghdr msg;
        struct iovec tmp;
-       struct sockaddr_storage ss;
-       socklen_t ss_len = sizeof(ss);
+       struct swrap_address saddr = {
+               .sa_socklen = sizeof(struct sockaddr_storage),
+       };
        ssize_t ret;
        int tret;
 
@@ -4110,8 +4364,8 @@ static ssize_t swrap_read(int s, void *buf, size_t len)
        tmp.iov_len = len;
 
        ZERO_STRUCT(msg);
-       msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
-       msg.msg_namelen = ss_len;      /* size of address */
+       msg.msg_name = &saddr.sa.ss;   /* optional address */
+       msg.msg_namelen = saddr.sa_socklen; /* size of address */
        msg.msg_iov = &tmp;            /* scatter/gather array */
        msg.msg_iovlen = 1;            /* # elements in msg_iov */
 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
@@ -4203,8 +4457,9 @@ ssize_t send(int s, const void *buf, size_t len, int flags)
 
 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
 {
-       struct sockaddr_un from_addr;
-       socklen_t from_addrlen = sizeof(from_addr);
+       struct swrap_address from_addr = {
+               .sa_socklen = sizeof(struct sockaddr_un),
+       };
        struct socket_info *si;
        struct msghdr msg;
        struct iovec tmp;
@@ -4225,8 +4480,8 @@ static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
        tmp.iov_len = 0;
 
        ZERO_STRUCT(msg);
-       msg.msg_name = (struct sockaddr *)&from_addr; /* optional address */
-       msg.msg_namelen = from_addrlen;            /* size of address */
+       msg.msg_name = &from_addr.sa;              /* optional address */
+       msg.msg_namelen = from_addr.sa_socklen;    /* size of address */
        msg.msg_iov = omsg->msg_iov;               /* scatter/gather array */
        msg.msg_iovlen = omsg->msg_iovlen;         /* # elements in msg_iov */
 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
@@ -4266,7 +4521,12 @@ static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
        }
 #endif
 
-       rc = swrap_recvmsg_after(s, si, &msg, &from_addr, from_addrlen, ret);
+       rc = swrap_recvmsg_after(s,
+                                si,
+                                &msg,
+                                &from_addr.sa.un,
+                                from_addr.sa_socklen,
+                                ret);
        if (rc != 0) {
                return rc;
        }
@@ -4387,7 +4647,7 @@ static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
                        libc_sendmsg(s, &msg, flags);
                }
 
-               swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
+               swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
                free(buf);
 
                return len;
@@ -4414,8 +4674,9 @@ static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
        struct socket_info *si;
        struct msghdr msg;
        struct iovec tmp;
-       struct sockaddr_storage ss;
-       socklen_t ss_len = sizeof(ss);
+       struct swrap_address saddr = {
+               .sa_socklen = sizeof(struct sockaddr_storage)
+       };
        ssize_t ret;
        int rc;
 
@@ -4428,8 +4689,8 @@ static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
        tmp.iov_len = 0;
 
        ZERO_STRUCT(msg);
-       msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
-       msg.msg_namelen = ss_len;      /* size of address */
+       msg.msg_name = &saddr.sa.s; /* optional address */
+       msg.msg_namelen = saddr.sa_socklen;      /* size of address */
        msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
        msg.msg_iovlen = count;        /* # elements in msg_iov */
 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
@@ -4541,26 +4802,19 @@ static int swrap_close(int fd)
 
        SWRAP_DLIST_REMOVE(sockets, si);
 
-       if (si->myname && si->peername) {
-               swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
+       if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
+               swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
        }
 
        ret = libc_close(fd);
 
-       if (si->myname && si->peername) {
-               swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
-               swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
-       }
-
-       if (si->bindname != NULL) {
-               free(si->bindname);
+       if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
+               swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
+               swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
        }
 
-       if (si->myname) free(si->myname);
-       if (si->peername) free(si->peername);
-       if (si->tmp_path) {
-               unlink(si->tmp_path);
-               free(si->tmp_path);
+       if (si->un_addr.sun_path[0] != '\0') {
+               unlink(si->un_addr.sun_path);
        }
        free(si);