diff options
author | Stefan Metzmacher <metze@samba.org> | 2009-03-23 09:16:18 +0100 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2009-03-23 12:19:29 +0100 |
commit | 435a0a5a3bc8114991650a78e1f90049d2f3f343 (patch) | |
tree | f371a5d74e8f90da75653ea5357f52828d49174c | |
parent | 298bff5019be5a40dc0023b5af1e980fba91abd9 (diff) | |
download | samba-435a0a5a3bc8114991650a78e1f90049d2f3f343.tar.gz samba-435a0a5a3bc8114991650a78e1f90049d2f3f343.tar.bz2 samba-435a0a5a3bc8114991650a78e1f90049d2f3f343.zip |
socket_wrapper: fix connect() for dgram sockets, if the destination isn't there yet
Now we defer the real_connect() for dgram sockets to the first send()/sendto() call,
as the destination might not be there at connect time.
Commit 66dc53ee017d74a6f610bbe04337f064901fe2a1 was an incomplete fix for this
problem.
metze
-rw-r--r-- | lib/socket_wrapper/socket_wrapper.c | 56 |
1 files changed, 52 insertions, 4 deletions
diff --git a/lib/socket_wrapper/socket_wrapper.c b/lib/socket_wrapper/socket_wrapper.c index 44082e78a1..553827b192 100644 --- a/lib/socket_wrapper/socket_wrapper.c +++ b/lib/socket_wrapper/socket_wrapper.c @@ -218,6 +218,7 @@ struct socket_info int bcast; int is_server; int connected; + int defer_connect; char *path; char *tmp_path; @@ -1686,10 +1687,15 @@ _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t ad ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL); if (ret == -1) return -1; - swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0); + if (si->type == SOCK_DGRAM) { + si->defer_connect = 1; + ret = 0; + } else { + swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0); - ret = real_connect(s, (struct sockaddr *)&un_addr, - sizeof(struct sockaddr_un)); + ret = real_connect(s, (struct sockaddr *)&un_addr, + sizeof(struct sockaddr_un)); + } /* to give better errors */ if (ret == -1 && errno == ENOENT) { @@ -1917,7 +1923,22 @@ _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, con return len; } - + + if (si->defer_connect) { + 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_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr)); break; default: @@ -2002,6 +2023,33 @@ _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags) len = MIN(len, 1500); + 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_send(s, buf, len, flags); if (ret == -1) { |