Changeset 740 for vendor/current/source3/libsmb/unexpected.c
- Timestamp:
- Nov 14, 2012, 12:59:34 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/libsmb/unexpected.c
r414 r740 20 20 21 21 #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 26 static const char *nmbd_socket_dir(void) 27 { 28 return lp_parm_const_string(-1, "nmbd", "socket dir", 29 get_dyn_NMBDSOCKETDIR()); 30 } 31 32 struct nb_packet_query { 33 enum packet_type type; 34 size_t mailslot_namelen; 35 int trn_id; 30 36 }; 31 37 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")); 38 struct nb_packet_client; 39 40 struct 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 48 struct 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 61 static int nb_packet_server_destructor(struct nb_packet_server *s); 62 static void nb_packet_server_listener(struct tevent_context *ev, 63 struct tevent_fd *fde, 64 uint16_t flags, 65 void *private_data); 66 67 NTSTATUS 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; 101 fail: 102 TALLOC_FREE(result); 103 return status; 104 } 105 106 static 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 115 static int nb_packet_client_destructor(struct nb_packet_client *c); 116 static ssize_t nb_packet_client_more(uint8_t *buf, size_t buflen, 117 void *private_data); 118 static void nb_packet_got_query(struct tevent_req *req); 119 static void nb_packet_client_read_done(struct tevent_req *req); 120 121 static 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 184 static 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 201 static 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 212 static 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); 53 249 return; 54 250 } 55 251 } 56 252 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 279 static 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 296 static void nb_packet_client_send(struct nb_packet_client *client, 297 struct packet_struct *p); 298 299 void 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 350 struct 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 358 struct 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 365 static void nb_packet_client_send_done(struct tevent_req *req); 366 367 static 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 411 static 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 445 struct nb_packet_reader { 446 int sock; 447 }; 448 449 struct 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 459 static int nb_packet_reader_destructor(struct nb_packet_reader *r); 460 static void nb_packet_reader_connected(struct tevent_req *subreq); 461 static void nb_packet_reader_sent_query(struct tevent_req *subreq); 462 static void nb_packet_reader_got_ack(struct tevent_req *subreq); 463 464 struct 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 519 static 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 } 101 525 return 0; 102 526 } 103 527 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; 528 static 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 563 static 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 590 static 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 617 NTSTATUS 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 631 struct nb_packet_read_state { 632 struct nb_packet_client_header hdr; 633 uint8_t *buf; 634 size_t buflen; 126 635 }; 127 636 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)) { 637 static ssize_t nb_packet_read_more(uint8_t *buf, size_t buflen, void *p); 638 static void nb_packet_read_done(struct tevent_req *subreq); 639 640 struct 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 661 static 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 */ 144 670 return 0; 145 671 } 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 676 static 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 694 NTSTATUS 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.