summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/Makefile.in7
-rw-r--r--source3/include/ads_protos.h2
-rw-r--r--source3/include/async_smb.h146
-rw-r--r--source3/include/client.h30
-rw-r--r--source3/include/includes.h8
-rw-r--r--source3/include/proto.h222
-rw-r--r--source3/include/smbldap.h3
-rw-r--r--source3/lib/eventlog/eventlog.c (renamed from source3/rpc_server/srv_eventlog_lib.c)74
-rw-r--r--source3/lib/ms_fnmatch.c14
-rw-r--r--source3/lib/smbconf/smbconf_reg.c2
-rw-r--r--source3/lib/smbldap.c46
-rw-r--r--source3/lib/util_sock.c91
-rw-r--r--source3/lib/util_unistr.c199
-rw-r--r--source3/libads/authdata.c2
-rw-r--r--source3/libads/kerberos.c8
-rw-r--r--source3/libads/kerberos_keytab.c27
-rw-r--r--source3/libads/kerberos_verify.c6
-rw-r--r--source3/libads/ldap.c69
-rw-r--r--source3/libgpo/gpo_ldap.c8
-rw-r--r--source3/libnet/libnet_join.c4
-rw-r--r--source3/libnet/libnet_keytab.c32
-rw-r--r--source3/libsmb/async_smb.c1388
-rw-r--r--source3/libsmb/cliconnect.c339
-rw-r--r--source3/libsmb/clientgen.c157
-rw-r--r--source3/libsmb/clifile.c342
-rw-r--r--source3/libsmb/clikrb5.c23
-rw-r--r--source3/libsmb/clioplock.c123
-rw-r--r--source3/libsmb/clireadwrite.c611
-rw-r--r--source3/libsmb/clitrans.c668
-rw-r--r--source3/locking/brlock.c4
-rw-r--r--source3/modules/vfs_gpfs.c32
-rw-r--r--source3/modules/vfs_gpfs.h2
-rw-r--r--source3/modules/vfs_onefs.c12
-rw-r--r--source3/param/loadparm.c4
-rw-r--r--source3/passdb/pdb_ldap.c43
-rw-r--r--source3/passdb/pdb_nds.c4
-rw-r--r--source3/printing/nt_printing.c48
-rw-r--r--source3/rpc_client/cli_pipe.c18
-rw-r--r--source3/rpc_client/rpc_transport_np.c119
-rw-r--r--source3/rpc_client/rpc_transport_smbd.c237
-rw-r--r--source3/rpc_parse/parse_prs.c38
-rw-r--r--source3/rpc_server/srv_lsa_nt.c8
-rw-r--r--source3/rpc_server/srv_ntsvcs_nt.c41
-rw-r--r--source3/rpc_server/srv_samr_nt.c86
-rw-r--r--source3/rpc_server/srv_spoolss_nt.c245
-rw-r--r--source3/rpc_server/srv_svcctl_nt.c43
-rw-r--r--source3/rpc_server/srv_util.c88
-rw-r--r--source3/rpcclient/cmd_ntsvcs.c12
-rwxr-xr-xsource3/script/tests/selftest.sh3
-rwxr-xr-xsource3/script/tests/test_posix_s3.sh1
-rw-r--r--source3/smbd/ipc.c4
-rw-r--r--source3/smbd/oplock.c131
-rw-r--r--source3/smbd/oplock_onefs.c79
-rw-r--r--source3/smbd/sesssetup.c8
-rw-r--r--source3/torture/t_push_ucs2.c8
-rw-r--r--source3/torture/torture.c101
-rw-r--r--source3/utils/net_ads.c16
-rw-r--r--source3/utils/net_ads_gpo.c6
-rw-r--r--source3/utils/net_eventlog.c54
-rw-r--r--source3/utils/net_rpc_service.c204
-rw-r--r--source3/utils/ntlm_auth.c6
-rw-r--r--source3/utils/pdbedit.c7
-rw-r--r--source3/winbindd/idmap_adex/gc_util.c8
-rw-r--r--source3/winbindd/idmap_adex/likewise_cell.c4
-rw-r--r--source3/winbindd/idmap_adex/provider_unified.c6
-rw-r--r--source3/winbindd/winbindd_ads.c4
66 files changed, 3358 insertions, 3027 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 9a97d8de64..80ebf0c84b 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -363,8 +363,7 @@ LIB_OBJ = $(LIBSAMBAUTIL_OBJ) $(UTIL_OBJ) $(CRYPTO_OBJ) \
lib/messages.o librpc/gen_ndr/ndr_messaging.o lib/messages_local.o \
lib/messages_ctdbd.o lib/packet.o lib/ctdbd_conn.o \
lib/interfaces.o lib/memcache.o \
- lib/util_transfer_file.o ../lib/async_req/async_req.o \
- ../lib/async_req/async_sock.o ../lib/async_req/async_req_ntstatus.o \
+ lib/util_transfer_file.o ../lib/async_req/async_sock.o \
$(TDB_LIB_OBJ) \
$(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \
lib/interface.o lib/pidfile.o \
@@ -466,8 +465,6 @@ LIBCLI_LDAP_NDR_OBJ = ../libcli/ldap/ldap_ndr.o
LIBTSOCKET_OBJ = ../lib/tsocket/tsocket.o \
../lib/tsocket/tsocket_helpers.o \
../lib/tsocket/tsocket_bsd.o \
- ../lib/tsocket/tsocket_recvfrom.o \
- ../lib/tsocket/tsocket_sendto.o \
../lib/tsocket/tsocket_connect.o \
../lib/tsocket/tsocket_writev.o \
../lib/tsocket/tsocket_readv.o
@@ -570,7 +567,7 @@ REG_FULL_OBJ = $(REG_SMBCONF_OBJ) \
registry/reg_perfcount.o \
registry/reg_util_legacy.o
-LIB_EVENTLOG_OBJ = rpc_server/srv_eventlog_lib.o
+LIB_EVENTLOG_OBJ = lib/eventlog/eventlog.o
RPC_LSA_OBJ = rpc_server/srv_lsa_nt.o ../librpc/gen_ndr/srv_lsa.o
diff --git a/source3/include/ads_protos.h b/source3/include/ads_protos.h
index a372010b79..502eaa82d9 100644
--- a/source3/include/ads_protos.h
+++ b/source3/include/ads_protos.h
@@ -3,7 +3,7 @@
*/
void ads_msgfree(ADS_STRUCT *ads, LDAPMessage *msg);
-char *ads_get_dn(ADS_STRUCT *ads, LDAPMessage *msg);
+char *ads_get_dn(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, LDAPMessage *msg);
char *ads_get_dn_canonical(ADS_STRUCT *ads, LDAPMessage *msg);
char *ads_pull_string(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, LDAPMessage *msg,
diff --git a/source3/include/async_smb.h b/source3/include/async_smb.h
index 2ac1101a1e..87ddca6677 100644
--- a/source3/include/async_smb.h
+++ b/source3/include/async_smb.h
@@ -22,123 +22,11 @@
#include "includes.h"
-/**
- * struct cli_request is the state holder for an async client request we sent
- * to the server. It can consist of more than one struct async_req that we
- * have to server if the application did a cli_chain_cork() and
- * cli_chain_uncork()
- */
-
-struct cli_request {
- /**
- * "prev" and "next" form the doubly linked list in
- * cli_state->outstanding_requests
- */
- struct cli_request *prev, *next;
-
- /**
- * num_async: How many chained requests do we serve?
- */
- int num_async;
-
- /**
- * async: This is the list of chained requests that were queued up by
- * cli_request_chain before we sent out this request
- */
- struct async_req **async;
-
- /**
- * The client connection for this request
- */
- struct cli_state *cli;
-
- /**
- * The enc_state to decrypt the reply
- */
- struct smb_trans_enc_state *enc_state;
-
- /**
- * The mid we used for this request. Mainly used to demultiplex on
- * receiving replies.
- */
- uint16_t mid;
-
- uint32_t seqnum;
-
- /**
- * The bytes we have to ship to the server
- */
- uint8_t *outbuf;
-
- /**
- * How much from "outbuf" did we already send
- */
- size_t sent;
-
- /**
- * The reply comes in here. Its intended size is implicit by
- * smb_len(), its current size can be read via talloc_get_size()
- */
- char *inbuf;
-
- /**
- * Specific requests might add stuff here. Maybe convert this to a
- * private_pointer at some point.
- */
- union {
- struct {
- off_t ofs;
- size_t size;
- ssize_t received;
- uint8_t *rcvbuf;
- } read;
- struct {
- DATA_BLOB data;
- uint16_t num_echos;
- } echo;
- } data;
-
- /**
- * For requests that don't follow the strict request/reply pattern
- * such as the transaction request family and echo requests it is
- * necessary to break the standard procedure in
- * handle_incoming_pdu(). For a simple example look at
- * cli_echo_recv_helper().
- */
- struct {
- void (*fn)(struct async_req *req);
- void *priv;
- } recv_helper;
-};
-
-/*
- * Ship a new smb request to the server
- */
-
-struct async_req *cli_request_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli,
- uint8_t smb_command,
- uint8_t additional_flags,
- uint8_t wct, const uint16_t *vwv,
- size_t bytes_alignment,
- uint32_t num_bytes, const uint8_t *bytes);
-
-uint16_t cli_wct_ofs(const struct cli_state *cli);
-
-bool cli_chain_cork(struct cli_state *cli, struct event_context *ev,
- size_t size_hint);
-void cli_chain_uncork(struct cli_state *cli);
-bool cli_in_chain(struct cli_state *cli);
bool smb_splice_chain(uint8_t **poutbuf, uint8_t smb_command,
uint8_t wct, const uint16_t *vwv,
size_t bytes_alignment,
uint32_t num_bytes, const uint8_t *bytes);
-NTSTATUS cli_pull_reply(struct async_req *req,
- uint8_t *pwct, uint16_t **pvwv,
- uint16_t *pnum_bytes, uint8_t **pbytes);
-
/*
* Fetch an error out of a NBT packet
*/
@@ -151,4 +39,38 @@ NTSTATUS cli_pull_error(char *buf);
void cli_set_error(struct cli_state *cli, NTSTATUS status);
+struct tevent_req *cli_smb_req_create(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
+ uint8_t smb_command,
+ uint8_t additional_flags,
+ uint8_t wct, uint16_t *vwv,
+ int iov_count,
+ struct iovec *bytes_iov);
+bool cli_smb_req_send(struct tevent_req *req);
+size_t cli_smb_wct_ofs(struct tevent_req **reqs, int num_reqs);
+bool cli_smb_chain_send(struct tevent_req **reqs, int num_reqs);
+uint8_t *cli_smb_inbuf(struct tevent_req *req);
+bool cli_has_async_calls(struct cli_state *cli);
+void cli_smb_req_unset_pending(struct tevent_req *req);
+bool cli_smb_req_set_pending(struct tevent_req *req);
+uint16_t cli_smb_req_mid(struct tevent_req *req);
+void cli_smb_req_set_mid(struct tevent_req *req, uint16_t mid);
+struct tevent_req *cli_smb_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+ struct cli_state *cli,
+ uint8_t smb_command, uint8_t additional_flags,
+ uint8_t wct, uint16_t *vwv,
+ uint32_t num_bytes,
+ const uint8_t *bytes);
+NTSTATUS cli_smb_recv(struct tevent_req *req, uint8_t min_wct,
+ uint8_t *pwct, uint16_t **pvwv,
+ uint32_t *pnum_bytes, uint8_t **pbytes);
+
+struct tevent_req *cli_smb_oplock_break_waiter_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli);
+NTSTATUS cli_smb_oplock_break_waiter_recv(struct tevent_req *req,
+ uint16_t *pfnum,
+ uint8_t *plevel);
+
#endif
diff --git a/source3/include/client.h b/source3/include/client.h
index 73a1d7b554..c314c9c6a9 100644
--- a/source3/include/client.h
+++ b/source3/include/client.h
@@ -264,33 +264,11 @@ struct cli_state {
bool force_dos_errors;
bool case_sensitive; /* False by default. */
- /**
- * fd_event is around while we have async requests outstanding or are
- * building a chained request.
- *
- * (fd_event!=NULL) &&
- * ((outstanding_request!=NULL)||(chain_accumulator!=NULL))
- *
- * should always be true, as well as the reverse: If both cli_request
- * pointers are NULL, no fd_event is around.
- */
- struct fd_event *fd_event;
- char *evt_inbuf;
-
- /**
- * A linked list of requests that are waiting for a reply
- */
- struct cli_request *outstanding_requests;
-
- /**
- * The place to build up the list of chained requests. In CIFS, a
- * single cli_request corresponds to a MID and can serve more than one
- * chained async_req.
- */
- struct cli_request *chain_accumulator;
-
/* Where (if anywhere) this is mounted under DFS. */
char *dfs_mountpoint;
+
+ struct tevent_queue *outgoing;
+ struct tevent_req **pending;
};
typedef struct file_info {
@@ -311,5 +289,7 @@ typedef struct file_info {
#define CLI_FULL_CONNECTION_USE_KERBEROS 0x0002
#define CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK 0x0004
#define CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS 0x0008
+#define CLI_FULL_CONNECTION_OPLOCKS 0x0010
+#define CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS 0x0020
#endif /* _CLIENT_H */
diff --git a/source3/include/includes.h b/source3/include/includes.h
index c883e17713..433818d9ef 100644
--- a/source3/include/includes.h
+++ b/source3/include/includes.h
@@ -646,7 +646,6 @@ struct smb_iconv_convenience *lp_iconv_convenience(void *lp_ctx);
#include "ctdbd_conn.h"
#include "../lib/util/talloc_stack.h"
#include "memcache.h"
-#include "../lib/async_req/async_req_ntstatus.h"
#include "async_smb.h"
#include "../lib/async_req/async_sock.h"
#include "services.h"
@@ -901,9 +900,10 @@ krb5_error_code smb_krb5_parse_name(krb5_context context,
const char *name, /* in unix charset */
krb5_principal *principal);
-krb5_error_code smb_krb5_unparse_name(krb5_context context,
- krb5_const_principal principal,
- char **unix_name);
+krb5_error_code smb_krb5_unparse_name(TALLOC_CTX *mem_ctx,
+ krb5_context context,
+ krb5_const_principal principal,
+ char **unix_name);
#ifndef HAVE_KRB5_SET_REAL_TIME
krb5_error_code krb5_set_real_time(krb5_context context, int32_t seconds, int32_t microseconds);
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 0a2a8de4a9..678f087374 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -746,7 +746,6 @@ void smbldap_free_struct(struct smbldap_state **ldap_state) ;
NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, struct event_context *event_ctx,
const char *location,
struct smbldap_state **smbldap_state);
-char *smbldap_get_dn(LDAP *ld, LDAPMessage *entry);
bool smbldap_has_control(LDAP *ld, const char *control);
bool smbldap_has_extension(LDAP *ld, const char *extension);
bool smbldap_has_naming_context(LDAP *ld, const char *naming_context);
@@ -1421,6 +1420,11 @@ int create_pipe_sock(const char *socket_dir,
mode_t dir_perms);
const char *get_mydnsfullname(void);
bool is_myname_or_ipaddr(const char *s);
+struct tevent_req *read_smb_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ int fd);
+ssize_t read_smb_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ uint8_t **pbuf, int *perrno);
/* The following definitions come from lib/util_str.c */
@@ -1556,13 +1560,8 @@ int rpcstr_pull_talloc(TALLOC_CTX *ctx,
void *src,
int src_len,
int flags);
-int rpcstr_pull_unistr2_fstring(char *dest, UNISTR2 *src);
-char *rpcstr_pull_unistr2_talloc(TALLOC_CTX *ctx, const UNISTR2 *src);
int rpcstr_push(void *dest, const char *src, size_t dest_len, int flags);
int rpcstr_push_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src);
-void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen);
-char *unistr2_to_ascii_talloc(TALLOC_CTX *ctx, const UNISTR2 *str);
-const char *unistr2_static(const UNISTR2 *str);
smb_ucs2_t toupper_w(smb_ucs2_t val);
smb_ucs2_t tolower_w( smb_ucs2_t val );
bool islower_w(smb_ucs2_t c);
@@ -1596,9 +1595,6 @@ int strcmp_wa(const smb_ucs2_t *a, const char *b);
int strncmp_wa(const smb_ucs2_t *a, const char *b, size_t len);
smb_ucs2_t *strpbrk_wa(const smb_ucs2_t *s, const char *p);
smb_ucs2_t *strstr_wa(const smb_ucs2_t *s, const char *ins);
-int unistrlen(uint16 *s);
-int unistrcpy(uint16 *dst, uint16 *src);
-UNISTR2* ucs2_to_unistr2(TALLOC_CTX *ctx, UNISTR2* dst, smb_ucs2_t* src);
int toupper_ascii(int c);
int tolower_ascii(int c);
int isupper_ascii(int c);
@@ -2299,26 +2295,26 @@ NTSTATUS cli_session_setup(struct cli_state *cli,
const char *pass, int passlen,
const char *ntpass, int ntpasslen,
const char *workgroup);
-struct async_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli);
-NTSTATUS cli_session_setup_guest_recv(struct async_req *req);
+struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli);
+NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req);
bool cli_ulogoff(struct cli_state *cli);
-struct async_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli,
- const char *share, const char *dev,
- const char *pass, int passlen);
-NTSTATUS cli_tcon_andx_recv(struct async_req *req);
+struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
+ const char *share, const char *dev,
+ const char *pass, int passlen);
+NTSTATUS cli_tcon_andx_recv(struct tevent_req *req);
NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
const char *dev, const char *pass, int passlen);
bool cli_tdis(struct cli_state *cli);
void cli_negprot_sendsync(struct cli_state *cli);
NTSTATUS cli_negprot(struct cli_state *cli);
-struct async_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli);
-NTSTATUS cli_negprot_recv(struct async_req *req);
+struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli);
+NTSTATUS cli_negprot_recv(struct tevent_req *req);
bool cli_session_request(struct cli_state *cli,
struct nmb_name *calling, struct nmb_name *called);
NTSTATUS cli_connect(struct cli_state *cli,
@@ -2440,10 +2436,10 @@ void cli_sockopt(struct cli_state *cli, const char *options);
uint16 cli_setpid(struct cli_state *cli, uint16 pid);
bool cli_set_case_sensitive(struct cli_state *cli, bool case_sensitive);
bool cli_send_keepalive(struct cli_state *cli);
-struct async_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
- struct cli_state *cli, uint16_t num_echos,
- DATA_BLOB data);
-NTSTATUS cli_echo_recv(struct async_req *req);
+struct tevent_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+ struct cli_state *cli, uint16_t num_echos,
+ DATA_BLOB data);
+NTSTATUS cli_echo_recv(struct tevent_req *req);
NTSTATUS cli_echo(struct cli_state *cli, uint16_t num_echos, DATA_BLOB data);
bool cli_ucs2(struct cli_state *cli);
bool is_andx_req(uint8_t cmd);
@@ -2484,18 +2480,18 @@ int cli_nt_create_full(struct cli_state *cli, const char *fname,
uint32 FileAttributes, uint32 ShareAccess,
uint32 CreateDisposition, uint32 CreateOptions,
uint8 SecuityFlags);
-struct async_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli,
- const char *fname,
- uint32_t CreatFlags,
- uint32_t DesiredAccess,
- uint32_t FileAttributes,
- uint32_t ShareAccess,
- uint32_t CreateDisposition,
- uint32_t CreateOptions,
- uint8_t SecurityFlags);
-NTSTATUS cli_ntcreate_recv(struct async_req *req, uint16_t *pfnum);
+struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
+ const char *fname,
+ uint32_t CreatFlags,
+ uint32_t DesiredAccess,
+ uint32_t FileAttributes,
+ uint32_t ShareAccess,
+ uint32_t CreateDisposition,
+ uint32_t CreateOptions,
+ uint8_t SecurityFlags);
+NTSTATUS cli_ntcreate_recv(struct tevent_req *req, uint16_t *pfnum);
NTSTATUS cli_ntcreate(struct cli_state *cli,
const char *fname,
uint32_t CreatFlags,
@@ -2509,14 +2505,24 @@ NTSTATUS cli_ntcreate(struct cli_state *cli,
int cli_nt_create(struct cli_state *cli, const char *fname, uint32 DesiredAccess);
uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, const char *str,
size_t str_len, size_t *pconverted_size);
-struct async_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
- struct cli_state *cli,
- const char *fname, int flags, int share_mode);
-NTSTATUS cli_open_recv(struct async_req *req, int *fnum);
+struct tevent_req *cli_open_create(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli, const char *fname,
+ int flags, int share_mode,
+ struct tevent_req **psmbreq);
+struct tevent_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+ struct cli_state *cli, const char *fname,
+ int flags, int share_mode);
+NTSTATUS cli_open_recv(struct tevent_req *req, int *fnum);
int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode);
-struct async_req *cli_close_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
- struct cli_state *cli, int fnum);
-NTSTATUS cli_close_recv(struct async_req *req);
+struct tevent_req *cli_close_create(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli, int fnum,
+ struct tevent_req **psubreq);
+struct tevent_req *cli_close_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli, int fnum);
+NTSTATUS cli_close_recv(struct tevent_req *req);
bool cli_close(struct cli_state *cli, int fnum);
bool cli_ftruncate(struct cli_state *cli, int fnum, uint64_t size);
NTSTATUS cli_locktype(struct cli_state *cli, int fnum,
@@ -2630,6 +2636,11 @@ bool cli_message_end(struct cli_state *cli, int grp);
/* The following definitions come from libsmb/clioplock.c */
+struct tevent_req *cli_oplock_ack_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli,
+ uint16_t fnum, uint8_t level);
+NTSTATUS cli_oplock_ack_recv(struct tevent_req *req);
bool cli_oplock_ack(struct cli_state *cli, int fnum, unsigned char level);
void cli_oplock_handler(struct cli_state *cli,
bool (*handler)(struct cli_state *, int, unsigned char));
@@ -2757,21 +2768,26 @@ int cli_NetConnectionEnum(struct cli_state *cli, const char *qualifier,
/* The following definitions come from libsmb/clireadwrite.c */
-struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli, int fnum,
- off_t offset, size_t size);
-NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received,
+struct tevent_req *cli_read_andx_create(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli, int fnum,
+ off_t offset, size_t size,
+ struct tevent_req **psmbreq);
+struct tevent_req *cli_read_andx_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli, int fnum,
+ off_t offset, size_t size);
+NTSTATUS cli_read_andx_recv(struct tevent_req *req, ssize_t *received,
uint8_t **rcvbuf);
-struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli,
- uint16_t fnum, off_t start_offset,
- SMB_OFF_T size, size_t window_size,
- NTSTATUS (*sink)(char *buf, size_t n,
- void *priv),
- void *priv);
-NTSTATUS cli_pull_recv(struct async_req *req, SMB_OFF_T *received);
+struct tevent_req *cli_pull_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
+ uint16_t fnum, off_t start_offset,
+ SMB_OFF_T size, size_t window_size,
+ NTSTATUS (*sink)(char *buf, size_t n,
+ void *priv),
+ void *priv);
+NTSTATUS cli_pull_recv(struct tevent_req *req, SMB_OFF_T *received);
NTSTATUS cli_pull(struct cli_state *cli, uint16_t fnum,
off_t start_offset, SMB_OFF_T size, size_t window_size,
NTSTATUS (*sink)(char *buf, size_t n, void *priv),
@@ -2784,21 +2800,29 @@ ssize_t cli_write(struct cli_state *cli,
const char *buf, off_t offset, size_t size);
ssize_t cli_smbwrite(struct cli_state *cli,
int fnum, char *buf, off_t offset, size_t size1);
-struct async_req *cli_write_andx_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli, uint16_t fnum,
- uint16_t mode, const uint8_t *buf,
- off_t offset, size_t size);
-NTSTATUS cli_write_andx_recv(struct async_req *req, size_t *pwritten);
-
-struct async_req *cli_push_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
- struct cli_state *cli,
- uint16_t fnum, uint16_t mode,
- off_t start_offset, size_t window_size,
- size_t (*source)(uint8_t *buf, size_t n,
- void *priv),
- void *priv);
-NTSTATUS cli_push_recv(struct async_req *req);
+struct tevent_req *cli_write_andx_create(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli, uint16_t fnum,
+ uint16_t mode, const uint8_t *buf,
+ off_t offset, size_t size,
+ struct tevent_req **reqs_before,
+ int num_reqs_before,
+ struct tevent_req **psmbreq);
+struct tevent_req *cli_write_andx_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli, uint16_t fnum,
+ uint16_t mode, const uint8_t *buf,
+ off_t offset, size_t size);
+NTSTATUS cli_write_andx_recv(struct tevent_req *req, size_t *pwritten);
+
+struct tevent_req *cli_push_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+ struct cli_state *cli,
+ uint16_t fnum, uint16_t mode,
+ off_t start_offset, size_t window_size,
+ size_t (*source)(uint8_t *buf, size_t n,
+ void *priv),
+ void *priv);
+NTSTATUS cli_push_recv(struct tevent_req *req);
NTSTATUS cli_push(struct cli_state *cli, uint16_t fnum, uint16_t mode,
off_t start_offset, size_t window_size,
size_t (*source)(uint8_t *buf, size_t n, void *priv),
@@ -2885,14 +2909,14 @@ bool cli_send_nt_trans(struct cli_state *cli,
bool cli_receive_nt_trans(struct cli_state *cli,
char **param, unsigned int *param_len,
char **data, unsigned int *data_len);
-struct async_req *cli_trans_send(
+struct tevent_req *cli_trans_send(
TALLOC_CTX *mem_ctx, struct event_context *ev,
- struct cli_state *cli, uint8_t trans_cmd,
+ struct cli_state *cli, uint8_t cmd,
const char *pipe_name, uint16_t fid, uint16_t function, int flags,
uint16_t *setup, uint8_t num_setup, uint8_t max_setup,
uint8_t *param, uint32_t num_param, uint32_t max_param,
uint8_t *data, uint32_t num_data, uint32_t max_data);
-NTSTATUS cli_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
+NTSTATUS cli_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
uint16_t **setup, uint8_t *num_setup,
uint8_t **param, uint32_t *num_param,
uint8_t **data, uint32_t *num_data);
@@ -5367,11 +5391,11 @@ NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
/* The following definitions come from rpc_client/rpc_transport_np.c */
-struct async_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli,
- const struct ndr_syntax_id *abstract_syntax);
-NTSTATUS rpc_transport_np_init_recv(struct async_req *req,
+struct tevent_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
+ const struct ndr_syntax_id *abstract_syntax);
+NTSTATUS rpc_transport_np_init_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
struct rpc_cli_transport **presult);
NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, struct cli_state *cli,
@@ -5381,13 +5405,13 @@ struct cli_state *rpc_pipe_np_smb_conn(struct rpc_pipe_client *p);
/* The following definitions come from rpc_client/rpc_transport_smbd.c */
-struct async_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- void (*stdout_callback)(char *buf,
- size_t len,
- void *priv),
- void *priv);
-NTSTATUS rpc_cli_smbd_conn_init_recv(struct async_req *req,
+struct tevent_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ void (*stdout_callback)(char *buf,
+ size_t len,
+ void *priv),
+ void *priv);
+NTSTATUS rpc_cli_smbd_conn_init_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
struct rpc_cli_smbd_conn **pconn);
NTSTATUS rpc_cli_smbd_conn_init(TALLOC_CTX *mem_ctx,
@@ -5397,11 +5421,11 @@ NTSTATUS rpc_cli_smbd_conn_init(TALLOC_CTX *mem_ctx,
void *priv),
void *priv);
-struct async_req *rpc_transport_smbd_init_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct rpc_cli_smbd_conn *conn,
- const struct ndr_syntax_id *abstract_syntax);
-NTSTATUS rpc_transport_smbd_init_recv(struct async_req *req,
+struct tevent_req *rpc_transport_smbd_init_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct rpc_cli_smbd_conn *conn,
+ const struct ndr_syntax_id *abstract_syntax);
+NTSTATUS rpc_transport_smbd_init_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
struct rpc_cli_transport **presult);
NTSTATUS rpc_transport_smbd_init(TALLOC_CTX *mem_ctx,
@@ -5756,7 +5780,6 @@ bool prs_uint8s(bool charmode, const char *name, prs_struct *ps, int depth, uint
bool prs_uint16s(bool charmode, const char *name, prs_struct *ps, int depth, uint16 *data16s, int len);
bool prs_uint16uni(bool charmode, const char *name, prs_struct *ps, int depth, uint16 *data16s, int len);
bool prs_uint32s(bool charmode, const char *name, prs_struct *ps, int depth, uint32 *data32s, int len);
-bool prs_unistr2(bool charmode, const char *name, prs_struct *ps, int depth, UNISTR2 *str);
bool prs_unistr(const char *name, prs_struct *ps, int depth, UNISTR *str);
bool prs_string(const char *name, prs_struct *ps, int depth, char *str, int max_buf_size);
bool prs_string_alloc(const char *name, prs_struct *ps, int depth, const char **str);
@@ -5821,7 +5844,7 @@ bool smb_io_rpc_auth_schannel_chk(const char *desc, int auth_len,
RPC_AUTH_SCHANNEL_CHK * chk,
prs_struct *ps, int depth);
-/* The following definitions come from rpc_server/srv_eventlog_lib.c */
+/* The following definitions come from lib/eventlog/eventlog.c */
TDB_CONTEXT *elog_init_tdb( char *tdbfilename );
char *elog_tdbname(TALLOC_CTX *ctx, const char *name );
@@ -5851,6 +5874,10 @@ NTSTATUS evlog_evt_entry_to_tdb_entry(TALLOC_CTX *mem_ctx,
NTSTATUS evlog_tdb_entry_to_evt_entry(TALLOC_CTX *mem_ctx,
const struct eventlog_Record_tdb *t,
struct EVENTLOGRECORD *e);
+NTSTATUS evlog_convert_tdb_to_evt(TALLOC_CTX *mem_ctx,
+ ELOG_TDB *etdb,
+ DATA_BLOB *blob_p,
+ uint32_t *num_records_p);
/* The following definitions come from rpc_server/srv_eventlog_nt.c */
@@ -6645,6 +6672,7 @@ void release_file_oplock(files_struct *fsp);
bool remove_oplock(files_struct *fsp);
bool downgrade_oplock(files_struct *fsp);
bool should_notify_deferred_opens(void);
+void break_level2_to_none_async(files_struct *fsp);
void reply_to_oplock_break_requests(files_struct *fsp);
void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx,
void *private_data,
diff --git a/source3/include/smbldap.h b/source3/include/smbldap.h
index a2cb8c5eea..353e01aba6 100644
--- a/source3/include/smbldap.h
+++ b/source3/include/smbldap.h
@@ -141,7 +141,6 @@ void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing,
bool smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
const char *attribute, char *value,
int max_len);
-char *smbldap_get_dn(LDAP *ld, LDAPMessage *entry);
int smbldap_modify(struct smbldap_state *ldap_state,
const char *dn,
LDAPMod *attrs[]);
@@ -214,7 +213,7 @@ char * smbldap_talloc_single_attribute(LDAP *ldap_struct, LDAPMessage *entry,
TALLOC_CTX *mem_ctx);
void talloc_autofree_ldapmsg(TALLOC_CTX *mem_ctx, LDAPMessage *result);
void talloc_autofree_ldapmod(TALLOC_CTX *mem_ctx, LDAPMod **mod);
-const char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld,
+char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld,
LDAPMessage *entry);
diff --git a/source3/rpc_server/srv_eventlog_lib.c b/source3/lib/eventlog/eventlog.c
index f83c4fc3b8..11cb28a120 100644
--- a/source3/rpc_server/srv_eventlog_lib.c
+++ b/source3/lib/eventlog/eventlog.c
@@ -958,3 +958,77 @@ NTSTATUS evlog_tdb_entry_to_evt_entry(TALLOC_CTX *mem_ctx,
return NT_STATUS_OK;
}
+
+/********************************************************************
+ ********************************************************************/
+
+NTSTATUS evlog_convert_tdb_to_evt(TALLOC_CTX *mem_ctx,
+ ELOG_TDB *etdb,
+ DATA_BLOB *blob_p,
+ uint32_t *num_records_p)
+{
+ NTSTATUS status = NT_STATUS_OK;
+ enum ndr_err_code ndr_err;
+ DATA_BLOB blob;
+ uint32_t num_records = 0;
+ struct EVENTLOG_EVT_FILE evt;
+ uint32_t count = 1;
+ size_t endoffset = 0;
+
+ ZERO_STRUCT(evt);
+
+ while (1) {
+
+ struct eventlog_Record_tdb *r;
+ struct EVENTLOGRECORD e;
+
+ r = evlog_pull_record_tdb(mem_ctx, etdb->tdb, count);
+ if (!r) {
+ break;
+ }
+
+ status = evlog_tdb_entry_to_evt_entry(mem_ctx, r, &e);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ endoffset += ndr_size_EVENTLOGRECORD(&e, NULL, 0);
+
+ ADD_TO_ARRAY(mem_ctx, struct EVENTLOGRECORD, e, &evt.records, &num_records);
+ count++;
+ }
+
+ evt.hdr.StartOffset = 0x30;
+ evt.hdr.EndOffset = evt.hdr.StartOffset + endoffset;
+ evt.hdr.CurrentRecordNumber = count;
+ evt.hdr.OldestRecordNumber = 1;
+ evt.hdr.MaxSize = tdb_fetch_int32(etdb->tdb, EVT_MAXSIZE);
+ evt.hdr.Flags = 0;
+ evt.hdr.Retention = tdb_fetch_int32(etdb->tdb, EVT_RETENTION);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_DEBUG(EVENTLOGHEADER, &evt.hdr);
+ }
+
+ evt.eof.BeginRecord = 0x30;
+ evt.eof.EndRecord = evt.hdr.StartOffset + endoffset;
+ evt.eof.CurrentRecordNumber = evt.hdr.CurrentRecordNumber;
+ evt.eof.OldestRecordNumber = evt.hdr.OldestRecordNumber;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_DEBUG(EVENTLOGEOF, &evt.eof);
+ }
+
+ ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &evt,
+ (ndr_push_flags_fn_t)ndr_push_EVENTLOG_EVT_FILE);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ status = ndr_map_error2ntstatus(ndr_err);
+ goto done;
+ }
+
+ *blob_p = blob;
+ *num_records_p = num_records;
+
+ done:
+ return status;
+}
diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c
index ca534467fa..1eac9fa14a 100644
--- a/source3/lib/ms_fnmatch.c
+++ b/source3/lib/ms_fnmatch.c
@@ -170,12 +170,12 @@ int ms_fnmatch(const char *pattern, const char *string, bool translate_pattern,
}
}
- if (!push_ucs2_allocate(&p, pattern, &converted_size)) {
+ if (!push_ucs2_talloc(talloc_tos(), &p, pattern, &converted_size)) {
return -1;
}
- if (!push_ucs2_allocate(&s, string, &converted_size)) {
- SAFE_FREE(p);
+ if (!push_ucs2_talloc(talloc_tos(), &s, string, &converted_size)) {
+ TALLOC_FREE(p);
return -1;
}
@@ -214,8 +214,8 @@ int ms_fnmatch(const char *pattern, const char *string, bool translate_pattern,
else {
max_n = SMB_CALLOC_ARRAY(struct max_n, count);
if (!max_n) {
- SAFE_FREE(p);
- SAFE_FREE(s);
+ TALLOC_FREE(p);
+ TALLOC_FREE(s);
return -1;
}
max_n_free = max_n;
@@ -225,8 +225,8 @@ int ms_fnmatch(const char *pattern, const char *string, bool translate_pattern,
ret = ms_fnmatch_core(p, s, max_n, strrchr_w(s, UCS2_CHAR('.')), is_case_sensitive);
SAFE_FREE(max_n_free);
- SAFE_FREE(p);
- SAFE_FREE(s);
+ TALLOC_FREE(p);
+ TALLOC_FREE(s);
return ret;
}
diff --git a/source3/lib/smbconf/smbconf_reg.c b/source3/lib/smbconf/smbconf_reg.c
index ae6a41151d..0ecac97575 100644
--- a/source3/lib/smbconf/smbconf_reg.c
+++ b/source3/lib/smbconf/smbconf_reg.c
@@ -193,7 +193,7 @@ static WERROR smbconf_reg_set_value(struct registry_key *key,
if (!strequal(subkeyname, GLOBAL_NAME) &&
lp_parameter_is_global(valname))
{
- DEBUG(5, ("Global paramter '%s' not allowed in "
+ DEBUG(5, ("Global parameter '%s' not allowed in "
"service definition ('%s').\n", canon_valname,
subkeyname));
werr = WERR_INVALID_PARAM;
diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c
index e24d35818c..4f54f9ad58 100644
--- a/source3/lib/smbldap.c
+++ b/source3/lib/smbldap.c
@@ -1228,7 +1228,7 @@ static int smbldap_search_ext(struct smbldap_state *ldap_state,
ZERO_STRUCT(ldap_state->last_rebind);
}
- if (!push_utf8_allocate(&utf8_filter, filter, &converted_size)) {
+ if (!push_utf8_talloc(talloc_tos(), &utf8_filter, filter, &converted_size)) {
return LDAP_NO_MEMORY;
}
@@ -1276,7 +1276,7 @@ static int smbldap_search_ext(struct smbldap_state *ldap_state,
}
}
- SAFE_FREE(utf8_filter);
+ TALLOC_FREE(utf8_filter);
/* Teardown timeout. */
CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
@@ -1400,7 +1400,7 @@ int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *at
DEBUG(5,("smbldap_modify: dn => [%s]\n", dn ));
- if (!push_utf8_allocate(&utf8_dn, dn, &converted_size)) {
+ if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
return LDAP_NO_MEMORY;
}
@@ -1428,7 +1428,7 @@ int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *at
}
}
- SAFE_FREE(utf8_dn);
+ TALLOC_FREE(utf8_dn);
return rc;
}
@@ -1444,7 +1444,7 @@ int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs
DEBUG(5,("smbldap_add: dn => [%s]\n", dn ));
- if (!push_utf8_allocate(&utf8_dn, dn, &converted_size)) {
+ if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
return LDAP_NO_MEMORY;
}
@@ -1472,7 +1472,7 @@ int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs
}
}
- SAFE_FREE(utf8_dn);
+ TALLOC_FREE(utf8_dn);
return rc;
}
@@ -1488,7 +1488,7 @@ int smbldap_delete(struct smbldap_state *ldap_state, const char *dn)
DEBUG(5,("smbldap_delete: dn => [%s]\n", dn ));
- if (!push_utf8_allocate(&utf8_dn, dn, &converted_size)) {
+ if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
return LDAP_NO_MEMORY;
}
@@ -1516,7 +1516,7 @@ int smbldap_delete(struct smbldap_state *ldap_state, const char *dn)
}
}
- SAFE_FREE(utf8_dn);
+ TALLOC_FREE(utf8_dn);
return rc;
}
@@ -1649,41 +1649,19 @@ NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, struct event_context *event_ctx,
return NT_STATUS_OK;
}
-/*******************************************************************
- Return a copy of the DN for a LDAPMessage. Convert from utf8 to CH_UNIX.
-********************************************************************/
-char *smbldap_get_dn(LDAP *ld, LDAPMessage *entry)
-{
- char *utf8_dn, *unix_dn;
- size_t converted_size;
-
- utf8_dn = ldap_get_dn(ld, entry);
- if (!utf8_dn) {
- DEBUG (5, ("smbldap_get_dn: ldap_get_dn failed\n"));
- return NULL;
- }
- if (!pull_utf8_allocate(&unix_dn, utf8_dn, &converted_size)) {
- DEBUG (0, ("smbldap_get_dn: String conversion failure utf8 "
- "[%s]\n", utf8_dn));
- return NULL;
- }
- ldap_memfree(utf8_dn);
- return unix_dn;
-}
-
- const char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld,
- LDAPMessage *entry)
+ char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld,
+ LDAPMessage *entry)
{
char *utf8_dn, *unix_dn;
size_t converted_size;
utf8_dn = ldap_get_dn(ld, entry);
if (!utf8_dn) {
- DEBUG (5, ("smbldap_get_dn: ldap_get_dn failed\n"));
+ DEBUG (5, ("smbldap_talloc_dn: ldap_get_dn failed\n"));
return NULL;
}
if (!pull_utf8_talloc(mem_ctx, &unix_dn, utf8_dn, &converted_size)) {
- DEBUG (0, ("smbldap_get_dn: String conversion failure utf8 "
+ DEBUG (0, ("smbldap_talloc_dn: String conversion failure utf8 "
"[%s]\n", utf8_dn));
return NULL;
}
diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c
index a0dbca1a00..5f9d4768ba 100644
--- a/source3/lib/util_sock.c
+++ b/source3/lib/util_sock.c
@@ -1942,6 +1942,10 @@ bool is_myname_or_ipaddr(const char *s)
return false;
}
+ if (ismyaddr((struct sockaddr *)&ss)) {
+ return true;
+ }
+
if (is_zero_addr((struct sockaddr *)&ss) ||
is_loopback_addr((struct sockaddr *)&ss)) {
return false;
@@ -1965,3 +1969,90 @@ bool is_myname_or_ipaddr(const char *s)
/* No match */
return false;
}
+
+/*
+ * Read an smb packet asynchronously, discard keepalives
+ */
+
+struct read_smb_state {
+ struct tevent_context *ev;
+ int fd;
+ uint8_t *buf;
+};
+
+static ssize_t read_smb_more(uint8_t *buf, size_t buflen, void *private_data);
+static void read_smb_done(struct tevent_req *subreq);
+
+struct tevent_req *read_smb_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ int fd)
+{
+ struct tevent_req *result, *subreq;
+ struct read_smb_state *state;
+
+ result = tevent_req_create(mem_ctx, &state, struct read_smb_state);
+ if (result == NULL) {
+ return NULL;
+ }
+ state->ev = ev;
+ state->fd = fd;
+
+ subreq = read_packet_send(state, ev, fd, 4, read_smb_more, NULL);
+ if (subreq == NULL) {
+ goto fail;
+ }
+ tevent_req_set_callback(subreq, read_smb_done, result);
+ return result;
+ fail:
+ TALLOC_FREE(result);
+ return NULL;
+}
+
+static ssize_t read_smb_more(uint8_t *buf, size_t buflen, void *private_data)
+{
+ if (buflen > 4) {
+ return 0; /* We've been here, we're done */
+ }
+ return smb_len_large(buf);
+}
+
+static void read_smb_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct read_smb_state *state = tevent_req_data(
+ req, struct read_smb_state);
+ ssize_t len;
+ int err;
+
+ len = read_packet_recv(subreq, state, &state->buf, &err);
+ TALLOC_FREE(subreq);
+ if (len == -1) {
+ tevent_req_error(req, err);
+ return;
+ }
+
+ if (CVAL(state->buf, 0) == SMBkeepalive) {
+ subreq = read_packet_send(state, state->ev, state->fd, 4,
+ read_smb_more, NULL);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, read_smb_done, req);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+ssize_t read_smb_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ uint8_t **pbuf, int *perrno)
+{
+ struct read_smb_state *state = tevent_req_data(
+ req, struct read_smb_state);
+
+ if (tevent_req_is_unix_error(req, perrno)) {
+ return -1;
+ }
+ *pbuf = talloc_move(mem_ctx, &state->buf);
+ return talloc_get_size(*pbuf);
+}
diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c
index 840e8e06da..7d80b3cdea 100644
--- a/source3/lib/util_unistr.c
+++ b/source3/lib/util_unistr.c
@@ -291,64 +291,6 @@ int rpcstr_pull_talloc(TALLOC_CTX *ctx,
}
-/* Copy a string from a unistr2 source to internal samba format
- destination. Use this instead of direct calls to rpcstr_pull() to avoid
- having to determine whether the source string is null terminated. */
-
-int rpcstr_pull_unistr2_fstring(char *dest, UNISTR2 *src)
-{
- return pull_ucs2(NULL, dest, src->buffer, sizeof(fstring),
- src->uni_str_len * 2, 0);
-}
-
-/* Helper function to return a talloc'ed string. I have implemented it with a
- * copy because I don't really know how pull_ucs2 and friends calculate the
- * target size. If this turns out to be a major bottleneck someone with deeper
- * multi-byte knowledge needs to revisit this.
- * I just did (JRA :-). No longer uses copy.
- * My (VL) use is dsr_getdcname, which returns 6 strings, the alternative would
- * have been to manually talloc_strdup them in rpc_client/cli_netlogon.c.
- */
-
-char *rpcstr_pull_unistr2_talloc(TALLOC_CTX *ctx, const UNISTR2 *src)
-{
- char *dest = NULL;
- size_t dest_len;
-
- if (!convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src->buffer,
- src->uni_str_len * 2, (void *)&dest,
- &dest_len, true))
- {
- return NULL;
- }
-
- /* Ensure we're returning a null terminated string. */
- if (dest_len) {
- /* Did we already process the terminating zero ? */
- if (dest[dest_len-1] != 0) {
- size_t size = talloc_get_size(dest);
- /* Have we got space to append the '\0' ? */
- if (size <= dest_len) {
- /* No, realloc. */
- dest = TALLOC_REALLOC_ARRAY(ctx, dest, char,
- dest_len+1);
- if (!dest) {
- /* talloc fail. */
- dest_len = (size_t)-1;
- return NULL;
- }
- }
- /* Yay - space ! */
- dest[dest_len] = '\0';
- dest_len++;
- }
- } else if (dest) {
- dest[0] = 0;
- }
-
- return dest;
-}
-
/* Converts a string from internal samba format to unicode
*/
@@ -371,64 +313,6 @@ int rpcstr_push_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
}
/*******************************************************************
- Convert a (little-endian) UNISTR2 structure to an ASCII string.
-********************************************************************/
-
-void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen)
-{
- if ((str == NULL) || (str->uni_str_len == 0)) {
- *dest='\0';
- return;
- }
- pull_ucs2(NULL, dest, str->buffer, maxlen, str->uni_str_len*2, STR_NOALIGN);
-}
-
-/*******************************************************************
- Duplicate a UNISTR2 string into a null terminated char*
- using a talloc context.
-********************************************************************/
-
-char *unistr2_to_ascii_talloc(TALLOC_CTX *ctx, const UNISTR2 *str)
-{
- char *s = NULL;
-
- if (!str || !str->buffer) {
- return NULL;
- }
- if (pull_ucs2_base_talloc(ctx,
- NULL,
- &s,
- str->buffer,
- str->uni_str_len*2,
- STR_NOALIGN) == (size_t)-1) {
- return NULL;
- }
- return s;
-}
-
-/*******************************************************************
- Return a string for displaying a UNISTR2. Guarentees to return a
- valid string - "" if nothing else.
- Changed to use talloc_tos() under the covers.... JRA.
-********************************************************************/
-
-const char *unistr2_static(const UNISTR2 *str)
-{
- char *dest = NULL;
-
- if ((str == NULL) || (str->uni_str_len == 0)) {
- return "";
- }
-
- dest = unistr2_to_ascii_talloc(talloc_tos(), str);
- if (!dest) {
- return "";
- }
-
- return dest;
-}
-
-/*******************************************************************
Convert a wchar to upper case.
********************************************************************/
@@ -966,89 +850,6 @@ smb_ucs2_t *strstr_wa(const smb_ucs2_t *s, const char *ins)
return NULL;
}
-/*******************************************************************
- Returns the length in number of wide characters.
-******************************************************************/
-
-int unistrlen(uint16 *s)
-{
- int len;
-
- if (!s) {
- return -1;
- }
-
- for (len=0; SVAL(s,0); s++,len++) {
- ;
- }
-
- return len;
-}
-
-/*******************************************************************
- Strcpy for unicode strings. Returns length (in num of wide chars).
- Not odd align safe.
-********************************************************************/
-
-int unistrcpy(uint16 *dst, uint16 *src)
-{
- int num_wchars = 0;
-
- while (SVAL(src,0)) {
- *dst++ = *src++;
- num_wchars++;
- }
- *dst = 0;
-
- return num_wchars;
-}
-
-/**
- * Samba ucs2 type to UNISTR2 conversion
- *
- * @param ctx Talloc context to create the dst strcture (if null) and the
- * contents of the unicode string.
- * @param dst UNISTR2 destination. If equals null, then it's allocated.
- * @param src smb_ucs2_t source.
- * @param max_len maximum number of unicode characters to copy. If equals
- * null, then null-termination of src is taken
- *
- * @return copied UNISTR2 destination
- **/
-
-UNISTR2* ucs2_to_unistr2(TALLOC_CTX *ctx, UNISTR2* dst, smb_ucs2_t* src)
-{
- size_t len;
-
- if (!src) {
- return NULL;
- }
-
- len = strlen_w(src);
-
- /* allocate UNISTR2 destination if not given */
- if (!dst) {
- dst = TALLOC_P(ctx, UNISTR2);
- if (!dst)
- return NULL;
- }
- if (!dst->buffer) {
- dst->buffer = TALLOC_ARRAY(ctx, uint16, len + 1);
- if (!dst->buffer)
- return NULL;
- }
-
- /* set UNISTR2 parameters */
- dst->uni_max_len = len + 1;
- dst->offset = 0;
- dst->uni_str_len = len;
-
- /* copy the actual unicode string */
- strncpy_w(dst->buffer, src, dst->uni_max_len);
-
- return dst;
-}
-
/*************************************************************
ascii only toupper - saves the need for smbd to be in C locale.
*************************************************************/
diff --git a/source3/libads/authdata.c b/source3/libads/authdata.c
index 9f0f68ed7b..0032e9e4f6 100644
--- a/source3/libads/authdata.c
+++ b/source3/libads/authdata.c
@@ -469,7 +469,7 @@ out:
data_blob_free(&sesskey1);
data_blob_free(&sesskey2);
- SAFE_FREE(client_princ_out);
+ TALLOC_FREE(client_princ_out);
return status;
}
diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c
index 52cb975a6c..c476f59ff5 100644
--- a/source3/libads/kerberos.c
+++ b/source3/libads/kerberos.c
@@ -545,7 +545,7 @@ krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context,
/* look under the old key. If this fails, just use the standard key */
- if (smb_krb5_unparse_name(context, host_princ, &unparsed_name) != 0) {
+ if (smb_krb5_unparse_name(talloc_tos(), context, host_princ, &unparsed_name) != 0) {
return (krb5_principal)NULL;
}
if ((salt_princ_s = kerberos_secrets_fetch_salting_principal(unparsed_name, enctype)) == NULL) {
@@ -558,7 +558,7 @@ krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context,
ret_princ = NULL;
}
- SAFE_FREE(unparsed_name);
+ TALLOC_FREE(unparsed_name);
SAFE_FREE(salt_princ_s);
return ret_princ;
@@ -603,7 +603,7 @@ bool kerberos_secrets_store_salting_principal(const char *service,
goto out;
}
- if (smb_krb5_unparse_name(context, princ, &unparsed_name) != 0) {
+ if (smb_krb5_unparse_name(talloc_tos(), context, princ, &unparsed_name) != 0) {
goto out;
}
@@ -623,7 +623,7 @@ bool kerberos_secrets_store_salting_principal(const char *service,
SAFE_FREE(key);
SAFE_FREE(princ_s);
- SAFE_FREE(unparsed_name);
+ TALLOC_FREE(unparsed_name);
if (princ) {
krb5_free_principal(context, princ);
diff --git a/source3/libads/kerberos_keytab.c b/source3/libads/kerberos_keytab.c
index 7c028cb78f..4fede259ab 100644
--- a/source3/libads/kerberos_keytab.c
+++ b/source3/libads/kerberos_keytab.c
@@ -64,7 +64,7 @@ int smb_krb5_kt_add_entry_ext(krb5_context context,
while(!krb5_kt_next_entry(context, keytab, &kt_entry, &cursor)) {
bool compare_name_ok = False;
- ret = smb_krb5_unparse_name(context, kt_entry.principal, &ktprinc);
+ ret = smb_krb5_unparse_name(talloc_tos(), context, kt_entry.principal, &ktprinc);
if (ret) {
DEBUG(1,("smb_krb5_kt_add_entry_ext: smb_krb5_unparse_name failed (%s)\n",
error_message(ret)));
@@ -91,7 +91,7 @@ int smb_krb5_kt_add_entry_ext(krb5_context context,
ktprinc, kt_entry.vno));
}
- SAFE_FREE(ktprinc);
+ TALLOC_FREE(ktprinc);
if (compare_name_ok) {
if (kt_entry.vno == kvno - 1) {
@@ -549,13 +549,12 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
}
}
- TALLOC_FREE( ctx );
-
/* Now loop through the keytab and update any other existing entries... */
kvno = (krb5_kvno) ads_get_machine_kvno(ads, machine_name);
if (kvno == -1) {
DEBUG(1,("ads_keytab_create_default: ads_get_machine_kvno failed to determine the system's kvno.\n"));
+ TALLOC_FREE(ctx);
return -1;
}
@@ -569,6 +568,7 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
ret = krb5_init_context(&context);
if (ret) {
DEBUG(1,("ads_keytab_create_default: could not krb5_init_context: %s\n",error_message(ret)));
+ TALLOC_FREE(ctx);
return ret;
}
@@ -599,7 +599,7 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
if (!found) {
goto done;
}
- oldEntries = SMB_MALLOC_ARRAY(char *, found );
+ oldEntries = talloc_array(ctx, char *, found );
if (!oldEntries) {
DEBUG(1,("ads_keytab_create_default: Failed to allocate space to store the old keytab entries (malloc failed?).\n"));
ret = -1;
@@ -615,7 +615,7 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
char *p;
/* This returns a malloc'ed string in ktprinc. */
- ret = smb_krb5_unparse_name(context, kt_entry.principal, &ktprinc);
+ ret = smb_krb5_unparse_name(oldEntries, context, kt_entry.principal, &ktprinc);
if (ret) {
DEBUG(1,("smb_krb5_unparse_name failed (%s)\n", error_message(ret)));
goto done;
@@ -640,12 +640,12 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
break;
}
if (!strcmp(oldEntries[i], ktprinc)) {
- SAFE_FREE(ktprinc);
+ TALLOC_FREE(ktprinc);
break;
}
}
if (i == found) {
- SAFE_FREE(ktprinc);
+ TALLOC_FREE(ktprinc);
}
}
smb_krb5_kt_free_entry(context, &kt_entry);
@@ -654,7 +654,7 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
ret = 0;
for (i = 0; oldEntries[i]; i++) {
ret |= ads_keytab_add_entry(ads, oldEntries[i]);
- SAFE_FREE(oldEntries[i]);
+ TALLOC_FREE(oldEntries[i]);
}
krb5_kt_end_seq_get(context, keytab, &cursor);
}
@@ -662,7 +662,8 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
done:
- SAFE_FREE(oldEntries);
+ TALLOC_FREE(oldEntries);
+ TALLOC_FREE(ctx);
{
krb5_keytab_entry zero_kt_entry;
@@ -728,7 +729,7 @@ int ads_keytab_list(const char *keytab_name)
char *etype_s = NULL;
krb5_enctype enctype = 0;
- ret = smb_krb5_unparse_name(context, kt_entry.principal, &princ_s);
+ ret = smb_krb5_unparse_name(talloc_tos(), context, kt_entry.principal, &princ_s);
if (ret) {
goto out;
}
@@ -739,14 +740,14 @@ int ads_keytab_list(const char *keytab_name)
if (ret) {
if (asprintf(&etype_s, "UNKNOWN: %d\n", enctype) == -1)
{
- SAFE_FREE(princ_s);
+ TALLOC_FREE(princ_s);
goto out;
}
}
printf("%3d %s\t\t %s\n", kt_entry.vno, etype_s, princ_s);
- SAFE_FREE(princ_s);
+ TALLOC_FREE(princ_s);
SAFE_FREE(etype_s);
ret = smb_krb5_kt_free_entry(context, &kt_entry);
diff --git a/source3/libads/kerberos_verify.c b/source3/libads/kerberos_verify.c
index b903b2a6eb..8502902963 100644
--- a/source3/libads/kerberos_verify.c
+++ b/source3/libads/kerberos_verify.c
@@ -192,7 +192,7 @@ static bool ads_keytab_verify_ticket(krb5_context context,
}
while (!auth_ok && (krb5_kt_next_entry(context, keytab, &kt_entry, &kt_cursor) == 0)) {
- ret = smb_krb5_unparse_name(context, kt_entry.principal, &entry_princ_s);
+ ret = smb_krb5_unparse_name(talloc_tos(), context, kt_entry.principal, &entry_princ_s);
if (ret) {
DEBUG(1, ("ads_keytab_verify_ticket: smb_krb5_unparse_name failed (%s)\n",
error_message(ret)));
@@ -242,7 +242,7 @@ static bool ads_keytab_verify_ticket(krb5_context context,
}
/* Free the name we parsed. */
- SAFE_FREE(entry_princ_s);
+ TALLOC_FREE(entry_princ_s);
/* Free the entry we just read. */
smb_krb5_kt_free_entry(context, &kt_entry);
@@ -636,7 +636,7 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
#endif
#endif
- if ((ret = smb_krb5_unparse_name(context, client_principal, principal))) {
+ if ((ret = smb_krb5_unparse_name(mem_ctx, context, client_principal, principal))) {
DEBUG(3,("ads_verify_ticket: smb_krb5_unparse_name failed (%s)\n",
error_message(ret)));
sret = NT_STATUS_LOGON_FAILURE;
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index edbd69392c..841ea8caae 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -1267,22 +1267,12 @@ ADS_STATUS ads_do_search_all_fn(ADS_STRUCT *ads, const char *bind_path,
}
/**
- * Free up memory from various ads requests
- * @param ads connection to ads server
- * @param mem Area to free
- **/
-void ads_memfree(ADS_STRUCT *ads, void *mem)
-{
- SAFE_FREE(mem);
-}
-
-/**
* Get a dn from search results
* @param ads connection to ads server
* @param msg Search result
* @return dn string
**/
- char *ads_get_dn(ADS_STRUCT *ads, LDAPMessage *msg)
+ char *ads_get_dn(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, LDAPMessage *msg)
{
char *utf8_dn, *unix_dn;
size_t converted_size;
@@ -1294,7 +1284,7 @@ void ads_memfree(ADS_STRUCT *ads, void *mem)
return NULL;
}
- if (!pull_utf8_allocate(&unix_dn, utf8_dn, &converted_size)) {
+ if (!pull_utf8_talloc(mem_ctx, &unix_dn, utf8_dn, &converted_size)) {
DEBUG(0,("ads_get_dn: string conversion failure utf8 [%s]\n",
utf8_dn ));
return NULL;
@@ -1639,7 +1629,7 @@ char *ads_default_ou_string(ADS_STRUCT *ads, const char *wknguid)
}
/* substitute the bind-path from the well-known-guid-search result */
- wkn_dn = ads_get_dn(ads, res);
+ wkn_dn = ads_get_dn(ads, talloc_tos(), res);
if (!wkn_dn) {
goto out;
}
@@ -1685,7 +1675,7 @@ char *ads_default_ou_string(ADS_STRUCT *ads, const char *wknguid)
out:
SAFE_FREE(base);
ads_msgfree(ads, res);
- ads_memfree(ads, wkn_dn);
+ TALLOC_FREE(wkn_dn);
if (wkn_dn_exp) {
ldap_value_free(wkn_dn_exp);
}
@@ -1741,14 +1731,14 @@ uint32 ads_get_kvno(ADS_STRUCT *ads, const char *account_name)
return kvno;
}
- dn_string = ads_get_dn(ads, res);
+ dn_string = ads_get_dn(ads, talloc_tos(), res);
if (!dn_string) {
DEBUG(0,("ads_get_kvno: out of memory.\n"));
ads_msgfree(ads, res);
return kvno;
}
DEBUG(5,("ads_get_kvno: Using: %s\n", dn_string));
- ads_memfree(ads, dn_string);
+ TALLOC_FREE(dn_string);
/* ---------------------------------------------------------
* 0 is returned as a default KVNO from this point on...
@@ -1836,14 +1826,14 @@ ADS_STATUS ads_clear_service_principal_names(ADS_STRUCT *ads, const char *machin
talloc_destroy(ctx);
return ret;
}
- dn_string = ads_get_dn(ads, res);
+ dn_string = ads_get_dn(ads, talloc_tos(), res);
if (!dn_string) {
talloc_destroy(ctx);
ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
ret = ads_gen_mod(ads, dn_string, mods);
- ads_memfree(ads,dn_string);
+ TALLOC_FREE(dn_string);
if (!ADS_ERR_OK(ret)) {
DEBUG(1,("ads_clear_service_principal_names: Error: Updating Service Principals for machine %s in LDAP\n",
machine_name));
@@ -1933,13 +1923,12 @@ ADS_STATUS ads_add_service_principal_name(ADS_STRUCT *ads, const char *machine_n
goto out;
}
- if ( (dn_string = ads_get_dn(ads, res)) == NULL ) {
+ if ( (dn_string = ads_get_dn(ads, ctx, res)) == NULL ) {
ret = ADS_ERROR(LDAP_NO_MEMORY);
goto out;
}
ret = ads_gen_mod(ads, dn_string, mods);
- ads_memfree(ads,dn_string);
if (!ADS_ERR_OK(ret)) {
DEBUG(1,("ads_add_service_principal_name: Error: Updating Service Principals in LDAP\n"));
goto out;
@@ -2052,7 +2041,7 @@ ADS_STATUS ads_move_machine_acct(ADS_STRUCT *ads, const char *machine_name,
goto done;
}
- computer_dn = ads_get_dn(ads, res);
+ computer_dn = ads_get_dn(ads, talloc_tos(), res);
if (!computer_dn) {
rc = ADS_ERROR(LDAP_NO_MEMORY);
goto done;
@@ -3029,7 +3018,7 @@ ADS_STATUS ads_site_dn_for_machine(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const c
return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
}
- dn = ads_get_dn(ads, res);
+ dn = ads_get_dn(ads, mem_ctx, res);
if (dn == NULL) {
ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
@@ -3039,18 +3028,18 @@ ADS_STATUS ads_site_dn_for_machine(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const c
parent = ads_parent_dn(ads_parent_dn(ads_parent_dn(dn)));
if (parent == NULL) {
ads_msgfree(ads, res);
- ads_memfree(ads, dn);
+ TALLOC_FREE(dn);
return ADS_ERROR(LDAP_NO_MEMORY);
}
*site_dn = talloc_strdup(mem_ctx, parent);
if (*site_dn == NULL) {
ads_msgfree(ads, res);
- ads_memfree(ads, dn);
+ TALLOC_FREE(dn);
return ADS_ERROR(LDAP_NO_MEMORY);
}
- ads_memfree(ads, dn);
+ TALLOC_FREE(dn);
ads_msgfree(ads, res);
return status;
@@ -3140,7 +3129,7 @@ ADS_STATUS ads_get_joinable_ous(ADS_STRUCT *ads,
char *dn = NULL;
- dn = ads_get_dn(ads, msg);
+ dn = ads_get_dn(ads, talloc_tos(), msg);
if (!dn) {
ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
@@ -3149,12 +3138,12 @@ ADS_STATUS ads_get_joinable_ous(ADS_STRUCT *ads,
if (!add_string_to_array(mem_ctx, dn,
(const char ***)ous,
(int *)num_ous)) {
- ads_memfree(ads, dn);
+ TALLOC_FREE(dn);
ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
- ads_memfree(ads, dn);
+ TALLOC_FREE(dn);
}
ads_msgfree(ads, res);
@@ -3494,7 +3483,7 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
return ADS_ERROR_SYSTEM(ENOENT);
}
- hostnameDN = ads_get_dn(ads, (LDAPMessage *)msg);
+ hostnameDN = ads_get_dn(ads, talloc_tos(), (LDAPMessage *)msg);
rc = ldap_delete_ext_s(ads->ldap.ld, hostnameDN, pldap_control, NULL);
if (rc) {
@@ -3516,7 +3505,7 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
if (!ADS_ERR_OK(status)) {
SAFE_FREE(host);
- ads_memfree(ads, hostnameDN);
+ TALLOC_FREE(hostnameDN);
return status;
}
@@ -3525,9 +3514,9 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
char *dn = NULL;
- if ((dn = ads_get_dn(ads, msg_sub)) == NULL) {
+ if ((dn = ads_get_dn(ads, talloc_tos(), msg_sub)) == NULL) {
SAFE_FREE(host);
- ads_memfree(ads, hostnameDN);
+ TALLOC_FREE(hostnameDN);
return ADS_ERROR(LDAP_NO_MEMORY);
}
@@ -3535,12 +3524,12 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
if (!ADS_ERR_OK(status)) {
DEBUG(3,("failed to delete dn %s: %s\n", dn, ads_errstr(status)));
SAFE_FREE(host);
- ads_memfree(ads, dn);
- ads_memfree(ads, hostnameDN);
+ TALLOC_FREE(dn);
+ TALLOC_FREE(hostnameDN);
return status;
}
- ads_memfree(ads, dn);
+ TALLOC_FREE(dn);
}
/* there should be no subordinate objects anymore */
@@ -3550,7 +3539,7 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
if (!ADS_ERR_OK(status) || ( (ads_count_replies(ads, res)) > 0 ) ) {
SAFE_FREE(host);
- ads_memfree(ads, hostnameDN);
+ TALLOC_FREE(hostnameDN);
return status;
}
@@ -3559,12 +3548,12 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
if (!ADS_ERR_OK(status)) {
SAFE_FREE(host);
DEBUG(3,("failed to delete dn %s: %s\n", hostnameDN, ads_errstr(status)));
- ads_memfree(ads, hostnameDN);
+ TALLOC_FREE(hostnameDN);
return status;
}
}
- ads_memfree(ads, hostnameDN);
+ TALLOC_FREE(hostnameDN);
status = ads_find_machine_acct(ads, &res, host);
if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) {
@@ -3723,7 +3712,7 @@ ADS_STATUS ads_find_samaccount(ADS_STRUCT *ads,
goto out;
}
- dn = ads_get_dn(ads, res);
+ dn = ads_get_dn(ads, talloc_tos(), res);
if (dn == NULL) {
status = ADS_ERROR(LDAP_NO_MEMORY);
goto out;
@@ -3746,7 +3735,7 @@ ADS_STATUS ads_find_samaccount(ADS_STRUCT *ads,
}
}
out:
- ads_memfree(ads, dn);
+ TALLOC_FREE(dn);
ads_msgfree(ads, res);
return status;
diff --git a/source3/libgpo/gpo_ldap.c b/source3/libgpo/gpo_ldap.c
index 26813864e5..716b8729c3 100644
--- a/source3/libgpo/gpo_ldap.c
+++ b/source3/libgpo/gpo_ldap.c
@@ -415,7 +415,7 @@ ADS_STATUS ads_delete_gpo_link(ADS_STRUCT *ads,
if (gpo_dn) {
gpo->ds_path = talloc_strdup(mem_ctx, gpo_dn);
} else {
- gpo->ds_path = ads_get_dn(ads, res);
+ gpo->ds_path = ads_get_dn(ads, mem_ctx, res);
}
ADS_ERROR_HAVE_NO_MEMORY(gpo->ds_path);
@@ -453,7 +453,7 @@ ADS_STATUS ads_delete_gpo_link(ADS_STRUCT *ads,
}
/****************************************************************
- get a GROUP_POLICY_OBJECT structure based on different input paramters
+ get a GROUP_POLICY_OBJECT structure based on different input parameters
****************************************************************/
ADS_STATUS ads_get_gpo(ADS_STRUCT *ads,
@@ -523,7 +523,7 @@ ADS_STATUS ads_get_gpo(ADS_STRUCT *ads,
return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
}
- dn = ads_get_dn(ads, res);
+ dn = ads_get_dn(ads, mem_ctx, res);
if (dn == NULL) {
ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
@@ -531,7 +531,7 @@ ADS_STATUS ads_get_gpo(ADS_STRUCT *ads,
status = ads_parse_gpo(ads, mem_ctx, res, dn, gpo);
ads_msgfree(ads, res);
- ads_memfree(ads, dn);
+ TALLOC_FREE(dn);
return status;
}
diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c
index ccfd943a8d..fe9fd66fdc 100644
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -303,7 +303,7 @@ static ADS_STATUS libnet_join_find_machine_acct(TALLOC_CTX *mem_ctx,
goto done;
}
- dn = ads_get_dn(r->in.ads, res);
+ dn = ads_get_dn(r->in.ads, mem_ctx, res);
if (!dn) {
status = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
goto done;
@@ -317,7 +317,7 @@ static ADS_STATUS libnet_join_find_machine_acct(TALLOC_CTX *mem_ctx,
done:
ads_msgfree(r->in.ads, res);
- ads_memfree(r->in.ads, dn);
+ TALLOC_FREE(dn);
return status;
}
diff --git a/source3/libnet/libnet_keytab.c b/source3/libnet/libnet_keytab.c
index 81956942ca..589d4c2525 100644
--- a/source3/libnet/libnet_keytab.c
+++ b/source3/libnet/libnet_keytab.c
@@ -144,7 +144,7 @@ static krb5_error_code libnet_keytab_remove_entries(krb5_context context,
goto cont;
}
- ret = smb_krb5_unparse_name(context, kt_entry.principal,
+ ret = smb_krb5_unparse_name(talloc_tos(), context, kt_entry.principal,
&princ_s);
if (ret) {
DEBUG(5, ("smb_krb5_unparse_name failed (%s)\n",
@@ -190,7 +190,7 @@ static krb5_error_code libnet_keytab_remove_entries(krb5_context context,
cont:
smb_krb5_kt_free_entry(context, &kt_entry);
- SAFE_FREE(princ_s);
+ TALLOC_FREE(princ_s);
}
ret = krb5_kt_end_seq_get(context, keytab, &cursor);
@@ -334,6 +334,8 @@ struct libnet_keytab_entry *libnet_keytab_search(struct libnet_keytab_context *c
krb5_keyblock *keyp;
char *princ_s = NULL;
+ entry = NULL;
+
if (kt_entry.vno != kvno) {
goto cont;
}
@@ -344,7 +346,13 @@ struct libnet_keytab_entry *libnet_keytab_search(struct libnet_keytab_context *c
goto cont;
}
- ret = smb_krb5_unparse_name(ctx->context, kt_entry.principal,
+ entry = talloc_zero(mem_ctx, struct libnet_keytab_entry);
+ if (!entry) {
+ DEBUG(3, ("talloc failed\n"));
+ goto fail;
+ }
+
+ ret = smb_krb5_unparse_name(entry, ctx->context, kt_entry.principal,
&princ_s);
if (ret) {
goto cont;
@@ -354,24 +362,14 @@ struct libnet_keytab_entry *libnet_keytab_search(struct libnet_keytab_context *c
goto cont;
}
- entry = talloc_zero(mem_ctx, struct libnet_keytab_entry);
- if (!entry) {
- DEBUG(3, ("talloc failed\n"));
- goto fail;
- }
-
- entry->name = talloc_strdup(entry, princ_s);
- if (!entry->name) {
- DEBUG(3, ("talloc_strdup_failed\n"));
- goto fail;
- }
-
entry->principal = talloc_strdup(entry, princ_s);
if (!entry->principal) {
DEBUG(3, ("talloc_strdup_failed\n"));
goto fail;
}
+ entry->name = talloc_move(entry, &princ_s);
+
entry->password = data_blob_talloc(entry, KRB5_KEY_DATA(keyp),
KRB5_KEY_LENGTH(keyp));
if (!entry->password.data) {
@@ -382,18 +380,16 @@ struct libnet_keytab_entry *libnet_keytab_search(struct libnet_keytab_context *c
DEBUG(10, ("found entry\n"));
smb_krb5_kt_free_entry(ctx->context, &kt_entry);
- SAFE_FREE(princ_s);
break;
fail:
smb_krb5_kt_free_entry(ctx->context, &kt_entry);
- SAFE_FREE(princ_s);
TALLOC_FREE(entry);
break;
cont:
smb_krb5_kt_free_entry(ctx->context, &kt_entry);
- SAFE_FREE(princ_s);
+ TALLOC_FREE(entry);
continue;
}
diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c
index 86fd5c8bef..6faf96c207 100644
--- a/source3/libsmb/async_smb.c
+++ b/source3/libsmb/async_smb.c
@@ -19,9 +19,6 @@
#include "includes.h"
-static void cli_state_handler(struct event_context *event_ctx,
- struct fd_event *event, uint16 flags, void *p);
-
/**
* Fetch an error out of a NBT packet
* @param[in] buf The SMB packet
@@ -69,89 +66,6 @@ void cli_set_error(struct cli_state *cli, NTSTATUS status)
}
/**
- * Allocate a new mid
- * @param[in] cli The client connection
- * @retval The new, unused mid
- */
-
-static uint16_t cli_new_mid(struct cli_state *cli)
-{
- uint16_t result;
- struct cli_request *req;
-
- while (true) {
- result = cli->mid++;
- if (result == 0) {
- continue;
- }
-
- for (req = cli->outstanding_requests; req; req = req->next) {
- if (result == req->mid) {
- break;
- }
- }
-
- if (req == NULL) {
- return result;
- }
- }
-}
-
-/**
- * Print an async req that happens to be a cli_request
- * @param[in] mem_ctx The TALLOC_CTX to put the result on
- * @param[in] req The request to print
- * @retval The string representation of "req"
- */
-
-static char *cli_request_print(TALLOC_CTX *mem_ctx, struct async_req *req)
-{
- char *result = async_req_print(mem_ctx, req);
- struct cli_request *cli_req = talloc_get_type_abort(
- req->private_data, struct cli_request);
-
- if (result == NULL) {
- return NULL;
- }
-
- return talloc_asprintf_append_buffer(
- result, "mid=%d\n", cli_req->mid);
-}
-
-/**
- * Destroy a cli_request
- * @param[in] req The cli_request to kill
- * @retval Can't fail
- */
-
-static int cli_request_destructor(struct cli_request *req)
-{
- if (req->enc_state != NULL) {
- common_free_enc_buffer(req->enc_state, (char *)req->outbuf);
- }
- DLIST_REMOVE(req->cli->outstanding_requests, req);
- if (req->cli->outstanding_requests == NULL) {
- TALLOC_FREE(req->cli->fd_event);
- }
- return 0;
-}
-
-/**
- * Are there already requests waiting in the chain_accumulator?
- * @param[in] cli The cli_state we want to check
- * @retval reply :-)
- */
-
-bool cli_in_chain(struct cli_state *cli)
-{
- if (cli->chain_accumulator == NULL) {
- return false;
- }
-
- return (cli->chain_accumulator->num_async != 0);
-}
-
-/**
* @brief Find the smb_cmd offset of the last command pushed
* @param[in] buf The buffer we're building up
* @retval Where can we put our next andx cmd?
@@ -326,417 +240,614 @@ bool smb_splice_chain(uint8_t **poutbuf, uint8_t smb_command,
}
/**
- * @brief Destroy an async_req that is the visible part of a cli_request
- * @param[in] req The request to kill
- * @retval Return 0 to make talloc happy
- *
- * This destructor is a bit tricky: Because a cli_request can host more than
- * one async_req for chained requests, we need to make sure that the
- * "cli_request" that we were part of is correctly destroyed at the right
- * time. This is done by NULLing out ourself from the "async" member of our
- * "cli_request". If there is none left, then also TALLOC_FREE() the
- * cli_request, which was a talloc child of the client connection cli_state.
+ * Figure out if there is an andx command behind the current one
+ * @param[in] buf The smb buffer to look at
+ * @param[in] ofs The offset to the wct field that is followed by the cmd
+ * @retval Is there a command following?
*/
-static int cli_async_req_destructor(struct async_req *req)
+static bool have_andx_command(const char *buf, uint16_t ofs)
{
- struct cli_request *cli_req = talloc_get_type_abort(
- req->private_data, struct cli_request);
- int i, pending;
- bool found = false;
+ uint8_t wct;
+ size_t buflen = talloc_get_size(buf);
- pending = 0;
+ if ((ofs == buflen-1) || (ofs == buflen)) {
+ return false;
+ }
- for (i=0; i<cli_req->num_async; i++) {
- if (cli_req->async[i] == req) {
- cli_req->async[i] = NULL;
- found = true;
- }
- if (cli_req->async[i] != NULL) {
- pending += 1;
- }
+ wct = CVAL(buf, ofs);
+ if (wct < 2) {
+ /*
+ * Not enough space for the command and a following pointer
+ */
+ return false;
}
+ return (CVAL(buf, ofs+1) != 0xff);
+}
- SMB_ASSERT(found);
+#define MAX_SMB_IOV 5
- if (pending == 0) {
- TALLOC_FREE(cli_req);
- }
+struct cli_smb_state {
+ struct tevent_context *ev;
+ struct cli_state *cli;
+ uint8_t header[smb_wct+1]; /* Space for the header including the wct */
- return 0;
-}
+ /*
+ * For normal requests, cli_smb_req_send chooses a mid. Secondary
+ * trans requests need to use the mid of the primary request, so we
+ * need a place to store it. Assume it's set if != 0.
+ */
+ uint16_t mid;
-/**
- * @brief Chain up a request
- * @param[in] mem_ctx The TALLOC_CTX for the result
- * @param[in] ev The event context that will call us back
- * @param[in] cli The cli_state we queue the request up for
- * @param[in] smb_command The command that we want to issue
- * @param[in] additional_flags open_and_x wants to add oplock header flags
- * @param[in] wct How many words?
- * @param[in] vwv The words, already in network order
- * @param[in] bytes_alignment How shall we align "bytes"?
- * @param[in] num_bytes How many bytes?
- * @param[in] bytes The data the request ships
- *
- * cli_request_chain() is the core of the SMB request marshalling routine. It
- * will create a new async_req structure in the cli->chain_accumulator->async
- * array and marshall the smb_cmd, the vwv array and the bytes into
- * cli->chain_accumulator->outbuf.
- */
+ uint16_t *vwv;
+ uint8_t bytecount_buf[2];
+
+ struct iovec iov[MAX_SMB_IOV+3];
+ int iov_count;
-static struct async_req *cli_request_chain(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli,
- uint8_t smb_command,
- uint8_t additional_flags,
- uint8_t wct, const uint16_t *vwv,
- size_t bytes_alignment,
- uint32_t num_bytes,
- const uint8_t *bytes)
+ uint8_t *inbuf;
+ uint32_t seqnum;
+ int chain_num;
+ struct tevent_req **chained_requests;
+};
+
+static uint16_t cli_alloc_mid(struct cli_state *cli)
{
- struct async_req **tmp_reqs;
- struct cli_request *req;
+ int num_pending = talloc_array_length(cli->pending);
+ uint16_t result;
- req = cli->chain_accumulator;
+ while (true) {
+ int i;
- tmp_reqs = TALLOC_REALLOC_ARRAY(req, req->async, struct async_req *,
- req->num_async + 1);
- if (tmp_reqs == NULL) {
- DEBUG(0, ("talloc failed\n"));
- return NULL;
+ result = cli->mid++;
+ if ((result == 0) || (result == 0xffff)) {
+ continue;
+ }
+
+ for (i=0; i<num_pending; i++) {
+ if (result == cli_smb_req_mid(cli->pending[i])) {
+ break;
+ }
+ }
+
+ if (i == num_pending) {
+ return result;
+ }
}
- req->async = tmp_reqs;
- req->num_async += 1;
+}
- 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;
- return NULL;
+void cli_smb_req_unset_pending(struct tevent_req *req)
+{
+ struct cli_smb_state *state = tevent_req_data(
+ req, struct cli_smb_state);
+ struct cli_state *cli = state->cli;
+ int num_pending = talloc_array_length(cli->pending);
+ int i;
+
+ if (num_pending == 1) {
+ /*
+ * The pending read_smb tevent_req is a child of
+ * cli->pending. So if nothing is pending anymore, we need to
+ * delete the socket read fde.
+ */
+ TALLOC_FREE(cli->pending);
+ return;
}
- req->async[req->num_async-1]->private_data = req;
- req->async[req->num_async-1]->print = cli_request_print;
- talloc_set_destructor(req->async[req->num_async-1],
- cli_async_req_destructor);
- if (!smb_splice_chain(&req->outbuf, smb_command, wct, vwv,
- bytes_alignment, num_bytes, bytes)) {
- goto fail;
+ for (i=0; i<num_pending; i++) {
+ if (req == cli->pending[i]) {
+ break;
+ }
+ }
+ if (i == num_pending) {
+ /*
+ * Something's seriously broken. Just returning here is the
+ * right thing nevertheless, the point of this routine is to
+ * remove ourselves from cli->pending.
+ */
+ return;
+ }
+
+ /*
+ * Remove ourselves from the cli->pending array
+ */
+ if (num_pending > 1) {
+ cli->pending[i] = cli->pending[num_pending-1];
}
- return req->async[req->num_async-1];
+ /*
+ * No NULL check here, we're shrinking by sizeof(void *), and
+ * talloc_realloc just adjusts the size for this.
+ */
+ cli->pending = talloc_realloc(NULL, cli->pending, struct tevent_req *,
+ num_pending - 1);
+ return;
+}
- fail:
- TALLOC_FREE(req->async[req->num_async-1]);
- req->num_async -= 1;
- return NULL;
+static int cli_smb_req_destructor(struct tevent_req *req)
+{
+ cli_smb_req_unset_pending(req);
+ return 0;
}
-/**
- * @brief prepare a cli_state to accept a chain of requests
- * @param[in] cli The cli_state we want to queue up in
- * @param[in] ev The event_context that will call us back for the socket
- * @param[in] size_hint How many bytes are expected, just an optimization
- * @retval Did we have enough memory?
- *
- * cli_chain_cork() sets up a new cli_request in cli->chain_accumulator. If
- * cli is used in an async fashion, i.e. if we have outstanding requests, then
- * we do not have to create a fd event. If cli is used only with the sync
- * helpers, we need to create the fd_event here.
- *
- * If you want to issue a chained request to the server, do a
- * cli_chain_cork(), then do you cli_open_send(), cli_read_and_x_send(),
- * cli_close_send() and so on. The async requests that come out of
- * cli_xxx_send() are normal async requests with the difference that they
- * won't be shipped individually. But the event_context will still trigger the
- * req->async.fn to be called on every single request.
- *
- * You have to take care yourself that you only issue chainable requests in
- * the middle of the chain.
- */
+static void cli_smb_received(struct tevent_req *subreq);
-bool cli_chain_cork(struct cli_state *cli, struct event_context *ev,
- size_t size_hint)
+bool cli_smb_req_set_pending(struct tevent_req *req)
{
- struct cli_request *req = NULL;
+ struct cli_smb_state *state = tevent_req_data(
+ req, struct cli_smb_state);
+ struct cli_state *cli;
+ struct tevent_req **pending;
+ int num_pending;
+ struct tevent_req *subreq;
+
+ cli = state->cli;
+ num_pending = talloc_array_length(cli->pending);
+
+ pending = talloc_realloc(cli, cli->pending, struct tevent_req *,
+ num_pending+1);
+ if (pending == NULL) {
+ return false;
+ }
+ pending[num_pending] = req;
+ cli->pending = pending;
+ talloc_set_destructor(req, cli_smb_req_destructor);
- SMB_ASSERT(cli->chain_accumulator == NULL);
+ if (num_pending > 0) {
+ return true;
+ }
- if (cli->fd == -1) {
- DEBUG(10, ("cli->fd closed\n"));
+ /*
+ * We're the first ones, add the read_smb request that waits for the
+ * answer from the server
+ */
+ subreq = read_smb_send(cli->pending, state->ev, cli->fd);
+ if (subreq == NULL) {
+ cli_smb_req_unset_pending(req);
return false;
}
+ tevent_req_set_callback(subreq, cli_smb_received, cli);
+ return true;
+}
- if (cli->fd_event == NULL) {
- SMB_ASSERT(cli->outstanding_requests == NULL);
- cli->fd_event = event_add_fd(ev, cli, cli->fd,
- EVENT_FD_READ,
- cli_state_handler, cli);
- if (cli->fd_event == NULL) {
- return false;
- }
- }
+/*
+ * Fetch a smb request's mid. Only valid after the request has been sent by
+ * cli_smb_req_send().
+ */
+uint16_t cli_smb_req_mid(struct tevent_req *req)
+{
+ struct cli_smb_state *state = tevent_req_data(
+ req, struct cli_smb_state);
+ return SVAL(state->header, smb_mid);
+}
- req = talloc(cli, struct cli_request);
- if (req == NULL) {
- goto fail;
+void cli_smb_req_set_mid(struct tevent_req *req, uint16_t mid)
+{
+ struct cli_smb_state *state = tevent_req_data(
+ req, struct cli_smb_state);
+ state->mid = mid;
+}
+
+static size_t iov_len(const struct iovec *iov, int count)
+{
+ size_t result = 0;
+ int i;
+ for (i=0; i<count; i++) {
+ result += iov[i].iov_len;
}
- req->cli = cli;
+ return result;
+}
- if (size_hint == 0) {
- size_hint = 100;
+static uint8_t *iov_concat(TALLOC_CTX *mem_ctx, const struct iovec *iov,
+ int count)
+{
+ size_t len = iov_len(iov, count);
+ size_t copied;
+ uint8_t *buf;
+ int i;
+
+ buf = talloc_array(mem_ctx, uint8_t, len);
+ if (buf == NULL) {
+ return NULL;
}
- req->outbuf = talloc_array(req, uint8_t, smb_wct + size_hint);
- if (req->outbuf == NULL) {
- goto fail;
+ copied = 0;
+ for (i=0; i<count; i++) {
+ memcpy(buf+copied, iov[i].iov_base, iov[i].iov_len);
+ copied += iov[i].iov_len;
}
- req->outbuf = TALLOC_REALLOC_ARRAY(NULL, req->outbuf, uint8_t,
- smb_wct);
+ return buf;
+}
- req->num_async = 0;
- req->async = NULL;
+struct tevent_req *cli_smb_req_create(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
+ uint8_t smb_command,
+ uint8_t additional_flags,
+ uint8_t wct, uint16_t *vwv,
+ int iov_count,
+ struct iovec *bytes_iov)
+{
+ struct tevent_req *result;
+ struct cli_smb_state *state;
- req->enc_state = NULL;
- req->recv_helper.fn = NULL;
+ if (iov_count > MAX_SMB_IOV) {
+ /*
+ * Should not happen :-)
+ */
+ return NULL;
+ }
- SSVAL(req->outbuf, smb_tid, cli->cnum);
- cli_setup_packet_buf(cli, (char *)req->outbuf);
+ result = tevent_req_create(mem_ctx, &state, struct cli_smb_state);
+ if (result == NULL) {
+ return NULL;
+ }
+ state->ev = ev;
+ state->cli = cli;
+ state->mid = 0; /* Set to auto-choose in cli_smb_req_send */
+ state->chain_num = 0;
+ state->chained_requests = NULL;
+
+ cli_setup_packet_buf(cli, (char *)state->header);
+ SCVAL(state->header, smb_com, smb_command);
+ SSVAL(state->header, smb_tid, cli->cnum);
+ SCVAL(state->header, smb_wct, wct);
+
+ state->vwv = vwv;
+
+ SSVAL(state->bytecount_buf, 0, iov_len(bytes_iov, iov_count));
+
+ state->iov[0].iov_base = state->header;
+ state->iov[0].iov_len = sizeof(state->header);
+ state->iov[1].iov_base = state->vwv;
+ state->iov[1].iov_len = wct * sizeof(uint16_t);
+ state->iov[2].iov_base = state->bytecount_buf;
+ state->iov[2].iov_len = sizeof(uint16_t);
+
+ if (iov_count != 0) {
+ memcpy(&state->iov[3], bytes_iov,
+ iov_count * sizeof(*bytes_iov));
+ }
+ state->iov_count = iov_count + 3;
- req->mid = cli_new_mid(cli);
+ return result;
+}
- cli->chain_accumulator = req;
+static bool cli_signv(struct cli_state *cli, struct iovec *iov, int count,
+ uint32_t *seqnum)
+{
+ uint8_t *buf;
- DEBUG(10, ("cli_chain_cork: mid=%d\n", req->mid));
+ /*
+ * Obvious optimization: Make cli_calculate_sign_mac work with struct
+ * iovec directly. MD5Update would do that just fine.
+ */
- return true;
- fail:
- TALLOC_FREE(req);
- if (cli->outstanding_requests == NULL) {
- TALLOC_FREE(cli->fd_event);
+ if ((count <= 0) || (iov[0].iov_len < smb_wct)) {
+ return false;
}
- return false;
-}
-/**
- * Ship a request queued up via cli_request_chain()
- * @param[in] cl The connection
- */
+ buf = iov_concat(talloc_tos(), iov, count);
+ if (buf == NULL) {
+ return false;
+ }
-void cli_chain_uncork(struct cli_state *cli)
-{
- struct cli_request *req = cli->chain_accumulator;
- size_t smblen;
+ cli_calculate_sign_mac(cli, (char *)buf, seqnum);
+ memcpy(iov[0].iov_base, buf, iov[0].iov_len);
- SMB_ASSERT(req != NULL);
+ TALLOC_FREE(buf);
+ return true;
+}
- DLIST_ADD_END(cli->outstanding_requests, req, struct cli_request *);
- talloc_set_destructor(req, cli_request_destructor);
+static void cli_smb_sent(struct tevent_req *subreq);
- cli->chain_accumulator = NULL;
+static bool cli_smb_req_iov_send(struct tevent_req *req,
+ struct cli_smb_state *state,
+ struct iovec *iov, int iov_count)
+{
+ struct tevent_req *subreq;
- SSVAL(req->outbuf, smb_mid, req->mid);
+ if (iov[0].iov_len < smb_wct) {
+ return false;
+ }
- smblen = talloc_get_size(req->outbuf) - 4;
+ if (state->mid != 0) {
+ SSVAL(iov[0].iov_base, smb_mid, state->mid);
+ } else {
+ SSVAL(iov[0].iov_base, smb_mid, cli_alloc_mid(state->cli));
+ }
- smb_setlen((char *)req->outbuf, smblen);
+ smb_setlen((char *)iov[0].iov_base, iov_len(iov, iov_count) - 4);
- if (smblen > 0x1ffff) {
- /*
- * This is a POSIX 14 word large write. Overwrite just the
- * size field, the '0xFFSMB' has been set by smb_setlen which
- * _smb_setlen_large does not do.
- */
- _smb_setlen_large(((char *)req->outbuf), smblen);
+ if (!cli_signv(state->cli, iov, iov_count, &state->seqnum)) {
+ return false;
}
- cli_calculate_sign_mac(cli, (char *)req->outbuf, &req->seqnum);
-
- if (cli_encryption_on(cli)) {
+ if (cli_encryption_on(state->cli)) {
NTSTATUS status;
- char *enc_buf;
+ char *buf, *enc_buf;
- status = cli_encrypt_message(cli, (char *)req->outbuf,
+ buf = (char *)iov_concat(talloc_tos(), iov, iov_count);
+ if (buf == NULL) {
+ return false;
+ }
+ status = cli_encrypt_message(state->cli, (char *)buf,
&enc_buf);
+ TALLOC_FREE(buf);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("Error in encrypting client message. "
- "Error %s\n", nt_errstr(status)));
- TALLOC_FREE(req);
- return;
+ DEBUG(0, ("Error in encrypting client message: %s\n",
+ nt_errstr(status)));
+ return false;
}
- req->outbuf = (uint8_t *)enc_buf;
- req->enc_state = cli->trans_enc_state;
+ buf = (char *)talloc_memdup(state, enc_buf,
+ smb_len(enc_buf)+4);
+ SAFE_FREE(enc_buf);
+ if (buf == NULL) {
+ return false;
+ }
+ iov[0].iov_base = buf;
+ iov[0].iov_len = talloc_get_size(buf);
+ subreq = writev_send(state, state->ev, state->cli->outgoing,
+ state->cli->fd, iov, 1);
+ } else {
+ subreq = writev_send(state, state->ev, state->cli->outgoing,
+ state->cli->fd, iov, iov_count);
+ }
+ if (subreq == NULL) {
+ return false;
}
+ tevent_req_set_callback(subreq, cli_smb_sent, req);
+ return true;
+}
- req->sent = 0;
+bool cli_smb_req_send(struct tevent_req *req)
+{
+ struct cli_smb_state *state = tevent_req_data(
+ req, struct cli_smb_state);
- event_fd_set_writeable(cli->fd_event);
+ return cli_smb_req_iov_send(req, state, state->iov, state->iov_count);
}
-/**
- * @brief Send a request to the server
- * @param[in] mem_ctx The TALLOC_CTX for the result
- * @param[in] ev The event context that will call us back
- * @param[in] cli The cli_state we queue the request up for
- * @param[in] smb_command The command that we want to issue
- * @param[in] additional_flags open_and_x wants to add oplock header flags
- * @param[in] wct How many words?
- * @param[in] vwv The words, already in network order
- * @param[in] bytes_alignment How shall we align "bytes"?
- * @param[in] num_bytes How many bytes?
- * @param[in] bytes The data the request ships
- *
- * This is the generic routine to be used by the cli_xxx_send routines.
- */
-
-struct async_req *cli_request_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli,
- uint8_t smb_command,
- uint8_t additional_flags,
- uint8_t wct, const uint16_t *vwv,
- size_t bytes_alignment,
- uint32_t num_bytes, const uint8_t *bytes)
+struct tevent_req *cli_smb_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
+ uint8_t smb_command,
+ uint8_t additional_flags,
+ uint8_t wct, uint16_t *vwv,
+ uint32_t num_bytes,
+ const uint8_t *bytes)
{
- struct async_req *result;
- bool uncork = false;
-
- if (cli->chain_accumulator == NULL) {
- if (!cli_chain_cork(cli, ev,
- wct * sizeof(uint16_t) + num_bytes + 3)) {
- DEBUG(1, ("cli_chain_cork failed\n"));
- return NULL;
- }
- uncork = true;
- }
+ struct tevent_req *req;
+ struct iovec iov;
- result = cli_request_chain(mem_ctx, ev, cli, smb_command,
- additional_flags, wct, vwv, bytes_alignment,
- num_bytes, bytes);
+ iov.iov_base = CONST_DISCARD(char *, bytes);
+ iov.iov_len = num_bytes;
- if (result == NULL) {
- DEBUG(1, ("cli_request_chain failed\n"));
+ req = cli_smb_req_create(mem_ctx, ev, cli, smb_command,
+ additional_flags, wct, vwv, 1, &iov);
+ if (req == NULL) {
+ return NULL;
}
+ if (!cli_smb_req_send(req)) {
+ TALLOC_FREE(req);
+ }
+ return req;
+}
- if (uncork) {
- cli_chain_uncork(cli);
+static void cli_smb_sent(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_smb_state *state = tevent_req_data(
+ req, struct cli_smb_state);
+ ssize_t nwritten;
+ int err;
+
+ nwritten = writev_recv(subreq, &err);
+ TALLOC_FREE(subreq);
+ if (nwritten == -1) {
+ tevent_req_nterror(req, map_nt_error_from_unix(err));
+ return;
}
- return result;
-}
+ switch (CVAL(state->header, smb_com)) {
+ case SMBtranss:
+ case SMBtranss2:
+ case SMBnttranss:
+ case SMBntcancel:
+ state->inbuf = NULL;
+ tevent_req_done(req);
+ return;
+ case SMBlockingX:
+ if ((CVAL(state->header, smb_wct) == 8) &&
+ (CVAL(state->vwv+3, 0) == LOCKING_ANDX_OPLOCK_RELEASE)) {
+ state->inbuf = NULL;
+ tevent_req_done(req);
+ return;
+ }
+ }
-/**
- * Calculate the current ofs to wct for requests like write&x
- * @param[in] req The smb request we're currently building
- * @retval how many bytes offset have we accumulated?
- */
+ if (!cli_smb_req_set_pending(req)) {
+ tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
+ }
+}
-uint16_t cli_wct_ofs(const struct cli_state *cli)
+static void cli_smb_received(struct tevent_req *subreq)
{
- size_t buf_size;
+ struct cli_state *cli = tevent_req_callback_data(
+ subreq, struct cli_state);
+ struct tevent_req *req;
+ struct cli_smb_state *state;
+ struct tevent_context *ev;
+ NTSTATUS status;
+ uint8_t *inbuf;
+ ssize_t received;
+ int num_pending;
+ int i, err;
+ uint16_t mid;
+ bool oplock_break;
+
+ received = read_smb_recv(subreq, talloc_tos(), &inbuf, &err);
+ TALLOC_FREE(subreq);
+ if (received == -1) {
+ status = map_nt_error_from_unix(err);
+ goto fail;
+ }
- if (cli->chain_accumulator == NULL) {
- return smb_wct - 4;
+ if ((IVAL(inbuf, 4) != 0x424d53ff) /* 0xFF"SMB" */
+ && (SVAL(inbuf, 4) != 0x45ff)) /* 0xFF"E" */ {
+ DEBUG(10, ("Got non-SMB PDU\n"));
+ status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+ goto fail;
}
- buf_size = talloc_get_size(cli->chain_accumulator->outbuf);
+ if (cli_encryption_on(cli) && (CVAL(inbuf, 0) == 0)) {
+ uint16_t enc_ctx_num;
+
+ status = get_enc_ctx_num(inbuf, &enc_ctx_num);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("get_enc_ctx_num returned %s\n",
+ nt_errstr(status)));
+ goto fail;
+ }
+
+ if (enc_ctx_num != cli->trans_enc_state->enc_ctx_num) {
+ DEBUG(10, ("wrong enc_ctx %d, expected %d\n",
+ enc_ctx_num,
+ cli->trans_enc_state->enc_ctx_num));
+ status = NT_STATUS_INVALID_HANDLE;
+ goto fail;
+ }
- if (buf_size == smb_wct) {
- return smb_wct - 4;
+ status = common_decrypt_buffer(cli->trans_enc_state,
+ (char *)inbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("common_decrypt_buffer returned %s\n",
+ nt_errstr(status)));
+ goto fail;
+ }
}
- /*
- * Add alignment for subsequent requests
- */
+ mid = SVAL(inbuf, smb_mid);
+ num_pending = talloc_array_length(cli->pending);
- if ((buf_size % 4) != 0) {
- buf_size += (4 - (buf_size % 4));
+ for (i=0; i<num_pending; i++) {
+ if (mid == cli_smb_req_mid(cli->pending[i])) {
+ break;
+ }
+ }
+ if (i == num_pending) {
+ /* Dump unexpected reply */
+ TALLOC_FREE(inbuf);
+ goto done;
}
- return buf_size - 4;
-}
+ oplock_break = false;
-/**
- * Figure out if there is an andx command behind the current one
- * @param[in] buf The smb buffer to look at
- * @param[in] ofs The offset to the wct field that is followed by the cmd
- * @retval Is there a command following?
- */
+ if (mid == 0xffff) {
+ /*
+ * Paranoia checks that this is really an oplock break request.
+ */
+ oplock_break = (smb_len(inbuf) == 51); /* hdr + 8 words */
+ oplock_break &= ((CVAL(inbuf, smb_flg) & FLAG_REPLY) == 0);
+ oplock_break &= (CVAL(inbuf, smb_com) == SMBlockingX);
+ oplock_break &= (SVAL(inbuf, smb_vwv6) == 0);
+ oplock_break &= (SVAL(inbuf, smb_vwv7) == 0);
+
+ if (!oplock_break) {
+ /* Dump unexpected reply */
+ TALLOC_FREE(inbuf);
+ goto done;
+ }
+ }
-static bool have_andx_command(const char *buf, uint16_t ofs)
-{
- uint8_t wct;
- size_t buflen = talloc_get_size(buf);
+ req = cli->pending[i];
+ state = tevent_req_data(req, struct cli_smb_state);
+ ev = state->ev;
- if ((ofs == buflen-1) || (ofs == buflen)) {
- return false;
+ if (!oplock_break /* oplock breaks are not signed */
+ && !cli_check_sign_mac(cli, (char *)inbuf, state->seqnum+1)) {
+ DEBUG(10, ("cli_check_sign_mac failed\n"));
+ TALLOC_FREE(inbuf);
+ status = NT_STATUS_ACCESS_DENIED;
+ goto fail;
}
- wct = CVAL(buf, ofs);
- if (wct < 2) {
+ if (state->chained_requests == NULL) {
+ state->inbuf = talloc_move(state, &inbuf);
+ talloc_set_destructor(req, NULL);
+ cli_smb_req_destructor(req);
+ tevent_req_done(req);
+ } else {
+ struct tevent_req **chain = talloc_move(
+ talloc_tos(), &state->chained_requests);
+ int num_chained = talloc_array_length(chain);
+
+ for (i=0; i<num_chained; i++) {
+ state = tevent_req_data(chain[i], struct
+ cli_smb_state);
+ state->inbuf = inbuf;
+ state->chain_num = i;
+ tevent_req_done(chain[i]);
+ }
+ TALLOC_FREE(inbuf);
+ TALLOC_FREE(chain);
+ }
+ done:
+ if (talloc_array_length(cli->pending) > 0) {
/*
- * Not enough space for the command and a following pointer
+ * Set up another read request for the other pending cli_smb
+ * requests
*/
- return false;
+ state = tevent_req_data(cli->pending[0], struct cli_smb_state);
+ subreq = read_smb_send(cli->pending, state->ev, cli->fd);
+ if (subreq == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+ tevent_req_set_callback(subreq, cli_smb_received, cli);
+ }
+ return;
+ fail:
+ /*
+ * Cancel all pending requests. We don't do a for-loop walking
+ * cli->pending because that array changes in
+ * cli_smb_req_destructor().
+ */
+ while (talloc_array_length(cli->pending) > 0) {
+ req = cli->pending[0];
+ talloc_set_destructor(req, NULL);
+ cli_smb_req_destructor(req);
+ tevent_req_nterror(req, status);
}
- return (CVAL(buf, ofs+1) != 0xff);
}
-/**
- * @brief Pull reply data out of a request
- * @param[in] req The request that we just received a reply for
- * @param[out] pwct How many words did the server send?
- * @param[out] pvwv The words themselves
- * @param[out] pnum_bytes How many bytes did the server send?
- * @param[out] pbytes The bytes themselves
- * @retval Was the reply formally correct?
- */
-
-NTSTATUS cli_pull_reply(struct async_req *req,
- uint8_t *pwct, uint16_t **pvwv,
- uint16_t *pnum_bytes, uint8_t **pbytes)
+NTSTATUS cli_smb_recv(struct tevent_req *req, uint8_t min_wct,
+ uint8_t *pwct, uint16_t **pvwv,
+ uint32_t *pnum_bytes, uint8_t **pbytes)
{
- struct cli_request *cli_req = talloc_get_type_abort(
- req->private_data, struct cli_request);
- uint8_t wct, cmd;
+ struct cli_smb_state *state = tevent_req_data(
+ req, struct cli_smb_state);
+ NTSTATUS status = NT_STATUS_OK;
+ uint8_t cmd, wct;
uint16_t num_bytes;
size_t wct_ofs, bytes_offset;
- int i, j;
- NTSTATUS status;
-
- for (i = 0; i < cli_req->num_async; i++) {
- if (req == cli_req->async[i]) {
- break;
- }
- }
+ int i;
- if (i == cli_req->num_async) {
- cli_set_error(cli_req->cli, NT_STATUS_INVALID_PARAMETER);
- return NT_STATUS_INVALID_PARAMETER;
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
}
- /**
- * The status we pull here is only relevant for the last reply in the
- * chain.
- */
-
- status = cli_pull_error(cli_req->inbuf);
-
- if (i == 0) {
- if (NT_STATUS_IS_ERR(status)
- && !have_andx_command(cli_req->inbuf, smb_wct)) {
- cli_set_error(cli_req->cli, status);
- return status;
- }
- wct_ofs = smb_wct;
- goto done;
+ if (state->inbuf == NULL) {
+ /* This was a request without a reply */
+ return NT_STATUS_OK;
}
- cmd = CVAL(cli_req->inbuf, smb_com);
wct_ofs = smb_wct;
+ cmd = CVAL(state->inbuf, smb_com);
- for (j = 0; j < i; j++) {
- if (j < i-1) {
+ for (i=0; i<state->chain_num; i++) {
+ if (i < state->chain_num-1) {
if (cmd == 0xff) {
return NT_STATUS_REQUEST_ABORTED;
}
@@ -745,7 +856,7 @@ NTSTATUS cli_pull_reply(struct async_req *req,
}
}
- if (!have_andx_command(cli_req->inbuf, wct_ofs)) {
+ if (!have_andx_command((char *)state->inbuf, wct_ofs)) {
/*
* This request was not completed because a previous
* request in the chain had received an error.
@@ -753,7 +864,7 @@ NTSTATUS cli_pull_reply(struct async_req *req,
return NT_STATUS_REQUEST_ABORTED;
}
- wct_ofs = SVAL(cli_req->inbuf, wct_ofs + 3);
+ wct_ofs = SVAL(state->inbuf, wct_ofs + 3);
/*
* Skip the all-present length field. No overflow, we've just
@@ -761,14 +872,16 @@ NTSTATUS cli_pull_reply(struct async_req *req,
*/
wct_ofs += 4;
- if (wct_ofs+2 > talloc_get_size(cli_req->inbuf)) {
+ if (wct_ofs+2 > talloc_get_size(state->inbuf)) {
return NT_STATUS_INVALID_NETWORK_RESPONSE;
}
- cmd = CVAL(cli_req->inbuf, wct_ofs + 1);
+ cmd = CVAL(state->inbuf, wct_ofs + 1);
}
- if (!have_andx_command(cli_req->inbuf, wct_ofs)
+ status = cli_pull_error((char *)state->inbuf);
+
+ if (!have_andx_command((char *)state->inbuf, wct_ofs)
&& NT_STATUS_IS_ERR(status)) {
/*
* The last command takes the error code. All further commands
@@ -778,358 +891,241 @@ NTSTATUS cli_pull_reply(struct async_req *req,
return status;
}
- done:
- wct = CVAL(cli_req->inbuf, wct_ofs);
-
+ wct = CVAL(state->inbuf, wct_ofs);
bytes_offset = wct_ofs + 1 + wct * sizeof(uint16_t);
- num_bytes = SVAL(cli_req->inbuf, bytes_offset);
+ num_bytes = SVAL(state->inbuf, bytes_offset);
+
+ if (wct < min_wct) {
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
/*
* wct_ofs is a 16-bit value plus 4, wct is a 8-bit value, num_bytes
* is a 16-bit value. So bytes_offset being size_t should be far from
* wrapping.
*/
-
- if ((bytes_offset + 2 > talloc_get_size(cli_req->inbuf))
+ if ((bytes_offset + 2 > talloc_get_size(state->inbuf))
|| (bytes_offset > 0xffff)) {
return NT_STATUS_INVALID_NETWORK_RESPONSE;
}
- *pwct = wct;
- *pvwv = (uint16_t *)(cli_req->inbuf + wct_ofs + 1);
- *pnum_bytes = num_bytes;
- *pbytes = (uint8_t *)cli_req->inbuf + bytes_offset + 2;
-
- return NT_STATUS_OK;
-}
-
-/**
- * Decrypt a PDU, check the signature
- * @param[in] cli The cli_state that received something
- * @param[in] pdu The incoming bytes
- * @retval error code
- */
-
-
-static NTSTATUS validate_smb_crypto(struct cli_state *cli, char *pdu,
- struct cli_request **_req,
- uint16_t *_mid)
-{
- NTSTATUS status;
- struct cli_request *req = NULL;
- uint16_t mid;
-
- *_req = NULL;
- *_mid = 0;
-
- if ((IVAL(pdu, 4) != 0x424d53ff) /* 0xFF"SMB" */
- && (SVAL(pdu, 4) != 0x45ff)) /* 0xFF"E" */ {
- DEBUG(10, ("Got non-SMB PDU\n"));
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
- }
-
- if (cli_encryption_on(cli) && CVAL(pdu, 0) == 0) {
- uint16_t enc_ctx_num;
-
- status = get_enc_ctx_num((uint8_t *)pdu, &enc_ctx_num);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("get_enc_ctx_num returned %s\n",
- nt_errstr(status)));
- return status;
- }
-
- if (enc_ctx_num != cli->trans_enc_state->enc_ctx_num) {
- DEBUG(10, ("wrong enc_ctx %d, expected %d\n",
- enc_ctx_num,
- cli->trans_enc_state->enc_ctx_num));
- return NT_STATUS_INVALID_HANDLE;
- }
-
- status = common_decrypt_buffer(cli->trans_enc_state, pdu);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("common_decrypt_buffer returned %s\n",
- nt_errstr(status)));
- return status;
- }
+ if (pwct != NULL) {
+ *pwct = wct;
}
-
- mid = SVAL(pdu, smb_mid);
-
- for (req = cli->outstanding_requests; req; req = req->next) {
- if (req->mid == mid) {
- break;
- }
+ if (pvwv != NULL) {
+ *pvwv = (uint16_t *)(state->inbuf + wct_ofs + 1);
}
-
- if (!req) {
- /* oplock breaks are not signed */
- goto done;
+ if (pnum_bytes != NULL) {
+ *pnum_bytes = num_bytes;
}
-
- if (!cli_check_sign_mac(cli, pdu, req->seqnum+1)) {
- DEBUG(10, ("cli_check_sign_mac failed\n"));
- return NT_STATUS_ACCESS_DENIED;
+ if (pbytes != NULL) {
+ *pbytes = (uint8_t *)state->inbuf + bytes_offset + 2;
}
-done:
- *_req = req;
- *_mid = mid;
return NT_STATUS_OK;
}
-/**
- * A PDU has arrived on cli->evt_inbuf
- * @param[in] cli The cli_state that received something
- */
-
-static void handle_incoming_pdu(struct cli_state *cli)
+size_t cli_smb_wct_ofs(struct tevent_req **reqs, int num_reqs)
{
- struct cli_request *req, *next;
- uint16_t mid;
- size_t raw_pdu_len, buf_len, rest_len;
- char *pdu;
+ size_t wct_ofs;
int i;
- NTSTATUS status;
-
- int num_async;
- /*
- * The encrypted PDU len might differ from the unencrypted one
- */
- raw_pdu_len = smb_len(cli->evt_inbuf) + 4;
- buf_len = talloc_get_size(cli->evt_inbuf);
- rest_len = buf_len - raw_pdu_len;
+ wct_ofs = smb_wct - 4;
- if (buf_len == raw_pdu_len) {
- /*
- * Optimal case: Exactly one PDU was in the socket buffer
- */
- pdu = cli->evt_inbuf;
- cli->evt_inbuf = NULL;
+ for (i=0; i<num_reqs; i++) {
+ struct cli_smb_state *state;
+ state = tevent_req_data(reqs[i], struct cli_smb_state);
+ wct_ofs += iov_len(state->iov+1, state->iov_count-1);
+ wct_ofs = (wct_ofs + 3) & ~3;
}
- else {
- DEBUG(11, ("buf_len = %d, raw_pdu_len = %d, splitting "
- "buffer\n", (int)buf_len, (int)raw_pdu_len));
-
- if (raw_pdu_len < rest_len) {
- /*
- * The PDU is shorter, talloc_memdup that one.
- */
- pdu = (char *)talloc_memdup(
- cli, cli->evt_inbuf, raw_pdu_len);
-
- memmove(cli->evt_inbuf, cli->evt_inbuf + raw_pdu_len,
- buf_len - raw_pdu_len);
-
- cli->evt_inbuf = TALLOC_REALLOC_ARRAY(
- NULL, cli->evt_inbuf, char, rest_len);
-
- if (pdu == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto invalidate_requests;
- }
- }
- else {
- /*
- * The PDU is larger than the rest, talloc_memdup the
- * rest
- */
- pdu = cli->evt_inbuf;
-
- cli->evt_inbuf = (char *)talloc_memdup(
- cli, pdu + raw_pdu_len, rest_len);
+ return wct_ofs;
+}
- if (cli->evt_inbuf == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto invalidate_requests;
- }
- }
+bool cli_smb_chain_send(struct tevent_req **reqs, int num_reqs)
+{
+ struct cli_smb_state *first_state = tevent_req_data(
+ reqs[0], struct cli_smb_state);
+ struct cli_smb_state *last_state = tevent_req_data(
+ reqs[num_reqs-1], struct cli_smb_state);
+ struct cli_smb_state *state;
+ size_t wct_offset;
+ size_t chain_padding = 0;
+ int i, iovlen;
+ struct iovec *iov = NULL;
+ struct iovec *this_iov;
+
+ iovlen = 0;
+ for (i=0; i<num_reqs; i++) {
+ state = tevent_req_data(reqs[i], struct cli_smb_state);
+ iovlen += state->iov_count;
}
- status = validate_smb_crypto(cli, pdu, &req, &mid);
- if (!NT_STATUS_IS_OK(status)) {
- goto invalidate_requests;
+ iov = talloc_array(last_state, struct iovec, iovlen);
+ if (iov == NULL) {
+ goto fail;
}
- DEBUG(10, ("handle_incoming_pdu: got mid %d\n", mid));
-
- if (req == NULL) {
- DEBUG(3, ("Request for mid %d not found, dumping PDU\n", mid));
-
- TALLOC_FREE(pdu);
- return;
+ first_state->chained_requests = (struct tevent_req **)talloc_memdup(
+ last_state, reqs, sizeof(*reqs) * num_reqs);
+ if (first_state->chained_requests == NULL) {
+ goto fail;
}
- req->inbuf = talloc_move(req, &pdu);
+ wct_offset = smb_wct - 4;
+ this_iov = iov;
- /*
- * Freeing the last async_req will free the req (see
- * cli_async_req_destructor). So make a copy of req->num_async, we
- * can't reference it in the last round.
- */
+ for (i=0; i<num_reqs; i++) {
+ size_t next_padding = 0;
+ uint16_t *vwv;
- num_async = req->num_async;
+ state = tevent_req_data(reqs[i], struct cli_smb_state);
- for (i=0; i<num_async; i++) {
- /**
- * A request might have been talloc_free()'ed before we arrive
- * here. It will have removed itself from req->async via its
- * destructor cli_async_req_destructor().
- */
- if (req->async[i] != NULL) {
- if (req->recv_helper.fn != NULL) {
- req->recv_helper.fn(req->async[i]);
- } else {
- async_req_done(req->async[i]);
+ if (i < num_reqs-1) {
+ if (!is_andx_req(CVAL(state->header, smb_com))
+ || CVAL(state->header, smb_wct) < 2) {
+ goto fail;
}
}
- }
- return;
- invalidate_requests:
-
- DEBUG(10, ("handle_incoming_pdu: Aborting with %s\n",
- nt_errstr(status)));
-
- for (req = cli->outstanding_requests; req; req = next) {
- next = req->next;
- if (req->num_async) {
- async_req_nterror(req->async[0], status);
+ wct_offset += iov_len(state->iov+1, state->iov_count-1) + 1;
+ if ((wct_offset % 4) != 0) {
+ next_padding = 4 - (wct_offset % 4);
}
- }
- return;
-}
-
-/**
- * fd event callback. This is the basic connection to the socket
- * @param[in] event_ctx The event context that called us
- * @param[in] event The event that fired
- * @param[in] flags EVENT_FD_READ | EVENT_FD_WRITE
- * @param[in] p private_data, in this case the cli_state
- */
-
-static void cli_state_handler(struct event_context *event_ctx,
- struct fd_event *event, uint16 flags, void *p)
-{
- struct cli_state *cli = (struct cli_state *)p;
- struct cli_request *req, *next;
- NTSTATUS status;
-
- DEBUG(11, ("cli_state_handler called with flags %d\n", flags));
-
- if (flags & EVENT_FD_WRITE) {
- size_t to_send;
- ssize_t sent;
-
- for (req = cli->outstanding_requests; req; req = req->next) {
- to_send = smb_len(req->outbuf)+4;
- if (to_send > req->sent) {
- break;
- }
+ wct_offset += next_padding;
+ vwv = state->vwv;
+
+ if (i < num_reqs-1) {
+ struct cli_smb_state *next_state = tevent_req_data(
+ reqs[i+1], struct cli_smb_state);
+ SCVAL(vwv+0, 0, CVAL(next_state->header, smb_com));
+ SCVAL(vwv+0, 1, 0);
+ SSVAL(vwv+1, 0, wct_offset);
+ } else if (is_andx_req(CVAL(state->header, smb_com))) {
+ /* properly end the chain */
+ SCVAL(vwv+0, 0, 0xff);
+ SCVAL(vwv+0, 1, 0xff);
+ SSVAL(vwv+1, 0, 0);
}
- if (req == NULL) {
- if (cli->fd_event != NULL) {
- event_fd_set_not_writeable(cli->fd_event);
- }
- return;
- }
-
- sent = sys_send(cli->fd, req->outbuf + req->sent,
- to_send - req->sent, 0);
-
- if (sent < 0) {
- status = map_nt_error_from_unix(errno);
- goto sock_error;
- }
-
- req->sent += sent;
-
- if (req->sent == to_send) {
- return;
+ if (i == 0) {
+ this_iov[0] = state->iov[0];
+ } else {
+ /*
+ * This one is a bit subtle. We have to add
+ * chain_padding bytes between the requests, and we
+ * have to also include the wct field of the
+ * subsequent requests. We use the subsequent header
+ * for the padding, it contains the wct field in its
+ * last byte.
+ */
+ this_iov[0].iov_len = chain_padding+1;
+ this_iov[0].iov_base = &state->header[
+ sizeof(state->header) - this_iov[0].iov_len];
+ memset(this_iov[0].iov_base, 0, this_iov[0].iov_len-1);
}
+ memcpy(this_iov+1, state->iov+1,
+ sizeof(struct iovec) * (state->iov_count-1));
+ this_iov += state->iov_count;
+ chain_padding = next_padding;
}
- if (flags & EVENT_FD_READ) {
- int res, available;
- size_t old_size, new_size;
- char *tmp;
-
- res = ioctl(cli->fd, FIONREAD, &available);
- if (res == -1) {
- DEBUG(10, ("ioctl(FIONREAD) failed: %s\n",
- strerror(errno)));
- status = map_nt_error_from_unix(errno);
- goto sock_error;
- }
-
- if (available == 0) {
- /* EOF */
- status = NT_STATUS_END_OF_FILE;
- goto sock_error;
- }
-
- old_size = talloc_get_size(cli->evt_inbuf);
- new_size = old_size + available;
+ if (!cli_smb_req_iov_send(reqs[0], last_state, iov, iovlen)) {
+ goto fail;
+ }
+ return true;
+ fail:
+ TALLOC_FREE(iov);
+ return false;
+}
- if (new_size < old_size) {
- /* wrap */
- status = NT_STATUS_UNEXPECTED_IO_ERROR;
- goto sock_error;
- }
+uint8_t *cli_smb_inbuf(struct tevent_req *req)
+{
+ struct cli_smb_state *state = tevent_req_data(
+ req, struct cli_smb_state);
+ return state->inbuf;
+}
- tmp = TALLOC_REALLOC_ARRAY(cli, cli->evt_inbuf, char,
- new_size);
- if (tmp == NULL) {
- /* nomem */
- status = NT_STATUS_NO_MEMORY;
- goto sock_error;
- }
- cli->evt_inbuf = tmp;
+bool cli_has_async_calls(struct cli_state *cli)
+{
+ return ((tevent_queue_length(cli->outgoing) != 0)
+ || (talloc_array_length(cli->pending) != 0));
+}
- res = sys_recv(cli->fd, cli->evt_inbuf + old_size, available, 0);
- if (res == -1) {
- DEBUG(10, ("recv failed: %s\n", strerror(errno)));
- status = map_nt_error_from_unix(errno);
- goto sock_error;
- }
+struct cli_smb_oplock_break_waiter_state {
+ uint16_t fnum;
+ uint8_t level;
+};
- DEBUG(11, ("cli_state_handler: received %d bytes, "
- "smb_len(evt_inbuf) = %d\n", (int)res,
- smb_len(cli->evt_inbuf)));
+static void cli_smb_oplock_break_waiter_done(struct tevent_req *subreq);
- /* recv *might* have returned less than announced */
- new_size = old_size + res;
+struct tevent_req *cli_smb_oplock_break_waiter_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli)
+{
+ struct tevent_req *req, *subreq;
+ struct cli_smb_oplock_break_waiter_state *state;
+ struct cli_smb_state *smb_state;
- /* shrink, so I don't expect errors here */
- cli->evt_inbuf = TALLOC_REALLOC_ARRAY(cli, cli->evt_inbuf,
- char, new_size);
+ req = tevent_req_create(mem_ctx, &state,
+ struct cli_smb_oplock_break_waiter_state);
+ if (req == NULL) {
+ return NULL;
+ }
- while ((cli->evt_inbuf != NULL)
- && ((smb_len(cli->evt_inbuf) + 4) <= new_size)) {
- /*
- * we've got a complete NBT level PDU in evt_inbuf
- */
- handle_incoming_pdu(cli);
- new_size = talloc_get_size(cli->evt_inbuf);
- }
+ /*
+ * Create a fake SMB request that we will never send out. This is only
+ * used to be set into the pending queue with the right mid.
+ */
+ subreq = cli_smb_req_create(mem_ctx, ev, cli, 0, 0, 0, NULL, 0, NULL);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
}
+ smb_state = tevent_req_data(subreq, struct cli_smb_state);
+ SSVAL(smb_state->header, smb_mid, 0xffff);
- return;
+ if (!cli_smb_req_set_pending(subreq)) {
+ tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, cli_smb_oplock_break_waiter_done, req);
+ return req;
+}
- sock_error:
+static void cli_smb_oplock_break_waiter_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_smb_oplock_break_waiter_state *state = tevent_req_data(
+ req, struct cli_smb_oplock_break_waiter_state);
+ uint8_t wct;
+ uint16_t *vwv;
+ uint32_t num_bytes;
+ uint8_t *bytes;
+ NTSTATUS status;
- for (req = cli->outstanding_requests; req; req = next) {
- int i, num_async;
+ status = cli_smb_recv(subreq, 8, &wct, &vwv, &num_bytes, &bytes);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(subreq);
+ tevent_req_nterror(req, status);
+ return;
+ }
+ state->fnum = SVAL(vwv+2, 0);
+ state->level = CVAL(vwv+3, 1);
+ tevent_req_done(req);
+}
- next = req->next;
- num_async = req->num_async;
+NTSTATUS cli_smb_oplock_break_waiter_recv(struct tevent_req *req,
+ uint16_t *pfnum,
+ uint8_t *plevel)
+{
+ struct cli_smb_oplock_break_waiter_state *state = tevent_req_data(
+ req, struct cli_smb_oplock_break_waiter_state);
+ NTSTATUS status;
- for (i=0; i<num_async; i++) {
- async_req_nterror(req->async[i], status);
- }
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
}
- TALLOC_FREE(cli->fd_event);
- close(cli->fd);
- cli->fd = -1;
+ *pfnum = state->fnum;
+ *plevel = state->level;
+ return NT_STATUS_OK;
}
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index aa1ca595a7..53a812d222 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -165,14 +165,30 @@ static uint32 cli_session_setup_capabilities(struct cli_state *cli)
Do a NT1 guest session setup.
****************************************************************************/
-struct async_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli)
+struct cli_session_setup_guest_state {
+ struct cli_state *cli;
+ uint16_t vwv[16];
+};
+
+static void cli_session_setup_guest_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli)
{
- struct async_req *result;
- uint16_t vwv[13];
+ struct tevent_req *req, *subreq;
+ struct cli_session_setup_guest_state *state;
+ uint16_t *vwv;
uint8_t *bytes;
+ req = tevent_req_create(mem_ctx, &state,
+ struct cli_session_setup_guest_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->cli = cli;
+ vwv = state->vwv;
+
SCVAL(vwv+0, 0, 0xFF);
SCVAL(vwv+0, 1, 0);
SSVAL(vwv+1, 0, 0);
@@ -186,7 +202,7 @@ struct async_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
SSVAL(vwv+10, 0, 0);
SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
- bytes = talloc_array(talloc_tos(), uint8_t, 0);
+ bytes = talloc_array(state, uint8_t, 0);
bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
NULL);
@@ -195,68 +211,78 @@ struct async_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
- if (bytes == NULL) {
- return NULL;
+ if (tevent_req_nomem(bytes, req)) {
+ return tevent_req_post(req, ev);
}
- result = cli_request_send(mem_ctx, ev, cli, SMBsesssetupX, 0,
- 13, vwv, 0, talloc_get_size(bytes), bytes);
- TALLOC_FREE(bytes);
- return result;
+ subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
+ talloc_get_size(bytes), bytes);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
+ return req;
}
-NTSTATUS cli_session_setup_guest_recv(struct async_req *req)
+static void cli_session_setup_guest_done(struct tevent_req *subreq)
{
- struct cli_request *cli_req = talloc_get_type_abort(
- req->private_data, struct cli_request);
- struct cli_state *cli = cli_req->cli;
- uint8_t wct;
- uint16_t *vwv;
- uint16_t num_bytes;
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_session_setup_guest_state *state = tevent_req_data(
+ req, struct cli_session_setup_guest_state);
+ struct cli_state *cli = state->cli;
+ uint32_t num_bytes;
+ char *inbuf;
uint8_t *bytes;
uint8_t *p;
NTSTATUS status;
- if (async_req_is_nterror(req, &status)) {
- return status;
- }
-
- status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
+ status = cli_smb_recv(subreq, 0, NULL, NULL, &num_bytes, &bytes);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ TALLOC_FREE(subreq);
+ tevent_req_nterror(req, status);
+ return;
}
+ inbuf = (char *)cli_smb_inbuf(subreq);
p = bytes;
- cli->vuid = SVAL(cli_req->inbuf, smb_uid);
+ cli->vuid = SVAL(inbuf, smb_uid);
- p += clistr_pull(cli_req->inbuf, cli->server_os, (char *)p,
- sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE);
- p += clistr_pull(cli_req->inbuf, cli->server_type, (char *)p,
- sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE);
- p += clistr_pull(cli_req->inbuf, cli->server_domain, (char *)p,
- sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE);
+ p += clistr_pull(inbuf, cli->server_os, (char *)p, sizeof(fstring),
+ bytes+num_bytes-p, STR_TERMINATE);
+ p += clistr_pull(inbuf, cli->server_type, (char *)p, sizeof(fstring),
+ bytes+num_bytes-p, STR_TERMINATE);
+ p += clistr_pull(inbuf, cli->server_domain, (char *)p, sizeof(fstring),
+ bytes+num_bytes-p, STR_TERMINATE);
if (strstr(cli->server_type, "Samba")) {
cli->is_samba = True;
}
+ TALLOC_FREE(subreq);
+
status = cli_set_username(cli, "");
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ tevent_req_nterror(req, status);
+ return;
}
+ tevent_req_done(req);
+}
- return NT_STATUS_OK;
+NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
+{
+ return tevent_req_simple_recv_ntstatus(req);
}
static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
{
TALLOC_CTX *frame = talloc_stackframe();
struct event_context *ev;
- struct async_req *req;
- NTSTATUS status;
+ struct tevent_req *req;
+ NTSTATUS status = NT_STATUS_OK;
- if (cli->fd_event != NULL) {
+ if (cli_has_async_calls(cli)) {
/*
* Can't use sync call while an async call is in flight
*/
@@ -276,13 +302,17 @@ static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
goto fail;
}
- while (req->state < ASYNC_REQ_DONE) {
- event_loop_once(ev);
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
}
status = cli_session_setup_guest_recv(req);
fail:
TALLOC_FREE(frame);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_set_error(cli, status);
+ }
return status;
}
@@ -1189,18 +1219,33 @@ bool cli_ulogoff(struct cli_state *cli)
Send a tconX.
****************************************************************************/
-struct async_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli,
- const char *share, const char *dev,
- const char *pass, int passlen)
+struct cli_tcon_andx_state {
+ struct cli_state *cli;
+ uint16_t vwv[4];
+};
+
+static void cli_tcon_andx_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
+ const char *share, const char *dev,
+ const char *pass, int passlen)
{
+ struct tevent_req *req, *subreq;
+ struct cli_tcon_andx_state *state;
fstring pword;
+ uint16_t *vwv;
char *tmp = NULL;
- struct async_req *result;
- uint16_t vwv[4];
uint8_t *bytes;
+ req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->cli = cli;
+ vwv = state->vwv;
+
fstrcpy(cli->share, share);
/* in user level security don't send a password now */
@@ -1263,9 +1308,9 @@ struct async_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
SSVAL(vwv+3, 0, passlen);
if (passlen) {
- bytes = (uint8_t *)talloc_memdup(talloc_tos(), pword, passlen);
+ bytes = (uint8_t *)talloc_memdup(state, pword, passlen);
} else {
- bytes = talloc_array(talloc_tos(), uint8_t, 0);
+ bytes = talloc_array(state, uint8_t, 0);
}
/*
@@ -1273,9 +1318,8 @@ struct async_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
*/
tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
cli->desthost, share);
- if (tmp == NULL) {
- TALLOC_FREE(bytes);
- return NULL;
+ if (tevent_req_nomem(tmp, req)) {
+ return tevent_req_post(req, ev);
}
bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
NULL);
@@ -1285,60 +1329,52 @@ struct async_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
* Add the devicetype
*/
tmp = talloc_strdup_upper(talloc_tos(), dev);
- if (tmp == NULL) {
- TALLOC_FREE(bytes);
- return NULL;
+ if (tevent_req_nomem(tmp, req)) {
+ return tevent_req_post(req, ev);
}
bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
TALLOC_FREE(tmp);
- if (bytes == NULL) {
- return NULL;
+ if (tevent_req_nomem(bytes, req)) {
+ return tevent_req_post(req, ev);
}
- result = cli_request_send(mem_ctx, ev, cli, SMBtconX, 0,
- 4, vwv, 0, talloc_get_size(bytes), bytes);
- TALLOC_FREE(bytes);
- return result;
+ subreq = cli_smb_send(state, ev, cli, SMBtconX, 0, 4, vwv,
+ talloc_get_size(bytes), bytes);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
+ return req;
access_denied:
- {
- struct cli_request *state;
- if (!async_req_setup(mem_ctx, &result, &state,
- struct cli_request)) {
- goto fail;
- }
- if (async_post_ntstatus(result, ev, NT_STATUS_ACCESS_DENIED)) {
- return result;
- }
- }
- fail:
- TALLOC_FREE(result);
- return NULL;
+ tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
+ return tevent_req_post(req, ev);
}
-NTSTATUS cli_tcon_andx_recv(struct async_req *req)
+static void cli_tcon_andx_done(struct tevent_req *subreq)
{
- struct cli_request *cli_req = talloc_get_type_abort(
- req->private_data, struct cli_request);
- struct cli_state *cli = cli_req->cli;
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_tcon_andx_state *state = tevent_req_data(
+ req, struct cli_tcon_andx_state);
+ struct cli_state *cli = state->cli;
+ char *inbuf = (char *)cli_smb_inbuf(subreq);
uint8_t wct;
uint16_t *vwv;
- uint16_t num_bytes;
+ uint32_t num_bytes;
uint8_t *bytes;
NTSTATUS status;
- if (async_req_is_nterror(req, &status)) {
- return status;
- }
-
- status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
+ status = cli_smb_recv(subreq, 0, &wct, &vwv, &num_bytes, &bytes);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ TALLOC_FREE(subreq);
+ tevent_req_nterror(req, status);
+ return;
}
- clistr_pull(cli_req->inbuf, cli->dev, bytes, sizeof(fstring),
- num_bytes, STR_TERMINATE|STR_ASCII);
+ clistr_pull(inbuf, cli->dev, bytes, sizeof(fstring), num_bytes,
+ STR_TERMINATE|STR_ASCII);
if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
/* almost certainly win95 - enable bug fixes */
@@ -1356,8 +1392,13 @@ NTSTATUS cli_tcon_andx_recv(struct async_req *req)
cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
}
- cli->cnum = SVAL(cli_req->inbuf,smb_tid);
- return NT_STATUS_OK;
+ cli->cnum = SVAL(inbuf,smb_tid);
+ tevent_req_done(req);
+}
+
+NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
+{
+ return tevent_req_simple_recv_ntstatus(req);
}
NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
@@ -1365,10 +1406,10 @@ NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
{
TALLOC_CTX *frame = talloc_stackframe();
struct event_context *ev;
- struct async_req *req;
- NTSTATUS status;
+ struct tevent_req *req;
+ NTSTATUS status = NT_STATUS_OK;
- if (cli->fd_event != NULL) {
+ if (cli_has_async_calls(cli)) {
/*
* Can't use sync call while an async call is in flight
*/
@@ -1388,13 +1429,17 @@ NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
goto fail;
}
- while (req->state < ASYNC_REQ_DONE) {
- event_loop_once(ev);
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
}
status = cli_tcon_andx_recv(req);
fail:
TALLOC_FREE(frame);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_set_error(cli, status);
+ }
return status;
}
@@ -1461,14 +1506,27 @@ void cli_negprot_sendsync(struct cli_state *cli)
Send a negprot command.
****************************************************************************/
-struct async_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli)
+struct cli_negprot_state {
+ struct cli_state *cli;
+};
+
+static void cli_negprot_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli)
{
- struct async_req *result;
+ struct tevent_req *req, *subreq;
+ struct cli_negprot_state *state;
uint8_t *bytes = NULL;
int numprots;
+ req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->cli = cli;
+
if (cli->protocol < PROTOCOL_NT1)
cli->use_spnego = False;
@@ -1479,51 +1537,54 @@ struct async_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
break;
}
bytes = (uint8_t *)talloc_append_blob(
- talloc_tos(), bytes, data_blob_const(&c, sizeof(c)));
- if (bytes == NULL) {
- return NULL;
+ state, bytes, data_blob_const(&c, sizeof(c)));
+ if (tevent_req_nomem(bytes, req)) {
+ return tevent_req_post(req, ev);
}
bytes = smb_bytes_push_str(bytes, false,
prots[numprots].name,
strlen(prots[numprots].name)+1,
NULL);
- if (bytes == NULL) {
- return NULL;
+ if (tevent_req_nomem(bytes, req)) {
+ return tevent_req_post(req, ev);
}
}
- result = cli_request_send(mem_ctx, ev, cli, SMBnegprot, 0, 0, NULL, 0,
- talloc_get_size(bytes), bytes);
- TALLOC_FREE(bytes);
- return result;
+ subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
+ talloc_get_size(bytes), bytes);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, cli_negprot_done, req);
+ return req;
}
-NTSTATUS cli_negprot_recv(struct async_req *req)
+static void cli_negprot_done(struct tevent_req *subreq)
{
- struct cli_request *cli_req = talloc_get_type_abort(
- req->private_data, struct cli_request);
- struct cli_state *cli = cli_req->cli;
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_negprot_state *state = tevent_req_data(
+ req, struct cli_negprot_state);
+ struct cli_state *cli = state->cli;
uint8_t wct;
uint16_t *vwv;
- uint16_t num_bytes;
+ uint32_t num_bytes;
uint8_t *bytes;
NTSTATUS status;
uint16_t protnum;
- if (async_req_is_nterror(req, &status)) {
- return status;
- }
-
- status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
+ status = cli_smb_recv(subreq, 1, &wct, &vwv, &num_bytes, &bytes);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ TALLOC_FREE(subreq);
+ return;
}
protnum = SVAL(vwv, 0);
if ((protnum >= ARRAY_SIZE(prots))
- || (prots[protnum].prot > cli_req->cli->protocol)) {
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ || (prots[protnum].prot > cli->protocol)) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+ return;
}
cli->protocol = prots[protnum].prot;
@@ -1531,7 +1592,8 @@ NTSTATUS cli_negprot_recv(struct async_req *req)
if ((cli->protocol < PROTOCOL_NT1) &&
client_is_signing_mandatory(cli)) {
DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
- return NT_STATUS_ACCESS_DENIED;
+ tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
+ return;
}
if (cli->protocol >= PROTOCOL_NT1) {
@@ -1572,14 +1634,18 @@ NTSTATUS cli_negprot_recv(struct async_req *req)
/* Fail if server says signing is mandatory and we don't want to support it. */
if (!client_is_signing_allowed(cli)) {
DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
- return NT_STATUS_ACCESS_DENIED;
+ tevent_req_nterror(req,
+ NT_STATUS_ACCESS_DENIED);
+ return;
}
negotiated_smb_signing = true;
} else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
/* Fail if client says signing is mandatory and the server doesn't support it. */
if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
- return NT_STATUS_ACCESS_DENIED;
+ tevent_req_nterror(req,
+ NT_STATUS_ACCESS_DENIED);
+ return;
}
negotiated_smb_signing = true;
} else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
@@ -1625,41 +1691,52 @@ NTSTATUS cli_negprot_recv(struct async_req *req)
if (getenv("CLI_FORCE_ASCII"))
cli->capabilities &= ~CAP_UNICODE;
- return NT_STATUS_OK;
+ tevent_req_done(req);
+}
+
+NTSTATUS cli_negprot_recv(struct tevent_req *req)
+{
+ return tevent_req_simple_recv_ntstatus(req);
}
NTSTATUS cli_negprot(struct cli_state *cli)
{
TALLOC_CTX *frame = talloc_stackframe();
struct event_context *ev;
- struct async_req *req;
- NTSTATUS status = NT_STATUS_NO_MEMORY;
+ struct tevent_req *req;
+ NTSTATUS status = NT_STATUS_OK;
- if (cli->fd_event != NULL) {
+ if (cli_has_async_calls(cli)) {
/*
* Can't use sync call while an async call is in flight
*/
- cli_set_error(cli, NT_STATUS_INVALID_PARAMETER);
+ status = NT_STATUS_INVALID_PARAMETER;
goto fail;
}
ev = event_context_init(frame);
if (ev == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
req = cli_negprot_send(frame, ev, cli);
if (req == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
- while (req->state < ASYNC_REQ_DONE) {
- event_loop_once(ev);
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
}
status = cli_negprot_recv(req);
fail:
TALLOC_FREE(frame);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_set_error(cli, status);
+ }
return status;
}
@@ -2092,6 +2169,10 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
return nt_status;
}
+ cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
+ cli->use_level_II_oplocks =
+ ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
+
nt_status = cli_session_setup(cli, user, password, pw_len, password,
pw_len, domain);
if (!NT_STATUS_IS_OK(nt_status)) {
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index 6186387076..45addc2163 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -650,6 +650,12 @@ struct cli_state *cli_initialise_ex(int signing_state)
goto error;
}
+ cli->outgoing = tevent_queue_create(cli, "cli_outgoing");
+ if (cli->outgoing == NULL) {
+ goto error;
+ }
+ cli->pending = NULL;
+
cli->initialised = 1;
return cli;
@@ -740,6 +746,12 @@ void cli_shutdown(struct cli_state *cli)
cli->fd = -1;
cli->smb_rw_error = SMB_READ_OK;
+ /*
+ * Need to free pending first, they remove themselves
+ */
+ while (cli->pending) {
+ talloc_free(cli->pending[0]);
+ }
TALLOC_FREE(cli);
}
@@ -793,90 +805,72 @@ bool cli_send_keepalive(struct cli_state *cli)
return true;
}
-/**
- * @brief: Collect a echo reply
- * @param[in] req The corresponding async request
- *
- * There might be more than one echo reply. This helper pulls the reply out of
- * the data stream. If all expected replies have arrived, declare the
- * async_req done.
- */
-
-static void cli_echo_recv_helper(struct async_req *req)
-{
- struct cli_request *cli_req;
- uint8_t wct;
- uint16_t *vwv;
- uint16_t num_bytes;
- uint8_t *bytes;
- NTSTATUS status;
+struct cli_echo_state {
+ uint16_t vwv[1];
+ DATA_BLOB data;
+ int num_echos;
+};
- status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
- if (!NT_STATUS_IS_OK(status)) {
- async_req_nterror(req, status);
- return;
- }
+static void cli_echo_done(struct tevent_req *subreq);
- cli_req = talloc_get_type_abort(req->private_data, struct cli_request);
+struct tevent_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+ struct cli_state *cli, uint16_t num_echos,
+ DATA_BLOB data)
+{
+ struct tevent_req *req, *subreq;
+ struct cli_echo_state *state;
- if ((num_bytes != cli_req->data.echo.data.length)
- || (memcmp(cli_req->data.echo.data.data, bytes,
- num_bytes) != 0)) {
- async_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
- return;
+ req = tevent_req_create(mem_ctx, &state, struct cli_echo_state);
+ if (req == NULL) {
+ return NULL;
}
+ SSVAL(state->vwv, 0, num_echos);
+ state->data = data;
+ state->num_echos = num_echos;
- cli_req->data.echo.num_echos -= 1;
-
- if (cli_req->data.echo.num_echos == 0) {
- async_req_done(req);
- return;
+ subreq = cli_smb_send(state, ev, cli, SMBecho, 0, 1, state->vwv,
+ data.length, data.data);
+ if (subreq == NULL) {
+ goto fail;
}
-
- return;
+ tevent_req_set_callback(subreq, cli_echo_done, req);
+ return req;
+ fail:
+ TALLOC_FREE(req);
+ return NULL;
}
-/**
- * @brief Send SMBEcho requests
- * @param[in] mem_ctx The memory context to put the async_req on
- * @param[in] ev The event context that will call us back
- * @param[in] cli The connection to send the echo to
- * @param[in] num_echos How many times do we want to get the reply?
- * @param[in] data The data we want to get back
- * @retval The async request
- */
-
-struct async_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
- struct cli_state *cli, uint16_t num_echos,
- DATA_BLOB data)
+static void cli_echo_done(struct tevent_req *subreq)
{
- uint16_t vwv[1];
- uint8_t *data_copy;
- struct async_req *result;
- struct cli_request *req;
-
- SSVAL(vwv, 0, num_echos);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_echo_state *state = tevent_req_data(
+ req, struct cli_echo_state);
+ NTSTATUS status;
+ uint32_t num_bytes;
+ uint8_t *bytes;
- data_copy = (uint8_t *)talloc_memdup(mem_ctx, data.data, data.length);
- if (data_copy == NULL) {
- return NULL;
+ status = cli_smb_recv(subreq, 0, NULL, NULL, &num_bytes, &bytes);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
}
-
- result = cli_request_send(mem_ctx, ev, cli, SMBecho, 0, 1, vwv, 0,
- data.length, data.data);
- if (result == NULL) {
- TALLOC_FREE(data_copy);
- return NULL;
+ if ((num_bytes != state->data.length)
+ || (memcmp(bytes, state->data.data, num_bytes) != 0)) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+ return;
}
- req = talloc_get_type_abort(result->private_data, struct cli_request);
- req->data.echo.num_echos = num_echos;
- req->data.echo.data.data = talloc_move(req, &data_copy);
- req->data.echo.data.length = data.length;
-
- req->recv_helper.fn = cli_echo_recv_helper;
+ state->num_echos -=1;
+ if (state->num_echos == 0) {
+ tevent_req_done(req);
+ return;
+ }
- return result;
+ if (!cli_smb_req_set_pending(subreq)) {
+ tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
+ }
}
/**
@@ -885,9 +879,9 @@ struct async_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
* @retval Did the server reply correctly?
*/
-NTSTATUS cli_echo_recv(struct async_req *req)
+NTSTATUS cli_echo_recv(struct tevent_req *req)
{
- return async_req_simple_recv_ntstatus(req);
+ return tevent_req_simple_recv_ntstatus(req);
}
/**
@@ -904,35 +898,40 @@ NTSTATUS cli_echo(struct cli_state *cli, uint16_t num_echos, DATA_BLOB data)
{
TALLOC_CTX *frame = talloc_stackframe();
struct event_context *ev;
- struct async_req *req;
- NTSTATUS status = NT_STATUS_NO_MEMORY;
+ struct tevent_req *req;
+ NTSTATUS status = NT_STATUS_OK;
- if (cli->fd_event != NULL) {
+ if (cli_has_async_calls(cli)) {
/*
* Can't use sync call while an async call is in flight
*/
- cli_set_error(cli, NT_STATUS_INVALID_PARAMETER);
+ status = NT_STATUS_INVALID_PARAMETER;
goto fail;
}
ev = event_context_init(frame);
if (ev == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
req = cli_echo_send(frame, ev, cli, num_echos, data);
if (req == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
- while (req->state < ASYNC_REQ_DONE) {
- event_loop_once(ev);
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
}
status = cli_echo_recv(req);
-
fail:
TALLOC_FREE(frame);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_set_error(cli, status);
+ }
return status;
}
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index 0703f04c5f..4293828214 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -771,22 +771,36 @@ int cli_nt_create_full(struct cli_state *cli, const char *fname,
return SVAL(cli->inbuf,smb_vwv2 + 1);
}
-struct async_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli,
- const char *fname,
- uint32_t CreatFlags,
- uint32_t DesiredAccess,
- uint32_t FileAttributes,
- uint32_t ShareAccess,
- uint32_t CreateDisposition,
- uint32_t CreateOptions,
- uint8_t SecurityFlags)
-{
- struct async_req *result;
+struct cli_ntcreate_state {
+ uint16_t vwv[24];
+ uint16_t fnum;
+};
+
+static void cli_ntcreate_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
+ const char *fname,
+ uint32_t CreatFlags,
+ uint32_t DesiredAccess,
+ uint32_t FileAttributes,
+ uint32_t ShareAccess,
+ uint32_t CreateDisposition,
+ uint32_t CreateOptions,
+ uint8_t SecurityFlags)
+{
+ struct tevent_req *req, *subreq;
+ struct cli_ntcreate_state *state;
+ uint16_t *vwv;
uint8_t *bytes;
size_t converted_len;
- uint16_t vwv[24];
+
+ req = tevent_req_create(mem_ctx, &state, struct cli_ntcreate_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ vwv = state->vwv;
SCVAL(vwv+0, 0, 0xFF);
SCVAL(vwv+0, 1, 0);
@@ -808,7 +822,7 @@ struct async_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx,
SIVAL(vwv+21, 1, 0x02); /* ImpersonationLevel */
SCVAL(vwv+23, 1, SecurityFlags);
- bytes = talloc_array(talloc_tos(), uint8_t, 0);
+ bytes = talloc_array(state, uint8_t, 0);
bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
fname, strlen(fname)+1,
&converted_len);
@@ -816,41 +830,53 @@ struct async_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx,
/* sigh. this copes with broken netapp filer behaviour */
bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, NULL);
- if (bytes == NULL) {
- return NULL;
+ if (tevent_req_nomem(bytes, req)) {
+ return tevent_req_post(req, ev);
}
SIVAL(vwv+2, 1, converted_len);
- result = cli_request_send(mem_ctx, ev, cli, SMBntcreateX, 0,
- 24, vwv, 0, talloc_get_size(bytes), bytes);
- TALLOC_FREE(bytes);
- return result;
+ subreq = cli_smb_send(state, ev, cli, SMBntcreateX, 0, 24, vwv,
+ talloc_get_size(bytes), bytes);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, cli_ntcreate_done, req);
+ return req;
}
-NTSTATUS cli_ntcreate_recv(struct async_req *req, uint16_t *pfnum)
+static void cli_ntcreate_done(struct tevent_req *subreq)
{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_ntcreate_state *state = tevent_req_data(
+ req, struct cli_ntcreate_state);
uint8_t wct;
uint16_t *vwv;
- uint16_t num_bytes;
+ uint32_t num_bytes;
uint8_t *bytes;
NTSTATUS status;
- if (async_req_is_nterror(req, &status)) {
- return status;
- }
-
- status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
+ status = cli_smb_recv(subreq, 3, &wct, &vwv, &num_bytes, &bytes);
if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- if (wct < 3) {
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ TALLOC_FREE(subreq);
+ tevent_req_nterror(req, status);
+ return;
}
+ state->fnum = SVAL(vwv+2, 1);
+ tevent_req_done(req);
+}
- *pfnum = SVAL(vwv+2, 1);
+NTSTATUS cli_ntcreate_recv(struct tevent_req *req, uint16_t *pfnum)
+{
+ struct cli_ntcreate_state *state = tevent_req_data(
+ req, struct cli_ntcreate_state);
+ NTSTATUS status;
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+ *pfnum = state->fnum;
return NT_STATUS_OK;
}
@@ -867,10 +893,10 @@ NTSTATUS cli_ntcreate(struct cli_state *cli,
{
TALLOC_CTX *frame = talloc_stackframe();
struct event_context *ev;
- struct async_req *req;
- NTSTATUS status;
+ struct tevent_req *req;
+ NTSTATUS status = NT_STATUS_OK;
- if (cli->fd_event != NULL) {
+ if (cli_has_async_calls(cli)) {
/*
* Can't use sync call while an async call is in flight
*/
@@ -893,13 +919,17 @@ NTSTATUS cli_ntcreate(struct cli_state *cli,
goto fail;
}
- while (req->state < ASYNC_REQ_DONE) {
- event_loop_once(ev);
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
}
status = cli_ntcreate_recv(req, pfid);
fail:
TALLOC_FREE(frame);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_set_error(cli, status);
+ }
return status;
}
@@ -968,17 +998,33 @@ uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2,
WARNING: if you open with O_WRONLY then getattrE won't work!
****************************************************************************/
-struct async_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
- struct cli_state *cli,
- const char *fname, int flags, int share_mode)
+struct cli_open_state {
+ uint16_t vwv[15];
+ int fnum;
+ struct iovec bytes;
+};
+
+static void cli_open_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_open_create(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli, const char *fname,
+ int flags, int share_mode,
+ struct tevent_req **psmbreq)
{
- unsigned openfn = 0;
- unsigned accessmode = 0;
- uint8_t additional_flags = 0;
+ struct tevent_req *req, *subreq;
+ struct cli_open_state *state;
+ unsigned openfn;
+ unsigned accessmode;
+ uint8_t additional_flags;
uint8_t *bytes;
- uint16_t vwv[15];
- struct async_req *result;
+ req = tevent_req_create(mem_ctx, &state, struct cli_open_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ openfn = 0;
if (flags & O_CREAT) {
openfn |= (1<<4);
}
@@ -1007,63 +1053,96 @@ struct async_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
accessmode = 0xFF;
}
- SCVAL(vwv + 0, 0, 0xFF);
- SCVAL(vwv + 0, 1, 0);
- SSVAL(vwv + 1, 0, 0);
- SSVAL(vwv + 2, 0, 0); /* no additional info */
- SSVAL(vwv + 3, 0, accessmode);
- SSVAL(vwv + 4, 0, aSYSTEM | aHIDDEN);
- SSVAL(vwv + 5, 0, 0);
- SIVAL(vwv + 6, 0, 0);
- SSVAL(vwv + 8, 0, openfn);
- SIVAL(vwv + 9, 0, 0);
- SIVAL(vwv + 11, 0, 0);
- SIVAL(vwv + 13, 0, 0);
+ SCVAL(state->vwv + 0, 0, 0xFF);
+ SCVAL(state->vwv + 0, 1, 0);
+ SSVAL(state->vwv + 1, 0, 0);
+ SSVAL(state->vwv + 2, 0, 0); /* no additional info */
+ SSVAL(state->vwv + 3, 0, accessmode);
+ SSVAL(state->vwv + 4, 0, aSYSTEM | aHIDDEN);
+ SSVAL(state->vwv + 5, 0, 0);
+ SIVAL(state->vwv + 6, 0, 0);
+ SSVAL(state->vwv + 8, 0, openfn);
+ SIVAL(state->vwv + 9, 0, 0);
+ SIVAL(state->vwv + 11, 0, 0);
+ SIVAL(state->vwv + 13, 0, 0);
+
+ additional_flags = 0;
if (cli->use_oplocks) {
/* if using oplocks then ask for a batch oplock via
core and extended methods */
additional_flags =
FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK;
- SSVAL(vwv+2, 0, SVAL(vwv+2, 0) | 6);
+ SSVAL(state->vwv+2, 0, SVAL(state->vwv+2, 0) | 6);
}
- bytes = talloc_array(talloc_tos(), uint8_t, 0);
+ bytes = talloc_array(state, uint8_t, 0);
bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname,
strlen(fname)+1, NULL);
- if (bytes == NULL) {
+
+ if (tevent_req_nomem(bytes, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ state->bytes.iov_base = bytes;
+ state->bytes.iov_len = talloc_get_size(bytes);
+
+ subreq = cli_smb_req_create(state, ev, cli, SMBopenX, additional_flags,
+ 15, state->vwv, 1, &state->bytes);
+ if (subreq == NULL) {
+ TALLOC_FREE(req);
return NULL;
}
+ tevent_req_set_callback(subreq, cli_open_done, req);
+ *psmbreq = subreq;
+ return req;
+}
- result = cli_request_send(mem_ctx, ev, cli, SMBopenX, additional_flags,
- 15, vwv, 0, talloc_get_size(bytes), bytes);
- TALLOC_FREE(bytes);
- return result;
+struct tevent_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+ struct cli_state *cli, const char *fname,
+ int flags, int share_mode)
+{
+ struct tevent_req *req, *subreq;
+
+ req = cli_open_create(mem_ctx, ev, cli, fname, flags, share_mode,
+ &subreq);
+ if ((req == NULL) || !cli_smb_req_send(subreq)) {
+ TALLOC_FREE(req);
+ return NULL;
+ }
+ return req;
}
-NTSTATUS cli_open_recv(struct async_req *req, int *fnum)
+static void cli_open_done(struct tevent_req *subreq)
{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_open_state *state = tevent_req_data(
+ req, struct cli_open_state);
uint8_t wct;
uint16_t *vwv;
- uint16_t num_bytes;
- uint8_t *bytes;
NTSTATUS status;
- if (async_req_is_nterror(req, &status)) {
- return status;
- }
-
- status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
+ status = cli_smb_recv(subreq, 3, &wct, &vwv, NULL, NULL);
if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- if (wct < 3) {
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ TALLOC_FREE(subreq);
+ tevent_req_nterror(req, status);
+ return;
}
+ state->fnum = SVAL(vwv+2, 0);
+ tevent_req_done(req);
+}
- *fnum = SVAL(vwv+2, 0);
+NTSTATUS cli_open_recv(struct tevent_req *req, int *fnum)
+{
+ struct cli_open_state *state = tevent_req_data(
+ req, struct cli_open_state);
+ NTSTATUS status;
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+ *fnum = state->fnum;
return NT_STATUS_OK;
}
@@ -1072,34 +1151,41 @@ int cli_open(struct cli_state *cli, const char *fname, int flags,
{
TALLOC_CTX *frame = talloc_stackframe();
struct event_context *ev;
- struct async_req *req;
+ struct tevent_req *req;
+ NTSTATUS status = NT_STATUS_OK;
int result = -1;
- if (cli->fd_event != NULL) {
+ if (cli_has_async_calls(cli)) {
/*
* Can't use sync call while an async call is in flight
*/
- cli_set_error(cli, NT_STATUS_INVALID_PARAMETER);
+ status = NT_STATUS_INVALID_PARAMETER;
goto fail;
}
ev = event_context_init(frame);
if (ev == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
req = cli_open_send(frame, ev, cli, fname, flags, share_mode);
if (req == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
- while (req->state < ASYNC_REQ_DONE) {
- event_loop_once(ev);
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
}
cli_open_recv(req, &result);
fail:
TALLOC_FREE(frame);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_set_error(cli, status);
+ }
return result;
}
@@ -1107,65 +1193,111 @@ int cli_open(struct cli_state *cli, const char *fname, int flags,
Close a file.
****************************************************************************/
-struct async_req *cli_close_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
- struct cli_state *cli, int fnum)
-{
+struct cli_close_state {
uint16_t vwv[3];
+};
+
+static void cli_close_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_close_create(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli, int fnum,
+ struct tevent_req **psubreq)
+{
+ struct tevent_req *req, *subreq;
+ struct cli_close_state *state;
+
+ req = tevent_req_create(mem_ctx, &state, struct cli_close_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ SSVAL(state->vwv+0, 0, fnum);
+ SIVALS(state->vwv+1, 0, -1);
+
+ subreq = cli_smb_req_create(state, ev, cli, SMBclose, 0, 3, state->vwv,
+ 0, NULL);
+ if (subreq == NULL) {
+ TALLOC_FREE(req);
+ return NULL;
+ }
+ tevent_req_set_callback(subreq, cli_close_done, req);
+ *psubreq = subreq;
+ return req;
+}
- SSVAL(vwv+0, 0, fnum);
- SIVALS(vwv+1, 0, -1);
+struct tevent_req *cli_close_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli, int fnum)
+{
+ struct tevent_req *req, *subreq;
- return cli_request_send(mem_ctx, ev, cli, SMBclose, 0, 3, vwv, 0,
- 0, NULL);
+ req = cli_close_create(mem_ctx, ev, cli, fnum, &subreq);
+ if ((req == NULL) || !cli_smb_req_send(subreq)) {
+ TALLOC_FREE(req);
+ return NULL;
+ }
+ return req;
}
-NTSTATUS cli_close_recv(struct async_req *req)
+static void cli_close_done(struct tevent_req *subreq)
{
- uint8_t wct;
- uint16_t *vwv;
- uint16_t num_bytes;
- uint8_t *bytes;
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
NTSTATUS status;
- if (async_req_is_nterror(req, &status)) {
- return status;
+ status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
}
+ tevent_req_done(req);
+}
- return cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
+NTSTATUS cli_close_recv(struct tevent_req *req)
+{
+ return tevent_req_simple_recv_ntstatus(req);
}
bool cli_close(struct cli_state *cli, int fnum)
{
TALLOC_CTX *frame = talloc_stackframe();
struct event_context *ev;
- struct async_req *req;
+ struct tevent_req *req;
+ NTSTATUS status = NT_STATUS_OK;
bool result = false;
- if (cli->fd_event != NULL) {
+ if (cli_has_async_calls(cli)) {
/*
* Can't use sync call while an async call is in flight
*/
- cli_set_error(cli, NT_STATUS_INVALID_PARAMETER);
+ status = NT_STATUS_INVALID_PARAMETER;
goto fail;
}
ev = event_context_init(frame);
if (ev == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
req = cli_close_send(frame, ev, cli, fnum);
if (req == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
- while (req->state < ASYNC_REQ_DONE) {
- event_loop_once(ev);
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
}
result = NT_STATUS_IS_OK(cli_close_recv(req));
fail:
TALLOC_FREE(frame);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_set_error(cli, status);
+ }
return result;
}
diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c
index 4ab31374e2..aa98d7668f 100644
--- a/source3/libsmb/clikrb5.c
+++ b/source3/libsmb/clikrb5.c
@@ -56,12 +56,12 @@ static krb5_error_code ads_krb5_get_fwd_ticket( krb5_context context,
char *utf8_name;
size_t converted_size;
- if (!push_utf8_allocate(&utf8_name, name, &converted_size)) {
+ if (!push_utf8_talloc(talloc_tos(), &utf8_name, name, &converted_size)) {
return ENOMEM;
}
ret = krb5_parse_name(context, utf8_name, principal);
- SAFE_FREE(utf8_name);
+ TALLOC_FREE(utf8_name);
return ret;
}
@@ -79,24 +79,25 @@ static krb5_error_code smb_krb5_parse_name_norealm_conv(krb5_context context,
size_t converted_size;
*principal = NULL;
- if (!push_utf8_allocate(&utf8_name, name, &converted_size)) {
+ if (!push_utf8_talloc(talloc_tos(), &utf8_name, name, &converted_size)) {
return ENOMEM;
}
ret = krb5_parse_name_norealm(context, utf8_name, principal);
- SAFE_FREE(utf8_name);
+ TALLOC_FREE(utf8_name);
return ret;
}
#endif
/**************************************************************
krb5_parse_name that returns a UNIX charset name. Must
- be freed with normal free() call.
+ be freed with talloc_free() call.
**************************************************************/
- krb5_error_code smb_krb5_unparse_name(krb5_context context,
- krb5_const_principal principal,
- char **unix_name)
+krb5_error_code smb_krb5_unparse_name(TALLOC_CTX *mem_ctx,
+ krb5_context context,
+ krb5_const_principal principal,
+ char **unix_name)
{
krb5_error_code ret;
char *utf8_name;
@@ -108,7 +109,7 @@ static krb5_error_code smb_krb5_parse_name_norealm_conv(krb5_context context,
return ret;
}
- if (!pull_utf8_allocate(unix_name, utf8_name, &converted_size)) {
+ if (!pull_utf8_talloc(mem_ctx, unix_name, utf8_name, &converted_size)) {
krb5_free_unparsed_name(context, utf8_name);
return ENOMEM;
}
@@ -1081,10 +1082,10 @@ get_key_from_keytab(krb5_context context,
}
if ( DEBUGLEVEL >= 10 ) {
- if (smb_krb5_unparse_name(context, server, &name) == 0) {
+ if (smb_krb5_unparse_name(talloc_tos(), context, server, &name) == 0) {
DEBUG(10,("get_key_from_keytab: will look for kvno %d, enctype %d and name: %s\n",
kvno, enctype, name));
- SAFE_FREE(name);
+ TALLOC_FREE(name);
}
}
diff --git a/source3/libsmb/clioplock.c b/source3/libsmb/clioplock.c
index ef8b396461..e3fb66aba0 100644
--- a/source3/libsmb/clioplock.c
+++ b/source3/libsmb/clioplock.c
@@ -23,38 +23,103 @@
send an ack for an oplock break request
****************************************************************************/
-bool cli_oplock_ack(struct cli_state *cli, int fnum, unsigned char level)
+struct cli_oplock_ack_state {
+ uint16_t vwv[8];
+};
+
+static void cli_oplock_ack_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_oplock_ack_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli,
+ uint16_t fnum, uint8_t level)
+{
+ struct tevent_req *req, *subreq;
+ struct cli_oplock_ack_state *state;
+
+ req = tevent_req_create(mem_ctx, &state, struct cli_oplock_ack_state);;
+ if (req == NULL) {
+ return NULL;
+ }
+ SCVAL(state->vwv+0, 0, 0xff);
+ SCVAL(state->vwv+0, 1, 0);
+ SSVAL(state->vwv+1, 0, 0);
+ SSVAL(state->vwv+2, 0, fnum);
+ SCVAL(state->vwv+3, 0, LOCKING_ANDX_OPLOCK_RELEASE);
+ SCVAL(state->vwv+3, 1, level);
+ SIVAL(state->vwv+4, 0, 0); /* timeout */
+ SSVAL(state->vwv+6, 0, 0); /* unlockcount */
+ SSVAL(state->vwv+7, 0, 0); /* lockcount */
+
+ subreq = cli_smb_send(state, ev, cli, SMBlockingX, 0, 8, state->vwv,
+ 0, NULL);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, cli_oplock_ack_done, req);
+ return req;
+}
+
+static void cli_oplock_ack_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ NTSTATUS status;
+
+ status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS cli_oplock_ack_recv(struct tevent_req *req)
{
- char *oldbuf = cli->outbuf;
- char buf[smb_size+16];
- bool ret;
-
- cli->outbuf = buf;
-
- memset(buf,'\0',smb_size);
- cli_set_message(buf,8,0,True);
-
- SCVAL(buf,smb_com,SMBlockingX);
- SSVAL(buf,smb_tid, cli->cnum);
- cli_setup_packet(cli);
- SSVAL(buf,smb_vwv0,0xFF);
- SSVAL(buf,smb_vwv1,0);
- SSVAL(buf,smb_vwv2,fnum);
- if (level == 1)
- SSVAL(buf,smb_vwv3,0x102); /* levelII oplock break ack */
- else
- SSVAL(buf,smb_vwv3,2); /* exclusive oplock break ack */
- SIVAL(buf,smb_vwv4,0); /* timoeut */
- SSVAL(buf,smb_vwv6,0); /* unlockcount */
- SSVAL(buf,smb_vwv7,0); /* lockcount */
-
- ret = cli_send_smb(cli);
-
- cli->outbuf = oldbuf;
-
- return ret;
+ return tevent_req_simple_recv_ntstatus(req);
}
+bool cli_oplock_ack(struct cli_state *cli, int fnum, unsigned char level)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct event_context *ev;
+ struct tevent_req *req;
+ NTSTATUS status = NT_STATUS_OK;
+
+ if (cli_has_async_calls(cli)) {
+ /*
+ * Can't use sync call while an async call is in flight
+ */
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto fail;
+ }
+
+ ev = event_context_init(frame);
+ if (ev == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
+ req = cli_oplock_ack_send(frame, ev, cli, fnum, level);
+ if (req == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
+ }
+
+ status = cli_oplock_ack_recv(req);
+ fail:
+ TALLOC_FREE(frame);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_set_error(cli, status);
+ }
+ return NT_STATUS_IS_OK(status);
+}
/****************************************************************************
set the oplock handler for a connection
diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c
index f2f447b4c9..1d2f5f79ec 100644
--- a/source3/libsmb/clireadwrite.c
+++ b/source3/libsmb/clireadwrite.c
@@ -70,21 +70,25 @@ static size_t cli_write_max_bufsize(struct cli_state *cli, uint16_t write_mode)
return CLI_WINDOWS_MAX_LARGE_WRITEX_SIZE;
}
+struct cli_read_andx_state {
+ size_t size;
+ uint16_t vwv[12];
+ NTSTATUS status;
+ size_t received;
+ uint8_t *buf;
+};
-/*
- * Send a read&x request
- */
+static void cli_read_andx_done(struct tevent_req *subreq);
-struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli, int fnum,
- off_t offset, size_t size)
+struct tevent_req *cli_read_andx_create(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli, int fnum,
+ off_t offset, size_t size,
+ struct tevent_req **psmbreq)
{
- struct async_req *result;
- struct cli_request *req;
+ struct tevent_req *req, *subreq;
+ struct cli_read_andx_state *state;
bool bigoffset = False;
-
- uint16_t vwv[12];
uint8_t wct = 10;
if (size > cli_read_max_bufsize(cli)) {
@@ -94,82 +98,85 @@ struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx,
return NULL;
}
- SCVAL(vwv + 0, 0, 0xFF);
- SCVAL(vwv + 0, 1, 0);
- SSVAL(vwv + 1, 0, 0);
- SSVAL(vwv + 2, 0, fnum);
- SIVAL(vwv + 3, 0, offset);
- SSVAL(vwv + 5, 0, size);
- SSVAL(vwv + 6, 0, size);
- SSVAL(vwv + 7, 0, (size >> 16));
- SSVAL(vwv + 8, 0, 0);
- SSVAL(vwv + 9, 0, 0);
+ req = tevent_req_create(mem_ctx, &state, struct cli_read_andx_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->size = size;
+
+ SCVAL(state->vwv + 0, 0, 0xFF);
+ SCVAL(state->vwv + 0, 1, 0);
+ SSVAL(state->vwv + 1, 0, 0);
+ SSVAL(state->vwv + 2, 0, fnum);
+ SIVAL(state->vwv + 3, 0, offset);
+ SSVAL(state->vwv + 5, 0, size);
+ SSVAL(state->vwv + 6, 0, size);
+ SSVAL(state->vwv + 7, 0, (size >> 16));
+ SSVAL(state->vwv + 8, 0, 0);
+ SSVAL(state->vwv + 9, 0, 0);
if ((uint64_t)offset >> 32) {
- bigoffset = True;
- SIVAL(vwv + 10, 0,
+ bigoffset = true;
+ SIVAL(state->vwv + 10, 0,
(((uint64_t)offset)>>32) & 0xffffffff);
wct += 2;
}
- result = cli_request_send(mem_ctx, ev, cli, SMBreadX, 0, wct, vwv, 0,
- 0, NULL);
- if (result == NULL) {
+ subreq = cli_smb_req_create(state, ev, cli, SMBreadX, 0, wct,
+ state->vwv, 0, NULL);
+ if (subreq == NULL) {
+ TALLOC_FREE(req);
return NULL;
}
+ tevent_req_set_callback(subreq, cli_read_andx_done, req);
+ *psmbreq = subreq;
+ return req;
+}
- req = talloc_get_type_abort(result->private_data, struct cli_request);
-
- req->data.read.ofs = offset;
- req->data.read.size = size;
- req->data.read.received = 0;
- req->data.read.rcvbuf = NULL;
+struct tevent_req *cli_read_andx_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli, int fnum,
+ off_t offset, size_t size)
+{
+ struct tevent_req *req, *subreq;
- return result;
+ req = cli_read_andx_create(mem_ctx, ev, cli, fnum, offset, size,
+ &subreq);
+ if ((req == NULL) || !cli_smb_req_send(subreq)) {
+ TALLOC_FREE(req);
+ return NULL;
+ }
+ return req;
}
-/*
- * Pull the data out of a finished async read_and_x request. rcvbuf is
- * talloced from the request, so better make sure that you copy it away before
- * you talloc_free(req). "rcvbuf" is NOT a talloc_ctx of its own, so do not
- * talloc_move it!
- */
-
-NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received,
- uint8_t **rcvbuf)
+static void cli_read_andx_done(struct tevent_req *subreq)
{
- struct cli_request *cli_req = talloc_get_type_abort(
- req->private_data, struct cli_request);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_read_andx_state *state = tevent_req_data(
+ req, struct cli_read_andx_state);
+ uint8_t *inbuf;
uint8_t wct;
uint16_t *vwv;
- uint16_t num_bytes;
+ uint32_t num_bytes;
uint8_t *bytes;
- uint8_t *buf;
- NTSTATUS status;
- size_t size;
-
- if (async_req_is_nterror(req, &status)) {
- return status;
- }
-
- status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
-
- if (NT_STATUS_IS_ERR(status)) {
- return status;
- }
- if (wct < 12) {
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ state->status = cli_smb_recv(subreq, 12, &wct, &vwv, &num_bytes,
+ &bytes);
+ if (NT_STATUS_IS_ERR(state->status)) {
+ tevent_req_nterror(req, state->status);
+ return;
}
/* size is the number of bytes the server returned.
* Might be zero. */
- size = SVAL(vwv + 5, 0);
- size |= (((unsigned int)SVAL(vwv + 7, 0)) << 16);
+ state->received = SVAL(vwv + 5, 0);
+ state->received |= (((unsigned int)SVAL(vwv + 7, 0)) << 16);
- if (size > cli_req->data.read.size) {
+ if (state->received > state->size) {
DEBUG(5,("server returned more than we wanted!\n"));
- return NT_STATUS_UNEXPECTED_IO_ERROR;
+ tevent_req_nterror(req, NT_STATUS_UNEXPECTED_IO_ERROR);
+ return;
}
/*
@@ -177,24 +184,52 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received,
* bcc field can't be correct.
*/
- if ((size < 0xffff) && (size > num_bytes)) {
+ if ((state->received < 0xffff) && (state->received > num_bytes)) {
DEBUG(5, ("server announced more bytes than sent\n"));
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+ return;
}
- buf = (uint8_t *)smb_base(cli_req->inbuf) + SVAL(vwv+6, 0);
+ inbuf = cli_smb_inbuf(subreq);
+ state->buf = (uint8_t *)smb_base(inbuf) + SVAL(vwv+6, 0);
- if (trans_oob(smb_len(cli_req->inbuf), SVAL(vwv+6, 0), size)
- || (buf < bytes)) {
+ if (trans_oob(smb_len(inbuf), SVAL(vwv+6, 0), state->received)
+ || (state->buf < bytes)) {
DEBUG(5, ("server returned invalid read&x data offset\n"));
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+ return;
}
+ tevent_req_done(req);
+}
+
+/*
+ * Pull the data out of a finished async read_and_x request. rcvbuf is
+ * talloced from the request, so better make sure that you copy it away before
+ * you talloc_free(req). "rcvbuf" is NOT a talloc_ctx of its own, so do not
+ * talloc_move it!
+ */
+
+NTSTATUS cli_read_andx_recv(struct tevent_req *req, ssize_t *received,
+ uint8_t **rcvbuf)
+{
+ struct cli_read_andx_state *state = tevent_req_data(
+ req, struct cli_read_andx_state);
+ NTSTATUS status;
- *rcvbuf = (uint8_t *)(smb_base(cli_req->inbuf) + SVAL(vwv + 6, 0));
- *received = size;
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+ *received = state->received;
+ *rcvbuf = state->buf;
return NT_STATUS_OK;
}
+struct cli_pull_subreq {
+ struct tevent_req *req;
+ ssize_t received;
+ uint8_t *buf;
+};
+
/*
* Parallel read support.
*
@@ -204,7 +239,7 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received,
*/
struct cli_pull_state {
- struct async_req *req;
+ struct tevent_req *req;
struct event_context *ev;
struct cli_state *cli;
@@ -221,7 +256,7 @@ struct cli_pull_state {
* Outstanding requests
*/
int num_reqs;
- struct async_req **reqs;
+ struct cli_pull_subreq *reqs;
/*
* For how many bytes did we send requests already?
@@ -243,13 +278,13 @@ struct cli_pull_state {
SMB_OFF_T pushed;
};
-static char *cli_pull_print(TALLOC_CTX *mem_ctx, struct async_req *req)
+static char *cli_pull_print(struct tevent_req *req, TALLOC_CTX *mem_ctx)
{
- struct cli_pull_state *state = talloc_get_type_abort(
- req->private_data, struct cli_pull_state);
+ struct cli_pull_state *state = tevent_req_data(
+ req, struct cli_pull_state);
char *result;
- result = async_req_print(mem_ctx, req);
+ result = tevent_req_print(mem_ctx, req);
if (result == NULL) {
return NULL;
}
@@ -259,31 +294,31 @@ static char *cli_pull_print(TALLOC_CTX *mem_ctx, struct async_req *req)
state->num_reqs, state->top_req);
}
-static void cli_pull_read_done(struct async_req *read_req);
+static void cli_pull_read_done(struct tevent_req *read_req);
/*
* Prepare an async pull request
*/
-struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli,
- uint16_t fnum, off_t start_offset,
- SMB_OFF_T size, size_t window_size,
- NTSTATUS (*sink)(char *buf, size_t n,
- void *priv),
- void *priv)
+struct tevent_req *cli_pull_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
+ uint16_t fnum, off_t start_offset,
+ SMB_OFF_T size, size_t window_size,
+ NTSTATUS (*sink)(char *buf, size_t n,
+ void *priv),
+ void *priv)
{
- struct async_req *result;
+ struct tevent_req *req;
struct cli_pull_state *state;
int i;
- if (!async_req_setup(mem_ctx, &result, &state,
- struct cli_pull_state)) {
+ req = tevent_req_create(mem_ctx, &state, struct cli_pull_state);
+ if (req == NULL) {
return NULL;
}
- result->print = cli_pull_print;
- state->req = result;
+ tevent_req_set_print_fn(req, cli_pull_print);
+ state->req = req;
state->cli = cli;
state->ev = ev;
@@ -297,10 +332,8 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx,
state->top_req = 0;
if (size == 0) {
- if (!async_post_ntstatus(result, ev, NT_STATUS_OK)) {
- goto failed;
- }
- return result;
+ tevent_req_done(req);
+ return tevent_req_post(req, ev);
}
state->chunk_size = cli_read_max_bufsize(cli);
@@ -308,7 +341,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx,
state->num_reqs = MAX(window_size/state->chunk_size, 1);
state->num_reqs = MIN(state->num_reqs, cli->max_mux);
- state->reqs = TALLOC_ZERO_ARRAY(state, struct async_req *,
+ state->reqs = TALLOC_ZERO_ARRAY(state, struct cli_pull_subreq,
state->num_reqs);
if (state->reqs == NULL) {
goto failed;
@@ -317,6 +350,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx,
state->requested = 0;
for (i=0; i<state->num_reqs; i++) {
+ struct cli_pull_subreq *subreq = &state->reqs[i];
SMB_OFF_T size_left;
size_t request_thistime;
@@ -328,24 +362,21 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx,
size_left = size - state->requested;
request_thistime = MIN(size_left, state->chunk_size);
- state->reqs[i] = cli_read_andx_send(
+ subreq->req = cli_read_andx_send(
state->reqs, ev, cli, fnum,
state->start_offset + state->requested,
request_thistime);
- if (state->reqs[i] == NULL) {
+ if (subreq->req == NULL) {
goto failed;
}
-
- state->reqs[i]->async.fn = cli_pull_read_done;
- state->reqs[i]->async.priv = result;
-
+ tevent_req_set_callback(subreq->req, cli_pull_read_done, req);
state->requested += request_thistime;
}
- return result;
+ return req;
failed:
- TALLOC_FREE(result);
+ TALLOC_FREE(req);
return NULL;
}
@@ -354,20 +385,32 @@ failed:
* requests if necessary.
*/
-static void cli_pull_read_done(struct async_req *read_req)
+static void cli_pull_read_done(struct tevent_req *subreq)
{
- struct async_req *pull_req = talloc_get_type_abort(
- read_req->async.priv, struct async_req);
- struct cli_pull_state *state = talloc_get_type_abort(
- pull_req->private_data, struct cli_pull_state);
- struct cli_request *read_state = talloc_get_type_abort(
- read_req->private_data, struct cli_request);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_pull_state *state = tevent_req_data(
+ req, struct cli_pull_state);
+ struct cli_pull_subreq *pull_subreq = NULL;
NTSTATUS status;
+ int i;
- status = cli_read_andx_recv(read_req, &read_state->data.read.received,
- &read_state->data.read.rcvbuf);
+ for (i = 0; i < state->num_reqs; i++) {
+ pull_subreq = &state->reqs[i];
+ if (subreq == pull_subreq->req) {
+ break;
+ }
+ }
+ if (i == state->num_reqs) {
+ /* Huh -- received something we did not send?? */
+ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+ return;
+ }
+
+ status = cli_read_andx_recv(subreq, &pull_subreq->received,
+ &pull_subreq->buf);
if (!NT_STATUS_IS_OK(status)) {
- async_req_nterror(state->req, status);
+ tevent_req_nterror(state->req, status);
return;
}
@@ -380,39 +423,36 @@ static void cli_pull_read_done(struct async_req *read_req)
* requests.
*/
- while (state->reqs[state->top_req] != NULL) {
- struct cli_request *top_read;
+ while (state->reqs[state->top_req].req != NULL) {
+ struct cli_pull_subreq *top_subreq;
DEBUG(11, ("cli_pull_read_done: top_req = %d\n",
state->top_req));
- if (state->reqs[state->top_req]->state < ASYNC_REQ_DONE) {
+ top_subreq = &state->reqs[state->top_req];
+
+ if (tevent_req_is_in_progress(top_subreq->req)) {
DEBUG(11, ("cli_pull_read_done: top request not yet "
"done\n"));
return;
}
- top_read = talloc_get_type_abort(
- state->reqs[state->top_req]->private_data,
- struct cli_request);
-
DEBUG(10, ("cli_pull_read_done: Pushing %d bytes, %d already "
- "pushed\n", (int)top_read->data.read.received,
+ "pushed\n", (int)top_subreq->received,
(int)state->pushed));
- status = state->sink((char *)top_read->data.read.rcvbuf,
- top_read->data.read.received,
- state->priv);
+ status = state->sink((char *)top_subreq->buf,
+ top_subreq->received, state->priv);
if (!NT_STATUS_IS_OK(status)) {
- async_req_nterror(state->req, status);
+ tevent_req_nterror(state->req, status);
return;
}
- state->pushed += top_read->data.read.received;
+ state->pushed += top_subreq->received;
- TALLOC_FREE(state->reqs[state->top_req]);
+ TALLOC_FREE(state->reqs[state->top_req].req);
if (state->requested < state->size) {
- struct async_req *new_req;
+ struct tevent_req *new_req;
SMB_OFF_T size_left;
size_t request_thistime;
@@ -432,30 +472,29 @@ static void cli_pull_read_done(struct async_req *read_req)
state->start_offset + state->requested,
request_thistime);
- if (async_req_nomem(new_req, state->req)) {
+ if (tevent_req_nomem(new_req, state->req)) {
return;
}
+ tevent_req_set_callback(new_req, cli_pull_read_done,
+ req);
- new_req->async.fn = cli_pull_read_done;
- new_req->async.priv = pull_req;
-
- state->reqs[state->top_req] = new_req;
+ state->reqs[state->top_req].req = new_req;
state->requested += request_thistime;
}
state->top_req = (state->top_req+1) % state->num_reqs;
}
- async_req_done(pull_req);
+ tevent_req_done(req);
}
-NTSTATUS cli_pull_recv(struct async_req *req, SMB_OFF_T *received)
+NTSTATUS cli_pull_recv(struct tevent_req *req, SMB_OFF_T *received)
{
- struct cli_pull_state *state = talloc_get_type_abort(
- req->private_data, struct cli_pull_state);
+ struct cli_pull_state *state = tevent_req_data(
+ req, struct cli_pull_state);
NTSTATUS status;
- if (async_req_is_nterror(req, &status)) {
+ if (tevent_req_is_nterror(req, &status)) {
return status;
}
*received = state->pushed;
@@ -469,35 +508,42 @@ NTSTATUS cli_pull(struct cli_state *cli, uint16_t fnum,
{
TALLOC_CTX *frame = talloc_stackframe();
struct event_context *ev;
- struct async_req *req;
- NTSTATUS result = NT_STATUS_NO_MEMORY;
+ struct tevent_req *req;
+ NTSTATUS status = NT_STATUS_OK;
- if (cli->fd_event != NULL) {
+ if (cli_has_async_calls(cli)) {
/*
* Can't use sync call while an async call is in flight
*/
- return NT_STATUS_INVALID_PARAMETER;
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto fail;
}
ev = event_context_init(frame);
if (ev == NULL) {
- goto nomem;
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
}
req = cli_pull_send(frame, ev, cli, fnum, start_offset, size,
window_size, sink, priv);
if (req == NULL) {
- goto nomem;
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
}
- while (req->state < ASYNC_REQ_DONE) {
- event_loop_once(ev);
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
}
- result = cli_pull_recv(req, received);
- nomem:
+ status = cli_pull_recv(req, received);
+ fail:
TALLOC_FREE(frame);
- return result;
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_set_error(cli, status);
+ }
+ return status;
}
static NTSTATUS cli_read_sink(char *buf, size_t n, void *priv)
@@ -744,19 +790,41 @@ ssize_t cli_smbwrite(struct cli_state *cli,
* Send a write&x request
*/
-struct async_req *cli_write_andx_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli, uint16_t fnum,
- uint16_t mode, const uint8_t *buf,
- off_t offset, size_t size)
+struct cli_write_andx_state {
+ size_t size;
+ uint16_t vwv[14];
+ size_t written;
+ uint8_t pad;
+ struct iovec iov[2];
+};
+
+static void cli_write_andx_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_write_andx_create(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli, uint16_t fnum,
+ uint16_t mode, const uint8_t *buf,
+ off_t offset, size_t size,
+ struct tevent_req **reqs_before,
+ int num_reqs_before,
+ struct tevent_req **psmbreq)
{
+ struct tevent_req *req, *subreq;
+ struct cli_write_andx_state *state;
bool bigoffset = ((cli->capabilities & CAP_LARGE_FILES) != 0);
uint8_t wct = bigoffset ? 14 : 12;
size_t max_write = cli_write_max_bufsize(cli, mode);
- uint16_t vwv[14];
+ uint16_t *vwv;
+
+ req = tevent_req_create(mem_ctx, &state, struct cli_write_andx_state);
+ if (req == NULL) {
+ return NULL;
+ }
size = MIN(size, max_write);
+ vwv = state->vwv;
+
SCVAL(vwv+0, 0, 0xFF);
SCVAL(vwv+0, 1, 0);
SSVAL(vwv+1, 0, 0);
@@ -769,7 +837,7 @@ struct async_req *cli_write_andx_send(TALLOC_CTX *mem_ctx,
SSVAL(vwv+10, 0, size);
SSVAL(vwv+11, 0,
- cli_wct_ofs(cli)
+ cli_smb_wct_ofs(reqs_before, num_reqs_before)
+ 1 /* the wct field */
+ wct * 2 /* vwv */
+ 2 /* num_bytes field */
@@ -779,37 +847,70 @@ struct async_req *cli_write_andx_send(TALLOC_CTX *mem_ctx,
SIVAL(vwv+12, 0, (((uint64_t)offset)>>32) & 0xffffffff);
}
- return cli_request_send(mem_ctx, ev, cli, SMBwriteX, 0, wct, vwv,
- 2, size, buf);
+ state->pad = 0;
+ state->iov[0].iov_base = &state->pad;
+ state->iov[0].iov_len = 1;
+ state->iov[1].iov_base = CONST_DISCARD(uint8_t *, buf);
+ state->iov[1].iov_len = size;
+
+ subreq = cli_smb_req_create(state, ev, cli, SMBwriteX, 0, wct, vwv,
+ 2, state->iov);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, cli_write_andx_done, req);
+ *psmbreq = subreq;
+ return req;
}
-NTSTATUS cli_write_andx_recv(struct async_req *req, size_t *pwritten)
+struct tevent_req *cli_write_andx_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli, uint16_t fnum,
+ uint16_t mode, const uint8_t *buf,
+ off_t offset, size_t size)
{
+ struct tevent_req *req, *subreq;
+
+ req = cli_write_andx_create(mem_ctx, ev, cli, fnum, mode, buf, offset,
+ size, NULL, 0, &subreq);
+ if ((req == NULL) || !cli_smb_req_send(subreq)) {
+ TALLOC_FREE(req);
+ return NULL;
+ }
+ return req;
+}
+
+static void cli_write_andx_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_write_andx_state *state = tevent_req_data(
+ req, struct cli_write_andx_state);
uint8_t wct;
uint16_t *vwv;
- uint16_t num_bytes;
- uint8_t *bytes;
NTSTATUS status;
- size_t written;
- if (async_req_is_nterror(req, &status)) {
- return status;
+ status = cli_smb_recv(subreq, 6, &wct, &vwv, NULL, NULL);
+ if (NT_STATUS_IS_ERR(status)) {
+ TALLOC_FREE(subreq);
+ tevent_req_nterror(req, status);
+ return;
}
+ state->written = SVAL(vwv+2, 0);
+ state->written |= SVAL(vwv+4, 0)<<16;
+ tevent_req_done(req);
+}
- status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
+NTSTATUS cli_write_andx_recv(struct tevent_req *req, size_t *pwritten)
+{
+ struct cli_write_andx_state *state = tevent_req_data(
+ req, struct cli_write_andx_state);
+ NTSTATUS status;
- if (NT_STATUS_IS_ERR(status)) {
+ if (tevent_req_is_nterror(req, &status)) {
return status;
}
-
- if (wct < 6) {
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
- }
-
- written = SVAL(vwv+2, 0);
- written |= SVAL(vwv+4, 0)<<16;
- *pwritten = written;
-
+ *pwritten = state->written;
return NT_STATUS_OK;
}
@@ -824,22 +925,21 @@ struct cli_writeall_state {
size_t written;
};
-static void cli_writeall_written(struct async_req *req);
+static void cli_writeall_written(struct tevent_req *req);
-static struct async_req *cli_writeall_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli,
- uint16_t fnum,
- uint16_t mode,
- const uint8_t *buf,
- off_t offset, size_t size)
+static struct tevent_req *cli_writeall_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
+ uint16_t fnum,
+ uint16_t mode,
+ const uint8_t *buf,
+ off_t offset, size_t size)
{
- struct async_req *result;
- struct async_req *subreq;
+ struct tevent_req *req, *subreq;
struct cli_writeall_state *state;
- if (!async_req_setup(mem_ctx, &result, &state,
- struct cli_writeall_state)) {
+ req = tevent_req_create(mem_ctx, &state, struct cli_writeall_state);
+ if (req == NULL) {
return NULL;
}
state->ev = ev;
@@ -854,46 +954,40 @@ static struct async_req *cli_writeall_send(TALLOC_CTX *mem_ctx,
subreq = cli_write_andx_send(state, state->ev, state->cli, state->fnum,
state->mode, state->buf, state->offset,
state->size);
- if (subreq == NULL) {
- goto fail;
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
}
-
- subreq->async.fn = cli_writeall_written;
- subreq->async.priv = result;
- return result;
-
- fail:
- TALLOC_FREE(result);
- return NULL;
+ tevent_req_set_callback(subreq, cli_writeall_written, req);
+ return req;
}
-static void cli_writeall_written(struct async_req *subreq)
+static void cli_writeall_written(struct tevent_req *subreq)
{
- struct async_req *req = talloc_get_type_abort(
- subreq->async.priv, struct async_req);
- struct cli_writeall_state *state = talloc_get_type_abort(
- req->private_data, struct cli_writeall_state);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_writeall_state *state = tevent_req_data(
+ req, struct cli_writeall_state);
NTSTATUS status;
size_t written, to_write;
status = cli_write_andx_recv(subreq, &written);
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
- async_req_nterror(req, status);
+ tevent_req_nterror(req, status);
return;
}
state->written += written;
if (state->written > state->size) {
- async_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+ tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
return;
}
to_write = state->size - state->written;
if (to_write == 0) {
- async_req_done(req);
+ tevent_req_done(req);
return;
}
@@ -901,22 +995,19 @@ static void cli_writeall_written(struct async_req *subreq)
state->mode,
state->buf + state->written,
state->offset + state->written, to_write);
- if (subreq == NULL) {
- async_req_nterror(req, NT_STATUS_NO_MEMORY);
+ if (tevent_req_nomem(subreq, req)) {
return;
}
-
- subreq->async.fn = cli_writeall_written;
- subreq->async.priv = req;
+ tevent_req_set_callback(subreq, cli_writeall_written, req);
}
-static NTSTATUS cli_writeall_recv(struct async_req *req)
+static NTSTATUS cli_writeall_recv(struct tevent_req *req)
{
- return async_req_simple_recv_ntstatus(req);
+ return tevent_req_simple_recv_ntstatus(req);
}
struct cli_push_write_state {
- struct async_req *req;/* This is the main request! Not the subreq */
+ struct tevent_req *req;/* This is the main request! Not the subreq */
uint32_t idx;
off_t ofs;
uint8_t *buf;
@@ -947,14 +1038,14 @@ struct cli_push_state {
struct cli_push_write_state **reqs;
};
-static void cli_push_written(struct async_req *req);
+static void cli_push_written(struct tevent_req *req);
-static bool cli_push_write_setup(struct async_req *req,
+static bool cli_push_write_setup(struct tevent_req *req,
struct cli_push_state *state,
uint32_t idx)
{
struct cli_push_write_state *substate;
- struct async_req *subreq;
+ struct tevent_req *subreq;
substate = talloc(state->reqs, struct cli_push_write_state);
if (!substate) {
@@ -988,8 +1079,7 @@ static bool cli_push_write_setup(struct async_req *req,
talloc_free(substate);
return false;
}
- subreq->async.fn = cli_push_written;
- subreq->async.priv = substate;
+ tevent_req_set_callback(subreq, cli_push_written, substate);
state->reqs[idx] = substate;
state->pending += 1;
@@ -998,20 +1088,20 @@ static bool cli_push_write_setup(struct async_req *req,
return true;
}
-struct async_req *cli_push_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
- struct cli_state *cli,
- uint16_t fnum, uint16_t mode,
- off_t start_offset, size_t window_size,
- size_t (*source)(uint8_t *buf, size_t n,
- void *priv),
- void *priv)
+struct tevent_req *cli_push_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+ struct cli_state *cli,
+ uint16_t fnum, uint16_t mode,
+ off_t start_offset, size_t window_size,
+ size_t (*source)(uint8_t *buf, size_t n,
+ void *priv),
+ void *priv)
{
- struct async_req *req;
+ struct tevent_req *req;
struct cli_push_state *state;
uint32_t i;
- if (!async_req_setup(mem_ctx, &req, &state,
- struct cli_push_state)) {
+ req = tevent_req_create(mem_ctx, &state, struct cli_push_state);
+ if (req == NULL) {
return NULL;
}
state->cli = cli;
@@ -1054,26 +1144,24 @@ struct async_req *cli_push_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
}
if (state->pending == 0) {
- if (!async_post_ntstatus(req, ev, NT_STATUS_OK)) {
- goto failed;
- }
- return req;
+ tevent_req_done(req);
+ return tevent_req_post(req, ev);
}
return req;
failed:
- TALLOC_FREE(req);
- return NULL;
+ tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
+ return tevent_req_post(req, ev);
}
-static void cli_push_written(struct async_req *subreq)
+static void cli_push_written(struct tevent_req *subreq)
{
- struct cli_push_write_state *substate = talloc_get_type_abort(
- subreq->async.priv, struct cli_push_write_state);
- struct async_req *req = substate->req;
- struct cli_push_state *state = talloc_get_type_abort(
- req->private_data, struct cli_push_state);
+ struct cli_push_write_state *substate = tevent_req_callback_data(
+ subreq, struct cli_push_write_state);
+ struct tevent_req *req = substate->req;
+ struct cli_push_state *state = tevent_req_data(
+ req, struct cli_push_state);
NTSTATUS status;
uint32_t idx = substate->idx;
@@ -1084,26 +1172,26 @@ static void cli_push_written(struct async_req *subreq)
TALLOC_FREE(subreq);
TALLOC_FREE(substate);
if (!NT_STATUS_IS_OK(status)) {
- async_req_nterror(req, status);
+ tevent_req_nterror(req, status);
return;
}
if (!state->eof) {
if (!cli_push_write_setup(req, state, idx)) {
- async_req_nomem(NULL, req);
+ tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
return;
}
}
if (state->pending == 0) {
- async_req_done(req);
+ tevent_req_done(req);
return;
}
}
-NTSTATUS cli_push_recv(struct async_req *req)
+NTSTATUS cli_push_recv(struct tevent_req *req)
{
- return async_req_simple_recv_ntstatus(req);
+ return tevent_req_simple_recv_ntstatus(req);
}
NTSTATUS cli_push(struct cli_state *cli, uint16_t fnum, uint16_t mode,
@@ -1113,33 +1201,40 @@ NTSTATUS cli_push(struct cli_state *cli, uint16_t fnum, uint16_t mode,
{
TALLOC_CTX *frame = talloc_stackframe();
struct event_context *ev;
- struct async_req *req;
- NTSTATUS result = NT_STATUS_NO_MEMORY;
+ struct tevent_req *req;
+ NTSTATUS status = NT_STATUS_OK;
- if (cli->fd_event != NULL) {
+ if (cli_has_async_calls(cli)) {
/*
* Can't use sync call while an async call is in flight
*/
- return NT_STATUS_INVALID_PARAMETER;
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto fail;
}
ev = event_context_init(frame);
if (ev == NULL) {
- goto nomem;
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
}
req = cli_push_send(frame, ev, cli, fnum, mode, start_offset,
window_size, source, priv);
if (req == NULL) {
- goto nomem;
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
}
- while (req->state < ASYNC_REQ_DONE) {
- event_loop_once(ev);
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
}
- result = cli_push_recv(req);
- nomem:
+ status = cli_push_recv(req);
+ fail:
TALLOC_FREE(frame);
- return result;
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_set_error(cli, status);
+ }
+ return status;
}
diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c
index 91fb6e6296..3a6aa9e72c 100644
--- a/source3/libsmb/clitrans.c
+++ b/source3/libsmb/clitrans.c
@@ -704,6 +704,8 @@ struct cli_trans_state {
uint16_t mid;
uint32_t seqnum;
const char *pipe_name;
+ uint8_t *pipe_name_conv;
+ size_t pipe_name_conv_len;
uint16_t fid;
uint16_t function;
int flags;
@@ -720,27 +722,131 @@ struct cli_trans_state {
struct trans_recvblob rdata;
TALLOC_CTX *secondary_request_ctx;
+
+ struct iovec iov[4];
+ uint8_t pad[4];
+ uint16_t vwv[32];
};
-static void cli_trans_recv_helper(struct async_req *req);
+static NTSTATUS cli_pull_trans(uint8_t *inbuf,
+ uint8_t wct, uint16_t *vwv,
+ uint16_t num_bytes, uint8_t *bytes,
+ uint8_t smb_cmd, bool expect_first_reply,
+ uint8_t *pnum_setup, uint16_t **psetup,
+ uint32_t *ptotal_param, uint32_t *pnum_param,
+ uint32_t *pparam_disp, uint8_t **pparam,
+ uint32_t *ptotal_data, uint32_t *pnum_data,
+ uint32_t *pdata_disp, uint8_t **pdata)
+{
+ uint32_t param_ofs, data_ofs;
+
+ if (expect_first_reply) {
+ if ((wct != 0) || (num_bytes != 0)) {
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+ return NT_STATUS_OK;
+ }
+
+ switch (smb_cmd) {
+ case SMBtrans:
+ case SMBtrans2:
+ if (wct < 10) {
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+ *ptotal_param = SVAL(vwv + 0, 0);
+ *ptotal_data = SVAL(vwv + 1, 0);
+ *pnum_param = SVAL(vwv + 3, 0);
+ param_ofs = SVAL(vwv + 4, 0);
+ *pparam_disp = SVAL(vwv + 5, 0);
+ *pnum_data = SVAL(vwv + 6, 0);
+ data_ofs = SVAL(vwv + 7, 0);
+ *pdata_disp = SVAL(vwv + 8, 0);
+ *pnum_setup = CVAL(vwv + 9, 0);
+ if (wct < 10 + (*pnum_setup)) {
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+ *psetup = vwv + 10;
-static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx,
- struct cli_trans_state *state)
+ break;
+ case SMBnttrans:
+ if (wct < 18) {
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+ *ptotal_param = IVAL(vwv, 3);
+ *ptotal_data = IVAL(vwv, 7);
+ *pnum_param = IVAL(vwv, 11);
+ param_ofs = IVAL(vwv, 15);
+ *pparam_disp = IVAL(vwv, 19);
+ *pnum_data = IVAL(vwv, 23);
+ data_ofs = IVAL(vwv, 27);
+ *pdata_disp = IVAL(vwv, 31);
+ *pnum_setup = CVAL(vwv, 35);
+ *psetup = vwv + 18;
+ break;
+
+ default:
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ /*
+ * Check for buffer overflows. data_ofs needs to be checked against
+ * the incoming buffer length, data_disp against the total
+ * length. Likewise for param_ofs/param_disp.
+ */
+
+ if (trans_oob(smb_len(inbuf), param_ofs, *pnum_param)
+ || trans_oob(*ptotal_param, *pparam_disp, *pnum_param)
+ || trans_oob(smb_len(inbuf), data_ofs, *pnum_data)
+ || trans_oob(*ptotal_data, *pdata_disp, *pnum_data)) {
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+
+ *pparam = (uint8_t *)inbuf + 4 + param_ofs;
+ *pdata = (uint8_t *)inbuf + 4 + data_ofs;
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS cli_trans_pull_blob(TALLOC_CTX *mem_ctx,
+ struct trans_recvblob *blob,
+ uint32_t total, uint32_t thistime,
+ uint8_t *buf, uint32_t displacement)
{
- TALLOC_CTX *frame;
- struct async_req *result = NULL;
- struct cli_request *cli_req;
- uint8_t wct;
- uint16_t *vwv;
- uint8_t *bytes = NULL;
+ if (blob->data == NULL) {
+ if (total > blob->max) {
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+ blob->total = total;
+ blob->data = TALLOC_ARRAY(mem_ctx, uint8_t, total);
+ if (blob->data == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ if (total > blob->total) {
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+
+ if (thistime) {
+ memcpy(blob->data + displacement, buf, thistime);
+ blob->received += thistime;
+ }
+
+ return NT_STATUS_OK;
+}
+
+static void cli_trans_format(struct cli_trans_state *state, uint8_t *pwct,
+ int *piov_count)
+{
+ uint8_t wct = 0;
+ struct iovec *iov = state->iov;
+ uint8_t *pad = state->pad;
+ uint16_t *vwv = state->vwv;
uint16_t param_offset;
uint16_t this_param = 0;
uint16_t this_data = 0;
uint32_t useable_space;
uint8_t cmd;
- uint8_t pad[3];
-
- frame = talloc_stackframe();
cmd = state->cmd;
@@ -751,39 +857,26 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx,
param_offset = smb_size - 4;
- bytes = TALLOC_ARRAY(talloc_tos(), uint8_t, 0); /* padding */
- if (bytes == NULL) {
- goto fail;
- }
-
switch (cmd) {
case SMBtrans:
pad[0] = 0;
- bytes = (uint8_t *)talloc_append_blob(talloc_tos(), bytes,
- data_blob_const(pad, 1));
- if (bytes == NULL) {
- goto fail;
- }
- bytes = smb_bytes_push_str(bytes, cli_ucs2(state->cli),
- state->pipe_name,
- strlen(state->pipe_name)+1, NULL);
- if (bytes == NULL) {
- goto fail;
- }
+ iov[0].iov_base = pad;
+ iov[0].iov_len = 1;
+ iov[1].iov_base = state->pipe_name_conv;
+ iov[1].iov_len = state->pipe_name_conv_len;
wct = 14 + state->num_setup;
- param_offset += talloc_get_size(bytes);
+ param_offset += iov[0].iov_len + iov[1].iov_len;
+ iov += 2;
break;
case SMBtrans2:
pad[0] = 0;
pad[1] = 'D'; /* Copy this from "old" 3.0 behaviour */
pad[2] = ' ';
- bytes = (uint8_t *)talloc_append_blob(talloc_tos(), bytes,
- data_blob_const(pad, 3));
- if (bytes == NULL) {
- goto fail;
- }
+ iov[0].iov_base = pad;
+ iov[0].iov_len = 3;
wct = 14 + state->num_setup;
- param_offset += talloc_get_size(bytes);
+ param_offset += 3;
+ iov += 1;
break;
case SMBtranss:
wct = 8;
@@ -797,8 +890,6 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx,
case SMBnttranss:
wct = 18;
break;
- default:
- goto fail;
}
useable_space = state->cli->max_xmit - smb_size - sizeof(uint16_t)*wct;
@@ -806,17 +897,19 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx,
if (state->param_sent < state->num_param) {
this_param = MIN(state->num_param - state->param_sent,
useable_space);
+ iov[0].iov_base = state->param + state->param_sent;
+ iov[0].iov_len = this_param;
+ iov += 1;
}
if (state->data_sent < state->num_data) {
this_data = MIN(state->num_data - state->data_sent,
useable_space - this_param);
+ iov[0].iov_base = state->data + state->data_sent;
+ iov[0].iov_len = this_data;
+ iov += 1;
}
- vwv = TALLOC_ARRAY(talloc_tos(), uint16_t, wct);
- if (vwv == NULL) {
- goto fail;
- }
param_offset += wct * sizeof(uint16_t);
DEBUG(10, ("num_setup=%u, max_setup=%u, "
@@ -897,221 +990,120 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx,
break;
}
- bytes = (uint8_t *)talloc_append_blob(
- talloc_tos(), bytes,
- data_blob_const(state->param + state->param_sent, this_param));
- if (bytes == NULL) {
- goto fail;
- }
state->param_sent += this_param;
-
- bytes = (uint8_t *)talloc_append_blob(
- talloc_tos(), bytes,
- data_blob_const(state->data + state->data_sent, this_data));
- if (bytes == NULL) {
- goto fail;
- }
state->data_sent += this_data;
- if ((cmd == SMBtrans) || (cmd == SMBtrans2) || (cmd == SMBnttrans)) {
- /*
- * Primary request, retrieve our mid
- */
- result = cli_request_send(mem_ctx, state->ev, state->cli,
- cmd, 0, wct, vwv, 0,
- talloc_get_size(bytes), bytes);
- if (result == NULL) {
- goto fail;
- }
- cli_req = talloc_get_type_abort(result->private_data,
- struct cli_request);
- state->mid = cli_req->mid;
- state->seqnum = cli_req->seqnum;
- } else {
- uint16_t num_bytes = talloc_get_size(bytes);
- /*
- * Secondary request, we have to fix up the mid. Thus we do
- * the chain_cork/chain/uncork ourselves.
- */
- if (!cli_chain_cork(state->cli, state->ev,
- wct * sizeof(uint16_t) + num_bytes + 3)) {
- goto fail;
- }
- result = cli_request_send(mem_ctx, state->ev, state->cli, cmd,
- 0, wct, vwv, 0, num_bytes, bytes);
- if (result == NULL) {
- goto fail;
- }
- cli_req = talloc_get_type_abort(result->private_data,
- struct cli_request);
- cli_req->recv_helper.fn = cli_trans_recv_helper;
- cli_req->recv_helper.priv = state;
- cli_req->mid = state->mid;
- cli_chain_uncork(state->cli);
- state->seqnum = cli_req->seqnum;
- }
-
- fail:
- TALLOC_FREE(frame);
- return result;
+ *pwct = wct;
+ *piov_count = iov - state->iov;
}
-static void cli_trans_ship_rest(struct async_req *req,
- struct cli_trans_state *state)
+static void cli_trans_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_trans_send(
+ TALLOC_CTX *mem_ctx, struct event_context *ev,
+ struct cli_state *cli, uint8_t cmd,
+ const char *pipe_name, uint16_t fid, uint16_t function, int flags,
+ uint16_t *setup, uint8_t num_setup, uint8_t max_setup,
+ uint8_t *param, uint32_t num_param, uint32_t max_param,
+ uint8_t *data, uint32_t num_data, uint32_t max_data)
{
- struct cli_request *cli_req;
+ struct tevent_req *req, *subreq;
+ struct cli_trans_state *state;
+ int iov_count;
+ uint8_t wct;
- state->secondary_request_ctx = talloc_new(state);
- if (state->secondary_request_ctx == NULL) {
- async_req_nterror(req, NT_STATUS_NO_MEMORY);
- return;
+ req = tevent_req_create(mem_ctx, &state, struct cli_trans_state);
+ if (req == NULL) {
+ return NULL;
}
- while ((state->param_sent < state->num_param)
- || (state->data_sent < state->num_data)) {
- struct async_req *subreq;
-
- subreq = cli_ship_trans(state->secondary_request_ctx, state);
- if (subreq == NULL) {
- async_req_nterror(req, NT_STATUS_NO_MEMORY);
- return;
+ if ((cmd == SMBtrans) || (cmd == SMBtrans2)) {
+ if ((num_param > 0xffff) || (max_param > 0xffff)
+ || (num_data > 0xffff) || (max_data > 0xffff)) {
+ DEBUG(3, ("Attempt to send invalid trans2 request "
+ "(setup %u, params %u/%u, data %u/%u)\n",
+ (unsigned)num_setup,
+ (unsigned)num_param, (unsigned)max_param,
+ (unsigned)num_data, (unsigned)max_data));
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return tevent_req_post(req, ev);
}
}
- cli_req = talloc_get_type_abort(req->private_data,
- struct cli_request);
-
- cli_req->seqnum = state->seqnum;
-}
-
-static NTSTATUS cli_pull_trans(struct async_req *req,
- struct cli_request *cli_req,
- uint8_t smb_cmd, bool expect_first_reply,
- uint8_t *pnum_setup, uint16_t **psetup,
- uint32_t *ptotal_param, uint32_t *pnum_param,
- uint32_t *pparam_disp, uint8_t **pparam,
- uint32_t *ptotal_data, uint32_t *pnum_data,
- uint32_t *pdata_disp, uint8_t **pdata)
-{
- uint32_t param_ofs, data_ofs;
- uint8_t wct;
- uint16_t *vwv;
- uint16_t num_bytes;
- uint8_t *bytes;
- NTSTATUS status;
-
- status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
-
/*
- * We can receive something like STATUS_MORE_ENTRIES, so don't use
- * !NT_STATUS_IS_OK(status) here.
+ * The largest wct will be for nttrans (19+num_setup). Make sure we
+ * don't overflow state->vwv in cli_trans_format.
*/
- if (NT_STATUS_IS_ERR(status)) {
- return status;
+ if ((num_setup + 19) > ARRAY_SIZE(state->vwv)) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return tevent_req_post(req, ev);
}
- if (expect_first_reply) {
- if ((wct != 0) || (num_bytes != 0)) {
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
- }
- return NT_STATUS_OK;
- }
-
- switch (smb_cmd) {
- case SMBtrans:
- case SMBtrans2:
- if (wct < 10) {
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
- }
- *ptotal_param = SVAL(vwv + 0, 0);
- *ptotal_data = SVAL(vwv + 1, 0);
- *pnum_param = SVAL(vwv + 3, 0);
- param_ofs = SVAL(vwv + 4, 0);
- *pparam_disp = SVAL(vwv + 5, 0);
- *pnum_data = SVAL(vwv + 6, 0);
- data_ofs = SVAL(vwv + 7, 0);
- *pdata_disp = SVAL(vwv + 8, 0);
- *pnum_setup = CVAL(vwv + 9, 0);
- if (wct < 10 + (*pnum_setup)) {
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
- }
- *psetup = vwv + 10;
-
- break;
- case SMBnttrans:
- if (wct < 18) {
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
- }
- *ptotal_param = IVAL(vwv, 3);
- *ptotal_data = IVAL(vwv, 7);
- *pnum_param = IVAL(vwv, 11);
- param_ofs = IVAL(vwv, 15);
- *pparam_disp = IVAL(vwv, 19);
- *pnum_data = IVAL(vwv, 23);
- data_ofs = IVAL(vwv, 27);
- *pdata_disp = IVAL(vwv, 31);
- *pnum_setup = CVAL(vwv, 35);
- *psetup = vwv + 18;
- break;
+ state->cli = cli;
+ state->ev = ev;
+ state->cmd = cmd;
+ state->flags = flags;
+ state->num_rsetup = 0;
+ state->rsetup = NULL;
+ ZERO_STRUCT(state->rparam);
+ ZERO_STRUCT(state->rdata);
- default:
- return NT_STATUS_INTERNAL_ERROR;
+ if ((pipe_name != NULL)
+ && (!convert_string_allocate(state, CH_UNIX,
+ cli_ucs2(cli) ? CH_UTF16LE : CH_DOS,
+ pipe_name, strlen(pipe_name) + 1,
+ &state->pipe_name_conv,
+ &state->pipe_name_conv_len, true))) {
+ tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
+ return tevent_req_post(req, ev);
}
+ state->fid = fid; /* trans2 */
+ state->function = function; /* nttrans */
- /*
- * Check for buffer overflows. data_ofs needs to be checked against
- * the incoming buffer length, data_disp against the total
- * length. Likewise for param_ofs/param_disp.
- */
-
- if (trans_oob(smb_len(cli_req->inbuf), param_ofs, *pnum_param)
- || trans_oob(*ptotal_param, *pparam_disp, *pnum_param)
- || trans_oob(smb_len(cli_req->inbuf), data_ofs, *pnum_data)
- || trans_oob(*ptotal_data, *pdata_disp, *pnum_data)) {
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
- }
+ state->setup = setup;
+ state->num_setup = num_setup;
+ state->max_setup = max_setup;
- *pparam = (uint8_t *)cli_req->inbuf + 4 + param_ofs;
- *pdata = (uint8_t *)cli_req->inbuf + 4 + data_ofs;
+ state->param = param;
+ state->num_param = num_param;
+ state->param_sent = 0;
+ state->rparam.max = max_param;
- return NT_STATUS_OK;
-}
+ state->data = data;
+ state->num_data = num_data;
+ state->data_sent = 0;
+ state->rdata.max = max_data;
-static NTSTATUS cli_trans_pull_blob(TALLOC_CTX *mem_ctx,
- struct trans_recvblob *blob,
- uint32_t total, uint32_t thistime,
- uint8_t *buf, uint32_t displacement)
-{
- if (blob->data == NULL) {
- if (total > blob->max) {
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
- }
- blob->total = total;
- blob->data = TALLOC_ARRAY(mem_ctx, uint8_t, total);
- if (blob->data == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
- }
+ cli_trans_format(state, &wct, &iov_count);
- if (total > blob->total) {
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ subreq = cli_smb_req_create(state, ev, cli, cmd, 0, wct, state->vwv,
+ iov_count, state->iov);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
}
-
- if (thistime) {
- memcpy(blob->data + displacement, buf, thistime);
- blob->received += thistime;
+ state->mid = cli_smb_req_mid(subreq);
+ if (!cli_smb_req_send(subreq)) {
+ tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
+ return tevent_req_post(req, state->ev);
}
-
- return NT_STATUS_OK;
+ cli_state_seqnum_persistent(cli, state->mid);
+ tevent_req_set_callback(subreq, cli_trans_done, req);
+ return req;
}
-static void cli_trans_recv_helper(struct async_req *req)
+static void cli_trans_done(struct tevent_req *subreq)
{
- struct cli_request *cli_req = talloc_get_type_abort(
- req->private_data, struct cli_request);
- struct cli_trans_state *state = talloc_get_type_abort(
- cli_req->recv_helper.priv, struct cli_trans_state);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_trans_state *state = tevent_req_data(
+ req, struct cli_trans_state);
+ NTSTATUS status;
+ bool sent_all;
+ uint8_t wct;
+ uint16_t *vwv;
+ uint32_t num_bytes;
+ uint8_t *bytes;
uint8_t num_setup = 0;
uint16_t *setup = NULL;
uint32_t total_param = 0;
@@ -1122,16 +1114,8 @@ static void cli_trans_recv_helper(struct async_req *req)
uint32_t data_disp = 0;
uint8_t *param = NULL;
uint8_t *data = NULL;
- bool sent_all;
- NTSTATUS status;
- sent_all = (state->param_sent == state->num_param)
- && (state->data_sent == state->num_data);
-
- status = cli_pull_trans(
- req, cli_req, state->cmd, !sent_all, &num_setup, &setup,
- &total_param, &num_param, &param_disp, &param,
- &total_data, &num_data, &data_disp, &data);
+ status = cli_smb_recv(subreq, 0, &wct, &vwv, &num_bytes, &bytes);
/*
* We can receive something like STATUS_MORE_ENTRIES, so don't use
@@ -1139,30 +1123,43 @@ static void cli_trans_recv_helper(struct async_req *req)
*/
if (NT_STATUS_IS_ERR(status)) {
- async_req_nterror(req, status);
- return;
+ goto fail;
}
- if (!sent_all) {
- cli_trans_ship_rest(req, state);
- return;
+ sent_all = ((state->param_sent == state->num_param)
+ && (state->data_sent == state->num_data));
+
+ status = cli_pull_trans(
+ cli_smb_inbuf(subreq), wct, vwv, num_bytes, bytes,
+ state->cmd, !sent_all, &num_setup, &setup,
+ &total_param, &num_param, &param_disp, &param,
+ &total_data, &num_data, &data_disp, &data);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
}
- /*
- * We've just received a real response. This means that we don't need
- * the secondary cli_request structures anymore, they have all been
- * shipped to the server.
- */
- TALLOC_FREE(state->secondary_request_ctx);
+ if (!sent_all) {
+ int iov_count;
- if (num_setup != 0) {
- TALLOC_FREE(state->rsetup);
- state->rsetup = (uint16_t *)TALLOC_MEMDUP(
- state, setup, sizeof(uint16_t) * num_setup);
- if (state->rsetup == NULL) {
- async_req_nterror(req, NT_STATUS_NO_MEMORY);
+ TALLOC_FREE(subreq);
+
+ cli_trans_format(state, &wct, &iov_count);
+
+ subreq = cli_smb_req_create(state, state->ev, state->cli,
+ state->cmd + 1, 0, wct, state->vwv,
+ iov_count, state->iov);
+ if (tevent_req_nomem(subreq, req)) {
return;
}
+ cli_smb_req_set_mid(subreq, state->mid);
+
+ if (!cli_smb_req_send(subreq)) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+ tevent_req_set_callback(subreq, cli_trans_done, req);
+ return;
}
status = cli_trans_pull_blob(
@@ -1171,8 +1168,7 @@ static void cli_trans_recv_helper(struct async_req *req)
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("Pulling params failed: %s\n", nt_errstr(status)));
- async_req_nterror(req, status);
- return;
+ goto fail;
}
status = cli_trans_pull_blob(
@@ -1181,149 +1177,39 @@ static void cli_trans_recv_helper(struct async_req *req)
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("Pulling data failed: %s\n", nt_errstr(status)));
- async_req_nterror(req, status);
- return;
+ goto fail;
}
if ((state->rparam.total == state->rparam.received)
&& (state->rdata.total == state->rdata.received)) {
- async_req_done(req);
- }
-}
-
-struct async_req *cli_trans_send(
- TALLOC_CTX *mem_ctx, struct event_context *ev,
- struct cli_state *cli, uint8_t trans_cmd,
- const char *pipe_name, uint16_t fid, uint16_t function, int flags,
- uint16_t *setup, uint8_t num_setup, uint8_t max_setup,
- uint8_t *param, uint32_t num_param, uint32_t max_param,
- uint8_t *data, uint32_t num_data, uint32_t max_data)
-{
- struct async_req *req;
- struct cli_request *cli_req;
- struct cli_trans_state *state;
-
- /*
- * We can't use it in a chained request chain, we'd get the offset
- * calculations wrong.
- */
-
- if (cli_in_chain(cli)) {
- return NULL;
- }
-
- if ((trans_cmd == SMBtrans) || (trans_cmd == SMBtrans2)) {
- if ((num_param > 0xffff) || (max_param > 0xffff)
- || (num_data > 0xffff) || (max_data > 0xffff)) {
- DEBUG(3, ("Attempt to send invalid trans2 request "
- "(setup %u, params %u/%u, data %u/%u)\n",
- (unsigned)num_setup,
- (unsigned)num_param, (unsigned)max_param,
- (unsigned)num_data, (unsigned)max_data));
- return NULL;
- }
- }
-
- state = talloc(mem_ctx, struct cli_trans_state);
- if (state == NULL) {
- goto nomem;
- }
-
- state->cli = cli;
- state->ev = ev;
- state->cmd = trans_cmd;
- state->num_rsetup = 0;
- state->rsetup = NULL;
- ZERO_STRUCT(state->rparam);
- ZERO_STRUCT(state->rdata);
- state->secondary_request_ctx = NULL;
-
- if (trans_cmd == SMBtrans) {
- state->pipe_name = talloc_strdup(state, pipe_name);
- if (state->pipe_name == NULL) {
- goto nomem;
- }
- }
- if (trans_cmd == SMBtrans2) {
- state->fid = fid;
- }
- if (trans_cmd == SMBnttrans) {
- state->function = function;
- }
-
- state->flags = flags;
-
- if (setup != NULL) {
- state->setup = (uint16_t *)TALLOC_MEMDUP(
- state, setup, sizeof(*setup) * num_setup);
- if (state->setup == NULL) {
- goto nomem;
- }
- state->num_setup = num_setup;
- } else {
- state->setup = NULL;
- state->num_setup = 0;
- }
-
- state->max_setup = max_setup;
-
- if (param != NULL) {
- state->param = (uint8_t *)TALLOC_MEMDUP(state, param,
- num_param);
- if (state->param == NULL) {
- goto nomem;
- }
- state->num_param = num_param;
- } else {
- state->param = NULL;
- state->num_param = 0;
- }
-
- state->param_sent = 0;
- state->rparam.max = max_param;
-
- if (data != NULL) {
- state->data = (uint8_t *)TALLOC_MEMDUP(state, data, num_data);
- if (state->data == NULL) {
- goto nomem;
- }
- state->num_data = num_data;
- } else {
- state->data = NULL;
- state->num_data = 0;
+ TALLOC_FREE(subreq);
+ cli_state_seqnum_remove(state->cli, state->mid);
+ tevent_req_done(req);
+ return;
}
- state->data_sent = 0;
- state->rdata.max = max_data;
-
- req = cli_ship_trans(state, state);
- if (req == NULL) {
- goto nomem;
+ if (!cli_smb_req_set_pending(subreq)) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
}
+ return;
- cli_req = talloc_get_type_abort(req->private_data, struct cli_request);
- cli_req->recv_helper.fn = cli_trans_recv_helper;
- cli_req->recv_helper.priv = state;
-
- return req;
-
- nomem:
- TALLOC_FREE(state);
- return NULL;
+ fail:
+ cli_state_seqnum_remove(state->cli, state->mid);
+ TALLOC_FREE(subreq);
+ tevent_req_nterror(req, status);
}
-NTSTATUS cli_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
+NTSTATUS cli_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
uint16_t **setup, uint8_t *num_setup,
uint8_t **param, uint32_t *num_param,
uint8_t **data, uint32_t *num_data)
{
- struct cli_request *cli_req = talloc_get_type_abort(
- req->private_data, struct cli_request);
- struct cli_trans_state *state = talloc_get_type_abort(
- cli_req->recv_helper.priv, struct cli_trans_state);
+ struct cli_trans_state *state = tevent_req_data(
+ req, struct cli_trans_state);
NTSTATUS status;
- if (async_req_is_nterror(req, &status)) {
+ if (tevent_req_is_nterror(req, &status)) {
return status;
}
@@ -1364,19 +1250,20 @@ NTSTATUS cli_trans(TALLOC_CTX *mem_ctx, struct cli_state *cli,
{
TALLOC_CTX *frame = talloc_stackframe();
struct event_context *ev;
- struct async_req *req;
- NTSTATUS status = NT_STATUS_NO_MEMORY;
+ struct tevent_req *req;
+ NTSTATUS status = NT_STATUS_OK;
- if (cli->fd_event != NULL) {
+ if (cli_has_async_calls(cli)) {
/*
* Can't use sync call while an async call is in flight
*/
- cli_set_error(cli, NT_STATUS_INVALID_PARAMETER);
+ status = NT_STATUS_INVALID_PARAMETER;
goto fail;
}
ev = event_context_init(frame);
if (ev == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
@@ -1386,16 +1273,21 @@ NTSTATUS cli_trans(TALLOC_CTX *mem_ctx, struct cli_state *cli,
param, num_param, max_param,
data, num_data, max_data);
if (req == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
- while (req->state < ASYNC_REQ_DONE) {
- event_loop_once(ev);
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
}
status = cli_trans_recv(req, mem_ctx, rsetup, num_rsetup,
rparam, num_rparam, rdata, num_rdata);
fail:
TALLOC_FREE(frame);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_set_error(cli, status);
+ }
return status;
}
diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c
index aa522ac780..be2948c531 100644
--- a/source3/locking/brlock.c
+++ b/source3/locking/brlock.c
@@ -41,11 +41,11 @@ static struct db_context *brlock_db;
static void print_lock_struct(unsigned int i, struct lock_struct *pls)
{
- DEBUG(10,("[%u]: smbpid = %u, tid = %u, pid = %u, ",
+ DEBUG(10,("[%u]: smbpid = %u, tid = %u, pid = %s, ",
i,
(unsigned int)pls->context.smbpid,
(unsigned int)pls->context.tid,
- (unsigned int)procid_to_pid(&pls->context.pid) ));
+ procid_str(debug_ctx(), &pls->context.pid) ));
DEBUG(10,("start = %.0f, size = %.0f, fnum = %d, %s %s\n",
(double)pls->start,
diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c
index 3c061ece79..b304d8bdc2 100644
--- a/source3/modules/vfs_gpfs.c
+++ b/source3/modules/vfs_gpfs.c
@@ -341,7 +341,7 @@ static bool gpfsacl_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl)
gacl_len = sizeof(struct gpfs_acl) +
(smb_get_naces(smbacl)-1)*sizeof(gpfs_ace_v4_t);
- gacl = TALLOC_SIZE(mem_ctx, gacl_len);
+ gacl = (struct gpfs_acl *)TALLOC_SIZE(mem_ctx, gacl_len);
if (gacl == NULL) {
DEBUG(0, ("talloc failed\n"));
errno = ENOMEM;
@@ -556,9 +556,9 @@ static SMB_ACL_T gpfsacl_get_posix_acl(const char *path, gpfs_aclType_t type)
return result;
}
-SMB_ACL_T gpfsacl_sys_acl_get_file(vfs_handle_struct *handle,
- const char *path_p,
- SMB_ACL_TYPE_T type)
+static SMB_ACL_T gpfsacl_sys_acl_get_file(vfs_handle_struct *handle,
+ const char *path_p,
+ SMB_ACL_TYPE_T type)
{
gpfs_aclType_t gpfs_type;
@@ -577,8 +577,8 @@ SMB_ACL_T gpfsacl_sys_acl_get_file(vfs_handle_struct *handle,
return gpfsacl_get_posix_acl(path_p, gpfs_type);
}
-SMB_ACL_T gpfsacl_sys_acl_get_fd(vfs_handle_struct *handle,
- files_struct *fsp)
+static SMB_ACL_T gpfsacl_sys_acl_get_fd(vfs_handle_struct *handle,
+ files_struct *fsp)
{
return gpfsacl_get_posix_acl(fsp->fsp_name, GPFS_ACL_TYPE_ACCESS);
}
@@ -600,7 +600,7 @@ static struct gpfs_acl *smb2gpfs_acl(const SMB_ACL_T pacl,
len = sizeof(struct gpfs_acl) - sizeof(union gpfs_ace_union) +
(pacl->count)*sizeof(gpfs_ace_v1_t);
- result = SMB_MALLOC(len);
+ result = (struct gpfs_acl *)SMB_MALLOC(len);
if (result == NULL) {
errno = ENOMEM;
return result;
@@ -670,10 +670,10 @@ static struct gpfs_acl *smb2gpfs_acl(const SMB_ACL_T pacl,
return result;
}
-int gpfsacl_sys_acl_set_file(vfs_handle_struct *handle,
- const char *name,
- SMB_ACL_TYPE_T type,
- SMB_ACL_T theacl)
+static int gpfsacl_sys_acl_set_file(vfs_handle_struct *handle,
+ const char *name,
+ SMB_ACL_TYPE_T type,
+ SMB_ACL_T theacl)
{
struct gpfs_acl *gpfs_acl;
int result;
@@ -689,15 +689,15 @@ int gpfsacl_sys_acl_set_file(vfs_handle_struct *handle,
return result;
}
-int gpfsacl_sys_acl_set_fd(vfs_handle_struct *handle,
- files_struct *fsp,
- SMB_ACL_T theacl)
+static int gpfsacl_sys_acl_set_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ SMB_ACL_T theacl)
{
return gpfsacl_sys_acl_set_file(handle, fsp->fsp_name, SMB_ACL_TYPE_ACCESS, theacl);
}
-int gpfsacl_sys_acl_delete_def_file(vfs_handle_struct *handle,
- const char *path)
+static int gpfsacl_sys_acl_delete_def_file(vfs_handle_struct *handle,
+ const char *path)
{
errno = ENOTSUP;
return -1;
diff --git a/source3/modules/vfs_gpfs.h b/source3/modules/vfs_gpfs.h
index 3c499b0850..efca5603aa 100644
--- a/source3/modules/vfs_gpfs.h
+++ b/source3/modules/vfs_gpfs.h
@@ -29,4 +29,6 @@ bool set_gpfs_sharemode(files_struct *fsp, uint32 access_mask,
int set_gpfs_lease(int fd, int leasetype);
int smbd_gpfs_getacl(char *pathname, int flags, void *acl);
int smbd_gpfs_putacl(char *pathname, int flags, void *acl);
+int smbd_gpfs_get_realfilename_path(char *pathname, char *filenamep,
+ int *buflen);
void init_gpfs(void);
diff --git a/source3/modules/vfs_onefs.c b/source3/modules/vfs_onefs.c
index ad59c2b32d..e4a0febbec 100644
--- a/source3/modules/vfs_onefs.c
+++ b/source3/modules/vfs_onefs.c
@@ -153,10 +153,21 @@ static int onefs_get_real_filename(vfs_handle_struct *handle, const char *path,
char **found_name)
{
SMB_STRUCT_STAT sb;
+ struct connection_struct *conn = handle->conn;
struct stat_extra se;
int result;
+ char *unmangled_name = NULL;
char *full_name = NULL;
+ /* First demangle the name if necessary. */
+ if (!conn->case_sensitive && mangle_is_mangled(name, conn->params) &&
+ mangle_lookup_name_from_8_3(mem_ctx, name, &unmangled_name,
+ conn->params)) {
+ /* Name is now unmangled. */
+ name = unmangled_name;
+ }
+
+ /* Do the case insensitive stat. */
ZERO_STRUCT(se);
se.se_version = ESTAT_CURRENT_VERSION;
se.se_flags = ESTAT_CASE_INSENSITIVE | ESTAT_SYMLINK_NOFOLLOW;
@@ -184,6 +195,7 @@ static int onefs_get_real_filename(vfs_handle_struct *handle, const char *path,
done:
TALLOC_FREE(full_name);
+ TALLOC_FREE(unmangled_name);
return result;
}
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 8da1f6348f..4b14b80339 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -885,7 +885,7 @@ static const struct enum_list enum_kerberos_method[] = {
/* Note: We do not initialise the defaults union - it is not allowed in ANSI C
*
- * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
+ * The FLAG_HIDE is explicit. Parameters set this way do NOT appear in any edit
* screen in SWAT. This is used to exclude parameters as well as to squash all
* parameters that have been duplicated by pseudonyms.
*
@@ -894,7 +894,7 @@ static const struct enum_list enum_kerberos_method[] = {
* Set FLAG_SHARE and FLAG_PRINT to specifically display parameters in
* respective views.
*
- * NOTE2: Handling of duplicated (synonym) paramters:
+ * NOTE2: Handling of duplicated (synonym) parameters:
* Only the first occurance of a parameter should be enabled by FLAG_BASIC
* and/or FLAG_ADVANCED. All duplicates following the first mention should be
* set to FLAG_HIDE. ie: Make you must place the parameter that has the preferred
diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c
index 77b19e3de9..b706721e77 100644
--- a/source3/passdb/pdb_ldap.c
+++ b/source3/passdb/pdb_ldap.c
@@ -840,27 +840,27 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
/* Make call to Novell eDirectory ldap extension to get clear text password.
NOTE: This will only work if we have an SSL connection to eDirectory. */
- user_dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
+ user_dn = smbldap_talloc_dn(ctx, ldap_state->smbldap_state->ldap_struct, entry);
if (user_dn != NULL) {
- DEBUG(3, ("init_sam_from_ldap: smbldap_get_dn(%s) returned '%s'\n", username, user_dn));
+ DEBUG(3, ("init_sam_from_ldap: smbldap_talloc_dn(ctx, %s) returned '%s'\n", username, user_dn));
pwd_len = sizeof(clear_text_pw);
if (pdb_nds_get_password(ldap_state->smbldap_state, user_dn, &pwd_len, clear_text_pw) == LDAP_SUCCESS) {
nt_lm_owf_gen(clear_text_pw, smbntpwd, smblmpwd);
if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET)) {
- SAFE_FREE(user_dn);
+ TALLOC_FREE(user_dn);
return False;
}
ZERO_STRUCT(smblmpwd);
if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET)) {
- SAFE_FREE(user_dn);
+ TALLOC_FREE(user_dn);
return False;
}
ZERO_STRUCT(smbntpwd);
use_samba_attrs = False;
}
- SAFE_FREE(user_dn);
+ TALLOC_FREE(user_dn);
} else {
DEBUG(0, ("init_sam_from_ldap: failed to get user_dn for '%s'\n", username));
@@ -1908,7 +1908,7 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struc
}
entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
- dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
+ dn = smbldap_talloc_dn(NULL, ldap_state->smbldap_state->ldap_struct, entry);
if (!dn) {
return NT_STATUS_UNSUCCESSFUL;
}
@@ -1918,7 +1918,7 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struc
if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
element_is_changed)) {
DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
- SAFE_FREE(dn);
+ TALLOC_FREE(dn);
if (mods != NULL)
ldap_mods_free(mods,True);
return NT_STATUS_UNSUCCESSFUL;
@@ -1928,7 +1928,7 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struc
&& (mods == NULL)) {
DEBUG(4,("ldapsam_update_sam_account: mods is empty: nothing to update for user: %s\n",
pdb_get_username(newpwd)));
- SAFE_FREE(dn);
+ TALLOC_FREE(dn);
return NT_STATUS_OK;
}
@@ -1938,7 +1938,7 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struc
ldap_mods_free(mods,True);
}
- SAFE_FREE(dn);
+ TALLOC_FREE(dn);
/*
* We need to set the backend private data to NULL here. For example
@@ -2147,17 +2147,10 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct s
/* Check if we need to update an existing entry */
if (num_result == 1) {
- char *tmp;
-
DEBUG(3,("ldapsam_add_sam_account: User exists without samba attributes: adding them\n"));
ldap_op = LDAP_MOD_REPLACE;
entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
- tmp = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
- if (!tmp) {
- goto fn_exit;
- }
- dn = talloc_asprintf(ctx, "%s", tmp);
- SAFE_FREE(tmp);
+ dn = smbldap_talloc_dn(ctx, ldap_state->smbldap_state->ldap_struct, entry);
if (!dn) {
status = NT_STATUS_NO_MEMORY;
goto fn_exit;
@@ -2200,17 +2193,11 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct s
/* Check if we need to update an existing entry */
if (num_result == 1) {
- char *tmp;
DEBUG(3,("ldapsam_add_sam_account: User exists without samba attributes: adding them\n"));
ldap_op = LDAP_MOD_REPLACE;
entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
- tmp = smbldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
- if (!tmp) {
- goto fn_exit;
- }
- dn = talloc_asprintf(ctx, "%s", tmp);
- SAFE_FREE(tmp);
+ dn = smbldap_talloc_dn (ctx, ldap_state->smbldap_state->ldap_struct, entry);
if (!dn) {
status = NT_STATUS_NO_MEMORY;
goto fn_exit;
@@ -3525,7 +3512,7 @@ static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
return NT_STATUS_UNSUCCESSFUL;
}
- dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
+ dn = smbldap_talloc_dn(NULL, ldap_state->smbldap_state->ldap_struct, entry);
if (!dn) {
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
@@ -3540,7 +3527,7 @@ static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
ldap_mods_free(mods, True);
ldap_msgfree(result);
- SAFE_FREE(dn);
+ TALLOC_FREE(dn);
if (rc == LDAP_TYPE_OR_VALUE_EXISTS) {
return NT_STATUS_MEMBER_IN_ALIAS;
@@ -6307,14 +6294,14 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
return NT_STATUS_UNSUCCESSFUL;
}
- dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
+ dn = smbldap_talloc_dn(talloc_tos(), ldap_state->smbldap_state->ldap_struct, entry);
if (!dn) {
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
ldap_state->domain_dn = smb_xstrdup(dn);
- ldap_memfree(dn);
+ TALLOC_FREE(dn);
domain_sid_string = smbldap_talloc_single_attribute(
ldap_state->smbldap_state->ldap_struct,
diff --git a/source3/passdb/pdb_nds.c b/source3/passdb/pdb_nds.c
index 1edd665d54..08665e4617 100644
--- a/source3/passdb/pdb_nds.c
+++ b/source3/passdb/pdb_nds.c
@@ -788,7 +788,7 @@ static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods,
}
entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
- dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
+ dn = smbldap_talloc_dn(NULL, ldap_state->smbldap_state->ldap_struct, entry);
if (!dn) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
@@ -811,6 +811,7 @@ static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods,
rc = smb_ldap_setup_full_conn(&ld, ldap_state->location);
if (rc) {
+ TALLOC_FREE(dn);
return NT_STATUS_INVALID_CONNECTION;
}
@@ -841,6 +842,7 @@ static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods,
return nt_status;
}
}
+ TALLOC_FREE(dn);
}
return NT_STATUS_OK;
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c
index a99485d381..c20171b049 100644
--- a/source3/printing/nt_printing.c
+++ b/source3/printing/nt_printing.c
@@ -3243,7 +3243,12 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
struct GUID guid;
WERROR win_rc = WERR_OK;
size_t converted_size;
- int ret;
+
+ /* build the ads mods */
+ ctx = talloc_init("nt_printer_publish_ads");
+ if (ctx == NULL) {
+ return WERR_NOMEM;
+ }
DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
@@ -3255,24 +3260,28 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
if (!srv_dn_utf8) {
+ TALLOC_FREE(ctx);
return WERR_SERVER_UNAVAILABLE;
}
ads_msgfree(ads, res);
srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
if (!srv_cn_utf8) {
+ TALLOC_FREE(ctx);
ldap_memfree(srv_dn_utf8);
return WERR_SERVER_UNAVAILABLE;
}
/* Now convert to CH_UNIX. */
- if (!pull_utf8_allocate(&srv_dn, srv_dn_utf8, &converted_size)) {
+ if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
+ TALLOC_FREE(ctx);
ldap_memfree(srv_dn_utf8);
ldap_memfree(srv_cn_utf8);
return WERR_SERVER_UNAVAILABLE;
}
- if (!pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0], &converted_size)) {
+ if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
+ TALLOC_FREE(ctx);
ldap_memfree(srv_dn_utf8);
ldap_memfree(srv_cn_utf8);
- SAFE_FREE(srv_dn);
+ TALLOC_FREE(srv_dn);
return WERR_SERVER_UNAVAILABLE;
}
@@ -3281,41 +3290,26 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
if (!srv_cn_escaped) {
- SAFE_FREE(srv_cn_0);
- SAFE_FREE(srv_dn);
+ TALLOC_FREE(ctx);
return WERR_SERVER_UNAVAILABLE;
}
sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
if (!sharename_escaped) {
SAFE_FREE(srv_cn_escaped);
- SAFE_FREE(srv_cn_0);
- SAFE_FREE(srv_dn);
+ TALLOC_FREE(ctx);
return WERR_SERVER_UNAVAILABLE;
}
- ret = asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
+ prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
- SAFE_FREE(srv_dn);
- SAFE_FREE(srv_cn_0);
SAFE_FREE(srv_cn_escaped);
SAFE_FREE(sharename_escaped);
- if (ret == -1) {
- return WERR_NOMEM;
- }
-
- /* build the ads mods */
- ctx = talloc_init("nt_printer_publish_ads");
- if (ctx == NULL) {
- SAFE_FREE(prt_dn);
- return WERR_NOMEM;
- }
-
mods = ads_init_mods(ctx);
if (mods == NULL) {
SAFE_FREE(prt_dn);
- talloc_destroy(ctx);
+ TALLOC_FREE(ctx);
return WERR_NOMEM;
}
@@ -3336,8 +3330,6 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
if (!ADS_ERR_OK(ads_rc))
DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
- talloc_destroy(ctx);
-
/* retreive the guid and store it locally */
if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
ZERO_STRUCT(guid);
@@ -3346,8 +3338,8 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
store_printer_guid(printer->info_2, guid);
win_rc = mod_a_printer(printer, 2);
}
+ TALLOC_FREE(ctx);
- SAFE_FREE(prt_dn);
return win_rc;
}
@@ -3365,13 +3357,13 @@ static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
printer->info_2->sharename, global_myname());
if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
- prt_dn = ads_get_dn(ads, res);
+ prt_dn = ads_get_dn(ads, talloc_tos(), res);
if (!prt_dn) {
ads_msgfree(ads, res);
return WERR_NOMEM;
}
ads_rc = ads_del_dn(ads, prt_dn);
- ads_memfree(ads, prt_dn);
+ TALLOC_FREE(prt_dn);
}
if (res) {
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c
index 6b83c170f5..a8cc33f585 100644
--- a/source3/rpc_client/cli_pipe.c
+++ b/source3/rpc_client/cli_pipe.c
@@ -2291,19 +2291,24 @@ NTSTATUS rpc_api_pipe_req(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *cli,
TALLOC_CTX *frame = talloc_stackframe();
struct event_context *ev;
struct tevent_req *req;
- NTSTATUS status = NT_STATUS_NO_MEMORY;
+ NTSTATUS status = NT_STATUS_OK;
ev = event_context_init(frame);
if (ev == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
req = rpc_api_pipe_req_send(frame, ev, cli, op_num, in_data);
if (req == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
- tevent_req_poll(req, ev);
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
+ }
status = rpc_api_pipe_req_recv(req, mem_ctx, out_data);
fail:
@@ -2905,19 +2910,24 @@ NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
TALLOC_CTX *frame = talloc_stackframe();
struct event_context *ev;
struct tevent_req *req;
- NTSTATUS status = NT_STATUS_NO_MEMORY;
+ NTSTATUS status = NT_STATUS_OK;
ev = event_context_init(frame);
if (ev == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
req = rpc_pipe_bind_send(frame, ev, cli, auth);
if (req == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
- tevent_req_poll(req, ev);
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
+ }
status = rpc_pipe_bind_recv(req);
fail:
diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c
index 8b45cb4e9c..40d68dd2ea 100644
--- a/source3/rpc_client/rpc_transport_np.c
+++ b/source3/rpc_client/rpc_transport_np.c
@@ -49,7 +49,7 @@ struct rpc_np_write_state {
size_t written;
};
-static void rpc_np_write_done(struct async_req *subreq);
+static void rpc_np_write_done(struct tevent_req *subreq);
static struct tevent_req *rpc_np_write_send(TALLOC_CTX *mem_ctx,
struct event_context *ev,
@@ -58,8 +58,7 @@ static struct tevent_req *rpc_np_write_send(TALLOC_CTX *mem_ctx,
{
struct rpc_transport_np_state *np_transport = talloc_get_type_abort(
priv, struct rpc_transport_np_state);
- struct tevent_req *req;
- struct async_req *subreq;
+ struct tevent_req *req, *subreq;
struct rpc_np_write_state *state;
req = tevent_req_create(mem_ctx, &state, struct rpc_np_write_state);
@@ -72,21 +71,17 @@ static struct tevent_req *rpc_np_write_send(TALLOC_CTX *mem_ctx,
np_transport->fnum,
8, /* 8 means message mode. */
data, 0, size);
- if (subreq == NULL) {
- goto fail;
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
}
- subreq->async.fn = rpc_np_write_done;
- subreq->async.priv = req;
+ tevent_req_set_callback(subreq, rpc_np_write_done, req);
return req;
- fail:
- TALLOC_FREE(req);
- return NULL;
}
-static void rpc_np_write_done(struct async_req *subreq)
+static void rpc_np_write_done(struct tevent_req *subreq)
{
- struct tevent_req *req = talloc_get_type_abort(
- subreq->async.priv, struct tevent_req);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
struct rpc_np_write_state *state = tevent_req_data(
req, struct rpc_np_write_state);
NTSTATUS status;
@@ -119,7 +114,7 @@ struct rpc_np_read_state {
ssize_t received;
};
-static void rpc_np_read_done(struct async_req *subreq);
+static void rpc_np_read_done(struct tevent_req *subreq);
static struct tevent_req *rpc_np_read_send(TALLOC_CTX *mem_ctx,
struct event_context *ev,
@@ -128,8 +123,7 @@ static struct tevent_req *rpc_np_read_send(TALLOC_CTX *mem_ctx,
{
struct rpc_transport_np_state *np_transport = talloc_get_type_abort(
priv, struct rpc_transport_np_state);
- struct tevent_req *req;
- struct async_req *subreq;
+ struct tevent_req *req, *subreq;
struct rpc_np_read_state *state;
req = tevent_req_create(mem_ctx, &state, struct rpc_np_read_state);
@@ -144,18 +138,17 @@ static struct tevent_req *rpc_np_read_send(TALLOC_CTX *mem_ctx,
if (subreq == NULL) {
goto fail;
}
- subreq->async.fn = rpc_np_read_done;
- subreq->async.priv = req;
+ tevent_req_set_callback(subreq, rpc_np_read_done, req);
return req;
fail:
TALLOC_FREE(req);
return NULL;
}
-static void rpc_np_read_done(struct async_req *subreq)
+static void rpc_np_read_done(struct tevent_req *subreq)
{
- struct tevent_req *req = talloc_get_type_abort(
- subreq->async.priv, struct tevent_req);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
struct rpc_np_read_state *state = tevent_req_data(
req, struct rpc_np_read_state);
NTSTATUS status;
@@ -204,7 +197,7 @@ struct rpc_np_trans_state {
uint32_t rdata_len;
};
-static void rpc_np_trans_done(struct async_req *subreq);
+static void rpc_np_trans_done(struct tevent_req *subreq);
static struct tevent_req *rpc_np_trans_send(TALLOC_CTX *mem_ctx,
struct event_context *ev,
@@ -214,8 +207,7 @@ static struct tevent_req *rpc_np_trans_send(TALLOC_CTX *mem_ctx,
{
struct rpc_transport_np_state *np_transport = talloc_get_type_abort(
priv, struct rpc_transport_np_state);
- struct tevent_req *req;
- struct async_req *subreq;
+ struct tevent_req *req, *subreq;
struct rpc_np_trans_state *state;
req = tevent_req_create(mem_ctx, &state, struct rpc_np_trans_state);
@@ -233,8 +225,7 @@ static struct tevent_req *rpc_np_trans_send(TALLOC_CTX *mem_ctx,
if (subreq == NULL) {
goto fail;
}
- subreq->async.fn = rpc_np_trans_done;
- subreq->async.priv = req;
+ tevent_req_set_callback(subreq, rpc_np_trans_done, req);
return req;
fail:
@@ -242,10 +233,10 @@ static struct tevent_req *rpc_np_trans_send(TALLOC_CTX *mem_ctx,
return NULL;
}
-static void rpc_np_trans_done(struct async_req *subreq)
+static void rpc_np_trans_done(struct tevent_req *subreq)
{
- struct tevent_req *req = talloc_get_type_abort(
- subreq->async.priv, struct tevent_req);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
struct rpc_np_trans_state *state = tevent_req_data(
req, struct rpc_np_trans_state);
NTSTATUS status;
@@ -280,29 +271,30 @@ struct rpc_transport_np_init_state {
struct rpc_transport_np_state *transport_np;
};
-static void rpc_transport_np_init_pipe_open(struct async_req *subreq);
+static void rpc_transport_np_init_pipe_open(struct tevent_req *subreq);
-struct async_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli,
- const struct ndr_syntax_id *abstract_syntax)
+struct tevent_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
+ const struct ndr_syntax_id *abstract_syntax)
{
- struct async_req *result, *subreq;
+ struct tevent_req *req, *subreq;
struct rpc_transport_np_init_state *state;
- if (!async_req_setup(mem_ctx, &result, &state,
- struct rpc_transport_np_init_state)) {
+ req = tevent_req_create(mem_ctx, &state,
+ struct rpc_transport_np_init_state);
+ if (req == NULL) {
return NULL;
}
state->transport = talloc(state, struct rpc_cli_transport);
- if (state->transport == NULL) {
- goto fail;
+ if (tevent_req_nomem(state->transport, req)) {
+ return tevent_req_post(req, ev);
}
state->transport_np = talloc(state->transport,
struct rpc_transport_np_state);
- if (state->transport_np == NULL) {
- goto fail;
+ if (tevent_req_nomem(state->transport_np, req)) {
+ return tevent_req_post(req, ev);
}
state->transport->priv = state->transport_np;
@@ -314,47 +306,43 @@ struct async_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx,
state, ev, cli, state->transport_np->pipe_name, 0,
DESIRED_ACCESS_PIPE, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN, 0, 0);
- if (subreq == NULL) {
- goto fail;
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
}
- subreq->async.fn = rpc_transport_np_init_pipe_open;
- subreq->async.priv = result;
- return result;
-
- fail:
- TALLOC_FREE(result);
- return NULL;
+ tevent_req_set_callback(subreq, rpc_transport_np_init_pipe_open,
+ req);
+ return req;
}
-static void rpc_transport_np_init_pipe_open(struct async_req *subreq)
+static void rpc_transport_np_init_pipe_open(struct tevent_req *subreq)
{
- struct async_req *req = talloc_get_type_abort(
- subreq->async.priv, struct async_req);
- struct rpc_transport_np_init_state *state = talloc_get_type_abort(
- req->private_data, struct rpc_transport_np_init_state);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct rpc_transport_np_init_state *state = tevent_req_data(
+ req, struct rpc_transport_np_init_state);
NTSTATUS status;
status = cli_ntcreate_recv(subreq, &state->transport_np->fnum);
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
- async_req_nterror(req, status);
+ tevent_req_nterror(req, status);
return;
}
talloc_set_destructor(state->transport_np,
rpc_transport_np_state_destructor);
- async_req_done(req);
+ tevent_req_done(req);
}
-NTSTATUS rpc_transport_np_init_recv(struct async_req *req,
+NTSTATUS rpc_transport_np_init_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
struct rpc_cli_transport **presult)
{
- struct rpc_transport_np_init_state *state = talloc_get_type_abort(
- req->private_data, struct rpc_transport_np_init_state);
+ struct rpc_transport_np_init_state *state = tevent_req_data(
+ req, struct rpc_transport_np_init_state);
NTSTATUS status;
- if (async_req_is_nterror(req, &status)) {
+ if (tevent_req_is_nterror(req, &status)) {
return status;
}
@@ -375,8 +363,8 @@ NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, struct cli_state *cli,
{
TALLOC_CTX *frame = talloc_stackframe();
struct event_context *ev;
- struct async_req *req;
- NTSTATUS status;
+ struct tevent_req *req;
+ NTSTATUS status = NT_STATUS_OK;
ev = event_context_init(frame);
if (ev == NULL) {
@@ -390,8 +378,9 @@ NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, struct cli_state *cli,
goto fail;
}
- while (req->state < ASYNC_REQ_DONE) {
- event_loop_once(ev);
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
}
status = rpc_transport_np_init_recv(req, mem_ctx, presult);
diff --git a/source3/rpc_client/rpc_transport_smbd.c b/source3/rpc_client/rpc_transport_smbd.c
index bde8d04208..171048ae29 100644
--- a/source3/rpc_client/rpc_transport_smbd.c
+++ b/source3/rpc_client/rpc_transport_smbd.c
@@ -88,6 +88,7 @@ static void rpc_cli_smbd_stdout_reader(struct event_context *ev,
TALLOC_FREE(fde);
return;
}
+ buf[nread] = '\0';
if (conn->stdout_callback.fn != NULL) {
conn->stdout_callback.fn(buf, nread,
@@ -127,102 +128,95 @@ struct get_anon_ipc_state {
struct cli_state *cli;
};
-static void get_anon_ipc_negprot_done(struct async_req *subreq);
-static void get_anon_ipc_sesssetup_done(struct async_req *subreq);
-static void get_anon_ipc_tcon_done(struct async_req *subreq);
+static void get_anon_ipc_negprot_done(struct tevent_req *subreq);
+static void get_anon_ipc_sesssetup_done(struct tevent_req *subreq);
+static void get_anon_ipc_tcon_done(struct tevent_req *subreq);
-static struct async_req *get_anon_ipc_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli)
+static struct tevent_req *get_anon_ipc_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli)
{
- struct async_req *result, *subreq;
+ struct tevent_req *req, *subreq;
struct get_anon_ipc_state *state;
- if (!async_req_setup(mem_ctx, &result, &state,
- struct get_anon_ipc_state)) {
+ req = tevent_req_create(mem_ctx, &state, struct get_anon_ipc_state);
+ if (req == NULL) {
return NULL;
}
-
state->ev = ev;
state->cli = cli;
subreq = cli_negprot_send(state, ev, cli);
- if (subreq == NULL) {
- goto fail;
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
}
- subreq->async.fn = get_anon_ipc_negprot_done;
- subreq->async.priv = result;
- return result;
- fail:
- TALLOC_FREE(result);
- return NULL;
+ tevent_req_set_callback(subreq, get_anon_ipc_negprot_done, req);
+ return req;
}
-static void get_anon_ipc_negprot_done(struct async_req *subreq)
+static void get_anon_ipc_negprot_done(struct tevent_req *subreq)
{
- struct async_req *req = talloc_get_type_abort(
- subreq->async.priv, struct async_req);
- struct get_anon_ipc_state *state = talloc_get_type_abort(
- req->private_data, struct get_anon_ipc_state);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct get_anon_ipc_state *state = tevent_req_data(
+ req, struct get_anon_ipc_state);
NTSTATUS status;
status = cli_negprot_recv(subreq);
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
- async_req_nterror(req, status);
+ tevent_req_nterror(req, status);
return;
}
subreq = cli_session_setup_guest_send(state, state->ev, state->cli);
- if (async_req_nomem(subreq, req)) {
+ if (tevent_req_nomem(subreq, req)) {
return;
}
- subreq->async.fn = get_anon_ipc_sesssetup_done;
- subreq->async.priv = req;
+ tevent_req_set_callback(subreq, get_anon_ipc_sesssetup_done, req);
}
-static void get_anon_ipc_sesssetup_done(struct async_req *subreq)
+static void get_anon_ipc_sesssetup_done(struct tevent_req *subreq)
{
- struct async_req *req = talloc_get_type_abort(
- subreq->async.priv, struct async_req);
- struct get_anon_ipc_state *state = talloc_get_type_abort(
- req->private_data, struct get_anon_ipc_state);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct get_anon_ipc_state *state = tevent_req_data(
+ req, struct get_anon_ipc_state);
NTSTATUS status;
status = cli_session_setup_guest_recv(subreq);
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
- async_req_nterror(req, status);
+ tevent_req_nterror(req, status);
return;
}
subreq = cli_tcon_andx_send(state, state->ev, state->cli,
"IPC$", "IPC", NULL, 0);
- if (async_req_nomem(subreq, req)) {
+ if (tevent_req_nomem(subreq, req)) {
return;
}
- subreq->async.fn = get_anon_ipc_tcon_done;
- subreq->async.priv = req;
+ tevent_req_set_callback(subreq, get_anon_ipc_tcon_done, req);
}
-static void get_anon_ipc_tcon_done(struct async_req *subreq)
+static void get_anon_ipc_tcon_done(struct tevent_req *subreq)
{
- struct async_req *req = talloc_get_type_abort(
- subreq->async.priv, struct async_req);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
NTSTATUS status;
status = cli_tcon_andx_recv(subreq);
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
- async_req_nterror(req, status);
+ tevent_req_nterror(req, status);
return;
}
- async_req_done(req);
+ tevent_req_done(req);
}
-static NTSTATUS get_anon_ipc_recv(struct async_req *req)
+static NTSTATUS get_anon_ipc_recv(struct tevent_req *req)
{
- return async_req_simple_recv_ntstatus(req);
+ return tevent_req_simple_recv_ntstatus(req);
}
struct rpc_cli_smbd_conn_init_state {
@@ -230,16 +224,16 @@ struct rpc_cli_smbd_conn_init_state {
struct rpc_cli_smbd_conn *conn;
};
-static void rpc_cli_smbd_conn_init_done(struct async_req *subreq);
+static void rpc_cli_smbd_conn_init_done(struct tevent_req *subreq);
-struct async_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- void (*stdout_callback)(char *buf,
- size_t len,
- void *priv),
- void *priv)
+struct tevent_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ void (*stdout_callback)(char *buf,
+ size_t len,
+ void *priv),
+ void *priv)
{
- struct async_req *result, *subreq;
+ struct tevent_req *req, *subreq;
struct rpc_cli_smbd_conn_init_state *state;
int smb_sock[2];
int stdout_pipe[2];
@@ -249,20 +243,21 @@ struct async_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx,
smb_sock[0] = smb_sock[1] = stdout_pipe[0] = stdout_pipe[1] = -1;
- if (!async_req_setup(mem_ctx, &result, &state,
- struct rpc_cli_smbd_conn_init_state)) {
+ req = tevent_req_create(mem_ctx, &state,
+ struct rpc_cli_smbd_conn_init_state);
+ if (req == NULL) {
return NULL;
}
state->ev = ev;
state->conn = talloc(state, struct rpc_cli_smbd_conn);
- if (state->conn == NULL) {
- goto nomem;
+ if (tevent_req_nomem(state->conn, req)) {
+ return tevent_req_post(req, ev);
}
state->conn->cli = cli_initialise();
- if (state->conn->cli == NULL) {
- goto nomem;
+ if (tevent_req_nomem(state->conn->cli, req)) {
+ return tevent_req_post(req, ev);
}
state->conn->stdout_fd = -1;
state->conn->stdout_callback.fn = stdout_callback;
@@ -309,7 +304,8 @@ struct async_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx,
printf("no memory");
exit(1);
}
- if (asprintf(&smbd_cmd, "%s -F -S", smbd_cmd) == -1) {
+ if (asprintf(&smbd_cmd, "%s -F -S -d %d", smbd_cmd,
+ DEBUGLEVEL) == -1) {
printf("no memory");
exit(1);
}
@@ -328,21 +324,19 @@ struct async_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx,
stdout_pipe[1] = -1;
subreq = get_anon_ipc_send(state, ev, state->conn->cli);
- if (subreq == NULL) {
- goto nomem;
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
}
- if (event_add_fd(ev, subreq, state->conn->stdout_fd, EVENT_FD_READ,
+ if (event_add_fd(ev, state, state->conn->stdout_fd, EVENT_FD_READ,
rpc_cli_smbd_stdout_reader, state->conn) == NULL) {
- goto nomem;
+ status = NT_STATUS_NO_MEMORY;
+ goto post_status;
}
- subreq->async.fn = rpc_cli_smbd_conn_init_done;
- subreq->async.priv = result;
- return result;
+ tevent_req_set_callback(subreq, rpc_cli_smbd_conn_init_done, req);
+ return req;
- nomem:
- status = NT_STATUS_NO_MEMORY;
post_status:
if (smb_sock[0] != -1) {
close(smb_sock[0]);
@@ -356,37 +350,34 @@ struct async_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx,
if (stdout_pipe[1] != -1) {
close(stdout_pipe[1]);
}
- if (async_post_ntstatus(result, ev, status)) {
- return result;
- }
- TALLOC_FREE(result);
- return NULL;
+ tevent_req_nterror(req, status);
+ return tevent_req_post(req, ev);
}
-static void rpc_cli_smbd_conn_init_done(struct async_req *subreq)
+static void rpc_cli_smbd_conn_init_done(struct tevent_req *subreq)
{
- struct async_req *req = talloc_get_type_abort(
- subreq->async.priv, struct async_req);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
NTSTATUS status;
status = get_anon_ipc_recv(subreq);
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
- async_req_nterror(req, status);
+ tevent_req_nterror(req, status);
return;
}
- async_req_done(req);
+ tevent_req_done(req);
}
-NTSTATUS rpc_cli_smbd_conn_init_recv(struct async_req *req,
+NTSTATUS rpc_cli_smbd_conn_init_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
struct rpc_cli_smbd_conn **pconn)
{
- struct rpc_cli_smbd_conn_init_state *state = talloc_get_type_abort(
- req->private_data, struct rpc_cli_smbd_conn_init_state);
+ struct rpc_cli_smbd_conn_init_state *state = tevent_req_data(
+ req, struct rpc_cli_smbd_conn_init_state);
NTSTATUS status;
- if (async_req_is_nterror(req, &status)) {
+ if (tevent_req_is_nterror(req, &status)) {
return status;
}
*pconn = talloc_move(mem_ctx, &state->conn);
@@ -402,7 +393,7 @@ NTSTATUS rpc_cli_smbd_conn_init(TALLOC_CTX *mem_ctx,
{
TALLOC_CTX *frame = talloc_stackframe();
struct event_context *ev;
- struct async_req *req;
+ struct tevent_req *req;
NTSTATUS status;
ev = event_context_init(frame);
@@ -417,8 +408,9 @@ NTSTATUS rpc_cli_smbd_conn_init(TALLOC_CTX *mem_ctx,
goto fail;
}
- while (req->state < ASYNC_REQ_DONE) {
- event_loop_once(ev);
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
}
status = rpc_cli_smbd_conn_init_recv(req, mem_ctx, pconn);
@@ -456,7 +448,7 @@ static struct tevent_req *rpc_smbd_write_send(TALLOC_CTX *mem_ctx,
goto fail;
}
- if (event_add_fd(ev, subreq, transp->conn->stdout_fd, EVENT_FD_READ,
+ if (event_add_fd(ev, state, transp->conn->stdout_fd, EVENT_FD_READ,
rpc_cli_smbd_stdout_reader, transp->conn) == NULL) {
goto fail;
}
@@ -527,7 +519,7 @@ static struct tevent_req *rpc_smbd_read_send(TALLOC_CTX *mem_ctx,
goto fail;
}
- if (event_add_fd(ev, subreq, transp->conn->stdout_fd, EVENT_FD_READ,
+ if (event_add_fd(ev, state, transp->conn->stdout_fd, EVENT_FD_READ,
rpc_cli_smbd_stdout_reader, transp->conn) == NULL) {
goto fail;
}
@@ -573,53 +565,55 @@ struct rpc_transport_smbd_init_state {
struct rpc_transport_smbd_state *transport_smbd;
};
-static void rpc_transport_smbd_init_done(struct async_req *subreq);
+static void rpc_transport_smbd_init_done(struct tevent_req *subreq);
-struct async_req *rpc_transport_smbd_init_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct rpc_cli_smbd_conn *conn,
- const struct ndr_syntax_id *abstract_syntax)
+struct tevent_req *rpc_transport_smbd_init_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct rpc_cli_smbd_conn *conn,
+ const struct ndr_syntax_id *abstract_syntax)
{
- struct async_req *result, *subreq;
+ struct tevent_req *req, *subreq;
struct rpc_transport_smbd_init_state *state;
- if (!async_req_setup(mem_ctx, &result, &state,
- struct rpc_transport_smbd_init_state)) {
+ req = tevent_req_create(mem_ctx, &state,
+ struct rpc_transport_smbd_init_state);
+ if (req == NULL) {
return NULL;
}
state->transport = talloc(state, struct rpc_cli_transport);
- if (state->transport == NULL) {
- goto fail;
+ if (tevent_req_nomem(state->transport, req)) {
+ return tevent_req_post(req, ev);
}
state->transport_smbd = talloc(state->transport,
struct rpc_transport_smbd_state);
- if (state->transport_smbd == NULL) {
- goto fail;
+ if (tevent_req_nomem(state->transport_smbd, req)) {
+ return tevent_req_post(req, ev);
}
state->transport_smbd->conn = conn;
state->transport->priv = state->transport_smbd;
+ if (event_add_fd(ev, state, conn->stdout_fd, EVENT_FD_READ,
+ rpc_cli_smbd_stdout_reader, conn) == NULL) {
+ tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
+ return tevent_req_post(req, ev);
+ }
+
subreq = rpc_transport_np_init_send(state, ev, conn->cli,
abstract_syntax);
- if (subreq == NULL) {
- goto fail;
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
}
- subreq->async.fn = rpc_transport_smbd_init_done;
- subreq->async.priv = result;
- return result;
-
- fail:
- TALLOC_FREE(result);
- return NULL;
+ tevent_req_set_callback(subreq, rpc_transport_smbd_init_done, req);
+ return req;
}
-static void rpc_transport_smbd_init_done(struct async_req *subreq)
+static void rpc_transport_smbd_init_done(struct tevent_req *subreq)
{
- struct async_req *req = talloc_get_type_abort(
- subreq->async.priv, struct async_req);
- struct rpc_transport_smbd_init_state *state = talloc_get_type_abort(
- req->private_data, struct rpc_transport_smbd_init_state);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct rpc_transport_smbd_init_state *state = tevent_req_data(
+ req, struct rpc_transport_smbd_init_state);
NTSTATUS status;
status = rpc_transport_np_init_recv(
@@ -627,21 +621,21 @@ static void rpc_transport_smbd_init_done(struct async_req *subreq)
&state->transport_smbd->sub_transp);
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
- async_req_nterror(req, status);
+ tevent_req_nterror(req, status);
return;
}
- async_req_done(req);
+ tevent_req_done(req);
}
-NTSTATUS rpc_transport_smbd_init_recv(struct async_req *req,
+NTSTATUS rpc_transport_smbd_init_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
struct rpc_cli_transport **presult)
{
- struct rpc_transport_smbd_init_state *state = talloc_get_type_abort(
- req->private_data, struct rpc_transport_smbd_init_state);
+ struct rpc_transport_smbd_init_state *state = tevent_req_data(
+ req, struct rpc_transport_smbd_init_state);
NTSTATUS status;
- if (async_req_is_nterror(req, &status)) {
+ if (tevent_req_is_nterror(req, &status)) {
return status;
}
@@ -663,7 +657,7 @@ NTSTATUS rpc_transport_smbd_init(TALLOC_CTX *mem_ctx,
{
TALLOC_CTX *frame = talloc_stackframe();
struct event_context *ev;
- struct async_req *req;
+ struct tevent_req *req;
NTSTATUS status;
ev = event_context_init(frame);
@@ -678,8 +672,9 @@ NTSTATUS rpc_transport_smbd_init(TALLOC_CTX *mem_ctx,
goto fail;
}
- while (req->state < ASYNC_REQ_DONE) {
- event_loop_once(ev);
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
}
status = rpc_transport_smbd_init_recv(req, mem_ctx, presult);
diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c
index 94732b0a74..dfbd6dac74 100644
--- a/source3/rpc_parse/parse_prs.c
+++ b/source3/rpc_parse/parse_prs.c
@@ -1048,44 +1048,6 @@ bool prs_uint32s(bool charmode, const char *name, prs_struct *ps, int depth, uin
return True;
}
-/******************************************************************
- Stream a unicode string, length/buffer specified separately,
- in uint16 chars. The unicode string is already in little-endian format.
- ********************************************************************/
-
-bool prs_unistr2(bool charmode, const char *name, prs_struct *ps, int depth, UNISTR2 *str)
-{
- char *p;
- char *q = prs_mem_get(ps, str->uni_str_len * sizeof(uint16));
- if (q == NULL)
- return False;
-
- /* If the string is empty, we don't have anything to stream */
- if (str->uni_str_len==0)
- return True;
-
- if (UNMARSHALLING(ps)) {
- if (str->uni_str_len > str->uni_max_len) {
- return False;
- }
- if (str->uni_max_len) {
- str->buffer = PRS_ALLOC_MEM(ps,uint16,str->uni_max_len);
- if (str->buffer == NULL)
- return False;
- } else {
- str->buffer = NULL;
- }
- }
-
- p = (char *)str->buffer;
-
- dbg_rw_punival(charmode, name, depth, ps, q, p, str->uni_str_len);
-
- ps->data_offset += (str->uni_str_len * sizeof(uint16));
-
- return True;
-}
-
/*******************************************************************
Stream a unicode null-terminated string. As the string is already
in little-endian format then do it as a stream of bytes.
diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c
index 5fdcaf2d4a..0ce2b40f65 100644
--- a/source3/rpc_server/srv_lsa_nt.c
+++ b/source3/rpc_server/srv_lsa_nt.c
@@ -648,14 +648,14 @@ NTSTATUS _lsa_QueryInfoPolicy(pipes_struct *p,
* only a BDC is a backup controller
* of the domain, it controls.
*/
- info->role.role = 2;
+ info->role.role = LSA_ROLE_BACKUP;
break;
default:
/*
* any other role is a primary
* of the domain, it controls.
*/
- info->role.role = 3;
+ info->role.role = LSA_ROLE_PRIMARY;
break;
}
break;
@@ -1434,14 +1434,14 @@ NTSTATUS _lsa_EnumAccounts(pipes_struct *p,
sids = TALLOC_ZERO_ARRAY(p->mem_ctx, struct lsa_SidPtr,
num_entries - *r->in.resume_handle);
if (!sids) {
- SAFE_FREE(sid_list);
+ talloc_free(sid_list);
return NT_STATUS_NO_MEMORY;
}
for (i = *r->in.resume_handle, j = 0; i < num_entries; i++, j++) {
sids[j].sid = sid_dup_talloc(p->mem_ctx, &sid_list[i]);
if (!sids[j].sid) {
- SAFE_FREE(sid_list);
+ talloc_free(sid_list);
return NT_STATUS_NO_MEMORY;
}
}
diff --git a/source3/rpc_server/srv_ntsvcs_nt.c b/source3/rpc_server/srv_ntsvcs_nt.c
index 681c543c24..7b8dc93a6e 100644
--- a/source3/rpc_server/srv_ntsvcs_nt.c
+++ b/source3/rpc_server/srv_ntsvcs_nt.c
@@ -3,6 +3,7 @@
* RPC Pipe client / server routines
*
* Copyright (C) Gerald (Jerry) Carter 2005.
+ * Copyright (C) Guenther Deschner 2008,2009.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -50,8 +51,9 @@ WERROR _PNP_GetDeviceListSize(pipes_struct *p,
{
char *devicepath;
- if (!r->in.devicename) {
- return WERR_ACCESS_DENIED;
+ if ((r->in.flags & CM_GETIDLIST_FILTER_SERVICE) &&
+ (!r->in.devicename)) {
+ return WERR_CM_INVALID_POINTER;
}
if (!(devicepath = get_device_path(p->mem_ctx, r->in.devicename))) {
@@ -74,13 +76,14 @@ WERROR _PNP_GetDeviceList(pipes_struct *p,
{
char *devicepath;
uint32_t size = 0;
+ char **multi_sz = NULL;
+ size_t multi_sz_len;
+ uint16_t *multi_sz_buf;
- DATA_BLOB blob;
- struct lsa_StringLarge s;
- enum ndr_err_code ndr_err;
-
- if ( !r->in.filter )
- return WERR_ACCESS_DENIED;
+ if ((r->in.flags & CM_GETIDLIST_FILTER_SERVICE) &&
+ (!r->in.filter)) {
+ return WERR_CM_INVALID_POINTER;
+ }
if (!(devicepath = get_device_path(p->mem_ctx, r->in.filter))) {
return WERR_NOMEM;
@@ -92,20 +95,24 @@ WERROR _PNP_GetDeviceList(pipes_struct *p,
return WERR_CM_BUFFER_SMALL;
}
- s.string = r->in.filter;
-
- /* This has to be DOUBLE NULL terminated */
- ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, NULL, &s,
- (ndr_push_flags_fn_t)ndr_push_lsa_StringLarge);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- return ntstatus_to_werror(ndr_map_error2ntstatus(ndr_err));
+ multi_sz = talloc_zero_array(p->mem_ctx, char *, 2);
+ if (!multi_sz) {
+ return WERR_NOMEM;
}
- r->out.buffer = (uint16_t *)talloc_memdup(p->mem_ctx, blob.data, blob.length);
- if (!r->out.buffer) {
+ multi_sz[0] = devicepath;
+
+ multi_sz_len = regval_build_multi_sz(multi_sz, &multi_sz_buf);
+ if (!multi_sz_len) {
return WERR_NOMEM;
}
+ if (*r->in.length < multi_sz_len/2) {
+ return WERR_CM_BUFFER_SMALL;
+ }
+
+ memcpy(r->out.buffer, multi_sz_buf, multi_sz_len);
+
return WERR_OK;
}
diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c
index c60d904b18..7881ca62ea 100644
--- a/source3/rpc_server/srv_samr_nt.c
+++ b/source3/rpc_server/srv_samr_nt.c
@@ -3245,6 +3245,9 @@ NTSTATUS _samr_Connect2(pipes_struct *p,
case NDR_SAMR_CONNECT2:
fn = "_samr_Connect2";
break;
+ case NDR_SAMR_CONNECT3:
+ fn = "_samr_Connect3";
+ break;
case NDR_SAMR_CONNECT4:
fn = "_samr_Connect4";
break;
@@ -3289,6 +3292,22 @@ NTSTATUS _samr_Connect2(pipes_struct *p,
return nt_status;
}
+/****************************************************************
+ _samr_Connect3
+****************************************************************/
+
+NTSTATUS _samr_Connect3(pipes_struct *p,
+ struct samr_Connect3 *r)
+{
+ struct samr_Connect2 c;
+
+ c.in.system_name = r->in.system_name;
+ c.in.access_mask = r->in.access_mask;
+ c.out.connect_handle = r->out.connect_handle;
+
+ return _samr_Connect2(p, &c);
+}
+
/*******************************************************************
_samr_Connect4
********************************************************************/
@@ -3667,8 +3686,9 @@ static bool set_user_info_20(struct samr_UserInfo20 *id20,
set_user_info_21
********************************************************************/
-static NTSTATUS set_user_info_21(TALLOC_CTX *mem_ctx,
- struct samr_UserInfo21 *id21,
+static NTSTATUS set_user_info_21(struct samr_UserInfo21 *id21,
+ TALLOC_CTX *mem_ctx,
+ DATA_BLOB *session_key,
struct samu *pwd)
{
NTSTATUS status;
@@ -3686,6 +3706,52 @@ static NTSTATUS set_user_info_21(TALLOC_CTX *mem_ctx,
return NT_STATUS_ACCESS_DENIED;
}
+ if (id21->fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
+ if (id21->nt_password_set) {
+ DATA_BLOB in, out;
+
+ if ((id21->nt_owf_password.length != 16) ||
+ (id21->nt_owf_password.size != 16)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (!session_key->length) {
+ return NT_STATUS_NO_USER_SESSION_KEY;
+ }
+
+ in = data_blob_const(id21->nt_owf_password.array, 16);
+ out = data_blob_talloc_zero(mem_ctx, 16);
+
+ sess_crypt_blob(&out, &in, session_key, false);
+
+ pdb_set_nt_passwd(pwd, out.data, PDB_CHANGED);
+ pdb_set_pass_last_set_time(pwd, time(NULL), PDB_CHANGED);
+ }
+ }
+
+ if (id21->fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
+ if (id21->lm_password_set) {
+ DATA_BLOB in, out;
+
+ if ((id21->lm_owf_password.length != 16) ||
+ (id21->lm_owf_password.size != 16)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (!session_key->length) {
+ return NT_STATUS_NO_USER_SESSION_KEY;
+ }
+
+ in = data_blob_const(id21->lm_owf_password.array, 16);
+ out = data_blob_talloc_zero(mem_ctx, 16);
+
+ sess_crypt_blob(&out, &in, session_key, false);
+
+ pdb_set_lanman_passwd(pwd, out.data, PDB_CHANGED);
+ pdb_set_pass_last_set_time(pwd, time(NULL), PDB_CHANGED);
+ }
+ }
+
/* we need to separately check for an account rename first */
if (id21->account_name.string &&
@@ -4147,8 +4213,10 @@ NTSTATUS _samr_SetUserInfo(pipes_struct *p,
break;
case 21:
- status = set_user_info_21(p->mem_ctx,
- &info->info21, pwd);
+ status = set_user_info_21(&info->info21,
+ p->mem_ctx,
+ &p->server_info->user_session_key,
+ pwd);
break;
case 23:
@@ -5852,16 +5920,6 @@ NTSTATUS _samr_GetBootKeyInformation(pipes_struct *p,
/****************************************************************
****************************************************************/
-NTSTATUS _samr_Connect3(pipes_struct *p,
- struct samr_Connect3 *r)
-{
- p->rng_fault_state = true;
- return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-/****************************************************************
-****************************************************************/
-
NTSTATUS _samr_RidToSid(pipes_struct *p,
struct samr_RidToSid *r)
{
diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c
index 15c137a88c..098e59216b 100644
--- a/source3/rpc_server/srv_spoolss_nt.c
+++ b/source3/rpc_server/srv_spoolss_nt.c
@@ -445,7 +445,7 @@ static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
aprinter++;
}
} else {
- servername = "";
+ servername = global_myname();
}
/* save the servername to fill in replies on this handle */
@@ -4890,6 +4890,174 @@ static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
}
/********************************************************************
+ ********************************************************************/
+
+static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
+ struct spoolss_DriverFileInfo *r,
+ const char *cservername,
+ const char *file_name,
+ enum spoolss_DriverFileType file_type,
+ uint32_t file_version)
+{
+ r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
+ cservername, file_name);
+ W_ERROR_HAVE_NO_MEMORY(r->file_name);
+ r->file_type = file_type;
+ r->file_version = file_version;
+
+ return WERR_OK;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
+ const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
+ const char *cservername,
+ struct spoolss_DriverFileInfo **info_p,
+ uint32_t *count_p)
+{
+ struct spoolss_DriverFileInfo *info = NULL;
+ uint32_t count = 0;
+ WERROR result;
+ uint32_t i;
+
+ *info_p = NULL;
+ *count_p = 0;
+
+ if (strlen(driver->info_3->driverpath)) {
+ info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
+ struct spoolss_DriverFileInfo,
+ count + 1);
+ W_ERROR_HAVE_NO_MEMORY(info);
+ result = fill_spoolss_DriverFileInfo(info,
+ &info[count],
+ cservername,
+ driver->info_3->driverpath,
+ SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
+ 0);
+ W_ERROR_NOT_OK_RETURN(result);
+ count++;
+ }
+
+ if (strlen(driver->info_3->configfile)) {
+ info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
+ struct spoolss_DriverFileInfo,
+ count + 1);
+ W_ERROR_HAVE_NO_MEMORY(info);
+ result = fill_spoolss_DriverFileInfo(info,
+ &info[count],
+ cservername,
+ driver->info_3->configfile,
+ SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
+ 0);
+ W_ERROR_NOT_OK_RETURN(result);
+ count++;
+ }
+
+ if (strlen(driver->info_3->datafile)) {
+ info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
+ struct spoolss_DriverFileInfo,
+ count + 1);
+ W_ERROR_HAVE_NO_MEMORY(info);
+ result = fill_spoolss_DriverFileInfo(info,
+ &info[count],
+ cservername,
+ driver->info_3->datafile,
+ SPOOLSS_DRIVER_FILE_TYPE_DATA,
+ 0);
+ W_ERROR_NOT_OK_RETURN(result);
+ count++;
+ }
+
+ if (strlen(driver->info_3->helpfile)) {
+ info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
+ struct spoolss_DriverFileInfo,
+ count + 1);
+ W_ERROR_HAVE_NO_MEMORY(info);
+ result = fill_spoolss_DriverFileInfo(info,
+ &info[count],
+ cservername,
+ driver->info_3->helpfile,
+ SPOOLSS_DRIVER_FILE_TYPE_HELP,
+ 0);
+ W_ERROR_NOT_OK_RETURN(result);
+ count++;
+ }
+
+ for (i=0; driver->info_3->dependentfiles[i][0] != '\0'; i++) {
+ info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
+ struct spoolss_DriverFileInfo,
+ count + 1);
+ W_ERROR_HAVE_NO_MEMORY(info);
+ result = fill_spoolss_DriverFileInfo(info,
+ &info[count],
+ cservername,
+ driver->info_3->dependentfiles[i],
+ SPOOLSS_DRIVER_FILE_TYPE_OTHER,
+ 0);
+ W_ERROR_NOT_OK_RETURN(result);
+ count++;
+ }
+
+ *info_p = info;
+ *count_p = count;
+
+ return WERR_OK;
+}
+
+/********************************************************************
+ * fill a spoolss_DriverInfo101 sttruct
+ ********************************************************************/
+
+static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
+ struct spoolss_DriverInfo101 *r,
+ const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
+ const char *servername)
+{
+ const char *cservername = canon_servername(servername);
+ WERROR result;
+
+ r->version = driver->info_3->cversion;
+
+ r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
+ W_ERROR_HAVE_NO_MEMORY(r->driver_name);
+ r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
+ W_ERROR_HAVE_NO_MEMORY(r->architecture);
+
+ result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
+ cservername,
+ &r->file_info,
+ &r->file_count);
+ if (!W_ERROR_IS_OK(result)) {
+ return result;
+ }
+
+ r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
+ W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
+
+ r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
+ W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
+
+ r->previous_names = string_array_from_driver_info(mem_ctx,
+ NULL,
+ cservername);
+ r->driver_date = 0;
+ r->driver_version = 0;
+
+ r->manufacturer_name = talloc_strdup(mem_ctx, "");
+ W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
+ r->manufacturer_url = talloc_strdup(mem_ctx, "");
+ W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
+ r->hardware_id = talloc_strdup(mem_ctx, "");
+ W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
+ r->provider = talloc_strdup(mem_ctx, "");
+ W_ERROR_HAVE_NO_MEMORY(r->provider);
+
+ return WERR_OK;
+}
+
+/********************************************************************
* construct_printer_driver_info_1
********************************************************************/
@@ -5077,6 +5245,69 @@ static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
return status;
}
+/********************************************************************
+ * construct_printer_info_101
+ * fill a printer_info_101 struct
+ ********************************************************************/
+
+static WERROR construct_printer_driver_info_101(TALLOC_CTX *mem_ctx,
+ struct spoolss_DriverInfo101 *r,
+ int snum,
+ const char *servername,
+ const char *architecture,
+ uint32_t version)
+{
+ NT_PRINTER_INFO_LEVEL *printer = NULL;
+ NT_PRINTER_DRIVER_INFO_LEVEL driver;
+ WERROR result;
+
+ ZERO_STRUCT(driver);
+
+ result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
+
+ DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
+ win_errstr(result)));
+
+ if (!W_ERROR_IS_OK(result)) {
+ return WERR_INVALID_PRINTER_NAME;
+ }
+
+ result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
+ architecture, version);
+
+ DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
+ win_errstr(result)));
+
+ if (!W_ERROR_IS_OK(result)) {
+ /*
+ * Is this a W2k client ?
+ */
+
+ if (version < 3) {
+ free_a_printer(&printer, 2);
+ return WERR_UNKNOWN_PRINTER_DRIVER;
+ }
+
+ /* Yes - try again with a WinNT driver. */
+ version = 2;
+ result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
+ architecture, version);
+ DEBUG(8,("construct_printer_driver_info_6: status: %s\n",
+ win_errstr(result)));
+ if (!W_ERROR_IS_OK(result)) {
+ free_a_printer(&printer, 2);
+ return WERR_UNKNOWN_PRINTER_DRIVER;
+ }
+ }
+
+ result = fill_printer_driver_info101(mem_ctx, r, &driver, servername);
+
+ free_a_printer(&printer, 2);
+ free_a_printer_driver(driver, 3);
+
+ return result;
+}
+
/****************************************************************
_spoolss_GetPrinterDriver2
****************************************************************/
@@ -5146,13 +5377,15 @@ WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
r->in.architecture,
r->in.client_major_version);
break;
- default:
-#if 0 /* JERRY */
case 101:
- /* apparently this call is the equivalent of
- EnumPrinterDataEx() for the DsDriver key */
+ result = construct_printer_driver_info_101(p->mem_ctx,
+ &r->out.info->info101,
+ snum,
+ servername,
+ r->in.architecture,
+ r->in.client_major_version);
break;
-#endif
+ default:
result = WERR_UNKNOWN_LEVEL;
break;
}
diff --git a/source3/rpc_server/srv_svcctl_nt.c b/source3/rpc_server/srv_svcctl_nt.c
index 3ca85aa755..0b0ef83bee 100644
--- a/source3/rpc_server/srv_svcctl_nt.c
+++ b/source3/rpc_server/srv_svcctl_nt.c
@@ -32,8 +32,6 @@ struct service_control_op {
SERVICE_CONTROL_OPS *ops;
};
-#define SVCCTL_NUM_INTERNAL_SERVICES 4
-
/* handle external services */
extern SERVICE_CONTROL_OPS rcinit_svc_ops;
@@ -446,7 +444,7 @@ WERROR _svcctl_EnumServicesStatusW(pipes_struct *p,
buffer_size += buffer_size % 4;
- if (buffer_size > r->in.buf_size ) {
+ if (buffer_size > r->in.offered) {
num_services = 0;
result = WERR_MORE_DATA;
}
@@ -468,10 +466,10 @@ WERROR _svcctl_EnumServicesStatusW(pipes_struct *p,
}
blob = ndr_push_blob(ndr);
+ memcpy(r->out.service, blob.data, r->in.offered);
}
- r->out.service = blob.data;
- *r->out.bytes_needed = (buffer_size > r->in.buf_size) ? buffer_size : r->in.buf_size;
+ *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
*r->out.services_returned = (uint32)num_services;
*r->out.resume_handle = 0x0;
@@ -548,11 +546,20 @@ WERROR _svcctl_EnumDependentServicesW(pipes_struct *p,
if ( !(info->access_granted & SC_RIGHT_SVC_ENUMERATE_DEPENDENTS) )
return WERR_ACCESS_DENIED;
+ switch (r->in.state) {
+ case SERVICE_STATE_ACTIVE:
+ case SERVICE_STATE_INACTIVE:
+ case SERVICE_STATE_ALL:
+ break;
+ default:
+ return WERR_INVALID_PARAM;
+ }
+
/* we have to set the outgoing buffer size to the same as the
incoming buffer size (even in the case of failure */
/* this is done in the autogenerated server already - gd */
- *r->out.bytes_needed = r->in.buf_size;
+ *r->out.needed = r->in.offered;
/* no dependent services...basically a stub function */
*r->out.services_returned = 0;
@@ -580,7 +587,7 @@ WERROR _svcctl_QueryServiceStatusEx(pipes_struct *p,
/* we have to set the outgoing buffer size to the same as the
incoming buffer size (even in the case of failure) */
- *r->out.bytes_needed = r->in.buf_size;
+ *r->out.needed = r->in.offered;
switch ( r->in.info_level ) {
case SVC_STATUS_PROCESS_INFO:
@@ -612,9 +619,9 @@ WERROR _svcctl_QueryServiceStatusEx(pipes_struct *p,
buffer_size += buffer_size % 4;
- *r->out.bytes_needed = (buffer_size > r->in.buf_size) ? buffer_size : r->in.buf_size;
+ *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
- if (buffer_size > r->in.buf_size ) {
+ if (buffer_size > r->in.offered ) {
return WERR_INSUFFICIENT_BUFFER;
}
@@ -697,7 +704,7 @@ WERROR _svcctl_QueryServiceConfigW(pipes_struct *p,
/* we have to set the outgoing buffer size to the same as the
incoming buffer size (even in the case of failure */
- *r->out.bytes_needed = r->in.buf_size;
+ *r->out.needed = r->in.offered;
wresult = fill_svc_config( p->mem_ctx, info->name, r->out.query,
p->server_info->ptok);
@@ -705,9 +712,9 @@ WERROR _svcctl_QueryServiceConfigW(pipes_struct *p,
return wresult;
buffer_size = ndr_size_QUERY_SERVICE_CONFIG(r->out.query, NULL, 0);
- *r->out.bytes_needed = (buffer_size > r->in.buf_size) ? buffer_size : r->in.buf_size;
+ *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
- if (buffer_size > r->in.buf_size ) {
+ if (buffer_size > r->in.offered ) {
ZERO_STRUCTP(r->out.query);
return WERR_INSUFFICIENT_BUFFER;
}
@@ -735,7 +742,7 @@ WERROR _svcctl_QueryServiceConfig2W(pipes_struct *p,
/* we have to set the outgoing buffer size to the same as the
incoming buffer size (even in the case of failure */
- *r->out.bytes_needed = r->in.buf_size;
+ *r->out.needed = r->in.offered;
switch ( r->in.info_level ) {
case SERVICE_CONFIG_DESCRIPTION:
@@ -792,9 +799,9 @@ WERROR _svcctl_QueryServiceConfig2W(pipes_struct *p,
}
buffer_size += buffer_size % 4;
- *r->out.bytes_needed = (buffer_size > r->in.buf_size) ? buffer_size : r->in.buf_size;
+ *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
- if (buffer_size > r->in.buf_size )
+ if (buffer_size > r->in.offered)
return WERR_INSUFFICIENT_BUFFER;
return WERR_OK;
@@ -874,8 +881,7 @@ WERROR _svcctl_QueryServiceObjectSecurity(pipes_struct *p,
*r->out.needed = ndr_size_security_descriptor( sec_desc, NULL, 0 );
- if ( *r->out.needed > r->in.buffer_size ) {
- ZERO_STRUCTP( &r->out.buffer );
+ if ( *r->out.needed > r->in.offered) {
return WERR_INSUFFICIENT_BUFFER;
}
@@ -934,7 +940,8 @@ WERROR _svcctl_SetServiceObjectSecurity(pipes_struct *p,
/* read the security descfriptor */
status = unmarshall_sec_desc(p->mem_ctx,
- r->in.buffer, r->in.buffer_size,
+ r->in.buffer,
+ r->in.offered,
&sec_desc);
if (!NT_STATUS_IS_OK(status)) {
return ntstatus_to_werror(status);
diff --git a/source3/rpc_server/srv_util.c b/source3/rpc_server/srv_util.c
deleted file mode 100644
index b276e75faa..0000000000
--- a/source3/rpc_server/srv_util.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- * RPC Pipe client / server routines
- * Copyright (C) Andrew Tridgell 1992-1998
- * Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
- * Copyright (C) Paul Ashton 1997-1998,
- * Copyright (C) Andrew Bartlett 2004.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* this module apparently provides an implementation of DCE/RPC over a
- * named pipe (IPC$ connection using SMBtrans). details of DCE/RPC
- * documentation are available (in on-line form) from the X-Open group.
- *
- * this module should provide a level of abstraction between SMB
- * and DCE/RPC, while minimising the amount of mallocs, unnecessary
- * data copies, and network traffic.
- *
- * in this version, which takes a "let's learn what's going on and
- * get something running" approach, there is additional network
- * traffic generated, but the code should be easier to understand...
- *
- * ... if you read the docs. or stare at packets for weeks on end.
- *
- */
-
-#include "includes.h"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_RPC_SRV
-
-#if 0 /* these aren't used currently but are here if you need them */
-
-typedef struct {
- uint32 rid;
- const char *name;
-} rid_name;
-
-/*
- * A list of the rids of well known BUILTIN and Domain users
- * and groups.
- */
-
-static const rid_name builtin_alias_rids[] =
-{
- { BUILTIN_ALIAS_RID_ADMINS , "Administrators" },
- { BUILTIN_ALIAS_RID_USERS , "Users" },
- { BUILTIN_ALIAS_RID_GUESTS , "Guests" },
- { BUILTIN_ALIAS_RID_POWER_USERS , "Power Users" },
-
- { BUILTIN_ALIAS_RID_ACCOUNT_OPS , "Account Operators" },
- { BUILTIN_ALIAS_RID_SYSTEM_OPS , "System Operators" },
- { BUILTIN_ALIAS_RID_PRINT_OPS , "Print Operators" },
- { BUILTIN_ALIAS_RID_BACKUP_OPS , "Backup Operators" },
- { BUILTIN_ALIAS_RID_REPLICATOR , "Replicator" },
- { 0 , NULL }
-};
-
-/* array lookup of well-known Domain RID users. */
-static const rid_name domain_user_rids[] =
-{
- { DOMAIN_USER_RID_ADMIN , "Administrator" },
- { DOMAIN_USER_RID_GUEST , "Guest" },
- { 0 , NULL }
-};
-
-/* array lookup of well-known Domain RID groups. */
-static const rid_name domain_group_rids[] =
-{
- { DOMAIN_GROUP_RID_ADMINS , "Domain Admins" },
- { DOMAIN_GROUP_RID_USERS , "Domain Users" },
- { DOMAIN_GROUP_RID_GUESTS , "Domain Guests" },
- { 0 , NULL }
-};
-#endif
-
diff --git a/source3/rpcclient/cmd_ntsvcs.c b/source3/rpcclient/cmd_ntsvcs.c
index eb620d06b2..a345cdc8bf 100644
--- a/source3/rpcclient/cmd_ntsvcs.c
+++ b/source3/rpcclient/cmd_ntsvcs.c
@@ -235,17 +235,21 @@ static WERROR cmd_ntsvcs_get_dev_list(struct rpc_pipe_client *cli,
uint32_t length = 0;
uint32_t flags = 0;
- if (argc > 3) {
- printf("usage: %s [length] [filter]\n", argv[0]);
+ if (argc > 4) {
+ printf("usage: %s [filter] [length] [flags]\n", argv[0]);
return WERR_OK;
}
if (argc >= 2) {
- length = atoi(argv[1]);
+ filter = argv[1];
}
if (argc >= 3) {
- filter = argv[2];
+ length = atoi(argv[2]);
+ }
+
+ if (argc >= 4) {
+ flags = atoi(argv[3]);
}
buffer = talloc(mem_ctx, uint16_t);
diff --git a/source3/script/tests/selftest.sh b/source3/script/tests/selftest.sh
index a430d01a0e..60b71a5adc 100755
--- a/source3/script/tests/selftest.sh
+++ b/source3/script/tests/selftest.sh
@@ -268,6 +268,7 @@ EOF
##
cat >$NSS_WRAPPER_PASSWD<<EOF
+root:x:65533:65532:root gecos:$PREFIX_ABS:/bin/false
nobody:x:65534:65533:nobody gecos:$PREFIX_ABS:/bin/false
$USERNAME:x:$USERID:$GROUPID:$USERNAME gecos:$PREFIX_ABS:/bin/false
EOF
@@ -282,7 +283,7 @@ MAKE_TEST_BINARY="bin/smbpasswd"
export MAKE_TEST_BINARY
(echo $PASSWORD; echo $PASSWORD) | \
- bin/smbpasswd -c $CONFFILE -L -s -a $USERNAME >/dev/null || exit 1
+ bin/smbpasswd -c $SERVERCONFFILE -L -s -a $USERNAME >/dev/null || exit 1
echo "DONE";
diff --git a/source3/script/tests/test_posix_s3.sh b/source3/script/tests/test_posix_s3.sh
index 0885b139bb..b3a66e1db7 100755
--- a/source3/script/tests/test_posix_s3.sh
+++ b/source3/script/tests/test_posix_s3.sh
@@ -40,6 +40,7 @@ raw="$raw RAW-SAMBA3ROOTDIRFID"
rpc="RPC-AUTHCONTEXT RPC-BINDSAMBA3 RPC-SAMBA3-SRVSVC RPC-SAMBA3-SHARESEC"
rpc="$rpc RPC-SAMBA3-SPOOLSS RPC-SAMBA3-WKSSVC"
rpc="$rpc RPC-NETLOGSAMBA3 RPC-SAMBA3SESSIONKEY RPC-SAMBA3-GETUSERNAME"
+rpc="$rpc RPC-SVCCTL RPC-SPOOLSS-WIN RPC-NTSVCS"
# NOTE: to enable the UNIX-WHOAMI test, we need to change the default share
# config to allow guest access. I'm not sure whether this would break other
diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c
index d39aab4f47..2d5713590d 100644
--- a/source3/smbd/ipc.c
+++ b/source3/smbd/ipc.c
@@ -754,6 +754,8 @@ void reply_trans(struct smb_request *req)
return;
}
+ talloc_steal(talloc_tos(), state);
+
handle_trans(conn, req, state);
SAFE_FREE(state->data);
@@ -852,6 +854,8 @@ void reply_transs(struct smb_request *req)
return;
}
+ talloc_steal(talloc_tos(), state);
+
handle_trans(conn, req, state);
DLIST_REMOVE(conn->pending_trans, state);
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index ce00397bbd..b937e8e07d 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -344,6 +344,54 @@ static void add_oplock_timeout_handler(files_struct *fsp)
}
}
+void break_level2_to_none_async(files_struct *fsp)
+{
+ char *break_msg;
+
+ if (fsp->oplock_type == NO_OPLOCK) {
+ /* We already got a "break to none" message and we've handled
+ * it. just ignore. */
+ DEBUG(3, ("process_oplock_async_level2_break_message: already "
+ "broken to none, ignoring.\n"));
+ return;
+ }
+
+ if (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK) {
+ /* Don't tell the client, just downgrade. */
+ DEBUG(3, ("process_oplock_async_level2_break_message: "
+ "downgrading fake level 2 oplock.\n"));
+ remove_oplock(fsp);
+ return;
+ }
+
+ /* Ensure we're really at level2 state. */
+ SMB_ASSERT(fsp->oplock_type == LEVEL_II_OPLOCK);
+
+ DEBUG(10,("process_oplock_async_level2_break_message: sending break "
+ "to none message for fid %d, file %s\n", fsp->fnum,
+ fsp->fsp_name));
+
+ /* Now send a break to none message to our client. */
+ break_msg = new_break_smb_message(NULL, fsp, OPLOCKLEVEL_NONE);
+ if (break_msg == NULL) {
+ exit_server("Could not talloc break_msg\n");
+ }
+
+ show_msg(break_msg);
+ if (!srv_send_smb(smbd_server_fd(),
+ break_msg, false, 0,
+ IS_CONN_ENCRYPTED(fsp->conn),
+ NULL)) {
+ exit_server_cleanly("oplock_break: srv_send_smb failed.");
+ }
+
+ TALLOC_FREE(break_msg);
+
+ /* Async level2 request, don't send a reply, just remove the oplock. */
+ remove_oplock(fsp);
+
+}
+
/*******************************************************************
This handles the case of a write triggering a break to none
message on a level2 oplock.
@@ -360,7 +408,6 @@ void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx
{
struct share_mode_entry msg;
files_struct *fsp;
- char *break_msg;
if (data->data == NULL) {
DEBUG(0, ("Got NULL buffer\n"));
@@ -375,8 +422,9 @@ void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx
/* De-linearize incoming message. */
message_to_share_mode_entry(&msg, (char *)data->data);
- DEBUG(10, ("Got oplock async level 2 break message from pid %d: %s/%lu\n",
- (int)procid_to_pid(&src), file_id_string_tos(&msg.id), msg.share_file_id));
+ DEBUG(10, ("Got oplock async level 2 break message from pid %s: "
+ "%s/%lu\n", procid_str(debug_ctx(), &src),
+ file_id_string_tos(&msg.id), msg.share_file_id));
fsp = initial_break_processing(msg.id, msg.share_file_id);
@@ -388,52 +436,7 @@ void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx
return;
}
- if (fsp->oplock_type == NO_OPLOCK) {
- /* We already got a "break to none" message and we've handled it.
- * just ignore. */
- DEBUG(3, ("process_oplock_async_level2_break_message: already broken to none, ignoring.\n"));
- return;
- }
-
- if (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK) {
- /* Don't tell the client, just downgrade. */
- DEBUG(3, ("process_oplock_async_level2_break_message: downgrading fake level 2 oplock.\n"));
- remove_oplock(fsp);
- return;
- }
-
- /* Ensure we're really at level2 state. */
- SMB_ASSERT(fsp->oplock_type == LEVEL_II_OPLOCK);
-
- DEBUG(10,("process_oplock_async_level2_break_message: sending break to "
- "none message for fid %d, file %s\n",
- fsp->fnum,
- fsp->fsp_name));
-
- /* Now send a break to none message to our client. */
-
- break_msg = new_break_smb_message(NULL, fsp, OPLOCKLEVEL_NONE);
- if (break_msg == NULL) {
- exit_server("Could not talloc break_msg\n");
- }
-
- /* Need to wait before sending a break message if we sent ourselves this message. */
- if (procid_to_pid(&src) == sys_getpid()) {
- wait_before_sending_break();
- }
-
- show_msg(break_msg);
- if (!srv_send_smb(smbd_server_fd(),
- break_msg, false, 0,
- IS_CONN_ENCRYPTED(fsp->conn),
- NULL)) {
- exit_server_cleanly("oplock_break: srv_send_smb failed.");
- }
-
- TALLOC_FREE(break_msg);
-
- /* Async level2 request, don't send a reply, just remove the oplock. */
- remove_oplock(fsp);
+ break_level2_to_none_async(fsp);
}
/*******************************************************************
@@ -464,8 +467,9 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
/* De-linearize incoming message. */
message_to_share_mode_entry(&msg, (char *)data->data);
- DEBUG(10, ("Got oplock break message from pid %d: %s/%lu\n",
- (int)procid_to_pid(&src), file_id_string_tos(&msg.id), msg.share_file_id));
+ DEBUG(10, ("Got oplock break message from pid %s: %s/%lu\n",
+ procid_str(debug_ctx(), &src), file_id_string_tos(&msg.id),
+ msg.share_file_id));
fsp = initial_break_processing(msg.id, msg.share_file_id);
@@ -518,7 +522,7 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
}
/* Need to wait before sending a break message if we sent ourselves this message. */
- if (procid_to_pid(&src) == sys_getpid()) {
+ if (procid_is_me(&src)) {
wait_before_sending_break();
}
@@ -571,8 +575,8 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx,
pull_file_id_24((char *)data->data, &id);
file_id = (unsigned long)IVAL(data->data, 24);
- DEBUG(10, ("Got kernel oplock break message from pid %d: %s/%u\n",
- (int)procid_to_pid(&src), file_id_string_tos(&id),
+ DEBUG(10, ("Got kernel oplock break message from pid %s: %s/%u\n",
+ procid_str(debug_ctx(), &src), file_id_string_tos(&id),
(unsigned int)file_id));
fsp = initial_break_processing(id, file_id);
@@ -667,9 +671,9 @@ static void process_oplock_break_response(struct messaging_context *msg_ctx,
/* De-linearize incoming message. */
message_to_share_mode_entry(&msg, (char *)data->data);
- DEBUG(10, ("Got oplock break response from pid %d: %s/%lu mid %u\n",
- (int)procid_to_pid(&src), file_id_string_tos(&msg.id), msg.share_file_id,
- (unsigned int)msg.op_mid));
+ DEBUG(10, ("Got oplock break response from pid %s: %s/%lu mid %u\n",
+ procid_str(debug_ctx(), &src), file_id_string_tos(&msg.id),
+ msg.share_file_id, (unsigned int)msg.op_mid));
/* Here's the hack from open.c, store the mid in the 'port' field */
schedule_deferred_open_smb_message(msg.op_mid);
@@ -696,8 +700,8 @@ static void process_open_retry_message(struct messaging_context *msg_ctx,
/* De-linearize incoming message. */
message_to_share_mode_entry(&msg, (char *)data->data);
- DEBUG(10, ("Got open retry msg from pid %d: %s mid %u\n",
- (int)procid_to_pid(&src), file_id_string_tos(&msg.id),
+ DEBUG(10, ("Got open retry msg from pid %s: %s mid %u\n",
+ procid_str(debug_ctx(), &src), file_id_string_tos(&msg.id),
(unsigned int)msg.op_mid));
schedule_deferred_open_smb_message(msg.op_mid);
@@ -788,13 +792,8 @@ static void contend_level2_oplocks_begin_default(files_struct *fsp,
*/
if (procid_is_me(&share_entry->pid)) {
- DATA_BLOB blob = data_blob_const(msg,
- MSG_SMB_SHARE_MODE_ENTRY_SIZE);
- process_oplock_async_level2_break_message(smbd_messaging_context(),
- NULL,
- MSG_SMB_ASYNC_LEVEL2_BREAK,
- share_entry->pid,
- &blob);
+ wait_before_sending_break();
+ break_level2_to_none_async(fsp);
} else {
messaging_send_buf(smbd_messaging_context(),
share_entry->pid,
diff --git a/source3/smbd/oplock_onefs.c b/source3/smbd/oplock_onefs.c
index d4f181fc47..b69d937915 100644
--- a/source3/smbd/oplock_onefs.c
+++ b/source3/smbd/oplock_onefs.c
@@ -550,87 +550,18 @@ static void onefs_semlock_write(int fd, enum level2_contention_type type,
* the cluster except the fsp's own level 2 oplock. This lack of
* self-contention is a limitation of the current OneFS kernel oplocks
* implementation. Luckily it is easy to contend our own level 2 oplock by
- * iterating the share mode entries and only breaking the oplock if the pid
- * matches our's.
+ * checking the the fsp's oplock_type. If it's a level2, send a break message
+ * to the client and remove the oplock.
*/
static void onefs_contend_level2_oplocks_begin(files_struct *fsp,
enum level2_contention_type type)
{
- int i;
- struct share_mode_lock *lck;
-
/* Take care of level 2 kernel contention. */
onefs_semlock_write(fsp->fh->fd, type, SEMLOCK_LOCK);
- /*
- * If this file is level II oplocked then we need
- * to grab the shared memory lock and inform all
- * other files with a level II lock that they need
- * to flush their read caches. We keep the lock over
- * the shared memory area whilst doing this.
- */
-
- if (!LEVEL_II_OPLOCK_TYPE(fsp->oplock_type))
- return;
-
- lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
- NULL);
- if (lck == NULL) {
- DEBUG(0,("onefs_contend_level2_oplocks_begin: failed to lock "
- "share mode entry for file %s.\n", fsp->fsp_name ));
- return;
- }
-
- DEBUG(10,("onefs_contend_level2_oplocks_begin: num_share_modes = %d\n",
- lck->num_share_modes ));
-
- for(i = 0; i < lck->num_share_modes; i++) {
- struct share_mode_entry *share_entry = &lck->share_modes[i];
- char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
-
- if (!is_valid_share_mode_entry(share_entry)) {
- continue;
- }
-
- DEBUG(10,("onefs_contend_level2_oplocks_begin: "
- "share_entry[%i]->op_type == %d\n",
- i, share_entry->op_type ));
-
- if (share_entry->op_type == NO_OPLOCK) {
- continue;
- }
-
- /* Paranoia .... */
- if (EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) {
- DEBUG(0,("onefs_contend_level2_oplocks_begin: PANIC. "
- "share mode entry %d is an exlusive "
- "oplock !\n", i ));
- TALLOC_FREE(lck);
- abort();
- }
-
- share_mode_entry_to_message(msg, share_entry);
-
- /*
- * Only contend our own level 2 oplock. The other processes
- * will be get break events from the kernel.
- */
- if (procid_is_me(&share_entry->pid)) {
- DATA_BLOB blob = data_blob_const(msg,
- MSG_SMB_SHARE_MODE_ENTRY_SIZE);
- process_oplock_async_level2_break_message(
- smbd_messaging_context(),
- NULL,
- MSG_SMB_ASYNC_LEVEL2_BREAK,
- share_entry->pid,
- &blob);
- }
- }
-
- /* We let the message receivers handle removing the oplock state
- in the share mode lock db. */
-
- TALLOC_FREE(lck);
+ /* Take care of level 2 self contention. */
+ if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type))
+ break_level2_to_none_async(fsp);
}
/**
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index e8878a29ab..d524f21817 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -333,7 +333,6 @@ static void reply_spnego_kerberos(struct smb_request *req,
DEBUG(3,("Doesn't look like a valid principal\n"));
data_blob_free(&ap_rep);
data_blob_free(&session_key);
- SAFE_FREE(client);
talloc_destroy(mem_ctx);
reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
return;
@@ -355,7 +354,6 @@ static void reply_spnego_kerberos(struct smb_request *req,
if (!lp_allow_trusted_domains()) {
data_blob_free(&ap_rep);
data_blob_free(&session_key);
- SAFE_FREE(client);
talloc_destroy(mem_ctx);
reply_nterror(req, nt_status_squash(
NT_STATUS_LOGON_FAILURE));
@@ -445,7 +443,6 @@ static void reply_spnego_kerberos(struct smb_request *req,
if ( !pw ) {
DEBUG(1,("Username %s is invalid on this system\n",
user));
- SAFE_FREE(client);
data_blob_free(&ap_rep);
data_blob_free(&session_key);
TALLOC_FREE(mem_ctx);
@@ -471,7 +468,6 @@ static void reply_spnego_kerberos(struct smb_request *req,
if ( !NT_STATUS_IS_OK(ret) ) {
DEBUG(1,("make_server_info_info3 failed: %s!\n",
nt_errstr(ret)));
- SAFE_FREE(client);
data_blob_free(&ap_rep);
data_blob_free(&session_key);
TALLOC_FREE(mem_ctx);
@@ -485,7 +481,6 @@ static void reply_spnego_kerberos(struct smb_request *req,
if ( !NT_STATUS_IS_OK(ret) ) {
DEBUG(1,("make_server_info_pw failed: %s!\n",
nt_errstr(ret)));
- SAFE_FREE(client);
data_blob_free(&ap_rep);
data_blob_free(&session_key);
TALLOC_FREE(mem_ctx);
@@ -513,7 +508,6 @@ static void reply_spnego_kerberos(struct smb_request *req,
if ( !NT_STATUS_IS_OK(ret) ) {
DEBUG(10,("failed to create local token: %s\n",
nt_errstr(ret)));
- SAFE_FREE(client);
data_blob_free(&ap_rep);
data_blob_free(&session_key);
TALLOC_FREE( mem_ctx );
@@ -541,8 +535,6 @@ static void reply_spnego_kerberos(struct smb_request *req,
nullblob,
client);
- SAFE_FREE(client);
-
reply_outbuf(req, 4, 0);
SSVAL(req->outbuf,smb_uid,sess_vuid);
diff --git a/source3/torture/t_push_ucs2.c b/source3/torture/t_push_ucs2.c
index b9bf87ba54..2bd91dafde 100644
--- a/source3/torture/t_push_ucs2.c
+++ b/source3/torture/t_push_ucs2.c
@@ -14,16 +14,16 @@ static int check_push_ucs2(const char *orig)
int ret;
size_t converted_size;
- push_ucs2_allocate(&dest, orig, &converted_size);
- pull_ucs2_allocate(&orig2, dest, &converted_size);
+ push_ucs2_talloc(NULL, &dest, orig, &converted_size);
+ pull_ucs2_talloc(NULL, &orig2, dest, &converted_size);
ret = strcmp(orig, orig2);
if (ret) {
fprintf(stderr, "orig: %s\n", orig);
fprintf(stderr, "orig (UNIX -> UCS2 -> UNIX): %s\n", orig2);
}
- SAFE_FREE(dest);
- SAFE_FREE(orig2);
+ TALLOC_FREE(dest);
+ TALLOC_FREE(orig2);
return ret;
}
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index 1b9e394a68..804e772516 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -273,6 +273,10 @@ static bool torture_open_connection_share(struct cli_state **c,
if (use_kerberos)
flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
+ if (use_oplocks)
+ flags |= CLI_FULL_CONNECTION_OPLOCKS;
+ if (use_level_II_oplocks)
+ flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
status = cli_full_connection(c, myname,
hostname, NULL, port_to_use,
@@ -285,8 +289,6 @@ static bool torture_open_connection_share(struct cli_state **c,
return False;
}
- if (use_oplocks) (*c)->use_oplocks = True;
- if (use_level_II_oplocks) (*c)->use_level_II_oplocks = True;
(*c)->timeout = 120000; /* set a really long timeout (2 minutes) */
if (do_encrypt) {
@@ -5023,11 +5025,10 @@ static bool subst_test(const char *str, const char *user, const char *domain,
return result;
}
-static void chain1_open_completion(struct async_req *req)
+static void chain1_open_completion(struct tevent_req *req)
{
int fnum;
NTSTATUS status;
-
status = cli_open_recv(req, &fnum);
TALLOC_FREE(req);
@@ -5036,48 +5037,25 @@ static void chain1_open_completion(struct async_req *req)
NT_STATUS_IS_OK(status) ? fnum : -1);
}
-static void chain1_read_completion(struct async_req *req)
+static void chain1_write_completion(struct tevent_req *req)
{
- NTSTATUS status;
- ssize_t received;
- uint8_t *rcvbuf;
-
- status = cli_read_andx_recv(req, &received, &rcvbuf);
- if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(req);
- d_printf("cli_read_andx_recv returned %s\n",
- nt_errstr(status));
- return;
- }
-
- d_printf("got %d bytes: %.*s\n", (int)received, (int)received,
- (char *)rcvbuf);
- TALLOC_FREE(req);
-}
-
-static void chain1_write_completion(struct async_req *req)
-{
- NTSTATUS status;
size_t written;
-
+ NTSTATUS status;
status = cli_write_andx_recv(req, &written);
- if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(req);
- d_printf("cli_write_andx_recv returned %s\n",
- nt_errstr(status));
- return;
- }
-
- d_printf("wrote %d bytes\n", (int)written);
TALLOC_FREE(req);
+
+ d_printf("cli_write_andx_recv returned %s: %d\n",
+ nt_errstr(status),
+ NT_STATUS_IS_OK(status) ? (int)written : -1);
}
-static void chain1_close_completion(struct async_req *req)
+static void chain1_close_completion(struct tevent_req *req)
{
NTSTATUS status;
+ bool *done = (bool *)tevent_req_callback_data_void(req);
status = cli_close_recv(req);
- *((bool *)(req->async.priv)) = true;
+ *done = true;
TALLOC_FREE(req);
@@ -5088,9 +5066,9 @@ static bool run_chain1(int dummy)
{
struct cli_state *cli1;
struct event_context *evt = event_context_init(NULL);
- struct async_req *reqs[4];
+ struct tevent_req *reqs[3], *smbreqs[3];
bool done = false;
- const char *text = "hallo";
+ const char *str = "foobar";
printf("starting chain1 test\n");
if (!torture_open_connection(&cli1, 0)) {
@@ -5099,19 +5077,25 @@ static bool run_chain1(int dummy)
cli_sockopt(cli1, sockops);
- cli_chain_cork(cli1, evt, 0);
- reqs[0] = cli_open_send(talloc_tos(), evt, cli1, "\\test",
- O_CREAT|O_RDWR, 0);
- reqs[0]->async.fn = chain1_open_completion;
- reqs[1] = cli_write_andx_send(talloc_tos(), evt, cli1, 0, 0,
- (uint8_t *)text, 0, strlen(text));
- reqs[1]->async.fn = chain1_write_completion;
- reqs[2] = cli_read_andx_send(talloc_tos(), evt, cli1, 0, 1, 10);
- reqs[2]->async.fn = chain1_read_completion;
- reqs[3] = cli_close_send(talloc_tos(), evt, cli1, 0);
- reqs[3]->async.fn = chain1_close_completion;
- reqs[3]->async.priv = (void *)&done;
- cli_chain_uncork(cli1);
+ reqs[0] = cli_open_create(talloc_tos(), evt, cli1, "\\test",
+ O_CREAT|O_RDWR, 0, &smbreqs[0]);
+ if (reqs[0] == NULL) return false;
+ tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
+
+
+ reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
+ (uint8_t *)str, 0, strlen(str)+1,
+ smbreqs, 1, &smbreqs[1]);
+ if (reqs[1] == NULL) return false;
+ tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
+
+ reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
+ if (reqs[2] == NULL) return false;
+ tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
+
+ if (!cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs))) {
+ return false;
+ }
while (!done) {
event_loop_once(evt);
@@ -5199,8 +5183,6 @@ static bool run_windows_write(int dummy)
static bool run_cli_echo(int dummy)
{
struct cli_state *cli;
- struct event_context *ev = event_context_init(NULL);
- struct async_req *req;
NTSTATUS status;
printf("starting cli_echo test\n");
@@ -5209,21 +5191,10 @@ static bool run_cli_echo(int dummy)
}
cli_sockopt(cli, sockops);
- req = cli_echo_send(ev, ev, cli, 5, data_blob_const("hello", 5));
- if (req == NULL) {
- d_printf("cli_echo_send failed\n");
- return false;
- }
-
- while (req->state < ASYNC_REQ_DONE) {
- event_loop_once(ev);
- }
+ status = cli_echo(cli, 5, data_blob_const("hello", 5));
- status = cli_echo_recv(req);
d_printf("cli_echo returned %s\n", nt_errstr(status));
- TALLOC_FREE(req);
-
torture_close_connection(cli);
return NT_STATUS_IS_OK(status);
}
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index 2a66619438..8e927becbe 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -503,9 +503,9 @@ static int ads_user_add(struct net_context *c, int argc, const char **argv)
ads_msgfree(ads, res);
status=ads_find_user_acct(ads, &res, argv[0]);
if (ADS_ERR_OK(status)) {
- userdn = ads_get_dn(ads, res);
+ userdn = ads_get_dn(ads, talloc_tos(), res);
ads_del_dn(ads, userdn);
- ads_memfree(ads, userdn);
+ TALLOC_FREE(userdn);
}
done:
@@ -598,10 +598,10 @@ static int ads_user_delete(struct net_context *c, int argc, const char **argv)
ads_destroy(&ads);
return -1;
}
- userdn = ads_get_dn(ads, res);
+ userdn = ads_get_dn(ads, talloc_tos(), res);
ads_msgfree(ads, res);
rc = ads_del_dn(ads, userdn);
- ads_memfree(ads, userdn);
+ TALLOC_FREE(userdn);
if (ADS_ERR_OK(rc)) {
d_printf("User %s deleted\n", argv[0]);
ads_destroy(&ads);
@@ -757,10 +757,10 @@ static int ads_group_delete(struct net_context *c, int argc, const char **argv)
ads_destroy(&ads);
return -1;
}
- groupdn = ads_get_dn(ads, res);
+ groupdn = ads_get_dn(ads, talloc_tos(), res);
ads_msgfree(ads, res);
rc = ads_del_dn(ads, groupdn);
- ads_memfree(ads, groupdn);
+ TALLOC_FREE(groupdn);
if (ADS_ERR_OK(rc)) {
d_printf("Group %s deleted\n", argv[0]);
ads_destroy(&ads);
@@ -1740,10 +1740,10 @@ static int net_ads_printer_remove(struct net_context *c, int argc, const char **
return -1;
}
- prt_dn = ads_get_dn(ads, res);
+ prt_dn = ads_get_dn(ads, talloc_tos(), res);
ads_msgfree(ads, res);
rc = ads_del_dn(ads, prt_dn);
- ads_memfree(ads, prt_dn);
+ TALLOC_FREE(prt_dn);
if (!ADS_ERR_OK(rc)) {
d_fprintf(stderr, "ads_del_dn: %s\n", ads_errstr(rc));
diff --git a/source3/utils/net_ads_gpo.c b/source3/utils/net_ads_gpo.c
index 181cba221d..910c78d05a 100644
--- a/source3/utils/net_ads_gpo.c
+++ b/source3/utils/net_ads_gpo.c
@@ -257,7 +257,7 @@ static int net_ads_gpo_list_all(struct net_context *c, int argc, const char **ar
msg;
msg = ads_next_entry(ads, msg)) {
- if ((dn = ads_get_dn(ads, msg)) == NULL) {
+ if ((dn = ads_get_dn(ads, mem_ctx, msg)) == NULL) {
goto out;
}
@@ -266,18 +266,16 @@ static int net_ads_gpo_list_all(struct net_context *c, int argc, const char **ar
if (!ADS_ERR_OK(status)) {
d_printf("ads_parse_gpo failed: %s\n",
ads_errstr(status));
- ads_memfree(ads, dn);
goto out;
}
dump_gpo(ads, mem_ctx, &gpo, 0);
- ads_memfree(ads, dn);
}
out:
ads_msgfree(ads, res);
- talloc_destroy(mem_ctx);
+ TALLOC_FREE(mem_ctx);
ads_destroy(&ads);
return 0;
diff --git a/source3/utils/net_eventlog.c b/source3/utils/net_eventlog.c
index 197a7cd330..b86be6d48b 100644
--- a/source3/utils/net_eventlog.c
+++ b/source3/utils/net_eventlog.c
@@ -182,13 +182,9 @@ static int net_eventlog_export(struct net_context *c, int argc,
int ret = -1;
NTSTATUS status;
TALLOC_CTX *ctx = talloc_stackframe();
- enum ndr_err_code ndr_err;
DATA_BLOB blob;
uint32_t num_records = 0;
- struct EVENTLOG_EVT_FILE evt;
ELOG_TDB *etdb = NULL;
- uint32_t count = 1;
- size_t endoffset = 0;
if (argc < 2 || c->display_usage) {
d_fprintf(stderr, "usage: net eventlog export <file> <eventlog>\n");
@@ -201,54 +197,8 @@ static int net_eventlog_export(struct net_context *c, int argc,
goto done;
}
- ZERO_STRUCT(evt);
-
- while (1) {
-
- struct eventlog_Record_tdb *r;
- struct EVENTLOGRECORD e;
-
- r = evlog_pull_record_tdb(ctx, etdb->tdb, count);
- if (!r) {
- break;
- }
-
- status = evlog_tdb_entry_to_evt_entry(ctx, r, &e);
- if (!NT_STATUS_IS_OK(status)) {
- goto done;
- }
-
- endoffset += ndr_size_EVENTLOGRECORD(&e, NULL, 0);
-
- ADD_TO_ARRAY(ctx, struct EVENTLOGRECORD, e, &evt.records, &num_records);
- count++;
- }
-
- evt.hdr.StartOffset = 0x30;
- evt.hdr.EndOffset = evt.hdr.StartOffset + endoffset;
- evt.hdr.CurrentRecordNumber = count;
- evt.hdr.OldestRecordNumber = 1;
- evt.hdr.MaxSize = tdb_fetch_int32(etdb->tdb, EVT_MAXSIZE);
- evt.hdr.Flags = 0;
- evt.hdr.Retention = tdb_fetch_int32(etdb->tdb, EVT_RETENTION);
-
- if (DEBUGLEVEL >= 10) {
- NDR_PRINT_DEBUG(EVENTLOGHEADER, &evt.hdr);
- }
-
- evt.eof.BeginRecord = 0x30;
- evt.eof.EndRecord = evt.hdr.StartOffset + endoffset;
- evt.eof.CurrentRecordNumber = evt.hdr.CurrentRecordNumber;
- evt.eof.OldestRecordNumber = evt.hdr.OldestRecordNumber;
-
- if (DEBUGLEVEL >= 10) {
- NDR_PRINT_DEBUG(EVENTLOGEOF, &evt.eof);
- }
-
- ndr_err = ndr_push_struct_blob(&blob, ctx, NULL, &evt,
- (ndr_push_flags_fn_t)ndr_push_EVENTLOG_EVT_FILE);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- d_fprintf(stderr, "evt push failed: %s\n", ndr_errstr(ndr_err));
+ status = evlog_convert_tdb_to_evt(ctx, etdb, &blob, &num_records);
+ if (!NT_STATUS_IS_OK(status)) {
goto done;
}
diff --git a/source3/utils/net_rpc_service.c b/source3/utils/net_rpc_service.c
index bcb1a00dab..57a721e55b 100644
--- a/source3/utils/net_rpc_service.c
+++ b/source3/utils/net_rpc_service.c
@@ -631,6 +631,161 @@ done:
/********************************************************************
********************************************************************/
+static NTSTATUS rpc_service_delete_internal(struct net_context *c,
+ const DOM_SID *domain_sid,
+ const char *domain_name,
+ struct cli_state *cli,
+ struct rpc_pipe_client *pipe_hnd,
+ TALLOC_CTX *mem_ctx,
+ int argc,
+ const char **argv)
+{
+ struct policy_handle hSCM, hService;
+ WERROR result = WERR_GENERAL_FAILURE;
+ NTSTATUS status;
+
+ if (argc != 1 ) {
+ d_printf("Usage: net rpc service delete <service>\n");
+ return NT_STATUS_OK;
+ }
+
+ /* Open the Service Control Manager */
+ status = rpccli_svcctl_OpenSCManagerW(pipe_hnd, mem_ctx,
+ pipe_hnd->srv_name_slash,
+ NULL,
+ SC_RIGHT_MGR_ENUMERATE_SERVICE,
+ &hSCM,
+ &result);
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
+ d_fprintf(stderr, "Failed to open Service Control Manager. [%s]\n",
+ win_errstr(result));
+ return werror_to_ntstatus(result);
+ }
+
+ /* Open the Service */
+
+ status = rpccli_svcctl_OpenServiceW(pipe_hnd, mem_ctx,
+ &hSCM,
+ argv[0],
+ SERVICE_ALL_ACCESS,
+ &hService,
+ &result);
+
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result) ) {
+ d_fprintf(stderr, "Failed to open service. [%s]\n",
+ win_errstr(result));
+ goto done;
+ }
+
+ /* Delete the Service */
+
+ status = rpccli_svcctl_DeleteService(pipe_hnd, mem_ctx,
+ &hService,
+ &result);
+
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result) ) {
+ d_fprintf(stderr, "Delete service request failed. [%s]\n",
+ win_errstr(result));
+ goto done;
+ }
+
+ d_printf("Successfully deleted Service: %s\n", argv[0]);
+
+ done:
+ if (is_valid_policy_hnd(&hService)) {
+ rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hService, NULL);
+ }
+ if (is_valid_policy_hnd(&hSCM)) {
+ rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hSCM, NULL);
+ }
+
+ return werror_to_ntstatus(result);
+}
+
+/********************************************************************
+********************************************************************/
+
+static NTSTATUS rpc_service_create_internal(struct net_context *c,
+ const DOM_SID *domain_sid,
+ const char *domain_name,
+ struct cli_state *cli,
+ struct rpc_pipe_client *pipe_hnd,
+ TALLOC_CTX *mem_ctx,
+ int argc,
+ const char **argv)
+{
+ struct policy_handle hSCM, hService;
+ WERROR result = WERR_GENERAL_FAILURE;
+ NTSTATUS status;
+ const char *ServiceName;
+ const char *DisplayName;
+ const char *binary_path;
+
+ if (argc != 3) {
+ d_printf("Usage: net rpc service create <service> <displayname> <binarypath>\n");
+ return NT_STATUS_OK;
+ }
+
+ /* Open the Service Control Manager */
+ status = rpccli_svcctl_OpenSCManagerW(pipe_hnd, mem_ctx,
+ pipe_hnd->srv_name_slash,
+ NULL,
+ SC_RIGHT_MGR_CREATE_SERVICE,
+ &hSCM,
+ &result);
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
+ d_fprintf(stderr, "Failed to open Service Control Manager. [%s]\n",
+ win_errstr(result));
+ return werror_to_ntstatus(result);
+ }
+
+ /* Create the service */
+
+ ServiceName = argv[0];
+ DisplayName = argv[1];
+ binary_path = argv[2];
+
+ status = rpccli_svcctl_CreateServiceW(pipe_hnd, mem_ctx,
+ &hSCM,
+ ServiceName,
+ DisplayName,
+ SERVICE_ALL_ACCESS,
+ SERVICE_TYPE_WIN32_OWN_PROCESS,
+ SVCCTL_DEMAND_START,
+ SVCCTL_SVC_ERROR_NORMAL,
+ binary_path,
+ NULL, /* LoadOrderGroupKey */
+ NULL, /* TagId */
+ NULL, /* dependencies */
+ 0, /* dependencies_size */
+ NULL, /* service_start_name */
+ NULL, /* password */
+ 0, /* password_size */
+ &hService,
+ &result);
+
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result) ) {
+ d_fprintf(stderr, "Create service request failed. [%s]\n",
+ win_errstr(result));
+ goto done;
+ }
+
+ d_printf("Successfully created Service: %s\n", argv[0]);
+
+ done:
+ if (is_valid_policy_hnd(&hService)) {
+ rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hService, NULL);
+ }
+ if (is_valid_policy_hnd(&hSCM)) {
+ rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hSCM, NULL);
+ }
+
+ return werror_to_ntstatus(result);
+}
+
+/********************************************************************
+********************************************************************/
+
static int rpc_service_list(struct net_context *c, int argc, const char **argv )
{
if (c->display_usage) {
@@ -727,6 +882,38 @@ static int rpc_service_status(struct net_context *c, int argc, const char **argv
/********************************************************************
********************************************************************/
+static int rpc_service_delete(struct net_context *c, int argc, const char **argv)
+{
+ if (c->display_usage) {
+ d_printf("Usage:\n"
+ "net rpc service delete <service>\n"
+ " Delete a Win32 service\n");
+ return 0;
+ }
+
+ return run_rpc_command(c, NULL, &ndr_table_svcctl.syntax_id, 0,
+ rpc_service_delete_internal, argc, argv);
+}
+
+/********************************************************************
+********************************************************************/
+
+static int rpc_service_create(struct net_context *c, int argc, const char **argv)
+{
+ if (c->display_usage) {
+ d_printf("Usage:\n"
+ "net rpc service create <service>\n"
+ " Create a Win32 service\n");
+ return 0;
+ }
+
+ return run_rpc_command(c, NULL, &ndr_table_svcctl.syntax_id, 0,
+ rpc_service_create_internal, argc, argv);
+}
+
+/********************************************************************
+********************************************************************/
+
int net_rpc_service(struct net_context *c, int argc, const char **argv)
{
struct functable func[] = {
@@ -778,6 +965,23 @@ int net_rpc_service(struct net_context *c, int argc, const char **argv)
"net rpc service status\n"
" View current status of a service"
},
+ {
+ "delete",
+ rpc_service_delete,
+ NET_TRANSPORT_RPC,
+ "Delete a service",
+ "net rpc service delete\n"
+ " Deletes a service"
+ },
+ {
+ "create",
+ rpc_service_create,
+ NET_TRANSPORT_RPC,
+ "Create a service",
+ "net rpc service create\n"
+ " Creates a service"
+ },
+
{NULL, NULL, 0, NULL, NULL}
};
diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c
index 9bc0c60b7b..7899bd0d07 100644
--- a/source3/utils/ntlm_auth.c
+++ b/source3/utils/ntlm_auth.c
@@ -1251,8 +1251,6 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state,
&principal, &pac_data, &ap_rep,
&session_key, True);
- talloc_destroy(mem_ctx);
-
/* Now in "principal" we have the name we are
authenticated as. */
@@ -1274,9 +1272,9 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state,
user = SMB_STRDUP(principal);
data_blob_free(&ap_rep);
-
- SAFE_FREE(principal);
}
+
+ TALLOC_FREE(mem_ctx);
}
#endif
diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c
index a5bc0c9bd4..328b2cb1f4 100644
--- a/source3/utils/pdbedit.c
+++ b/source3/utils/pdbedit.c
@@ -847,13 +847,6 @@ int main (int argc, char **argv)
POPT_TABLEEND
};
- /* we shouldn't have silly checks like this */
- if (getuid() != 0) {
- d_fprintf(stderr, "You must be root to use pdbedit\n");
- TALLOC_FREE(frame);
- return -1;
- }
-
bin = bout = bdef = NULL;
load_case_tables();
diff --git a/source3/winbindd/idmap_adex/gc_util.c b/source3/winbindd/idmap_adex/gc_util.c
index 6dc02336d5..58e641b630 100644
--- a/source3/winbindd/idmap_adex/gc_util.c
+++ b/source3/winbindd/idmap_adex/gc_util.c
@@ -592,11 +592,11 @@ done:
while (e) {
struct winbindd_tdc_domain *domain_rec;
- dn = ads_get_dn(ads, e);
+ dn = ads_get_dn(ads, frame, e);
BAIL_ON_PTR_ERROR(dn, nt_status);
dns_domain = cell_dn_to_dns(dn);
- SAFE_FREE(dn);
+ TALLOC_FREE(dn);
BAIL_ON_PTR_ERROR(dns_domain, nt_status);
domain_rec = wcache_tdc_fetch_domain(frame, dns_domain);
@@ -666,13 +666,13 @@ static NTSTATUS get_object_account_name(ADS_STRUCT *ads,
/* get the name and domain */
- dn = ads_get_dn(ads, msg);
+ dn = ads_get_dn(ads, frame, msg);
BAIL_ON_PTR_ERROR(dn, nt_status);
DEBUG(10,("get_object_account_name: dn = \"%s\"\n", dn));
dns_domain = cell_dn_to_dns(dn);
- SAFE_FREE(dn);
+ TALLOC_FREE(dn);
BAIL_ON_PTR_ERROR(dns_domain, nt_status);
domain_rec = wcache_tdc_fetch_domain(frame, dns_domain);
diff --git a/source3/winbindd/idmap_adex/likewise_cell.c b/source3/winbindd/idmap_adex/likewise_cell.c
index 7723b3e015..d666d8c01a 100644
--- a/source3/winbindd/idmap_adex/likewise_cell.c
+++ b/source3/winbindd/idmap_adex/likewise_cell.c
@@ -400,10 +400,10 @@ done:
e!=NULL;
e = ads_next_entry(c->conn, e))
{
- char *dn = ads_get_dn(c->conn, e);
+ char *dn = ads_get_dn(c->conn, talloc_tos(), e);
DEBUGADD(10,(" dn: %s\n", dn ? dn : "<NULL>"));
- SAFE_FREE(dn);
+ TALLOC_FREE(dn);
}
}
diff --git a/source3/winbindd/idmap_adex/provider_unified.c b/source3/winbindd/idmap_adex/provider_unified.c
index f18534797e..f9d73f5f95 100644
--- a/source3/winbindd/idmap_adex/provider_unified.c
+++ b/source3/winbindd/idmap_adex/provider_unified.c
@@ -368,7 +368,7 @@ static NTSTATUS check_result_unique_scoped(ADS_STRUCT **ads_list,
LDAPMessage *e = ads_first_entry(ads_list[i], msg_list[i]);
while (e) {
- entry_dn = ads_get_dn(ads_list[i], e);
+ entry_dn = ads_get_dn(ads_list[i], talloc_tos(), e);
BAIL_ON_PTR_ERROR(entry_dn, nt_status);
if (check_forest_scope(entry_dn)) {
@@ -389,7 +389,7 @@ static NTSTATUS check_result_unique_scoped(ADS_STRUCT **ads_list,
}
e = ads_next_entry(ads_list[i], e);
- SAFE_FREE(entry_dn);
+ TALLOC_FREE(entry_dn);
}
}
@@ -439,7 +439,7 @@ done:
}
talloc_destroy(frame);
- SAFE_FREE(entry_dn);
+ TALLOC_FREE(entry_dn);
return nt_status;
}
diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c
index a76faa7a25..dcf5623d29 100644
--- a/source3/winbindd/winbindd_ads.c
+++ b/source3/winbindd/winbindd_ads.c
@@ -865,7 +865,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
goto done;
}
- user_dn = ads_get_dn(ads, msg);
+ user_dn = ads_get_dn(ads, mem_ctx, msg);
if (user_dn == NULL) {
status = NT_STATUS_NO_MEMORY;
goto done;
@@ -942,7 +942,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
DEBUG(3,("ads lookup_usergroups (tokenGroups) succeeded for sid=%s\n",
sid_string_dbg(sid)));
done:
- ads_memfree(ads, user_dn);
+ TALLOC_FREE(user_dn);
ads_msgfree(ads, msg);
return status;
}