summaryrefslogtreecommitdiffstats
path: root/lib
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
parent714acfac013a46c3677c3eb72ad57db6d97c7d61 (diff)
downloadsamba-86039855759ce38e6074f956073199b0ccd29bdf.tar.gz
samba-86039855759ce38e6074f956073199b0ccd29bdf.tar.xz
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')
-rw-r--r--lib/socket_wrapper/socket_wrapper.c71
-rw-r--r--lib/socket_wrapper/socket_wrapper.h6
2 files changed, 77 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;
diff --git a/lib/socket_wrapper/socket_wrapper.h b/lib/socket_wrapper/socket_wrapper.h
index b2d44769ff..56282e23b9 100644
--- a/lib/socket_wrapper/socket_wrapper.h
+++ b/lib/socket_wrapper/socket_wrapper.h
@@ -49,6 +49,7 @@ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *opt
int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen);
ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);
ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);
+ssize_t swrap_sendmsg(int s, const struct msghdr *msg, int flags);
int swrap_ioctl(int s, int req, void *ptr);
ssize_t swrap_recv(int s, void *buf, size_t len, int flags);
ssize_t swrap_send(int s, const void *buf, size_t len, int flags);
@@ -108,6 +109,11 @@ int swrap_close(int);
#endif
#define sendto(s,buf,len,flags,to,tolen) swrap_sendto(s,buf,len,flags,to,tolen)
+#ifdef sendmsg
+#undef sendmsg
+#endif
+#define sendmsg(s,msg,flags) swrap_sendmsg(s,msg,flags)
+
#ifdef ioctl
#undef ioctl
#endif