diff options
author | Andrew Bartlett <abartlet@samba.org> | 2009-03-10 10:59:14 +1100 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2009-03-10 10:59:14 +1100 |
commit | c218d3e1173355acf025471a10b4b6425b9c086b (patch) | |
tree | 3e5be3c411ebe2575914f7866c91bad81f711154 /lib | |
parent | 6ac77d19b5a25a53459a58e4828fa9eac0bf11f4 (diff) | |
parent | 218ce0e80532b0dbc595e72502d9596a35acdffd (diff) | |
download | samba-c218d3e1173355acf025471a10b4b6425b9c086b.tar.gz samba-c218d3e1173355acf025471a10b4b6425b9c086b.tar.bz2 samba-c218d3e1173355acf025471a10b4b6425b9c086b.zip |
Merge branch 'master' of ssh://git.samba.org/data/git/samba into wspp-schema
Diffstat (limited to 'lib')
-rw-r--r-- | lib/async_req/async_sock.c | 30 | ||||
-rw-r--r-- | lib/async_req/async_sock.h | 3 | ||||
-rw-r--r-- | lib/socket_wrapper/socket_wrapper.c | 77 | ||||
-rw-r--r-- | lib/util/charset/charcnv.c | 6 | ||||
-rw-r--r-- | lib/util/charset/charset.h | 6 | ||||
-rw-r--r-- | lib/util/charset/util_unistr.c | 2 |
6 files changed, 101 insertions, 23 deletions
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, diff --git a/lib/socket_wrapper/socket_wrapper.c b/lib/socket_wrapper/socket_wrapper.c index 8ad9e1d93e..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) @@ -202,6 +215,7 @@ struct socket_info int bound; int bcast; int is_server; + int connected; char *path; char *tmp_path; @@ -304,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); @@ -394,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; @@ -510,7 +524,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; @@ -1485,6 +1501,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); @@ -1532,8 +1549,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; @@ -1551,7 +1570,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; @@ -1580,6 +1599,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; @@ -1594,7 +1618,7 @@ static int swrap_auto_bind(struct socket_info *si) 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); @@ -1630,6 +1654,7 @@ static int swrap_auto_bind(struct socket_info *si) return -1; } + si->family = family; set_port(si->family, port, si->myname); return 0; @@ -1647,7 +1672,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; } @@ -1672,7 +1697,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 { @@ -1801,11 +1833,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 :-( */ @@ -1836,6 +1875,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) { @@ -1844,7 +1893,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; } diff --git a/lib/util/charset/charcnv.c b/lib/util/charset/charcnv.c index 258730ec82..94d47a9f7f 100644 --- a/lib/util/charset/charcnv.c +++ b/lib/util/charset/charcnv.c @@ -169,9 +169,10 @@ static smb_iconv_t get_conv_handle(struct smb_iconv_convenience *ic, _PUBLIC_ ssize_t iconv_talloc(TALLOC_CTX *ctx, smb_iconv_t cd, void const *src, size_t srclen, - void **dest) + void *dst) { size_t i_len, o_len, destlen; + void **dest = (void **)dst; size_t retval; const char *inbuf = (const char *)src; char *outbuf, *ob; @@ -314,9 +315,10 @@ _PUBLIC_ bool convert_string_talloc_convenience(TALLOC_CTX *ctx, struct smb_iconv_convenience *ic, charset_t from, charset_t to, void const *src, size_t srclen, - void **dest, size_t *converted_size, + void *dst, size_t *converted_size, bool allow_badcharcnv) { + void **dest = (void **)dst; smb_iconv_t descriptor; ssize_t ret; diff --git a/lib/util/charset/charset.h b/lib/util/charset/charset.h index 655bae7bcd..37c5acafaf 100644 --- a/lib/util/charset/charset.h +++ b/lib/util/charset/charset.h @@ -136,7 +136,7 @@ ssize_t pull_string(char *dest, const void *src, size_t dest_len, size_t src_len bool convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, void const *src, size_t srclen, - void **dest, size_t *converted_size, + void *dest, size_t *converted_size, bool allow_badcharcnv); size_t convert_string(charset_t from, charset_t to, @@ -146,7 +146,7 @@ size_t convert_string(charset_t from, charset_t to, ssize_t iconv_talloc(TALLOC_CTX *mem_ctx, smb_iconv_t cd, void const *src, size_t srclen, - void **dest); + void *dest); extern struct smb_iconv_convenience *global_iconv_convenience; @@ -176,7 +176,7 @@ bool convert_string_talloc_convenience(TALLOC_CTX *ctx, struct smb_iconv_convenience *ic, charset_t from, charset_t to, void const *src, size_t srclen, - void **dest, size_t *converted_size, bool allow_badcharcnv); + void *dest, size_t *converted_size, bool allow_badcharcnv); /* iconv */ smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode); int smb_iconv_close(smb_iconv_t cd); diff --git a/lib/util/charset/util_unistr.c b/lib/util/charset/util_unistr.c index ec88e784d0..ea2bfeab9f 100644 --- a/lib/util/charset/util_unistr.c +++ b/lib/util/charset/util_unistr.c @@ -978,7 +978,7 @@ _PUBLIC_ size_t convert_string(charset_t from, charset_t to, _PUBLIC_ bool convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, void const *src, size_t srclen, - void **dest, size_t *converted_size, + void *dest, size_t *converted_size, bool allow_badcharcnv) { return convert_string_talloc_convenience(ctx, get_iconv_convenience(), |