From 4d82f69f884c0c9105d7c1cc53a1235e26222fbc Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Wed, 31 Dec 2008 21:24:25 -0800 Subject: s3: Fix caller of print_fsp_open --- source3/modules/onefs_open.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3') diff --git a/source3/modules/onefs_open.c b/source3/modules/onefs_open.c index a4a317d905..a86d39948d 100644 --- a/source3/modules/onefs_open.c +++ b/source3/modules/onefs_open.c @@ -1,8 +1,8 @@ /* * Unix SMB/CIFS implementation. * - * This file began with some code from source3/smbd/open.c and modified it to - * work with ifs_createfile. + * This file began with some code from source3/smbd/open.c and has been + * modified it work with ifs_createfile. * * ifs_createfile is a CIFS-specific syscall for opening/files and * directories. It adds support for: @@ -459,7 +459,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, DEBUG(10, ("onefs_open_file_ntcreate: printer open fname=%s\n", fname)); - return print_fsp_open(req, conn, fname, req->vuid, fsp); + return print_fsp_open(req, conn, fname, req->vuid, fsp, psbuf); } if (!parent_dirname(talloc_tos(), fname, &parent_dir, &newname)) { -- cgit From 74ea79cb8fa42b1bc13ac2bd9450beb13ad1cd5e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 1 Jan 2009 13:28:38 +0100 Subject: The Tru64 shell doesn't like (*) in a case statement --- source3/autogen.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/autogen.sh b/source3/autogen.sh index 61316a8f70..1a33eb22cc 100755 --- a/source3/autogen.sh +++ b/source3/autogen.sh @@ -4,11 +4,11 @@ while true; do case $1 in - (--version-file) + --version-file) VERSION_FILE=$2 shift 2 ;; - (*) + *) break ;; esac -- cgit From e551f43b4b690d92cbf00a510e6c79a497d91464 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 1 Jan 2009 18:16:42 +0100 Subject: Remove two pointless globals --- source3/lib/ldb/tools/ldbadd.c | 13 ++++++------- source3/lib/ldb/tools/ldbmodify.c | 12 ++++++------ 2 files changed, 12 insertions(+), 13 deletions(-) (limited to 'source3') diff --git a/source3/lib/ldb/tools/ldbadd.c b/source3/lib/ldb/tools/ldbadd.c index 4dde2a1ef5..155395e065 100644 --- a/source3/lib/ldb/tools/ldbadd.c +++ b/source3/lib/ldb/tools/ldbadd.c @@ -35,8 +35,6 @@ #include "ldb/include/includes.h" #include "ldb/tools/cmdline.h" -static int failures; - static void usage(void) { printf("Usage: ldbadd \n"); @@ -53,7 +51,8 @@ static void usage(void) /* add records from an opened file */ -static int process_file(struct ldb_context *ldb, FILE *f, int *count) +static int process_file(struct ldb_context *ldb, FILE *f, int *count, + int *failures) { struct ldb_ldif *ldif; int ret = LDB_SUCCESS; @@ -71,7 +70,7 @@ static int process_file(struct ldb_context *ldb, FILE *f, int *count) if (ret != LDB_SUCCESS) { fprintf(stderr, "ERR: \"%s\" on DN %s\n", ldb_errstring(ldb), ldb_dn_linearize(ldb, ldif->msg->dn)); - failures++; + (*failures)++; } else { (*count)++; } @@ -86,7 +85,7 @@ static int process_file(struct ldb_context *ldb, FILE *f, int *count) int main(int argc, const char **argv) { struct ldb_context *ldb; - int i, ret=0, count=0; + int i, ret=0, count=0, failures=0; struct ldb_cmdline *options; ldb_global_init(); @@ -96,7 +95,7 @@ int main(int argc, const char **argv) options = ldb_cmdline_process(ldb, argc, argv, usage); if (options->argc == 0) { - ret = process_file(ldb, stdin, &count); + ret = process_file(ldb, stdin, &count, &failures); } else { for (i=0;iargc;i++) { const char *fname = options->argv[i]; @@ -106,7 +105,7 @@ int main(int argc, const char **argv) perror(fname); exit(1); } - ret = process_file(ldb, f, &count); + ret = process_file(ldb, f, &count, &failures); fclose(f); } } diff --git a/source3/lib/ldb/tools/ldbmodify.c b/source3/lib/ldb/tools/ldbmodify.c index 368b4cf996..f12387a8f6 100644 --- a/source3/lib/ldb/tools/ldbmodify.c +++ b/source3/lib/ldb/tools/ldbmodify.c @@ -35,8 +35,6 @@ #include "ldb/include/includes.h" #include "ldb/tools/cmdline.h" -static int failures; - static void usage(void) { printf("Usage: ldbmodify \n"); @@ -52,7 +50,8 @@ static void usage(void) /* process modifies for one file */ -static int process_file(struct ldb_context *ldb, FILE *f, int *count) +static int process_file(struct ldb_context *ldb, FILE *f, int *count, + int *failures) { struct ldb_ldif *ldif; int ret = LDB_SUCCESS; @@ -73,7 +72,7 @@ static int process_file(struct ldb_context *ldb, FILE *f, int *count) if (ret != LDB_SUCCESS) { fprintf(stderr, "ERR: \"%s\" on DN %s\n", ldb_errstring(ldb), ldb_dn_linearize(ldb, ldif->msg->dn)); - failures++; + (*failures)++; } else { (*count)++; } @@ -87,6 +86,7 @@ int main(int argc, const char **argv) { struct ldb_context *ldb; int count=0; + int failures=0; int i, ret=LDB_SUCCESS; struct ldb_cmdline *options; @@ -97,7 +97,7 @@ int main(int argc, const char **argv) options = ldb_cmdline_process(ldb, argc, argv, usage); if (options->argc == 0) { - ret = process_file(ldb, stdin, &count); + ret = process_file(ldb, stdin, &count, &failures); } else { for (i=0;iargc;i++) { const char *fname = options->argv[i]; @@ -107,7 +107,7 @@ int main(int argc, const char **argv) perror(fname); exit(1); } - ret = process_file(ldb, f, &count); + ret = process_file(ldb, f, &count, &failures); } } -- cgit From bf34e998f967a2e9c3528b61a825569378b480af Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 1 Jan 2009 19:47:40 +0100 Subject: fix some nonempty blank lines --- source3/libsmb/smb_share_modes.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3') diff --git a/source3/libsmb/smb_share_modes.c b/source3/libsmb/smb_share_modes.c index 16b3b10925..7d363f5d8b 100644 --- a/source3/libsmb/smb_share_modes.c +++ b/source3/libsmb/smb_share_modes.c @@ -1,7 +1,7 @@ /* Samba share mode database library external interface library. Used by non-Samba products needing access to the Samba share mode db. - + Copyright (C) Jeremy Allison 2005 - 2006 sharemodes_procid functions (C) Copyright (C) Volker Lendecke 2005 @@ -9,17 +9,17 @@ ** NOTE! The following LGPL license applies to this module only. ** 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 . */ @@ -115,7 +115,7 @@ int smb_lock_share_mode_entry(struct smbdb_ctx *db_ctx, { return tdb_chainlock(db_ctx->smb_tdb, get_locking_key(dev, ino)); } - + int smb_unlock_share_mode_entry(struct smbdb_ctx *db_ctx, uint64_t dev, uint64_t ino) -- cgit From 707a5a41b5818b7a59027d16abdce9f57be9cdcd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 1 Jan 2009 19:55:20 +0100 Subject: Remove a global variable --- source3/libsmb/smb_share_modes.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'source3') diff --git a/source3/libsmb/smb_share_modes.c b/source3/libsmb/smb_share_modes.c index 7d363f5d8b..af3f7b0dd5 100644 --- a/source3/libsmb/smb_share_modes.c +++ b/source3/libsmb/smb_share_modes.c @@ -92,16 +92,16 @@ int smb_share_mode_db_close(struct smbdb_ctx *db_ctx) return ret; } -static TDB_DATA get_locking_key(uint64_t dev, uint64_t ino) +static TDB_DATA get_locking_key(struct locking_key *lk, uint64_t dev, + uint64_t ino) { - static struct locking_key lk; TDB_DATA ld; - memset(&lk, '\0', sizeof(struct locking_key)); - lk.dev = (SMB_DEV_T)dev; - lk.inode = (SMB_INO_T)ino; - ld.dptr = (uint8 *)&lk; - ld.dsize = sizeof(lk); + memset(lk, '\0', sizeof(*lk)); + lk->dev = (SMB_DEV_T)dev; + lk->inode = (SMB_INO_T)ino; + ld.dptr = (uint8 *)lk; + ld.dsize = sizeof(*lk); return ld; } @@ -113,14 +113,17 @@ int smb_lock_share_mode_entry(struct smbdb_ctx *db_ctx, uint64_t dev, uint64_t ino) { - return tdb_chainlock(db_ctx->smb_tdb, get_locking_key(dev, ino)); + struct locking_key lk; + return tdb_chainlock(db_ctx->smb_tdb, get_locking_key(&lk, dev, ino)); } int smb_unlock_share_mode_entry(struct smbdb_ctx *db_ctx, uint64_t dev, uint64_t ino) { - return tdb_chainunlock(db_ctx->smb_tdb, get_locking_key(dev, ino)); + struct locking_key lk; + return tdb_chainunlock(db_ctx->smb_tdb, + get_locking_key(&lk, dev, ino)); } /* @@ -172,6 +175,7 @@ int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx, struct smb_share_mode_entry **pp_list, unsigned char *p_delete_on_close) { + struct locking_key lk; TDB_DATA db_data; struct smb_share_mode_entry *list = NULL; int num_share_modes = 0; @@ -183,7 +187,7 @@ int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx, *pp_list = NULL; *p_delete_on_close = 0; - db_data = tdb_fetch(db_ctx->smb_tdb, get_locking_key(dev, ino)); + db_data = tdb_fetch(db_ctx->smb_tdb, get_locking_key(&lk, dev, ino)); if (!db_data.dptr) { return 0; } @@ -258,7 +262,8 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx, const char *filename) /* Must be relative utf8 path. */ { TDB_DATA db_data; - TDB_DATA locking_key = get_locking_key(dev, ino); + struct locking_key lk; + TDB_DATA locking_key = get_locking_key(&lk, dev, ino); int orig_num_share_modes = 0; struct locking_data *ld = NULL; /* internal samba db state. */ struct share_mode_entry *shares = NULL; @@ -371,7 +376,8 @@ int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx, const struct smb_share_mode_entry *del_entry) { TDB_DATA db_data; - TDB_DATA locking_key = get_locking_key(dev, ino); + struct locking_key lk; + TDB_DATA locking_key = get_locking_key(&lk, dev, ino); int orig_num_share_modes = 0; struct locking_data *ld = NULL; /* internal samba db state. */ struct share_mode_entry *shares = NULL; @@ -473,7 +479,8 @@ int smb_change_share_mode_entry(struct smbdb_ctx *db_ctx, const struct smb_share_mode_entry *new_entry) { TDB_DATA db_data; - TDB_DATA locking_key = get_locking_key(dev, ino); + struct locking_key lk; + TDB_DATA locking_key = get_locking_key(&lk, dev, ino); int num_share_modes = 0; struct locking_data *ld = NULL; /* internal samba db state. */ struct share_mode_entry *shares = NULL; -- cgit From 7458111ea4cf33b2a093e5edfb3b42ebfdc330c5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 1 Jan 2009 22:05:03 +0100 Subject: Fix bug 5913. Never seen this to be a problem, but it doesn't hurt either :-) --- source3/lib/ldb/include/ldb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/lib/ldb/include/ldb.h b/source3/lib/ldb/include/ldb.h index 0a745742d9..3891c1c6a3 100644 --- a/source3/lib/ldb/include/ldb.h +++ b/source3/lib/ldb/include/ldb.h @@ -991,7 +991,7 @@ int ldb_search(struct ldb_context *ldb, const struct ldb_dn *base, enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_result **res); + const char * const *attrs, struct ldb_result **_res); /* * a useful search function where you can easily define the expression and -- cgit From 8b81e7c7c65f3923aaa7a366733000517b44756e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 2 Jan 2009 09:44:53 +0100 Subject: Happy New Year! metze --- source3/include/smb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/include/smb.h b/source3/include/smb.h index a8a2d98154..3253773903 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -27,7 +27,7 @@ #define _SMB_H /* logged when starting the various Samba daemons */ -#define COPYRIGHT_STARTUP_MESSAGE "Copyright Andrew Tridgell and the Samba Team 1992-2008" +#define COPYRIGHT_STARTUP_MESSAGE "Copyright Andrew Tridgell and the Samba Team 1992-2009" #if defined(LARGE_SMB_OFF_T) -- cgit From c033ea562669a2d28da53b3dbe566cdb7d26d43e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 2 Jan 2009 14:51:06 +0100 Subject: Revert "s3:idmap: Remove passd check from idmap_backends_unixid_to_sid()." This reverts commit 45db33e73262d8e195a46fb96405dfb3dc43d6bc. --- source3/winbindd/idmap.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index 6be55ef03c..38cc0d0c0a 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -735,6 +735,15 @@ NTSTATUS idmap_backends_unixid_to_sid(const char *domname, struct id_map *id) maps[0] = id; maps[1] = NULL; + if (sid_check_is_in_builtin(id->sid) + || (sid_check_is_in_our_domain(id->sid))) { + dom = idmap_init_passdb_domain(NULL); + if (dom == NULL) { + return NT_STATUS_NONE_MAPPED; + } + return dom->methods->unixids_to_sids(dom, maps); + } + dom = idmap_find_domain(domname); if (dom == NULL) { return NT_STATUS_NONE_MAPPED; -- cgit From 13248e8917015435c8979535531484344e3f2262 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 2 Jan 2009 14:51:23 +0100 Subject: Revert "s:Fix uid_to_sid mapping when the idmap cache is empty." This reverts commit 9a9b64dbdfce4414ada22d4f882c8c757b5813e1. --- source3/winbindd/idmap.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'source3') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index 38cc0d0c0a..aaba7e53ee 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -735,13 +735,14 @@ NTSTATUS idmap_backends_unixid_to_sid(const char *domname, struct id_map *id) maps[0] = id; maps[1] = NULL; - if (sid_check_is_in_builtin(id->sid) - || (sid_check_is_in_our_domain(id->sid))) { - dom = idmap_init_passdb_domain(NULL); - if (dom == NULL) { - return NT_STATUS_NONE_MAPPED; - } - return dom->methods->unixids_to_sids(dom, maps); + /* + * Always give passdb a chance first + */ + + dom = idmap_init_passdb_domain(NULL); + if ((dom != NULL) + && NT_STATUS_IS_OK(dom->methods->unixids_to_sids(dom, maps))) { + return NT_STATUS_OK; } dom = idmap_find_domain(domname); -- cgit From 76d53e7648869bbdc83be1e07941467019b96321 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 2 Jan 2009 14:53:26 +0100 Subject: Alternative fix for 45db33e73 and 0d443ae7931 Simo is right, we need to ask passdb first. At least this fixes a nasty to find NT_STATUS_ACCESS_DENIED problem in the build farm for the test run I just did on host "opi". Michael, can you re-check if this also fixes the error you found, leading to the two fixes? Thanks, Volker --- source3/winbindd/idmap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index aaba7e53ee..ca07f230ab 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -741,7 +741,8 @@ NTSTATUS idmap_backends_unixid_to_sid(const char *domname, struct id_map *id) dom = idmap_init_passdb_domain(NULL); if ((dom != NULL) - && NT_STATUS_IS_OK(dom->methods->unixids_to_sids(dom, maps))) { + && NT_STATUS_IS_OK(dom->methods->unixids_to_sids(dom, maps)) + && id->status == ID_MAPPED) { return NT_STATUS_OK; } -- cgit From 2234173220c51c2e37818149ddf41421672904c0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 2 Jan 2009 11:38:24 -0800 Subject: Fix warnings in make test code. Jeremy. --- source3/torture/nbio.c | 19 +++++++++++++++---- source3/torture/torture.c | 18 ++++++++++++++---- source3/torture/utable.c | 6 +++++- 3 files changed, 34 insertions(+), 9 deletions(-) (limited to 'source3') diff --git a/source3/torture/nbio.c b/source3/torture/nbio.c index 81d0eb816b..a010c80985 100644 --- a/source3/torture/nbio.c +++ b/source3/torture/nbio.c @@ -111,7 +111,9 @@ static void sigsegv(int sig) printf("segv at line %d\n", line_count); slprintf(line, sizeof(line), "/usr/X11R6/bin/xterm -e gdb /proc/%d/exe %d", (int)getpid(), (int)getpid()); - system(line); + if (system(line) == -1) { + printf("system() failed\n"); + } exit(1); } @@ -280,10 +282,16 @@ static void delete_fn(const char *mnt, file_info *finfo, const char *name, void n = SMB_STRDUP(name); n[strlen(n)-1] = 0; - asprintf(&s, "%s%s", n, finfo->name); + if (asprintf(&s, "%s%s", n, finfo->name) == -1) { + printf("asprintf failed\n"); + return; + } if (finfo->mode & aDIR) { char *s2; - asprintf(&s2, "%s\\*", s); + if (asprintf(&s2, "%s\\*", s) == -1) { + printf("asprintf failed\n"); + return; + } cli_list(c, s2, aDIR, delete_fn, NULL); nb_rmdir(s); } else { @@ -297,7 +305,10 @@ static void delete_fn(const char *mnt, file_info *finfo, const char *name, void void nb_deltree(const char *dname) { char *mask; - asprintf(&mask, "%s\\*", dname); + if (asprintf(&mask, "%s\\*", dname) == -1) { + printf("asprintf failed\n"); + return; + } total_deleted = 0; cli_list(c, mask, aDIR, delete_fn, NULL); diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 63942da2e5..3261e78d44 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -1213,7 +1213,9 @@ static bool run_tcon2_test(int dummy) printf("starting tcon2 test\n"); - asprintf(&service, "\\\\%s\\%s", host, share); + if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) { + return false; + } status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum); @@ -5280,8 +5282,13 @@ static bool run_local_rbtree(int dummy) for (i=0; i<1000; i++) { char *key, *value; - asprintf(&key, "key%ld", random()); - asprintf(&value, "value%ld", random()); + if (asprintf(&key, "key%ld", random()) == -1) { + goto done; + } + if (asprintf(&value, "value%ld", random()) == -1) { + SAFE_FREE(key); + goto done; + } if (!rbt_testval(db, key, value)) { SAFE_FREE(key); @@ -5290,7 +5297,10 @@ static bool run_local_rbtree(int dummy) } SAFE_FREE(value); - asprintf(&value, "value%ld", random()); + if (asprintf(&value, "value%ld", random()) == -1) { + SAFE_FREE(key); + goto done; + } if (!rbt_testval(db, key, value)) { SAFE_FREE(key); diff --git a/source3/torture/utable.c b/source3/torture/utable.c index 7032cea99b..e36b0388c4 100644 --- a/source3/torture/utable.c +++ b/source3/torture/utable.c @@ -84,7 +84,11 @@ bool torture_utable(int dummy) d_printf("Failed to create valid.dat - %s", strerror(errno)); return False; } - write(fd, valid, 0x10000); + if (write(fd, valid, 0x10000) != 0x10000) { + d_printf("Failed to create valid.dat - %s", strerror(errno)); + close(fd); + return false; + } close(fd); d_printf("wrote valid.dat\n"); -- cgit From 3d2d0203e57bacf0cd61cfb72780a4bd9aa42707 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 2 Jan 2009 12:49:49 -0800 Subject: Remove cli_cm_set_dest_ss() - removes the global dest_ss from libsmb/clidfs.c. Keep the '-I
' option in smbclient working. The intent is to remove all globals from libsmb/clidfs.c. Jeremy. --- source3/client/client.c | 13 ++++++++----- source3/libsmb/clidfs.c | 20 +++++--------------- 2 files changed, 13 insertions(+), 20 deletions(-) (limited to 'source3') diff --git a/source3/client/client.c b/source3/client/client.c index c63921aa1a..529f21ab30 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -78,6 +78,7 @@ static bool showacls = false; bool lowercase = false; static struct sockaddr_storage dest_ss; +static char dest_ss_str[INET6_ADDRSTRLEN]; #define SEPARATORS " \t\n\r" @@ -4043,7 +4044,8 @@ static int process_command_string(const char *cmd_in) /* establish the connection if not already */ if (!cli) { - cli = cli_cm_open(talloc_tos(), NULL, desthost, + cli = cli_cm_open(talloc_tos(), NULL, + have_ip ? dest_ss_str : desthost, service, true, smb_encrypt); if (!cli) { return 1; @@ -4508,7 +4510,8 @@ static int process(const char *base_directory) int rc = 0; cli = cli_cm_open(talloc_tos(), NULL, - desthost, service, true, smb_encrypt); + have_ip ? dest_ss_str : desthost, + service, true, smb_encrypt); if (!cli) { return 1; } @@ -4586,7 +4589,8 @@ static int do_tar_op(const char *base_directory) /* do we already have a connection? */ if (!cli) { cli = cli_cm_open(talloc_tos(), NULL, - desthost, service, true, smb_encrypt); + have_ip ? dest_ss_str : desthost, + service, true, smb_encrypt); if (!cli) return 1; } @@ -4792,8 +4796,7 @@ static int do_message_op(struct user_auth_info *auth_info) exit(1); } have_ip = true; - - cli_cm_set_dest_ss(&dest_ss); + print_sockaddr(dest_ss_str, sizeof(dest_ss_str), &dest_ss); } break; case 'E': diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c index 4597e63c98..ac68700fd0 100644 --- a/source3/libsmb/clidfs.c +++ b/source3/libsmb/clidfs.c @@ -54,8 +54,6 @@ static void cm_set_password(const char *newpass); static int port; static int name_type = 0x20; -static bool have_ip; -static struct sockaddr_storage dest_ss; static struct client_connection *connections; @@ -133,8 +131,11 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx, } sharename = servicename; if (*sharename == '\\') { - server = sharename+2; - sharename = strchr_m(server,'\\'); + sharename += 2; + if (server == NULL) { + server = sharename; + } + sharename = strchr_m(sharename,'\\'); if (!sharename) { return NULL; } @@ -151,8 +152,6 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx, again: zero_sockaddr(&ss); - if (have_ip) - ss = dest_ss; /* have to open a new connection */ if (!(c=cli_initialise()) || (cli_set_port(c, port) != port)) { @@ -550,15 +549,6 @@ void cli_cm_set_fallback_after_kerberos(void) cm_creds.fallback_after_kerberos = true; } -/**************************************************************************** -****************************************************************************/ - -void cli_cm_set_dest_ss(struct sockaddr_storage *pss) -{ - dest_ss = *pss; - have_ip = true; -} - /********************************************************************** split a dfs path into the server, share name, and extrapath components **********************************************************************/ -- cgit From aed8c7bfcfb3c860758d39d476ca87ef9eda2b6d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 20 Dec 2008 10:44:29 +0100 Subject: packet.h API: The callback is now responsible to talloc_free() "buf" --- source3/include/packet.h | 6 ++++-- source3/lib/ctdbd_conn.c | 49 +++++++++++++++++++++++++++--------------------- source3/lib/packet.c | 32 +++++++++++++++++-------------- 3 files changed, 50 insertions(+), 37 deletions(-) (limited to 'source3') diff --git a/source3/include/packet.h b/source3/include/packet.h index 05974da8fc..03331da750 100644 --- a/source3/include/packet.h +++ b/source3/include/packet.h @@ -44,12 +44,14 @@ NTSTATUS packet_fd_read_sync(struct packet_context *ctx); * Handle an incoming packet: * Return False if none is available * Otherwise return True and store the callback result in *status + * Callback must either talloc_move or talloc_free buf */ bool packet_handler(struct packet_context *ctx, - bool (*full_req)(const DATA_BLOB *data, + bool (*full_req)(const uint8_t *buf, + size_t available, size_t *length, void *private_data), - NTSTATUS (*callback)(const DATA_BLOB *data, + NTSTATUS (*callback)(uint8_t *buf, size_t length, void *private_data), void *private_data, NTSTATUS *status); diff --git a/source3/lib/ctdbd_conn.c b/source3/lib/ctdbd_conn.c index 8d97606b85..75a513312e 100644 --- a/source3/lib/ctdbd_conn.c +++ b/source3/lib/ctdbd_conn.c @@ -155,17 +155,17 @@ static NTSTATUS ctdbd_connect(TALLOC_CTX *mem_ctx, * Do we have a complete ctdb packet in the queue? */ -static bool ctdb_req_complete(const DATA_BLOB *data, +static bool ctdb_req_complete(const uint8_t *buf, size_t available, size_t *length, void *private_data) { uint32 msglen; - if (data->length < sizeof(msglen)) { + if (available < sizeof(msglen)) { return False; } - msglen = *((uint32 *)data->data); + msglen = *((uint32 *)buf); DEBUG(10, ("msglen = %d\n", msglen)); @@ -176,12 +176,12 @@ static bool ctdb_req_complete(const DATA_BLOB *data, cluster_fatal("ctdbd protocol error\n"); } - if (data->length >= msglen) { - *length = msglen; - return True; + if (available < msglen) { + return false; } - return False; + *length = msglen; + return true; } /* @@ -220,16 +220,13 @@ struct req_pull_state { * Pull a ctdb request out of the incoming packet queue */ -static NTSTATUS ctdb_req_pull(const DATA_BLOB *data, +static NTSTATUS ctdb_req_pull(uint8_t *buf, size_t length, void *private_data) { struct req_pull_state *state = (struct req_pull_state *)private_data; - state->req = data_blob_talloc(state->mem_ctx, data->data, - data->length); - if (state->req.data == NULL) { - return NT_STATUS_NO_MEMORY; - } + state->req.data = talloc_move(state->mem_ctx, &buf); + state->req.length = length; return NT_STATUS_OK; } @@ -497,7 +494,7 @@ NTSTATUS ctdbd_messaging_connection(TALLOC_CTX *mem_ctx, /* * Packet handler to receive and handle a ctdb message */ -static NTSTATUS ctdb_handle_message(const DATA_BLOB *data, +static NTSTATUS ctdb_handle_message(uint8_t *buf, size_t length, void *private_data) { struct ctdbd_connection *conn = talloc_get_type_abort( @@ -505,11 +502,12 @@ static NTSTATUS ctdb_handle_message(const DATA_BLOB *data, struct ctdb_req_message *msg; struct messaging_rec *msg_rec; - msg = (struct ctdb_req_message *)data->data; + msg = (struct ctdb_req_message *)buf; if (msg->hdr.operation != CTDB_REQ_MESSAGE) { DEBUG(0, ("Received async msg of type %u, discarding\n", msg->hdr.operation)); + TALLOC_FREE(buf); return NT_STATUS_INVALID_PARAMETER; } @@ -519,6 +517,7 @@ static NTSTATUS ctdb_handle_message(const DATA_BLOB *data, DEBUG(10, ("received CTDB_SRVID_RELEASE_IP\n")); conn->release_ip_handler((const char *)msg->data, conn->release_ip_priv); + TALLOC_FREE(buf); return NT_STATUS_OK; } @@ -540,6 +539,8 @@ static NTSTATUS ctdb_handle_message(const DATA_BLOB *data, */ message_send_all(conn->msg_ctx, MSG_SMB_UNLOCK, NULL, 0, NULL); + TALLOC_FREE(buf); + return NT_STATUS_OK; } @@ -548,17 +549,20 @@ static NTSTATUS ctdb_handle_message(const DATA_BLOB *data, if (msg->srvid != sys_getpid() && msg->srvid != MSG_SRVID_SAMBA) { DEBUG(0,("Got unexpected message with srvid=%llu\n", (unsigned long long)msg->srvid)); + TALLOC_FREE(buf); return NT_STATUS_OK; } - if (!(msg_rec = ctdb_pull_messaging_rec(NULL, data->length, msg))) { + if (!(msg_rec = ctdb_pull_messaging_rec(NULL, length, msg))) { DEBUG(10, ("ctdb_pull_messaging_rec failed\n")); + TALLOC_FREE(buf); return NT_STATUS_NO_MEMORY; } messaging_dispatch_rec(conn->msg_ctx, msg_rec); TALLOC_FREE(msg_rec); + TALLOC_FREE(buf); return NT_STATUS_OK; } @@ -1025,7 +1029,7 @@ struct ctdbd_traverse_state { * Handle a traverse record coming in on the ctdbd connection */ -static NTSTATUS ctdb_traverse_handler(const DATA_BLOB *blob, +static NTSTATUS ctdb_traverse_handler(uint8_t *buf, size_t length, void *private_data) { struct ctdbd_traverse_state *state = @@ -1035,11 +1039,11 @@ static NTSTATUS ctdb_traverse_handler(const DATA_BLOB *blob, struct ctdb_rec_data *d; TDB_DATA key, data; - m = (struct ctdb_req_message *)blob->data; + m = (struct ctdb_req_message *)buf; - if (blob->length < sizeof(*m) || m->hdr.length != blob->length) { - DEBUG(0, ("Got invalid message of length %d\n", - (int)blob->length)); + if (length < sizeof(*m) || m->hdr.length != length) { + DEBUG(0, ("Got invalid message of length %d\n", (int)length)); + TALLOC_FREE(buf); return NT_STATUS_UNEXPECTED_IO_ERROR; } @@ -1047,6 +1051,7 @@ static NTSTATUS ctdb_traverse_handler(const DATA_BLOB *blob, if (m->datalen < sizeof(uint32_t) || m->datalen != d->length) { DEBUG(0, ("Got invalid traverse data of length %d\n", (int)m->datalen)); + TALLOC_FREE(buf); return NT_STATUS_UNEXPECTED_IO_ERROR; } @@ -1063,6 +1068,7 @@ static NTSTATUS ctdb_traverse_handler(const DATA_BLOB *blob, if (data.dsize < sizeof(struct ctdb_ltdb_header)) { DEBUG(0, ("Got invalid ltdb header length %d\n", (int)data.dsize)); + TALLOC_FREE(buf); return NT_STATUS_UNEXPECTED_IO_ERROR; } data.dsize -= sizeof(struct ctdb_ltdb_header); @@ -1072,6 +1078,7 @@ static NTSTATUS ctdb_traverse_handler(const DATA_BLOB *blob, state->fn(key, data, state->private_data); } + TALLOC_FREE(buf); return NT_STATUS_OK; } diff --git a/source3/lib/packet.c b/source3/lib/packet.c index e4cab6ba87..72de30e8ca 100644 --- a/source3/lib/packet.c +++ b/source3/lib/packet.c @@ -120,33 +120,37 @@ NTSTATUS packet_fd_read_sync(struct packet_context *ctx) } bool packet_handler(struct packet_context *ctx, - bool (*full_req)(const DATA_BLOB *data, + bool (*full_req)(const uint8_t *buf, + size_t available, size_t *length, - void *private_data), - NTSTATUS (*callback)(const DATA_BLOB *data, - void *private_data), - void *private_data, - NTSTATUS *status) + void *priv), + NTSTATUS (*callback)(uint8_t *buf, size_t length, + void *priv), + void *priv, NTSTATUS *status) { size_t length; - DATA_BLOB data; + uint8_t *buf; - if (!full_req(&ctx->in, &length, private_data)) { + if (!full_req(ctx->in.data, ctx->in.length, &length, priv)) { return False; } - SMB_ASSERT(length <= ctx->in.length); + if (length > ctx->in.length) { + *status = NT_STATUS_INTERNAL_ERROR; + return true; + } - data = data_blob(ctx->in.data, length); + buf = (uint8_t *)TALLOC_MEMDUP(ctx, ctx->in.data, length); + if (buf == NULL) { + *status = NT_STATUS_NO_MEMORY; + return true; + } memmove(ctx->in.data, ctx->in.data + length, ctx->in.length - length); ctx->in.length -= length; - *status = callback(&data, private_data); - - data_blob_free(&data); - + *status = callback(buf, length, priv); return True; } -- cgit From b4e1eb4345ab0be00e31d09cf0753597ef0af44a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 20 Dec 2008 10:51:54 +0100 Subject: Optimize for the common case that packet.c received exactly one full packet --- source3/lib/packet.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'source3') diff --git a/source3/lib/packet.c b/source3/lib/packet.c index 72de30e8ca..ef28bf9f62 100644 --- a/source3/lib/packet.c +++ b/source3/lib/packet.c @@ -140,15 +140,21 @@ bool packet_handler(struct packet_context *ctx, return true; } - buf = (uint8_t *)TALLOC_MEMDUP(ctx, ctx->in.data, length); - if (buf == NULL) { - *status = NT_STATUS_NO_MEMORY; - return true; - } + if (length == ctx->in.length) { + buf = ctx->in.data; + ctx->in.data = NULL; + ctx->in.length = 0; + } else { + buf = (uint8_t *)TALLOC_MEMDUP(ctx, ctx->in.data, length); + if (buf == NULL) { + *status = NT_STATUS_NO_MEMORY; + return true; + } - memmove(ctx->in.data, ctx->in.data + length, - ctx->in.length - length); - ctx->in.length -= length; + memmove(ctx->in.data, ctx->in.data + length, + ctx->in.length - length); + ctx->in.length -= length; + } *status = callback(buf, length, priv); return True; -- cgit From 980aa0d464b5e95c777539cdd7a289b5407f1912 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 27 Dec 2008 17:20:25 +0100 Subject: Replace some SMB_ASSERTs with NT_STATUS_INTERNAL_ERROR --- source3/lib/async_sock.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) (limited to 'source3') diff --git a/source3/lib/async_sock.c b/source3/lib/async_sock.c index 225cc7b195..3e9d6f7904 100644 --- a/source3/lib/async_sock.c +++ b/source3/lib/async_sock.c @@ -236,7 +236,10 @@ static void async_send_callback(struct event_context *ev, req->private_data, struct async_syscall_state); struct param_send *p = &state->param.param_send; - SMB_ASSERT(state->syscall_type == ASYNC_SYSCALL_SEND); + if (state->syscall_type != ASYNC_SYSCALL_SEND) { + async_req_error(req, NT_STATUS_INTERNAL_ERROR); + return; + } state->result.result_ssize_t = send(p->fd, p->buffer, p->length, p->flags); @@ -300,7 +303,10 @@ static void async_sendall_callback(struct event_context *ev, req->private_data, struct async_syscall_state); struct param_sendall *p = &state->param.param_sendall; - SMB_ASSERT(state->syscall_type == ASYNC_SYSCALL_SENDALL); + if (state->syscall_type != ASYNC_SYSCALL_SENDALL) { + async_req_error(req, NT_STATUS_INTERNAL_ERROR); + return; + } state->result.result_ssize_t = send(p->fd, (char *)p->buffer + p->sent, p->length - p->sent, p->flags); @@ -317,7 +323,10 @@ static void async_sendall_callback(struct event_context *ev, } p->sent += state->result.result_ssize_t; - SMB_ASSERT(p->sent <= p->length); + if (p->sent > p->length) { + async_req_error(req, NT_STATUS_INTERNAL_ERROR); + return; + } if (p->sent == p->length) { TALLOC_FREE(state->fde); @@ -385,7 +394,10 @@ static void async_recv_callback(struct event_context *ev, req->private_data, struct async_syscall_state); struct param_recv *p = &state->param.param_recv; - SMB_ASSERT(state->syscall_type == ASYNC_SYSCALL_RECV); + if (state->syscall_type != ASYNC_SYSCALL_RECV) { + async_req_error(req, NT_STATUS_INTERNAL_ERROR); + return; + } state->result.result_ssize_t = recv(p->fd, p->buffer, p->length, p->flags); @@ -450,7 +462,10 @@ static void async_recvall_callback(struct event_context *ev, req->private_data, struct async_syscall_state); struct param_recvall *p = &state->param.param_recvall; - SMB_ASSERT(state->syscall_type == ASYNC_SYSCALL_RECVALL); + if (state->syscall_type != ASYNC_SYSCALL_RECVALL) { + async_req_error(req, NT_STATUS_INTERNAL_ERROR); + return; + } state->result.result_ssize_t = recv(p->fd, (char *)p->buffer + p->received, @@ -468,7 +483,10 @@ static void async_recvall_callback(struct event_context *ev, } p->received += state->result.result_ssize_t; - SMB_ASSERT(p->received <= p->length); + if (p->received > p->length) { + async_req_error(req, NT_STATUS_INTERNAL_ERROR); + return; + } if (p->received == p->length) { TALLOC_FREE(state->fde); @@ -535,7 +553,10 @@ static void async_connect_callback(struct event_context *ev, req->private_data, struct async_syscall_state); struct param_connect *p = &state->param.param_connect; - SMB_ASSERT(state->syscall_type == ASYNC_SYSCALL_CONNECT); + if (state->syscall_type != ASYNC_SYSCALL_CONNECT) { + async_req_error(req, NT_STATUS_INTERNAL_ERROR); + return; + } TALLOC_FREE(state->fde); -- cgit From b00f6d169c1b5b4da5d8c5167d81a659e1deca13 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 3 Jan 2009 09:14:23 +0100 Subject: tevent: raise version to 0.9.1 This 0.9.1 isn't compatible with 0.9.0, but it makes only sense to raise the major version after we have reached 1.0.0. metze --- source3/samba4.m4 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3') diff --git a/source3/samba4.m4 b/source3/samba4.m4 index 5199363fc3..8bcc18c5c7 100644 --- a/source3/samba4.m4 +++ b/source3/samba4.m4 @@ -65,7 +65,7 @@ SMB_EXT_LIB_FROM_PKGCONFIG(LIBTDB, tdb >= 1.1.3, SMB_INCLUDE_MK(../lib/tdb/python.mk) -SMB_EXT_LIB_FROM_PKGCONFIG(LIBTEVENT, tevent >= 0.9.0, +SMB_EXT_LIB_FROM_PKGCONFIG(LIBTEVENT, tevent >= 0.9.1, [], [ m4_include(../lib/tevent/libtevent.m4) @@ -114,8 +114,6 @@ SMB_INCLUDE_MK(lib/ldb/python.mk) SMB_ENABLE(swig_ldb,YES) m4_include(lib/tls/config.m4) -teventdir="../lib/tevent" -m4_include(../lib/tevent/libtevent.m4) dnl m4_include(auth/kerberos/config.m4) m4_include(auth/gensec/config.m4) -- cgit From 141b76d747a0741cf9175529ec638f4625fcb099 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 3 Jan 2009 15:23:13 +0100 Subject: Remove unused argument "vuid" from make_internal_rpc_pipe_p --- source3/rpc_server/srv_pipe_hnd.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source3') diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index 1cff95dcab..7d1f824234 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -105,8 +105,7 @@ static bool pipe_init_outgoing_data(pipes_struct *p) static struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx, const char *pipe_name, const char *client_address, - struct auth_serversupplied_info *server_info, - uint16_t vuid) + struct auth_serversupplied_info *server_info) { pipes_struct *p; @@ -1125,8 +1124,7 @@ NTSTATUS np_open(struct smb_request *smb_req, const char *name, p = make_internal_rpc_pipe_p(fsp->fake_file_handle, name, conn->client_address, - conn->server_info, - smb_req->vuid); + conn->server_info); fsp->fake_file_handle->type = FAKE_FILE_TYPE_NAMED_PIPE; fsp->fake_file_handle->private_data = p; -- cgit From 27abf6731ed472580157a0447e858e11f6f63f3b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 3 Jan 2009 10:34:59 +0100 Subject: struct async_req doesn't really need to carry an event_context --- source3/include/async_req.h | 12 +++--------- source3/lib/async_req.c | 9 ++++----- source3/lib/async_sock.c | 10 ++++++---- source3/libsmb/async_smb.c | 2 +- source3/libsmb/clireadwrite.c | 10 +++++----- source3/winbindd/winbindd_reqtrans.c | 10 +++++----- 6 files changed, 24 insertions(+), 29 deletions(-) (limited to 'source3') diff --git a/source3/include/async_req.h b/source3/include/async_req.h index 14a30696c4..2633027e37 100644 --- a/source3/include/async_req.h +++ b/source3/include/async_req.h @@ -96,13 +96,6 @@ struct async_req { **/ NTSTATUS status; - /** - * @brief The event context we are using - * - * The event context that this async request works on. - */ - struct event_context *event_ctx; - /** * @brief What to do on completion * @@ -122,7 +115,7 @@ struct async_req { } async; }; -struct async_req *async_req_new(TALLOC_CTX *mem_ctx, struct event_context *ev); +struct async_req *async_req_new(TALLOC_CTX *mem_ctx); char *async_req_print(TALLOC_CTX *mem_ctx, struct async_req *req); @@ -130,7 +123,8 @@ void async_req_done(struct async_req *req); void async_req_error(struct async_req *req, NTSTATUS status); -bool async_post_status(struct async_req *req, NTSTATUS status); +bool async_post_status(struct async_req *req, struct event_context *ev, + NTSTATUS status); bool async_req_nomem(const void *p, struct async_req *req); diff --git a/source3/lib/async_req.c b/source3/lib/async_req.c index 159666f15c..8c9b2e6b47 100644 --- a/source3/lib/async_req.c +++ b/source3/lib/async_req.c @@ -49,7 +49,7 @@ char *async_req_print(TALLOC_CTX *mem_ctx, struct async_req *req) * The new async request will be initialized in state ASYNC_REQ_IN_PROGRESS */ -struct async_req *async_req_new(TALLOC_CTX *mem_ctx, struct event_context *ev) +struct async_req *async_req_new(TALLOC_CTX *mem_ctx) { struct async_req *result; @@ -58,7 +58,6 @@ struct async_req *async_req_new(TALLOC_CTX *mem_ctx, struct event_context *ev) return NULL; } result->state = ASYNC_REQ_IN_PROGRESS; - result->event_ctx = ev; result->print = async_req_print; return result; } @@ -135,12 +134,12 @@ static void async_trigger(struct event_context *ev, struct timed_event *te, * conventions, independent of whether the request was actually deferred. */ -bool async_post_status(struct async_req *req, NTSTATUS status) +bool async_post_status(struct async_req *req, struct event_context *ev, + NTSTATUS status) { req->status = status; - if (event_add_timed(req->event_ctx, req, timeval_zero(), - "async_trigger", + if (event_add_timed(ev, req, timeval_zero(), "async_trigger", async_trigger, req) == NULL) { return false; } diff --git a/source3/lib/async_sock.c b/source3/lib/async_sock.c index 3e9d6f7904..cb545854dd 100644 --- a/source3/lib/async_sock.c +++ b/source3/lib/async_sock.c @@ -106,7 +106,7 @@ static struct async_req *async_syscall_new(TALLOC_CTX *mem_ctx, struct async_req *result; struct async_syscall_state *state; - result = async_req_new(mem_ctx, ev); + result = async_req_new(mem_ctx); if (result == NULL) { return NULL; } @@ -628,7 +628,8 @@ struct async_req *async_connect(TALLOC_CTX *mem_ctx, struct event_context *ev, p->old_sockflags = sys_fcntl_long(fd, F_GETFL, 0); if (p->old_sockflags == -1) { - if (async_post_status(result, map_nt_error_from_unix(errno))) { + if (async_post_status(result, ev, + map_nt_error_from_unix(errno))) { return result; } TALLOC_FREE(result); @@ -641,7 +642,7 @@ struct async_req *async_connect(TALLOC_CTX *mem_ctx, struct event_context *ev, if (state->result.result_int == 0) { state->sys_errno = 0; - if (async_post_status(result, NT_STATUS_OK)) { + if (async_post_status(result, ev, NT_STATUS_OK)) { return result; } sys_fcntl_long(fd, F_SETFL, p->old_sockflags); @@ -664,7 +665,8 @@ struct async_req *async_connect(TALLOC_CTX *mem_ctx, struct event_context *ev, state->sys_errno = errno; - if (async_post_status(result, map_nt_error_from_unix(errno))) { + if (async_post_status(result, ev, + map_nt_error_from_unix(errno))) { return result; } sys_fcntl_long(fd, F_SETFL, p->old_sockflags); diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index 82a919455a..a1fcf8eb07 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -435,7 +435,7 @@ static struct async_req *cli_request_chain(TALLOC_CTX *mem_ctx, req->async = tmp_reqs; req->num_async += 1; - req->async[req->num_async-1] = async_req_new(mem_ctx, ev); + req->async[req->num_async-1] = async_req_new(mem_ctx); if (req->async[req->num_async-1] == NULL) { DEBUG(0, ("async_req_new failed\n")); req->num_async -= 1; diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index b33d0f0938..1d5582e61d 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -278,7 +278,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_pull_state *state; int i; - result = async_req_new(mem_ctx, ev); + result = async_req_new(mem_ctx); if (result == NULL) { goto failed; } @@ -302,7 +302,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, state->top_req = 0; if (size == 0) { - if (!async_post_status(result, NT_STATUS_OK)) { + if (!async_post_status(result, ev, NT_STATUS_OK)) { goto failed; } return result; @@ -843,7 +843,7 @@ static struct async_req *cli_writeall_send(TALLOC_CTX *mem_ctx, struct async_req *subreq; struct cli_writeall_state *state; - result = async_req_new(mem_ctx, ev); + result = async_req_new(mem_ctx); if (result == NULL) { goto fail; } @@ -969,7 +969,7 @@ struct async_req *cli_push_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct cli_push_state *state; int i; - result = async_req_new(mem_ctx, ev); + result = async_req_new(mem_ctx); if (result == NULL) { goto failed; } @@ -1034,7 +1034,7 @@ struct async_req *cli_push_send(TALLOC_CTX *mem_ctx, struct event_context *ev, } if (i == 0) { - if (!async_post_status(result, NT_STATUS_OK)) { + if (!async_post_status(result, ev, NT_STATUS_OK)) { goto failed; } return result; diff --git a/source3/winbindd/winbindd_reqtrans.c b/source3/winbindd/winbindd_reqtrans.c index ea16c5f81e..6c4f0f2c75 100644 --- a/source3/winbindd/winbindd_reqtrans.c +++ b/source3/winbindd/winbindd_reqtrans.c @@ -43,7 +43,7 @@ struct async_req *wb_req_read_send(TALLOC_CTX *mem_ctx, struct async_req *result, *subreq; struct req_read_state *state; - result = async_req_new(mem_ctx, ev); + result = async_req_new(mem_ctx); if (result == NULL) { return NULL; } @@ -205,7 +205,7 @@ struct async_req *wb_req_write_send(TALLOC_CTX *mem_ctx, struct async_req *result, *subreq; struct req_write_state *state; - result = async_req_new(mem_ctx, ev); + result = async_req_new(mem_ctx); if (result == NULL) { return NULL; } @@ -304,7 +304,7 @@ struct async_req *wb_resp_read_send(TALLOC_CTX *mem_ctx, struct async_req *result, *subreq; struct resp_read_state *state; - result = async_req_new(mem_ctx, ev); + result = async_req_new(mem_ctx); if (result == NULL) { return NULL; } @@ -458,7 +458,7 @@ struct async_req *wb_resp_write_send(TALLOC_CTX *mem_ctx, struct async_req *result, *subreq; struct resp_write_state *state; - result = async_req_new(mem_ctx, ev); + result = async_req_new(mem_ctx); if (result == NULL) { return NULL; } @@ -564,7 +564,7 @@ struct async_req *wb_trans_send(TALLOC_CTX *mem_ctx, struct async_req *result, *subreq; struct wb_trans_state *state; - result = async_req_new(mem_ctx, ev); + result = async_req_new(mem_ctx); if (result == NULL) { return NULL; } -- cgit From b6138bf4f22e7a093d35e2f23992595acae55068 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 27 Dec 2008 18:42:45 +0100 Subject: Fix retval of async_syscall_result_int --- source3/include/async_sock.h | 2 +- source3/lib/async_sock.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/include/async_sock.h b/source3/include/async_sock.h index f0cd5fdaa4..892ffef087 100644 --- a/source3/include/async_sock.h +++ b/source3/include/async_sock.h @@ -24,7 +24,7 @@ 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); -ssize_t async_syscall_result_int(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 event_context *ev, int fd, const void *buffer, size_t length, diff --git a/source3/lib/async_sock.c b/source3/lib/async_sock.c index cb545854dd..107d1402fc 100644 --- a/source3/lib/async_sock.c +++ b/source3/lib/async_sock.c @@ -209,7 +209,7 @@ size_t async_syscall_result_size_t(struct async_req *req, int *perrno) * @retval The return value from the asynchronously called syscall */ -ssize_t async_syscall_result_int(struct async_req *req, int *perrno) +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); -- cgit From fafb9ecc613914ee49bfdb4c1eb249fcbbcf25f7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 3 Jan 2009 18:16:08 +0100 Subject: open_socket_out is always used with SOCK_STREAM, remove argument "type" --- source3/include/proto.h | 3 +-- source3/lib/util_sock.c | 12 +++--------- source3/libads/krb5_setpw.c | 2 +- source3/libsmb/cliconnect.c | 12 +++++------- source3/modules/vfs_smb_traffic_analyzer.c | 2 +- source3/rpc_client/cli_pipe.c | 2 +- source3/utils/smbfilter.c | 2 +- 7 files changed, 13 insertions(+), 22 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index be34bb0e65..42d1f52fe1 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1457,8 +1457,7 @@ int open_socket_in(int type, int dlevel, const struct sockaddr_storage *psock, bool rebind); -int open_socket_out(int type, - const struct sockaddr_storage *pss, +int open_socket_out(const struct sockaddr_storage *pss, uint16_t port, int timeout); bool open_any_socket_out(struct sockaddr_storage *addrs, int num_addrs, diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index d23758ad6a..a8c3b3031d 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -952,10 +952,8 @@ int open_socket_in(int type, Create an outgoing socket. timeout is in milliseconds. **************************************************************************/ -int open_socket_out(int type, - const struct sockaddr_storage *pss, - uint16_t port, - int timeout) +int open_socket_out(const struct sockaddr_storage *pss, uint16_t port, + int timeout) { char addr[INET6_ADDRSTRLEN]; struct sockaddr_storage sock_out = *pss; @@ -964,16 +962,12 @@ int open_socket_out(int type, int increment = 10; /* create a socket to write to */ - res = socket(pss->ss_family, type, 0); + res = socket(pss->ss_family, SOCK_STREAM, 0); if (res == -1) { DEBUG(0,("socket error (%s)\n", strerror(errno))); return -1; } - if (type != SOCK_STREAM) { - return res; - } - #if defined(HAVE_IPV6) if (pss->ss_family == AF_INET6) { struct sockaddr_in6 *psa6 = (struct sockaddr_in6 *)&sock_out; diff --git a/source3/libads/krb5_setpw.c b/source3/libads/krb5_setpw.c index 5032ffd14c..e164a55b38 100644 --- a/source3/libads/krb5_setpw.c +++ b/source3/libads/krb5_setpw.c @@ -428,7 +428,7 @@ static ADS_STATUS do_krb5_kpasswd_request(krb5_context context, } else { - sock = open_socket_out(SOCK_STREAM, &addr, DEFAULT_KPASSWD_PORT, + sock = open_socket_out(&addr, DEFAULT_KPASSWD_PORT, LONG_CONNECT_TIMEOUT); } diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 5892bdc859..44899e3b1a 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -1499,10 +1499,8 @@ bool cli_session_request(struct cli_state *cli, putip((char *)&dest_ip,cli->inbuf+4); in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip); - cli->fd = open_socket_out(SOCK_STREAM, - &cli->dest_ss, - port, - LONG_CONNECT_TIMEOUT); + cli->fd = open_socket_out(&cli->dest_ss, port, + LONG_CONNECT_TIMEOUT); if (cli->fd == -1) return False; @@ -1589,11 +1587,11 @@ NTSTATUS cli_connect(struct cli_state *cli, } else { /* try 445 first, then 139 */ uint16_t port = cli->port?cli->port:445; - cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ss, - port, cli->timeout); + cli->fd = open_socket_out(&cli->dest_ss, port, + cli->timeout); if (cli->fd == -1 && cli->port == 0) { port = 139; - cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ss, + cli->fd = open_socket_out(&cli->dest_ss, port, cli->timeout); } if (cli->fd != -1) { diff --git a/source3/modules/vfs_smb_traffic_analyzer.c b/source3/modules/vfs_smb_traffic_analyzer.c index 63cc904bed..fe292e5ce8 100644 --- a/source3/modules/vfs_smb_traffic_analyzer.c +++ b/source3/modules/vfs_smb_traffic_analyzer.c @@ -86,7 +86,7 @@ static int smb_traffic_analyzer_connect_inet_socket(vfs_handle_struct *handle, ZERO_STRUCT(ss); memcpy(&ss, res->ai_addr, res->ai_addrlen); - sockfd = open_socket_out(SOCK_STREAM, &ss, port, 10000); + sockfd = open_socket_out(&ss, port, 10000); if (sockfd != -1) { break; } diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index a2d334230d..45eab503fe 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2618,7 +2618,7 @@ static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host, goto fail; } - result->trans.sock.fd = open_socket_out(SOCK_STREAM, &addr, port, 60); + result->trans.sock.fd = open_socket_out(&addr, port, 60); if (result->trans.sock.fd == -1) { status = map_nt_error_from_unix(errno); goto fail; diff --git a/source3/utils/smbfilter.c b/source3/utils/smbfilter.c index 1e22a40201..e7b71bd5db 100644 --- a/source3/utils/smbfilter.c +++ b/source3/utils/smbfilter.c @@ -144,7 +144,7 @@ static void filter_child(int c, struct sockaddr_storage *dest_ss) int s; /* we have a connection from a new client, now connect to the server */ - s = open_socket_out(SOCK_STREAM, dest_ss, 445, LONG_CONNECT_TIMEOUT); + s = open_socket_out(dest_ss, 445, LONG_CONNECT_TIMEOUT); if (s == -1) { char addr[INET6_ADDRSTRLEN]; -- cgit From c652b426126d97ae8fad256bf5b96beed414a385 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 3 Jan 2009 11:36:04 +0100 Subject: tevent: raise version to 0.9.2 after AUTOCLOSE changes metze --- source3/samba4.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/samba4.m4 b/source3/samba4.m4 index 8bcc18c5c7..fe3995dfa0 100644 --- a/source3/samba4.m4 +++ b/source3/samba4.m4 @@ -65,7 +65,7 @@ SMB_EXT_LIB_FROM_PKGCONFIG(LIBTDB, tdb >= 1.1.3, SMB_INCLUDE_MK(../lib/tdb/python.mk) -SMB_EXT_LIB_FROM_PKGCONFIG(LIBTEVENT, tevent >= 0.9.1, +SMB_EXT_LIB_FROM_PKGCONFIG(LIBTEVENT, tevent >= 0.9.2, [], [ m4_include(../lib/tevent/libtevent.m4) -- cgit From ebacce2efe6dbb27a9e7962597da8ef783473f6a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 3 Jan 2009 19:10:57 +0100 Subject: Add async timeout helpers --- source3/include/async_req.h | 10 ++++++++++ source3/lib/async_req.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) (limited to 'source3') diff --git a/source3/include/async_req.h b/source3/include/async_req.h index 2633027e37..bbe52da723 100644 --- a/source3/include/async_req.h +++ b/source3/include/async_req.h @@ -132,4 +132,14 @@ bool async_req_is_error(struct async_req *req, NTSTATUS *status); NTSTATUS async_req_simple_recv(struct async_req *req); +bool async_req_set_timeout(struct async_req *req, struct event_context *ev, + struct timeval to); + +struct async_req *async_wait_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct timeval to); + +NTSTATUS async_wait_recv(struct async_req *req); + + #endif diff --git a/source3/lib/async_req.c b/source3/lib/async_req.c index 8c9b2e6b47..0653ff62a7 100644 --- a/source3/lib/async_req.c +++ b/source3/lib/async_req.c @@ -194,3 +194,45 @@ NTSTATUS async_req_simple_recv(struct async_req *req) } return NT_STATUS_OK; } + +static void async_req_timedout(struct event_context *ev, + struct timed_event *te, + const struct timeval *now, + void *priv) +{ + struct async_req *req = talloc_get_type_abort( + priv, struct async_req); + TALLOC_FREE(te); + async_req_error(req, NT_STATUS_IO_TIMEOUT); +} + +bool async_req_set_timeout(struct async_req *req, struct event_context *ev, + struct timeval to) +{ + return (event_add_timed(ev, req, + timeval_current_ofs(to.tv_sec, to.tv_usec), + "async_req_timedout", async_req_timedout, req) + != NULL); +} + +struct async_req *async_wait_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct timeval to) +{ + struct async_req *result; + + result = async_req_new(mem_ctx); + if (result == NULL) { + return result; + } + if (!async_req_set_timeout(result, ev, to)) { + TALLOC_FREE(result); + return NULL; + } + return result; +} + +NTSTATUS async_wait_recv(struct async_req *req) +{ + return NT_STATUS_OK; +} -- cgit From 611f0d7ee607bad65b7a40ba2f0195ba987f1cab Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 4 Jan 2009 11:28:40 +0100 Subject: Add an async queueing mechanism --- source3/include/async_req.h | 8 +++++ source3/lib/async_req.c | 78 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) (limited to 'source3') diff --git a/source3/include/async_req.h b/source3/include/async_req.h index bbe52da723..1b8dbf3346 100644 --- a/source3/include/async_req.h +++ b/source3/include/async_req.h @@ -141,5 +141,13 @@ struct async_req *async_wait_send(TALLOC_CTX *mem_ctx, NTSTATUS async_wait_recv(struct async_req *req); +struct async_req_queue; + +struct async_req_queue *async_req_queue_init(TALLOC_CTX *mem_ctx); + +bool async_req_enqueue(struct async_req_queue *queue, + struct event_context *ev, + struct async_req *req, + void (*trigger)(struct async_req *req)); #endif diff --git a/source3/lib/async_req.c b/source3/lib/async_req.c index 0653ff62a7..ac06df65a3 100644 --- a/source3/lib/async_req.c +++ b/source3/lib/async_req.c @@ -236,3 +236,81 @@ NTSTATUS async_wait_recv(struct async_req *req) { return NT_STATUS_OK; } + +struct async_queue_entry { + struct async_queue_entry *prev, *next; + struct async_req_queue *queue; + struct async_req *req; + void (*trigger)(struct async_req *req); +}; + +struct async_req_queue { + struct async_queue_entry *queue; +}; + +struct async_req_queue *async_req_queue_init(TALLOC_CTX *mem_ctx) +{ + return TALLOC_ZERO_P(mem_ctx, struct async_req_queue); +} + +static int async_queue_entry_destructor(struct async_queue_entry *e) +{ + struct async_req_queue *queue = e->queue; + + DLIST_REMOVE(queue->queue, e); + + if (queue->queue != NULL) { + queue->queue->trigger(queue->queue->req); + } + + return 0; +} + +static void async_req_immediate_trigger(struct event_context *ev, + struct timed_event *te, + const struct timeval *now, + void *priv) +{ + struct async_queue_entry *e = talloc_get_type_abort( + priv, struct async_queue_entry); + + TALLOC_FREE(te); + e->trigger(e->req); +} + +bool async_req_enqueue(struct async_req_queue *queue, struct event_context *ev, + struct async_req *req, + void (*trigger)(struct async_req *req)) +{ + struct async_queue_entry *e; + bool busy; + + busy = (queue->queue != NULL); + + e = talloc(req, struct async_queue_entry); + if (e == NULL) { + return false; + } + + e->req = req; + e->trigger = trigger; + e->queue = queue; + + DLIST_ADD_END(queue->queue, e, struct async_queue_entry *); + talloc_set_destructor(e, async_queue_entry_destructor); + + if (!busy) { + struct timed_event *te; + + te = event_add_timed(ev, e, timeval_zero(), + "async_req_immediate_trigger", + async_req_immediate_trigger, + e); + if (te == NULL) { + TALLOC_FREE(e); + return false; + } + } + + return true; +} -- cgit From 34e8945cb5d0568e511708779d2c33cc59ed54e1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 3 Jan 2009 19:23:13 +0100 Subject: Actually do a non-blocking connect.... :-) --- source3/lib/async_sock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/lib/async_sock.c b/source3/lib/async_sock.c index 107d1402fc..f755f7ac58 100644 --- a/source3/lib/async_sock.c +++ b/source3/lib/async_sock.c @@ -636,7 +636,7 @@ struct async_req *async_connect(TALLOC_CTX *mem_ctx, struct event_context *ev, return NULL; } - set_blocking(fd, true); + set_blocking(fd, false); state->result.result_int = connect(fd, address, address_len); -- cgit From c6c33d840ba90686fcdc81b49b5e256270b97f29 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 4 Jan 2009 00:26:49 +0100 Subject: Convert async_connect to "normal" style --- source3/include/async_sock.h | 8 +- source3/lib/async_sock.c | 214 +++++++++++++++++++++++-------------------- 2 files changed, 118 insertions(+), 104 deletions(-) (limited to 'source3') diff --git a/source3/include/async_sock.h b/source3/include/async_sock.h index 892ffef087..c6f95d64d5 100644 --- a/source3/include/async_sock.h +++ b/source3/include/async_sock.h @@ -32,9 +32,11 @@ struct async_req *async_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct event_context *ev, int fd, void *buffer, size_t length, int flags); -struct async_req *async_connect(TALLOC_CTX *mem_ctx, struct event_context *ev, - int fd, const struct sockaddr *address, - socklen_t address_len); +struct async_req *async_connect_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + int fd, const struct sockaddr *address, + socklen_t address_len); +NTSTATUS async_connect_recv(struct async_req *req, int *perrno); struct async_req *sendall_send(TALLOC_CTX *mem_ctx, struct event_context *ev, int fd, const void *buffer, size_t length, diff --git a/source3/lib/async_sock.c b/source3/lib/async_sock.c index f755f7ac58..bb89a1353a 100644 --- a/source3/lib/async_sock.c +++ b/source3/lib/async_sock.c @@ -535,63 +535,16 @@ NTSTATUS recvall_recv(struct async_req *req) return async_req_simple_recv(req); } -/** - * fde event handler for connect(2) - * @param[in] ev The event context that sent us here - * @param[in] fde The file descriptor event associated with the connect - * @param[in] flags Indicate read/writeability of the socket - * @param[in] priv private data, "struct async_req *" in this case - */ - -static void async_connect_callback(struct event_context *ev, - struct fd_event *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_connect *p = &state->param.param_connect; - - if (state->syscall_type != ASYNC_SYSCALL_CONNECT) { - async_req_error(req, NT_STATUS_INTERNAL_ERROR); - return; - } - - TALLOC_FREE(state->fde); - - /* - * Stevens, Network Programming says that if there's a - * successful connect, the socket is only writable. Upon an - * error, it's both readable and writable. - */ - if ((flags & (EVENT_FD_READ|EVENT_FD_WRITE)) - == (EVENT_FD_READ|EVENT_FD_WRITE)) { - int sockerr; - socklen_t err_len = sizeof(sockerr); - - if (getsockopt(p->fd, SOL_SOCKET, SO_ERROR, - (void *)&sockerr, &err_len) == 0) { - errno = sockerr; - } - - state->sys_errno = errno; - - DEBUG(10, ("connect returned %s\n", strerror(errno))); - - sys_fcntl_long(p->fd, F_SETFL, p->old_sockflags); - - async_req_error(req, map_nt_error_from_unix(state->sys_errno)); - return; - } - - sys_fcntl_long(p->fd, F_SETFL, p->old_sockflags); - - state->result.result_int = 0; - state->sys_errno = 0; +struct async_connect_state { + int fd; + int result; + int sys_errno; + long old_sockflags; +}; - async_req_done(req); -} +static void async_connect_connected(struct event_context *ev, + struct fd_event *fde, uint16_t flags, + void *priv); /** * @brief async version of connect(2) @@ -606,48 +559,46 @@ static void async_connect_callback(struct event_context *ev, * connect in an async state. This will be reset when the request is finished. */ -struct async_req *async_connect(TALLOC_CTX *mem_ctx, struct event_context *ev, - int fd, const struct sockaddr *address, - socklen_t address_len) +struct async_req *async_connect_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + int fd, const struct sockaddr *address, + socklen_t address_len) { struct async_req *result; - struct async_syscall_state *state; - struct param_connect *p; + struct async_connect_state *state; + struct fd_event *fde; + NTSTATUS status; - result = async_syscall_new(mem_ctx, ev, ASYNC_SYSCALL_CONNECT, &state); + result = async_req_new(mem_ctx); if (result == NULL) { return NULL; } - p = &state->param.param_connect; + state = talloc(result, struct async_connect_state); + if (state == NULL) { + goto fail; + } + result->private_data = state; /** * We have to set the socket to nonblocking for async connect(2). Keep * the old sockflags around. */ - p->old_sockflags = sys_fcntl_long(fd, F_GETFL, 0); + state->fd = fd; + state->sys_errno = 0; - if (p->old_sockflags == -1) { - if (async_post_status(result, ev, - map_nt_error_from_unix(errno))) { - return result; - } - TALLOC_FREE(result); - return NULL; + state->old_sockflags = sys_fcntl_long(fd, F_GETFL, 0); + if (state->old_sockflags == -1) { + goto post_errno; } set_blocking(fd, false); - state->result.result_int = connect(fd, address, address_len); - - if (state->result.result_int == 0) { + state->result = connect(fd, address, address_len); + if (state->result == 0) { state->sys_errno = 0; - if (async_post_status(result, ev, NT_STATUS_OK)) { - return result; - } - sys_fcntl_long(fd, F_SETFL, p->old_sockflags); - TALLOC_FREE(result); - return NULL; + status = NT_STATUS_OK; + goto post_status; } /** @@ -662,32 +613,93 @@ struct async_req *async_connect(TALLOC_CTX *mem_ctx, struct event_context *ev, errno == EISCONN || #endif errno == EAGAIN || errno == EINTR)) { + goto post_errno; + } - state->sys_errno = errno; - - if (async_post_status(result, ev, - map_nt_error_from_unix(errno))) { - return result; - } - sys_fcntl_long(fd, F_SETFL, p->old_sockflags); - TALLOC_FREE(result); - return NULL; + fde = event_add_fd(ev, state, fd, EVENT_FD_READ | EVENT_FD_WRITE, + async_connect_connected, result); + if (fde == NULL) { + status = NT_STATUS_NO_MEMORY; + goto post_status; } + return result; - state->fde = event_add_fd(ev, state, fd, - EVENT_FD_READ | EVENT_FD_WRITE, - async_connect_callback, result); - if (state->fde == NULL) { - sys_fcntl_long(fd, F_SETFL, p->old_sockflags); - TALLOC_FREE(result); - return NULL; + post_errno: + state->sys_errno = errno; + status = map_nt_error_from_unix(state->sys_errno); + post_status: + sys_fcntl_long(fd, F_SETFL, state->old_sockflags); + if (!async_post_status(result, ev, status)) { + goto fail; } - result->private_data = state; + return result; + fail: + TALLOC_FREE(result); + return NULL; +} - state->param.param_connect.fd = fd; - state->param.param_connect.address = address; - state->param.param_connect.address_len = address_len; +/** + * fde event handler for connect(2) + * @param[in] ev The event context that sent us here + * @param[in] fde The file descriptor event associated with the connect + * @param[in] flags Indicate read/writeability of the socket + * @param[in] priv private data, "struct async_req *" in this case + */ - return result; +static void async_connect_connected(struct event_context *ev, + struct fd_event *fde, uint16_t flags, + void *priv) +{ + struct async_req *req = talloc_get_type_abort( + priv, struct async_req); + struct async_connect_state *state = talloc_get_type_abort( + req->private_data, struct async_connect_state); + + TALLOC_FREE(fde); + + /* + * Stevens, Network Programming says that if there's a + * successful connect, the socket is only writable. Upon an + * error, it's both readable and writable. + */ + if ((flags & (EVENT_FD_READ|EVENT_FD_WRITE)) + == (EVENT_FD_READ|EVENT_FD_WRITE)) { + int sockerr; + socklen_t err_len = sizeof(sockerr); + + if (getsockopt(state->fd, SOL_SOCKET, SO_ERROR, + (void *)&sockerr, &err_len) == 0) { + errno = sockerr; + } + + state->sys_errno = errno; + + DEBUG(10, ("connect returned %s\n", strerror(errno))); + + sys_fcntl_long(state->fd, F_SETFL, state->old_sockflags); + async_req_error(req, map_nt_error_from_unix(state->sys_errno)); + return; + } + + state->sys_errno = 0; + async_req_done(req); } +NTSTATUS async_connect_recv(struct async_req *req, int *perrno) +{ + struct async_connect_state *state = talloc_get_type_abort( + req->private_data, struct async_connect_state); + NTSTATUS status; + + sys_fcntl_long(state->fd, F_SETFL, state->old_sockflags); + + *perrno = state->sys_errno; + + if (async_req_is_error(req, &status)) { + return status; + } + if (state->sys_errno == 0) { + return NT_STATUS_OK; + } + return map_nt_error_from_unix(state->sys_errno); +} -- cgit From d933362cb7fdd93fef860feeac1d86b180e29a59 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 28 Dec 2008 14:47:40 +0100 Subject: Move winbindd/winbindd_reqtrans.c to lib/wb_reqtrans.c --- source3/Makefile.in | 1 - source3/lib/wb_reqtrans.c | 685 +++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_reqtrans.c | 685 ----------------------------------- 3 files changed, 685 insertions(+), 686 deletions(-) create mode 100644 source3/lib/wb_reqtrans.c delete mode 100644 source3/winbindd/winbindd_reqtrans.c (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index 49f576f507..8631520486 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -1029,7 +1029,6 @@ IDMAP_ADEX_OBJ = \ WINBINDD_OBJ1 = \ winbindd/winbindd.o \ - winbindd/winbindd_reqtrans.o \ winbindd/winbindd_user.o \ winbindd/winbindd_group.o \ winbindd/winbindd_util.o \ diff --git a/source3/lib/wb_reqtrans.c b/source3/lib/wb_reqtrans.c new file mode 100644 index 0000000000..faf1666705 --- /dev/null +++ b/source3/lib/wb_reqtrans.c @@ -0,0 +1,685 @@ +/* + Unix SMB/CIFS implementation. + + Async transfer of winbindd_request and _response structs + + Copyright (C) Volker Lendecke 2008 + + 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 . +*/ + +#include "includes.h" +#include "winbindd/winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +struct req_read_state { + struct winbindd_request *wb_req; + struct event_context *ev; + size_t max_extra_data; + int fd; +}; + +static void wb_req_read_len(struct async_req *subreq); +static void wb_req_read_main(struct async_req *subreq); +static void wb_req_read_extra(struct async_req *subreq); + +struct async_req *wb_req_read_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + int fd, size_t max_extra_data) +{ + struct async_req *result, *subreq; + struct req_read_state *state; + + result = async_req_new(mem_ctx); + if (result == NULL) { + return NULL; + } + + state = talloc(result, struct req_read_state); + if (state == NULL) { + goto nomem; + } + result->private_data = state; + + state->fd = fd; + state->ev = ev; + state->max_extra_data = max_extra_data; + state->wb_req = talloc(state, struct winbindd_request); + if (state->wb_req == NULL) { + goto nomem; + } + + subreq = recvall_send(state, ev, state->fd, &(state->wb_req->length), + sizeof(state->wb_req->length), 0); + if (subreq == NULL) { + goto nomem; + } + + subreq->async.fn = wb_req_read_len; + subreq->async.priv = result; + return result; + + nomem: + TALLOC_FREE(result); + return NULL; +} + +static void wb_req_read_len(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct req_read_state *state = talloc_get_type_abort( + req->private_data, struct req_read_state); + NTSTATUS status; + + status = recvall_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + if (state->wb_req->length != sizeof(struct winbindd_request)) { + DEBUG(0, ("wb_req_read_len: Invalid request size received: " + "%d (expected %d)\n", (int)state->wb_req->length, + (int)sizeof(struct winbindd_request))); + async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE); + return; + } + + subreq = recvall_send( + req, state->ev, state->fd, (uint32 *)(state->wb_req)+1, + sizeof(struct winbindd_request) - sizeof(uint32), 0); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_req_read_main; + subreq->async.priv = req; +} + +static void wb_req_read_main(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct req_read_state *state = talloc_get_type_abort( + req->private_data, struct req_read_state); + NTSTATUS status; + + status = recvall_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + if ((state->max_extra_data != 0) + && (state->wb_req->extra_len > state->max_extra_data)) { + DEBUG(3, ("Got request with %d bytes extra data on " + "unprivileged socket\n", + (int)state->wb_req->extra_len)); + async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE); + return; + } + + if (state->wb_req->extra_len == 0) { + async_req_done(req); + return; + } + + state->wb_req->extra_data.data = TALLOC_ARRAY( + state->wb_req, char, state->wb_req->extra_len + 1); + if (async_req_nomem(state->wb_req->extra_data.data, req)) { + return; + } + + state->wb_req->extra_data.data[state->wb_req->extra_len] = 0; + + subreq = recvall_send( + req, state->ev, state->fd, state->wb_req->extra_data.data, + state->wb_req->extra_len, 0); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_req_read_extra; + subreq->async.priv = req; +} + +static void wb_req_read_extra(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + NTSTATUS status; + + status = recvall_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + async_req_done(req); +} + + +NTSTATUS wb_req_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx, + struct winbindd_request **preq) +{ + struct req_read_state *state = talloc_get_type_abort( + req->private_data, struct req_read_state); + NTSTATUS status; + + if (async_req_is_error(req, &status)) { + return status; + } + *preq = talloc_move(mem_ctx, &state->wb_req); + return NT_STATUS_OK; +} + +struct req_write_state { + struct winbindd_request *wb_req; + struct event_context *ev; + int fd; +}; + +static void wb_req_write_main(struct async_req *subreq); +static void wb_req_write_extra(struct async_req *subreq); + +struct async_req *wb_req_write_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, int fd, + struct winbindd_request *wb_req) +{ + struct async_req *result, *subreq; + struct req_write_state *state; + + result = async_req_new(mem_ctx); + if (result == NULL) { + return NULL; + } + + state = talloc(result, struct req_write_state); + if (state == NULL) { + goto nomem; + } + result->private_data = state; + + state->fd = fd; + state->ev = ev; + state->wb_req = wb_req; + + subreq = sendall_send(state, state->ev, state->fd, state->wb_req, + sizeof(struct winbindd_request), 0); + if (subreq == NULL) { + goto nomem; + } + + subreq->async.fn = wb_req_write_main; + subreq->async.priv = result; + return result; + + nomem: + TALLOC_FREE(result); + return NULL; +} + +static void wb_req_write_main(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct req_write_state *state = talloc_get_type_abort( + req->private_data, struct req_write_state); + NTSTATUS status; + + status = sendall_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + if (state->wb_req->extra_len == 0) { + async_req_done(req); + return; + } + + subreq = sendall_send(state, state->ev, state->fd, + state->wb_req->extra_data.data, + state->wb_req->extra_len, 0); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_req_write_extra; + subreq->async.priv = req; +} + +static void wb_req_write_extra(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + NTSTATUS status; + + status = sendall_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + async_req_done(req); +} + +NTSTATUS wb_req_write_recv(struct async_req *req) +{ + return async_req_simple_recv(req); +} + +struct resp_read_state { + struct winbindd_response *wb_resp; + struct event_context *ev; + size_t max_extra_data; + int fd; +}; + +static void wb_resp_read_len(struct async_req *subreq); +static void wb_resp_read_main(struct async_req *subreq); +static void wb_resp_read_extra(struct async_req *subreq); + +struct async_req *wb_resp_read_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, int fd) +{ + struct async_req *result, *subreq; + struct resp_read_state *state; + + result = async_req_new(mem_ctx); + if (result == NULL) { + return NULL; + } + + state = talloc(result, struct resp_read_state); + if (state == NULL) { + goto nomem; + } + result->private_data = state; + + state->fd = fd; + state->ev = ev; + state->wb_resp = talloc(state, struct winbindd_response); + if (state->wb_resp == NULL) { + goto nomem; + } + + subreq = recvall_send(state, ev, state->fd, &(state->wb_resp->length), + sizeof(state->wb_resp->length), 0); + if (subreq == NULL) { + goto nomem; + } + + subreq->async.fn = wb_resp_read_len; + subreq->async.priv = result; + return result; + + nomem: + TALLOC_FREE(result); + return NULL; +} + +static void wb_resp_read_len(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct resp_read_state *state = talloc_get_type_abort( + req->private_data, struct resp_read_state); + NTSTATUS status; + + status = recvall_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + if (state->wb_resp->length < sizeof(struct winbindd_response)) { + DEBUG(0, ("wb_resp_read_len: Invalid response size received: " + "%d (expected at least%d)\n", + (int)state->wb_resp->length, + (int)sizeof(struct winbindd_response))); + async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE); + return; + } + + subreq = recvall_send( + req, state->ev, state->fd, (uint32 *)(state->wb_resp)+1, + sizeof(struct winbindd_response) - sizeof(uint32), 0); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_resp_read_main; + subreq->async.priv = req; +} + +static void wb_resp_read_main(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct resp_read_state *state = talloc_get_type_abort( + req->private_data, struct resp_read_state); + NTSTATUS status; + size_t extra_len; + + status = recvall_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + extra_len = state->wb_resp->length - sizeof(struct winbindd_response); + if (extra_len == 0) { + async_req_done(req); + return; + } + + state->wb_resp->extra_data.data = TALLOC_ARRAY( + state->wb_resp, char, extra_len+1); + if (async_req_nomem(state->wb_resp->extra_data.data, req)) { + return; + } + ((char *)state->wb_resp->extra_data.data)[extra_len] = 0; + + subreq = recvall_send( + req, state->ev, state->fd, state->wb_resp->extra_data.data, + extra_len, 0); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_resp_read_extra; + subreq->async.priv = req; +} + +static void wb_resp_read_extra(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + NTSTATUS status; + + status = recvall_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + async_req_done(req); +} + + +NTSTATUS wb_resp_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx, + struct winbindd_response **presp) +{ + struct resp_read_state *state = talloc_get_type_abort( + req->private_data, struct resp_read_state); + NTSTATUS status; + + if (async_req_is_error(req, &status)) { + return status; + } + *presp = talloc_move(mem_ctx, &state->wb_resp); + return NT_STATUS_OK; +} + +struct resp_write_state { + struct winbindd_response *wb_resp; + struct event_context *ev; + int fd; +}; + +static void wb_resp_write_main(struct async_req *subreq); +static void wb_resp_write_extra(struct async_req *subreq); + +struct async_req *wb_resp_write_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, int fd, + struct winbindd_response *wb_resp) +{ + struct async_req *result, *subreq; + struct resp_write_state *state; + + result = async_req_new(mem_ctx); + if (result == NULL) { + return NULL; + } + + state = talloc(result, struct resp_write_state); + if (state == NULL) { + goto nomem; + } + result->private_data = state; + + state->fd = fd; + state->ev = ev; + state->wb_resp = wb_resp; + + subreq = sendall_send(state, state->ev, state->fd, state->wb_resp, + sizeof(struct winbindd_response), 0); + if (subreq == NULL) { + goto nomem; + } + + subreq->async.fn = wb_resp_write_main; + subreq->async.priv = result; + return result; + + nomem: + TALLOC_FREE(result); + return NULL; +} + +static void wb_resp_write_main(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct resp_write_state *state = talloc_get_type_abort( + req->private_data, struct resp_write_state); + NTSTATUS status; + + status = sendall_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + if (state->wb_resp->length == sizeof(struct winbindd_response)) { + async_req_done(req); + return; + } + + subreq = sendall_send( + state, state->ev, state->fd, + state->wb_resp->extra_data.data, + state->wb_resp->length - sizeof(struct winbindd_response), 0); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_resp_write_extra; + subreq->async.priv = req; +} + +static void wb_resp_write_extra(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + NTSTATUS status; + + status = sendall_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + async_req_done(req); +} + +NTSTATUS wb_resp_write_recv(struct async_req *req) +{ + return async_req_simple_recv(req); +} + +struct wb_trans_state { + struct event_context *ev; + struct timed_event *te; + int fd; + struct winbindd_response *wb_resp; + size_t reply_max_extra_data; +}; + +static void wb_trans_timeout(struct event_context *ev, struct timed_event *te, + const struct timeval *now, void *priv); +static void wb_trans_sent(struct async_req *req); +static void wb_trans_received(struct async_req *req); + +struct async_req *wb_trans_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + int fd, + struct winbindd_request *wb_req, + struct timeval timeout, + size_t reply_max_extra_data) +{ + struct async_req *result, *subreq; + struct wb_trans_state *state; + + result = async_req_new(mem_ctx); + if (result == NULL) { + return NULL; + } + + state = talloc(result, struct wb_trans_state); + if (state == NULL) { + goto nomem; + } + result->private_data = state; + + state->ev = ev; + state->fd = fd; + state->reply_max_extra_data = reply_max_extra_data; + + state->te = event_add_timed( + ev, state, + timeval_current_ofs(timeout.tv_sec, timeout.tv_usec), + "wb_trans_timeout", wb_trans_timeout, result); + if (state->te == NULL) { + goto nomem; + } + + subreq = wb_req_write_send(state, state->ev, state->fd, wb_req); + if (subreq == NULL) { + goto nomem; + } + subreq->async.fn = wb_trans_sent; + subreq->async.priv = result; + + return result; + + nomem: + TALLOC_FREE(result); + return NULL; +} + +static void wb_trans_timeout(struct event_context *ev, struct timed_event *te, + const struct timeval *now, void *priv) +{ + struct async_req *req = talloc_get_type_abort( + priv, struct async_req); + struct wb_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_trans_state); + + TALLOC_FREE(state->te); + async_req_error(req, NT_STATUS_IO_TIMEOUT); +} + +static void wb_trans_sent(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_trans_state); + NTSTATUS status; + + status = wb_req_write_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + subreq = wb_resp_read_send(state, state->ev, state->fd); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_trans_received; + subreq->async.priv = req; +}; + +static void wb_trans_received(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_trans_state); + NTSTATUS status; + + TALLOC_FREE(state->te); + + status = wb_resp_read_recv(subreq, state, &state->wb_resp); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + async_req_done(req); +} + +NTSTATUS wb_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, + struct winbindd_response **presp) +{ + struct wb_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_trans_state); + NTSTATUS status; + + if (async_req_is_error(req, &status)) { + return status; + } + *presp = talloc_move(mem_ctx, &state->wb_resp); + return NT_STATUS_OK; +} + +struct wb_trans_queue_state { + struct wb_trans_queue_state *prev, *next; + struct wb_trans_queue *queue; + struct winbindd_request *req; +}; + +struct wb_trans_queue { + int fd; + struct timeval timeout; + size_t max_resp_extra_data; + struct wb_trans_queue_state *queued_requests; +}; diff --git a/source3/winbindd/winbindd_reqtrans.c b/source3/winbindd/winbindd_reqtrans.c deleted file mode 100644 index 6c4f0f2c75..0000000000 --- a/source3/winbindd/winbindd_reqtrans.c +++ /dev/null @@ -1,685 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Async transfer of winbindd_request and _response structs - - Copyright (C) Volker Lendecke 2008 - - 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 . -*/ - -#include "includes.h" -#include "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -struct req_read_state { - struct winbindd_request *wb_req; - struct event_context *ev; - size_t max_extra_data; - int fd; -}; - -static void wb_req_read_len(struct async_req *subreq); -static void wb_req_read_main(struct async_req *subreq); -static void wb_req_read_extra(struct async_req *subreq); - -struct async_req *wb_req_read_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - int fd, size_t max_extra_data) -{ - struct async_req *result, *subreq; - struct req_read_state *state; - - result = async_req_new(mem_ctx); - if (result == NULL) { - return NULL; - } - - state = talloc(result, struct req_read_state); - if (state == NULL) { - goto nomem; - } - result->private_data = state; - - state->fd = fd; - state->ev = ev; - state->max_extra_data = max_extra_data; - state->wb_req = talloc(state, struct winbindd_request); - if (state->wb_req == NULL) { - goto nomem; - } - - subreq = recvall_send(state, ev, state->fd, &(state->wb_req->length), - sizeof(state->wb_req->length), 0); - if (subreq == NULL) { - goto nomem; - } - - subreq->async.fn = wb_req_read_len; - subreq->async.priv = result; - return result; - - nomem: - TALLOC_FREE(result); - return NULL; -} - -static void wb_req_read_len(struct async_req *subreq) -{ - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct req_read_state *state = talloc_get_type_abort( - req->private_data, struct req_read_state); - NTSTATUS status; - - status = recvall_recv(subreq); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); - return; - } - - if (state->wb_req->length != sizeof(struct winbindd_request)) { - DEBUG(0, ("wb_req_read_len: Invalid request size received: " - "%d (expected %d)\n", (int)state->wb_req->length, - (int)sizeof(struct winbindd_request))); - async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE); - return; - } - - subreq = recvall_send( - req, state->ev, state->fd, (uint32 *)(state->wb_req)+1, - sizeof(struct winbindd_request) - sizeof(uint32), 0); - if (async_req_nomem(subreq, req)) { - return; - } - - subreq->async.fn = wb_req_read_main; - subreq->async.priv = req; -} - -static void wb_req_read_main(struct async_req *subreq) -{ - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct req_read_state *state = talloc_get_type_abort( - req->private_data, struct req_read_state); - NTSTATUS status; - - status = recvall_recv(subreq); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); - return; - } - - if ((state->max_extra_data != 0) - && (state->wb_req->extra_len > state->max_extra_data)) { - DEBUG(3, ("Got request with %d bytes extra data on " - "unprivileged socket\n", - (int)state->wb_req->extra_len)); - async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE); - return; - } - - if (state->wb_req->extra_len == 0) { - async_req_done(req); - return; - } - - state->wb_req->extra_data.data = TALLOC_ARRAY( - state->wb_req, char, state->wb_req->extra_len + 1); - if (async_req_nomem(state->wb_req->extra_data.data, req)) { - return; - } - - state->wb_req->extra_data.data[state->wb_req->extra_len] = 0; - - subreq = recvall_send( - req, state->ev, state->fd, state->wb_req->extra_data.data, - state->wb_req->extra_len, 0); - if (async_req_nomem(subreq, req)) { - return; - } - - subreq->async.fn = wb_req_read_extra; - subreq->async.priv = req; -} - -static void wb_req_read_extra(struct async_req *subreq) -{ - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - NTSTATUS status; - - status = recvall_recv(subreq); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); - return; - } - async_req_done(req); -} - - -NTSTATUS wb_req_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx, - struct winbindd_request **preq) -{ - struct req_read_state *state = talloc_get_type_abort( - req->private_data, struct req_read_state); - NTSTATUS status; - - if (async_req_is_error(req, &status)) { - return status; - } - *preq = talloc_move(mem_ctx, &state->wb_req); - return NT_STATUS_OK; -} - -struct req_write_state { - struct winbindd_request *wb_req; - struct event_context *ev; - int fd; -}; - -static void wb_req_write_main(struct async_req *subreq); -static void wb_req_write_extra(struct async_req *subreq); - -struct async_req *wb_req_write_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, int fd, - struct winbindd_request *wb_req) -{ - struct async_req *result, *subreq; - struct req_write_state *state; - - result = async_req_new(mem_ctx); - if (result == NULL) { - return NULL; - } - - state = talloc(result, struct req_write_state); - if (state == NULL) { - goto nomem; - } - result->private_data = state; - - state->fd = fd; - state->ev = ev; - state->wb_req = wb_req; - - subreq = sendall_send(state, state->ev, state->fd, state->wb_req, - sizeof(struct winbindd_request), 0); - if (subreq == NULL) { - goto nomem; - } - - subreq->async.fn = wb_req_write_main; - subreq->async.priv = result; - return result; - - nomem: - TALLOC_FREE(result); - return NULL; -} - -static void wb_req_write_main(struct async_req *subreq) -{ - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct req_write_state *state = talloc_get_type_abort( - req->private_data, struct req_write_state); - NTSTATUS status; - - status = sendall_recv(subreq); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); - return; - } - - if (state->wb_req->extra_len == 0) { - async_req_done(req); - return; - } - - subreq = sendall_send(state, state->ev, state->fd, - state->wb_req->extra_data.data, - state->wb_req->extra_len, 0); - if (async_req_nomem(subreq, req)) { - return; - } - - subreq->async.fn = wb_req_write_extra; - subreq->async.priv = req; -} - -static void wb_req_write_extra(struct async_req *subreq) -{ - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - NTSTATUS status; - - status = sendall_recv(subreq); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); - return; - } - - async_req_done(req); -} - -NTSTATUS wb_req_write_recv(struct async_req *req) -{ - return async_req_simple_recv(req); -} - -struct resp_read_state { - struct winbindd_response *wb_resp; - struct event_context *ev; - size_t max_extra_data; - int fd; -}; - -static void wb_resp_read_len(struct async_req *subreq); -static void wb_resp_read_main(struct async_req *subreq); -static void wb_resp_read_extra(struct async_req *subreq); - -struct async_req *wb_resp_read_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, int fd) -{ - struct async_req *result, *subreq; - struct resp_read_state *state; - - result = async_req_new(mem_ctx); - if (result == NULL) { - return NULL; - } - - state = talloc(result, struct resp_read_state); - if (state == NULL) { - goto nomem; - } - result->private_data = state; - - state->fd = fd; - state->ev = ev; - state->wb_resp = talloc(state, struct winbindd_response); - if (state->wb_resp == NULL) { - goto nomem; - } - - subreq = recvall_send(state, ev, state->fd, &(state->wb_resp->length), - sizeof(state->wb_resp->length), 0); - if (subreq == NULL) { - goto nomem; - } - - subreq->async.fn = wb_resp_read_len; - subreq->async.priv = result; - return result; - - nomem: - TALLOC_FREE(result); - return NULL; -} - -static void wb_resp_read_len(struct async_req *subreq) -{ - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct resp_read_state *state = talloc_get_type_abort( - req->private_data, struct resp_read_state); - NTSTATUS status; - - status = recvall_recv(subreq); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); - return; - } - - if (state->wb_resp->length < sizeof(struct winbindd_response)) { - DEBUG(0, ("wb_resp_read_len: Invalid response size received: " - "%d (expected at least%d)\n", - (int)state->wb_resp->length, - (int)sizeof(struct winbindd_response))); - async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE); - return; - } - - subreq = recvall_send( - req, state->ev, state->fd, (uint32 *)(state->wb_resp)+1, - sizeof(struct winbindd_response) - sizeof(uint32), 0); - if (async_req_nomem(subreq, req)) { - return; - } - - subreq->async.fn = wb_resp_read_main; - subreq->async.priv = req; -} - -static void wb_resp_read_main(struct async_req *subreq) -{ - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct resp_read_state *state = talloc_get_type_abort( - req->private_data, struct resp_read_state); - NTSTATUS status; - size_t extra_len; - - status = recvall_recv(subreq); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); - return; - } - - extra_len = state->wb_resp->length - sizeof(struct winbindd_response); - if (extra_len == 0) { - async_req_done(req); - return; - } - - state->wb_resp->extra_data.data = TALLOC_ARRAY( - state->wb_resp, char, extra_len+1); - if (async_req_nomem(state->wb_resp->extra_data.data, req)) { - return; - } - ((char *)state->wb_resp->extra_data.data)[extra_len] = 0; - - subreq = recvall_send( - req, state->ev, state->fd, state->wb_resp->extra_data.data, - extra_len, 0); - if (async_req_nomem(subreq, req)) { - return; - } - - subreq->async.fn = wb_resp_read_extra; - subreq->async.priv = req; -} - -static void wb_resp_read_extra(struct async_req *subreq) -{ - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - NTSTATUS status; - - status = recvall_recv(subreq); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); - return; - } - async_req_done(req); -} - - -NTSTATUS wb_resp_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx, - struct winbindd_response **presp) -{ - struct resp_read_state *state = talloc_get_type_abort( - req->private_data, struct resp_read_state); - NTSTATUS status; - - if (async_req_is_error(req, &status)) { - return status; - } - *presp = talloc_move(mem_ctx, &state->wb_resp); - return NT_STATUS_OK; -} - -struct resp_write_state { - struct winbindd_response *wb_resp; - struct event_context *ev; - int fd; -}; - -static void wb_resp_write_main(struct async_req *subreq); -static void wb_resp_write_extra(struct async_req *subreq); - -struct async_req *wb_resp_write_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, int fd, - struct winbindd_response *wb_resp) -{ - struct async_req *result, *subreq; - struct resp_write_state *state; - - result = async_req_new(mem_ctx); - if (result == NULL) { - return NULL; - } - - state = talloc(result, struct resp_write_state); - if (state == NULL) { - goto nomem; - } - result->private_data = state; - - state->fd = fd; - state->ev = ev; - state->wb_resp = wb_resp; - - subreq = sendall_send(state, state->ev, state->fd, state->wb_resp, - sizeof(struct winbindd_response), 0); - if (subreq == NULL) { - goto nomem; - } - - subreq->async.fn = wb_resp_write_main; - subreq->async.priv = result; - return result; - - nomem: - TALLOC_FREE(result); - return NULL; -} - -static void wb_resp_write_main(struct async_req *subreq) -{ - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct resp_write_state *state = talloc_get_type_abort( - req->private_data, struct resp_write_state); - NTSTATUS status; - - status = sendall_recv(subreq); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); - return; - } - - if (state->wb_resp->length == sizeof(struct winbindd_response)) { - async_req_done(req); - return; - } - - subreq = sendall_send( - state, state->ev, state->fd, - state->wb_resp->extra_data.data, - state->wb_resp->length - sizeof(struct winbindd_response), 0); - if (async_req_nomem(subreq, req)) { - return; - } - - subreq->async.fn = wb_resp_write_extra; - subreq->async.priv = req; -} - -static void wb_resp_write_extra(struct async_req *subreq) -{ - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - NTSTATUS status; - - status = sendall_recv(subreq); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); - return; - } - - async_req_done(req); -} - -NTSTATUS wb_resp_write_recv(struct async_req *req) -{ - return async_req_simple_recv(req); -} - -struct wb_trans_state { - struct event_context *ev; - struct timed_event *te; - int fd; - struct winbindd_response *wb_resp; - size_t reply_max_extra_data; -}; - -static void wb_trans_timeout(struct event_context *ev, struct timed_event *te, - const struct timeval *now, void *priv); -static void wb_trans_sent(struct async_req *req); -static void wb_trans_received(struct async_req *req); - -struct async_req *wb_trans_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - int fd, - struct winbindd_request *wb_req, - struct timeval timeout, - size_t reply_max_extra_data) -{ - struct async_req *result, *subreq; - struct wb_trans_state *state; - - result = async_req_new(mem_ctx); - if (result == NULL) { - return NULL; - } - - state = talloc(result, struct wb_trans_state); - if (state == NULL) { - goto nomem; - } - result->private_data = state; - - state->ev = ev; - state->fd = fd; - state->reply_max_extra_data = reply_max_extra_data; - - state->te = event_add_timed( - ev, state, - timeval_current_ofs(timeout.tv_sec, timeout.tv_usec), - "wb_trans_timeout", wb_trans_timeout, result); - if (state->te == NULL) { - goto nomem; - } - - subreq = wb_req_write_send(state, state->ev, state->fd, wb_req); - if (subreq == NULL) { - goto nomem; - } - subreq->async.fn = wb_trans_sent; - subreq->async.priv = result; - - return result; - - nomem: - TALLOC_FREE(result); - return NULL; -} - -static void wb_trans_timeout(struct event_context *ev, struct timed_event *te, - const struct timeval *now, void *priv) -{ - struct async_req *req = talloc_get_type_abort( - priv, struct async_req); - struct wb_trans_state *state = talloc_get_type_abort( - req->private_data, struct wb_trans_state); - - TALLOC_FREE(state->te); - async_req_error(req, NT_STATUS_IO_TIMEOUT); -} - -static void wb_trans_sent(struct async_req *subreq) -{ - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct wb_trans_state *state = talloc_get_type_abort( - req->private_data, struct wb_trans_state); - NTSTATUS status; - - status = wb_req_write_recv(subreq); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); - return; - } - - subreq = wb_resp_read_send(state, state->ev, state->fd); - if (async_req_nomem(subreq, req)) { - return; - } - - subreq->async.fn = wb_trans_received; - subreq->async.priv = req; -}; - -static void wb_trans_received(struct async_req *subreq) -{ - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct wb_trans_state *state = talloc_get_type_abort( - req->private_data, struct wb_trans_state); - NTSTATUS status; - - TALLOC_FREE(state->te); - - status = wb_resp_read_recv(subreq, state, &state->wb_resp); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); - return; - } - - async_req_done(req); -} - -NTSTATUS wb_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, - struct winbindd_response **presp) -{ - struct wb_trans_state *state = talloc_get_type_abort( - req->private_data, struct wb_trans_state); - NTSTATUS status; - - if (async_req_is_error(req, &status)) { - return status; - } - *presp = talloc_move(mem_ctx, &state->wb_resp); - return NT_STATUS_OK; -} - -struct wb_trans_queue_state { - struct wb_trans_queue_state *prev, *next; - struct wb_trans_queue *queue; - struct winbindd_request *req; -}; - -struct wb_trans_queue { - int fd; - struct timeval timeout; - size_t max_resp_extra_data; - struct wb_trans_queue_state *queued_requests; -}; -- cgit From 8c1691d2139e49d6fb47a6d85400a1b7b91ffd67 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 28 Dec 2008 14:49:22 +0100 Subject: Remove wb_trans_send/recv --- source3/lib/wb_reqtrans.c | 143 -------------------------------------- source3/winbindd/winbindd_proto.h | 9 --- 2 files changed, 152 deletions(-) (limited to 'source3') diff --git a/source3/lib/wb_reqtrans.c b/source3/lib/wb_reqtrans.c index faf1666705..1f5f181aa1 100644 --- a/source3/lib/wb_reqtrans.c +++ b/source3/lib/wb_reqtrans.c @@ -540,146 +540,3 @@ NTSTATUS wb_resp_write_recv(struct async_req *req) { return async_req_simple_recv(req); } - -struct wb_trans_state { - struct event_context *ev; - struct timed_event *te; - int fd; - struct winbindd_response *wb_resp; - size_t reply_max_extra_data; -}; - -static void wb_trans_timeout(struct event_context *ev, struct timed_event *te, - const struct timeval *now, void *priv); -static void wb_trans_sent(struct async_req *req); -static void wb_trans_received(struct async_req *req); - -struct async_req *wb_trans_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - int fd, - struct winbindd_request *wb_req, - struct timeval timeout, - size_t reply_max_extra_data) -{ - struct async_req *result, *subreq; - struct wb_trans_state *state; - - result = async_req_new(mem_ctx); - if (result == NULL) { - return NULL; - } - - state = talloc(result, struct wb_trans_state); - if (state == NULL) { - goto nomem; - } - result->private_data = state; - - state->ev = ev; - state->fd = fd; - state->reply_max_extra_data = reply_max_extra_data; - - state->te = event_add_timed( - ev, state, - timeval_current_ofs(timeout.tv_sec, timeout.tv_usec), - "wb_trans_timeout", wb_trans_timeout, result); - if (state->te == NULL) { - goto nomem; - } - - subreq = wb_req_write_send(state, state->ev, state->fd, wb_req); - if (subreq == NULL) { - goto nomem; - } - subreq->async.fn = wb_trans_sent; - subreq->async.priv = result; - - return result; - - nomem: - TALLOC_FREE(result); - return NULL; -} - -static void wb_trans_timeout(struct event_context *ev, struct timed_event *te, - const struct timeval *now, void *priv) -{ - struct async_req *req = talloc_get_type_abort( - priv, struct async_req); - struct wb_trans_state *state = talloc_get_type_abort( - req->private_data, struct wb_trans_state); - - TALLOC_FREE(state->te); - async_req_error(req, NT_STATUS_IO_TIMEOUT); -} - -static void wb_trans_sent(struct async_req *subreq) -{ - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct wb_trans_state *state = talloc_get_type_abort( - req->private_data, struct wb_trans_state); - NTSTATUS status; - - status = wb_req_write_recv(subreq); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); - return; - } - - subreq = wb_resp_read_send(state, state->ev, state->fd); - if (async_req_nomem(subreq, req)) { - return; - } - - subreq->async.fn = wb_trans_received; - subreq->async.priv = req; -}; - -static void wb_trans_received(struct async_req *subreq) -{ - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct wb_trans_state *state = talloc_get_type_abort( - req->private_data, struct wb_trans_state); - NTSTATUS status; - - TALLOC_FREE(state->te); - - status = wb_resp_read_recv(subreq, state, &state->wb_resp); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); - return; - } - - async_req_done(req); -} - -NTSTATUS wb_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, - struct winbindd_response **presp) -{ - struct wb_trans_state *state = talloc_get_type_abort( - req->private_data, struct wb_trans_state); - NTSTATUS status; - - if (async_req_is_error(req, &status)) { - return status; - } - *presp = talloc_move(mem_ctx, &state->wb_resp); - return NT_STATUS_OK; -} - -struct wb_trans_queue_state { - struct wb_trans_queue_state *prev, *next; - struct wb_trans_queue *queue; - struct winbindd_request *req; -}; - -struct wb_trans_queue { - int fd; - struct timeval timeout; - size_t max_resp_extra_data; - struct wb_trans_queue_state *queued_requests; -}; diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 92ce1f9850..3869ac5771 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -88,15 +88,6 @@ struct async_req *wb_resp_write_send(TALLOC_CTX *mem_ctx, struct winbindd_response *wb_resp); NTSTATUS wb_resp_write_recv(struct async_req *req); -struct async_req *wb_trans_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - int fd, - struct winbindd_request *wb_req, - struct timeval timeout, - size_t reply_max_extra_data); -NTSTATUS wb_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, - struct winbindd_response **presp); - /* The following definitions come from winbindd/winbindd_ads.c */ -- cgit From 4df681abf497c24e8abf3df1137023389bfed709 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 27 Dec 2008 18:43:03 +0100 Subject: async libwbclient infrastructure --- source3/include/proto.h | 10 + source3/include/smb.h | 1 + source3/lib/wbclient.c | 774 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 785 insertions(+) create mode 100644 source3/lib/wbclient.c (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index 42d1f52fe1..dc63611514 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -7982,4 +7982,14 @@ NTSTATUS idmap_sid_to_gid(const char *domname, DOM_SID *sid, gid_t *gid); NTSTATUS nss_info_template_init( void ); +/* Misc protos */ + +struct async_req *wb_trans_send(TALLOC_CTX *mem_ctx, struct event_context *ev, + struct wb_context *wb_ctx, bool need_priv, + const struct winbindd_request *wb_req); +NTSTATUS wb_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, + struct winbindd_response **presponse); +struct wb_context *wb_context_init(TALLOC_CTX *mem_ctx); + + #endif /* _PROTO_H_ */ diff --git a/source3/include/smb.h b/source3/include/smb.h index 3253773903..7fd4fbb553 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -369,6 +369,7 @@ struct share_mode_entry; struct uuid; struct named_mutex; struct pcap_cache; +struct wb_context; struct vfs_fsp_data { struct vfs_fsp_data *next; diff --git a/source3/lib/wbclient.c b/source3/lib/wbclient.c new file mode 100644 index 0000000000..d58c934c07 --- /dev/null +++ b/source3/lib/wbclient.c @@ -0,0 +1,774 @@ +/* + Unix SMB/CIFS implementation. + Infrastructure for async winbind requests + Copyright (C) Volker Lendecke 2008 + + 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 . +*/ + +#include "includes.h" +#include "winbindd/winbindd.h" +#include "winbindd/winbindd_proto.h" + +static int make_nonstd_fd(int fd) +{ + int i; + int sys_errno = 0; + int fds[3]; + int num_fds = 0; + + if (fd == -1) { + return -1; + } + while (fd < 3) { + fds[num_fds++] = fd; + fd = dup(fd); + if (fd == -1) { + sys_errno = errno; + break; + } + } + for (i=0; i= 0) { + flags |= FD_CLOEXEC; + result = fcntl( new_fd, F_SETFD, flags ); + } + if (result < 0) { + goto fail; + } +#endif + return new_fd; + + fail: + if (new_fd != -1) { + int sys_errno = errno; + close(new_fd); + errno = sys_errno; + } + return -1; +} + +static bool winbind_closed_fd(int fd) +{ + struct timeval tv; + fd_set r_fds; + + if (fd == -1) { + return true; + } + + FD_ZERO(&r_fds); + FD_SET(fd, &r_fds); + ZERO_STRUCT(tv); + + if ((select(fd+1, &r_fds, NULL, NULL, &tv) == -1) + || FD_ISSET(fd, &r_fds)) { + return true; + } + + return false; +} + +struct wb_context { + struct async_req_queue *queue; + int fd; + bool is_priv; +}; + +struct wb_context *wb_context_init(TALLOC_CTX *mem_ctx) +{ + struct wb_context *result; + + result = talloc(mem_ctx, struct wb_context); + if (result == NULL) { + return NULL; + } + result->queue = async_req_queue_init(result); + if (result->queue == NULL) { + TALLOC_FREE(result); + return NULL; + } + result->fd = -1; + return result; +} + +static struct async_req *wb_connect_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct wb_context *wb_ctx, + const char *dir) +{ + struct async_req *req; + struct sockaddr_un sunaddr; + struct stat st; + char *path = NULL; + NTSTATUS status; + + if (wb_ctx->fd != -1) { + close(wb_ctx->fd); + wb_ctx->fd = -1; + } + + /* Check permissions on unix socket directory */ + + if (lstat(dir, &st) == -1) { + status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + goto post_status; + } + + if (!S_ISDIR(st.st_mode) || + (st.st_uid != 0 && st.st_uid != geteuid())) { + status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + goto post_status; + } + + /* Connect to socket */ + + path = talloc_asprintf(talloc_tos(), "%s/%s", dir, + WINBINDD_SOCKET_NAME); + if (path == NULL) { + goto nomem; + } + + sunaddr.sun_family = AF_UNIX; + strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)); + TALLOC_FREE(path); + + /* If socket file doesn't exist, don't bother trying to connect + with retry. This is an attempt to make the system usable when + the winbindd daemon is not running. */ + + if ((lstat(sunaddr.sun_path, &st) == -1) + || !S_ISSOCK(st.st_mode) + || (st.st_uid != 0 && st.st_uid != geteuid())) { + status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + goto post_status; + } + + wb_ctx->fd = make_safe_fd(socket(AF_UNIX, SOCK_STREAM, 0)); + if (wb_ctx->fd == -1) { + status = map_nt_error_from_unix(errno); + goto post_status; + } + + req = async_connect_send(mem_ctx, ev, wb_ctx->fd, + (struct sockaddr *)&sunaddr, + sizeof(sunaddr)); + if (req == NULL) { + goto nomem; + } + if (!async_req_set_timeout(req, ev, timeval_set(30, 0))) { + TALLOC_FREE(req); + goto nomem; + } + + return req; + + nomem: + status = NT_STATUS_NO_MEMORY; + post_status: + req = async_req_new(mem_ctx); + if (req == NULL) { + return NULL; + } + if (async_post_status(req, ev, status)) { + return req; + } + TALLOC_FREE(req); + return NULL; +} + +static NTSTATUS wb_connect_recv(struct async_req *req) +{ + int dummy; + + return async_connect_recv(req, &dummy); +} + +static struct winbindd_request *winbindd_request_copy( + TALLOC_CTX *mem_ctx, + const struct winbindd_request *req) +{ + struct winbindd_request *result; + + result = (struct winbindd_request *)TALLOC_MEMDUP( + mem_ctx, req, sizeof(struct winbindd_request)); + if (result == NULL) { + return NULL; + } + + if (result->extra_len == 0) { + return result; + } + + result->extra_data.data = (char *)TALLOC_MEMDUP( + result, result->extra_data.data, result->extra_len); + if (result->extra_data.data == NULL) { + TALLOC_FREE(result); + return NULL; + } + return result; +} + +struct wb_int_trans_state { + struct event_context *ev; + int fd; + struct winbindd_request *wb_req; + struct winbindd_response *wb_resp; +}; + +static void wb_int_trans_write_done(struct async_req *subreq); +static void wb_int_trans_read_done(struct async_req *subreq); + +static struct async_req *wb_int_trans_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, int fd, + struct winbindd_request *wb_req) +{ + struct async_req *result; + struct async_req *subreq; + struct wb_int_trans_state *state; + + result = async_req_new(mem_ctx); + if (result == NULL) { + return NULL; + } + state = talloc(result, struct wb_int_trans_state); + if (state == NULL) { + goto fail; + } + result->private_data = state; + + if (winbind_closed_fd(fd)) { + if (!async_post_status(result, ev, + NT_STATUS_PIPE_DISCONNECTED)) { + goto fail; + } + return result; + } + + state->ev = ev; + state->fd = fd; + state->wb_req = wb_req; + + state->wb_req->length = sizeof(struct winbindd_request); + state->wb_req->pid = getpid(); + + subreq = wb_req_write_send(state, state->ev, state->fd, state->wb_req); + if (subreq == NULL) { + goto fail; + } + subreq->async.fn = wb_int_trans_write_done; + subreq->async.priv = result; + + return result; + + fail: + TALLOC_FREE(result); + return NULL; +} + +static void wb_int_trans_write_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_int_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_int_trans_state); + NTSTATUS status; + + status = wb_req_write_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + subreq = wb_resp_read_send(state, state->ev, state->fd); + if (subreq == NULL) { + async_req_error(req, NT_STATUS_NO_MEMORY); + } + subreq->async.fn = wb_int_trans_read_done; + subreq->async.priv = req; +} + +static void wb_int_trans_read_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_int_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_int_trans_state); + NTSTATUS status; + + status = wb_resp_read_recv(subreq, state, &state->wb_resp); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + async_req_done(req); +} + +static NTSTATUS wb_int_trans_recv(struct async_req *req, + TALLOC_CTX *mem_ctx, + struct winbindd_response **presponse) +{ + struct wb_int_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_int_trans_state); + NTSTATUS status; + + if (async_req_is_error(req, &status)) { + return status; + } + + *presponse = talloc_move(mem_ctx, &state->wb_resp); + return NT_STATUS_OK; +} + +static const char *winbindd_socket_dir(void) +{ +#ifdef SOCKET_WRAPPER + const char *env_dir; + + env_dir = getenv(WINBINDD_SOCKET_DIR_ENVVAR); + if (env_dir) { + return env_dir; + } +#endif + + return WINBINDD_SOCKET_DIR; +} + +struct wb_open_pipe_state { + struct wb_context *wb_ctx; + struct event_context *ev; + bool need_priv; + struct winbindd_request wb_req; +}; + +static void wb_open_pipe_connect_nonpriv_done(struct async_req *subreq); +static void wb_open_pipe_ping_done(struct async_req *subreq); +static void wb_open_pipe_getpriv_done(struct async_req *subreq); +static void wb_open_pipe_connect_priv_done(struct async_req *subreq); + +static struct async_req *wb_open_pipe_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct wb_context *wb_ctx, + bool need_priv) +{ + struct async_req *result; + struct async_req *subreq; + struct wb_open_pipe_state *state; + + result = async_req_new(mem_ctx); + if (result == NULL) { + return NULL; + } + state = talloc(result, struct wb_open_pipe_state); + if (state == NULL) { + goto fail; + } + result->private_data = state; + + state->wb_ctx = wb_ctx; + state->ev = ev; + state->need_priv = need_priv; + + if (wb_ctx->fd != -1) { + close(wb_ctx->fd); + wb_ctx->fd = -1; + } + + subreq = wb_connect_send(state, ev, wb_ctx, winbindd_socket_dir()); + if (subreq == NULL) { + goto fail; + } + + subreq->async.fn = wb_open_pipe_connect_nonpriv_done; + subreq->async.priv = result; + return result; + + fail: + TALLOC_FREE(result); + return NULL; +} + +static void wb_open_pipe_connect_nonpriv_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_open_pipe_state *state = talloc_get_type_abort( + req->private_data, struct wb_open_pipe_state); + NTSTATUS status; + + status = wb_connect_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + state->wb_ctx->is_priv = true; + async_req_error(req, status); + return; + } + + ZERO_STRUCT(state->wb_req); + state->wb_req.cmd = WINBINDD_INTERFACE_VERSION; + + subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->fd, + &state->wb_req); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_open_pipe_ping_done; + subreq->async.priv = req; +} + +static void wb_open_pipe_ping_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_open_pipe_state *state = talloc_get_type_abort( + req->private_data, struct wb_open_pipe_state); + struct winbindd_response *wb_resp; + NTSTATUS status; + + status = wb_int_trans_recv(subreq, state, &wb_resp); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + if (!state->need_priv) { + async_req_done(req); + return; + } + + state->wb_req.cmd = WINBINDD_PRIV_PIPE_DIR; + + subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->fd, + &state->wb_req); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_open_pipe_getpriv_done; + subreq->async.priv = req; +} + +static void wb_open_pipe_getpriv_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_open_pipe_state *state = talloc_get_type_abort( + req->private_data, struct wb_open_pipe_state); + struct winbindd_response *wb_resp = NULL; + NTSTATUS status; + + status = wb_int_trans_recv(subreq, state, &wb_resp); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + close(state->wb_ctx->fd); + state->wb_ctx->fd = -1; + + subreq = wb_connect_send(state, state->ev, state->wb_ctx, + (char *)wb_resp->extra_data.data); + TALLOC_FREE(wb_resp); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_open_pipe_connect_priv_done; + subreq->async.priv = req; +} + +static void wb_open_pipe_connect_priv_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_open_pipe_state *state = talloc_get_type_abort( + req->private_data, struct wb_open_pipe_state); + NTSTATUS status; + + status = wb_connect_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + state->wb_ctx->is_priv = true; + async_req_done(req); +} + +static NTSTATUS wb_open_pipe_recv(struct async_req *req) +{ + return async_req_simple_recv(req); +} + +struct wb_trans_state { + struct wb_trans_state *prev, *next; + struct wb_context *wb_ctx; + struct event_context *ev; + struct winbindd_request *wb_req; + struct winbindd_response *wb_resp; + int num_retries; + bool need_priv; +}; + +static void wb_trans_connect_done(struct async_req *subreq); +static void wb_trans_done(struct async_req *subreq); +static void wb_trans_retry_wait_done(struct async_req *subreq); + +static void wb_trigger_trans(struct async_req *req) +{ + struct wb_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_trans_state); + struct async_req *subreq; + + if ((state->wb_ctx->fd == -1) + || (state->need_priv && !state->wb_ctx->is_priv)) { + + subreq = wb_open_pipe_send(state, state->ev, state->wb_ctx, + state->need_priv); + if (async_req_nomem(subreq, req)) { + return; + } + subreq->async.fn = wb_trans_connect_done; + subreq->async.priv = req; + return; + } + + subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->fd, + state->wb_req); + if (async_req_nomem(subreq, req)) { + return; + } + subreq->async.fn = wb_trans_done; + subreq->async.priv = req; +} + +struct async_req *wb_trans_send(TALLOC_CTX *mem_ctx, struct event_context *ev, + struct wb_context *wb_ctx, bool need_priv, + const struct winbindd_request *wb_req) +{ + struct async_req *result; + struct wb_trans_state *state; + + result = async_req_new(mem_ctx); + if (result == NULL) { + return NULL; + } + state = talloc(result, struct wb_trans_state); + if (state == NULL) { + goto fail; + } + result->private_data = state; + + state->wb_ctx = wb_ctx; + state->ev = ev; + state->wb_req = winbindd_request_copy(state, wb_req); + if (state->wb_req == NULL) { + goto fail; + } + state->num_retries = 10; + state->need_priv = need_priv; + + if (!async_req_enqueue(wb_ctx->queue, ev, result, wb_trigger_trans)) { + goto fail; + } + return result; + + fail: + TALLOC_FREE(result); + return NULL; +} + +static bool wb_trans_retry(struct async_req *req, + struct wb_trans_state *state, + NTSTATUS status) +{ + struct async_req *subreq; + + if (NT_STATUS_IS_OK(status)) { + return false; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) + || NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { + /* + * Winbind not around or we can't connect to the pipe. Fail + * immediately. + */ + async_req_error(req, status); + return true; + } + + state->num_retries -= 1; + if (state->num_retries == 0) { + async_req_error(req, status); + return true; + } + + /* + * The transfer as such failed, retry after one second + */ + + if (state->wb_ctx->fd != -1) { + close(state->wb_ctx->fd); + state->wb_ctx->fd = -1; + } + + subreq = async_wait_send(state, state->ev, timeval_set(1, 0)); + if (async_req_nomem(subreq, req)) { + return true; + } + + subreq->async.fn = wb_trans_retry_wait_done; + subreq->async.priv = req; + return true; +} + +static void wb_trans_retry_wait_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_trans_state); + NTSTATUS status; + + status = async_wait_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { + async_req_error(req, status); + return; + } + + subreq = wb_open_pipe_send(state, state->ev, state->wb_ctx, + state->need_priv); + if (async_req_nomem(subreq, req)) { + return; + } + subreq->async.fn = wb_trans_connect_done; + subreq->async.priv = req; +} + +static void wb_trans_connect_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_trans_state); + NTSTATUS status; + + status = wb_open_pipe_recv(subreq); + TALLOC_FREE(subreq); + + if (wb_trans_retry(req, state, status)) { + return; + } + + subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->fd, + state->wb_req); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_trans_done; + subreq->async.priv = req; +} + +static void wb_trans_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_trans_state); + NTSTATUS status; + + status = wb_int_trans_recv(subreq, state, &state->wb_resp); + TALLOC_FREE(subreq); + + if (wb_trans_retry(req, state, status)) { + return; + } + + async_req_done(req); +} + +NTSTATUS wb_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, + struct winbindd_response **presponse) +{ + struct wb_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_trans_state); + NTSTATUS status; + + if (async_req_is_error(req, &status)) { + return status; + } + + *presponse = talloc_move(mem_ctx, &state->wb_resp); + return NT_STATUS_OK; +} -- cgit From 1b328d98208d4245733dc8e04f6b81ab606ead8c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 28 Dec 2008 17:43:18 +0100 Subject: Add a quick test of wb_trans_send/recv --- source3/Makefile.in | 1 + source3/torture/torture.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index 8631520486..c13f5ae20a 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -930,6 +930,7 @@ SMBTORTURE_OBJ1 = torture/torture.o torture/nbio.o torture/scanner.o torture/uta SMBTORTURE_OBJ = $(SMBTORTURE_OBJ1) $(PARAM_OBJ) \ $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) \ + lib/wb_reqtrans.o lib/wbclient.o \ $(LIBNDR_GEN_OBJ0) MASKTEST_OBJ = torture/masktest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \ diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 3261e78d44..8a1a61e79a 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -5493,6 +5493,70 @@ static bool run_local_memcache(int dummy) return ret; } +static void wbclient_done(struct async_req *req) +{ + NTSTATUS status; + struct winbindd_response *wb_resp; + int *i = (int *)req->async.priv; + + status = wb_trans_recv(req, req, &wb_resp); + TALLOC_FREE(req); + *i += 1; + d_printf("wb_trans_recv %d returned %s\n", *i, nt_errstr(status)); +} + +static bool run_local_wbclient(int dummy) +{ + struct event_context *ev; + struct wb_context **wb_ctx; + struct winbindd_request wb_req; + bool result = false; + int i, j; + + BlockSignals(True, SIGPIPE); + + ev = event_context_init(talloc_tos()); + if (ev == NULL) { + goto fail; + } + + wb_ctx = TALLOC_ARRAY(ev, struct wb_context *, torture_numops); + if (wb_ctx == NULL) { + goto fail; + } + + ZERO_STRUCT(wb_req); + wb_req.cmd = WINBINDD_PING; + + for (i=0; iasync.fn = wbclient_done; + req->async.priv = &i; + } + } + + i = 0; + + while (i < 5 * torture_numops) { + event_loop_once(ev); + } + + result = true; + fail: + TALLOC_FREE(ev); + return result; +} + static double create_procs(bool (*fn)(int), bool *result) { int i, status; @@ -5652,6 +5716,7 @@ static struct { { "LOCAL-RBTREE", run_local_rbtree, 0}, { "LOCAL-MEMCACHE", run_local_memcache, 0}, { "LOCAL-STREAM-NAME", run_local_stream_name, 0}, + { "LOCAL-WBCLIENT", run_local_wbclient, 0}, {NULL, NULL, 0}}; -- cgit From 19b783cce9edf7b616cd1a9d9dcb78a02791d89e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 3 Jan 2009 19:50:05 +0100 Subject: Async wrapper for open_socket_out_send/recv --- source3/include/proto.h | 11 +- source3/lib/util_sock.c | 224 +++++++++++++++++++++-------- source3/libads/krb5_setpw.c | 31 ++-- source3/libsmb/cliconnect.c | 23 +-- source3/modules/vfs_smb_traffic_analyzer.c | 5 +- source3/rpc_client/cli_pipe.c | 5 +- 6 files changed, 215 insertions(+), 84 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index dc63611514..957302c378 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1457,9 +1457,14 @@ int open_socket_in(int type, int dlevel, const struct sockaddr_storage *psock, bool rebind); -int open_socket_out(const struct sockaddr_storage *pss, - uint16_t port, - int timeout); +NTSTATUS open_socket_out(const struct sockaddr_storage *pss, uint16_t port, + int timeout, int *pfd); +struct async_req *open_socket_out_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + const struct sockaddr_storage *pss, + uint16_t port, + int timeout); +NTSTATUS open_socket_out_recv(struct async_req *req, int *pfd); bool open_any_socket_out(struct sockaddr_storage *addrs, int num_addrs, int timeout, int *fd_index, int *fd); int open_udp_socket(const char *host, int port); diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index a8c3b3031d..3356318c88 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -948,96 +948,208 @@ int open_socket_in(int type, return( res ); } +struct open_socket_out_state { + int fd; + struct event_context *ev; + struct sockaddr_storage ss; + socklen_t salen; + uint16_t port; + int wait_nsec; +}; + +static void open_socket_out_connected(struct async_req *subreq); + +static int open_socket_out_state_destructor(struct open_socket_out_state *s) +{ + if (s->fd != -1) { + close(s->fd); + } + return 0; +} + /**************************************************************************** Create an outgoing socket. timeout is in milliseconds. **************************************************************************/ -int open_socket_out(const struct sockaddr_storage *pss, uint16_t port, - int timeout) +struct async_req *open_socket_out_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + const struct sockaddr_storage *pss, + uint16_t port, + int timeout) { char addr[INET6_ADDRSTRLEN]; - struct sockaddr_storage sock_out = *pss; - int res,ret; - int connect_loop = 10; - int increment = 10; + struct async_req *result, *subreq; + struct open_socket_out_state *state; + NTSTATUS status; - /* create a socket to write to */ - res = socket(pss->ss_family, SOCK_STREAM, 0); - if (res == -1) { - DEBUG(0,("socket error (%s)\n", strerror(errno))); - return -1; + result = async_req_new(mem_ctx); + if (result == NULL) { + return NULL; + } + state = talloc(result, struct open_socket_out_state); + if (state == NULL) { + goto fail; + } + result->private_data = state; + + state->ev = ev; + state->ss = *pss; + state->port = port; + state->wait_nsec = 10000; + state->salen = -1; + + state->fd = socket(state->ss.ss_family, SOCK_STREAM, 0); + if (state->fd == -1) { + status = map_nt_error_from_unix(errno); + goto post_status; + } + talloc_set_destructor(state, open_socket_out_state_destructor); + + if (!async_req_set_timeout(result, ev, timeval_set(0, timeout*1000))) { + goto fail; } #if defined(HAVE_IPV6) if (pss->ss_family == AF_INET6) { - struct sockaddr_in6 *psa6 = (struct sockaddr_in6 *)&sock_out; + struct sockaddr_in6 *psa6; + psa6 = (struct sockaddr_in6 *)&state->ss; psa6->sin6_port = htons(port); - if (psa6->sin6_scope_id == 0 && - IN6_IS_ADDR_LINKLOCAL(&psa6->sin6_addr)) { - setup_linklocal_scope_id((struct sockaddr *)&sock_out); + if (psa6->sin6_scope_id == 0 + && IN6_IS_ADDR_LINKLOCAL(&psa6->sin6_addr)) { + setup_linklocal_scope_id( + (struct sockaddr *)&(state->ss)); } + state->salen = sizeof(struct sockaddr_in6); } #endif if (pss->ss_family == AF_INET) { - struct sockaddr_in *psa = (struct sockaddr_in *)&sock_out; + struct sockaddr_in *psa; + psa = (struct sockaddr_in *)&state->ss; psa->sin_port = htons(port); + state->salen = sizeof(struct sockaddr_in); } - /* set it non-blocking */ - set_blocking(res,false); + print_sockaddr(addr, sizeof(addr), &state->ss); + DEBUG(3,("Connecting to %s at port %u\n", addr, (unsigned int)port)); - print_sockaddr(addr, sizeof(addr), &sock_out); - DEBUG(3,("Connecting to %s at port %u\n", - addr, - (unsigned int)port)); + subreq = async_connect_send(state, state->ev, state->fd, + (struct sockaddr *)&state->ss, + state->salen); + if ((subreq == NULL) + || !async_req_set_timeout(subreq, state->ev, + timeval_set(0, state->wait_nsec))) { + status = NT_STATUS_NO_MEMORY; + goto post_status; + } + subreq->async.fn = open_socket_out_connected; + subreq->async.priv = result; + return result; - /* and connect it to the destination */ - connect_again: + post_status: + if (!async_post_status(result, ev, status)) { + goto fail; + } + return result; + fail: + TALLOC_FREE(result); + return NULL; +} - ret = sys_connect(res, (struct sockaddr *)&sock_out); +static void open_socket_out_connected(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct open_socket_out_state *state = talloc_get_type_abort( + req->private_data, struct open_socket_out_state); + NTSTATUS status; + int sys_errno; - /* Some systems return EAGAIN when they mean EINPROGRESS */ - if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || - errno == EAGAIN) && (connect_loop < timeout) ) { - smb_msleep(connect_loop); - timeout -= connect_loop; - connect_loop += increment; - if (increment < 250) { - /* After 8 rounds we end up at a max of 255 msec */ - increment *= 1.5; - } - goto connect_again; + status = async_connect_recv(subreq, &sys_errno); + TALLOC_FREE(subreq); + if (NT_STATUS_IS_OK(status)) { + async_req_done(req); + return; } - if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || - errno == EAGAIN)) { - DEBUG(1,("timeout connecting to %s:%u\n", - addr, - (unsigned int)port)); - close(res); - return -1; + if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) + || (sys_errno == EINPROGRESS) + || (sys_errno == EALREADY) + || (sys_errno == EAGAIN)) { + + /* + * retry + */ + + if (state->wait_nsec < 250000) { + state->wait_nsec *= 1.5; + } + + subreq = async_connect_send(state, state->ev, state->fd, + (struct sockaddr *)&state->ss, + state->salen); + if (async_req_nomem(subreq, req)) { + return; + } + if (!async_req_set_timeout(subreq, state->ev, + timeval_set(0, state->wait_nsec))) { + async_req_error(req, NT_STATUS_NO_MEMORY); + return; + } + subreq->async.fn = open_socket_out_connected; + subreq->async.priv = req; + return; } #ifdef EISCONN - if (ret < 0 && errno == EISCONN) { - errno = 0; - ret = 0; + if (sys_errno == EISCONN) { + async_req_done(req); + return; } #endif - if (ret < 0) { - DEBUG(2,("error connecting to %s:%d (%s)\n", - addr, - (unsigned int)port, - strerror(errno))); - close(res); - return -1; + /* real error */ + async_req_error(req, map_nt_error_from_unix(sys_errno)); +} + +NTSTATUS open_socket_out_recv(struct async_req *req, int *pfd) +{ + struct open_socket_out_state *state = talloc_get_type_abort( + req->private_data, struct open_socket_out_state); + NTSTATUS status; + + if (async_req_is_error(req, &status)) { + return status; } + *pfd = state->fd; + state->fd = -1; + return NT_STATUS_OK; +} - /* set it blocking again */ - set_blocking(res,true); +NTSTATUS open_socket_out(const struct sockaddr_storage *pss, uint16_t port, + int timeout, int *pfd) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; + struct async_req *req; + NTSTATUS status = NT_STATUS_NO_MEMORY; - return res; + ev = event_context_init(frame); + if (ev == NULL) { + goto fail; + } + + req = open_socket_out_send(frame, ev, pss, port, timeout); + if (req == NULL) { + goto fail; + } + while (req->state < ASYNC_REQ_DONE) { + event_loop_once(ev); + } + + status = open_socket_out_recv(req, pfd); + fail: + TALLOC_FREE(frame); + return status; } /******************************************************************* diff --git a/source3/libads/krb5_setpw.c b/source3/libads/krb5_setpw.c index e164a55b38..7cdfbc58a4 100644 --- a/source3/libads/krb5_setpw.c +++ b/source3/libads/krb5_setpw.c @@ -425,21 +425,28 @@ static ADS_STATUS do_krb5_kpasswd_request(krb5_context context, if (!use_tcp) { sock = open_udp_socket(kdc_host, DEFAULT_KPASSWD_PORT); - + if (sock == -1) { + int rc = errno; + SAFE_FREE(ap_req.data); + krb5_auth_con_free(context, auth_context); + DEBUG(1,("failed to open kpasswd socket to %s " + "(%s)\n", kdc_host, strerror(errno))); + return ADS_ERROR_SYSTEM(rc); + } } else { - - sock = open_socket_out(&addr, DEFAULT_KPASSWD_PORT, - LONG_CONNECT_TIMEOUT); + NTSTATUS status; + status = open_socket_out(&addr, DEFAULT_KPASSWD_PORT, + LONG_CONNECT_TIMEOUT, &sock); + if (!NT_STATUS_IS_OK(status)) { + SAFE_FREE(ap_req.data); + krb5_auth_con_free(context, auth_context); + DEBUG(1,("failed to open kpasswd socket to %s " + "(%s)\n", kdc_host, + nt_errstr(status))); + return ADS_ERROR_NT(status); + } } - if (sock == -1) { - int rc = errno; - SAFE_FREE(ap_req.data); - krb5_auth_con_free(context, auth_context); - DEBUG(1,("failed to open kpasswd socket to %s (%s)\n", - kdc_host, strerror(errno))); - return ADS_ERROR_SYSTEM(rc); - } addr_len = sizeof(remote_addr); if (getpeername(sock, (struct sockaddr *)&remote_addr, &addr_len) != 0) { close(sock); diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 44899e3b1a..1b03459658 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -1494,15 +1494,17 @@ bool cli_session_request(struct cli_state *cli, */ uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9); struct in_addr dest_ip; + NTSTATUS status; /* SESSION RETARGET */ putip((char *)&dest_ip,cli->inbuf+4); in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip); - cli->fd = open_socket_out(&cli->dest_ss, port, - LONG_CONNECT_TIMEOUT); - if (cli->fd == -1) + status = open_socket_out(&cli->dest_ss, port, + LONG_CONNECT_TIMEOUT, &cli->fd); + if (!NT_STATUS_IS_OK(status)) { return False; + } DEBUG(3,("Retargeted\n")); @@ -1587,12 +1589,17 @@ NTSTATUS cli_connect(struct cli_state *cli, } else { /* try 445 first, then 139 */ uint16_t port = cli->port?cli->port:445; - cli->fd = open_socket_out(&cli->dest_ss, port, - cli->timeout); - if (cli->fd == -1 && cli->port == 0) { + NTSTATUS status; + + cli->fd = -1; + + status = open_socket_out(&cli->dest_ss, port, + cli->timeout, &cli->fd); + if (!NT_STATUS_IS_OK(status) && cli->port == 0) { port = 139; - cli->fd = open_socket_out(&cli->dest_ss, - port, cli->timeout); + status = open_socket_out( + &cli->dest_ss, port, cli->timeout, + &cli->fd); } if (cli->fd != -1) { cli->port = port; diff --git a/source3/modules/vfs_smb_traffic_analyzer.c b/source3/modules/vfs_smb_traffic_analyzer.c index fe292e5ce8..3ac5a4971b 100644 --- a/source3/modules/vfs_smb_traffic_analyzer.c +++ b/source3/modules/vfs_smb_traffic_analyzer.c @@ -78,6 +78,7 @@ static int smb_traffic_analyzer_connect_inet_socket(vfs_handle_struct *handle, for (res = ailist; res; res = res->ai_next) { struct sockaddr_storage ss; + NTSTATUS status; if (!res->ai_addr || res->ai_addrlen == 0) { continue; @@ -86,8 +87,8 @@ static int smb_traffic_analyzer_connect_inet_socket(vfs_handle_struct *handle, ZERO_STRUCT(ss); memcpy(&ss, res->ai_addr, res->ai_addrlen); - sockfd = open_socket_out(&ss, port, 10000); - if (sockfd != -1) { + status = open_socket_out(&ss, port, 10000, &sockfd); + if (NT_STATUS_IS_OK(status)) { break; } } diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 45eab503fe..3fd31e2867 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2618,9 +2618,8 @@ static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host, goto fail; } - result->trans.sock.fd = open_socket_out(&addr, port, 60); - if (result->trans.sock.fd == -1) { - status = map_nt_error_from_unix(errno); + status = open_socket_out(&addr, port, 60, &result->trans.sock.fd); + if (!NT_STATUS_IS_OK(status)) { goto fail; } -- cgit From 0cc63c64166d2e26b7a7ffc0e78ea6041de35f53 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 4 Jan 2009 01:45:06 +0100 Subject: Add open_socket_out_defer_send/recv --- source3/include/proto.h | 7 +++ source3/lib/util_sock.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index 957302c378..6238ba3d00 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1465,6 +1465,13 @@ struct async_req *open_socket_out_send(TALLOC_CTX *mem_ctx, uint16_t port, int timeout); NTSTATUS open_socket_out_recv(struct async_req *req, int *pfd); +struct async_req *open_socket_out_defer_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct timeval wait_time, + const struct sockaddr_storage *pss, + uint16_t port, + int timeout); +NTSTATUS open_socket_out_defer_recv(struct async_req *req, int *pfd); bool open_any_socket_out(struct sockaddr_storage *addrs, int num_addrs, int timeout, int *fd_index, int *fd); int open_udp_socket(const char *host, int port); diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index 3356318c88..518bb78f65 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -1152,6 +1152,117 @@ NTSTATUS open_socket_out(const struct sockaddr_storage *pss, uint16_t port, return status; } +struct open_socket_out_defer_state { + struct event_context *ev; + struct sockaddr_storage ss; + uint16_t port; + int timeout; + int fd; +}; + +static void open_socket_out_defer_waited(struct async_req *subreq); +static void open_socket_out_defer_connected(struct async_req *subreq); + +struct async_req *open_socket_out_defer_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct timeval wait_time, + const struct sockaddr_storage *pss, + uint16_t port, + int timeout) +{ + struct async_req *result, *subreq; + struct open_socket_out_defer_state *state; + NTSTATUS status; + + result = async_req_new(mem_ctx); + if (result == NULL) { + return NULL; + } + state = talloc(result, struct open_socket_out_defer_state); + if (state == NULL) { + goto fail; + } + result->private_data = state; + + state->ev = ev; + state->ss = *pss; + state->port = port; + state->timeout = timeout; + + subreq = async_wait_send(state, ev, wait_time); + if (subreq == NULL) { + status = NT_STATUS_NO_MEMORY; + goto post_status; + } + subreq->async.fn = open_socket_out_defer_waited; + subreq->async.priv = result; + return result; + + post_status: + if (!async_post_status(result, ev, status)) { + goto fail; + } + return result; + fail: + TALLOC_FREE(result); + return NULL; +} + +static void open_socket_out_defer_waited(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct open_socket_out_defer_state *state = talloc_get_type_abort( + req->private_data, struct open_socket_out_defer_state); + NTSTATUS status; + + status = async_wait_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + subreq = open_socket_out_send(state, state->ev, &state->ss, + state->port, state->timeout); + if (async_req_nomem(subreq, req)) { + return; + } + subreq->async.fn = open_socket_out_defer_connected; + subreq->async.priv = req; +} + +static void open_socket_out_defer_connected(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct open_socket_out_defer_state *state = talloc_get_type_abort( + req->private_data, struct open_socket_out_defer_state); + NTSTATUS status; + + status = open_socket_out_recv(subreq, &state->fd); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + async_req_done(req); +} + +NTSTATUS open_socket_out_defer_recv(struct async_req *req, int *pfd) +{ + struct open_socket_out_defer_state *state = talloc_get_type_abort( + req->private_data, struct open_socket_out_defer_state); + NTSTATUS status; + + if (async_req_is_error(req, &status)) { + return status; + } + *pfd = state->fd; + state->fd = -1; + return NT_STATUS_OK; +} + /******************************************************************* Create an outgoing TCP socket to the first addr that connects. -- cgit From b4f8996ac79309a3ff4cd299e7978ec9f993a5c4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 4 Jan 2009 01:46:05 +0100 Subject: Simulate the Windows behaviour to fire 445 and after a timeout 139 --- source3/libsmb/cliconnect.c | 90 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 76 insertions(+), 14 deletions(-) (limited to 'source3') diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 1b03459658..6ddc249c04 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -1533,6 +1533,78 @@ bool cli_session_request(struct cli_state *cli, return(True); } +static void smb_sock_connected(struct async_req *req) +{ + int *pfd = (int *)req->async.priv; + int fd; + NTSTATUS status; + + status = open_socket_out_defer_recv(req, &fd); + if (NT_STATUS_IS_OK(status)) { + *pfd = fd; + } +} + +static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss, + uint16_t *port, int timeout, int *pfd) +{ + struct event_context *ev; + struct async_req *r139, *r445; + int fd139 = -1; + int fd445 = -1; + NTSTATUS status; + + if (*port != 0) { + return open_socket_out(pss, *port, timeout, pfd); + } + + ev = event_context_init(talloc_tos()); + if (ev == NULL) { + return NT_STATUS_NO_MEMORY; + } + + r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0), + pss, 445, timeout); + r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000), + pss, 139, timeout); + if ((r445 == NULL) || (r139 == NULL)) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + r445->async.fn = smb_sock_connected; + r445->async.priv = &fd445; + r139->async.fn = smb_sock_connected; + r139->async.priv = &fd139; + + while ((fd139 == -1) && (r139->state < ASYNC_REQ_DONE) + && (fd445 == -1) && (r445->state < ASYNC_REQ_DONE)) { + event_loop_once(ev); + } + + if ((fd139 != -1) && (fd445 != -1)) { + close(fd139); + fd139 = -1; + } + + if (fd445 != -1) { + *port = 445; + *pfd = fd445; + status = NT_STATUS_OK; + goto done; + } + if (fd139 != -1) { + *port = 139; + *pfd = fd139; + status = NT_STATUS_OK; + goto done; + } + + status = open_socket_out_defer_recv(r445, &fd445); + done: + TALLOC_FREE(ev); + return status; +} + /**************************************************************************** Open the client sockets. ****************************************************************************/ @@ -1587,21 +1659,11 @@ NTSTATUS cli_connect(struct cli_state *cli, if (getenv("LIBSMB_PROG")) { cli->fd = sock_exec(getenv("LIBSMB_PROG")); } else { - /* try 445 first, then 139 */ - uint16_t port = cli->port?cli->port:445; + uint16_t port = cli->port; NTSTATUS status; - - cli->fd = -1; - - status = open_socket_out(&cli->dest_ss, port, - cli->timeout, &cli->fd); - if (!NT_STATUS_IS_OK(status) && cli->port == 0) { - port = 139; - status = open_socket_out( - &cli->dest_ss, port, cli->timeout, - &cli->fd); - } - if (cli->fd != -1) { + status = open_smb_socket(&cli->dest_ss, &port, + cli->timeout, &cli->fd); + if (NT_STATUS_IS_OK(status)) { cli->port = port; } } -- cgit From c4ff426f673ca4be01a599af80a9b99616b1543a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 4 Jan 2009 17:28:24 +0100 Subject: Fix the build of smbfilter --- source3/utils/smbfilter.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/utils/smbfilter.c b/source3/utils/smbfilter.c index e7b71bd5db..1fdea818d6 100644 --- a/source3/utils/smbfilter.c +++ b/source3/utils/smbfilter.c @@ -141,10 +141,11 @@ static bool send_smb(int fd, char *buffer) static void filter_child(int c, struct sockaddr_storage *dest_ss) { - int s; + NTSTATUS status; + int s = -1; /* we have a connection from a new client, now connect to the server */ - s = open_socket_out(dest_ss, 445, LONG_CONNECT_TIMEOUT); + status = open_socket_out(dest_ss, 445, LONG_CONNECT_TIMEOUT, &s); if (s == -1) { char addr[INET6_ADDRSTRLEN]; -- cgit From fe56659442bd5ad7298720b830c26f595189ed2e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 4 Jan 2009 18:03:23 +0100 Subject: Remove a duplicated comment --- source3/lib/util_sock.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3') diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index 518bb78f65..e913b35d60 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -707,10 +707,6 @@ ssize_t write_data_iov(int fd, const struct iovec *orig_iov, int iovcnt) Write data to a fd. ****************************************************************************/ -/**************************************************************************** - Write data to a fd. -****************************************************************************/ - ssize_t write_data(int fd, const char *buffer, size_t N) { ssize_t ret; -- cgit From 81624030efdcdc3b19651d79df0c50c5ef046581 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 4 Jan 2009 18:14:33 +0100 Subject: Fix a typo found by the IBM Checker --- source3/param/loadparm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 274c79904e..cb0ba47572 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -4630,7 +4630,7 @@ static void free_one_parameter_by_snum(int snum, struct parm_struct parm) { void *parm_ptr; - if (parm.ptr == NULL); { + if (parm.ptr == NULL) { return; } -- cgit From 033428d7da12a6ddc741aa6c70c65eca57b6d182 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 4 Jan 2009 17:58:56 +0100 Subject: tevent: move samba4 stuff from libtevent.m4 to samba.m4 metze --- source3/samba4.m4 | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'source3') diff --git a/source3/samba4.m4 b/source3/samba4.m4 index fe3995dfa0..a7916ef794 100644 --- a/source3/samba4.m4 +++ b/source3/samba4.m4 @@ -66,12 +66,7 @@ SMB_EXT_LIB_FROM_PKGCONFIG(LIBTDB, tdb >= 1.1.3, SMB_INCLUDE_MK(../lib/tdb/python.mk) SMB_EXT_LIB_FROM_PKGCONFIG(LIBTEVENT, tevent >= 0.9.2, - [], - [ - m4_include(../lib/tevent/libtevent.m4) - SMB_INCLUDE_MK(../lib/tevent/config.mk) - AC_CONFIG_FILES(../lib/tevent/tevent.pc) - ] + [],[m4_include(../lib/tevent/samba.m4)] ) SMB_INCLUDE_MK(../lib/tevent/python.mk) -- cgit From 2c0faaf5d921fe57a88d3b999067458e8774c6f6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 4 Jan 2009 11:47:16 -0800 Subject: Fix bug #6009 - Setting "min receivefile size = 1" breaks writes. Jeremy. --- source3/smbd/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 8466e84179..67e6067b26 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -284,7 +284,7 @@ static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, int fd, if (CVAL(lenbuf,0) == 0 && min_recv_size && - smb_len_large(lenbuf) > min_recv_size && /* Could be a UNIX large writeX. */ + smb_len_large(lenbuf) > (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE) && /* Could be a UNIX large writeX. */ !srv_is_signing_active()) { return receive_smb_raw_talloc_partial_read( -- cgit