#include "includes.h"
#include "../lib/util/tevent_ntstatus.h"
-#include "lib/async_req/async_sock.h"
+#include "lib/tsocket/tsocket.h"
#include "libsmb/nmblib.h"
-#include "lib/sys_rw.h"
+#include "lib/util/sys_rw.h"
static const char *nmbd_socket_dir(void)
{
struct nb_packet_server {
struct tevent_context *ev;
int listen_sock;
+ struct tevent_fd *listen_fde;
int max_clients;
int num_clients;
struct nb_packet_client *clients;
int trn_id;
char *mailslot_name;
- int sock;
- struct tevent_req *read_req;
+ struct {
+ uint8_t byte;
+ struct iovec iov[1];
+ } ack;
+
+ struct tstream_context *sock;
struct tevent_queue *out_queue;
};
struct nb_packet_server **presult)
{
struct nb_packet_server *result;
- struct tevent_fd *fde;
NTSTATUS status;
int rc;
}
talloc_set_destructor(result, nb_packet_server_destructor);
- fde = tevent_add_fd(ev, result, result->listen_sock, TEVENT_FD_READ,
- nb_packet_server_listener, result);
- if (fde == NULL) {
+ result->listen_fde = tevent_add_fd(ev, result,
+ result->listen_sock,
+ TEVENT_FD_READ,
+ nb_packet_server_listener,
+ result);
+ if (result->listen_fde == NULL) {
status = NT_STATUS_NO_MEMORY;
goto fail;
}
static int nb_packet_server_destructor(struct nb_packet_server *s)
{
+ TALLOC_FREE(s->listen_fde);
+
if (s->listen_sock != -1) {
close(s->listen_sock);
s->listen_sock = -1;
static ssize_t nb_packet_client_more(uint8_t *buf, size_t buflen,
void *private_data);
static void nb_packet_got_query(struct tevent_req *req);
+static void nb_packet_client_ack_done(struct tevent_req *req);
static void nb_packet_client_read_done(struct tevent_req *req);
static void nb_packet_server_listener(struct tevent_context *ev,
struct sockaddr_un sunaddr;
socklen_t len;
int sock;
+ int ret;
len = sizeof(sunaddr);
close(sock);
return;
}
- client->sock = sock;
+ ret = tstream_bsd_existing_socket(client, sock, &client->sock);
+ if (ret != 0) {
+ DEBUG(10, ("tstream_bsd_existing_socket failed\n"));
+ close(sock);
+ return;
+ }
+
client->server = server;
talloc_set_destructor(client, nb_packet_client_destructor);
return;
}
- req = read_packet_send(client, ev, client->sock,
- sizeof(struct nb_packet_query),
- nb_packet_client_more, NULL);
+ req = tstream_read_packet_send(client, ev, client->sock,
+ sizeof(struct nb_packet_query),
+ nb_packet_client_more, NULL);
if (req == NULL) {
- DEBUG(10, ("read_packet_send failed\n"));
+ DEBUG(10, ("tstream_read_packet_send failed\n"));
TALLOC_FREE(client);
return;
}
static int nb_packet_client_destructor(struct nb_packet_client *c)
{
- if (c->sock != -1) {
- close(c->sock);
- c->sock = -1;
- }
+ tevent_queue_stop(c->out_queue);
+ TALLOC_FREE(c->sock);
+
DLIST_REMOVE(c->server->clients, c);
c->server->num_clients -= 1;
return 0;
req, struct nb_packet_client);
struct nb_packet_query q;
uint8_t *buf;
- ssize_t nread, nwritten;
+ ssize_t nread;
int err;
- char c;
- nread = read_packet_recv(req, talloc_tos(), &buf, &err);
+ nread = tstream_read_packet_recv(req, talloc_tos(), &buf, &err);
TALLOC_FREE(req);
if (nread < (ssize_t)sizeof(struct nb_packet_query)) {
DEBUG(10, ("read_packet_recv returned %d (%s)\n",
}
}
- /*
- * Yes, this is a blocking write of 1 byte into a unix
- * domain socket that has never been written to. Highly
- * unlikely that this actually blocks.
- */
- c = 0;
- nwritten = sys_write(client->sock, &c, sizeof(c));
- if (nwritten != sizeof(c)) {
- DEBUG(10, ("Could not write success indicator to client: %s\n",
- strerror(errno)));
+ client->ack.byte = 0;
+ client->ack.iov[0].iov_base = &client->ack.byte;
+ client->ack.iov[0].iov_len = 1;
+ req = tstream_writev_queue_send(client, client->server->ev,
+ client->sock,
+ client->out_queue,
+ client->ack.iov, 1);
+ if (req == NULL) {
+ DEBUG(10, ("tstream_writev_queue_send failed\n"));
TALLOC_FREE(client);
return;
}
+ tevent_req_set_callback(req, nb_packet_client_ack_done, client);
- client->read_req = read_packet_send(client, client->server->ev,
- client->sock, 1, NULL, NULL);
- if (client->read_req == NULL) {
+ req = tstream_read_packet_send(client, client->server->ev,
+ client->sock, 1, NULL, NULL);
+ if (req == NULL) {
DEBUG(10, ("Could not activate reader for client exit "
"detection\n"));
TALLOC_FREE(client);
return;
}
- tevent_req_set_callback(client->read_req, nb_packet_client_read_done,
+ tevent_req_set_callback(req, nb_packet_client_read_done,
client);
}
+static void nb_packet_client_ack_done(struct tevent_req *req)
+{
+ struct nb_packet_client *client = tevent_req_callback_data(
+ req, struct nb_packet_client);
+ ssize_t nwritten;
+ int err;
+
+ nwritten = tstream_writev_queue_recv(req, &err);
+
+ TALLOC_FREE(req);
+
+ if (nwritten == -1) {
+ DEBUG(10, ("tstream_writev_queue_recv failed: %s\n",
+ strerror(err)));
+ TALLOC_FREE(client);
+ return;
+ }
+}
+
static void nb_packet_client_read_done(struct tevent_req *req)
{
struct nb_packet_client *client = tevent_req_callback_data(
uint8_t *buf;
int err;
- nread = read_packet_recv(req, talloc_tos(), &buf, &err);
+ nread = tstream_read_packet_recv(req, talloc_tos(), &buf, &err);
TALLOC_FREE(req);
if (nread == 1) {
DEBUG(10, ("Protocol error, received data on write-only "
state->iov[1].iov_base = state->buf;
state->iov[1].iov_len = state->hdr.len;
- TALLOC_FREE(client->read_req);
-
- req = writev_send(client, client->server->ev, client->out_queue,
- client->sock, true, state->iov, 2);
+ req = tstream_writev_queue_send(state, client->server->ev,
+ client->sock,
+ client->out_queue,
+ state->iov, 2);
if (req == NULL) {
- DEBUG(10, ("writev_send failed\n"));
+ DEBUG(10, ("tstream_writev_queue_send failed\n"));
return;
}
tevent_req_set_callback(req, nb_packet_client_send_done, state);
ssize_t nwritten;
int err;
- nwritten = writev_recv(req, &err);
+ nwritten = tstream_writev_queue_recv(req, &err);
TALLOC_FREE(req);
TALLOC_FREE(state);
if (nwritten == -1) {
- DEBUG(10, ("writev failed: %s\n", strerror(err)));
+ DEBUG(10, ("tstream_writev_queue failed: %s\n", strerror(err)));
TALLOC_FREE(client);
- }
-
- if (tevent_queue_length(client->out_queue) == 0) {
- client->read_req = read_packet_send(client, client->server->ev,
- client->sock, 1,
- NULL, NULL);
- if (client->read_req == NULL) {
- DEBUG(10, ("Could not activate reader for client exit "
- "detection\n"));
- TALLOC_FREE(client);
- return;
- }
- tevent_req_set_callback(client->read_req,
- nb_packet_client_read_done,
- client);
+ return;
}
}
struct nb_packet_reader {
- int sock;
+ struct tstream_context *sock;
};
struct nb_packet_reader_state {
struct tevent_context *ev;
- struct sockaddr_un addr;
struct nb_packet_query query;
const char *mailslot_name;
struct iovec iov[2];
struct nb_packet_reader *reader;
};
-static int nb_packet_reader_destructor(struct nb_packet_reader *r);
static void nb_packet_reader_connected(struct tevent_req *subreq);
static void nb_packet_reader_sent_query(struct tevent_req *subreq);
static void nb_packet_reader_got_ack(struct tevent_req *subreq);
{
struct tevent_req *req, *subreq;
struct nb_packet_reader_state *state;
- char *path;
+ struct tsocket_address *laddr;
+ char *rpath;
+ struct tsocket_address *raddr;
+ int ret;
req = tevent_req_create(mem_ctx, &state,
struct nb_packet_reader_state);
return tevent_req_post(req, ev);
}
- path = talloc_asprintf(talloc_tos(), "%s/%s", nmbd_socket_dir(),
+ ret = tsocket_address_unix_from_path(state, "", &laddr);
+ if (ret != 0) {
+ tevent_req_nterror(req, map_nt_error_from_unix(errno));
+ return tevent_req_post(req, ev);
+ }
+ rpath = talloc_asprintf(state, "%s/%s", nmbd_socket_dir(),
"unexpected");
- if (tevent_req_nomem(path, req)) {
+ if (tevent_req_nomem(rpath, req)) {
return tevent_req_post(req, ev);
}
- state->addr.sun_family = AF_UNIX;
- strlcpy(state->addr.sun_path, path, sizeof(state->addr.sun_path));
- TALLOC_FREE(path);
-
- state->reader->sock = socket(AF_UNIX, SOCK_STREAM, 0);
- if (state->reader->sock == -1) {
+ ret = tsocket_address_unix_from_path(state, rpath, &raddr);
+ if (ret != 0) {
tevent_req_nterror(req, map_nt_error_from_unix(errno));
return tevent_req_post(req, ev);
}
- talloc_set_destructor(state->reader, nb_packet_reader_destructor);
- subreq = async_connect_send(state, ev, state->reader->sock,
- (struct sockaddr *)(void *)&state->addr,
- sizeof(state->addr), NULL, NULL, NULL);
+ subreq = tstream_unix_connect_send(state, ev, laddr, raddr);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
return req;
}
-static int nb_packet_reader_destructor(struct nb_packet_reader *r)
-{
- if (r->sock != -1) {
- close(r->sock);
- r->sock = -1;
- }
- return 0;
-}
-
static void nb_packet_reader_connected(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(
int res, err;
int num_iovecs = 1;
- res = async_connect_recv(subreq, &err);
+ res = tstream_unix_connect_recv(subreq, &err, state->reader,
+ &state->reader->sock);
TALLOC_FREE(subreq);
if (res == -1) {
- DEBUG(10, ("async_connect failed: %s\n", strerror(err)));
+ DEBUG(10, ("tstream_unix_connect failed: %s\n", strerror(err)));
tevent_req_nterror(req, map_nt_error_from_unix(err));
return;
}
state->iov[1].iov_len = state->query.mailslot_namelen;
}
- subreq = writev_send(state, state->ev, NULL, state->reader->sock,
- true, state->iov, num_iovecs);
+ subreq = tstream_writev_send(state, state->ev, state->reader->sock,
+ state->iov, num_iovecs);
if (tevent_req_nomem(subreq, req)) {
return;
}
ssize_t written;
int err;
- written = writev_recv(subreq, &err);
+ written = tstream_writev_recv(subreq, &err);
TALLOC_FREE(subreq);
if (written == -1) {
tevent_req_nterror(req, map_nt_error_from_unix(err));
tevent_req_nterror(req, NT_STATUS_UNEXPECTED_IO_ERROR);
return;
}
- subreq = read_packet_send(state, state->ev, state->reader->sock,
- sizeof(state->c), NULL, NULL);
+ subreq = tstream_read_packet_send(state, state->ev,
+ state->reader->sock,
+ sizeof(state->c), NULL, NULL);
if (tevent_req_nomem(subreq, req)) {
return;
}
int err;
uint8_t *buf;
- nread = read_packet_recv(subreq, state, &buf, &err);
+ nread = tstream_read_packet_recv(subreq, state, &buf, &err);
TALLOC_FREE(subreq);
if (nread == -1) {
DEBUG(10, ("read_packet_recv returned %s\n",
NTSTATUS status;
if (tevent_req_is_nterror(req, &status)) {
+ tevent_req_received(req);
return status;
}
*preader = talloc_move(mem_ctx, &state->reader);
+ tevent_req_received(req);
return NT_STATUS_OK;
}
if (req == NULL) {
return NULL;
}
- subreq = read_packet_send(state, ev, reader->sock,
- sizeof(struct nb_packet_client_header),
- nb_packet_read_more, state);
+ subreq = tstream_read_packet_send(state, ev, reader->sock,
+ sizeof(struct nb_packet_client_header),
+ nb_packet_read_more, state);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
ssize_t nread;
int err;
- nread = read_packet_recv(subreq, state, &state->buf, &err);
+ nread = tstream_read_packet_recv(subreq, state, &state->buf, &err);
if (nread == -1) {
tevent_req_nterror(req, map_nt_error_from_unix(err));
return;
NTSTATUS status;
if (tevent_req_is_nterror(req, &status)) {
+ tevent_req_received(req);
return status;
}
state->buflen - sizeof(struct nb_packet_client_header),
state->hdr.type, state->hdr.ip, state->hdr.port);
if (packet == NULL) {
+ tevent_req_received(req);
return NT_STATUS_INVALID_NETWORK_RESPONSE;
}
*ppacket = packet;
+ tevent_req_received(req);
return NT_STATUS_OK;
}