1/* 2 Unix SMB/CIFS implementation. 3 4 low level socket handling for nbt requests 5 6 Copyright (C) Andrew Tridgell 2005 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21 22#include "includes.h" 23#include "lib/events/events.h" 24#include "../lib/util/dlinklist.h" 25#include "../libcli/nbt/libnbt.h" 26#include "../libcli/nbt/nbt_proto.h" 27#include "lib/socket/socket.h" 28#include "librpc/gen_ndr/ndr_nbt.h" 29#include "param/param.h" 30 31#define NBT_MAX_REPLIES 1000 32 33/* 34 destroy a pending request 35*/ 36static int nbt_name_request_destructor(struct nbt_name_request *req) 37{ 38 if (req->state == NBT_REQUEST_SEND) { 39 DLIST_REMOVE(req->nbtsock->send_queue, req); 40 } 41 if (req->state == NBT_REQUEST_WAIT) { 42 req->nbtsock->num_pending--; 43 } 44 if (req->name_trn_id != 0 && !req->is_reply) { 45 idr_remove(req->nbtsock->idr, req->name_trn_id); 46 req->name_trn_id = 0; 47 } 48 if (req->te) { 49 talloc_free(req->te); 50 req->te = NULL; 51 } 52 if (req->nbtsock->send_queue == NULL) { 53 EVENT_FD_NOT_WRITEABLE(req->nbtsock->fde); 54 } 55 if (req->nbtsock->num_pending == 0 && 56 req->nbtsock->incoming.handler == NULL) { 57 EVENT_FD_NOT_READABLE(req->nbtsock->fde); 58 } 59 return 0; 60} 61 62 63/* 64 handle send events on a nbt name socket 65*/ 66static void nbt_name_socket_send(struct nbt_name_socket *nbtsock) 67{ 68 struct nbt_name_request *req = nbtsock->send_queue; 69 TALLOC_CTX *tmp_ctx = talloc_new(nbtsock); 70 NTSTATUS status; 71 72 while ((req = nbtsock->send_queue)) { 73 size_t len; 74 75 len = req->encoded.length; 76 status = socket_sendto(nbtsock->sock, &req->encoded, &len, 77 req->dest); 78 if (NT_STATUS_IS_ERR(status)) goto failed; 79 80 if (!NT_STATUS_IS_OK(status)) { 81 talloc_free(tmp_ctx); 82 return; 83 } 84 85 DLIST_REMOVE(nbtsock->send_queue, req); 86 req->state = NBT_REQUEST_WAIT; 87 if (req->is_reply) { 88 talloc_free(req); 89 } else { 90 EVENT_FD_READABLE(nbtsock->fde); 91 nbtsock->num_pending++; 92 } 93 } 94 95 EVENT_FD_NOT_WRITEABLE(nbtsock->fde); 96 talloc_free(tmp_ctx); 97 return; 98 99failed: 100 DLIST_REMOVE(nbtsock->send_queue, req); 101 nbt_name_request_destructor(req); 102 req->status = status; 103 req->state = NBT_REQUEST_ERROR; 104 talloc_free(tmp_ctx); 105 if (req->async.fn) { 106 req->async.fn(req); 107 } else if (req->is_reply) { 108 talloc_free(req); 109 } 110 return; 111} 112 113 114/* 115 handle a request timeout 116*/ 117static void nbt_name_socket_timeout(struct tevent_context *ev, struct tevent_timer *te, 118 struct timeval t, void *private_data) 119{ 120 struct nbt_name_request *req = talloc_get_type(private_data, 121 struct nbt_name_request); 122 123 if (req->num_retries != 0) { 124 req->num_retries--; 125 req->te = event_add_timed(req->nbtsock->event_ctx, req, 126 timeval_add(&t, req->timeout, 0), 127 nbt_name_socket_timeout, req); 128 if (req->state != NBT_REQUEST_SEND) { 129 req->state = NBT_REQUEST_SEND; 130 DLIST_ADD_END(req->nbtsock->send_queue, req, 131 struct nbt_name_request *); 132 } 133 EVENT_FD_WRITEABLE(req->nbtsock->fde); 134 return; 135 } 136 137 nbt_name_request_destructor(req); 138 if (req->num_replies == 0) { 139 req->state = NBT_REQUEST_TIMEOUT; 140 req->status = NT_STATUS_IO_TIMEOUT; 141 } else { 142 req->state = NBT_REQUEST_DONE; 143 req->status = NT_STATUS_OK; 144 } 145 if (req->async.fn) { 146 req->async.fn(req); 147 } else if (req->is_reply) { 148 talloc_free(req); 149 } 150} 151 152 153 154/** 155 handle recv events on a nbt name socket 156*/ 157static void nbt_name_socket_recv(struct nbt_name_socket *nbtsock) 158{ 159 TALLOC_CTX *tmp_ctx = talloc_new(nbtsock); 160 NTSTATUS status; 161 enum ndr_err_code ndr_err; 162 struct socket_address *src; 163 DATA_BLOB blob; 164 size_t nread, dsize; 165 struct nbt_name_packet *packet; 166 struct nbt_name_request *req; 167 168 status = socket_pending(nbtsock->sock, &dsize); 169 if (!NT_STATUS_IS_OK(status)) { 170 talloc_free(tmp_ctx); 171 return; 172 } 173 174 blob = data_blob_talloc(tmp_ctx, NULL, dsize); 175 if (blob.data == NULL) { 176 talloc_free(tmp_ctx); 177 return; 178 } 179 180 status = socket_recvfrom(nbtsock->sock, blob.data, blob.length, &nread, 181 tmp_ctx, &src); 182 if (!NT_STATUS_IS_OK(status)) { 183 talloc_free(tmp_ctx); 184 return; 185 } 186 187 packet = talloc(tmp_ctx, struct nbt_name_packet); 188 if (packet == NULL) { 189 talloc_free(tmp_ctx); 190 return; 191 } 192 193 /* parse the request */ 194 ndr_err = ndr_pull_struct_blob(&blob, packet, nbtsock->iconv_convenience, packet, 195 (ndr_pull_flags_fn_t)ndr_pull_nbt_name_packet); 196 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 197 status = ndr_map_error2ntstatus(ndr_err); 198 DEBUG(2,("Failed to parse incoming NBT name packet - %s\n", 199 nt_errstr(status))); 200 talloc_free(tmp_ctx); 201 return; 202 } 203 204 if (DEBUGLVL(10)) { 205 DEBUG(10,("Received nbt packet of length %d from %s:%d\n", 206 (int)blob.length, src->addr, src->port)); 207 NDR_PRINT_DEBUG(nbt_name_packet, packet); 208 } 209 210 /* if its not a reply then pass it off to the incoming request 211 handler, if any */ 212 if (!(packet->operation & NBT_FLAG_REPLY)) { 213 if (nbtsock->incoming.handler) { 214 nbtsock->incoming.handler(nbtsock, packet, src); 215 } 216 talloc_free(tmp_ctx); 217 return; 218 } 219 220 /* find the matching request */ 221 req = (struct nbt_name_request *)idr_find(nbtsock->idr, 222 packet->name_trn_id); 223 if (req == NULL) { 224 if (nbtsock->unexpected.handler) { 225 nbtsock->unexpected.handler(nbtsock, packet, src); 226 } else { 227 DEBUG(10,("Failed to match request for incoming name packet id 0x%04x on %p\n", 228 packet->name_trn_id, nbtsock)); 229 } 230 talloc_free(tmp_ctx); 231 return; 232 } 233 234 talloc_steal(req, packet); 235 talloc_steal(req, src); 236 talloc_free(tmp_ctx); 237 nbt_name_socket_handle_response_packet(req, packet, src); 238} 239 240void nbt_name_socket_handle_response_packet(struct nbt_name_request *req, 241 struct nbt_name_packet *packet, 242 struct socket_address *src) 243{ 244 /* if this is a WACK response, this we need to go back to waiting, 245 but perhaps increase the timeout */ 246 if ((packet->operation & NBT_OPCODE) == NBT_OPCODE_WACK) { 247 uint32_t ttl; 248 if (req->received_wack || packet->ancount < 1) { 249 nbt_name_request_destructor(req); 250 req->status = NT_STATUS_INVALID_NETWORK_RESPONSE; 251 req->state = NBT_REQUEST_ERROR; 252 goto done; 253 } 254 talloc_free(req->te); 255 /* we know we won't need any more retries - the server 256 has received our request */ 257 req->num_retries = 0; 258 req->received_wack = true; 259 /* 260 * there is a timeout in the packet, 261 * it is 5 + 4 * num_old_addresses 262 * 263 * although w2k3 screws it up 264 * and uses num_old_addresses = 0 265 * 266 * so we better fallback to the maximum 267 * of num_old_addresses = 25 if we got 268 * a timeout of less than 9s (5 + 4*1) 269 * or more than 105s (5 + 4*25). 270 */ 271 ttl = packet->answers[0].ttl; 272 if ((ttl < (5 + 4*1)) || (ttl > (5 + 4*25))) { 273 ttl = 5 + 4*25; 274 } 275 req->timeout = ttl; 276 req->te = event_add_timed(req->nbtsock->event_ctx, req, 277 timeval_current_ofs(req->timeout, 0), 278 nbt_name_socket_timeout, req); 279 return; 280 } 281 282 283 req->replies = talloc_realloc(req, req->replies, struct nbt_name_reply, req->num_replies+1); 284 if (req->replies == NULL) { 285 nbt_name_request_destructor(req); 286 req->state = NBT_REQUEST_ERROR; 287 req->status = NT_STATUS_NO_MEMORY; 288 goto done; 289 } 290 291 talloc_steal(req, src); 292 req->replies[req->num_replies].dest = src; 293 talloc_steal(req, packet); 294 req->replies[req->num_replies].packet = packet; 295 req->num_replies++; 296 297 /* if we don't want multiple replies then we are done */ 298 if (req->allow_multiple_replies && 299 req->num_replies < NBT_MAX_REPLIES) { 300 return; 301 } 302 303 nbt_name_request_destructor(req); 304 req->state = NBT_REQUEST_DONE; 305 req->status = NT_STATUS_OK; 306 307done: 308 if (req->async.fn) { 309 req->async.fn(req); 310 } 311} 312 313/* 314 handle fd events on a nbt_name_socket 315*/ 316static void nbt_name_socket_handler(struct tevent_context *ev, struct tevent_fd *fde, 317 uint16_t flags, void *private_data) 318{ 319 struct nbt_name_socket *nbtsock = talloc_get_type(private_data, 320 struct nbt_name_socket); 321 if (flags & EVENT_FD_WRITE) { 322 nbt_name_socket_send(nbtsock); 323 } 324 if (flags & EVENT_FD_READ) { 325 nbt_name_socket_recv(nbtsock); 326 } 327} 328 329 330/* 331 initialise a nbt_name_socket. The event_ctx is optional, if provided 332 then operations will use that event context 333*/ 334_PUBLIC_ struct nbt_name_socket *nbt_name_socket_init(TALLOC_CTX *mem_ctx, 335 struct tevent_context *event_ctx, 336 struct smb_iconv_convenience *iconv_convenience) 337{ 338 struct nbt_name_socket *nbtsock; 339 NTSTATUS status; 340 341 nbtsock = talloc(mem_ctx, struct nbt_name_socket); 342 if (nbtsock == NULL) goto failed; 343 344 nbtsock->event_ctx = talloc_reference(nbtsock, event_ctx); 345 if (nbtsock->event_ctx == NULL) goto failed; 346 347 status = socket_create("ip", SOCKET_TYPE_DGRAM, &nbtsock->sock, 0); 348 if (!NT_STATUS_IS_OK(status)) goto failed; 349 350 socket_set_option(nbtsock->sock, "SO_BROADCAST", "1"); 351 352 talloc_steal(nbtsock, nbtsock->sock); 353 354 nbtsock->idr = idr_init(nbtsock); 355 if (nbtsock->idr == NULL) goto failed; 356 357 nbtsock->send_queue = NULL; 358 nbtsock->num_pending = 0; 359 nbtsock->incoming.handler = NULL; 360 nbtsock->unexpected.handler = NULL; 361 nbtsock->iconv_convenience = iconv_convenience; 362 363 nbtsock->fde = event_add_fd(nbtsock->event_ctx, nbtsock, 364 socket_get_fd(nbtsock->sock), 0, 365 nbt_name_socket_handler, nbtsock); 366 367 return nbtsock; 368 369failed: 370 talloc_free(nbtsock); 371 return NULL; 372} 373 374/* 375 send off a nbt name request 376*/ 377struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock, 378 struct socket_address *dest, 379 struct nbt_name_packet *request, 380 int timeout, int retries, 381 bool allow_multiple_replies) 382{ 383 struct nbt_name_request *req; 384 int id; 385 enum ndr_err_code ndr_err; 386 387 req = talloc_zero(nbtsock, struct nbt_name_request); 388 if (req == NULL) goto failed; 389 390 req->nbtsock = nbtsock; 391 req->allow_multiple_replies = allow_multiple_replies; 392 req->state = NBT_REQUEST_SEND; 393 req->is_reply = false; 394 req->timeout = timeout; 395 req->num_retries = retries; 396 req->dest = dest; 397 if (talloc_reference(req, dest) == NULL) goto failed; 398 399 /* we select a random transaction id unless the user supplied one */ 400 if (request->name_trn_id == 0) { 401 id = idr_get_new_random(req->nbtsock->idr, req, UINT16_MAX); 402 } else { 403 if (idr_find(req->nbtsock->idr, request->name_trn_id)) goto failed; 404 id = idr_get_new_above(req->nbtsock->idr, req, request->name_trn_id, 405 UINT16_MAX); 406 } 407 if (id == -1) goto failed; 408 409 request->name_trn_id = id; 410 req->name_trn_id = id; 411 412 req->te = event_add_timed(nbtsock->event_ctx, req, 413 timeval_current_ofs(req->timeout, 0), 414 nbt_name_socket_timeout, req); 415 416 talloc_set_destructor(req, nbt_name_request_destructor); 417 418 ndr_err = ndr_push_struct_blob(&req->encoded, req, 419 req->nbtsock->iconv_convenience, 420 request, 421 (ndr_push_flags_fn_t)ndr_push_nbt_name_packet); 422 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) goto failed; 423 424 DLIST_ADD_END(nbtsock->send_queue, req, struct nbt_name_request *); 425 426 if (DEBUGLVL(10)) { 427 DEBUG(10,("Queueing nbt packet to %s:%d\n", 428 req->dest->addr, req->dest->port)); 429 NDR_PRINT_DEBUG(nbt_name_packet, request); 430 } 431 432 EVENT_FD_WRITEABLE(nbtsock->fde); 433 434 return req; 435 436failed: 437 talloc_free(req); 438 return NULL; 439} 440 441 442/* 443 send off a nbt name reply 444*/ 445_PUBLIC_ NTSTATUS nbt_name_reply_send(struct nbt_name_socket *nbtsock, 446 struct socket_address *dest, 447 struct nbt_name_packet *request) 448{ 449 struct nbt_name_request *req; 450 enum ndr_err_code ndr_err; 451 452 req = talloc_zero(nbtsock, struct nbt_name_request); 453 NT_STATUS_HAVE_NO_MEMORY(req); 454 455 req->nbtsock = nbtsock; 456 req->dest = dest; 457 if (talloc_reference(req, dest) == NULL) goto failed; 458 req->state = NBT_REQUEST_SEND; 459 req->is_reply = true; 460 461 talloc_set_destructor(req, nbt_name_request_destructor); 462 463 if (DEBUGLVL(10)) { 464 NDR_PRINT_DEBUG(nbt_name_packet, request); 465 } 466 467 ndr_err = ndr_push_struct_blob(&req->encoded, req, 468 req->nbtsock->iconv_convenience, 469 request, 470 (ndr_push_flags_fn_t)ndr_push_nbt_name_packet); 471 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 472 talloc_free(req); 473 return ndr_map_error2ntstatus(ndr_err); 474 } 475 476 DLIST_ADD_END(nbtsock->send_queue, req, struct nbt_name_request *); 477 478 EVENT_FD_WRITEABLE(nbtsock->fde); 479 480 return NT_STATUS_OK; 481 482failed: 483 talloc_free(req); 484 return NT_STATUS_NO_MEMORY; 485} 486 487/* 488 wait for a nbt request to complete 489*/ 490NTSTATUS nbt_name_request_recv(struct nbt_name_request *req) 491{ 492 if (!req) return NT_STATUS_NO_MEMORY; 493 494 while (req->state < NBT_REQUEST_DONE) { 495 if (event_loop_once(req->nbtsock->event_ctx) != 0) { 496 req->state = NBT_REQUEST_ERROR; 497 req->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR; 498 break; 499 } 500 } 501 return req->status; 502} 503 504 505/* 506 setup a handler for incoming requests 507*/ 508_PUBLIC_ NTSTATUS nbt_set_incoming_handler(struct nbt_name_socket *nbtsock, 509 void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *, 510 struct socket_address *), 511 void *private_data) 512{ 513 nbtsock->incoming.handler = handler; 514 nbtsock->incoming.private_data = private_data; 515 EVENT_FD_READABLE(nbtsock->fde); 516 return NT_STATUS_OK; 517} 518 519/* 520 setup a handler for unexpected requests 521*/ 522NTSTATUS nbt_set_unexpected_handler(struct nbt_name_socket *nbtsock, 523 void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *, 524 struct socket_address *), 525 void *private_data) 526{ 527 nbtsock->unexpected.handler = handler; 528 nbtsock->unexpected.private_data = private_data; 529 EVENT_FD_READABLE(nbtsock->fde); 530 return NT_STATUS_OK; 531} 532 533/* 534 turn a NBT rcode into a NTSTATUS 535*/ 536_PUBLIC_ NTSTATUS nbt_rcode_to_ntstatus(uint8_t rcode) 537{ 538 int i; 539 struct { 540 enum nbt_rcode rcode; 541 NTSTATUS status; 542 } map[] = { 543 { NBT_RCODE_FMT, NT_STATUS_INVALID_PARAMETER }, 544 { NBT_RCODE_SVR, NT_STATUS_SERVER_DISABLED }, 545 { NBT_RCODE_NAM, NT_STATUS_OBJECT_NAME_NOT_FOUND }, 546 { NBT_RCODE_IMP, NT_STATUS_NOT_SUPPORTED }, 547 { NBT_RCODE_RFS, NT_STATUS_ACCESS_DENIED }, 548 { NBT_RCODE_ACT, NT_STATUS_ADDRESS_ALREADY_EXISTS }, 549 { NBT_RCODE_CFT, NT_STATUS_CONFLICTING_ADDRESSES } 550 }; 551 for (i=0;i<ARRAY_SIZE(map);i++) { 552 if (map[i].rcode == rcode) { 553 return map[i].status; 554 } 555 } 556 return NT_STATUS_UNSUCCESSFUL; 557} 558