summaryrefslogtreecommitdiff
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
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
-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