LCOV - code coverage report
Current view: top level - source3/libsmb - unexpected.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 236 368 64.1 %
Date: 2024-05-31 13:13:24 Functions: 20 20 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    handle unexpected packets
       4             :    Copyright (C) Andrew Tridgell 2000
       5             : 
       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.
      10             : 
      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.
      15             : 
      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/>.
      18             : 
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "libsmb/unexpected.h"
      23             : #include "../lib/util/tevent_ntstatus.h"
      24             : #include "lib/util_tsock.h"
      25             : #include "libsmb/nmblib.h"
      26             : #include "lib/tsocket/tsocket.h"
      27             : #include "lib/util/sys_rw.h"
      28             : 
      29             : struct nb_packet_query {
      30             :         enum packet_type type;
      31             :         size_t mailslot_namelen;
      32             :         int trn_id;
      33             : };
      34             : 
      35             : struct nb_packet_client;
      36             : 
      37             : struct nb_packet_server {
      38             :         struct tevent_context *ev;
      39             :         int listen_sock;
      40             :         struct tevent_fd *listen_fde;
      41             :         int max_clients;
      42             :         int num_clients;
      43             :         struct nb_packet_client *clients;
      44             : };
      45             : 
      46             : struct nb_packet_client {
      47             :         struct nb_packet_client *prev, *next;
      48             :         struct nb_packet_server *server;
      49             : 
      50             :         enum packet_type type;
      51             :         int trn_id;
      52             :         char *mailslot_name;
      53             : 
      54             :         struct {
      55             :                 uint8_t byte;
      56             :                 struct iovec iov[1];
      57             :         } ack;
      58             : 
      59             :         struct tstream_context *sock;
      60             :         struct tevent_queue *out_queue;
      61             : };
      62             : 
      63             : static int nb_packet_server_destructor(struct nb_packet_server *s);
      64             : static void nb_packet_server_listener(struct tevent_context *ev,
      65             :                                       struct tevent_fd *fde,
      66             :                                       uint16_t flags,
      67             :                                       void *private_data);
      68             : 
      69         108 : NTSTATUS nb_packet_server_create(TALLOC_CTX *mem_ctx,
      70             :                                  struct tevent_context *ev,
      71             :                                  const char *nmbd_socket_dir,
      72             :                                  int max_clients,
      73             :                                  struct nb_packet_server **presult)
      74             : {
      75           2 :         struct nb_packet_server *result;
      76           2 :         NTSTATUS status;
      77           2 :         int rc;
      78             : 
      79         108 :         result = talloc_zero(mem_ctx, struct nb_packet_server);
      80         108 :         if (result == NULL) {
      81           0 :                 status = NT_STATUS_NO_MEMORY;
      82           0 :                 goto fail;
      83             :         }
      84         108 :         result->ev = ev;
      85         108 :         result->max_clients = max_clients;
      86             : 
      87         108 :         result->listen_sock = create_pipe_sock(
      88             :                 nmbd_socket_dir, "unexpected", 0755);
      89         108 :         if (result->listen_sock == -1) {
      90           0 :                 status = map_nt_error_from_unix(errno);
      91           0 :                 goto fail;
      92             :         }
      93         108 :         rc = listen(result->listen_sock, 5);
      94         108 :         if (rc < 0) {
      95           0 :                 status = map_nt_error_from_unix(errno);
      96           0 :                 goto fail;
      97             :         }
      98         108 :         talloc_set_destructor(result, nb_packet_server_destructor);
      99             : 
     100         108 :         result->listen_fde = tevent_add_fd(ev, result,
     101             :                                            result->listen_sock,
     102             :                                            TEVENT_FD_READ,
     103             :                                            nb_packet_server_listener,
     104             :                                            result);
     105         108 :         if (result->listen_fde == NULL) {
     106           0 :                 status = NT_STATUS_NO_MEMORY;
     107           0 :                 goto fail;
     108             :         }
     109             : 
     110         108 :         *presult = result;
     111         108 :         return NT_STATUS_OK;
     112           0 : fail:
     113           0 :         TALLOC_FREE(result);
     114           0 :         return status;
     115             : }
     116             : 
     117          65 : static int nb_packet_server_destructor(struct nb_packet_server *s)
     118             : {
     119          65 :         TALLOC_FREE(s->listen_fde);
     120             : 
     121          65 :         if (s->listen_sock != -1) {
     122          65 :                 close(s->listen_sock);
     123          65 :                 s->listen_sock = -1;
     124             :         }
     125          65 :         return 0;
     126             : }
     127             : 
     128             : static int nb_packet_client_destructor(struct nb_packet_client *c);
     129             : static ssize_t nb_packet_client_more(uint8_t *buf, size_t buflen,
     130             :                                      void *private_data);
     131             : static void nb_packet_got_query(struct tevent_req *req);
     132             : static void nb_packet_client_ack_done(struct tevent_req *req);
     133             : static void nb_packet_client_read_done(struct tevent_req *req);
     134             : 
     135        2161 : static void nb_packet_server_listener(struct tevent_context *ev,
     136             :                                       struct tevent_fd *fde,
     137             :                                       uint16_t flags,
     138             :                                       void *private_data)
     139             : {
     140        2161 :         struct nb_packet_server *server = talloc_get_type_abort(
     141             :                 private_data, struct nb_packet_server);
     142           0 :         struct nb_packet_client *client;
     143           0 :         struct tevent_req *req;
     144           0 :         struct sockaddr_un sunaddr;
     145           0 :         socklen_t len;
     146           0 :         int sock;
     147           0 :         int ret;
     148             : 
     149        2161 :         len = sizeof(sunaddr);
     150             : 
     151        2161 :         sock = accept(server->listen_sock, (struct sockaddr *)(void *)&sunaddr,
     152             :                       &len);
     153        2161 :         if (sock == -1) {
     154           0 :                 return;
     155             :         }
     156        2161 :         smb_set_close_on_exec(sock);
     157        2161 :         DEBUG(6,("accepted socket %d\n", sock));
     158             : 
     159        2161 :         client = talloc_zero(server, struct nb_packet_client);
     160        2161 :         if (client == NULL) {
     161           0 :                 DEBUG(10, ("talloc failed\n"));
     162           0 :                 close(sock);
     163           0 :                 return;
     164             :         }
     165        2161 :         ret = tstream_bsd_existing_socket(client, sock, &client->sock);
     166        2161 :         if (ret != 0) {
     167           0 :                 DEBUG(10, ("tstream_bsd_existing_socket failed\n"));
     168           0 :                 TALLOC_FREE(client);
     169           0 :                 close(sock);
     170           0 :                 return;
     171             :         }
     172             :         /* as server we want to fail early */
     173        2161 :         tstream_bsd_fail_readv_first_error(client->sock, true);
     174             : 
     175        2161 :         client->server = server;
     176             : 
     177        2161 :         client->out_queue = tevent_queue_create(
     178             :                 client, "unexpected packet output");
     179        2161 :         if (client->out_queue == NULL) {
     180           0 :                 DEBUG(10, ("tevent_queue_create failed\n"));
     181           0 :                 TALLOC_FREE(client);
     182           0 :                 return;
     183             :         }
     184             : 
     185        2161 :         req = tstream_read_packet_send(client, ev, client->sock,
     186             :                                        sizeof(struct nb_packet_query),
     187             :                                        nb_packet_client_more, NULL);
     188        2161 :         if (req == NULL) {
     189           0 :                 DEBUG(10, ("tstream_read_packet_send failed\n"));
     190           0 :                 TALLOC_FREE(client);
     191           0 :                 return;
     192             :         }
     193        2161 :         tevent_req_set_callback(req, nb_packet_got_query, client);
     194             : 
     195        2161 :         DLIST_ADD(server->clients, client);
     196        2161 :         server->num_clients += 1;
     197             : 
     198        2161 :         talloc_set_destructor(client, nb_packet_client_destructor);
     199             : 
     200        2161 :         if (server->num_clients > server->max_clients) {
     201           0 :                 DEBUG(10, ("Too many clients, dropping oldest\n"));
     202             : 
     203             :                 /*
     204             :                  * no TALLOC_FREE here, don't mess with the list structs
     205             :                  */
     206           0 :                 talloc_free(server->clients->prev);
     207             :         }
     208             : }
     209             : 
     210        2194 : static ssize_t nb_packet_client_more(uint8_t *buf, size_t buflen,
     211             :                                      void *private_data)
     212             : {
     213           0 :         struct nb_packet_query q;
     214        2194 :         if (buflen > sizeof(struct nb_packet_query)) {
     215          33 :                 return 0;
     216             :         }
     217             :         /* Take care of alignment */
     218        2161 :         memcpy(&q, buf, sizeof(q));
     219        2161 :         if (q.mailslot_namelen > 1024) {
     220           0 :                 DEBUG(10, ("Got invalid mailslot namelen %d\n",
     221             :                            (int)q.mailslot_namelen));
     222           0 :                 return -1;
     223             :         }
     224        2161 :         return q.mailslot_namelen;
     225             : }
     226             : 
     227        2161 : static int nb_packet_client_destructor(struct nb_packet_client *c)
     228             : {
     229        2161 :         tevent_queue_stop(c->out_queue);
     230        2161 :         TALLOC_FREE(c->sock);
     231             : 
     232        2161 :         DLIST_REMOVE(c->server->clients, c);
     233        2161 :         c->server->num_clients -= 1;
     234        2161 :         return 0;
     235             : }
     236             : 
     237        2161 : static void nb_packet_got_query(struct tevent_req *req)
     238             : {
     239        2161 :         struct nb_packet_client *client = tevent_req_callback_data(
     240             :                 req, struct nb_packet_client);
     241           0 :         struct nb_packet_query q;
     242           0 :         uint8_t *buf;
     243           0 :         ssize_t nread;
     244           0 :         int err;
     245             : 
     246        2161 :         nread = tstream_read_packet_recv(req, client, &buf, &err);
     247        2161 :         TALLOC_FREE(req);
     248        2161 :         if (nread < (ssize_t)sizeof(struct nb_packet_query)) {
     249           0 :                 DEBUG(10, ("read_packet_recv returned %d (%s)\n",
     250             :                            (int)nread,
     251             :                            (nread == -1) ? strerror(err) : "wrong length"));
     252           0 :                 TALLOC_FREE(client);
     253           0 :                 return;
     254             :         }
     255             : 
     256             :         /* Take care of alignment */
     257        2161 :         memcpy(&q, buf, sizeof(q));
     258             : 
     259        2161 :         if ((size_t)nread !=
     260        2161 :             sizeof(struct nb_packet_query) + q.mailslot_namelen) {
     261           0 :                 DEBUG(10, ("nb_packet_got_query: Invalid mailslot namelength\n"));
     262           0 :                 TALLOC_FREE(client);
     263           0 :                 return;
     264             :         }
     265             : 
     266        2161 :         client->trn_id = q.trn_id;
     267        2161 :         client->type = q.type;
     268        2161 :         if (q.mailslot_namelen > 0) {
     269          66 :                 client->mailslot_name = talloc_strndup(
     270          33 :                         client, (char *)buf + sizeof(q),
     271             :                         q.mailslot_namelen);
     272          33 :                 if (client->mailslot_name == NULL) {
     273           0 :                         TALLOC_FREE(client);
     274           0 :                         return;
     275             :                 }
     276             :         }
     277             : 
     278        2161 :         TALLOC_FREE(buf);
     279             : 
     280        2161 :         client->ack.byte = 0;
     281        2161 :         client->ack.iov[0].iov_base = &client->ack.byte;
     282        2161 :         client->ack.iov[0].iov_len = 1;
     283        2161 :         req = tstream_writev_queue_send(client, client->server->ev,
     284             :                                         client->sock,
     285             :                                         client->out_queue,
     286        2161 :                                         client->ack.iov, 1);
     287        2161 :         if (req == NULL) {
     288           0 :                 DEBUG(10, ("tstream_writev_queue_send failed\n"));
     289           0 :                 TALLOC_FREE(client);
     290           0 :                 return;
     291             :         }
     292        2161 :         tevent_req_set_callback(req, nb_packet_client_ack_done, client);
     293             : 
     294        2161 :         req = tstream_read_packet_send(client, client->server->ev,
     295             :                                        client->sock, 1, NULL, NULL);
     296        2161 :         if (req == NULL) {
     297           0 :                 DEBUG(10, ("Could not activate reader for client exit "
     298             :                            "detection\n"));
     299           0 :                 TALLOC_FREE(client);
     300           0 :                 return;
     301             :         }
     302        2161 :         tevent_req_set_callback(req, nb_packet_client_read_done,
     303             :                                 client);
     304             : }
     305             : 
     306        2161 : static void nb_packet_client_ack_done(struct tevent_req *req)
     307             : {
     308        2161 :         struct nb_packet_client *client = tevent_req_callback_data(
     309             :                 req, struct nb_packet_client);
     310           0 :         ssize_t nwritten;
     311           0 :         int err;
     312             : 
     313        2161 :         nwritten = tstream_writev_queue_recv(req, &err);
     314             : 
     315        2161 :         TALLOC_FREE(req);
     316             : 
     317        2161 :         if (nwritten == -1) {
     318           0 :                 DEBUG(10, ("tstream_writev_queue_recv failed: %s\n",
     319             :                            strerror(err)));
     320           0 :                 TALLOC_FREE(client);
     321           0 :                 return;
     322             :         }
     323             : }
     324             : 
     325        2161 : static void nb_packet_client_read_done(struct tevent_req *req)
     326             : {
     327        2161 :         struct nb_packet_client *client = tevent_req_callback_data(
     328             :                 req, struct nb_packet_client);
     329           0 :         ssize_t nread;
     330           0 :         uint8_t *buf;
     331           0 :         int err;
     332             : 
     333        2161 :         nread = tstream_read_packet_recv(req, client, &buf, &err);
     334        2161 :         TALLOC_FREE(req);
     335        2161 :         if (nread == 1) {
     336           0 :                 DEBUG(10, ("Protocol error, received data on write-only "
     337             :                            "unexpected socket: 0x%2.2x\n", (*buf)));
     338             :         }
     339        2161 :         TALLOC_FREE(client);
     340        2161 : }
     341             : 
     342             : static void nb_packet_client_send(struct nb_packet_client *client,
     343             :                                   struct packet_struct *p);
     344             : 
     345        1155 : void nb_packet_dispatch(struct nb_packet_server *server,
     346             :                         struct packet_struct *p)
     347             : {
     348           0 :         struct nb_packet_client *c;
     349           0 :         uint16_t trn_id;
     350             : 
     351        1155 :         switch (p->packet_type) {
     352           6 :         case NMB_PACKET:
     353           6 :                 trn_id = p->packet.nmb.header.name_trn_id;
     354           6 :                 break;
     355        1149 :         case DGRAM_PACKET:
     356        1149 :                 trn_id = p->packet.dgram.header.dgm_id;
     357        1149 :                 break;
     358           0 :         default:
     359           0 :                 DEBUG(10, ("Got invalid packet type %d\n",
     360             :                            (int)p->packet_type));
     361           0 :                 return;
     362             :         }
     363        1221 :         for (c = server->clients; c != NULL; c = c->next) {
     364             : 
     365          66 :                 if (c->type != p->packet_type) {
     366          34 :                         DEBUG(10, ("client expects packet %d, got %d\n",
     367             :                                    c->type, p->packet_type));
     368          34 :                         continue;
     369             :                 }
     370             : 
     371          32 :                 if (p->packet_type == NMB_PACKET) {
     372             :                         /*
     373             :                          * See if the client specified transaction
     374             :                          * ID. Filter if it did.
     375             :                          */
     376           0 :                         if ((c->trn_id != -1) &&
     377           0 :                             (c->trn_id != trn_id)) {
     378           0 :                                 DEBUG(10, ("client expects trn %d, got %d\n",
     379             :                                            c->trn_id, trn_id));
     380           0 :                                 continue;
     381             :                         }
     382             :                 } else {
     383             :                         /*
     384             :                          * See if the client specified a mailslot
     385             :                          * name. Filter if it did.
     386             :                          */
     387          32 :                         if ((c->mailslot_name != NULL) &&
     388          32 :                             !match_mailslot_name(p, c->mailslot_name)) {
     389           2 :                                 continue;
     390             :                         }
     391             :                 }
     392          30 :                 nb_packet_client_send(c, p);
     393             :         }
     394             : }
     395             : 
     396             : struct nb_packet_client_header {
     397             :         size_t len;
     398             :         enum packet_type type;
     399             :         time_t timestamp;
     400             :         struct in_addr ip;
     401             :         int port;
     402             : };
     403             : 
     404             : struct nb_packet_client_state {
     405             :         struct nb_packet_client *client;
     406             :         struct iovec iov[2];
     407             :         struct nb_packet_client_header hdr;
     408             :         char buf[1024];
     409             : };
     410             : 
     411             : static void nb_packet_client_send_done(struct tevent_req *req);
     412             : 
     413          30 : static void nb_packet_client_send(struct nb_packet_client *client,
     414             :                                   struct packet_struct *p)
     415             : {
     416           0 :         struct nb_packet_client_state *state;
     417           0 :         struct tevent_req *req;
     418             : 
     419          30 :         if (tevent_queue_length(client->out_queue) > 10) {
     420             :                 /*
     421             :                  * Skip clients that don't listen anyway, some form of DoS
     422             :                  * protection
     423             :                  */
     424           0 :                 return;
     425             :         }
     426             : 
     427          30 :         state = talloc_zero(client, struct nb_packet_client_state);
     428          30 :         if (state == NULL) {
     429           0 :                 DEBUG(10, ("talloc failed\n"));
     430           0 :                 return;
     431             :         }
     432             : 
     433          30 :         state->client = client;
     434             : 
     435          30 :         state->hdr.ip = p->ip;
     436          30 :         state->hdr.port = p->port;
     437          30 :         state->hdr.timestamp = p->timestamp;
     438          30 :         state->hdr.type = p->packet_type;
     439          30 :         state->hdr.len = build_packet(state->buf, sizeof(state->buf), p);
     440             : 
     441          30 :         state->iov[0].iov_base = (char *)&state->hdr;
     442          30 :         state->iov[0].iov_len = sizeof(state->hdr);
     443          30 :         state->iov[1].iov_base = state->buf;
     444          30 :         state->iov[1].iov_len = state->hdr.len;
     445             : 
     446          30 :         req = tstream_writev_queue_send(state, client->server->ev,
     447             :                                         client->sock,
     448             :                                         client->out_queue,
     449          30 :                                         state->iov, 2);
     450          30 :         if (req == NULL) {
     451           0 :                 DEBUG(10, ("tstream_writev_queue_send failed\n"));
     452           0 :                 return;
     453             :         }
     454          30 :         tevent_req_set_callback(req, nb_packet_client_send_done, state);
     455             : }
     456             : 
     457          30 : static void nb_packet_client_send_done(struct tevent_req *req)
     458             : {
     459          30 :         struct nb_packet_client_state *state = tevent_req_callback_data(
     460             :                 req, struct nb_packet_client_state);
     461          30 :         struct nb_packet_client *client = state->client;
     462           0 :         ssize_t nwritten;
     463           0 :         int err;
     464             : 
     465          30 :         nwritten = tstream_writev_queue_recv(req, &err);
     466             : 
     467          30 :         TALLOC_FREE(req);
     468          30 :         TALLOC_FREE(state);
     469             : 
     470          30 :         if (nwritten == -1) {
     471           0 :                 DEBUG(10, ("tstream_writev_queue failed: %s\n", strerror(err)));
     472           0 :                 TALLOC_FREE(client);
     473           0 :                 return;
     474             :         }
     475             : }
     476             : 
     477             : struct nb_packet_reader {
     478             :         struct tstream_context *sock;
     479             : };
     480             : 
     481             : struct nb_packet_reader_state {
     482             :         struct tevent_context *ev;
     483             :         struct nb_packet_query query;
     484             :         const char *mailslot_name;
     485             :         struct iovec iov[2];
     486             :         struct nb_packet_reader *reader;
     487             : };
     488             : 
     489             : static void nb_packet_reader_connected(struct tevent_req *subreq);
     490             : static void nb_packet_reader_sent_query(struct tevent_req *subreq);
     491             : static void nb_packet_reader_got_ack(struct tevent_req *subreq);
     492             : 
     493         866 : struct tevent_req *nb_packet_reader_send(TALLOC_CTX *mem_ctx,
     494             :                                          struct tevent_context *ev,
     495             :                                          const char *nmbd_socket_dir,
     496             :                                          enum packet_type type,
     497             :                                          int trn_id,
     498             :                                          const char *mailslot_name)
     499             : {
     500           0 :         struct tevent_req *req, *subreq;
     501           0 :         struct nb_packet_reader_state *state;
     502           0 :         struct tsocket_address *laddr;
     503           0 :         char *rpath;
     504           0 :         struct tsocket_address *raddr;
     505           0 :         int ret;
     506             : 
     507         866 :         req = tevent_req_create(mem_ctx, &state,
     508             :                                 struct nb_packet_reader_state);
     509         866 :         if (req == NULL) {
     510           0 :                 return NULL;
     511             :         }
     512         866 :         state->ev = ev;
     513         866 :         state->query.trn_id = trn_id;
     514         866 :         state->query.type = type;
     515         866 :         state->mailslot_name = mailslot_name;
     516             : 
     517         866 :         if (mailslot_name != NULL) {
     518           5 :                 state->query.mailslot_namelen = strlen(mailslot_name);
     519             :         }
     520             : 
     521         866 :         state->reader = talloc_zero(state, struct nb_packet_reader);
     522         866 :         if (tevent_req_nomem(state->reader, req)) {
     523           0 :                 return tevent_req_post(req, ev);
     524             :         }
     525             : 
     526         866 :         ret = tsocket_address_unix_from_path(state, NULL, &laddr);
     527         866 :         if (ret != 0) {
     528           0 :                 tevent_req_nterror(req, map_nt_error_from_unix(errno));
     529           0 :                 return tevent_req_post(req, ev);
     530             :         }
     531         866 :         rpath = talloc_asprintf(state, "%s/%s", nmbd_socket_dir,
     532             :                                "unexpected");
     533         866 :         if (tevent_req_nomem(rpath, req)) {
     534           0 :                 return tevent_req_post(req, ev);
     535             :         }
     536         866 :         ret = tsocket_address_unix_from_path(state, rpath, &raddr);
     537         866 :         if (ret != 0) {
     538           0 :                 tevent_req_nterror(req, map_nt_error_from_unix(errno));
     539           0 :                 return tevent_req_post(req, ev);
     540             :         }
     541             : 
     542         866 :         subreq = tstream_unix_connect_send(state, ev, laddr, raddr);
     543         866 :         if (tevent_req_nomem(subreq, req)) {
     544           0 :                 return tevent_req_post(req, ev);
     545             :         }
     546         866 :         tevent_req_set_callback(subreq, nb_packet_reader_connected, req);
     547         866 :         return req;
     548             : }
     549             : 
     550         866 : static void nb_packet_reader_connected(struct tevent_req *subreq)
     551             : {
     552         866 :         struct tevent_req *req = tevent_req_callback_data(
     553             :                 subreq, struct tevent_req);
     554         866 :         struct nb_packet_reader_state *state = tevent_req_data(
     555             :                 req, struct nb_packet_reader_state);
     556           0 :         int res, err;
     557         866 :         int num_iovecs = 1;
     558             : 
     559         866 :         res = tstream_unix_connect_recv(subreq, &err, state->reader,
     560             :                                         &state->reader->sock);
     561         866 :         TALLOC_FREE(subreq);
     562         866 :         if (res == -1) {
     563         478 :                 DEBUG(10, ("tstream_unix_connect failed: %s\n", strerror(err)));
     564         478 :                 tevent_req_nterror(req, map_nt_error_from_unix(err));
     565         478 :                 return;
     566             :         }
     567             : 
     568         388 :         state->iov[0].iov_base = (char *)&state->query;
     569         388 :         state->iov[0].iov_len = sizeof(state->query);
     570             : 
     571         388 :         if (state->mailslot_name != NULL) {
     572           5 :                 num_iovecs = 2;
     573           5 :                 state->iov[1].iov_base = discard_const_p(
     574             :                         char, state->mailslot_name);
     575           5 :                 state->iov[1].iov_len = state->query.mailslot_namelen;
     576             :         }
     577             : 
     578         388 :         subreq = tstream_writev_send(state, state->ev, state->reader->sock,
     579         388 :                                      state->iov, num_iovecs);
     580         388 :         if (tevent_req_nomem(subreq, req)) {
     581           0 :                 return;
     582             :         }
     583         388 :         tevent_req_set_callback(subreq, nb_packet_reader_sent_query, req);
     584             : }
     585             : 
     586         388 : static void nb_packet_reader_sent_query(struct tevent_req *subreq)
     587             : {
     588         388 :         struct tevent_req *req = tevent_req_callback_data(
     589             :                 subreq, struct tevent_req);
     590         388 :         struct nb_packet_reader_state *state = tevent_req_data(
     591             :                 req, struct nb_packet_reader_state);
     592           0 :         ssize_t written;
     593           0 :         int err;
     594             : 
     595         388 :         written = tstream_writev_recv(subreq, &err);
     596         388 :         TALLOC_FREE(subreq);
     597         388 :         if (written == -1) {
     598           0 :                 tevent_req_nterror(req, map_nt_error_from_unix(err));
     599           0 :                 return;
     600             :         }
     601         388 :         if ((size_t)written !=
     602         388 :             sizeof(state->query) + state->query.mailslot_namelen) {
     603           0 :                 tevent_req_nterror(req, NT_STATUS_UNEXPECTED_IO_ERROR);
     604           0 :                 return;
     605             :         }
     606         388 :         subreq = tstream_read_packet_send(state, state->ev,
     607         388 :                                           state->reader->sock,
     608             :                                           1, NULL, NULL);
     609         388 :         if (tevent_req_nomem(subreq, req)) {
     610           0 :                 return;
     611             :         }
     612         388 :         tevent_req_set_callback(subreq, nb_packet_reader_got_ack, req);
     613             : }
     614             : 
     615         388 : static void nb_packet_reader_got_ack(struct tevent_req *subreq)
     616             : {
     617         388 :         struct tevent_req *req = tevent_req_callback_data(
     618             :                 subreq, struct tevent_req);
     619         388 :         struct nb_packet_reader_state *state = tevent_req_data(
     620             :                 req, struct nb_packet_reader_state);
     621           0 :         ssize_t nread;
     622           0 :         int err;
     623           0 :         uint8_t *buf;
     624             : 
     625         388 :         nread = tstream_read_packet_recv(subreq, state, &buf, &err);
     626         388 :         TALLOC_FREE(subreq);
     627         388 :         if (nread == -1) {
     628           0 :                 DEBUG(10, ("read_packet_recv returned %s\n",
     629             :                            strerror(err)));
     630           0 :                 tevent_req_nterror(req, map_nt_error_from_unix(err));
     631           0 :                 return;
     632             :         }
     633         388 :         if (nread != 1) {
     634           0 :                 DBG_DEBUG("read = %zd, expected 1\n", nread);
     635           0 :                 tevent_req_nterror(req, NT_STATUS_UNEXPECTED_IO_ERROR);
     636           0 :                 return;
     637             :         }
     638         388 :         tevent_req_done(req);
     639             : }
     640             : 
     641         866 : NTSTATUS nb_packet_reader_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     642             :                                struct nb_packet_reader **preader)
     643             : {
     644         866 :         struct nb_packet_reader_state *state = tevent_req_data(
     645             :                 req, struct nb_packet_reader_state);
     646           0 :         NTSTATUS status;
     647             : 
     648         866 :         if (tevent_req_is_nterror(req, &status)) {
     649         478 :                 tevent_req_received(req);
     650         478 :                 return status;
     651             :         }
     652         388 :         *preader = talloc_move(mem_ctx, &state->reader);
     653         388 :         tevent_req_received(req);
     654         388 :         return NT_STATUS_OK;
     655             : }
     656             : 
     657             : struct nb_packet_read_state {
     658             :         struct nb_packet_client_header hdr;
     659             :         uint8_t *buf;
     660             :         size_t buflen;
     661             : };
     662             : 
     663             : static ssize_t nb_packet_read_more(uint8_t *buf, size_t buflen, void *p);
     664             : static void nb_packet_read_done(struct tevent_req *subreq);
     665             : 
     666         386 : struct tevent_req *nb_packet_read_send(TALLOC_CTX *mem_ctx,
     667             :                                        struct tevent_context *ev,
     668             :                                        struct nb_packet_reader *reader)
     669             : {
     670           0 :         struct tevent_req *req, *subreq;
     671           0 :         struct nb_packet_read_state *state;
     672             : 
     673         386 :         req = tevent_req_create(mem_ctx, &state, struct nb_packet_read_state);
     674         386 :         if (req == NULL) {
     675           0 :                 return NULL;
     676             :         }
     677         386 :         subreq = tstream_read_packet_send(state, ev, reader->sock,
     678             :                                           sizeof(struct nb_packet_client_header),
     679             :                                           nb_packet_read_more, state);
     680         386 :         if (tevent_req_nomem(subreq, req)) {
     681           0 :                 return tevent_req_post(req, ev);
     682             :         }
     683         386 :         tevent_req_set_callback(subreq, nb_packet_read_done, req);
     684         386 :         return req;
     685             : }
     686             : 
     687           6 : static ssize_t nb_packet_read_more(uint8_t *buf, size_t buflen, void *p)
     688             : {
     689           6 :         struct nb_packet_read_state *state = talloc_get_type_abort(
     690             :                 p, struct nb_packet_read_state);
     691             : 
     692           6 :         if (buflen > sizeof(struct nb_packet_client_header)) {
     693             :                 /*
     694             :                  * Been here, done
     695             :                  */
     696           3 :                 return 0;
     697             :         }
     698           3 :         memcpy(&state->hdr, buf, sizeof(struct nb_packet_client_header));
     699           3 :         return state->hdr.len;
     700             : }
     701             : 
     702           3 : static void nb_packet_read_done(struct tevent_req *subreq)
     703             : {
     704           3 :         struct tevent_req *req = tevent_req_callback_data(
     705             :                 subreq, struct tevent_req);
     706           3 :         struct nb_packet_read_state *state = tevent_req_data(
     707             :                 req, struct nb_packet_read_state);
     708           0 :         ssize_t nread;
     709           0 :         int err;
     710             : 
     711           3 :         nread = tstream_read_packet_recv(subreq, state, &state->buf, &err);
     712           3 :         if (nread == -1) {
     713           0 :                 tevent_req_nterror(req, map_nt_error_from_unix(err));
     714           0 :                 return;
     715             :         }
     716           3 :         state->buflen = nread;
     717           3 :         tevent_req_done(req);
     718             : }
     719             : 
     720           3 : NTSTATUS nb_packet_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     721             :                              struct packet_struct **ppacket)
     722             : {
     723           3 :         struct nb_packet_read_state *state = tevent_req_data(
     724             :                 req, struct nb_packet_read_state);
     725           0 :         struct nb_packet_client_header hdr;
     726           0 :         struct packet_struct *packet;
     727           0 :         NTSTATUS status;
     728             : 
     729           3 :         if (tevent_req_is_nterror(req, &status)) {
     730           0 :                 tevent_req_received(req);
     731           0 :                 return status;
     732             :         }
     733             : 
     734           3 :         memcpy(&hdr, state->buf, sizeof(hdr));
     735             : 
     736           3 :         packet = parse_packet_talloc(
     737             :                 mem_ctx,
     738           3 :                 (char *)state->buf + sizeof(struct nb_packet_client_header),
     739           3 :                 state->buflen - sizeof(struct nb_packet_client_header),
     740             :                 state->hdr.type, state->hdr.ip, state->hdr.port);
     741           3 :         if (packet == NULL) {
     742           0 :                 tevent_req_received(req);
     743           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     744             :         }
     745             : 
     746           3 :         *ppacket = packet;
     747           3 :         tevent_req_received(req);
     748           3 :         return NT_STATUS_OK;
     749             : }

Generated by: LCOV version 1.14