summaryrefslogtreecommitdiff
path: root/lib/socket_wrapper/socket_wrapper.c
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2009-05-26 11:43:37 +1000
committerAndrew Bartlett <abartlet@samba.org>2009-05-26 12:37:09 +1000
commit86039855759ce38e6074f956073199b0ccd29bdf (patch)
treea7c9bfb03bdb6ac6e3aca74a81028faa28583485 /lib/socket_wrapper/socket_wrapper.c
parent714acfac013a46c3677c3eb72ad57db6d97c7d61 (diff)
downloadsamba-86039855759ce38e6074f956073199b0ccd29bdf.tar.gz
samba-86039855759ce38e6074f956073199b0ccd29bdf.tar.bz2
samba-86039855759ce38e6074f956073199b0ccd29bdf.zip
Add support for sendmsg() in socket_wrapper
This is required because the deferred connect code skips the connect() until sending the packet, but unless we catch this call, the connect() never happens. Andrew Bartlett
Diffstat (limited to 'lib/socket_wrapper/socket_wrapper.c')
-rw-r--r--lib/socket_wrapper/socket_wrapper.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/lib/socket_wrapper/socket_wrapper.c b/lib/socket_wrapper/socket_wrapper.c
index d809d8a500..bd848f920b 100644
--- a/lib/socket_wrapper/socket_wrapper.c
+++ b/lib/socket_wrapper/socket_wrapper.c
@@ -118,6 +118,7 @@
#define real_setsockopt setsockopt
#define real_recvfrom recvfrom
#define real_sendto sendto
+#define real_sendmsg sendmsg
#define real_ioctl ioctl
#define real_recv recv
#define real_send send
@@ -2064,6 +2065,76 @@ _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)
+{
+ int ret;
+ uint8_t *buf;
+ off_t ofs = 0;
+ size_t i;
+ size_t remain;
+
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return real_sendmsg(s, msg, flags);
+ }
+
+ if (si->defer_connect) {
+ struct sockaddr_un un_addr;
+ int bcast = 0;
+
+ if (si->bound == 0) {
+ ret = swrap_auto_bind(si, si->family);
+ if (ret == -1) return -1;
+ }
+
+ ret = sockaddr_convert_to_un(si, si->peername, si->peername_len,
+ &un_addr, 0, &bcast);
+ if (ret == -1) return -1;
+
+ ret = real_connect(s, (struct sockaddr *)&un_addr,
+ sizeof(un_addr));
+
+ /* to give better errors */
+ if (ret == -1 && errno == ENOENT) {
+ errno = EHOSTUNREACH;
+ }
+
+ if (ret == -1) {
+ return ret;
+ }
+ si->defer_connect = 0;
+ }
+
+ ret = real_sendmsg(s, msg, flags);
+ remain = ret;
+
+ /* we capture it as one single packet */
+ buf = (uint8_t *)malloc(ret);
+ if (!buf) {
+ /* we just not capture the packet */
+ errno = 0;
+ return ret;
+ }
+
+ 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;
+ }
+
+ swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
+ free(buf);
+ if (ret == -1) {
+ swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
+ }
+
+ return ret;
+}
+
int swrap_readv(int s, const struct iovec *vector, size_t count)
{
int ret;