From fe486d7b9f580a17d23dd57582087c7d28cb738d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 1 Mar 2009 19:43:07 +0100 Subject: Add "queue" to writev_send Unless higher levels queue themselves somehow, writev will *always* be queued. So the queueing should be done at the right level. --- lib/async_req/async_sock.c | 30 ++++++++++++++++++++++++++++-- lib/async_req/async_sock.h | 3 ++- 2 files changed, 30 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/async_req/async_sock.c b/lib/async_req/async_sock.c index 424da952eb..f803b9cc36 100644 --- a/lib/async_req/async_sock.c +++ b/lib/async_req/async_sock.c @@ -379,11 +379,13 @@ struct writev_state { size_t total_size; }; +static void writev_trigger(struct tevent_req *req, void *private_data); static void writev_handler(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, void *private_data); struct tevent_req *writev_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - int fd, struct iovec *iov, int count) + struct tevent_queue *queue, int fd, + struct iovec *iov, int count) { struct tevent_req *result; struct writev_state *state; @@ -403,18 +405,42 @@ struct tevent_req *writev_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, goto fail; } + /* + * This if () should go away once our callers are converted to always + * pass in a queue. + */ + + if (queue != NULL) { + if (!tevent_queue_add(queue, ev, result, writev_trigger, + NULL)) { + goto fail; + } + return result; + } + fde = tevent_add_fd(ev, state, fd, TEVENT_FD_WRITE, writev_handler, result); if (fde == NULL) { goto fail; } return result; - fail: TALLOC_FREE(result); return NULL; } +static void writev_trigger(struct tevent_req *req, void *private_data) +{ + struct writev_state *state = tevent_req_data(req, struct writev_state); + struct tevent_fd *fde; + + fde = tevent_add_fd(state->ev, state, state->fd, TEVENT_FD_WRITE, + writev_handler, req); + if (fde == NULL) { + tevent_req_error(req, ENOMEM); + } +} + static void writev_handler(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, void *private_data) { diff --git a/lib/async_req/async_sock.h b/lib/async_req/async_sock.h index e001709d27..c5d9400eb6 100644 --- a/lib/async_req/async_sock.h +++ b/lib/async_req/async_sock.h @@ -43,7 +43,8 @@ struct tevent_req *async_connect_send(TALLOC_CTX *mem_ctx, int async_connect_recv(struct tevent_req *req, int *perrno); struct tevent_req *writev_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - int fd, struct iovec *iov, int count); + struct tevent_queue *queue, int fd, + struct iovec *iov, int count); ssize_t writev_recv(struct tevent_req *req, int *perrno); struct tevent_req *read_packet_send(TALLOC_CTX *mem_ctx, -- cgit From 81e2633e41e9c8c1dddff7cc1122c7d6f28626bd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 3 Mar 2009 19:40:57 +0100 Subject: socket_wrapper: make it possible to bind to '::' metze --- lib/socket_wrapper/socket_wrapper.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/socket_wrapper/socket_wrapper.c b/lib/socket_wrapper/socket_wrapper.c index 8ad9e1d93e..1f56a8358e 100644 --- a/lib/socket_wrapper/socket_wrapper.c +++ b/lib/socket_wrapper/socket_wrapper.c @@ -510,7 +510,9 @@ static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *in cmp = in->sin6_addr; cmp.s6_addr[15] = 0; - if (IN6_ARE_ADDR_EQUAL(&swrap_ipv6, &cmp)) { + if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) { + iface = socket_wrapper_default_iface(); + } else if (IN6_ARE_ADDR_EQUAL(&swrap_ipv6, &cmp)) { iface = in->sin6_addr.s6_addr[15]; } else { errno = EADDRNOTAVAIL; -- cgit From f9156f6c77d9e87edc153b024a1d564b44eedd8f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 8 Mar 2009 17:19:50 +0100 Subject: socket_wrapper: correctly handle connected dgram sockets metze --- lib/socket_wrapper/socket_wrapper.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'lib') diff --git a/lib/socket_wrapper/socket_wrapper.c b/lib/socket_wrapper/socket_wrapper.c index 1f56a8358e..b2d3a6b15d 100644 --- a/lib/socket_wrapper/socket_wrapper.c +++ b/lib/socket_wrapper/socket_wrapper.c @@ -202,6 +202,7 @@ struct socket_info int bound; int bcast; int is_server; + int connected; char *path; char *tmp_path; @@ -1487,6 +1488,7 @@ _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) child_si->protocol = parent_si->protocol; child_si->bound = 1; child_si->is_server = 1; + child_si->connected = 1; child_si->peername_len = len; child_si->peername = sockaddr_dup(my_addr, len); @@ -1674,7 +1676,14 @@ _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t ad if (ret == 0) { si->peername_len = addrlen; si->peername = sockaddr_dup(serv_addr, addrlen); + si->connected = 1; + } + + if (si->type != SOCK_STREAM) { + return ret; + } + if (ret == 0) { swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0); swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0); } else { @@ -1803,11 +1812,18 @@ _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct socklen_t un_addrlen = sizeof(un_addr); int ret; struct socket_info *si = find_socket_info(s); + struct sockaddr_storage ss; + socklen_t ss_len = sizeof(ss); if (!si) { return real_recvfrom(s, buf, len, flags, from, fromlen); } + if (!from) { + from = (struct sockaddr *)&ss; + fromlen = &ss_len; + } + len = MIN(len, 1500); /* irix 6.4 forgets to null terminate the sun_path string :-( */ @@ -1838,6 +1854,16 @@ _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, con return real_sendto(s, buf, len, flags, to, tolen); } + if (si->connected) { + if (to) { + errno = EISCONN; + return -1; + } + + to = si->peername; + tolen = si->peername_len; + } + len = MIN(len, 1500); switch (si->type) { -- cgit From 3679e8243459f928b1a4d0998d47c6efdedd0301 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 8 Mar 2009 17:20:18 +0100 Subject: socket_wrapper: downgrade ipv6 sockets to ipv4 is in connect() if the dest is ipv4 We only do this if the socket isn't explicit bound yet. metze --- lib/socket_wrapper/socket_wrapper.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/socket_wrapper/socket_wrapper.c b/lib/socket_wrapper/socket_wrapper.c index b2d3a6b15d..733a33217c 100644 --- a/lib/socket_wrapper/socket_wrapper.c +++ b/lib/socket_wrapper/socket_wrapper.c @@ -1536,8 +1536,10 @@ static int autobind_start; /* using sendto() or connect() on an unbound socket would give the recipient no way to reply, as unlike UDP and TCP, a unix domain socket can't auto-assign emphemeral port numbers, so we need to - assign it here */ -static int swrap_auto_bind(struct socket_info *si) + assign it here. + Note: this might change the family from ipv6 to ipv4 +*/ +static int swrap_auto_bind(struct socket_info *si, int family) { struct sockaddr_un un_addr; int i; @@ -1555,7 +1557,7 @@ static int swrap_auto_bind(struct socket_info *si) un_addr.sun_family = AF_UNIX; - switch (si->family) { + switch (family) { case AF_INET: { struct sockaddr_in in; @@ -1584,6 +1586,11 @@ static int swrap_auto_bind(struct socket_info *si) case AF_INET6: { struct sockaddr_in6 in6; + if (si->family != family) { + errno = ENETUNREACH; + return -1; + } + switch (si->type) { case SOCK_STREAM: type = SOCKET_TYPE_CHAR_TCP_V6; @@ -1634,6 +1641,7 @@ static int swrap_auto_bind(struct socket_info *si) return -1; } + si->family = family; set_port(si->family, port, si->myname); return 0; @@ -1651,7 +1659,7 @@ _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t ad } if (si->bound == 0) { - ret = swrap_auto_bind(si); + ret = swrap_auto_bind(si, serv_addr->sa_family); if (ret == -1) return -1; } @@ -1872,7 +1880,7 @@ _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, con break; case SOCK_DGRAM: if (si->bound == 0) { - ret = swrap_auto_bind(si); + ret = swrap_auto_bind(si, si->family); if (ret == -1) return -1; } -- cgit From 5ff4cb580f5892754a208684dba6fef4834d6e7f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 9 Mar 2009 09:24:45 +0100 Subject: socket_wrapper: try to make ipv6 support more portable The internal structure of in6_addr isn't always the same. metze --- lib/socket_wrapper/socket_wrapper.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/socket_wrapper/socket_wrapper.c b/lib/socket_wrapper/socket_wrapper.c index 733a33217c..97e60468c4 100644 --- a/lib/socket_wrapper/socket_wrapper.c +++ b/lib/socket_wrapper/socket_wrapper.c @@ -149,11 +149,24 @@ /* * FD00::5357:5FXX */ -static const struct in6_addr swrap_ipv6 = -{ { { -0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x53,0x57,0x5F,0x00 -} } }; +static const struct in6_addr *swrap_ipv6(void) +{ + static struct in6_addr v; + static int initialized; + int ret; + + if (initialized) { + return &v; + } + initialized = 1; + + ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v); + if (ret <= 0) { + abort(); + } + + return &v; +} #endif static struct sockaddr *sockaddr_dup(const void *data, socklen_t len) @@ -305,7 +318,7 @@ static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, sock memset(in2, 0, sizeof(*in2)); in2->sin6_family = AF_INET6; - in2->sin6_addr = swrap_ipv6; + in2->sin6_addr = *swrap_ipv6(); in2->sin6_addr.s6_addr[15] = iface; in2->sin6_port = htons(prt); @@ -395,7 +408,7 @@ static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *i cmp = in->sin6_addr; cmp.s6_addr[15] = 0; - if (IN6_ARE_ADDR_EQUAL(&swrap_ipv6, &cmp)) { + if (IN6_ARE_ADDR_EQUAL(swrap_ipv6(), &cmp)) { iface = in->sin6_addr.s6_addr[15]; } else { errno = ENETUNREACH; @@ -513,7 +526,7 @@ static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *in cmp.s6_addr[15] = 0; if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) { iface = socket_wrapper_default_iface(); - } else if (IN6_ARE_ADDR_EQUAL(&swrap_ipv6, &cmp)) { + } else if (IN6_ARE_ADDR_EQUAL(swrap_ipv6(), &cmp)) { iface = in->sin6_addr.s6_addr[15]; } else { errno = EADDRNOTAVAIL; @@ -1605,7 +1618,7 @@ static int swrap_auto_bind(struct socket_info *si, int family) memset(&in6, 0, sizeof(in6)); in6.sin6_family = AF_INET6; - in6.sin6_addr = swrap_ipv6; + in6.sin6_addr = *swrap_ipv6(); in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface(); si->myname_len = sizeof(in6); si->myname = sockaddr_dup(&in6, si->myname_len); -- cgit