Ignore:
Timestamp:
Nov 14, 2012, 12:59:34 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to 3.6.0

File:
1 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source3/libsmb/unexpected.c

    r414 r740  
    2020
    2121#include "includes.h"
    22 
    23 static TDB_CONTEXT *tdbd = NULL;
    24 
    25 /* the key type used in the unexpected packet database */
    26 struct unexpected_key {
    27         enum packet_type packet_type;
    28         time_t timestamp;
    29         int count;
     22#include "../lib/util/tevent_ntstatus.h"
     23#include "lib/async_req/async_sock.h"
     24#include "libsmb/nmblib.h"
     25
     26static const char *nmbd_socket_dir(void)
     27{
     28        return lp_parm_const_string(-1, "nmbd", "socket dir",
     29                                    get_dyn_NMBDSOCKETDIR());
     30}
     31
     32struct nb_packet_query {
     33        enum packet_type type;
     34        size_t mailslot_namelen;
     35        int trn_id;
    3036};
    3137
    32 /****************************************************************************
    33  All unexpected packets are passed in here, to be stored in a unexpected
    34  packet database. This allows nmblookup and other tools to receive packets
    35  erroneously sent to the wrong port by broken MS systems.
    36 **************************************************************************/
    37 
    38 void unexpected_packet(struct packet_struct *p)
    39 {
    40         static int count;
    41         TDB_DATA kbuf, dbuf;
    42         struct unexpected_key key;
    43         char buf[1024];
    44         int len=0;
    45         uint32_t enc_ip;
    46 
    47         if (!tdbd) {
    48                 tdbd = tdb_open_log(lock_path("unexpected.tdb"), 0,
    49                                TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
    50                                O_RDWR | O_CREAT, 0644);
    51                 if (!tdbd) {
    52                         DEBUG(0,("Failed to open unexpected.tdb\n"));
     38struct nb_packet_client;
     39
     40struct nb_packet_server {
     41        struct tevent_context *ev;
     42        int listen_sock;
     43        int max_clients;
     44        int num_clients;
     45        struct nb_packet_client *clients;
     46};
     47
     48struct nb_packet_client {
     49        struct nb_packet_client *prev, *next;
     50        struct nb_packet_server *server;
     51
     52        enum packet_type type;
     53        int trn_id;
     54        char *mailslot_name;
     55
     56        int sock;
     57        struct tevent_req *read_req;
     58        struct tevent_queue *out_queue;
     59};
     60
     61static int nb_packet_server_destructor(struct nb_packet_server *s);
     62static void nb_packet_server_listener(struct tevent_context *ev,
     63                                      struct tevent_fd *fde,
     64                                      uint16_t flags,
     65                                      void *private_data);
     66
     67NTSTATUS nb_packet_server_create(TALLOC_CTX *mem_ctx,
     68                                 struct tevent_context *ev,
     69                                 int max_clients,
     70                                 struct nb_packet_server **presult)
     71{
     72        struct nb_packet_server *result;
     73        struct tevent_fd *fde;
     74        NTSTATUS status;
     75
     76        result = TALLOC_ZERO_P(mem_ctx, struct nb_packet_server);
     77        if (result == NULL) {
     78                status = NT_STATUS_NO_MEMORY;
     79                goto fail;
     80        }
     81        result->ev = ev;
     82        result->max_clients = max_clients;
     83
     84        result->listen_sock = create_pipe_sock(
     85                nmbd_socket_dir(), "unexpected", 0755);
     86        if (result->listen_sock == -1) {
     87                status = map_nt_error_from_unix(errno);
     88                goto fail;
     89        }
     90        talloc_set_destructor(result, nb_packet_server_destructor);
     91
     92        fde = tevent_add_fd(ev, result, result->listen_sock, TEVENT_FD_READ,
     93                            nb_packet_server_listener, result);
     94        if (fde == NULL) {
     95                status = NT_STATUS_NO_MEMORY;
     96                goto fail;
     97        }
     98
     99        *presult = result;
     100        return NT_STATUS_OK;
     101fail:
     102        TALLOC_FREE(result);
     103        return status;
     104}
     105
     106static int nb_packet_server_destructor(struct nb_packet_server *s)
     107{
     108        if (s->listen_sock != -1) {
     109                close(s->listen_sock);
     110                s->listen_sock = -1;
     111        }
     112        return 0;
     113}
     114
     115static int nb_packet_client_destructor(struct nb_packet_client *c);
     116static ssize_t nb_packet_client_more(uint8_t *buf, size_t buflen,
     117                                     void *private_data);
     118static void nb_packet_got_query(struct tevent_req *req);
     119static void nb_packet_client_read_done(struct tevent_req *req);
     120
     121static void nb_packet_server_listener(struct tevent_context *ev,
     122                                      struct tevent_fd *fde,
     123                                      uint16_t flags,
     124                                      void *private_data)
     125{
     126        struct nb_packet_server *server = talloc_get_type_abort(
     127                private_data, struct nb_packet_server);
     128        struct nb_packet_client *client;
     129        struct tevent_req *req;
     130        struct sockaddr_un sunaddr;
     131        socklen_t len;
     132        int sock;
     133
     134        len = sizeof(sunaddr);
     135
     136        sock = accept(server->listen_sock, (struct sockaddr *)(void *)&sunaddr,
     137                      &len);
     138        if (sock == -1) {
     139                return;
     140        }
     141        DEBUG(6,("accepted socket %d\n", sock));
     142
     143        client = TALLOC_ZERO_P(server, struct nb_packet_client);
     144        if (client == NULL) {
     145                DEBUG(10, ("talloc failed\n"));
     146                close(sock);
     147                return;
     148        }
     149        client->sock = sock;
     150        client->server = server;
     151        talloc_set_destructor(client, nb_packet_client_destructor);
     152
     153        client->out_queue = tevent_queue_create(
     154                client, "unexpected packet output");
     155        if (client->out_queue == NULL) {
     156                DEBUG(10, ("tevent_queue_create failed\n"));
     157                TALLOC_FREE(client);
     158                return;
     159        }
     160
     161        req = read_packet_send(client, ev, client->sock,
     162                               sizeof(struct nb_packet_query),
     163                               nb_packet_client_more, NULL);
     164        if (req == NULL) {
     165                DEBUG(10, ("read_packet_send failed\n"));
     166                TALLOC_FREE(client);
     167                return;
     168        }
     169        tevent_req_set_callback(req, nb_packet_got_query, client);
     170
     171        DLIST_ADD(server->clients, client);
     172        server->num_clients += 1;
     173
     174        if (server->num_clients > server->max_clients) {
     175                DEBUG(10, ("Too many clients, dropping oldest\n"));
     176
     177                /*
     178                 * no TALLOC_FREE here, don't mess with the list structs
     179                 */
     180                talloc_free(server->clients->prev);
     181        }
     182}
     183
     184static ssize_t nb_packet_client_more(uint8_t *buf, size_t buflen,
     185                                     void *private_data)
     186{
     187        struct nb_packet_query q;
     188        if (buflen > sizeof(struct nb_packet_query)) {
     189                return 0;
     190        }
     191        /* Take care of alignment */
     192        memcpy(&q, buf, sizeof(q));
     193        if (q.mailslot_namelen > 1024) {
     194                DEBUG(10, ("Got invalid mailslot namelen %d\n",
     195                           (int)q.mailslot_namelen));
     196                return -1;
     197        }
     198        return q.mailslot_namelen;
     199}
     200
     201static int nb_packet_client_destructor(struct nb_packet_client *c)
     202{
     203        if (c->sock != -1) {
     204                close(c->sock);
     205                c->sock = -1;
     206        }
     207        DLIST_REMOVE(c->server->clients, c);
     208        c->server->num_clients -= 1;
     209        return 0;
     210}
     211
     212static void nb_packet_got_query(struct tevent_req *req)
     213{
     214        struct nb_packet_client *client = tevent_req_callback_data(
     215                req, struct nb_packet_client);
     216        struct nb_packet_query q;
     217        uint8_t *buf;
     218        ssize_t nread, nwritten;
     219        int err;
     220        char c;
     221
     222        nread = read_packet_recv(req, talloc_tos(), &buf, &err);
     223        TALLOC_FREE(req);
     224        if (nread < (ssize_t)sizeof(struct nb_packet_query)) {
     225                DEBUG(10, ("read_packet_recv returned %d (%s)\n",
     226                           (int)nread,
     227                           (nread == -1) ? strerror(err) : "wrong length"));
     228                TALLOC_FREE(client);
     229                return;
     230        }
     231
     232        /* Take care of alignment */
     233        memcpy(&q, buf, sizeof(q));
     234
     235        if (nread != sizeof(struct nb_packet_query) + q.mailslot_namelen) {
     236                DEBUG(10, ("nb_packet_got_query: Invalid mailslot namelength\n"));
     237                TALLOC_FREE(client);
     238                return;
     239        }
     240
     241        client->trn_id = q.trn_id;
     242        client->type = q.type;
     243        if (q.mailslot_namelen > 0) {
     244                client->mailslot_name = talloc_strndup(
     245                        client, (char *)buf + sizeof(q),
     246                        q.mailslot_namelen);
     247                if (client->mailslot_name == NULL) {
     248                        TALLOC_FREE(client);
    53249                        return;
    54250                }
    55251        }
    56252
    57         memset(buf,'\0',sizeof(buf));
    58 
    59         /* Encode the ip addr and port. */
    60         enc_ip = ntohl(p->ip.s_addr);
    61         SIVAL(buf,0,enc_ip);
    62         SSVAL(buf,4,p->port);
    63 
    64         len = build_packet(&buf[6], sizeof(buf)-6, p) + 6;
    65 
    66         ZERO_STRUCT(key);       /* needed for potential alignment */
    67 
    68         key.packet_type = p->packet_type;
    69         key.timestamp = p->timestamp;
    70         key.count = count++;
    71 
    72         kbuf.dptr = (uint8_t *)&key;
    73         kbuf.dsize = sizeof(key);
    74         dbuf.dptr = (uint8_t *)buf;
    75         dbuf.dsize = len;
    76 
    77         tdb_store(tdbd, kbuf, dbuf, TDB_REPLACE);
    78 }
    79 
    80 
    81 static time_t lastt;
    82 
    83 /****************************************************************************
    84  Delete the record if it is too old.
    85 **************************************************************************/
    86 
    87 static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
    88 {
    89         struct unexpected_key key;
    90 
    91         if (kbuf.dsize != sizeof(key)) {
    92                 tdb_delete(ttdb, kbuf);
    93         }
    94 
    95         memcpy(&key, kbuf.dptr, sizeof(key));
    96 
    97         if (lastt - key.timestamp > NMBD_UNEXPECTED_TIMEOUT) {
    98                 tdb_delete(ttdb, kbuf);
    99         }
    100 
     253        /*
     254         * Yes, this is a blocking write of 1 byte into a unix
     255         * domain socket that has never been written to. Highly
     256         * unlikely that this actually blocks.
     257         */
     258        c = 0;
     259        nwritten = sys_write(client->sock, &c, sizeof(c));
     260        if (nwritten != sizeof(c)) {
     261                DEBUG(10, ("Could not write success indicator to client: %s\n",
     262                           strerror(errno)));
     263                TALLOC_FREE(client);
     264                return;
     265        }
     266
     267        client->read_req = read_packet_send(client, client->server->ev,
     268                                            client->sock, 1, NULL, NULL);
     269        if (client->read_req == NULL) {
     270                DEBUG(10, ("Could not activate reader for client exit "
     271                           "detection\n"));
     272                TALLOC_FREE(client);
     273                return;
     274        }
     275        tevent_req_set_callback(client->read_req, nb_packet_client_read_done,
     276                                client);
     277}
     278
     279static void nb_packet_client_read_done(struct tevent_req *req)
     280{
     281        struct nb_packet_client *client = tevent_req_callback_data(
     282                req, struct nb_packet_client);
     283        ssize_t nread;
     284        uint8_t *buf;
     285        int err;
     286
     287        nread = read_packet_recv(req, talloc_tos(), &buf, &err);
     288        TALLOC_FREE(req);
     289        if (nread == 1) {
     290                DEBUG(10, ("Protocol error, received data on write-only "
     291                           "unexpected socket: 0x%2.2x\n", (*buf)));
     292        }
     293        TALLOC_FREE(client);
     294}
     295
     296static void nb_packet_client_send(struct nb_packet_client *client,
     297                                  struct packet_struct *p);
     298
     299void nb_packet_dispatch(struct nb_packet_server *server,
     300                        struct packet_struct *p)
     301{
     302        struct nb_packet_client *c;
     303        uint16_t trn_id;
     304
     305        switch (p->packet_type) {
     306        case NMB_PACKET:
     307                trn_id = p->packet.nmb.header.name_trn_id;
     308                break;
     309        case DGRAM_PACKET:
     310                trn_id = p->packet.dgram.header.dgm_id;
     311                break;
     312        default:
     313                DEBUG(10, ("Got invalid packet type %d\n",
     314                           (int)p->packet_type));
     315                return;
     316        }
     317        for (c = server->clients; c != NULL; c = c->next) {
     318
     319                if (c->type != p->packet_type) {
     320                        DEBUG(10, ("client expects packet %d, got %d\n",
     321                                   c->type, p->packet_type));
     322                        continue;
     323                }
     324
     325                if (p->packet_type == NMB_PACKET) {
     326                        /*
     327                         * See if the client specified transaction
     328                         * ID. Filter if it did.
     329                         */
     330                        if ((c->trn_id != -1) &&
     331                            (c->trn_id != trn_id)) {
     332                                DEBUG(10, ("client expects trn %d, got %d\n",
     333                                           c->trn_id, trn_id));
     334                                continue;
     335                        }
     336                } else {
     337                        /*
     338                         * See if the client specified a mailslot
     339                         * name. Filter if it did.
     340                         */
     341                        if ((c->mailslot_name != NULL) &&
     342                            !match_mailslot_name(p, c->mailslot_name)) {
     343                                continue;
     344                        }
     345                }
     346                nb_packet_client_send(c, p);
     347        }
     348}
     349
     350struct nb_packet_client_header {
     351        size_t len;
     352        enum packet_type type;
     353        time_t timestamp;
     354        struct in_addr ip;
     355        int port;
     356};
     357
     358struct nb_packet_client_state {
     359        struct nb_packet_client *client;
     360        struct iovec iov[2];
     361        struct nb_packet_client_header hdr;
     362        char buf[1024];
     363};
     364
     365static void nb_packet_client_send_done(struct tevent_req *req);
     366
     367static void nb_packet_client_send(struct nb_packet_client *client,
     368                                  struct packet_struct *p)
     369{
     370        struct nb_packet_client_state *state;
     371        struct tevent_req *req;
     372
     373        if (tevent_queue_length(client->out_queue) > 10) {
     374                /*
     375                 * Skip clients that don't listen anyway, some form of DoS
     376                 * protection
     377                 */
     378                return;
     379        }
     380
     381        state = TALLOC_ZERO_P(client, struct nb_packet_client_state);
     382        if (state == NULL) {
     383                DEBUG(10, ("talloc failed\n"));
     384                return;
     385        }
     386
     387        state->client = client;
     388
     389        state->hdr.ip = p->ip;
     390        state->hdr.port = p->port;
     391        state->hdr.timestamp = p->timestamp;
     392        state->hdr.type = p->packet_type;
     393        state->hdr.len = build_packet(state->buf, sizeof(state->buf), p);
     394
     395        state->iov[0].iov_base = (char *)&state->hdr;
     396        state->iov[0].iov_len = sizeof(state->hdr);
     397        state->iov[1].iov_base = state->buf;
     398        state->iov[1].iov_len = state->hdr.len;
     399
     400        TALLOC_FREE(client->read_req);
     401
     402        req = writev_send(client, client->server->ev, client->out_queue,
     403                          client->sock, true, state->iov, 2);
     404        if (req == NULL) {
     405                DEBUG(10, ("writev_send failed\n"));
     406                return;
     407        }
     408        tevent_req_set_callback(req, nb_packet_client_send_done, state);
     409}
     410
     411static void nb_packet_client_send_done(struct tevent_req *req)
     412{
     413        struct nb_packet_client_state *state = tevent_req_callback_data(
     414                req, struct nb_packet_client_state);
     415        struct nb_packet_client *client = state->client;
     416        ssize_t nwritten;
     417        int err;
     418
     419        nwritten = writev_recv(req, &err);
     420
     421        TALLOC_FREE(req);
     422        TALLOC_FREE(state);
     423
     424        if (nwritten == -1) {
     425                DEBUG(10, ("writev failed: %s\n", strerror(err)));
     426                TALLOC_FREE(client);
     427        }
     428
     429        if (tevent_queue_length(client->out_queue) == 0) {
     430                client->read_req = read_packet_send(client, client->server->ev,
     431                                                    client->sock, 1,
     432                                                    NULL, NULL);
     433                if (client->read_req == NULL) {
     434                        DEBUG(10, ("Could not activate reader for client exit "
     435                                   "detection\n"));
     436                        TALLOC_FREE(client);
     437                        return;
     438                }
     439                tevent_req_set_callback(client->read_req,
     440                                        nb_packet_client_read_done,
     441                                        client);
     442        }
     443}
     444
     445struct nb_packet_reader {
     446        int sock;
     447};
     448
     449struct nb_packet_reader_state {
     450        struct tevent_context *ev;
     451        struct sockaddr_un addr;
     452        struct nb_packet_query query;
     453        const char *mailslot_name;
     454        struct iovec iov[2];
     455        char c;
     456        struct nb_packet_reader *reader;
     457};
     458
     459static int nb_packet_reader_destructor(struct nb_packet_reader *r);
     460static void nb_packet_reader_connected(struct tevent_req *subreq);
     461static void nb_packet_reader_sent_query(struct tevent_req *subreq);
     462static void nb_packet_reader_got_ack(struct tevent_req *subreq);
     463
     464struct tevent_req *nb_packet_reader_send(TALLOC_CTX *mem_ctx,
     465                                         struct tevent_context *ev,
     466                                         enum packet_type type,
     467                                         int trn_id,
     468                                         const char *mailslot_name)
     469{
     470        struct tevent_req *req, *subreq;
     471        struct nb_packet_reader_state *state;
     472        char *path;
     473
     474        req = tevent_req_create(mem_ctx, &state,
     475                                struct nb_packet_reader_state);
     476        if (req == NULL) {
     477                return NULL;
     478        }
     479        state->ev = ev;
     480        state->query.trn_id = trn_id;
     481        state->query.type = type;
     482        state->mailslot_name = mailslot_name;
     483
     484        if (mailslot_name != NULL) {
     485                state->query.mailslot_namelen = strlen(mailslot_name);
     486        }
     487
     488        state->reader = TALLOC_ZERO_P(state, struct nb_packet_reader);
     489        if (tevent_req_nomem(state->reader, req)) {
     490                return tevent_req_post(req, ev);
     491        }
     492
     493        path = talloc_asprintf(talloc_tos(), "%s/%s", nmbd_socket_dir(),
     494                               "unexpected");
     495        if (tevent_req_nomem(path, req)) {
     496                return tevent_req_post(req, ev);
     497        }
     498        state->addr.sun_family = AF_UNIX;
     499        strlcpy(state->addr.sun_path, path, sizeof(state->addr.sun_path));
     500        TALLOC_FREE(path);
     501
     502        state->reader->sock = socket(AF_UNIX, SOCK_STREAM, 0);
     503        if (state->reader->sock == -1) {
     504                tevent_req_nterror(req, map_nt_error_from_unix(errno));
     505                return tevent_req_post(req, ev);
     506        }
     507        talloc_set_destructor(state->reader, nb_packet_reader_destructor);
     508
     509        subreq = async_connect_send(state, ev, state->reader->sock,
     510                                    (struct sockaddr *)(void *)&state->addr,
     511                                    sizeof(state->addr));
     512        if (tevent_req_nomem(subreq, req)) {
     513                return tevent_req_post(req, ev);
     514        }
     515        tevent_req_set_callback(subreq, nb_packet_reader_connected, req);
     516        return req;
     517}
     518
     519static int nb_packet_reader_destructor(struct nb_packet_reader *r)
     520{
     521        if (r->sock != -1) {
     522                close(r->sock);
     523                r->sock = -1;
     524        }
    101525        return 0;
    102526}
    103527
    104 
    105 /****************************************************************************
    106  Delete all old unexpected packets.
    107 **************************************************************************/
    108 
    109 void clear_unexpected(time_t t)
    110 {
    111         if (!tdbd) return;
    112 
    113         if ((lastt != 0) && (t < lastt + NMBD_UNEXPECTED_TIMEOUT))
    114                 return;
    115 
    116         lastt = t;
    117 
    118         tdb_traverse(tdbd, traverse_fn, NULL);
    119 }
    120 
    121 struct receive_unexpected_state {
    122         struct packet_struct *matched_packet;
    123         int match_id;
    124         enum packet_type match_type;
    125         const char *match_name;
     528static void nb_packet_reader_connected(struct tevent_req *subreq)
     529{
     530        struct tevent_req *req = tevent_req_callback_data(
     531                subreq, struct tevent_req);
     532        struct nb_packet_reader_state *state = tevent_req_data(
     533                req, struct nb_packet_reader_state);
     534        int res, err;
     535        int num_iovecs = 1;
     536
     537        res = async_connect_recv(subreq, &err);
     538        TALLOC_FREE(subreq);
     539        if (res == -1) {
     540                DEBUG(10, ("async_connect failed: %s\n", strerror(err)));
     541                tevent_req_nterror(req, map_nt_error_from_unix(err));
     542                return;
     543        }
     544
     545        state->iov[0].iov_base = (char *)&state->query;
     546        state->iov[0].iov_len = sizeof(state->query);
     547
     548        if (state->mailslot_name != NULL) {
     549                num_iovecs = 2;
     550                state->iov[1].iov_base = discard_const_p(
     551                        char, state->mailslot_name);
     552                state->iov[1].iov_len = state->query.mailslot_namelen;
     553        }
     554
     555        subreq = writev_send(state, state->ev, NULL, state->reader->sock,
     556                             true, state->iov, num_iovecs);
     557        if (tevent_req_nomem(subreq, req)) {
     558                return;
     559        }
     560        tevent_req_set_callback(subreq, nb_packet_reader_sent_query, req);
     561}
     562
     563static void nb_packet_reader_sent_query(struct tevent_req *subreq)
     564{
     565        struct tevent_req *req = tevent_req_callback_data(
     566                subreq, struct tevent_req);
     567        struct nb_packet_reader_state *state = tevent_req_data(
     568                req, struct nb_packet_reader_state);
     569        ssize_t written;
     570        int err;
     571
     572        written = writev_recv(subreq, &err);
     573        TALLOC_FREE(subreq);
     574        if (written == -1) {
     575                tevent_req_nterror(req, map_nt_error_from_unix(err));
     576                return;
     577        }
     578        if (written != sizeof(state->query) + state->query.mailslot_namelen) {
     579                tevent_req_nterror(req, NT_STATUS_UNEXPECTED_IO_ERROR);
     580                return;
     581        }
     582        subreq = read_packet_send(state, state->ev, state->reader->sock,
     583                                  sizeof(state->c), NULL, NULL);
     584        if (tevent_req_nomem(subreq, req)) {
     585                return;
     586        }
     587        tevent_req_set_callback(subreq, nb_packet_reader_got_ack, req);
     588}
     589
     590static void nb_packet_reader_got_ack(struct tevent_req *subreq)
     591{
     592        struct tevent_req *req = tevent_req_callback_data(
     593                subreq, struct tevent_req);
     594        struct nb_packet_reader_state *state = tevent_req_data(
     595                req, struct nb_packet_reader_state);
     596        ssize_t nread;
     597        int err;
     598        uint8_t *buf;
     599
     600        nread = read_packet_recv(subreq, state, &buf, &err);
     601        TALLOC_FREE(subreq);
     602        if (nread == -1) {
     603                DEBUG(10, ("read_packet_recv returned %s\n",
     604                           strerror(err)));
     605                tevent_req_nterror(req, map_nt_error_from_unix(err));
     606                return;
     607        }
     608        if (nread != sizeof(state->c)) {
     609                DEBUG(10, ("read = %d, expected %d\n", (int)nread,
     610                           (int)sizeof(state->c)));
     611                tevent_req_nterror(req, NT_STATUS_UNEXPECTED_IO_ERROR);
     612                return;
     613        }
     614        tevent_req_done(req);
     615}
     616
     617NTSTATUS nb_packet_reader_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     618                               struct nb_packet_reader **preader)
     619{
     620        struct nb_packet_reader_state *state = tevent_req_data(
     621                req, struct nb_packet_reader_state);
     622        NTSTATUS status;
     623
     624        if (tevent_req_is_nterror(req, &status)) {
     625                return status;
     626        }
     627        *preader = talloc_move(mem_ctx, &state->reader);
     628        return NT_STATUS_OK;
     629}
     630
     631struct nb_packet_read_state {
     632        struct nb_packet_client_header hdr;
     633        uint8_t *buf;
     634        size_t buflen;
    126635};
    127636
    128 /****************************************************************************
    129  tdb traversal fn to find a matching 137 packet.
    130 **************************************************************************/
    131 
    132 static int traverse_match(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf,
    133                           void *private_data)
    134 {
    135         struct receive_unexpected_state *state =
    136                 (struct receive_unexpected_state *)private_data;
    137         struct unexpected_key key;
    138         struct in_addr ip;
    139         uint32_t enc_ip;
    140         int port;
    141         struct packet_struct *p;
    142 
    143         if (kbuf.dsize != sizeof(key)) {
     637static ssize_t nb_packet_read_more(uint8_t *buf, size_t buflen, void *p);
     638static void nb_packet_read_done(struct tevent_req *subreq);
     639
     640struct tevent_req *nb_packet_read_send(TALLOC_CTX *mem_ctx,
     641                                       struct tevent_context *ev,
     642                                       struct nb_packet_reader *reader)
     643{
     644        struct tevent_req *req, *subreq;
     645        struct nb_packet_read_state *state;
     646
     647        req = tevent_req_create(mem_ctx, &state, struct nb_packet_read_state);
     648        if (req == NULL) {
     649                return NULL;
     650        }
     651        subreq = read_packet_send(state, ev, reader->sock,
     652                                  sizeof(struct nb_packet_client_header),
     653                                  nb_packet_read_more, state);
     654        if (tevent_req_nomem(subreq, req)) {
     655                return tevent_req_post(req, ev);
     656        }
     657        tevent_req_set_callback(subreq, nb_packet_read_done, req);
     658        return req;
     659}
     660
     661static ssize_t nb_packet_read_more(uint8_t *buf, size_t buflen, void *p)
     662{
     663        struct nb_packet_read_state *state = talloc_get_type_abort(
     664                p, struct nb_packet_read_state);
     665
     666        if (buflen > sizeof(struct nb_packet_client_header)) {
     667                /*
     668                 * Been here, done
     669                 */
    144670                return 0;
    145671        }
    146 
    147         memcpy(&key, kbuf.dptr, sizeof(key));
    148 
    149         if (key.packet_type != state->match_type) return 0;
    150 
    151         if (dbuf.dsize < 6) {
    152                 return 0;
    153         }
    154 
    155         /* Decode the ip addr and port. */
    156         enc_ip = IVAL(dbuf.dptr,0);
    157         ip.s_addr = htonl(enc_ip);
    158         port = SVAL(dbuf.dptr,4);
    159 
    160         p = parse_packet((char *)&dbuf.dptr[6],
    161                         dbuf.dsize-6,
    162                         state->match_type,
    163                         ip,
    164                         port);
    165         if (!p)
    166                 return 0;
    167 
    168         if ((state->match_type == NMB_PACKET &&
    169              p->packet.nmb.header.name_trn_id == state->match_id) ||
    170             (state->match_type == DGRAM_PACKET &&
    171              match_mailslot_name(p, state->match_name))) {
    172                 state->matched_packet = p;
    173                 return -1;
    174         }
    175 
    176         free_packet(p);
    177 
    178         return 0;
    179 }
    180 
    181 /****************************************************************************
    182  Check for a particular packet in the unexpected packet queue.
    183 **************************************************************************/
    184 
    185 struct packet_struct *receive_unexpected(enum packet_type packet_type, int id,
    186                                          const char *mailslot_name)
    187 {
    188         TDB_CONTEXT *tdb2;
    189         struct receive_unexpected_state state;
    190 
    191         tdb2 = tdb_open_log(lock_path("unexpected.tdb"), 0, 0, O_RDONLY, 0);
    192         if (!tdb2) return NULL;
    193 
    194         state.matched_packet = NULL;
    195         state.match_id = id;
    196         state.match_type = packet_type;
    197         state.match_name = mailslot_name;
    198 
    199         tdb_traverse(tdb2, traverse_match, &state);
    200 
    201         tdb_close(tdb2);
    202 
    203         return state.matched_packet;
    204 }
     672        memcpy(&state->hdr, buf, sizeof(struct nb_packet_client_header));
     673        return state->hdr.len;
     674}
     675
     676static void nb_packet_read_done(struct tevent_req *subreq)
     677{
     678        struct tevent_req *req = tevent_req_callback_data(
     679                subreq, struct tevent_req);
     680        struct nb_packet_read_state *state = tevent_req_data(
     681                req, struct nb_packet_read_state);
     682        ssize_t nread;
     683        int err;
     684
     685        nread = read_packet_recv(subreq, state, &state->buf, &err);
     686        if (nread == -1) {
     687                tevent_req_nterror(req, map_nt_error_from_unix(err));
     688                return;
     689        }
     690        state->buflen = nread;
     691        tevent_req_done(req);
     692}
     693
     694NTSTATUS nb_packet_read_recv(struct tevent_req *req,
     695                             struct packet_struct **ppacket)
     696{
     697        struct nb_packet_read_state *state = tevent_req_data(
     698                req, struct nb_packet_read_state);
     699        struct nb_packet_client_header hdr;
     700        struct packet_struct *packet;
     701        NTSTATUS status;
     702
     703        if (tevent_req_is_nterror(req, &status)) {
     704                return status;
     705        }
     706
     707        memcpy(&hdr, state->buf, sizeof(hdr));
     708
     709        packet = parse_packet(
     710                (char *)state->buf + sizeof(struct nb_packet_client_header),
     711                state->buflen - sizeof(struct nb_packet_client_header),
     712                state->hdr.type, state->hdr.ip, state->hdr.port);
     713        if (packet == NULL) {
     714                return NT_STATUS_INVALID_NETWORK_RESPONSE;
     715        }
     716        *ppacket = packet;
     717        return NT_STATUS_OK;
     718}
Note: See TracChangeset for help on using the changeset viewer.