summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/socket_wrapper/socket_wrapper.c113
1 files changed, 66 insertions, 47 deletions
diff --git a/lib/socket_wrapper/socket_wrapper.c b/lib/socket_wrapper/socket_wrapper.c
index d514ae4535..e5614d1db4 100644
--- a/lib/socket_wrapper/socket_wrapper.c
+++ b/lib/socket_wrapper/socket_wrapper.c
@@ -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;
}