summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2009-03-23 09:16:18 +0100
committerStefan Metzmacher <metze@samba.org>2009-03-23 12:19:29 +0100
commit435a0a5a3bc8114991650a78e1f90049d2f3f343 (patch)
treef371a5d74e8f90da75653ea5357f52828d49174c
parent298bff5019be5a40dc0023b5af1e980fba91abd9 (diff)
downloadsamba-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.c56
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) {