*/
#include "includes.h"
+#include "events.h"
+#include "dlinklist.h"
+#include "smb_server/smb_server.h"
+
/* we over allocate the data buffer to prevent too many realloc calls */
-#define REQ_OVER_ALLOCATION 256
+#define REQ_OVER_ALLOCATION 0
/* destroy a request structure */
void req_destroy(struct smbsrv_request *req)
{
- /* the request might be marked protected. This is done by the
- * SMBecho code for example */
- if (req->control_flags & REQ_CONTROL_PROTECTED) {
- return;
- }
-
/* ahh, its so nice to destroy a complex structure in such a
* simple way! */
- talloc_destroy(req->mem_ctx);
+ talloc_free(req);
}
/****************************************************************************
struct smbsrv_request *init_smb_request(struct smbsrv_connection *smb_conn)
{
struct smbsrv_request *req;
- TALLOC_CTX *mem_ctx;
-
- /* each request gets its own talloc context. The request
- structure itself is also allocated inside this context, so
- we need to allocate it before we construct the request
- */
- mem_ctx = talloc_init("request_context[%d]", smb_conn->connection->socket->pkt_count);
- if (!mem_ctx) {
- return NULL;
- }
- smb_conn->connection->socket->pkt_count++;
+ smb_conn->pkt_count++;
- req = talloc(mem_ctx, sizeof(*req));
+ req = talloc_p(smb_conn, struct smbsrv_request);
if (!req) {
return NULL;
}
/* setup the request context */
req->smb_conn = smb_conn;
- req->mem_ctx = mem_ctx;
-
+
+ req->async_states = talloc_p(req, struct ntvfs_async_state);
+ if (!req->async_states) {
+ talloc_free(req);
+ return NULL;
+ }
+ req->async_states->state = 0;
+
return req;
}
/* over allocate by a small amount */
req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
- req->out.buffer = talloc_realloc(req->out.buffer, req->out.allocated);
+ req->out.buffer = talloc_realloc(req, req->out.buffer, req->out.allocated);
if (!req->out.buffer) {
smbsrv_terminate_connection(req->smb_conn, "allocation failed");
}
/* over allocate by a small amount */
req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
- req->out.buffer = talloc(req->mem_ctx, req->out.allocated);
+ req->out.buffer = talloc(req, req->out.allocated);
if (!req->out.buffer) {
smbsrv_terminate_connection(req->smb_conn, "allocation failed");
}
}
}
+
+/*
+ setup a copy of a request, used when the server needs to send
+ more than one reply for a single request packet
+*/
+struct smbsrv_request *req_setup_secondary(struct smbsrv_request *old_req)
+{
+ struct smbsrv_request *req;
+ ptrdiff_t diff;
+
+ req = talloc_memdup(old_req, old_req, sizeof(struct smbsrv_request));
+ if (req == NULL) {
+ return NULL;
+ }
+
+ req->out.buffer = talloc_memdup(req, req->out.buffer, req->out.allocated);
+ if (req->out.buffer == NULL) {
+ talloc_free(req);
+ return NULL;
+ }
+
+ diff = req->out.buffer - old_req->out.buffer;
+
+ req->out.hdr += diff;
+ req->out.vwv += diff;
+ req->out.data += diff;
+ req->out.ptr += diff;
+
+ return req;
+}
+
/*
work out the maximum data size we will allow for this reply, given
the negotiated max_xmit. The basic reply packet must be setup before
/* we need to realloc */
req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;
- buf2 = talloc_realloc(req->out.buffer, req->out.allocated);
+ buf2 = talloc_realloc(req, req->out.buffer, req->out.allocated);
if (buf2 == NULL) {
smb_panic("out of memory in req_grow_allocation");
}
_smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
}
- if (write_data(req->smb_conn->connection->socket->fde->fd, req->out.buffer, req->out.size) != req->out.size) {
- smbsrv_terminate_connection(req->smb_conn, "failed to send reply\n");
- }
+ /* add the request to the list of requests that need to be
+ sent to the client, then mark the socket event structure
+ ready for write events */
+ DLIST_ADD_END(req->smb_conn->pending_send, req, struct smbsrv_request *);
- req_destroy(req);
+ req->smb_conn->connection->event.fde->flags |= EVENT_FD_WRITE;
}
/*
dest = req->out.buffer + PTR_DIFF(dest, buf0);
}
- len = push_string(req->out.hdr, dest, str, len, flags);
+ len = push_string(dest, str, len, flags);
grow_size = len + PTR_DIFF(dest, req->out.data);
return the number of bytes added
*/
size_t req_append_bytes(struct smbsrv_request *req,
- const uint8_t *bytes, size_t byte_len)
+ const uint8_t *bytes, size_t byte_len)
{
req_grow_allocation(req, byte_len + req->out.data_size);
memcpy(req->out.data + req->out.data_size, bytes, byte_len);
{
int src_len, src_len2, alignment=0;
ssize_t ret;
+ char *dest2;
if (!(flags & STR_NOALIGN) && ucs2_align(req->in.buffer, src, flags)) {
src++;
}
}
- src_len2 = strnlen_w((const smb_ucs2_t *)src, src_len/2) * 2;
-
- if (src_len2 <= src_len - 2) {
- /* include the termination if we didn't reach the end of the packet */
- src_len2 += 2;
- }
-
- ret = convert_string_talloc(req->mem_ctx, CH_UCS2, CH_UNIX, src, src_len2, (const void **)dest);
+ src_len2 = utf16_len_n(src, src_len);
+ ret = convert_string_talloc(req, CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2);
if (ret == -1) {
*dest = NULL;
return 0;
}
+ *dest = dest2;
return src_len2 + alignment;
}
{
int src_len, src_len2;
ssize_t ret;
+ char *dest2;
if (flags & STR_NO_RANGE_CHECK) {
src_len = byte_len;
src_len2++;
}
- ret = convert_string_talloc(req->mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (const void **)dest);
+ ret = convert_string_talloc(req, CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2);
if (ret == -1) {
*dest = NULL;
return 0;
}
+ *dest = dest2;
return src_len2;
}
if (PTR_DIFF(src, req->in.data) + 1 > req->in.data_size) {
/* win2000 treats this as the NULL string! */
- (*dest) = talloc_strdup(req->mem_ctx, "");
+ (*dest) = talloc_strdup(req, "");
return 0;
}
ret = req_pull_string(req, dest, src, -1, flags);
if (ret == -1) {
- (*dest) = talloc_strdup(req->mem_ctx, "");
+ (*dest) = talloc_strdup(req, "");
return 1;
}
return False;
}
- (*blob) = data_blob_talloc(req->mem_ctx, src, len);
+ (*blob) = data_blob_talloc(req, src, len);
return True;
}