diff options
-rw-r--r-- | lib/async_req/async_sock.c | 583 | ||||
-rw-r--r-- | lib/async_req/async_sock.h | 46 | ||||
-rw-r--r-- | lib/tevent/tevent.h | 1 | ||||
-rw-r--r-- | lib/util/tevent_unix.c | 46 | ||||
-rw-r--r-- | lib/util/tevent_unix.h | 27 | ||||
-rw-r--r-- | source3/Makefile.in | 3 | ||||
-rw-r--r-- | source3/include/proto.h | 11 | ||||
-rw-r--r-- | source3/lib/util.c | 99 | ||||
-rw-r--r-- | source3/lib/util_sock.c | 29 | ||||
-rw-r--r-- | source3/lib/wb_reqtrans.c | 401 | ||||
-rw-r--r-- | source3/lib/wbclient.c | 62 | ||||
-rw-r--r-- | source3/libsmb/cliconnect.c | 25 | ||||
-rw-r--r-- | source3/libsmb/nmblib.c | 15 | ||||
-rw-r--r-- | source3/rpc_server/srv_pipe_hnd.c | 38 | ||||
-rw-r--r-- | source3/utils/smbfilter.c | 11 | ||||
-rw-r--r-- | source4/rpc_server/netlogon/dcerpc_netlogon.c | 33 |
16 files changed, 715 insertions, 715 deletions
diff --git a/lib/async_req/async_sock.c b/lib/async_req/async_sock.c index 02ae880683..3563421e0e 100644 --- a/lib/async_req/async_sock.c +++ b/lib/async_req/async_sock.c @@ -22,6 +22,7 @@ #include "lib/tevent/tevent.h" #include "lib/async_req/async_req.h" #include "lib/async_req/async_sock.h" +#include "lib/util/tevent_unix.h" #include <fcntl.h> #ifndef TALLOC_FREE @@ -33,10 +34,7 @@ */ enum async_syscall_type { ASYNC_SYSCALL_SEND, - ASYNC_SYSCALL_SENDALL, ASYNC_SYSCALL_RECV, - ASYNC_SYSCALL_RECVALL, - ASYNC_SYSCALL_CONNECT }; /** @@ -54,36 +52,12 @@ struct async_syscall_state { size_t length; int flags; } param_send; - struct param_sendall { - int fd; - const void *buffer; - size_t length; - int flags; - size_t sent; - } param_sendall; struct param_recv { int fd; void *buffer; size_t length; int flags; } param_recv; - struct param_recvall { - int fd; - void *buffer; - size_t length; - int flags; - size_t received; - } param_recvall; - struct param_connect { - /** - * connect needs to be done on a nonblocking - * socket. Keep the old flags around - */ - long old_sockflags; - int fd; - const struct sockaddr *address; - socklen_t address_len; - } param_connect; } param; union { @@ -337,109 +311,6 @@ struct async_req *async_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, } /** - * fde event handler for the "sendall" syscall group - * @param[in] ev The event context that sent us here - * @param[in] fde The file descriptor event associated with the send - * @param[in] flags Can only be TEVENT_FD_WRITE here - * @param[in] priv private data, "struct async_req *" in this case - */ - -static void async_sendall_callback(struct tevent_context *ev, - struct tevent_fd *fde, uint16_t flags, - void *priv) -{ - struct async_req *req = talloc_get_type_abort( - priv, struct async_req); - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - struct param_sendall *p = &state->param.param_sendall; - - if (state->syscall_type != ASYNC_SYSCALL_SENDALL) { - async_req_error(req, EIO); - return; - } - - state->result.result_ssize_t = send(p->fd, - (const char *)p->buffer + p->sent, - p->length - p->sent, p->flags); - state->sys_errno = errno; - - if (state->result.result_ssize_t == -1) { - async_req_error(req, state->sys_errno); - return; - } - - if (state->result.result_ssize_t == 0) { - async_req_error(req, EOF); - return; - } - - p->sent += state->result.result_ssize_t; - if (p->sent > p->length) { - async_req_error(req, EIO); - return; - } - - if (p->sent == p->length) { - TALLOC_FREE(state->fde); - async_req_done(req); - } -} - -/** - * @brief Send all bytes to a socket - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] fd The socket to send to - * @param[in] buffer The buffer to send - * @param[in] length How many bytes to send - * @param[in] flags flags passed to send(2) - * - * async_sendall calls send(2) as long as it is necessary to send all of the - * "length" bytes - */ - -struct async_req *sendall_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - int fd, const void *buffer, size_t length, - int flags) -{ - struct async_req *result; - struct async_syscall_state *state; - - result = async_fde_syscall_new( - mem_ctx, ev, ASYNC_SYSCALL_SENDALL, - fd, TEVENT_FD_WRITE, async_sendall_callback, - &state); - if (result == NULL) { - return NULL; - } - - state->param.param_sendall.fd = fd; - state->param.param_sendall.buffer = buffer; - state->param.param_sendall.length = length; - state->param.param_sendall.flags = flags; - state->param.param_sendall.sent = 0; - - return result; -} - -ssize_t sendall_recv(struct async_req *req, int *perr) -{ - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - int err; - - err = async_req_simple_recv_errno(req); - - if (err != 0) { - *perr = err; - return -1; - } - - return state->result.result_ssize_t; -} - -/** * fde event handler for the "recv" syscall * @param[in] ev The event context that sent us here * @param[in] fde The file descriptor event associated with the recv @@ -507,106 +378,138 @@ struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct tevent_context *ev, return result; } -/** - * fde event handler for the "recvall" syscall group - * @param[in] ev The event context that sent us here - * @param[in] fde The file descriptor event associated with the recv - * @param[in] flags Can only be TEVENT_FD_READ here - * @param[in] priv private data, "struct async_req *" in this case - */ +struct async_send_state { + int fd; + const void *buf; + size_t len; + int flags; + ssize_t sent; +}; -static void async_recvall_callback(struct tevent_context *ev, - struct tevent_fd *fde, uint16_t flags, - void *priv) +static void async_send_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, void *private_data); + +struct tevent_req *async_send_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int fd, const void *buf, size_t len, + int flags) { - struct async_req *req = talloc_get_type_abort( - priv, struct async_req); - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - struct param_recvall *p = &state->param.param_recvall; + struct tevent_req *result; + struct async_send_state *state; + struct tevent_fd *fde; - if (state->syscall_type != ASYNC_SYSCALL_RECVALL) { - async_req_error(req, EIO); - return; + result = tevent_req_create(mem_ctx, &state, struct async_send_state); + if (result == NULL) { + return result; } + state->fd = fd; + state->buf = buf; + state->len = len; + state->flags = flags; - state->result.result_ssize_t = recv(p->fd, - (char *)p->buffer + p->received, - p->length - p->received, p->flags); - state->sys_errno = errno; - - if (state->result.result_ssize_t == -1) { - async_req_error(req, state->sys_errno); - return; + fde = tevent_add_fd(ev, state, fd, TEVENT_FD_WRITE, async_send_handler, + result); + if (fde == NULL) { + TALLOC_FREE(result); + return NULL; } + return result; +} - if (state->result.result_ssize_t == 0) { - async_req_error(req, EIO); +static void async_send_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, void *private_data) +{ + struct tevent_req *req = talloc_get_type_abort( + private_data, struct tevent_req); + struct async_send_state *state = talloc_get_type_abort( + req->private_state, struct async_send_state); + + state->sent = send(state->fd, state->buf, state->len, state->flags); + if (state->sent == -1) { + tevent_req_error(req, errno); return; } + tevent_req_done(req); +} - p->received += state->result.result_ssize_t; - if (p->received > p->length) { - async_req_error(req, EIO); - return; - } +ssize_t async_send_recv(struct tevent_req *req, int *perrno) +{ + struct async_send_state *state = talloc_get_type_abort( + req->private_state, struct async_send_state); - if (p->received == p->length) { - TALLOC_FREE(state->fde); - async_req_done(req); + if (tevent_req_is_unix_error(req, perrno)) { + return -1; } + return state->sent; } -/** - * Receive a specified number of bytes from a socket - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] fd The socket to recv from - * @param[in] buffer The buffer to recv into - * @param[in] length How many bytes to recv - * @param[in] flags flags passed to recv(2) - * - * async_recvall will call recv(2) until "length" bytes are received - */ +struct async_recv_state { + int fd; + void *buf; + size_t len; + int flags; + ssize_t received; +}; -struct async_req *recvall_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - int fd, void *buffer, size_t length, - int flags) +static void async_recv_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, void *private_data); + +struct tevent_req *async_recv_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int fd, void *buf, size_t len, int flags) { - struct async_req *result; - struct async_syscall_state *state; + struct tevent_req *result; + struct async_recv_state *state; + struct tevent_fd *fde; - result = async_fde_syscall_new( - mem_ctx, ev, ASYNC_SYSCALL_RECVALL, - fd, TEVENT_FD_READ, async_recvall_callback, - &state); + result = tevent_req_create(mem_ctx, &state, struct async_recv_state); if (result == NULL) { - return NULL; + return result; } + state->fd = fd; + state->buf = buf; + state->len = len; + state->flags = flags; - state->param.param_recvall.fd = fd; - state->param.param_recvall.buffer = buffer; - state->param.param_recvall.length = length; - state->param.param_recvall.flags = flags; - state->param.param_recvall.received = 0; - + fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ, async_recv_handler, + result); + if (fde == NULL) { + TALLOC_FREE(result); + return NULL; + } return result; } -ssize_t recvall_recv(struct async_req *req, int *perr) +static void async_recv_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, void *private_data) { - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - int err; + struct tevent_req *req = talloc_get_type_abort( + private_data, struct tevent_req); + struct async_recv_state *state = talloc_get_type_abort( + req->private_state, struct async_recv_state); + + state->received = recv(state->fd, state->buf, state->len, + state->flags); + if (state->received == -1) { + tevent_req_error(req, errno); + return; + } + tevent_req_done(req); +} - err = async_req_simple_recv_errno(req); +ssize_t async_recv_recv(struct tevent_req *req, int *perrno) +{ + struct async_recv_state *state = talloc_get_type_abort( + req->private_state, struct async_recv_state); - if (err != 0) { - *perr = err; + if (tevent_req_is_unix_error(req, perrno)) { return -1; } - - return state->result.result_ssize_t; + return state->received; } struct async_connect_state { @@ -633,17 +536,18 @@ static void async_connect_connected(struct tevent_context *ev, * connect in an async state. This will be reset when the request is finished. */ -struct async_req *async_connect_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - int fd, const struct sockaddr *address, - socklen_t address_len) +struct tevent_req *async_connect_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int fd, const struct sockaddr *address, + socklen_t address_len) { - struct async_req *result; + struct tevent_req *result; struct async_connect_state *state; struct tevent_fd *fde; - if (!async_req_setup(mem_ctx, &result, &state, - struct async_connect_state)) { + result = tevent_req_create( + mem_ctx, &state, struct async_connect_state); + if (result == NULL) { return NULL; } @@ -664,8 +568,8 @@ struct async_req *async_connect_send(TALLOC_CTX *mem_ctx, state->result = connect(fd, address, address_len); if (state->result == 0) { - state->sys_errno = 0; - goto post_status; + errno = 0; + goto post_errno; } /** @@ -686,22 +590,20 @@ struct async_req *async_connect_send(TALLOC_CTX *mem_ctx, fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ | TEVENT_FD_WRITE, async_connect_connected, result); if (fde == NULL) { - state->sys_errno = ENOMEM; - goto post_status; + errno = ENOMEM; + goto post_errno; } return result; post_errno: state->sys_errno = errno; - post_status: fcntl(fd, F_SETFL, state->old_sockflags); - if (!async_post_error(result, ev, state->sys_errno)) { - goto fail; + if (state->sys_errno == 0) { + tevent_req_done(result); + } else { + tevent_req_error(result, state->sys_errno); } - return result; - fail: - TALLOC_FREE(result); - return NULL; + return tevent_req_post(result, ev); } /** @@ -716,10 +618,10 @@ static void async_connect_connected(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, void *priv) { - struct async_req *req = talloc_get_type_abort( - priv, struct async_req); + struct tevent_req *req = talloc_get_type_abort( + priv, struct tevent_req); struct async_connect_state *state = talloc_get_type_abort( - req->private_data, struct async_connect_state); + req->private_state, struct async_connect_state); TALLOC_FREE(fde); @@ -743,27 +645,27 @@ static void async_connect_connected(struct tevent_context *ev, DEBUG(10, ("connect returned %s\n", strerror(errno))); fcntl(state->fd, F_SETFL, state->old_sockflags); - async_req_error(req, state->sys_errno); + tevent_req_error(req, state->sys_errno); return; } state->sys_errno = 0; - async_req_done(req); + tevent_req_done(req); } -int async_connect_recv(struct async_req *req, int *perrno) +int async_connect_recv(struct tevent_req *req, int *perrno) { struct async_connect_state *state = talloc_get_type_abort( - req->private_data, struct async_connect_state); + req->private_state, struct async_connect_state); int err; fcntl(state->fd, F_SETFL, state->old_sockflags); - - if (async_req_is_errno(req, &err)) { + if (tevent_req_is_unix_error(req, &err)) { *perrno = err; return -1; } + if (state->sys_errno == 0) { return 0; } @@ -771,3 +673,226 @@ int async_connect_recv(struct async_req *req, int *perrno) *perrno = state->sys_errno; return -1; } + +struct writev_state { + struct tevent_context *ev; + int fd; + struct iovec *iov; + int count; + size_t total_size; +}; + +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_req *result; + struct writev_state *state; + struct tevent_fd *fde; + + result = tevent_req_create(mem_ctx, &state, struct writev_state); + if (result == NULL) { + return NULL; + } + state->ev = ev; + state->fd = fd; + state->total_size = 0; + state->count = count; + state->iov = (struct iovec *)talloc_memdup( + state, iov, sizeof(struct iovec) * count); + if (state->iov == NULL) { + goto fail; + } + + 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_handler(struct tevent_context *ev, struct tevent_fd *fde, + uint16_t flags, void *private_data) +{ + struct tevent_req *req = talloc_get_type_abort( + private_data, struct tevent_req); + struct writev_state *state = talloc_get_type_abort( + req->private_state, struct writev_state); + size_t to_write, written; + int i; + + to_write = 0; + + for (i=0; i<state->count; i++) { + to_write += state->iov[i].iov_len; + } + + written = sys_writev(state->fd, state->iov, state->count); + if (written == -1) { + tevent_req_error(req, errno); + return; + } + if (written == 0) { + tevent_req_error(req, EPIPE); + return; + } + state->total_size += written; + + if (written == to_write) { + tevent_req_done(req); + return; + } + + /* + * We've written less than we were asked to, drop stuff from + * state->iov. + */ + + while (written > 0) { + if (written < state->iov[0].iov_len) { + state->iov[0].iov_base = + (char *)state->iov[0].iov_base + written; + state->iov[0].iov_len -= written; + break; + } + written = state->iov[0].iov_len; + state->iov += 1; + state->count -= 1; + } +} + +ssize_t writev_recv(struct tevent_req *req, int *perrno) +{ + struct writev_state *state = talloc_get_type_abort( + req->private_state, struct writev_state); + + if (tevent_req_is_unix_error(req, perrno)) { + return -1; + } + return state->total_size; +} + +struct read_packet_state { + int fd; + uint8_t *buf; + size_t nread; + ssize_t (*more)(uint8_t *buf, size_t buflen, void *private_data); + void *private_data; +}; + +static void read_packet_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, void *private_data); + +struct tevent_req *read_packet_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int fd, size_t initial, + ssize_t (*more)(uint8_t *buf, + size_t buflen, + void *private_data), + void *private_data) +{ + struct tevent_req *result; + struct read_packet_state *state; + struct tevent_fd *fde; + + result = tevent_req_create(mem_ctx, &state, struct read_packet_state); + if (result == NULL) { + return NULL; + } + state->fd = fd; + state->nread = 0; + state->more = more; + state->private_data = private_data; + + state->buf = talloc_array(state, uint8_t, initial); + if (state->buf == NULL) { + goto fail; + } + + fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ, read_packet_handler, + result); + if (fde == NULL) { + goto fail; + } + return result; + fail: + TALLOC_FREE(result); + return NULL; +} + +static void read_packet_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, void *private_data) +{ + struct tevent_req *req = talloc_get_type_abort( + private_data, struct tevent_req); + struct read_packet_state *state = talloc_get_type_abort( + req->private_state, struct read_packet_state); + size_t total = talloc_get_size(state->buf); + ssize_t nread, more; + uint8_t *tmp; + + nread = read(state->fd, state->buf+state->nread, total-state->nread); + if (nread == -1) { + tevent_req_error(req, errno); + return; + } + if (nread == 0) { + tevent_req_error(req, EPIPE); + return; + } + + state->nread += nread; + if (state->nread < total) { + /* Come back later */ + return; + } + + /* + * We got what was initially requested. See if "more" asks for -- more. + */ + if (state->more == NULL) { + /* Nobody to ask, this is a async read_data */ + tevent_req_done(req); + return; + } + + more = state->more(state->buf, total, state->private_data); + if (more == -1) { + /* We got an invalid packet, tell the caller */ + tevent_req_error(req, EIO); + return; + } + if (more == 0) { + /* We're done, full packet received */ + tevent_req_done(req); + return; + } + + tmp = TALLOC_REALLOC_ARRAY(state, state->buf, uint8_t, total+more); + if (tevent_req_nomem(tmp, req)) { + return; + } + state->buf = tmp; +} + +ssize_t read_packet_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + uint8_t **pbuf, int *perrno) +{ + struct read_packet_state *state = talloc_get_type_abort( + req->private_state, struct read_packet_state); + + if (tevent_req_is_unix_error(req, perrno)) { + return -1; + } + *pbuf = talloc_move(mem_ctx, &state->buf); + return talloc_get_size(*pbuf); +} diff --git a/lib/async_req/async_sock.h b/lib/async_req/async_sock.h index c8739e9ed6..bfc4346d39 100644 --- a/lib/async_req/async_sock.h +++ b/lib/async_req/async_sock.h @@ -35,20 +35,36 @@ struct async_req *async_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct tevent_context *ev, int fd, void *buffer, size_t length, int flags); -struct async_req *async_connect_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - int fd, const struct sockaddr *address, - socklen_t address_len); -int async_connect_recv(struct async_req *req, int *perrno); - -struct async_req *sendall_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - int fd, const void *buffer, size_t length, - int flags); -ssize_t sendall_recv(struct async_req *req, int *perr); - -struct async_req *recvall_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - int fd, void *buffer, size_t length, - int flags); -ssize_t recvall_recv(struct async_req *req, int *perr); + +struct tevent_req *async_send_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int fd, const void *buf, size_t len, + int flags); +ssize_t async_send_recv(struct tevent_req *req, int *perrno); + +struct tevent_req *async_recv_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int fd, void *buf, size_t len, int flags); +ssize_t async_recv_recv(struct tevent_req *req, int *perrno); + +struct tevent_req *async_connect_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int fd, const struct sockaddr *address, + socklen_t address_len); +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); +ssize_t writev_recv(struct tevent_req *req, int *perrno); + +struct tevent_req *read_packet_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int fd, size_t initial, + ssize_t (*more)(uint8_t *buf, + size_t buflen, + void *private_data), + void *private_data); +ssize_t read_packet_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + uint8_t **pbuf, int *perrno); #endif diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index 16fac7327f..33747f0986 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -31,6 +31,7 @@ #include <stdint.h> #include <talloc.h> #include <sys/time.h> +#include <../lib/replace/replace.h> struct tevent_context; struct tevent_ops; diff --git a/lib/util/tevent_unix.c b/lib/util/tevent_unix.c new file mode 100644 index 0000000000..b89d5cd4d4 --- /dev/null +++ b/lib/util/tevent_unix.c @@ -0,0 +1,46 @@ +/* + Unix SMB/CIFS implementation. + Wrap unix errno around tevent_req + Copyright (C) Volker Lendecke 2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "tevent_unix.h" +#include "../replace/replace.h" + +bool tevent_req_is_unix_error(struct tevent_req *req, int *perrno) +{ + enum tevent_req_state state; + uint64_t err; + + if (!tevent_req_is_error(req, &state, &err)) { + return false; + } + switch (state) { + case TEVENT_REQ_TIMED_OUT: + *perrno = ETIMEDOUT; + break; + case TEVENT_REQ_NO_MEMORY: + *perrno = ENOMEM; + break; + case TEVENT_REQ_USER_ERROR: + *perrno = err; + break; + default: + *perrno = EINVAL; + break; + } + return true; +} diff --git a/lib/util/tevent_unix.h b/lib/util/tevent_unix.h new file mode 100644 index 0000000000..dc3ffaef33 --- /dev/null +++ b/lib/util/tevent_unix.h @@ -0,0 +1,27 @@ +/* + Unix SMB/CIFS implementation. + Wrap unix errno around tevent_req + Copyright (C) Volker Lendecke 2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _TEVENT_UNIX_H +#define _TEVENT_UNIX_H + +#include "../tevent/tevent.h" + +bool tevent_req_is_unix_error(struct tevent_req *req, int *perrno); + +#endif diff --git a/source3/Makefile.in b/source3/Makefile.in index 4cd25c8cee..73b2989421 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -339,7 +339,8 @@ UTIL_OBJ = ../lib/util/rbtree.o ../lib/util/signal.o ../lib/util/time.o \ ../lib/util/util.o ../lib/util/fsusage.o \ ../lib/util/params.o ../lib/util/talloc_stack.o \ ../lib/util/genrand.o ../lib/util/util_net.o \ - ../lib/util/become_daemon.o ../lib/util/system.o + ../lib/util/become_daemon.o ../lib/util/system.o \ + ../lib/util/tevent_unix.o CRYPTO_OBJ = ../lib/crypto/crc32.o ../lib/crypto/md5.o \ ../lib/crypto/hmacmd5.o ../lib/crypto/arcfour.o \ diff --git a/source3/include/proto.h b/source3/include/proto.h index 3ca94b9192..daeef637ca 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1243,15 +1243,6 @@ bool is_valid_policy_hnd(const POLICY_HND *hnd); bool policy_hnd_equal(const struct policy_handle *hnd1, const struct policy_handle *hnd2); const char *strip_hostname(const char *s); -struct async_req *read_pkt_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - int fd, size_t initial, - ssize_t (*more)(uint8_t *buf, size_t buflen, - void *priv), - void *priv); -ssize_t read_pkt_recv(struct async_req *req, TALLOC_CTX *mem_ctx, - uint8_t **pbuf, int *perr); - /* The following definitions come from lib/util_file.c */ @@ -3117,7 +3108,7 @@ struct packet_struct *receive_dgram_packet(int fd, int t, bool match_mailslot_name(struct packet_struct *p, const char *mailslot_name); int matching_len_bits(unsigned char *p1, unsigned char *p2, size_t len); void sort_query_replies(char *data, int n, struct in_addr ip); -int name_mangle( char *In, char *Out, char name_type ); +char *name_mangle(TALLOC_CTX *mem_ctx, char *In, char name_type); int name_extract(char *buf,int ofs, fstring name); int name_len(char *s1); diff --git a/source3/lib/util.c b/source3/lib/util.c index cda1fb474d..89f7be8e6c 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -3145,102 +3145,3 @@ const char *strip_hostname(const char *s) return s; } - -struct read_pkt_state { - struct event_context *ev; - int fd; - uint8_t *buf; - ssize_t (*more)(uint8_t *buf, size_t buflen, void *priv); - void *priv; -}; - -static void read_pkt_done(struct async_req *subreq); - -struct async_req *read_pkt_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - int fd, size_t initial, - ssize_t (*more)(uint8_t *buf, size_t buflen, - void *priv), - void *priv) -{ - struct async_req *result, *subreq; - struct read_pkt_state *state; - - if (!async_req_setup(mem_ctx, &result, &state, - struct read_pkt_state)) { - return NULL; - } - state->ev = ev; - state->fd = fd; - state->more = more; - - state->buf = talloc_array(state, uint8_t, initial); - if (state->buf == NULL) { - goto fail; - } - subreq = recvall_send(state, ev, fd, state->buf, initial, 0); - if (subreq == NULL) { - goto fail; - } - subreq->async.fn = read_pkt_done; - subreq->async.priv = result; - return result; - fail: - TALLOC_FREE(result); - return NULL; -} - -static void read_pkt_done(struct async_req *subreq) -{ - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct read_pkt_state *state = talloc_get_type_abort( - req->private_data, struct read_pkt_state); - size_t current_size; - ssize_t received; - ssize_t more; - int err; - - received = recvall_recv(subreq, &err); - TALLOC_FREE(subreq); - if (received == -1) { - async_req_error(req, err); - return; - } - current_size = talloc_get_size(state->buf); - - more = state->more(state->buf, current_size, state->priv); - if (more < 0) { - async_req_error(req, EIO); - return; - } - if (more == 0) { - async_req_done(req); - return; - } - state->buf = TALLOC_REALLOC_ARRAY(state, state->buf, uint8_t, - current_size + more); - if (async_req_nomem(state->buf, req)) { - return; - } - subreq = recvall_send(state, state->ev, state->fd, - state->buf + current_size, more, 0); - if (async_req_nomem(subreq, req)) { - return; - } - subreq->async.fn = read_pkt_done; - subreq->async.priv = req; -} - -ssize_t read_pkt_recv(struct async_req *req, TALLOC_CTX *mem_ctx, - uint8_t **pbuf, int *perr) -{ - struct read_pkt_state *state = talloc_get_type_abort( - req->private_data, struct read_pkt_state); - - if (async_req_is_errno(req, perr)) { - return -1; - } - *pbuf = talloc_move(mem_ctx, &state->buf); - return talloc_get_size(*pbuf); -} diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index c46aa2ac49..83e8a9d355 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -953,7 +953,7 @@ struct open_socket_out_state { int wait_nsec; }; -static void open_socket_out_connected(struct async_req *subreq); +static void open_socket_out_connected(struct tevent_req *subreq); static int open_socket_out_state_destructor(struct open_socket_out_state *s) { @@ -974,7 +974,8 @@ struct async_req *open_socket_out_send(TALLOC_CTX *mem_ctx, int timeout) { char addr[INET6_ADDRSTRLEN]; - struct async_req *result, *subreq; + struct async_req *result; + struct tevent_req *subreq; struct open_socket_out_state *state; NTSTATUS status; @@ -1026,13 +1027,14 @@ struct async_req *open_socket_out_send(TALLOC_CTX *mem_ctx, (struct sockaddr *)&state->ss, state->salen); if ((subreq == NULL) - || !async_req_set_timeout(subreq, state->ev, - timeval_set(0, state->wait_nsec))) { + || !tevent_req_set_endtime( + subreq, state->ev, + timeval_current_ofs(0, state->wait_nsec))) { status = NT_STATUS_NO_MEMORY; goto post_status; } subreq->async.fn = open_socket_out_connected; - subreq->async.priv = result; + subreq->async.private_data = result; return result; post_status: @@ -1045,18 +1047,18 @@ struct async_req *open_socket_out_send(TALLOC_CTX *mem_ctx, return NULL; } -static void open_socket_out_connected(struct async_req *subreq) +static void open_socket_out_connected(struct tevent_req *subreq) { struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); + subreq->async.private_data, struct async_req); struct open_socket_out_state *state = talloc_get_type_abort( req->private_data, struct open_socket_out_state); - int err; + int ret; int sys_errno; - err = async_connect_recv(subreq, &sys_errno); + ret = async_connect_recv(subreq, &sys_errno); TALLOC_FREE(subreq); - if (err == 0) { + if (ret == 0) { async_req_done(req); return; } @@ -1083,13 +1085,14 @@ static void open_socket_out_connected(struct async_req *subreq) if (async_req_nomem(subreq, req)) { return; } - if (!async_req_set_timeout(subreq, state->ev, - timeval_set(0, state->wait_nsec))) { + if (!tevent_req_set_endtime( + subreq, state->ev, + timeval_current_ofs(0, state->wait_nsec))) { async_req_error(req, ENOMEM); return; } subreq->async.fn = open_socket_out_connected; - subreq->async.priv = req; + subreq->async.private_data = req; return; } diff --git a/source3/lib/wb_reqtrans.c b/source3/lib/wb_reqtrans.c index 9bf6f29105..a5adf8f108 100644 --- a/source3/lib/wb_reqtrans.c +++ b/source3/lib/wb_reqtrans.c @@ -27,9 +27,7 @@ struct req_read_state { struct winbindd_request *wb_req; - struct tevent_context *ev; size_t max_extra_data; - int fd; }; bool async_req_is_wbcerr(struct async_req *req, wbcErr *pwbc_err) @@ -83,145 +81,91 @@ wbcErr async_req_simple_recv_wbcerr(struct async_req *req) return WBC_ERR_SUCCESS; } -static void wb_req_read_len(struct async_req *subreq); -static void wb_req_read_main(struct async_req *subreq); -static void wb_req_read_extra(struct async_req *subreq); +static ssize_t wb_req_more(uint8_t *buf, size_t buflen, void *private_data); +static void wb_req_read_done(struct tevent_req *subreq); struct async_req *wb_req_read_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, int fd, size_t max_extra_data) { - struct async_req *result, *subreq; + struct async_req *result; + struct tevent_req *subreq; struct req_read_state *state; if (!async_req_setup(mem_ctx, &result, &state, struct req_read_state)) { return NULL; } - state->fd = fd; - state->ev = ev; state->max_extra_data = max_extra_data; - state->wb_req = talloc(state, struct winbindd_request); - if (state->wb_req == NULL) { - goto nomem; - } - subreq = recvall_send(state, ev, state->fd, &(state->wb_req->length), - sizeof(state->wb_req->length), 0); + subreq = read_packet_send(state, ev, fd, 4, wb_req_more, state); if (subreq == NULL) { goto nomem; } - subreq->async.fn = wb_req_read_len; - subreq->async.priv = result; + subreq->async.fn = wb_req_read_done; + subreq->async.private_data = result; return result; - nomem: TALLOC_FREE(result); return NULL; } -static void wb_req_read_len(struct async_req *subreq) +static ssize_t wb_req_more(uint8_t *buf, size_t buflen, void *private_data) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); struct req_read_state *state = talloc_get_type_abort( - req->private_data, struct req_read_state); - int err; - ssize_t ret; - - ret = recvall_recv(subreq, &err); - TALLOC_FREE(subreq); - if (ret < 0) { - async_req_error(req, map_wbc_err_from_errno(err)); - return; - } + private_data, struct req_read_state); + struct winbindd_request *req = (struct winbindd_request *)buf; - if (state->wb_req->length != sizeof(struct winbindd_request)) { - DEBUG(0, ("wb_req_read_len: Invalid request size received: " - "%d (expected %d)\n", (int)state->wb_req->length, - (int)sizeof(struct winbindd_request))); - async_req_error(req, WBC_ERR_INVALID_RESPONSE); - return; + if (buflen == 4) { + if (req->length != sizeof(struct winbindd_request)) { + DEBUG(0, ("wb_req_read_len: Invalid request size " + "received: %d (expected %d)\n", + (int)req->length, + (int)sizeof(struct winbindd_request))); + return -1; + } + return sizeof(struct winbindd_request) - 4; } - subreq = recvall_send( - req, state->ev, state->fd, (uint32 *)(state->wb_req)+1, - sizeof(struct winbindd_request) - sizeof(uint32), 0); - if (async_req_nomem(subreq, req)) { - return; + if ((state->max_extra_data != 0) + && (req->extra_len > state->max_extra_data)) { + DEBUG(3, ("Got request with %d bytes extra data on " + "unprivileged socket\n", (int)req->extra_len)); + return -1; } - subreq->async.fn = wb_req_read_main; - subreq->async.priv = req; + return req->extra_len; } -static void wb_req_read_main(struct async_req *subreq) +static void wb_req_read_done(struct tevent_req *subreq) { struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); + subreq->async.private_data, struct async_req); struct req_read_state *state = talloc_get_type_abort( req->private_data, struct req_read_state); int err; ssize_t ret; + uint8_t *buf; - ret = recvall_recv(subreq, &err); + ret = read_packet_recv(subreq, state, &buf, &err); TALLOC_FREE(subreq); - if (ret < 0) { + if (ret == -1) { async_req_error(req, map_wbc_err_from_errno(err)); return; } - if ((state->max_extra_data != 0) - && (state->wb_req->extra_len > state->max_extra_data)) { - DEBUG(3, ("Got request with %d bytes extra data on " - "unprivileged socket\n", - (int)state->wb_req->extra_len)); - async_req_error(req, WBC_ERR_INVALID_RESPONSE); - return; - } - - if (state->wb_req->extra_len == 0) { - async_req_done(req); - return; - } - - state->wb_req->extra_data.data = TALLOC_ARRAY( - state->wb_req, char, state->wb_req->extra_len + 1); - if (async_req_nomem(state->wb_req->extra_data.data, req)) { - return; - } - - state->wb_req->extra_data.data[state->wb_req->extra_len] = 0; - - subreq = recvall_send( - req, state->ev, state->fd, state->wb_req->extra_data.data, - state->wb_req->extra_len, 0); - if (async_req_nomem(subreq, req)) { - return; - } - - subreq->async.fn = wb_req_read_extra; - subreq->async.priv = req; -} - -static void wb_req_read_extra(struct async_req *subreq) -{ - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - int err; - ssize_t ret; + state->wb_req = (struct winbindd_request *)buf; - ret = recvall_recv(subreq, &err); - TALLOC_FREE(subreq); - if (ret < 0) { - async_req_error(req, map_wbc_err_from_errno(err)); - return; + if (state->wb_req->extra_len != 0) { + state->wb_req->extra_data.data = + (char *)buf + sizeof(struct winbindd_request); + } else { + state->wb_req->extra_data.data = NULL; } async_req_done(req); } - wbcErr wb_req_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx, struct winbindd_request **preq) { @@ -237,90 +181,60 @@ wbcErr wb_req_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx, } struct req_write_state { - struct winbindd_request *wb_req; - struct tevent_context *ev; - int fd; + struct iovec iov[2]; }; -static void wb_req_write_main(struct async_req *subreq); -static void wb_req_write_extra(struct async_req *subreq); +static void wb_req_write_done(struct tevent_req *subreq); struct async_req *wb_req_write_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, int fd, struct winbindd_request *wb_req) { - struct async_req *result, *subreq; + struct async_req *result; + struct tevent_req *subreq; struct req_write_state *state; + int count = 1; if (!async_req_setup(mem_ctx, &result, &state, struct req_write_state)) { return NULL; } - state->fd = fd; - state->ev = ev; - state->wb_req = wb_req; - subreq = sendall_send(state, state->ev, state->fd, state->wb_req, - sizeof(struct winbindd_request), 0); - if (subreq == NULL) { - goto nomem; + state->iov[0].iov_base = wb_req; + state->iov[0].iov_len = sizeof(struct winbindd_request); + + if (wb_req->extra_len != 0) { + state->iov[1].iov_base = wb_req->extra_data.data; + state->iov[1].iov_len = wb_req->extra_len; + count = 2; } - subreq->async.fn = wb_req_write_main; - subreq->async.priv = result; + subreq = writev_send(state, ev, fd, state->iov, count); + if (subreq == NULL) { + goto fail; + } + subreq->async.fn = wb_req_write_done; + subreq->async.private_data = result; return result; - nomem: + fail: TALLOC_FREE(result); return NULL; } -static void wb_req_write_main(struct async_req *subreq) -{ - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct req_write_state *state = talloc_get_type_abort( - req->private_data, struct req_write_state); - int err; - ssize_t ret; - - ret = sendall_recv(subreq, &err); - TALLOC_FREE(subreq); - if (ret < 0) { - async_req_error(req, map_wbc_err_from_errno(err)); - return; - } - - if (state->wb_req->extra_len == 0) { - async_req_done(req); - return; - } - - subreq = sendall_send(state, state->ev, state->fd, - state->wb_req->extra_data.data, - state->wb_req->extra_len, 0); - if (async_req_nomem(subreq, req)) { - return; - } - - subreq->async.fn = wb_req_write_extra; - subreq->async.priv = req; -} - -static void wb_req_write_extra(struct async_req *subreq) +static void wb_req_write_done(struct tevent_req *subreq) { struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); + subreq->async.private_data, struct async_req); int err; ssize_t ret; - ret = sendall_recv(subreq, &err); + ret = writev_recv(subreq, &err); TALLOC_FREE(subreq); if (ret < 0) { async_req_error(req, map_wbc_err_from_errno(err)); return; } - async_req_done(req); } @@ -331,40 +245,29 @@ wbcErr wb_req_write_recv(struct async_req *req) struct resp_read_state { struct winbindd_response *wb_resp; - struct tevent_context *ev; - size_t max_extra_data; - int fd; }; -static void wb_resp_read_len(struct async_req *subreq); -static void wb_resp_read_main(struct async_req *subreq); -static void wb_resp_read_extra(struct async_req *subreq); +static ssize_t wb_resp_more(uint8_t *buf, size_t buflen, void *private_data); +static void wb_resp_read_done(struct tevent_req *subreq); struct async_req *wb_resp_read_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, int fd) { - struct async_req *result, *subreq; + struct async_req *result; + struct tevent_req *subreq; struct resp_read_state *state; if (!async_req_setup(mem_ctx, &result, &state, struct resp_read_state)) { return NULL; } - state->fd = fd; - state->ev = ev; - state->wb_resp = talloc(state, struct winbindd_response); - if (state->wb_resp == NULL) { - goto nomem; - } - subreq = recvall_send(state, ev, state->fd, &(state->wb_resp->length), - sizeof(state->wb_resp->length), 0); + subreq = read_packet_send(state, ev, fd, 4, wb_resp_more, state); if (subreq == NULL) { goto nomem; } - - subreq->async.fn = wb_resp_read_len; - subreq->async.priv = result; + subreq->async.fn = wb_resp_read_done; + subreq->async.private_data = result; return result; nomem: @@ -372,100 +275,50 @@ struct async_req *wb_resp_read_send(TALLOC_CTX *mem_ctx, return NULL; } -static void wb_resp_read_len(struct async_req *subreq) +static ssize_t wb_resp_more(uint8_t *buf, size_t buflen, void *private_data) { - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct resp_read_state *state = talloc_get_type_abort( - req->private_data, struct resp_read_state); - int err; - ssize_t ret; - - ret = recvall_recv(subreq, &err); - TALLOC_FREE(subreq); - if (ret < 0) { - async_req_error(req, map_wbc_err_from_errno(err)); - return; - } - - if (state->wb_resp->length < sizeof(struct winbindd_response)) { - DEBUG(0, ("wb_resp_read_len: Invalid response size received: " - "%d (expected at least%d)\n", - (int)state->wb_resp->length, - (int)sizeof(struct winbindd_response))); - async_req_error(req, WBC_ERR_INVALID_RESPONSE); - return; - } - - subreq = recvall_send( - req, state->ev, state->fd, (uint32 *)(state->wb_resp)+1, - sizeof(struct winbindd_response) - sizeof(uint32), 0); - if (async_req_nomem(subreq, req)) { - return; - } - - subreq->async.fn = wb_resp_read_main; - subreq->async.priv = req; + struct winbindd_response *resp = (struct winbindd_response *)buf; + + if (buflen == 4) { + if (resp->length < sizeof(struct winbindd_response)) { + DEBUG(0, ("wb_resp_read_len: Invalid response size " + "received: %d (expected at least%d)\n", + (int)resp->length, + (int)sizeof(struct winbindd_response))); + return -1; + } + } + return resp->length - 4; } -static void wb_resp_read_main(struct async_req *subreq) +static void wb_resp_read_done(struct tevent_req *subreq) { struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); + subreq->async.private_data, struct async_req); struct resp_read_state *state = talloc_get_type_abort( req->private_data, struct resp_read_state); + uint8_t *buf; int err; ssize_t ret; - size_t extra_len; - ret = recvall_recv(subreq, &err); + ret = read_packet_recv(subreq, state, &buf, &err); TALLOC_FREE(subreq); - if (ret < 0) { + if (ret == -1) { async_req_error(req, map_wbc_err_from_errno(err)); return; } - extra_len = state->wb_resp->length - sizeof(struct winbindd_response); - if (extra_len == 0) { - async_req_done(req); - return; - } - - state->wb_resp->extra_data.data = TALLOC_ARRAY( - state->wb_resp, char, extra_len+1); - if (async_req_nomem(state->wb_resp->extra_data.data, req)) { - return; - } - ((char *)state->wb_resp->extra_data.data)[extra_len] = 0; - - subreq = recvall_send( - req, state->ev, state->fd, state->wb_resp->extra_data.data, - extra_len, 0); - if (async_req_nomem(subreq, req)) { - return; - } - - subreq->async.fn = wb_resp_read_extra; - subreq->async.priv = req; -} - -static void wb_resp_read_extra(struct async_req *subreq) -{ - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - int err; - ssize_t ret; + state->wb_resp = (struct winbindd_response *)buf; - ret = recvall_recv(subreq, &err); - TALLOC_FREE(subreq); - if (ret < 0) { - async_req_error(req, map_wbc_err_from_errno(err)); - return; + if (state->wb_resp->length > sizeof(struct winbindd_response)) { + state->wb_resp->extra_data.data = + (char *)buf + sizeof(struct winbindd_response); + } else { + state->wb_resp->extra_data.data = NULL; } async_req_done(req); } - wbcErr wb_resp_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx, struct winbindd_response **presp) { @@ -481,91 +334,61 @@ wbcErr wb_resp_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx, } struct resp_write_state { - struct winbindd_response *wb_resp; - struct tevent_context *ev; - int fd; + struct iovec iov[2]; }; -static void wb_resp_write_main(struct async_req *subreq); -static void wb_resp_write_extra(struct async_req *subreq); +static void wb_resp_write_done(struct tevent_req *subreq); struct async_req *wb_resp_write_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, int fd, struct winbindd_response *wb_resp) { - struct async_req *result, *subreq; + struct async_req *result; + struct tevent_req *subreq; struct resp_write_state *state; + int count = 1; if (!async_req_setup(mem_ctx, &result, &state, struct resp_write_state)) { return NULL; } - state->fd = fd; - state->ev = ev; - state->wb_resp = wb_resp; - subreq = sendall_send(state, state->ev, state->fd, state->wb_resp, - sizeof(struct winbindd_response), 0); - if (subreq == NULL) { - goto nomem; + state->iov[0].iov_base = wb_resp; + state->iov[0].iov_len = sizeof(struct winbindd_response); + + if (wb_resp->length > sizeof(struct winbindd_response)) { + state->iov[1].iov_base = wb_resp->extra_data.data; + state->iov[1].iov_len = + wb_resp->length - sizeof(struct winbindd_response); + count = 2; } - subreq->async.fn = wb_resp_write_main; - subreq->async.priv = result; + subreq = writev_send(state, ev, fd, state->iov, count); + if (subreq == NULL) { + goto fail; + } + subreq->async.fn = wb_resp_write_done; + subreq->async.private_data = result; return result; - nomem: + fail: TALLOC_FREE(result); return NULL; } -static void wb_resp_write_main(struct async_req *subreq) +static void wb_resp_write_done(struct tevent_req *subreq) { struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct resp_write_state *state = talloc_get_type_abort( - req->private_data, struct resp_write_state); + subreq->async.private_data, struct async_req); int err; ssize_t ret; - ret = sendall_recv(subreq, &err); + ret = writev_recv(subreq, &err); TALLOC_FREE(subreq); if (ret < 0) { async_req_error(req, map_wbc_err_from_errno(err)); return; } - - if (state->wb_resp->length == sizeof(struct winbindd_response)) { - async_req_done(req); - return; - } - - subreq = sendall_send( - state, state->ev, state->fd, - state->wb_resp->extra_data.data, - state->wb_resp->length - sizeof(struct winbindd_response), 0); - if (async_req_nomem(subreq, req)) { - return; - } - - subreq->async.fn = wb_resp_write_extra; - subreq->async.priv = req; -} - -static void wb_resp_write_extra(struct async_req *subreq) -{ - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - int err; - ssize_t ret; - - ret = sendall_recv(subreq, &err); - TALLOC_FREE(subreq); - if (err < 0) { - async_req_error(req, map_wbc_err_from_errno(err)); - return; - } - async_req_done(req); } diff --git a/source3/lib/wbclient.c b/source3/lib/wbclient.c index 4d3a609530..b8d55a944a 100644 --- a/source3/lib/wbclient.c +++ b/source3/lib/wbclient.c @@ -147,17 +147,30 @@ struct wb_context *wb_context_init(TALLOC_CTX *mem_ctx) return result; } +struct wb_connect_state { + int dummy; +}; + +static void wbc_connect_connected(struct tevent_req *subreq); + static struct async_req *wb_connect_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct wb_context *wb_ctx, - const char *dir) + struct tevent_context *ev, + struct wb_context *wb_ctx, + const char *dir) { - struct async_req *req; + struct async_req *result; + struct tevent_req *subreq; + struct wb_connect_state *state; struct sockaddr_un sunaddr; struct stat st; char *path = NULL; wbcErr wbc_err; + if (!async_req_setup(mem_ctx, &result, &state, + struct wb_connect_state)) { + return NULL; + } + if (wb_ctx->fd != -1) { close(wb_ctx->fd); wb_ctx->fd = -1; @@ -205,33 +218,46 @@ static struct async_req *wb_connect_send(TALLOC_CTX *mem_ctx, goto post_status; } - req = async_connect_send(mem_ctx, ev, wb_ctx->fd, - (struct sockaddr *)&sunaddr, - sizeof(sunaddr)); - if (req == NULL) { + subreq = async_connect_send(mem_ctx, ev, wb_ctx->fd, + (struct sockaddr *)&sunaddr, + sizeof(sunaddr)); + if (subreq == NULL) { goto nomem; } - if (!async_req_set_timeout(req, ev, timeval_set(30, 0))) { - TALLOC_FREE(req); + subreq->async.fn = wbc_connect_connected; + subreq->async.private_data = result; + + if (!tevent_req_set_endtime(subreq, ev, timeval_current_ofs(30, 0))) { goto nomem; } - return req; + return result; nomem: wbc_err = WBC_ERR_NO_MEMORY; post_status: - req = async_req_new(mem_ctx); - if (req == NULL) { - return NULL; - } - if (async_post_error(req, ev, wbc_err)) { - return req; + if (async_post_error(result, ev, wbc_err)) { + return result; } - TALLOC_FREE(req); + TALLOC_FREE(result); return NULL; } +static void wbc_connect_connected(struct tevent_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.private_data, struct async_req); + int res, err; + + res = async_connect_recv(subreq, &err); + TALLOC_FREE(subreq); + if (res == -1) { + async_req_error(req, map_wbc_err_from_errno(err)); + return; + } + async_req_done(req); +} + static wbcErr wb_connect_recv(struct async_req *req) { return async_req_simple_recv_wbcerr(req); diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index dabfc398ce..ad11ee0ed4 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -1642,6 +1642,7 @@ bool cli_session_request(struct cli_state *cli, { char *p; int len = 4; + char *tmp; /* 445 doesn't have session request */ if (cli->port == 445) @@ -1651,14 +1652,30 @@ bool cli_session_request(struct cli_state *cli, memcpy(&(cli->called ), called , sizeof(*called )); /* put in the destination name */ + + tmp = name_mangle(talloc_tos(), cli->called.name, + cli->called.name_type); + if (tmp == NULL) { + return false; + } + p = cli->outbuf+len; - name_mangle(cli->called .name, p, cli->called .name_type); - len += name_len(p); + memcpy(p, tmp, name_len(tmp)); + len += name_len(tmp); + TALLOC_FREE(tmp); /* and my name */ + + tmp = name_mangle(talloc_tos(), cli->calling.name, + cli->calling.name_type); + if (tmp == NULL) { + return false; + } + p = cli->outbuf+len; - name_mangle(cli->calling.name, p, cli->calling.name_type); - len += name_len(p); + memcpy(p, tmp, name_len(tmp)); + len += name_len(tmp); + TALLOC_FREE(tmp); /* send a session request (RFC 1002) */ /* setup the packet length diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c index 02b13ae63e..5f3eda44fe 100644 --- a/source3/libsmb/nmblib.c +++ b/source3/libsmb/nmblib.c @@ -1279,12 +1279,19 @@ static int name_interpret(char *in, fstring name) Note: <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum. ****************************************************************************/ -int name_mangle( char *In, char *Out, char name_type ) +char *name_mangle(TALLOC_CTX *mem_ctx, char *In, char name_type) { int i; int len; nstring buf; - char *p = Out; + char *result; + char *p; + + result = talloc_array(mem_ctx, char, 33 + strlen(global_scope()) + 2); + if (result == NULL) { + return NULL; + } + p = result; /* Safely copy the input string, In, into buf[]. */ if (strcmp(In,"*") == 0) @@ -1321,7 +1328,7 @@ int name_mangle( char *In, char *Out, char name_type ) p[0] = len; if( len > 0 ) p[len+1] = 0; - return( name_len(Out) ); + return result; case '.': p[0] = len; p += (len + 1); @@ -1333,7 +1340,7 @@ int name_mangle( char *In, char *Out, char name_type ) } } - return( name_len(Out) ); + return result; } /**************************************************************************** diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index 6dead2d264..33e89c8acb 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -1171,13 +1171,12 @@ NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name, struct np_write_state { struct event_context *ev; struct np_proxy_state *p; - const uint8_t *data; - size_t len; + struct iovec iov; ssize_t nwritten; }; static void np_write_trigger(struct async_req *req); -static void np_write_done(struct async_req *subreq); +static void np_write_done(struct tevent_req *subreq); struct async_req *np_write_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct fake_file_handle *handle, @@ -1218,8 +1217,8 @@ struct async_req *np_write_send(TALLOC_CTX *mem_ctx, struct event_context *ev, state->ev = ev; state->p = p; - state->data = data; - state->len = len; + state->iov.iov_base = CONST_DISCARD(void *, data); + state->iov.iov_len = len; if (!async_req_enqueue(p->write_queue, ev, result, np_write_trigger)) { @@ -1242,27 +1241,26 @@ static void np_write_trigger(struct async_req *req) { struct np_write_state *state = talloc_get_type_abort( req->private_data, struct np_write_state); - struct async_req *subreq; + struct tevent_req *subreq; - subreq = sendall_send(state, state->ev, state->p->fd, state->data, - state->len, 0); + subreq = writev_send(state, state->ev, state->p->fd, &state->iov, 1); if (async_req_nomem(subreq, req)) { return; } subreq->async.fn = np_write_done; - subreq->async.priv = req; + subreq->async.private_data = req; } -static void np_write_done(struct async_req *subreq) +static void np_write_done(struct tevent_req *subreq) { struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); + subreq->async.private_data, struct async_req); struct np_write_state *state = talloc_get_type_abort( req->private_data, struct np_write_state); ssize_t received; int err; - received = sendall_recv(subreq, &err); + received = writev_recv(subreq, &err); if (received < 0) { async_req_nterror(req, map_nt_error_from_unix(err)); return; @@ -1316,7 +1314,7 @@ struct np_read_state { }; static void np_read_trigger(struct async_req *req); -static void np_read_done(struct async_req *subreq); +static void np_read_done(struct tevent_req *subreq); struct async_req *np_read_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct fake_file_handle *handle, @@ -1393,28 +1391,28 @@ static void np_read_trigger(struct async_req *req) { struct np_read_state *state = talloc_get_type_abort( req->private_data, struct np_read_state); - struct async_req *subreq; + struct tevent_req *subreq; - subreq = read_pkt_send(state, state->ev, state->p->fd, RPC_HEADER_LEN, - rpc_frag_more_fn, NULL); + subreq = read_packet_send(state, state->ev, state->p->fd, + RPC_HEADER_LEN, rpc_frag_more_fn, NULL); if (async_req_nomem(subreq, req)) { return; } subreq->async.fn = np_read_done; - subreq->async.priv = req; + subreq->async.private_data = req; } -static void np_read_done(struct async_req *subreq) +static void np_read_done(struct tevent_req *subreq) { struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); + subreq->async.private_data, struct async_req); struct np_read_state *state = talloc_get_type_abort( req->private_data, struct np_read_state); ssize_t received; size_t thistime; int err; - received = read_pkt_recv(subreq, state->p, &state->p->msg, &err); + received = read_packet_recv(subreq, state->p, &state->p->msg, &err); TALLOC_FREE(subreq); if (received == -1) { async_req_nterror(req, map_nt_error_from_unix(err)); diff --git a/source3/utils/smbfilter.c b/source3/utils/smbfilter.c index 1fdea818d6..39a264011e 100644 --- a/source3/utils/smbfilter.c +++ b/source3/utils/smbfilter.c @@ -91,8 +91,15 @@ static void filter_request(char *buf) d_printf("sesion_request: %s -> %s\n", name1, name2); if (netbiosname) { - /* replace the destination netbios name */ - name_mangle(netbiosname, buf+4, 0x20); + char *mangled = name_mangle( + talloc_tos(), netbiosname, 0x20); + if (mangled != NULL) { + /* replace the destination netbios + * name */ + memcpy(buf+4, mangled, + name_len(mangled)); + TALLOC_FREE(mangled); + } } } return; diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 0fa638e863..f1c063ed90 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -47,7 +47,8 @@ struct server_pipe_state { static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct netr_ServerReqChallenge *r) { - struct server_pipe_state *pipe_state = dce_call->context->private_data; + struct server_pipe_state *pipe_state = + (struct server_pipe_state *)dce_call->context->private_data; ZERO_STRUCTP(r->out.return_credentials); @@ -76,7 +77,8 @@ static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_cal static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct netr_ServerAuthenticate3 *r) { - struct server_pipe_state *pipe_state = dce_call->context->private_data; + struct server_pipe_state *pipe_state = + (struct server_pipe_state *)dce_call->context->private_data; struct creds_CredentialState *creds; void *sam_ctx; struct samr_Password *mach_pwd; @@ -148,7 +150,9 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca } /* pull the user attributes */ - num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, trust_dom_attrs, + num_records = gendb_search((struct ldb_context *)sam_ctx, + mem_ctx, NULL, &msgs, + trust_dom_attrs, "(&(trustPartner=%s)(objectclass=trustedDomain))", encoded_account); @@ -179,7 +183,8 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca } /* pull the user attributes */ - num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs, + num_records = gendb_search((struct ldb_context *)sam_ctx, mem_ctx, + NULL, &msgs, attrs, "(&(sAMAccountName=%s)(objectclass=user))", ldb_binary_encode_string(mem_ctx, account_name)); @@ -848,13 +853,14 @@ static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_C return WERR_DS_SERVICE_UNAVAILABLE; } - domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx, + domain_dn = samdb_domain_to_dn((struct ldb_context *)sam_ctx, mem_ctx, r->in.domainname); if (domain_dn == NULL) { return WERR_DS_SERVICE_UNAVAILABLE; } - ret = gendb_search_dn(sam_ctx, mem_ctx, domain_dn, &res, attrs); + ret = gendb_search_dn((struct ldb_context *)sam_ctx, mem_ctx, + domain_dn, &res, attrs); if (ret != 1) { return WERR_NO_SUCH_DOMAIN; } @@ -1218,13 +1224,15 @@ static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call, TA r->in.domain_name = lp_realm(dce_call->conn->dce_ctx->lp_ctx); } - domain_dn = samdb_dns_domain_to_dn(sam_ctx, mem_ctx, + domain_dn = samdb_dns_domain_to_dn((struct ldb_context *)sam_ctx, + mem_ctx, r->in.domain_name); if (domain_dn == NULL) { return WERR_DS_SERVICE_UNAVAILABLE; } - ret = gendb_search_dn(sam_ctx, mem_ctx, domain_dn, &res, attrs); + ret = gendb_search_dn((struct ldb_context *)sam_ctx, mem_ctx, + domain_dn, &res, attrs); if (ret != 1) { return WERR_NO_SUCH_DOMAIN; } @@ -1377,9 +1385,11 @@ static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce return WERR_GENERAL_FAILURE; } - partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx); + partitions_basedn = samdb_partitions_dn((struct ldb_context *)sam_ctx, + mem_ctx); - ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs); + ret = gendb_search_dn((struct ldb_context *)sam_ctx, mem_ctx, NULL, + &dom_res, dom_attrs); if (ret == -1) { return WERR_GENERAL_FAILURE; } @@ -1387,7 +1397,8 @@ static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce return WERR_GENERAL_FAILURE; } - ret = gendb_search(sam_ctx, mem_ctx, partitions_basedn, &ref_res, ref_attrs, + ret = gendb_search((struct ldb_context *)sam_ctx, mem_ctx, + partitions_basedn, &ref_res, ref_attrs, "(&(objectClass=crossRef)(ncName=%s))", ldb_dn_get_linearized(dom_res[0]->dn)); if (ret == -1) { |