socket_wrapper: use swrap_sendmsg_before()/after() in swrap_sendmsg()
authorStefan Metzmacher <metze@samba.org>
Sat, 30 Oct 2010 14:23:49 +0000 (16:23 +0200)
committerStefan Metzmacher <metze@samba.org>
Thu, 3 Mar 2011 21:57:26 +0000 (22:57 +0100)
This also adds the same logic for broadcast as in swrap_sendto()
for SOCK_DGRAM.

metze

lib/socket_wrapper/socket_wrapper.c

index d514ae45359d83414bea6f68a14f93fb414a627a..e5614d1db4244ee958df3e1df00defc0009cc0a1 100644 (file)
@@ -2285,72 +2285,91 @@ _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
        return ret;
 }
 
-_PUBLIC_ ssize_t swrap_sendmsg(int s, const struct msghdr *msg, int flags)
+_PUBLIC_ ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
 {
-       int ret;
-       uint8_t *buf;
-       off_t ofs = 0;
-       size_t i;
-       size_t remain;
-
+       struct msghdr msg;
+       struct iovec tmp;
+       struct sockaddr_un un_addr;
+       const struct sockaddr_un *to_un = NULL;
+       const struct sockaddr *to = NULL;
+       ssize_t ret;
        struct socket_info *si = find_socket_info(s);
+       int bcast = 0;
 
        if (!si) {
-               return real_sendmsg(s, msg, flags);
+               return real_sendmsg(s, omsg, flags);
        }
 
-       if (si->defer_connect) {
-               struct sockaddr_un un_addr;
-               int bcast = 0;
+       tmp.iov_base = NULL;
+       tmp.iov_len = 0;
 
-               if (si->bound == 0) {
-                       ret = swrap_auto_bind(si, si->family);
-                       if (ret == -1) return -1;
+       msg.msg_name = omsg->msg_name;             /* optional address */
+       msg.msg_namelen = omsg->msg_namelen;       /* size of address */
+       msg.msg_iov = omsg->msg_iov;               /* scatter/gather array */
+       msg.msg_iovlen = omsg->msg_iovlen;         /* # elements in msg_iov */
+       msg.msg_control = omsg->msg_control;       /* ancillary data, see below */
+       msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
+       msg.msg_flags = omsg->msg_flags;           /* flags on received message */
+
+       ret = swrap_sendmsg_before(si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
+       if (ret == -1) return -1;
+
+       if (bcast) {
+               struct stat st;
+               unsigned int iface;
+               unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
+               char type;
+               size_t i, len = 0;
+               uint8_t *buf;
+               off_t ofs = 0;
+               size_t avail = 0;
+               size_t remain;
+
+               for (i=0; i < msg.msg_iovlen; i++) {
+                       avail += msg.msg_iov[i].iov_len;
                }
 
-               ret = sockaddr_convert_to_un(si, si->peername, si->peername_len,
-                                            &un_addr, 0, &bcast);
-               if (ret == -1) return -1;
+               len = avail;
+               remain = avail;
 
-               ret = real_connect(s, (struct sockaddr *)(void *)&un_addr,
-                                  sizeof(un_addr));
+               /* we capture it as one single packet */
+               buf = (uint8_t *)malloc(remain);
+               if (!buf) {
+                       return -1;
+               }
 
-               /* to give better errors */
-               if (ret == -1 && errno == ENOENT) {
-                       errno = EHOSTUNREACH;
+               for (i=0; i < msg.msg_iovlen; i++) {
+                       size_t this_time = MIN(remain, msg.msg_iov[i].iov_len);
+                       memcpy(buf + ofs,
+                              msg.msg_iov[i].iov_base,
+                              this_time);
+                       ofs += this_time;
+                       remain -= this_time;
                }
 
-               if (ret == -1) {
-                       return ret;
+               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,
+                                socket_wrapper_dir(), type, iface, prt);
+                       if (stat(un_addr.sun_path, &st) != 0) continue;
+
+                       msg.msg_name = &un_addr;           /* optional address */
+                       msg.msg_namelen = sizeof(un_addr); /* size of address */
+
+                       /* ignore the any errors in broadcast sends */
+                       real_sendmsg(s, &msg, flags);
                }
-               si->defer_connect = 0;
-       }
 
-       ret = real_sendmsg(s, msg, flags);
-       remain = ret;
+               swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
+               free(buf);
 
-       /* we capture it as one single packet */
-       buf = (uint8_t *)malloc(ret);
-       if (!buf) {
-               /* we just not capture the packet */
-               errno = 0;
-               return ret;
+               return len;
        }
 
-       for (i=0; i < msg->msg_iovlen; i++) {
-               size_t this_time = MIN(remain, msg->msg_iov[i].iov_len);
-               memcpy(buf + ofs,
-                      msg->msg_iov[i].iov_base,
-                      this_time);
-               ofs += this_time;
-               remain -= this_time;
-       }
+       ret = real_sendmsg(s, &msg, flags);
 
-       swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
-       free(buf);
-       if (ret == -1) {
-               swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
-       }
+       swrap_sendmsg_after(si, &msg, to, ret);
 
        return ret;
 }