summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/async_req/async_sock.c355
-rw-r--r--lib/async_req/async_sock.h11
-rw-r--r--lib/replace/system/network.h6
-rw-r--r--lib/smbconf/smbconf.c43
-rw-r--r--lib/smbconf/smbconf.h4
-rw-r--r--lib/smbconf/smbconf_private.h3
-rw-r--r--lib/smbconf/smbconf_txt.c17
-rw-r--r--lib/socket_wrapper/socket_wrapper.c569
-rw-r--r--lib/talloc/configure.ac2
-rw-r--r--lib/talloc/talloc.c24
-rw-r--r--lib/talloc/talloc.h2
-rw-r--r--lib/tdb/common/open.c5
-rw-r--r--lib/tevent/libtevent.m42
-rw-r--r--lib/tevent/pytevent.c4
-rw-r--r--lib/tevent/tevent.h124
-rw-r--r--lib/tevent/tevent_internal.h93
-rw-r--r--lib/tevent/tevent_queue.c198
-rw-r--r--lib/tevent/tevent_req.c84
-rw-r--r--lib/torture/config.mk4
-rw-r--r--lib/util/charset/charcnv.c45
-rw-r--r--lib/util/charset/charset.h130
-rw-r--r--lib/util/charset/iconv.c30
-rw-r--r--lib/util/charset/tests/iconv.c11
-rw-r--r--lib/util/charset/util_unistr.c57
-rw-r--r--lib/util/tevent_ntstatus.c51
-rw-r--r--lib/util/tevent_ntstatus.h32
-rw-r--r--lib/util/util.c115
-rw-r--r--lib/util/util.h22
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);