root/libcli/nbt/nameregister.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nbt_name_register_send
  2. nbt_name_register_recv
  3. nbt_name_register
  4. name_register_bcast_handler
  5. nbt_name_register_bcast_send
  6. nbt_name_register_bcast_recv
  7. nbt_name_register_bcast
  8. name_register_wins_handler
  9. nbt_name_register_wins_send
  10. nbt_name_register_wins_recv
  11. nbt_name_register_wins

   1 /*
   2    Unix SMB/CIFS implementation.
   3 
   4    send out a name registration request
   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 "../libcli/nbt/libnbt.h"
  24 #include "../libcli/nbt/nbt_proto.h"
  25 #include "libcli/composite/composite.h"
  26 #include "lib/socket/socket.h"
  27 #include "librpc/gen_ndr/ndr_nbt.h"
  28 
  29 /*
  30   send a nbt name registration request
  31 */
  32 struct nbt_name_request *nbt_name_register_send(struct nbt_name_socket *nbtsock,
     /* [<][>][^][v][top][bottom][index][help] */
  33                                                 struct nbt_name_register *io)
  34 {
  35         struct nbt_name_request *req;
  36         struct nbt_name_packet *packet;
  37         struct socket_address *dest;
  38 
  39         packet = talloc_zero(nbtsock, struct nbt_name_packet);
  40         if (packet == NULL) return NULL;
  41 
  42         packet->qdcount = 1;
  43         packet->arcount = 1;
  44         if (io->in.multi_homed) {
  45                 packet->operation = NBT_OPCODE_MULTI_HOME_REG;
  46         } else {
  47                 packet->operation = NBT_OPCODE_REGISTER;
  48         }
  49         if (io->in.broadcast) {
  50                 packet->operation |= NBT_FLAG_BROADCAST;
  51         }
  52         if (io->in.register_demand) {
  53                 packet->operation |= NBT_FLAG_RECURSION_DESIRED;
  54         }
  55 
  56         packet->questions = talloc_array(packet, struct nbt_name_question, 1);
  57         if (packet->questions == NULL) goto failed;
  58 
  59         packet->questions[0].name           = io->in.name;
  60         packet->questions[0].question_type  = NBT_QTYPE_NETBIOS;
  61         packet->questions[0].question_class = NBT_QCLASS_IP;
  62 
  63         packet->additional = talloc_array(packet, struct nbt_res_rec, 1);
  64         if (packet->additional == NULL) goto failed;
  65 
  66         packet->additional[0].name                   = io->in.name;
  67         packet->additional[0].rr_type                = NBT_QTYPE_NETBIOS;
  68         packet->additional[0].rr_class               = NBT_QCLASS_IP;
  69         packet->additional[0].ttl                    = io->in.ttl;
  70         packet->additional[0].rdata.netbios.length   = 6;
  71         packet->additional[0].rdata.netbios.addresses = talloc_array(packet->additional,
  72                                                                      struct nbt_rdata_address, 1);
  73         if (packet->additional[0].rdata.netbios.addresses == NULL) goto failed;
  74         packet->additional[0].rdata.netbios.addresses[0].nb_flags = io->in.nb_flags;
  75         packet->additional[0].rdata.netbios.addresses[0].ipaddr =
  76                 talloc_strdup(packet->additional, io->in.address);
  77         if (packet->additional[0].rdata.netbios.addresses[0].ipaddr == NULL) goto failed;
  78 
  79         dest = socket_address_from_strings(packet, nbtsock->sock->backend_name,
  80                                            io->in.dest_addr, io->in.dest_port);
  81         if (dest == NULL) goto failed;
  82         req = nbt_name_request_send(nbtsock, dest, packet,
  83                                     io->in.timeout, io->in.retries, false);
  84         if (req == NULL) goto failed;
  85 
  86         talloc_free(packet);
  87         return req;
  88 
  89 failed:
  90         talloc_free(packet);
  91         return NULL;
  92 }
  93 
  94 /*
  95   wait for a registration reply
  96 */
  97 _PUBLIC_ NTSTATUS nbt_name_register_recv(struct nbt_name_request *req,
     /* [<][>][^][v][top][bottom][index][help] */
  98                                 TALLOC_CTX *mem_ctx, struct nbt_name_register *io)
  99 {
 100         NTSTATUS status;
 101         struct nbt_name_packet *packet;
 102 
 103         status = nbt_name_request_recv(req);
 104         if (!NT_STATUS_IS_OK(status) ||
 105             req->num_replies == 0) {
 106                 talloc_free(req);
 107                 return status;
 108         }
 109 
 110         packet = req->replies[0].packet;
 111         io->out.reply_from = talloc_steal(mem_ctx, req->replies[0].dest->addr);
 112 
 113         if (packet->ancount != 1 ||
 114             packet->answers[0].rr_type != NBT_QTYPE_NETBIOS ||
 115             packet->answers[0].rr_class != NBT_QCLASS_IP) {
 116                 talloc_free(req);
 117                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
 118         }
 119 
 120         io->out.rcode = packet->operation & NBT_RCODE;
 121         io->out.name = packet->answers[0].name;
 122         if (packet->answers[0].rdata.netbios.length < 6) {
 123                 talloc_free(req);
 124                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
 125         }
 126         io->out.reply_addr = talloc_steal(mem_ctx,
 127                                           packet->answers[0].rdata.netbios.addresses[0].ipaddr);
 128         talloc_steal(mem_ctx, io->out.name.name);
 129         talloc_steal(mem_ctx, io->out.name.scope);
 130 
 131         talloc_free(req);
 132 
 133         return NT_STATUS_OK;
 134 }
 135 
 136 /*
 137   synchronous name registration request
 138 */
 139 _PUBLIC_ NTSTATUS nbt_name_register(struct nbt_name_socket *nbtsock,
     /* [<][>][^][v][top][bottom][index][help] */
 140                            TALLOC_CTX *mem_ctx, struct nbt_name_register *io)
 141 {
 142         struct nbt_name_request *req = nbt_name_register_send(nbtsock, io);
 143         return nbt_name_register_recv(req, mem_ctx, io);
 144 }
 145 
 146 
 147 /*
 148   a 4 step broadcast registration. 3 lots of name registration requests, followed by
 149   a name registration demand
 150 */
 151 struct register_bcast_state {
 152         struct nbt_name_socket *nbtsock;
 153         struct nbt_name_register *io;
 154         struct nbt_name_request *req;
 155 };
 156 
 157 
 158 /*
 159   state handler for 4 stage name registration
 160 */
 161 static void name_register_bcast_handler(struct nbt_name_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 162 {
 163         struct composite_context *c = talloc_get_type(req->async.private_data, struct composite_context);
 164         struct register_bcast_state *state = talloc_get_type(c->private_data, struct register_bcast_state);
 165         NTSTATUS status;
 166 
 167         status = nbt_name_register_recv(state->req, state, state->io);
 168         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
 169                 if (state->io->in.register_demand == true) {
 170                         /* all done */
 171                         c->state = COMPOSITE_STATE_DONE;
 172                         c->status = NT_STATUS_OK;
 173                         goto done;
 174                 }
 175 
 176                 /* the registration timed out - good, send the demand */
 177                 state->io->in.register_demand = true;
 178                 state->io->in.retries         = 0;
 179                 state->req = nbt_name_register_send(state->nbtsock, state->io);
 180                 if (state->req == NULL) {
 181                         c->state = COMPOSITE_STATE_ERROR;
 182                         c->status = NT_STATUS_NO_MEMORY;
 183                 } else {
 184                         state->req->async.fn      = name_register_bcast_handler;
 185                         state->req->async.private_data = c;
 186                 }
 187         } else if (!NT_STATUS_IS_OK(status)) {
 188                 c->state = COMPOSITE_STATE_ERROR;
 189                 c->status = status;
 190         } else {
 191                 c->state = COMPOSITE_STATE_ERROR;
 192                 c->status = NT_STATUS_CONFLICTING_ADDRESSES;
 193                 DEBUG(3,("Name registration conflict from %s for %s with ip %s - rcode %d\n",
 194                          state->io->out.reply_from,
 195                          nbt_name_string(state, &state->io->out.name),
 196                          state->io->out.reply_addr,
 197                          state->io->out.rcode));
 198         }
 199 
 200 done:
 201         if (c->state >= COMPOSITE_STATE_DONE &&
 202             c->async.fn) {
 203                 c->async.fn(c);
 204         }
 205 }
 206 
 207 /*
 208   the async send call for a 4 stage name registration
 209 */
 210 _PUBLIC_ struct composite_context *nbt_name_register_bcast_send(struct nbt_name_socket *nbtsock,
     /* [<][>][^][v][top][bottom][index][help] */
 211                                                        struct nbt_name_register_bcast *io)
 212 {
 213         struct composite_context *c;
 214         struct register_bcast_state *state;
 215 
 216         c = talloc_zero(nbtsock, struct composite_context);
 217         if (c == NULL) goto failed;
 218 
 219         state = talloc(c, struct register_bcast_state);
 220         if (state == NULL) goto failed;
 221 
 222         state->io = talloc(state, struct nbt_name_register);
 223         if (state->io == NULL) goto failed;
 224 
 225         state->io->in.name            = io->in.name;
 226         state->io->in.dest_addr       = io->in.dest_addr;
 227         state->io->in.dest_port       = io->in.dest_port;
 228         state->io->in.address         = io->in.address;
 229         state->io->in.nb_flags        = io->in.nb_flags;
 230         state->io->in.register_demand = false;
 231         state->io->in.broadcast       = true;
 232         state->io->in.multi_homed     = false;
 233         state->io->in.ttl             = io->in.ttl;
 234         state->io->in.timeout         = 1;
 235         state->io->in.retries         = 2;
 236 
 237         state->nbtsock = nbtsock;
 238 
 239         state->req = nbt_name_register_send(nbtsock, state->io);
 240         if (state->req == NULL) goto failed;
 241 
 242         state->req->async.fn      = name_register_bcast_handler;
 243         state->req->async.private_data = c;
 244 
 245         c->private_data = state;
 246         c->state        = COMPOSITE_STATE_IN_PROGRESS;
 247         c->event_ctx    = nbtsock->event_ctx;
 248 
 249         return c;
 250 
 251 failed:
 252         talloc_free(c);
 253         return NULL;
 254 }
 255 
 256 /*
 257   broadcast 4 part name register - recv
 258 */
 259 _PUBLIC_ NTSTATUS nbt_name_register_bcast_recv(struct composite_context *c)
     /* [<][>][^][v][top][bottom][index][help] */
 260 {
 261         NTSTATUS status;
 262         status = composite_wait(c);
 263         talloc_free(c);
 264         return status;
 265 }
 266 
 267 /*
 268   broadcast 4 part name register - sync interface
 269 */
 270 NTSTATUS nbt_name_register_bcast(struct nbt_name_socket *nbtsock,
     /* [<][>][^][v][top][bottom][index][help] */
 271                                  struct nbt_name_register_bcast *io)
 272 {
 273         struct composite_context *c = nbt_name_register_bcast_send(nbtsock, io);
 274         return nbt_name_register_bcast_recv(c);
 275 }
 276 
 277 
 278 /*
 279   a wins name register with multiple WINS servers and multiple
 280   addresses to register. Try each WINS server in turn, until we get a
 281   reply for each address
 282 */
 283 struct register_wins_state {
 284         struct nbt_name_socket *nbtsock;
 285         struct nbt_name_register *io;
 286         const char **wins_servers;
 287         uint16_t wins_port;
 288         const char **addresses;
 289         int address_idx;
 290         struct nbt_name_request *req;
 291 };
 292 
 293 
 294 /*
 295   state handler for WINS multi-homed multi-server name register
 296 */
 297 static void name_register_wins_handler(struct nbt_name_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 298 {
 299         struct composite_context *c = talloc_get_type(req->async.private_data,
 300                                                       struct composite_context);
 301         struct register_wins_state *state = talloc_get_type(c->private_data,
 302                                                             struct register_wins_state);
 303         NTSTATUS status;
 304 
 305         status = nbt_name_register_recv(state->req, state, state->io);
 306         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
 307                 /* the register timed out - try the next WINS server */
 308                 state->wins_servers++;
 309                 state->address_idx = 0;
 310                 if (state->wins_servers[0] == NULL) {
 311                         c->state = COMPOSITE_STATE_ERROR;
 312                         c->status = status;
 313                         goto done;
 314                 }
 315                 state->io->in.dest_addr = state->wins_servers[0];
 316                 state->io->in.dest_port = state->wins_port;
 317                 state->io->in.address   = state->addresses[0];
 318                 state->req = nbt_name_register_send(state->nbtsock, state->io);
 319                 if (state->req == NULL) {
 320                         c->state = COMPOSITE_STATE_ERROR;
 321                         c->status = NT_STATUS_NO_MEMORY;
 322                 } else {
 323                         state->req->async.fn      = name_register_wins_handler;
 324                         state->req->async.private_data = c;
 325                 }
 326         } else if (!NT_STATUS_IS_OK(status)) {
 327                 c->state = COMPOSITE_STATE_ERROR;
 328                 c->status = status;
 329         } else {
 330                 if (state->io->out.rcode == 0 &&
 331                     state->addresses[state->address_idx+1] != NULL) {
 332                         /* register our next address */
 333                         state->io->in.address = state->addresses[++(state->address_idx)];
 334                         state->req = nbt_name_register_send(state->nbtsock, state->io);
 335                         if (state->req == NULL) {
 336                                 c->state = COMPOSITE_STATE_ERROR;
 337                                 c->status = NT_STATUS_NO_MEMORY;
 338                         } else {
 339                                 state->req->async.fn      = name_register_wins_handler;
 340                                 state->req->async.private_data = c;
 341                         }
 342                 } else {
 343                         c->state = COMPOSITE_STATE_DONE;
 344                         c->status = NT_STATUS_OK;
 345                 }
 346         }
 347 
 348 done:
 349         if (c->state >= COMPOSITE_STATE_DONE &&
 350             c->async.fn) {
 351                 c->async.fn(c);
 352         }
 353 }
 354 
 355 /*
 356   the async send call for a multi-server WINS register
 357 */
 358 _PUBLIC_ struct composite_context *nbt_name_register_wins_send(struct nbt_name_socket *nbtsock,
     /* [<][>][^][v][top][bottom][index][help] */
 359                                                       struct nbt_name_register_wins *io)
 360 {
 361         struct composite_context *c;
 362         struct register_wins_state *state;
 363 
 364         c = talloc_zero(nbtsock, struct composite_context);
 365         if (c == NULL) goto failed;
 366 
 367         state = talloc(c, struct register_wins_state);
 368         if (state == NULL) goto failed;
 369 
 370         state->io = talloc(state, struct nbt_name_register);
 371         if (state->io == NULL) goto failed;
 372 
 373         state->wins_port = io->in.wins_port;
 374         state->wins_servers = (const char **)str_list_copy(state, io->in.wins_servers);
 375         if (state->wins_servers == NULL ||
 376             state->wins_servers[0] == NULL) goto failed;
 377 
 378         state->addresses = (const char **)str_list_copy(state, io->in.addresses);
 379         if (state->addresses == NULL ||
 380             state->addresses[0] == NULL) goto failed;
 381 
 382         state->io->in.name            = io->in.name;
 383         state->io->in.dest_addr       = state->wins_servers[0];
 384         state->io->in.dest_port       = state->wins_port;
 385         state->io->in.address         = io->in.addresses[0];
 386         state->io->in.nb_flags        = io->in.nb_flags;
 387         state->io->in.broadcast       = false;
 388         state->io->in.register_demand = false;
 389         state->io->in.multi_homed     = (io->in.nb_flags & NBT_NM_GROUP)?false:true;
 390         state->io->in.ttl             = io->in.ttl;
 391         state->io->in.timeout         = 3;
 392         state->io->in.retries         = 2;
 393 
 394         state->nbtsock     = nbtsock;
 395         state->address_idx = 0;
 396 
 397         state->req = nbt_name_register_send(nbtsock, state->io);
 398         if (state->req == NULL) goto failed;
 399 
 400         state->req->async.fn      = name_register_wins_handler;
 401         state->req->async.private_data = c;
 402 
 403         c->private_data = state;
 404         c->state        = COMPOSITE_STATE_IN_PROGRESS;
 405         c->event_ctx    = nbtsock->event_ctx;
 406 
 407         return c;
 408 
 409 failed:
 410         talloc_free(c);
 411         return NULL;
 412 }
 413 
 414 /*
 415   multi-homed WINS name register - recv side
 416 */
 417 _PUBLIC_ NTSTATUS nbt_name_register_wins_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 418                                      struct nbt_name_register_wins *io)
 419 {
 420         NTSTATUS status;
 421         status = composite_wait(c);
 422         if (NT_STATUS_IS_OK(status)) {
 423                 struct register_wins_state *state =
 424                         talloc_get_type(c->private_data, struct register_wins_state);
 425                 io->out.wins_server = talloc_steal(mem_ctx, state->wins_servers[0]);
 426                 io->out.rcode = state->io->out.rcode;
 427         }
 428         talloc_free(c);
 429         return status;
 430 }
 431 
 432 /*
 433   multi-homed WINS register - sync interface
 434 */
 435 _PUBLIC_ NTSTATUS nbt_name_register_wins(struct nbt_name_socket *nbtsock,
     /* [<][>][^][v][top][bottom][index][help] */
 436                                 TALLOC_CTX *mem_ctx,
 437                                 struct nbt_name_register_wins *io)
 438 {
 439         struct composite_context *c = nbt_name_register_wins_send(nbtsock, io);
 440         return nbt_name_register_wins_recv(c, mem_ctx, io);
 441 }

/* [<][>][^][v][top][bottom][index][help] */