2 Unix SMB/CIFS implementation.
4 Copyright (C) Volker Lendecke 2007
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 struct packet_context
{
25 struct data_blob in
, out
;
29 * Close the underlying fd
31 static int packet_context_destructor(struct packet_context
*ctx
)
33 return close(ctx
->fd
);
37 * Initialize a packet context. The fd is given to the packet context, meaning
38 * that it is automatically closed when the packet context is freed.
40 struct packet_context
*packet_init(TALLOC_CTX
*mem_ctx
, int fd
)
42 struct packet_context
*result
;
44 if (!(result
= TALLOC_ZERO_P(mem_ctx
, struct packet_context
))) {
49 talloc_set_destructor(result
, packet_context_destructor
);
54 * Pull data from the fd
56 NTSTATUS
packet_fd_read(struct packet_context
*ctx
)
62 res
= ioctl(ctx
->fd
, FIONREAD
, &available
);
65 DEBUG(10, ("ioctl(FIONREAD) failed: %s\n", strerror(errno
)));
66 return map_nt_error_from_unix(errno
);
69 SMB_ASSERT(available
>= 0);
72 return NT_STATUS_END_OF_FILE
;
75 new_size
= ctx
->in
.length
+ available
;
77 if (new_size
< ctx
->in
.length
) {
78 DEBUG(0, ("integer wrap\n"));
79 return NT_STATUS_NO_MEMORY
;
82 if (!(in
= TALLOC_REALLOC_ARRAY(ctx
, ctx
->in
.data
, uint8
, new_size
))) {
83 DEBUG(10, ("talloc failed\n"));
84 return NT_STATUS_NO_MEMORY
;
87 res
= recv(ctx
->fd
, in
+ ctx
->in
.length
, available
, 0);
90 DEBUG(10, ("recv failed: %s\n", strerror(errno
)));
91 return map_nt_error_from_unix(errno
);
95 return NT_STATUS_END_OF_FILE
;
99 ctx
->in
.length
+= available
;
104 NTSTATUS
packet_fd_read_sync(struct packet_context
*ctx
)
110 FD_SET(ctx
->fd
, &r_fds
);
112 res
= sys_select(ctx
->fd
+1, &r_fds
, NULL
, NULL
, NULL
);
115 DEBUG(10, ("select returned %s\n", strerror(errno
)));
116 return map_nt_error_from_unix(errno
);
119 return packet_fd_read(ctx
);
122 BOOL
packet_handler(struct packet_context
*ctx
,
123 BOOL (*full_req
)(const struct data_blob
*data
,
126 NTSTATUS (*callback
)(const struct data_blob
*data
,
132 struct data_blob data
;
134 if (!full_req(&ctx
->in
, &length
, private_data
)) {
138 SMB_ASSERT(length
<= ctx
->in
.length
);
140 data
.data
= ctx
->in
.data
;
141 data
.length
= length
;
143 *status
= callback(&data
, private_data
);
145 memmove(ctx
->in
.data
, ctx
->in
.data
+ length
,
146 ctx
->in
.length
- length
);
147 ctx
->in
.length
-= length
;
153 * How many bytes of outgoing data do we have pending?
155 size_t packet_outgoing_bytes(struct packet_context
*ctx
)
157 return ctx
->out
.length
;
161 * Push data to the fd
163 NTSTATUS
packet_fd_write(struct packet_context
*ctx
)
167 sent
= send(ctx
->fd
, ctx
->out
.data
, ctx
->out
.length
, 0);
170 DEBUG(0, ("send failed: %s\n", strerror(errno
)));
171 return map_nt_error_from_unix(errno
);
174 memmove(ctx
->out
.data
, ctx
->out
.data
+ sent
,
175 ctx
->out
.length
- sent
);
176 ctx
->out
.length
-= sent
;
182 * Sync flush all outgoing bytes
184 NTSTATUS
packet_flush(struct packet_context
*ctx
)
186 while (ctx
->out
.length
!= 0) {
187 NTSTATUS status
= packet_fd_write(ctx
);
188 if (!NT_STATUS_IS_OK(status
)) {
196 * Send a list of DATA_BLOBs
198 * Example: packet_send(ctx, 2, data_blob_const(&size, sizeof(size)),
199 * data_blob_const(buf, size));
201 NTSTATUS
packet_send(struct packet_context
*ctx
, int num_blobs
, ...)
208 len
= ctx
->out
.length
;
210 va_start(ap
, num_blobs
);
211 for (i
=0; i
<num_blobs
; i
++) {
213 struct data_blob blob
= va_arg(ap
, struct data_blob
);
215 tmp
= len
+ blob
.length
;
217 DEBUG(0, ("integer overflow\n"));
219 return NT_STATUS_NO_MEMORY
;
229 if (!(out
= TALLOC_REALLOC_ARRAY(ctx
, ctx
->out
.data
, uint8
, len
))) {
230 DEBUG(0, ("talloc failed\n"));
231 return NT_STATUS_NO_MEMORY
;
236 va_start(ap
, num_blobs
);
237 for (i
=0; i
<num_blobs
; i
++) {
238 struct data_blob blob
= va_arg(ap
, struct data_blob
);
240 memcpy(ctx
->out
.data
+ctx
->out
.length
, blob
.data
, blob
.length
);
241 ctx
->out
.length
+= blob
.length
;
245 SMB_ASSERT(ctx
->out
.length
== len
);
250 * Get the packet context's file descriptor
252 int packet_get_fd(struct packet_context
*ctx
)