diff options
Diffstat (limited to 'lib')
28 files changed, 1284 insertions, 759 deletions
diff --git a/lib/async_req/async_sock.c b/lib/async_req/async_sock.c index 3563421e0e..424da952eb 100644 --- a/lib/async_req/async_sock.c +++ b/lib/async_req/async_sock.c @@ -30,45 +30,6 @@ #endif /** - * Discriminator for async_syscall_state - */ -enum async_syscall_type { - ASYNC_SYSCALL_SEND, - ASYNC_SYSCALL_RECV, -}; - -/** - * Holder for syscall arguments and the result - */ - -struct async_syscall_state { - enum async_syscall_type syscall_type; - struct tevent_fd *fde; - - union { - struct param_send { - int fd; - const void *buffer; - size_t length; - int flags; - } param_send; - struct param_recv { - int fd; - void *buffer; - size_t length; - int flags; - } param_recv; - } param; - - union { - ssize_t result_ssize_t; - size_t result_size_t; - int result_int; - } result; - int sys_errno; -}; - -/** * @brief Map async_req states to unix-style errnos * @param[in] req The async req to get the state from * @param[out] err Pointer to take the unix-style errno @@ -117,267 +78,6 @@ int async_req_simple_recv_errno(struct async_req *req) return 0; } -/** - * @brief Create a new async syscall req - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] type Which syscall will this be - * @param[in] pstate Where to put the newly created private_data state - * @retval The new request - * - * This is a helper function to prepare a new struct async_req with an - * associated struct async_syscall_state. The async_syscall_state will be put - * into the async_req as private_data. - */ - -static struct async_req *async_syscall_new(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - enum async_syscall_type type, - struct async_syscall_state **pstate) -{ - struct async_req *result; - struct async_syscall_state *state; - - if (!async_req_setup(mem_ctx, &result, &state, - struct async_syscall_state)) { - return NULL; - } - state->syscall_type = type; - - result->private_data = state; - - *pstate = state; - - return result; -} - -/** - * @brief Create a new async syscall req based on a fd - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] type Which syscall will this be - * @param[in] fd The file descriptor we work on - * @param[in] fde_flags TEVENT_FD_READ/WRITE -- what are we interested in? - * @param[in] fde_cb The callback function for the file descriptor event - * @param[in] pstate Where to put the newly created private_data state - * @retval The new request - * - * This is a helper function to prepare a new struct async_req with an - * associated struct async_syscall_state and an associated file descriptor - * event. - */ - -static struct async_req *async_fde_syscall_new( - TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - enum async_syscall_type type, - int fd, - uint16_t fde_flags, - void (*fde_cb)(struct tevent_context *ev, - struct tevent_fd *fde, uint16_t flags, - void *priv), - struct async_syscall_state **pstate) -{ - struct async_req *result; - struct async_syscall_state *state; - - result = async_syscall_new(mem_ctx, ev, type, &state); - if (result == NULL) { - return NULL; - } - - state->fde = tevent_add_fd(ev, state, fd, fde_flags, fde_cb, result); - if (state->fde == NULL) { - TALLOC_FREE(result); - return NULL; - } - *pstate = state; - return result; -} - -/** - * Retrieve a ssize_t typed result from an async syscall - * @param[in] req The syscall that has just finished - * @param[out] perrno Where to put the syscall's errno - * @retval The return value from the asynchronously called syscall - */ - -ssize_t async_syscall_result_ssize_t(struct async_req *req, int *perrno) -{ - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - - *perrno = state->sys_errno; - return state->result.result_ssize_t; -} - -/** - * Retrieve a size_t typed result from an async syscall - * @param[in] req The syscall that has just finished - * @param[out] perrno Where to put the syscall's errno - * @retval The return value from the asynchronously called syscall - */ - -size_t async_syscall_result_size_t(struct async_req *req, int *perrno) -{ - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - - *perrno = state->sys_errno; - return state->result.result_size_t; -} - -/** - * Retrieve a int typed result from an async syscall - * @param[in] req The syscall that has just finished - * @param[out] perrno Where to put the syscall's errno - * @retval The return value from the asynchronously called syscall - */ - -int async_syscall_result_int(struct async_req *req, int *perrno) -{ - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - - *perrno = state->sys_errno; - return state->result.result_int; -} - -/** - * fde event handler for the "send" syscall - * @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_send_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_send *p = &state->param.param_send; - - if (state->syscall_type != ASYNC_SYSCALL_SEND) { - async_req_error(req, EIO); - return; - } - - state->result.result_ssize_t = send(p->fd, p->buffer, p->length, - p->flags); - state->sys_errno = errno; - - TALLOC_FREE(state->fde); - - async_req_done(req); -} - -/** - * Async version of send(2) - * @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) - * - * This function is a direct counterpart of send(2) - */ - -struct async_req *async_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_SEND, - fd, TEVENT_FD_WRITE, async_send_callback, - &state); - if (result == NULL) { - return NULL; - } - - state->param.param_send.fd = fd; - state->param.param_send.buffer = buffer; - state->param.param_send.length = length; - state->param.param_send.flags = flags; - - return result; -} - -/** - * 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 - * @param[in] flags Can only be TEVENT_FD_READ here - * @param[in] priv private data, "struct async_req *" in this case - */ - -static void async_recv_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_recv *p = &state->param.param_recv; - - if (state->syscall_type != ASYNC_SYSCALL_RECV) { - async_req_error(req, EIO); - return; - } - - state->result.result_ssize_t = recv(p->fd, p->buffer, p->length, - p->flags); - state->sys_errno = errno; - - TALLOC_FREE(state->fde); - - async_req_done(req); -} - -/** - * Async version of recv(2) - * @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) - * - * This function is a direct counterpart of recv(2) - */ - -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 *result; - struct async_syscall_state *state; - - result = async_fde_syscall_new( - mem_ctx, ev, ASYNC_SYSCALL_RECV, - fd, TEVENT_FD_READ, async_recv_callback, - &state); - - if (result == NULL) { - return NULL; - } - - state->param.param_recv.fd = fd; - state->param.param_recv.buffer = buffer; - state->param.param_recv.length = length; - state->param.param_recv.flags = flags; - - return result; -} - struct async_send_state { int fd; const void *buf; @@ -423,8 +123,8 @@ static void async_send_handler(struct tevent_context *ev, { 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); + struct async_send_state *state = + tevent_req_data(req, struct async_send_state); state->sent = send(state->fd, state->buf, state->len, state->flags); if (state->sent == -1) { @@ -436,8 +136,8 @@ static void async_send_handler(struct tevent_context *ev, 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); + struct async_send_state *state = + tevent_req_data(req, struct async_send_state); if (tevent_req_is_unix_error(req, perrno)) { return -1; @@ -489,8 +189,8 @@ static void async_recv_handler(struct tevent_context *ev, { 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); + struct async_recv_state *state = + tevent_req_data(req, struct async_recv_state); state->received = recv(state->fd, state->buf, state->len, state->flags); @@ -503,8 +203,8 @@ static void async_recv_handler(struct tevent_context *ev, 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); + struct async_recv_state *state = + tevent_req_data(req, struct async_recv_state); if (tevent_req_is_unix_error(req, perrno)) { return -1; @@ -568,8 +268,8 @@ struct tevent_req *async_connect_send(TALLOC_CTX *mem_ctx, state->result = connect(fd, address, address_len); if (state->result == 0) { - errno = 0; - goto post_errno; + tevent_req_done(result); + goto done; } /** @@ -584,25 +284,22 @@ struct tevent_req *async_connect_send(TALLOC_CTX *mem_ctx, errno == EISCONN || #endif errno == EAGAIN || errno == EINTR)) { + state->sys_errno = errno; goto post_errno; } fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ | TEVENT_FD_WRITE, async_connect_connected, result); if (fde == NULL) { - errno = ENOMEM; + state->sys_errno = ENOMEM; goto post_errno; } return result; post_errno: - state->sys_errno = errno; + tevent_req_error(result, state->sys_errno); + done: fcntl(fd, F_SETFL, state->old_sockflags); - if (state->sys_errno == 0) { - tevent_req_done(result); - } else { - tevent_req_error(result, state->sys_errno); - } return tevent_req_post(result, ev); } @@ -620,8 +317,8 @@ static void async_connect_connected(struct tevent_context *ev, { struct tevent_req *req = talloc_get_type_abort( priv, struct tevent_req); - struct async_connect_state *state = talloc_get_type_abort( - req->private_state, struct async_connect_state); + struct async_connect_state *state = + tevent_req_data(req, struct async_connect_state); TALLOC_FREE(fde); @@ -655,8 +352,8 @@ static void async_connect_connected(struct tevent_context *ev, int async_connect_recv(struct tevent_req *req, int *perrno) { - struct async_connect_state *state = talloc_get_type_abort( - req->private_state, struct async_connect_state); + struct async_connect_state *state = + tevent_req_data(req, struct async_connect_state); int err; fcntl(state->fd, F_SETFL, state->old_sockflags); @@ -723,8 +420,8 @@ static void writev_handler(struct tevent_context *ev, struct tevent_fd *fde, { 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); + struct writev_state *state = + tevent_req_data(req, struct writev_state); size_t to_write, written; int i; @@ -770,8 +467,8 @@ static void writev_handler(struct tevent_context *ev, struct tevent_fd *fde, ssize_t writev_recv(struct tevent_req *req, int *perrno) { - struct writev_state *state = talloc_get_type_abort( - req->private_state, struct writev_state); + struct writev_state *state = + tevent_req_data(req, struct writev_state); if (tevent_req_is_unix_error(req, perrno)) { return -1; @@ -834,8 +531,8 @@ static void read_packet_handler(struct tevent_context *ev, { 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); + struct read_packet_state *state = + tevent_req_data(req, struct read_packet_state); size_t total = talloc_get_size(state->buf); ssize_t nread, more; uint8_t *tmp; @@ -887,8 +584,8 @@ static void read_packet_handler(struct tevent_context *ev, 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); + struct read_packet_state *state = + tevent_req_data(req, struct read_packet_state); if (tevent_req_is_unix_error(req, perrno)) { return -1; diff --git a/lib/async_req/async_sock.h b/lib/async_req/async_sock.h index bfc4346d39..e001709d27 100644 --- a/lib/async_req/async_sock.h +++ b/lib/async_req/async_sock.h @@ -25,17 +25,6 @@ bool async_req_is_errno(struct async_req *req, int *err); int async_req_simple_recv_errno(struct async_req *req); -ssize_t async_syscall_result_ssize_t(struct async_req *req, int *perrno); -size_t async_syscall_result_size_t(struct async_req *req, int *perrno); -int async_syscall_result_int(struct async_req *req, int *perrno); - -struct async_req *async_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - int fd, const void *buffer, size_t length, - int flags); -struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - int fd, void *buffer, size_t length, - int flags); - struct tevent_req *async_send_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, int fd, const void *buf, size_t len, diff --git a/lib/replace/system/network.h b/lib/replace/system/network.h index 40d20db2d4..f135d175d4 100644 --- a/lib/replace/system/network.h +++ b/lib/replace/system/network.h @@ -327,10 +327,12 @@ struct addrinfo { #endif #ifdef SOCKET_WRAPPER +#ifndef SOCKET_WRAPPER_DISABLE #ifndef SOCKET_WRAPPER_NOT_REPLACE #define SOCKET_WRAPPER_REPLACE -#endif +#endif /* SOCKET_WRAPPER_NOT_REPLACE */ #include "../socket_wrapper/socket_wrapper.h" -#endif +#endif /* SOCKET_WRAPPER_DISABLE */ +#endif /* SOCKET_WRAPPER */ #endif diff --git a/lib/smbconf/smbconf.c b/lib/smbconf/smbconf.c index bcab0b97cd..80fe9aac37 100644 --- a/lib/smbconf/smbconf.c +++ b/lib/smbconf/smbconf.c @@ -203,10 +203,6 @@ WERROR smbconf_get_share(struct smbconf_ctx *ctx, const char *servicename, struct smbconf_service **service) { - if (!smbconf_share_exists(ctx, servicename)) { - return WERR_NO_SUCH_SERVICE; - } - return ctx->ops->get_share(ctx, mem_ctx, servicename, service); } @@ -230,10 +226,6 @@ WERROR smbconf_set_parameter(struct smbconf_ctx *ctx, const char *param, const char *valstr) { - if (!smbconf_share_exists(ctx, service)) { - return WERR_NO_SUCH_SERVICE; - } - return ctx->ops->set_parameter(ctx, service, param, valstr); } @@ -269,10 +261,6 @@ WERROR smbconf_get_parameter(struct smbconf_ctx *ctx, return WERR_INVALID_PARAM; } - if (!smbconf_share_exists(ctx, service)) { - return WERR_NO_SUCH_SERVICE; - } - return ctx->ops->get_parameter(ctx, mem_ctx, service, param, valstr); } @@ -303,10 +291,6 @@ WERROR smbconf_get_global_parameter(struct smbconf_ctx *ctx, WERROR smbconf_delete_parameter(struct smbconf_ctx *ctx, const char *service, const char *param) { - if (!smbconf_share_exists(ctx, service)) { - return WERR_NO_SUCH_SERVICE; - } - return ctx->ops->delete_parameter(ctx, service, param); } @@ -333,10 +317,6 @@ WERROR smbconf_get_includes(struct smbconf_ctx *ctx, const char *service, uint32_t *num_includes, char ***includes) { - if (!smbconf_share_exists(ctx, service)) { - return WERR_NO_SUCH_SERVICE; - } - return ctx->ops->get_includes(ctx, mem_ctx, service, num_includes, includes); } @@ -360,10 +340,6 @@ WERROR smbconf_set_includes(struct smbconf_ctx *ctx, const char *service, uint32_t num_includes, const char **includes) { - if (!smbconf_share_exists(ctx, service)) { - return WERR_NO_SUCH_SERVICE; - } - return ctx->ops->set_includes(ctx, service, num_includes, includes); } @@ -385,10 +361,6 @@ WERROR smbconf_set_global_includes(struct smbconf_ctx *ctx, WERROR smbconf_delete_includes(struct smbconf_ctx *ctx, const char *service) { - if (!smbconf_share_exists(ctx, service)) { - return WERR_NO_SUCH_SERVICE; - } - return ctx->ops->delete_includes(ctx, service); } @@ -403,3 +375,18 @@ WERROR smbconf_delete_global_includes(struct smbconf_ctx *ctx) return werr; } + +WERROR smbconf_transaction_start(struct smbconf_ctx *ctx) +{ + return ctx->ops->transaction_start(ctx); +} + +WERROR smbconf_transaction_commit(struct smbconf_ctx *ctx) +{ + return ctx->ops->transaction_commit(ctx); +} + +WERROR smbconf_transaction_cancel(struct smbconf_ctx *ctx) +{ + return ctx->ops->transaction_cancel(ctx); +} diff --git a/lib/smbconf/smbconf.h b/lib/smbconf/smbconf.h index 106fae6431..517302ac88 100644 --- a/lib/smbconf/smbconf.h +++ b/lib/smbconf/smbconf.h @@ -94,4 +94,8 @@ WERROR smbconf_set_global_includes(struct smbconf_ctx *ctx, WERROR smbconf_delete_includes(struct smbconf_ctx *ctx, const char *service); WERROR smbconf_delete_global_includes(struct smbconf_ctx *ctx); +WERROR smbconf_transaction_start(struct smbconf_ctx *ctx); +WERROR smbconf_transaction_commit(struct smbconf_ctx *ctx); +WERROR smbconf_transaction_cancel(struct smbconf_ctx *ctx); + #endif /* _LIBSMBCONF_H_ */ diff --git a/lib/smbconf/smbconf_private.h b/lib/smbconf/smbconf_private.h index c9e44181c6..e6998ad639 100644 --- a/lib/smbconf/smbconf_private.h +++ b/lib/smbconf/smbconf_private.h @@ -68,6 +68,9 @@ struct smbconf_ops { uint32_t num_includes, const char **includes); WERROR (*delete_includes)(struct smbconf_ctx *ctx, const char *service); + WERROR (*transaction_start)(struct smbconf_ctx *ctx); + WERROR (*transaction_commit)(struct smbconf_ctx *ctx); + WERROR (*transaction_cancel)(struct smbconf_ctx *ctx); }; struct smbconf_ctx { diff --git a/lib/smbconf/smbconf_txt.c b/lib/smbconf/smbconf_txt.c index 1df4a9fdb7..501382cc5f 100644 --- a/lib/smbconf/smbconf_txt.c +++ b/lib/smbconf/smbconf_txt.c @@ -612,6 +612,20 @@ static WERROR smbconf_txt_delete_includes(struct smbconf_ctx *ctx, return WERR_NOT_SUPPORTED; } +static WERROR smbconf_txt_transaction_start(struct smbconf_ctx *ctx) +{ + return WERR_OK; +} + +static WERROR smbconf_txt_transaction_commit(struct smbconf_ctx *ctx) +{ + return WERR_OK; +} + +static WERROR smbconf_txt_transaction_cancel(struct smbconf_ctx *ctx) +{ + return WERR_OK; +} static struct smbconf_ops smbconf_ops_txt = { .init = smbconf_txt_init, @@ -633,6 +647,9 @@ static struct smbconf_ops smbconf_ops_txt = { .get_includes = smbconf_txt_get_includes, .set_includes = smbconf_txt_set_includes, .delete_includes = smbconf_txt_delete_includes, + .transaction_start = smbconf_txt_transaction_start, + .transaction_commit = smbconf_txt_transaction_commit, + .transaction_cancel = smbconf_txt_transaction_cancel, }; diff --git a/lib/socket_wrapper/socket_wrapper.c b/lib/socket_wrapper/socket_wrapper.c index 1e3927705b..8ad9e1d93e 100644 --- a/lib/socket_wrapper/socket_wrapper.c +++ b/lib/socket_wrapper/socket_wrapper.c @@ -145,7 +145,16 @@ #define MAX_WRAPPED_INTERFACES 16 -#define SW_IPV6_ADDRESS 1 +#ifdef HAVE_IPV6 +/* + * 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 +} } }; +#endif static struct sockaddr *sockaddr_dup(const void *data, socklen_t len) { @@ -295,7 +304,8 @@ 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.s6_addr[0] = SW_IPV6_ADDRESS; + in2->sin6_addr = swrap_ipv6; + in2->sin6_addr.s6_addr[15] = iface; in2->sin6_port = htons(prt); *len = sizeof(*in2); @@ -367,6 +377,7 @@ static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *i case AF_INET6: { const struct sockaddr_in6 *in = (const struct sockaddr_in6 *)inaddr; + struct in6_addr cmp; switch (si->type) { case SOCK_STREAM: @@ -380,8 +391,16 @@ static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *i /* XXX no multicast/broadcast */ prt = ntohs(in->sin6_port); - iface = SW_IPV6_ADDRESS; - + + cmp = in->sin6_addr; + cmp.s6_addr[15] = 0; + if (IN6_ARE_ADDR_EQUAL(&swrap_ipv6, &cmp)) { + iface = in->sin6_addr.s6_addr[15]; + } else { + errno = ENETUNREACH; + return -1; + } + break; } #endif @@ -474,6 +493,7 @@ static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *in case AF_INET6: { const struct sockaddr_in6 *in = (const struct sockaddr_in6 *)inaddr; + struct in6_addr cmp; switch (si->type) { case SOCK_STREAM: @@ -487,13 +507,21 @@ static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *in /* XXX no multicast/broadcast */ prt = ntohs(in->sin6_port); - iface = SW_IPV6_ADDRESS; - + + cmp = in->sin6_addr; + cmp.s6_addr[15] = 0; + if (IN6_ARE_ADDR_EQUAL(&swrap_ipv6, &cmp)) { + iface = in->sin6_addr.s6_addr[15]; + } else { + errno = EADDRNOTAVAIL; + return -1; + } + break; } #endif default: - errno = ENETUNREACH; + errno = EADDRNOTAVAIL; return -1; } @@ -636,69 +664,93 @@ struct swrap_file_hdr { }; #define SWRAP_FILE_HDR_SIZE 24 -struct swrap_packet { +struct swrap_packet_frame { + uint32_t seconds; + uint32_t micro_seconds; + uint32_t recorded_length; + uint32_t full_length; +}; +#define SWRAP_PACKET_FRAME_SIZE 16 + +union swrap_packet_ip { + struct { + uint8_t ver_hdrlen; + uint8_t tos; + uint16_t packet_length; + uint16_t identification; + uint8_t flags; + uint8_t fragment; + uint8_t ttl; + uint8_t protocol; + uint16_t hdr_checksum; + uint32_t src_addr; + uint32_t dest_addr; + } v4; +#define SWRAP_PACKET_IP_V4_SIZE 20 struct { - uint32_t seconds; - uint32_t micro_seconds; - uint32_t recorded_length; - uint32_t full_length; - } frame; -#define SWRAP_PACKET__FRAME_SIZE 16 + uint8_t ver_prio; + uint8_t flow_label_high; + uint16_t flow_label_low; + uint16_t payload_length; + uint8_t next_header; + uint8_t hop_limit; + uint8_t src_addr[16]; + uint8_t dest_addr[16]; + } v6; +#define SWRAP_PACKET_IP_V6_SIZE 40 +}; +#define SWRAP_PACKET_IP_SIZE 40 +union swrap_packet_payload { + struct { + uint16_t source_port; + uint16_t dest_port; + uint32_t seq_num; + uint32_t ack_num; + uint8_t hdr_length; + uint8_t control; + uint16_t window; + uint16_t checksum; + uint16_t urg; + } tcp; +#define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20 struct { - struct { - uint8_t ver_hdrlen; - uint8_t tos; - uint16_t packet_length; - uint16_t identification; - uint8_t flags; - uint8_t fragment; - uint8_t ttl; - uint8_t protocol; - uint16_t hdr_checksum; - uint32_t src_addr; - uint32_t dest_addr; - } hdr; -#define SWRAP_PACKET__IP_HDR_SIZE 20 - - union { - struct { - uint16_t source_port; - uint16_t dest_port; - uint32_t seq_num; - uint32_t ack_num; - uint8_t hdr_length; - uint8_t control; - uint16_t window; - uint16_t checksum; - uint16_t urg; - } tcp; -#define SWRAP_PACKET__IP_P_TCP_SIZE 20 - struct { - uint16_t source_port; - uint16_t dest_port; - uint16_t length; - uint16_t checksum; - } udp; -#define SWRAP_PACKET__IP_P_UDP_SIZE 8 - struct { - uint8_t type; - uint8_t code; - uint16_t checksum; - uint32_t unused; - } icmp; -#define SWRAP_PACKET__IP_P_ICMP_SIZE 8 - } p; - } ip; + uint16_t source_port; + uint16_t dest_port; + uint16_t length; + uint16_t checksum; + } udp; +#define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8 + struct { + uint8_t type; + uint8_t code; + uint16_t checksum; + uint32_t unused; + } icmp4; +#define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8 + struct { + uint8_t type; + uint8_t code; + uint16_t checksum; + uint32_t unused; + } icmp6; +#define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8 }; -#define SWRAP_PACKET_SIZE 56 +#define SWRAP_PACKET_PAYLOAD_SIZE 20 + +#define SWRAP_PACKET_MIN_ALLOC \ + (SWRAP_PACKET_FRAME_SIZE + \ + SWRAP_PACKET_IP_SIZE + \ + SWRAP_PACKET_PAYLOAD_SIZE) static const char *socket_wrapper_pcap_file(void) { static int initialized = 0; static const char *s = NULL; - static const struct swrap_file_hdr h = { 0, }; - static const struct swrap_packet p = { { 0, }, { { 0, }, { { 0, } } } }; + static const struct swrap_file_hdr h; + static const struct swrap_packet_frame f; + static const union swrap_packet_ip i; + static const union swrap_packet_payload p; if (initialized == 1) { return s; @@ -715,22 +767,31 @@ static const char *socket_wrapper_pcap_file(void) if (sizeof(h) != SWRAP_FILE_HDR_SIZE) { return NULL; } - if (sizeof(p) != SWRAP_PACKET_SIZE) { + if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) { + return NULL; + } + if (sizeof(i) != SWRAP_PACKET_IP_SIZE) { return NULL; } - if (sizeof(p.frame) != SWRAP_PACKET__FRAME_SIZE) { + if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) { return NULL; } - if (sizeof(p.ip.hdr) != SWRAP_PACKET__IP_HDR_SIZE) { + if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) { return NULL; } - if (sizeof(p.ip.p.tcp) != SWRAP_PACKET__IP_P_TCP_SIZE) { + if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) { return NULL; } - if (sizeof(p.ip.p.udp) != SWRAP_PACKET__IP_P_UDP_SIZE) { + if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) { return NULL; } - if (sizeof(p.ip.p.icmp) != SWRAP_PACKET__IP_P_ICMP_SIZE) { + if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) { + return NULL; + } + if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) { + return NULL; + } + if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) { return NULL; } @@ -744,41 +805,72 @@ static const char *socket_wrapper_pcap_file(void) return s; } -static struct swrap_packet *swrap_packet_init(struct timeval *tval, - const struct sockaddr_in *src_addr, - const struct sockaddr_in *dest_addr, - int socket_type, - const unsigned char *payload, - size_t payload_len, - unsigned long tcp_seqno, - unsigned long tcp_ack, - unsigned char tcp_ctl, - int unreachable, - size_t *_packet_len) +static uint8_t *swrap_packet_init(struct timeval *tval, + const struct sockaddr *src, + const struct sockaddr *dest, + int socket_type, + const uint8_t *payload, + size_t payload_len, + unsigned long tcp_seqno, + unsigned long tcp_ack, + unsigned char tcp_ctl, + int unreachable, + size_t *_packet_len) { - struct swrap_packet *ret; - struct swrap_packet *packet; + uint8_t *base; + uint8_t *buf; + struct swrap_packet_frame *frame; + union swrap_packet_ip *ip; + union swrap_packet_payload *pay; size_t packet_len; size_t alloc_len; - size_t nonwire_len = sizeof(packet->frame); + size_t nonwire_len = sizeof(*frame); size_t wire_hdr_len = 0; size_t wire_len = 0; + size_t ip_hdr_len = 0; size_t icmp_hdr_len = 0; size_t icmp_truncate_len = 0; - unsigned char protocol = 0, icmp_protocol = 0; - unsigned short src_port = src_addr->sin_port; - unsigned short dest_port = dest_addr->sin_port; + uint8_t protocol = 0, icmp_protocol = 0; + const struct sockaddr_in *src_in = NULL; + const struct sockaddr_in *dest_in = NULL; +#ifdef HAVE_IPV6 + const struct sockaddr_in6 *src_in6 = NULL; + const struct sockaddr_in6 *dest_in6 = NULL; +#endif + uint16_t src_port; + uint16_t dest_port; + + switch (src->sa_family) { + case AF_INET: + src_in = (const struct sockaddr_in *)src; + dest_in = (const struct sockaddr_in *)dest; + src_port = src_in->sin_port; + dest_port = dest_in->sin_port; + ip_hdr_len = sizeof(ip->v4); + break; +#ifdef HAVE_IPV6 + case AF_INET6: + src_in6 = (const struct sockaddr_in6 *)src; + dest_in6 = (const struct sockaddr_in6 *)dest; + src_port = src_in6->sin6_port; + dest_port = dest_in6->sin6_port; + ip_hdr_len = sizeof(ip->v6); + break; +#endif + default: + return NULL; + } switch (socket_type) { case SOCK_STREAM: protocol = 0x06; /* TCP */ - wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.tcp); + wire_hdr_len = ip_hdr_len + sizeof(pay->tcp); wire_len = wire_hdr_len + payload_len; break; case SOCK_DGRAM: protocol = 0x11; /* UDP */ - wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.udp); + wire_hdr_len = ip_hdr_len + sizeof(pay->udp); wire_len = wire_hdr_len + payload_len; break; @@ -788,98 +880,160 @@ static struct swrap_packet *swrap_packet_init(struct timeval *tval, if (unreachable) { icmp_protocol = protocol; - protocol = 0x01; /* ICMP */ + switch (src->sa_family) { + case AF_INET: + protocol = 0x01; /* ICMPv4 */ + icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4); + break; +#ifdef HAVE_IPV6 + case AF_INET6: + protocol = 0x3A; /* ICMPv6 */ + icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6); + break; +#endif + } if (wire_len > 64 ) { icmp_truncate_len = wire_len - 64; } - icmp_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.icmp); wire_hdr_len += icmp_hdr_len; wire_len += icmp_hdr_len; } packet_len = nonwire_len + wire_len; alloc_len = packet_len; - if (alloc_len < sizeof(struct swrap_packet)) { - alloc_len = sizeof(struct swrap_packet); - } - ret = (struct swrap_packet *)malloc(alloc_len); - if (!ret) return NULL; - - packet = ret; - - packet->frame.seconds = tval->tv_sec; - packet->frame.micro_seconds = tval->tv_usec; - packet->frame.recorded_length = wire_len - icmp_truncate_len; - packet->frame.full_length = wire_len - icmp_truncate_len; - - packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */ - packet->ip.hdr.tos = 0x00; - packet->ip.hdr.packet_length = htons(wire_len - icmp_truncate_len); - packet->ip.hdr.identification = htons(0xFFFF); - packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */ - packet->ip.hdr.fragment = htons(0x0000); - packet->ip.hdr.ttl = 0xFF; - packet->ip.hdr.protocol = protocol; - packet->ip.hdr.hdr_checksum = htons(0x0000); - packet->ip.hdr.src_addr = src_addr->sin_addr.s_addr; - packet->ip.hdr.dest_addr = dest_addr->sin_addr.s_addr; + if (alloc_len < SWRAP_PACKET_MIN_ALLOC) { + alloc_len = SWRAP_PACKET_MIN_ALLOC; + } + + base = (uint8_t *)malloc(alloc_len); + if (!base) return NULL; + + buf = base; + + frame = (struct swrap_packet_frame *)buf; + frame->seconds = tval->tv_sec; + frame->micro_seconds = tval->tv_usec; + frame->recorded_length = wire_len - icmp_truncate_len; + frame->full_length = wire_len - icmp_truncate_len; + buf += SWRAP_PACKET_FRAME_SIZE; + + ip = (union swrap_packet_ip *)buf; + switch (src->sa_family) { + case AF_INET: + ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */ + ip->v4.tos = 0x00; + ip->v4.packet_length = htons(wire_len - icmp_truncate_len); + ip->v4.identification = htons(0xFFFF); + ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */ + ip->v4.fragment = htons(0x0000); + ip->v4.ttl = 0xFF; + ip->v4.protocol = protocol; + ip->v4.hdr_checksum = htons(0x0000); + ip->v4.src_addr = src_in->sin_addr.s_addr; + ip->v4.dest_addr = dest_in->sin_addr.s_addr; + buf += SWRAP_PACKET_IP_V4_SIZE; + break; +#ifdef HAVE_IPV6 + case AF_INET6: + ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */ + ip->v6.flow_label_high = 0x00; + ip->v6.flow_label_low = 0x0000; + ip->v6.payload_length = htons(wire_len - icmp_truncate_len);//TODO + ip->v6.next_header = protocol; + memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16); + memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16); + buf += SWRAP_PACKET_IP_V6_SIZE; + break; +#endif + } if (unreachable) { - packet->ip.p.icmp.type = 0x03; /* destination unreachable */ - packet->ip.p.icmp.code = 0x01; /* host unreachable */ - packet->ip.p.icmp.checksum = htons(0x0000); - packet->ip.p.icmp.unused = htonl(0x00000000); - - /* set the ip header in the ICMP payload */ - packet = (struct swrap_packet *)(((unsigned char *)ret) + icmp_hdr_len); - packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */ - packet->ip.hdr.tos = 0x00; - packet->ip.hdr.packet_length = htons(wire_len - icmp_hdr_len); - packet->ip.hdr.identification = htons(0xFFFF); - packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */ - packet->ip.hdr.fragment = htons(0x0000); - packet->ip.hdr.ttl = 0xFF; - packet->ip.hdr.protocol = icmp_protocol; - packet->ip.hdr.hdr_checksum = htons(0x0000); - packet->ip.hdr.src_addr = dest_addr->sin_addr.s_addr; - packet->ip.hdr.dest_addr = src_addr->sin_addr.s_addr; - - src_port = dest_addr->sin_port; - dest_port = src_addr->sin_port; + pay = (union swrap_packet_payload *)buf; + switch (src->sa_family) { + case AF_INET: + pay->icmp4.type = 0x03; /* destination unreachable */ + pay->icmp4.code = 0x01; /* host unreachable */ + pay->icmp4.checksum = htons(0x0000); + pay->icmp4.unused = htonl(0x00000000); + buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE; + + /* set the ip header in the ICMP payload */ + ip = (union swrap_packet_ip *)buf; + ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */ + ip->v4.tos = 0x00; + ip->v4.packet_length = htons(wire_len - icmp_hdr_len); + ip->v4.identification = htons(0xFFFF); + ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */ + ip->v4.fragment = htons(0x0000); + ip->v4.ttl = 0xFF; + ip->v4.protocol = icmp_protocol; + ip->v4.hdr_checksum = htons(0x0000); + ip->v4.src_addr = dest_in->sin_addr.s_addr; + ip->v4.dest_addr = src_in->sin_addr.s_addr; + buf += SWRAP_PACKET_IP_V4_SIZE; + + src_port = dest_in->sin_port; + dest_port = src_in->sin_port; + break; +#ifdef HAVE_IPV6 + case AF_INET6: + pay->icmp6.type = 0x01; /* destination unreachable */ + pay->icmp6.code = 0x03; /* address unreachable */ + pay->icmp6.checksum = htons(0x0000); + pay->icmp6.unused = htonl(0x00000000); + buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE; + + /* set the ip header in the ICMP payload */ + ip = (union swrap_packet_ip *)buf; + ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */ + ip->v6.flow_label_high = 0x00; + ip->v6.flow_label_low = 0x0000; + ip->v6.payload_length = htons(wire_len - icmp_truncate_len);//TODO + ip->v6.next_header = protocol; + memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16); + memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16); + buf += SWRAP_PACKET_IP_V6_SIZE; + + src_port = dest_in6->sin6_port; + dest_port = src_in6->sin6_port; + break; +#endif + } } + pay = (union swrap_packet_payload *)buf; + switch (socket_type) { case SOCK_STREAM: - packet->ip.p.tcp.source_port = src_port; - packet->ip.p.tcp.dest_port = dest_port; - packet->ip.p.tcp.seq_num = htonl(tcp_seqno); - packet->ip.p.tcp.ack_num = htonl(tcp_ack); - packet->ip.p.tcp.hdr_length = 0x50; /* 5 * 32 bit words */ - packet->ip.p.tcp.control = tcp_ctl; - packet->ip.p.tcp.window = htons(0x7FFF); - packet->ip.p.tcp.checksum = htons(0x0000); - packet->ip.p.tcp.urg = htons(0x0000); + pay->tcp.source_port = src_port; + pay->tcp.dest_port = dest_port; + pay->tcp.seq_num = htonl(tcp_seqno); + pay->tcp.ack_num = htonl(tcp_ack); + pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */ + pay->tcp.control = tcp_ctl; + pay->tcp.window = htons(0x7FFF); + pay->tcp.checksum = htons(0x0000); + pay->tcp.urg = htons(0x0000); + buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE; break; case SOCK_DGRAM: - packet->ip.p.udp.source_port = src_addr->sin_port; - packet->ip.p.udp.dest_port = dest_addr->sin_port; - packet->ip.p.udp.length = htons(8 + payload_len); - packet->ip.p.udp.checksum = htons(0x0000); + pay->udp.source_port = src_port; + pay->udp.dest_port = dest_port; + pay->udp.length = htons(8 + payload_len); + pay->udp.checksum = htons(0x0000); + buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE; break; } if (payload && payload_len > 0) { - unsigned char *p = (unsigned char *)ret; - p += nonwire_len; - p += wire_hdr_len; - memcpy(p, payload, payload_len); + memcpy(buf, payload, payload_len); } *_packet_len = packet_len - icmp_truncate_len; - return ret; + return base; } static int swrap_get_pcap_fd(const char *fname) @@ -911,14 +1065,14 @@ static int swrap_get_pcap_fd(const char *fname) return fd; } -static struct swrap_packet *swrap_marshall_packet(struct socket_info *si, - const struct sockaddr *addr, - enum swrap_packet_type type, - const void *buf, size_t len, - size_t *packet_len) +static uint8_t *swrap_marshall_packet(struct socket_info *si, + const struct sockaddr *addr, + enum swrap_packet_type type, + const void *buf, size_t len, + size_t *packet_len) { - const struct sockaddr_in *src_addr; - const struct sockaddr_in *dest_addr; + const struct sockaddr *src_addr; + const struct sockaddr *dest_addr; unsigned long tcp_seqno = 0; unsigned long tcp_ack = 0; unsigned char tcp_ctl = 0; @@ -929,6 +1083,8 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si, switch (si->family) { case AF_INET: break; + case AF_INET6: + break; default: return NULL; } @@ -937,8 +1093,8 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si, case SWRAP_CONNECT_SEND: if (si->type != SOCK_STREAM) return NULL; - src_addr = (const struct sockaddr_in *)si->myname; - dest_addr = (const struct sockaddr_in *)addr; + src_addr = si->myname; + dest_addr = addr; tcp_seqno = si->io.pck_snd; tcp_ack = si->io.pck_rcv; @@ -951,8 +1107,8 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si, case SWRAP_CONNECT_RECV: if (si->type != SOCK_STREAM) return NULL; - dest_addr = (const struct sockaddr_in *)si->myname; - src_addr = (const struct sockaddr_in *)addr; + dest_addr = si->myname; + src_addr = addr; tcp_seqno = si->io.pck_rcv; tcp_ack = si->io.pck_snd; @@ -965,8 +1121,8 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si, case SWRAP_CONNECT_UNREACH: if (si->type != SOCK_STREAM) return NULL; - dest_addr = (const struct sockaddr_in *)si->myname; - src_addr = (const struct sockaddr_in *)addr; + dest_addr = si->myname; + src_addr = addr; /* Unreachable: resend the data of SWRAP_CONNECT_SEND */ tcp_seqno = si->io.pck_snd - 1; @@ -979,8 +1135,8 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si, case SWRAP_CONNECT_ACK: if (si->type != SOCK_STREAM) return NULL; - src_addr = (const struct sockaddr_in *)si->myname; - dest_addr = (const struct sockaddr_in *)addr; + src_addr = si->myname; + dest_addr = addr; tcp_seqno = si->io.pck_snd; tcp_ack = si->io.pck_rcv; @@ -991,8 +1147,8 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si, case SWRAP_ACCEPT_SEND: if (si->type != SOCK_STREAM) return NULL; - dest_addr = (const struct sockaddr_in *)si->myname; - src_addr = (const struct sockaddr_in *)addr; + dest_addr = si->myname; + src_addr = addr; tcp_seqno = si->io.pck_rcv; tcp_ack = si->io.pck_snd; @@ -1005,8 +1161,8 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si, case SWRAP_ACCEPT_RECV: if (si->type != SOCK_STREAM) return NULL; - src_addr = (const struct sockaddr_in *)si->myname; - dest_addr = (const struct sockaddr_in *)addr; + src_addr = si->myname; + dest_addr = addr; tcp_seqno = si->io.pck_snd; tcp_ack = si->io.pck_rcv; @@ -1019,8 +1175,8 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si, case SWRAP_ACCEPT_ACK: if (si->type != SOCK_STREAM) return NULL; - dest_addr = (const struct sockaddr_in *)si->myname; - src_addr = (const struct sockaddr_in *)addr; + dest_addr = si->myname; + src_addr = addr; tcp_seqno = si->io.pck_rcv; tcp_ack = si->io.pck_snd; @@ -1029,8 +1185,8 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si, break; case SWRAP_SEND: - src_addr = (const struct sockaddr_in *)si->myname; - dest_addr = (const struct sockaddr_in *)si->peername; + src_addr = si->myname; + dest_addr = si->peername; tcp_seqno = si->io.pck_snd; tcp_ack = si->io.pck_rcv; @@ -1041,8 +1197,8 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si, break; case SWRAP_SEND_RST: - dest_addr = (const struct sockaddr_in *)si->myname; - src_addr = (const struct sockaddr_in *)si->peername; + dest_addr = si->myname; + src_addr = si->peername; if (si->type == SOCK_DGRAM) { return swrap_marshall_packet(si, si->peername, @@ -1057,8 +1213,8 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si, break; case SWRAP_PENDING_RST: - dest_addr = (const struct sockaddr_in *)si->myname; - src_addr = (const struct sockaddr_in *)si->peername; + dest_addr = si->myname; + src_addr = si->peername; if (si->type == SOCK_DGRAM) { return NULL; @@ -1071,8 +1227,8 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si, break; case SWRAP_RECV: - dest_addr = (const struct sockaddr_in *)si->myname; - src_addr = (const struct sockaddr_in *)si->peername; + dest_addr = si->myname; + src_addr = si->peername; tcp_seqno = si->io.pck_rcv; tcp_ack = si->io.pck_snd; @@ -1083,8 +1239,8 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si, break; case SWRAP_RECV_RST: - dest_addr = (const struct sockaddr_in *)si->myname; - src_addr = (const struct sockaddr_in *)si->peername; + dest_addr = si->myname; + src_addr = si->peername; if (si->type == SOCK_DGRAM) { return NULL; @@ -1097,24 +1253,24 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si, break; case SWRAP_SENDTO: - src_addr = (const struct sockaddr_in *)si->myname; - dest_addr = (const struct sockaddr_in *)addr; + src_addr = si->myname; + dest_addr = addr; si->io.pck_snd += len; break; case SWRAP_SENDTO_UNREACH: - dest_addr = (const struct sockaddr_in *)si->myname; - src_addr = (const struct sockaddr_in *)addr; + dest_addr = si->myname; + src_addr = addr; unreachable = 1; break; case SWRAP_RECVFROM: - dest_addr = (const struct sockaddr_in *)si->myname; - src_addr = (const struct sockaddr_in *)addr; + dest_addr = si->myname; + src_addr = addr; si->io.pck_rcv += len; @@ -1123,8 +1279,8 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si, case SWRAP_CLOSE_SEND: if (si->type != SOCK_STREAM) return NULL; - src_addr = (const struct sockaddr_in *)si->myname; - dest_addr = (const struct sockaddr_in *)si->peername; + src_addr = si->myname; + dest_addr = si->peername; tcp_seqno = si->io.pck_snd; tcp_ack = si->io.pck_rcv; @@ -1137,8 +1293,8 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si, case SWRAP_CLOSE_RECV: if (si->type != SOCK_STREAM) return NULL; - dest_addr = (const struct sockaddr_in *)si->myname; - src_addr = (const struct sockaddr_in *)si->peername; + dest_addr = si->myname; + src_addr = si->peername; tcp_seqno = si->io.pck_rcv; tcp_ack = si->io.pck_snd; @@ -1151,8 +1307,8 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si, case SWRAP_CLOSE_ACK: if (si->type != SOCK_STREAM) return NULL; - src_addr = (const struct sockaddr_in *)si->myname; - dest_addr = (const struct sockaddr_in *)si->peername; + src_addr = si->myname; + dest_addr = si->peername; tcp_seqno = si->io.pck_snd; tcp_ack = si->io.pck_rcv; @@ -1166,18 +1322,18 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si, swrapGetTimeOfDay(&tv); return swrap_packet_init(&tv, src_addr, dest_addr, si->type, - (const unsigned char *)buf, len, - tcp_seqno, tcp_ack, tcp_ctl, unreachable, - packet_len); + (const uint8_t *)buf, len, + tcp_seqno, tcp_ack, tcp_ctl, unreachable, + packet_len); } -static void swrap_dump_packet(struct socket_info *si, - const struct sockaddr *addr, - enum swrap_packet_type type, - const void *buf, size_t len) +static void swrap_dump_packet(struct socket_info *si, + const struct sockaddr *addr, + enum swrap_packet_type type, + const void *buf, size_t len) { const char *file_name; - struct swrap_packet *packet; + uint8_t *packet; size_t packet_len = 0; int fd; @@ -1432,13 +1588,14 @@ static int swrap_auto_bind(struct socket_info *si) type = SOCKET_TYPE_CHAR_UDP_V6; break; default: - errno = ESOCKTNOSUPPORT; - return -1; + errno = ESOCKTNOSUPPORT; + return -1; } memset(&in6, 0, sizeof(in6)); in6.sin6_family = AF_INET6; - in6.sin6_addr.s6_addr[0] = SW_IPV6_ADDRESS; + 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); break; @@ -1781,7 +1938,7 @@ _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags) swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0); } else if (ret == 0) { /* END OF FILE */ swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0); - } else { + } else if (ret > 0) { swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret); } diff --git a/lib/talloc/configure.ac b/lib/talloc/configure.ac index d2538f9222..39cea393ce 100644 --- a/lib/talloc/configure.ac +++ b/lib/talloc/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.50) -AC_INIT(talloc, 1.2.0) +AC_INIT(talloc, 1.2.1) AC_CONFIG_SRCDIR([talloc.c]) AC_SUBST(datarootdir) AC_CONFIG_HEADER(config.h) diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c index 1f7e52439f..c472e9fda9 100644 --- a/lib/talloc/talloc.c +++ b/lib/talloc/talloc.c @@ -806,6 +806,30 @@ void *talloc_check_name(const void *ptr, const char *name) return NULL; } +static void talloc_abort_type_missmatch(const char *location, + const char *name, + const char *expected) +{ + TALLOC_ABORT("Type missmatch"); +} + +void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location) +{ + const char *pname; + + if (unlikely(ptr == NULL)) { + talloc_abort_type_missmatch(location, NULL, name); + return NULL; + } + + pname = talloc_get_name(ptr); + if (likely(pname == name || strcmp(pname, name) == 0)) { + return discard_const_p(void, ptr); + } + + talloc_abort_type_missmatch(location, pname, name); + return NULL; +} /* this is for compatibility with older versions of talloc diff --git a/lib/talloc/talloc.h b/lib/talloc/talloc.h index 5431971655..002e06e52d 100644 --- a/lib/talloc/talloc.h +++ b/lib/talloc/talloc.h @@ -102,6 +102,7 @@ typedef void TALLOC_CTX; #define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type) #define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type) +#define talloc_get_type_abort(ptr, type) (type *)_talloc_get_type_abort(ptr, #type, __location__) #define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type) @@ -129,6 +130,7 @@ void *talloc_named(const void *context, size_t size, void *talloc_named_const(const void *context, size_t size, const char *name); const char *talloc_get_name(const void *ptr); void *talloc_check_name(const void *ptr, const char *name); +void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location); void *talloc_parent(const void *ptr); const char *talloc_parent_name(const void *ptr); void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); diff --git a/lib/tdb/common/open.c b/lib/tdb/common/open.c index b19e4cea29..e58c8ca7ff 100644 --- a/lib/tdb/common/open.c +++ b/lib/tdb/common/open.c @@ -461,6 +461,10 @@ fail: /* reopen all tdb's */ int tdb_reopen_all(int parent_longlived) { +#if defined(LIBREPLACE_PREAD_NOT_REPLACED) && \ + defined(LIBREPLACE_PWRITE_NOT_REPLACED) + return 0; +#else struct tdb_context *tdb; for (tdb=tdbs; tdb; tdb = tdb->next) { @@ -483,6 +487,7 @@ int tdb_reopen_all(int parent_longlived) if (tdb_reopen(tdb) != 0) return -1; } +#endif return 0; } diff --git a/lib/tevent/libtevent.m4 b/lib/tevent/libtevent.m4 index 29a64ae3b3..c316823a71 100644 --- a/lib/tevent/libtevent.m4 +++ b/lib/tevent/libtevent.m4 @@ -27,7 +27,7 @@ AC_SUBST(TEVENT_LIBS) TEVENT_CFLAGS="-I$teventdir" TEVENT_OBJ="tevent.o tevent_fd.o tevent_timed.o tevent_signal.o tevent_debug.o tevent_util.o" -TEVENT_OBJ="$TEVENT_OBJ tevent_req.o tevent_wakeup.o" +TEVENT_OBJ="$TEVENT_OBJ tevent_req.o tevent_wakeup.o tevent_queue.o" TEVENT_OBJ="$TEVENT_OBJ tevent_standard.o tevent_select.o" AC_CHECK_HEADERS(sys/epoll.h) diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c index 3b45ba1928..fe7e7e3e38 100644 --- a/lib/tevent/pytevent.c +++ b/lib/tevent/pytevent.c @@ -29,7 +29,6 @@ #include <tevent.h> #include <stdbool.h> -#include "tevent_util.h" typedef struct { PyObject_HEAD @@ -54,7 +53,8 @@ static PyObject *py_backend_list(PyObject *self) PyObject *ret; int i, len; - len = ev_str_list_length(backends); + for (len = 0; backends[len]; len++); + ret = PyList_New(len); for (i = 0; i < len; i++) PyList_SetItem(ret, i, PyString_FromString(backends[i])); diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index 33747f0986..5089d18ec2 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -31,7 +31,7 @@ #include <stdint.h> #include <talloc.h> #include <sys/time.h> -#include <../lib/replace/replace.h> +#include <stdbool.h> struct tevent_context; struct tevent_ops; @@ -183,89 +183,24 @@ enum tevent_req_state { * finished. This can happen while the completion function is called. */ -struct tevent_req { - /** - * @brief What to do on completion - * - * This is used for the user of an async request, fn is called when - * the request completes, either successfully or with an error. - */ - struct { - /** - * @brief Completion function - * Completion function, to be filled by the API user - */ - void (*fn)(struct tevent_req *); - /** - * @brief Private data for the completion function - */ - void *private_data; - } async; +struct tevent_req; - /** - * @brief Private state pointer for the actual implementation - * - * The implementation doing the work for the async request needs a - * current state like for example a fd event. The user of an async - * request should not touch this. - */ - void *private_state; +typedef void (*tevent_req_fn)(struct tevent_req *); - /** - * @brief Internal state of the request - * - * Callers should only access this via functions and never directly. - */ - struct { - /** - * @brief The talloc type of the private_state pointer - * - * This is filled by the tevent_req_create() macro. - * - * This for debugging only. - */ - const char *private_type; - - /** - * @brief The location where the request was created - * - * This uses the __location__ macro via the tevent_req_create() - * macro. - * - * This for debugging only. - */ - const char *location; - - /** - * @brief The external state - will be queried by the caller - * - * While the async request is being processed, state will remain in - * TEVENT_REQ_IN_PROGRESS. A request is finished if - * req->state>=TEVENT_REQ_DONE. - */ - enum tevent_req_state state; - - /** - * @brief status code when finished - * - * This status can be queried in the async completion function. It - * will be set to 0 when everything went fine. - */ - uint64_t error; - - /** - * @brief the timer event if tevent_req_post was used - * - */ - struct tevent_timer *trigger; - - /** - * @brief the timer event if tevent_req_set_timeout was used - * - */ - struct tevent_timer *timer; - } internal; -}; +void tevent_req_set_callback(struct tevent_req *req, tevent_req_fn fn, void *pvt); +void *_tevent_req_callback_data(struct tevent_req *req); +void *_tevent_req_data(struct tevent_req *req); + +#define tevent_req_callback_data(_req, _type) \ + talloc_get_type_abort(_tevent_req_callback_data(_req), _type) +#define tevent_req_data(_req, _type) \ + talloc_get_type_abort(_tevent_req_data(_req), _type) + +typedef char *(*tevent_req_print_fn)(struct tevent_req *, TALLOC_CTX *); + +void tevent_req_set_print_fn(struct tevent_req *req, tevent_req_print_fn fn); + +char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx); char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req); @@ -296,6 +231,9 @@ struct tevent_req *tevent_req_post(struct tevent_req *req, bool tevent_req_is_in_progress(struct tevent_req *req); +bool tevent_req_poll(struct tevent_req *req, + struct tevent_context *ev); + bool tevent_req_is_error(struct tevent_req *req, enum tevent_req_state *state, uint64_t *error); @@ -324,6 +262,28 @@ struct timeval tevent_timeval_add(const struct timeval *tv, uint32_t secs, struct timeval tevent_timeval_current_ofs(uint32_t secs, uint32_t usecs); +struct tevent_queue; + +struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx, + const char *name, + const char *location); + +#define tevent_queue_create(_mem_ctx, _name) \ + _tevent_queue_create((_mem_ctx), (_name), __location__) + +typedef void (*tevent_queue_trigger_fn_t)(struct tevent_req *req, + void *private_data); +bool tevent_queue_add(struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data); +bool tevent_queue_start(struct tevent_queue *queue, + struct tevent_context *ev); +void tevent_queue_stop(struct tevent_queue *queue); + +size_t tevent_queue_length(struct tevent_queue *queue); + #ifdef TEVENT_COMPAT_DEFINES #define event_context tevent_context diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h index 758bdb4628..fa73b22a48 100644 --- a/lib/tevent/tevent_internal.h +++ b/lib/tevent/tevent_internal.h @@ -25,6 +25,99 @@ License along with this library; if not, see <http://www.gnu.org/licenses/>. */ +struct tevent_req { + /** + * @brief What to do on completion + * + * This is used for the user of an async request, fn is called when + * the request completes, either successfully or with an error. + */ + struct { + /** + * @brief Completion function + * Completion function, to be filled by the API user + */ + tevent_req_fn fn; + /** + * @brief Private data for the completion function + */ + void *private_data; + } async; + + /** + * @brief Private state pointer for the actual implementation + * + * The implementation doing the work for the async request needs to + * keep around current data like for example a fd event. The user of + * an async request should not touch this. + */ + void *data; + + /** + * @brief A function to overwrite the default print function + * + * The implementation doing the work may want to imeplement a + * custom function to print the text representation of the async + * request. + */ + tevent_req_print_fn private_print; + + /** + * @brief Internal state of the request + * + * Callers should only access this via functions and never directly. + */ + struct { + /** + * @brief The talloc type of the data pointer + * + * This is filled by the tevent_req_create() macro. + * + * This for debugging only. + */ + const char *private_type; + + /** + * @brief The location where the request was created + * + * This uses the __location__ macro via the tevent_req_create() + * macro. + * + * This for debugging only. + */ + const char *location; + + /** + * @brief The external state - will be queried by the caller + * + * While the async request is being processed, state will remain in + * TEVENT_REQ_IN_PROGRESS. A request is finished if + * req->state>=TEVENT_REQ_DONE. + */ + enum tevent_req_state state; + + /** + * @brief status code when finished + * + * This status can be queried in the async completion function. It + * will be set to 0 when everything went fine. + */ + uint64_t error; + + /** + * @brief the timer event if tevent_req_post was used + * + */ + struct tevent_timer *trigger; + + /** + * @brief the timer event if tevent_req_set_timeout was used + * + */ + struct tevent_timer *timer; + } internal; +}; + struct tevent_ops { /* conntext init */ int (*context_init)(struct tevent_context *ev); diff --git a/lib/tevent/tevent_queue.c b/lib/tevent/tevent_queue.c new file mode 100644 index 0000000000..6c8fbe4f95 --- /dev/null +++ b/lib/tevent/tevent_queue.c @@ -0,0 +1,198 @@ +/* + Unix SMB/CIFS implementation. + Infrastructure for async requests + Copyright (C) Volker Lendecke 2008 + Copyright (C) Stefan Metzmacher 2009 + + ** NOTE! The following LGPL license applies to the tevent + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +struct tevent_queue_entry { + struct tevent_queue_entry *prev, *next; + struct tevent_queue *queue; + + bool triggered; + + struct tevent_req *req; + + tevent_queue_trigger_fn_t trigger; + void *private_data; +}; + +struct tevent_queue { + const char *name; + const char *location; + + bool running; + struct tevent_timer *timer; + + size_t length; + struct tevent_queue_entry *list; +}; + +static int tevent_queue_entry_destructor(struct tevent_queue_entry *e) +{ + struct tevent_queue *q = e->queue; + + if (!q) { + return 0; + } + + DLIST_REMOVE(q->list, e); + q->length--; + + if (e->triggered && + q->running && + q->list) { + q->list->triggered = true; + q->list->trigger(q->list->req, + q->list->private_data); + } + + return 0; +} + +static int tevent_queue_destructor(struct tevent_queue *q) +{ + q->running = false; + + while (q->list) { + struct tevent_queue_entry *e = q->list; + talloc_free(e); + } + + return 0; +} + +struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx, + const char *name, + const char *location) +{ + struct tevent_queue *queue; + + queue = talloc_zero(mem_ctx, struct tevent_queue); + if (!queue) { + return NULL; + } + + queue->name = talloc_strdup(queue, name); + if (!queue->name) { + talloc_free(queue); + return NULL; + } + + queue->location = location; + + /* queue is running by default */ + queue->running = true; + + talloc_set_destructor(queue, tevent_queue_destructor); + return queue; +} + +static void tevent_queue_timer_start(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval now, + void *private_data) +{ + struct tevent_queue *q = talloc_get_type(private_data, + struct tevent_queue); + + talloc_free(te); + q->timer = NULL; + + q->list->triggered = true; + q->list->trigger(q->list->req, q->list->private_data); +} + +bool tevent_queue_add(struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data) +{ + struct tevent_queue_entry *e; + + e = talloc_zero(req, struct tevent_queue_entry); + if (e == NULL) { + return false; + } + + e->queue = queue; + e->req = req; + e->trigger = trigger; + e->private_data = private_data; + + if (queue->running && + !queue->timer && + !queue->list) { + queue->timer = tevent_add_timer(ev, queue, tevent_timeval_zero(), + tevent_queue_timer_start, + queue); + if (!queue->timer) { + talloc_free(e); + return false; + } + } + + DLIST_ADD_END(queue->list, e, struct tevent_queue_entry *); + queue->length++; + talloc_set_destructor(e, tevent_queue_entry_destructor); + + return true; +} + +bool tevent_queue_start(struct tevent_queue *queue, + struct tevent_context *ev) +{ + if (queue->running) { + /* already started */ + return true; + } + + if (!queue->timer && + queue->list) { + queue->timer = tevent_add_timer(ev, queue, tevent_timeval_zero(), + tevent_queue_timer_start, + queue); + if (!queue->timer) { + return false; + } + } + + queue->running = true; + + return true; +} + +void tevent_queue_stop(struct tevent_queue *queue) +{ + queue->running = false; + talloc_free(queue->timer); + queue->timer = NULL; +} + +size_t tevent_queue_length(struct tevent_queue *queue) +{ + return queue->length; +} diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c index 800e3855d1..9b3e00ec8f 100644 --- a/lib/tevent/tevent_req.c +++ b/lib/tevent/tevent_req.c @@ -28,14 +28,17 @@ #include "tevent_util.h" /** - * @brief Print an tevent_req structure in debug messages - * @param[in] mem_ctx The memory context for the result + * @brief The default print function for creating debug messages * @param[in] req The request to be printed + * @param[in] mem_ctx The memory context for the result * @retval Text representation of req * + * The function should not be used by users of the asynx API, + * but custom print function can use it and append custom text + * to the string. */ -char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req) +char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx) { return talloc_asprintf(mem_ctx, "tevent_req[%p/%s]: state[%d] error[%lld (0x%llX)] " @@ -44,13 +47,31 @@ char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req) req->internal.state, (unsigned long long)req->internal.error, (unsigned long long)req->internal.error, - talloc_get_name(req->private_state), - req->private_state, + talloc_get_name(req->data), + req->data, req->internal.timer ); } /** + * @brief Print an tevent_req structure in debug messages + * @param[in] mem_ctx The memory context for the result + * @param[in] req The request to be printed + * @retval Text representation of req + * + * This function should be used by callers of the async API + */ + +char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req) +{ + if (!req->private_print) { + return tevent_req_default_print(req, mem_ctx); + } + + return req->private_print(req, mem_ctx); +} + +/** * @brief Create an async request * @param[in] mem_ctx The memory context for the result * @param[in] ev The event context this async request will be driven by @@ -60,14 +81,14 @@ char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req) */ struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, - void *pstate, - size_t state_size, + void *pdata, + size_t data_size, const char *type, const char *location) { struct tevent_req *req; - void **ppstate = (void **)pstate; - void *state; + void **ppdata = (void **)pdata; + void *data; req = talloc_zero(mem_ctx, struct tevent_req); if (req == NULL) { @@ -77,16 +98,16 @@ struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, req->internal.location = location; req->internal.state = TEVENT_REQ_IN_PROGRESS; - state = talloc_size(req, state_size); - if (state == NULL) { + data = talloc_size(req, data_size); + if (data == NULL) { talloc_free(req); return NULL; } - talloc_set_name_const(state, type); + talloc_set_name_const(data, type); - req->private_state = state; + req->data = data; - *ppstate = state; + *ppdata = data; return req; } @@ -235,6 +256,21 @@ bool tevent_req_is_in_progress(struct tevent_req *req) return false; } +bool tevent_req_poll(struct tevent_req *req, + struct tevent_context *ev) +{ + while (tevent_req_is_in_progress(req)) { + int ret; + + ret = tevent_loop_once(ev); + if (ret != 0) { + return false; + } + } + + return true; +} + bool tevent_req_is_error(struct tevent_req *req, enum tevent_req_state *state, uint64_t *error) { @@ -278,3 +314,23 @@ bool tevent_req_set_endtime(struct tevent_req *req, return true; } +void tevent_req_set_callback(struct tevent_req *req, tevent_req_fn fn, void *pvt) +{ + req->async.fn = fn; + req->async.private_data = pvt; +} + +void *_tevent_req_callback_data(struct tevent_req *req) +{ + return req->async.private_data; +} + +void *_tevent_req_data(struct tevent_req *req) +{ + return req->data; +} + +void tevent_req_set_print_fn(struct tevent_req *req, tevent_req_print_fn fn) +{ + req->private_print = fn; +} diff --git a/lib/torture/config.mk b/lib/torture/config.mk index abd89260f6..b4ad9ae17f 100644 --- a/lib/torture/config.mk +++ b/lib/torture/config.mk @@ -3,7 +3,9 @@ PUBLIC_DEPENDENCIES = \ LIBSAMBA-HOSTCONFIG \ LIBSAMBA-UTIL \ - LIBTALLOC + LIBSAMBA-ERRORS \ + LIBTALLOC \ + LIBTEVENT CFLAGS = -I$(libtorturesrcdir) -I$(libtorturesrcdir)/../ torture_VERSION = 0.0.1 diff --git a/lib/util/charset/charcnv.c b/lib/util/charset/charcnv.c index 1f3b1ac846..258730ec82 100644 --- a/lib/util/charset/charcnv.c +++ b/lib/util/charset/charcnv.c @@ -186,7 +186,7 @@ convert: destlen = 2 + (destlen*3); ob = talloc_realloc(ctx, outbuf, char, destlen); if (!ob) { - DEBUG(0, ("convert_string_talloc: realloc failed!\n")); + DEBUG(0, ("iconv_talloc: realloc failed!\n")); talloc_free(outbuf); return (size_t)-1; } else { @@ -237,10 +237,11 @@ convert: * @param destlen maximal length allowed for string * @returns the number of bytes occupied in the destination **/ -_PUBLIC_ ssize_t convert_string_convenience(struct smb_iconv_convenience *ic, +_PUBLIC_ bool convert_string_convenience(struct smb_iconv_convenience *ic, charset_t from, charset_t to, void const *src, size_t srclen, - void *dest, size_t destlen) + void *dest, size_t destlen, size_t *converted_size, + bool allow_badcharcnv) { size_t i_len, o_len; size_t retval; @@ -248,6 +249,11 @@ _PUBLIC_ ssize_t convert_string_convenience(struct smb_iconv_convenience *ic, char* outbuf = (char*)dest; smb_iconv_t descriptor; + if (allow_badcharcnv) { + /* Not implemented yet */ + return false; + } + if (srclen == (size_t)-1) srclen = strlen(inbuf)+1; @@ -257,7 +263,8 @@ _PUBLIC_ ssize_t convert_string_convenience(struct smb_iconv_convenience *ic, /* conversion not supported, use as is */ size_t len = MIN(srclen,destlen); memcpy(dest,src,len); - return len; + *converted_size = len; + return true; } i_len=srclen; @@ -268,7 +275,7 @@ _PUBLIC_ ssize_t convert_string_convenience(struct smb_iconv_convenience *ic, switch(errno) { case EINVAL: reason="Incomplete multibyte sequence"; - return -1; + return false; case E2BIG: reason="No more room"; if (from == CH_UNIX) { @@ -281,14 +288,16 @@ _PUBLIC_ ssize_t convert_string_convenience(struct smb_iconv_convenience *ic, charset_name(ic, from), charset_name(ic, to), (int)srclen, (int)destlen)); } - return -1; + return false; case EILSEQ: reason="Illegal multibyte sequence"; - return -1; + return false; } /* smb_panic(reason); */ } - return destlen-o_len; + if (converted_size != NULL) + *converted_size = destlen-o_len; + return true; } /** @@ -301,18 +310,23 @@ _PUBLIC_ ssize_t convert_string_convenience(struct smb_iconv_convenience *ic, * @returns Size in bytes of the converted string; or -1 in case of error. **/ -_PUBLIC_ ssize_t convert_string_talloc_convenience(TALLOC_CTX *ctx, +_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) + void **dest, size_t *converted_size, + bool allow_badcharcnv) { smb_iconv_t descriptor; + ssize_t ret; + + if (allow_badcharcnv) + return false; /* Not implemented yet */ *dest = NULL; if (src == NULL || srclen == (size_t)-1 || srclen == 0) - return (size_t)-1; + return false; descriptor = get_conv_handle(ic, from, to); @@ -321,10 +335,15 @@ _PUBLIC_ ssize_t convert_string_talloc_convenience(TALLOC_CTX *ctx, DEBUG(3, ("convert_string_talloc: conversion from %s to %s not supported!\n", charset_name(ic, from), charset_name(ic, to))); - return -1; + return false; } - return iconv_talloc(ctx, descriptor, src, srclen, dest); + ret = iconv_talloc(ctx, descriptor, src, srclen, dest); + if (ret == -1) + return false; + if (converted_size != NULL) + *converted_size = ret; + return true; } /* diff --git a/lib/util/charset/charset.h b/lib/util/charset/charset.h index f027beb8db..655bae7bcd 100644 --- a/lib/util/charset/charset.h +++ b/lib/util/charset/charset.h @@ -28,9 +28,16 @@ #include <talloc.h> /* this defines the charset types used in samba */ -typedef enum {CH_UTF16=0, CH_UNIX, CH_DOS, CH_UTF8, CH_UTF16BE, CH_UTF16MUNGED} charset_t; +typedef enum {CH_UTF16LE=0, CH_UTF16=0, CH_UNIX, CH_DISPLAY, CH_DOS, CH_UTF8, CH_UTF16BE, CH_UTF16MUNGED} charset_t; -#define NUM_CHARSETS 6 +#define NUM_CHARSETS 7 + +/* + * SMB UCS2 (16-bit unicode) internal type. + * smb_ucs2_t is *always* in little endian format. + */ + +typedef uint16_t smb_ucs2_t; /* * for each charset we have a function that pulls from that charset to @@ -51,6 +58,17 @@ typedef uint32_t codepoint_t; #define INVALID_CODEPOINT ((codepoint_t)-1) +/* + * This is auxiliary struct used by source/script/gen-8-bit-gap.sh script + * during generation of an encoding table for charset module + * */ + +struct charset_gap_table { + uint16_t start; + uint16_t end; + int32_t idx; +}; + /* generic iconv conversion structure */ typedef struct smb_iconv_s { @@ -61,6 +79,7 @@ typedef struct smb_iconv_s { size_t (*push)(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); void *cd_direct, *cd_pull, *cd_push; + char *from_name, *to_name; } *smb_iconv_t; /* string manipulation flags */ @@ -105,23 +124,24 @@ bool strhaslower(const char *string); char *strrchr_m(const char *s, char c); char *strchr_m(const char *s, char c); -ssize_t push_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src); -ssize_t push_ucs2_talloc(TALLOC_CTX *ctx, void **dest, const char *src); -ssize_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src); -ssize_t pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src); -ssize_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const void *src); -ssize_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src); +bool push_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size); +bool push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src, size_t *converted_size); +bool push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size); +bool pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size); +bool pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src, size_t *converted_size); +bool pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size); ssize_t push_string(void *dest, const char *src, size_t dest_len, int flags); ssize_t pull_string(char *dest, const void *src, size_t dest_len, size_t src_len, int flags); -ssize_t convert_string_talloc(TALLOC_CTX *ctx, +bool convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, void const *src, size_t srclen, - void **dest); + void **dest, size_t *converted_size, + bool allow_badcharcnv); -ssize_t convert_string(charset_t from, charset_t to, +size_t convert_string(charset_t from, charset_t to, void const *src, size_t srclen, - void *dest, size_t destlen); + void *dest, size_t destlen, bool allow_badcharcnv); ssize_t iconv_talloc(TALLOC_CTX *mem_ctx, smb_iconv_t cd, @@ -147,15 +167,16 @@ struct smb_iconv_convenience *smb_iconv_convenience_init(TALLOC_CTX *mem_ctx, const char *unix_charset, bool native_iconv); -ssize_t convert_string_convenience(struct smb_iconv_convenience *ic, +bool convert_string_convenience(struct smb_iconv_convenience *ic, charset_t from, charset_t to, void const *src, size_t srclen, - void *dest, size_t destlen); -ssize_t convert_string_talloc_convenience(TALLOC_CTX *ctx, + void *dest, size_t destlen, size_t *converted_size, + bool allow_badcharcnv); +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); + 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); @@ -168,4 +189,81 @@ smb_iconv_t smb_iconv_open_ex(TALLOC_CTX *mem_ctx, const char *tocode, void load_case_tables(void); bool charset_register_backend(const void *_funcs); +/* + * Define stub for charset module which implements 8-bit encoding with gaps. + * Encoding tables for such module should be produced from glibc's CHARMAPs + * using script source/script/gen-8bit-gap.sh + * CHARSETNAME is CAPITALIZED charset name + * + * */ +#define SMB_GENERATE_CHARSET_MODULE_8_BIT_GAP(CHARSETNAME) \ +static size_t CHARSETNAME ## _push(void *cd, const char **inbuf, size_t *inbytesleft, \ + char **outbuf, size_t *outbytesleft) \ +{ \ + while (*inbytesleft >= 2 && *outbytesleft >= 1) { \ + int i; \ + int done = 0; \ + \ + uint16 ch = SVAL(*inbuf,0); \ + \ + for (i=0; from_idx[i].start != 0xffff; i++) { \ + if ((from_idx[i].start <= ch) && (from_idx[i].end >= ch)) { \ + ((unsigned char*)(*outbuf))[0] = from_ucs2[from_idx[i].idx+ch]; \ + (*inbytesleft) -= 2; \ + (*outbytesleft) -= 1; \ + (*inbuf) += 2; \ + (*outbuf) += 1; \ + done = 1; \ + break; \ + } \ + } \ + if (!done) { \ + errno = EINVAL; \ + return -1; \ + } \ + \ + } \ + \ + if (*inbytesleft == 1) { \ + errno = EINVAL; \ + return -1; \ + } \ + \ + if (*inbytesleft > 1) { \ + errno = E2BIG; \ + return -1; \ + } \ + \ + return 0; \ +} \ + \ +static size_t CHARSETNAME ## _pull(void *cd, const char **inbuf, size_t *inbytesleft, \ + char **outbuf, size_t *outbytesleft) \ +{ \ + while (*inbytesleft >= 1 && *outbytesleft >= 2) { \ + *(uint16*)(*outbuf) = to_ucs2[((unsigned char*)(*inbuf))[0]]; \ + (*inbytesleft) -= 1; \ + (*outbytesleft) -= 2; \ + (*inbuf) += 1; \ + (*outbuf) += 2; \ + } \ + \ + if (*inbytesleft > 0) { \ + errno = E2BIG; \ + return -1; \ + } \ + \ + return 0; \ +} \ + \ +struct charset_functions CHARSETNAME ## _functions = \ + {#CHARSETNAME, CHARSETNAME ## _pull, CHARSETNAME ## _push}; \ + \ +NTSTATUS charset_ ## CHARSETNAME ## _init(void); \ +NTSTATUS charset_ ## CHARSETNAME ## _init(void) \ +{ \ + return smb_register_charset(& CHARSETNAME ## _functions); \ +} \ + + #endif /* __CHARSET_H__ */ diff --git a/lib/util/charset/iconv.c b/lib/util/charset/iconv.c index b6842a49aa..9825e4be01 100644 --- a/lib/util/charset/iconv.c +++ b/lib/util/charset/iconv.c @@ -22,6 +22,7 @@ #include "../lib/util/dlinklist.h" #include "system/iconv.h" #include "system/filesys.h" +#undef strcasecmp /** @@ -49,6 +50,7 @@ static size_t ascii_pull (void *,const char **, size_t *, char **, size_t *); static size_t ascii_push (void *,const char **, size_t *, char **, size_t *); +static size_t latin1_push (void *,const char **, size_t *, char **, size_t *); static size_t utf8_pull (void *,const char **, size_t *, char **, size_t *); static size_t utf8_push (void *,const char **, size_t *, char **, size_t *); static size_t utf16_munged_pull(void *,const char **, size_t *, char **, size_t *); @@ -72,6 +74,8 @@ static const struct charset_functions builtin_functions[] = { {"UTF16_MUNGED", utf16_munged_pull, iconv_copy}, {"ASCII", ascii_pull, ascii_push}, + {"646", ascii_pull, ascii_push}, + {"ISO-8859-1", ascii_pull, latin1_push}, {"UCS2-HEX", ucs2hex_pull, ucs2hex_push} }; @@ -340,6 +344,32 @@ static size_t ascii_push(void *cd, const char **inbuf, size_t *inbytesleft, return ir_count; } +static size_t latin1_push(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + int ir_count=0; + + while (*inbytesleft >= 2 && *outbytesleft >= 1) { + (*outbuf)[0] = (*inbuf)[0]; + if ((*inbuf)[1]) ir_count++; + (*inbytesleft) -= 2; + (*outbytesleft) -= 1; + (*inbuf) += 2; + (*outbuf) += 1; + } + + if (*inbytesleft == 1) { + errno = EINVAL; + return -1; + } + + if (*inbytesleft > 1) { + errno = E2BIG; + return -1; + } + + return ir_count; +} static size_t ucs2hex_pull(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) diff --git a/lib/util/charset/tests/iconv.c b/lib/util/charset/tests/iconv.c index 1facea6136..091876f63b 100644 --- a/lib/util/charset/tests/iconv.c +++ b/lib/util/charset/tests/iconv.c @@ -404,12 +404,12 @@ static bool test_string2key(struct torture_context *tctx) uint16_t *buf; char *dest = NULL; TALLOC_CTX *mem_ctx = talloc_new(tctx); - ssize_t ret; size_t len = (random()%1000)+1; const uint16_t in1[10] = { 'a', 0xd805, 'b', 0xdcf0, 'c', 0, 'd', 'e', 'f', 'g' }; uint8_t le1[20]; uint8_t *munged1; uint8_t *out1; + size_t ret; int i; const char *correct = "a\357\277\275b\357\277\275c\001defg"; @@ -418,8 +418,7 @@ static bool test_string2key(struct torture_context *tctx) torture_comment(tctx, "converting random buffer\n"); - ret = convert_string_talloc(mem_ctx, CH_UTF16MUNGED, CH_UTF8, (void *)buf, len*2, (void**)&dest); - if (ret == -1) { + if (!convert_string_talloc(mem_ctx, CH_UTF16MUNGED, CH_UTF8, (void *)buf, len*2, (void**)&dest, &ret, false)) { torture_fail(tctx, "Failed to convert random buffer\n"); } @@ -429,8 +428,7 @@ static bool test_string2key(struct torture_context *tctx) torture_comment(tctx, "converting fixed buffer to UTF16\n"); - ret = convert_string_talloc(mem_ctx, CH_UTF16MUNGED, CH_UTF16, (void *)le1, 20, (void**)&munged1); - if (ret == -1) { + if (!convert_string_talloc(mem_ctx, CH_UTF16MUNGED, CH_UTF16, (void *)le1, 20, (void**)&munged1, &ret, false)) { torture_fail(tctx, "Failed to convert fixed buffer to UTF16_MUNGED\n"); } @@ -438,8 +436,7 @@ static bool test_string2key(struct torture_context *tctx) torture_comment(tctx, "converting fixed buffer to UTF8\n"); - ret = convert_string_talloc(mem_ctx, CH_UTF16MUNGED, CH_UTF8, (void *)le1, 20, (void**)&out1); - if (ret == -1) { + if (!convert_string_talloc(mem_ctx, CH_UTF16MUNGED, CH_UTF8, (void *)le1, 20, (void**)&out1, &ret, false)) { torture_fail(tctx, "Failed to convert fixed buffer to UTF8\n"); } diff --git a/lib/util/charset/util_unistr.c b/lib/util/charset/util_unistr.c index 41b9c94cbb..ec88e784d0 100644 --- a/lib/util/charset/util_unistr.c +++ b/lib/util/charset/util_unistr.c @@ -656,7 +656,7 @@ static ssize_t push_ascii(void *dest, const char *src, size_t dest_len, int flag if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) src_len++; - return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len); + return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len, false); } /** @@ -668,11 +668,11 @@ static ssize_t push_ascii(void *dest, const char *src, size_t dest_len, int flag * @returns The number of bytes occupied by the string in the destination * or -1 in case of error. **/ -_PUBLIC_ ssize_t push_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src) +_PUBLIC_ bool push_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size) { size_t src_len = strlen(src)+1; *dest = NULL; - return convert_string_talloc(ctx, CH_UNIX, CH_DOS, src, src_len, (void **)dest); + return convert_string_talloc(ctx, CH_UNIX, CH_DOS, src, src_len, (void **)dest, converted_size, false); } @@ -706,7 +706,7 @@ static ssize_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t s } } - ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len); + ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len, false); if (dest_len) dest[MIN(ret, dest_len-1)] = 0; @@ -759,7 +759,7 @@ static ssize_t push_ucs2(void *dest, const char *src, size_t dest_len, int flags /* ucs2 is always a multiple of 2 bytes */ dest_len &= ~1; - ret = convert_string(CH_UNIX, CH_UTF16, src, src_len, dest, dest_len); + ret = convert_string(CH_UNIX, CH_UTF16, src, src_len, dest, dest_len, false); if (ret == (size_t)-1) { return 0; } @@ -779,11 +779,11 @@ static ssize_t push_ucs2(void *dest, const char *src, size_t dest_len, int flags * @returns The number of bytes occupied by the string in the destination * or -1 in case of error. **/ -_PUBLIC_ ssize_t push_ucs2_talloc(TALLOC_CTX *ctx, void **dest, const char *src) +_PUBLIC_ bool push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src, size_t *converted_size) { size_t src_len = strlen(src)+1; *dest = NULL; - return convert_string_talloc(ctx, CH_UNIX, CH_UTF16, src, src_len, dest); + return convert_string_talloc(ctx, CH_UNIX, CH_UTF16, src, src_len, (void **)dest, converted_size, false); } @@ -795,11 +795,11 @@ _PUBLIC_ ssize_t push_ucs2_talloc(TALLOC_CTX *ctx, void **dest, const char *src) * @returns The number of bytes occupied by the string in the destination **/ -_PUBLIC_ ssize_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src) +_PUBLIC_ bool push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size) { size_t src_len = strlen(src)+1; *dest = NULL; - return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void **)dest); + return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void **)dest, converted_size, false); } /** @@ -835,7 +835,7 @@ static size_t pull_ucs2(char *dest, const void *src, size_t dest_len, size_t src if (src_len != (size_t)-1) src_len &= ~1; - ret = convert_string(CH_UTF16, CH_UNIX, src, src_len, dest, dest_len); + ret = convert_string(CH_UTF16, CH_UNIX, src, src_len, dest, dest_len, false); if (dest_len) dest[MIN(ret, dest_len-1)] = 0; @@ -850,11 +850,11 @@ static size_t pull_ucs2(char *dest, const void *src, size_t dest_len, size_t src * @returns The number of bytes occupied by the string in the destination **/ -_PUBLIC_ ssize_t pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src) +_PUBLIC_ bool pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size) { size_t src_len = strlen(src)+1; *dest = NULL; - return convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, (void **)dest); + return convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, (void **)dest, converted_size, false); } /** @@ -865,11 +865,11 @@ _PUBLIC_ ssize_t pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src * @returns The number of bytes occupied by the string in the destination **/ -_PUBLIC_ ssize_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const void *src) +_PUBLIC_ bool pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src, size_t *converted_size) { size_t src_len = utf16_len(src); *dest = NULL; - return convert_string_talloc(ctx, CH_UTF16, CH_UNIX, src, src_len, (void **)dest); + return convert_string_talloc(ctx, CH_UTF16, CH_UNIX, src, src_len, (void **)dest, converted_size, false); } /** @@ -880,11 +880,11 @@ _PUBLIC_ ssize_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const void *src) * @returns The number of bytes occupied by the string in the destination **/ -_PUBLIC_ ssize_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src) +_PUBLIC_ bool pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size) { size_t src_len = strlen(src)+1; *dest = NULL; - return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest); + return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest, converted_size, false); } /** @@ -950,13 +950,18 @@ _PUBLIC_ ssize_t pull_string(char *dest, const void *src, size_t dest_len, size_ * @param destlen maximal length allowed for string * @returns the number of bytes occupied in the destination **/ -_PUBLIC_ ssize_t convert_string(charset_t from, charset_t to, +_PUBLIC_ size_t convert_string(charset_t from, charset_t to, void const *src, size_t srclen, - void *dest, size_t destlen) + void *dest, size_t destlen, + bool allow_badcharcnv) { - return convert_string_convenience(get_iconv_convenience(), from, to, + size_t ret; + if (!convert_string_convenience(get_iconv_convenience(), from, to, src, srclen, - dest, destlen); + dest, destlen, &ret, + allow_badcharcnv)) + return -1; + return ret; } /** @@ -964,18 +969,22 @@ _PUBLIC_ ssize_t convert_string(charset_t from, charset_t to, * * @param srclen length of source buffer. * @param dest always set at least to NULL + * @param converted_size Size in bytes of the converted string * @note -1 is not accepted for srclen. * - * @returns Size in bytes of the converted string; or -1 in case of error. + * @returns boolean indication whether the conversion succeeded **/ -_PUBLIC_ ssize_t convert_string_talloc(TALLOC_CTX *ctx, +_PUBLIC_ bool convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, void const *src, size_t srclen, - void **dest) + void **dest, size_t *converted_size, + bool allow_badcharcnv) { return convert_string_talloc_convenience(ctx, get_iconv_convenience(), - from, to, src, srclen, dest); + from, to, src, srclen, dest, + converted_size, + allow_badcharcnv); } diff --git a/lib/util/tevent_ntstatus.c b/lib/util/tevent_ntstatus.c new file mode 100644 index 0000000000..1a34e9c749 --- /dev/null +++ b/lib/util/tevent_ntstatus.c @@ -0,0 +1,51 @@ +/* + 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_ntstatus.h" +#include "../replace/replace.h" + +bool tevent_req_nterror(struct tevent_req *req, NTSTATUS status) +{ + return tevent_req_error(req, NT_STATUS_V(status)); +} + +bool tevent_req_is_nterror(struct tevent_req *req, NTSTATUS *status) +{ + 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: + *status = NT_STATUS_IO_TIMEOUT; + break; + case TEVENT_REQ_NO_MEMORY: + *status = NT_STATUS_NO_MEMORY; + break; + case TEVENT_REQ_USER_ERROR: + *status = NT_STATUS(err); + break; + default: + *status = NT_STATUS_INTERNAL_ERROR; + break; + } + return true; +} diff --git a/lib/util/tevent_ntstatus.h b/lib/util/tevent_ntstatus.h new file mode 100644 index 0000000000..84c275fb13 --- /dev/null +++ b/lib/util/tevent_ntstatus.h @@ -0,0 +1,32 @@ +/* + 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_NTSTATUS_H +#define _TEVENT_NTSTATUS_H + +#include <stdint.h> +#include <stdbool.h> +#include "config.h" +#include "../libcli/util/ntstatus.h" +#include "../tevent/tevent.h" + +bool tevent_req_nterror(struct tevent_req *req, NTSTATUS status); +bool tevent_req_is_nterror(struct tevent_req *req, NTSTATUS *pstatus); + +#endif diff --git a/lib/util/util.c b/lib/util/util.c index 988d8f9fa0..0148bdb00d 100644 --- a/lib/util/util.c +++ b/lib/util/util.c @@ -541,21 +541,6 @@ void *malloc_array(size_t el_size, unsigned int count) return realloc_array(NULL, el_size, count, false); } -_PUBLIC_ void *talloc_check_name_abort(const void *ptr, const char *name) -{ - void *result; - - result = talloc_check_name(ptr, name); - if (result != NULL) - return result; - - DEBUG(0, ("Talloc type mismatch, expected %s, got %s\n", - name, talloc_get_name(ptr))); - smb_panic("talloc type mismatch"); - /* Keep the compiler happy */ - return NULL; -} - /** Trim the specified elements off the front and back of a string. **/ @@ -836,4 +821,104 @@ _PUBLIC_ size_t utf16_len_n(const void *src, size_t n) return len; } +/** + * @file + * @brief String utilities. + **/ + +static bool next_token_internal_talloc(TALLOC_CTX *ctx, + const char **ptr, + char **pp_buff, + const char *sep, + bool ltrim) +{ + char *s; + char *saved_s; + char *pbuf; + bool quoted; + size_t len=1; + + *pp_buff = NULL; + if (!ptr) { + return(false); + } + + s = (char *)*ptr; + + /* default to simple separators */ + if (!sep) { + sep = " \t\n\r"; + } + + /* find the first non sep char, if left-trimming is requested */ + if (ltrim) { + while (*s && strchr_m(sep,*s)) { + s++; + } + } + + /* nothing left? */ + if (!*s) { + return false; + } + + /* When restarting we need to go from here. */ + saved_s = s; + + /* Work out the length needed. */ + for (quoted = false; *s && + (quoted || !strchr_m(sep,*s)); s++) { + if (*s == '\"') { + quoted = !quoted; + } else { + len++; + } + } + + /* We started with len = 1 so we have space for the nul. */ + *pp_buff = talloc_array(ctx, char, len); + if (!*pp_buff) { + return false; + } + + /* copy over the token */ + pbuf = *pp_buff; + s = saved_s; + for (quoted = false; *s && + (quoted || !strchr_m(sep,*s)); s++) { + if ( *s == '\"' ) { + quoted = !quoted; + } else { + *pbuf++ = *s; + } + } + + *ptr = (*s) ? s+1 : s; + *pbuf = 0; + + return true; +} + +bool next_token_talloc(TALLOC_CTX *ctx, + const char **ptr, + char **pp_buff, + const char *sep) +{ + return next_token_internal_talloc(ctx, ptr, pp_buff, sep, true); +} + +/* + * Get the next token from a string, return false if none found. Handles + * double-quotes. This version does not trim leading separator characters + * before looking for a token. + */ + +bool next_token_no_ltrim_talloc(TALLOC_CTX *ctx, + const char **ptr, + char **pp_buff, + const char *sep) +{ + return next_token_internal_talloc(ctx, ptr, pp_buff, sep, false); +} + diff --git a/lib/util/util.h b/lib/util/util.h index 27f94cd685..defef127d9 100644 --- a/lib/util/util.h +++ b/lib/util/util.h @@ -204,6 +204,21 @@ _PUBLIC_ void display_set_stderr(void); /* The following definitions come from lib/util/util_str.c */ +bool next_token_talloc(TALLOC_CTX *ctx, + const char **ptr, + char **pp_buff, + const char *sep); + +/** + * Get the next token from a string, return false if none found. Handles + * double-quotes. This version does not trim leading separator characters + * before looking for a token. + */ +bool next_token_no_ltrim_talloc(TALLOC_CTX *ctx, + const char **ptr, + char **pp_buff, + const char *sep); + /** Trim the specified elements off the front and back of a string. @@ -752,13 +767,6 @@ bool pm_process( const char *fileName, bool (*pfunc)(const char *, const char *, void *), void *userdata); -/** - * Add-on to talloc_get_type - */ -_PUBLIC_ void *talloc_check_name_abort(const void *ptr, const char *name); -#define talloc_get_type_abort(ptr, type) \ - (type *)talloc_check_name_abort(ptr, #type) - bool unmap_file(void *start, size_t size); void print_asc(int level, const uint8_t *buf,int len); |