docs: Improve description of the share commands in man smb.conf.
[Samba/gebeck_regimport.git] / source3 / lib / async_sock.c
blobbb89a1353ae4b21e8b3ccacd88c93c0e93689eda
1 /*
2 Unix SMB/CIFS implementation.
3 async socket syscalls
4 Copyright (C) Volker Lendecke 2008
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 3 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, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
22 /**
23 * Discriminator for async_syscall_state
25 enum async_syscall_type {
26 ASYNC_SYSCALL_SEND,
27 ASYNC_SYSCALL_SENDALL,
28 ASYNC_SYSCALL_RECV,
29 ASYNC_SYSCALL_RECVALL,
30 ASYNC_SYSCALL_CONNECT
33 /**
34 * Holder for syscall arguments and the result
37 struct async_syscall_state {
38 enum async_syscall_type syscall_type;
39 struct fd_event *fde;
41 union {
42 struct param_send {
43 int fd;
44 const void *buffer;
45 size_t length;
46 int flags;
47 } param_send;
48 struct param_sendall {
49 int fd;
50 const void *buffer;
51 size_t length;
52 int flags;
53 size_t sent;
54 } param_sendall;
55 struct param_recv {
56 int fd;
57 void *buffer;
58 size_t length;
59 int flags;
60 } param_recv;
61 struct param_recvall {
62 int fd;
63 void *buffer;
64 size_t length;
65 int flags;
66 size_t received;
67 } param_recvall;
68 struct param_connect {
69 /**
70 * connect needs to be done on a nonblocking
71 * socket. Keep the old flags around
73 long old_sockflags;
74 int fd;
75 const struct sockaddr *address;
76 socklen_t address_len;
77 } param_connect;
78 } param;
80 union {
81 ssize_t result_ssize_t;
82 size_t result_size_t;
83 int result_int;
84 } result;
85 int sys_errno;
88 /**
89 * @brief Create a new async syscall req
90 * @param[in] mem_ctx The memory context to hang the result off
91 * @param[in] ev The event context to work from
92 * @param[in] type Which syscall will this be
93 * @param[in] pstate Where to put the newly created private_data state
94 * @retval The new request
96 * This is a helper function to prepare a new struct async_req with an
97 * associated struct async_syscall_state. The async_syscall_state will be put
98 * into the async_req as private_data.
101 static struct async_req *async_syscall_new(TALLOC_CTX *mem_ctx,
102 struct event_context *ev,
103 enum async_syscall_type type,
104 struct async_syscall_state **pstate)
106 struct async_req *result;
107 struct async_syscall_state *state;
109 result = async_req_new(mem_ctx);
110 if (result == NULL) {
111 return NULL;
114 state = talloc(result, struct async_syscall_state);
115 if (state == NULL) {
116 TALLOC_FREE(result);
117 return NULL;
120 state->syscall_type = type;
122 result->private_data = state;
124 *pstate = state;
126 return result;
130 * @brief Create a new async syscall req based on a fd
131 * @param[in] mem_ctx The memory context to hang the result off
132 * @param[in] ev The event context to work from
133 * @param[in] type Which syscall will this be
134 * @param[in] fd The file descriptor we work on
135 * @param[in] fde_flags EVENT_FD_READ/WRITE -- what are we interested in?
136 * @param[in] fde_cb The callback function for the file descriptor event
137 * @param[in] pstate Where to put the newly created private_data state
138 * @retval The new request
140 * This is a helper function to prepare a new struct async_req with an
141 * associated struct async_syscall_state and an associated file descriptor
142 * event.
145 static struct async_req *async_fde_syscall_new(
146 TALLOC_CTX *mem_ctx,
147 struct event_context *ev,
148 enum async_syscall_type type,
149 int fd,
150 uint16_t fde_flags,
151 void (*fde_cb)(struct event_context *ev,
152 struct fd_event *fde, uint16_t flags,
153 void *priv),
154 struct async_syscall_state **pstate)
156 struct async_req *result;
157 struct async_syscall_state *state;
159 result = async_syscall_new(mem_ctx, ev, type, &state);
160 if (result == NULL) {
161 return NULL;
164 state->fde = event_add_fd(ev, state, fd, fde_flags, fde_cb, result);
165 if (state->fde == NULL) {
166 TALLOC_FREE(result);
167 return NULL;
169 *pstate = state;
170 return result;
174 * Retrieve a ssize_t typed result from an async syscall
175 * @param[in] req The syscall that has just finished
176 * @param[out] perrno Where to put the syscall's errno
177 * @retval The return value from the asynchronously called syscall
180 ssize_t async_syscall_result_ssize_t(struct async_req *req, int *perrno)
182 struct async_syscall_state *state = talloc_get_type_abort(
183 req->private_data, struct async_syscall_state);
185 *perrno = state->sys_errno;
186 return state->result.result_ssize_t;
190 * Retrieve a size_t typed result from an async syscall
191 * @param[in] req The syscall that has just finished
192 * @param[out] perrno Where to put the syscall's errno
193 * @retval The return value from the asynchronously called syscall
196 size_t async_syscall_result_size_t(struct async_req *req, int *perrno)
198 struct async_syscall_state *state = talloc_get_type_abort(
199 req->private_data, struct async_syscall_state);
201 *perrno = state->sys_errno;
202 return state->result.result_size_t;
206 * Retrieve a int typed result from an async syscall
207 * @param[in] req The syscall that has just finished
208 * @param[out] perrno Where to put the syscall's errno
209 * @retval The return value from the asynchronously called syscall
212 int async_syscall_result_int(struct async_req *req, int *perrno)
214 struct async_syscall_state *state = talloc_get_type_abort(
215 req->private_data, struct async_syscall_state);
217 *perrno = state->sys_errno;
218 return state->result.result_int;
222 * fde event handler for the "send" syscall
223 * @param[in] ev The event context that sent us here
224 * @param[in] fde The file descriptor event associated with the send
225 * @param[in] flags Can only be EVENT_FD_WRITE here
226 * @param[in] priv private data, "struct async_req *" in this case
229 static void async_send_callback(struct event_context *ev,
230 struct fd_event *fde, uint16_t flags,
231 void *priv)
233 struct async_req *req = talloc_get_type_abort(
234 priv, struct async_req);
235 struct async_syscall_state *state = talloc_get_type_abort(
236 req->private_data, struct async_syscall_state);
237 struct param_send *p = &state->param.param_send;
239 if (state->syscall_type != ASYNC_SYSCALL_SEND) {
240 async_req_error(req, NT_STATUS_INTERNAL_ERROR);
241 return;
244 state->result.result_ssize_t = send(p->fd, p->buffer, p->length,
245 p->flags);
246 state->sys_errno = errno;
248 TALLOC_FREE(state->fde);
250 async_req_done(req);
254 * Async version of send(2)
255 * @param[in] mem_ctx The memory context to hang the result off
256 * @param[in] ev The event context to work from
257 * @param[in] fd The socket to send to
258 * @param[in] buffer The buffer to send
259 * @param[in] length How many bytes to send
260 * @param[in] flags flags passed to send(2)
262 * This function is a direct counterpart of send(2)
265 struct async_req *async_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
266 int fd, const void *buffer, size_t length,
267 int flags)
269 struct async_req *result;
270 struct async_syscall_state *state;
272 result = async_fde_syscall_new(
273 mem_ctx, ev, ASYNC_SYSCALL_SEND,
274 fd, EVENT_FD_WRITE, async_send_callback,
275 &state);
276 if (result == NULL) {
277 return NULL;
280 state->param.param_send.fd = fd;
281 state->param.param_send.buffer = buffer;
282 state->param.param_send.length = length;
283 state->param.param_send.flags = flags;
285 return result;
289 * fde event handler for the "sendall" syscall group
290 * @param[in] ev The event context that sent us here
291 * @param[in] fde The file descriptor event associated with the send
292 * @param[in] flags Can only be EVENT_FD_WRITE here
293 * @param[in] priv private data, "struct async_req *" in this case
296 static void async_sendall_callback(struct event_context *ev,
297 struct fd_event *fde, uint16_t flags,
298 void *priv)
300 struct async_req *req = talloc_get_type_abort(
301 priv, struct async_req);
302 struct async_syscall_state *state = talloc_get_type_abort(
303 req->private_data, struct async_syscall_state);
304 struct param_sendall *p = &state->param.param_sendall;
306 if (state->syscall_type != ASYNC_SYSCALL_SENDALL) {
307 async_req_error(req, NT_STATUS_INTERNAL_ERROR);
308 return;
311 state->result.result_ssize_t = send(p->fd, (char *)p->buffer + p->sent,
312 p->length - p->sent, p->flags);
313 state->sys_errno = errno;
315 if (state->result.result_ssize_t == -1) {
316 async_req_error(req, map_nt_error_from_unix(state->sys_errno));
317 return;
320 if (state->result.result_ssize_t == 0) {
321 async_req_error(req, NT_STATUS_END_OF_FILE);
322 return;
325 p->sent += state->result.result_ssize_t;
326 if (p->sent > p->length) {
327 async_req_error(req, NT_STATUS_INTERNAL_ERROR);
328 return;
331 if (p->sent == p->length) {
332 TALLOC_FREE(state->fde);
333 async_req_done(req);
338 * @brief Send all bytes to a socket
339 * @param[in] mem_ctx The memory context to hang the result off
340 * @param[in] ev The event context to work from
341 * @param[in] fd The socket to send to
342 * @param[in] buffer The buffer to send
343 * @param[in] length How many bytes to send
344 * @param[in] flags flags passed to send(2)
346 * async_sendall calls send(2) as long as it is necessary to send all of the
347 * "length" bytes
350 struct async_req *sendall_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
351 int fd, const void *buffer, size_t length,
352 int flags)
354 struct async_req *result;
355 struct async_syscall_state *state;
357 result = async_fde_syscall_new(
358 mem_ctx, ev, ASYNC_SYSCALL_SENDALL,
359 fd, EVENT_FD_WRITE, async_sendall_callback,
360 &state);
361 if (result == NULL) {
362 return NULL;
365 state->param.param_sendall.fd = fd;
366 state->param.param_sendall.buffer = buffer;
367 state->param.param_sendall.length = length;
368 state->param.param_sendall.flags = flags;
369 state->param.param_sendall.sent = 0;
371 return result;
374 NTSTATUS sendall_recv(struct async_req *req)
376 return async_req_simple_recv(req);
380 * fde event handler for the "recv" syscall
381 * @param[in] ev The event context that sent us here
382 * @param[in] fde The file descriptor event associated with the recv
383 * @param[in] flags Can only be EVENT_FD_READ here
384 * @param[in] priv private data, "struct async_req *" in this case
387 static void async_recv_callback(struct event_context *ev,
388 struct fd_event *fde, uint16_t flags,
389 void *priv)
391 struct async_req *req = talloc_get_type_abort(
392 priv, struct async_req);
393 struct async_syscall_state *state = talloc_get_type_abort(
394 req->private_data, struct async_syscall_state);
395 struct param_recv *p = &state->param.param_recv;
397 if (state->syscall_type != ASYNC_SYSCALL_RECV) {
398 async_req_error(req, NT_STATUS_INTERNAL_ERROR);
399 return;
402 state->result.result_ssize_t = recv(p->fd, p->buffer, p->length,
403 p->flags);
404 state->sys_errno = errno;
406 TALLOC_FREE(state->fde);
408 async_req_done(req);
412 * Async version of recv(2)
413 * @param[in] mem_ctx The memory context to hang the result off
414 * @param[in] ev The event context to work from
415 * @param[in] fd The socket to recv from
416 * @param[in] buffer The buffer to recv into
417 * @param[in] length How many bytes to recv
418 * @param[in] flags flags passed to recv(2)
420 * This function is a direct counterpart of recv(2)
423 struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct event_context *ev,
424 int fd, void *buffer, size_t length,
425 int flags)
427 struct async_req *result;
428 struct async_syscall_state *state;
430 result = async_fde_syscall_new(
431 mem_ctx, ev, ASYNC_SYSCALL_RECV,
432 fd, EVENT_FD_READ, async_recv_callback,
433 &state);
435 if (result == NULL) {
436 return NULL;
439 state->param.param_recv.fd = fd;
440 state->param.param_recv.buffer = buffer;
441 state->param.param_recv.length = length;
442 state->param.param_recv.flags = flags;
444 return result;
448 * fde event handler for the "recvall" syscall group
449 * @param[in] ev The event context that sent us here
450 * @param[in] fde The file descriptor event associated with the recv
451 * @param[in] flags Can only be EVENT_FD_READ here
452 * @param[in] priv private data, "struct async_req *" in this case
455 static void async_recvall_callback(struct event_context *ev,
456 struct fd_event *fde, uint16_t flags,
457 void *priv)
459 struct async_req *req = talloc_get_type_abort(
460 priv, struct async_req);
461 struct async_syscall_state *state = talloc_get_type_abort(
462 req->private_data, struct async_syscall_state);
463 struct param_recvall *p = &state->param.param_recvall;
465 if (state->syscall_type != ASYNC_SYSCALL_RECVALL) {
466 async_req_error(req, NT_STATUS_INTERNAL_ERROR);
467 return;
470 state->result.result_ssize_t = recv(p->fd,
471 (char *)p->buffer + p->received,
472 p->length - p->received, p->flags);
473 state->sys_errno = errno;
475 if (state->result.result_ssize_t == -1) {
476 async_req_error(req, map_nt_error_from_unix(state->sys_errno));
477 return;
480 if (state->result.result_ssize_t == 0) {
481 async_req_error(req, NT_STATUS_END_OF_FILE);
482 return;
485 p->received += state->result.result_ssize_t;
486 if (p->received > p->length) {
487 async_req_error(req, NT_STATUS_INTERNAL_ERROR);
488 return;
491 if (p->received == p->length) {
492 TALLOC_FREE(state->fde);
493 async_req_done(req);
498 * Receive a specified number of bytes from a socket
499 * @param[in] mem_ctx The memory context to hang the result off
500 * @param[in] ev The event context to work from
501 * @param[in] fd The socket to recv from
502 * @param[in] buffer The buffer to recv into
503 * @param[in] length How many bytes to recv
504 * @param[in] flags flags passed to recv(2)
506 * async_recvall will call recv(2) until "length" bytes are received
509 struct async_req *recvall_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
510 int fd, void *buffer, size_t length,
511 int flags)
513 struct async_req *result;
514 struct async_syscall_state *state;
516 result = async_fde_syscall_new(
517 mem_ctx, ev, ASYNC_SYSCALL_RECVALL,
518 fd, EVENT_FD_READ, async_recvall_callback,
519 &state);
520 if (result == NULL) {
521 return NULL;
524 state->param.param_recvall.fd = fd;
525 state->param.param_recvall.buffer = buffer;
526 state->param.param_recvall.length = length;
527 state->param.param_recvall.flags = flags;
528 state->param.param_recvall.received = 0;
530 return result;
533 NTSTATUS recvall_recv(struct async_req *req)
535 return async_req_simple_recv(req);
538 struct async_connect_state {
539 int fd;
540 int result;
541 int sys_errno;
542 long old_sockflags;
545 static void async_connect_connected(struct event_context *ev,
546 struct fd_event *fde, uint16_t flags,
547 void *priv);
550 * @brief async version of connect(2)
551 * @param[in] mem_ctx The memory context to hang the result off
552 * @param[in] ev The event context to work from
553 * @param[in] fd The socket to recv from
554 * @param[in] address Where to connect?
555 * @param[in] address_len Length of *address
556 * @retval The async request
558 * This function sets the socket into non-blocking state to be able to call
559 * connect in an async state. This will be reset when the request is finished.
562 struct async_req *async_connect_send(TALLOC_CTX *mem_ctx,
563 struct event_context *ev,
564 int fd, const struct sockaddr *address,
565 socklen_t address_len)
567 struct async_req *result;
568 struct async_connect_state *state;
569 struct fd_event *fde;
570 NTSTATUS status;
572 result = async_req_new(mem_ctx);
573 if (result == NULL) {
574 return NULL;
576 state = talloc(result, struct async_connect_state);
577 if (state == NULL) {
578 goto fail;
580 result->private_data = state;
583 * We have to set the socket to nonblocking for async connect(2). Keep
584 * the old sockflags around.
587 state->fd = fd;
588 state->sys_errno = 0;
590 state->old_sockflags = sys_fcntl_long(fd, F_GETFL, 0);
591 if (state->old_sockflags == -1) {
592 goto post_errno;
595 set_blocking(fd, false);
597 state->result = connect(fd, address, address_len);
598 if (state->result == 0) {
599 state->sys_errno = 0;
600 status = NT_STATUS_OK;
601 goto post_status;
605 * A number of error messages show that something good is progressing
606 * and that we have to wait for readability.
608 * If none of them are present, bail out.
611 if (!(errno == EINPROGRESS || errno == EALREADY ||
612 #ifdef EISCONN
613 errno == EISCONN ||
614 #endif
615 errno == EAGAIN || errno == EINTR)) {
616 goto post_errno;
619 fde = event_add_fd(ev, state, fd, EVENT_FD_READ | EVENT_FD_WRITE,
620 async_connect_connected, result);
621 if (fde == NULL) {
622 status = NT_STATUS_NO_MEMORY;
623 goto post_status;
625 return result;
627 post_errno:
628 state->sys_errno = errno;
629 status = map_nt_error_from_unix(state->sys_errno);
630 post_status:
631 sys_fcntl_long(fd, F_SETFL, state->old_sockflags);
632 if (!async_post_status(result, ev, status)) {
633 goto fail;
635 return result;
636 fail:
637 TALLOC_FREE(result);
638 return NULL;
642 * fde event handler for connect(2)
643 * @param[in] ev The event context that sent us here
644 * @param[in] fde The file descriptor event associated with the connect
645 * @param[in] flags Indicate read/writeability of the socket
646 * @param[in] priv private data, "struct async_req *" in this case
649 static void async_connect_connected(struct event_context *ev,
650 struct fd_event *fde, uint16_t flags,
651 void *priv)
653 struct async_req *req = talloc_get_type_abort(
654 priv, struct async_req);
655 struct async_connect_state *state = talloc_get_type_abort(
656 req->private_data, struct async_connect_state);
658 TALLOC_FREE(fde);
661 * Stevens, Network Programming says that if there's a
662 * successful connect, the socket is only writable. Upon an
663 * error, it's both readable and writable.
665 if ((flags & (EVENT_FD_READ|EVENT_FD_WRITE))
666 == (EVENT_FD_READ|EVENT_FD_WRITE)) {
667 int sockerr;
668 socklen_t err_len = sizeof(sockerr);
670 if (getsockopt(state->fd, SOL_SOCKET, SO_ERROR,
671 (void *)&sockerr, &err_len) == 0) {
672 errno = sockerr;
675 state->sys_errno = errno;
677 DEBUG(10, ("connect returned %s\n", strerror(errno)));
679 sys_fcntl_long(state->fd, F_SETFL, state->old_sockflags);
680 async_req_error(req, map_nt_error_from_unix(state->sys_errno));
681 return;
684 state->sys_errno = 0;
685 async_req_done(req);
688 NTSTATUS async_connect_recv(struct async_req *req, int *perrno)
690 struct async_connect_state *state = talloc_get_type_abort(
691 req->private_data, struct async_connect_state);
692 NTSTATUS status;
694 sys_fcntl_long(state->fd, F_SETFL, state->old_sockflags);
696 *perrno = state->sys_errno;
698 if (async_req_is_error(req, &status)) {
699 return status;
701 if (state->sys_errno == 0) {
702 return NT_STATUS_OK;
704 return map_nt_error_from_unix(state->sys_errno);