diff options
author | Andrew Bartlett <abartlet@samba.org> | 2009-05-26 11:43:37 +1000 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2009-05-26 12:37:09 +1000 |
commit | 86039855759ce38e6074f956073199b0ccd29bdf (patch) | |
tree | a7c9bfb03bdb6ac6e3aca74a81028faa28583485 | |
parent | 714acfac013a46c3677c3eb72ad57db6d97c7d61 (diff) | |
download | samba-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.c | 71 | ||||
-rw-r--r-- | lib/socket_wrapper/socket_wrapper.h | 6 |
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 |