1/* 2 Unix SMB/CIFS implementation. 3 NBT netbios routines and daemon - version 2 4 5 Copyright (C) Jeremy Allison 1994-2005 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. 19 20 Converted to store WINS data in a tdb. Dec 2005. JRA. 21*/ 22 23#include "includes.h" 24 25#define WINS_LIST "wins.dat" 26#define WINS_VERSION 1 27#define WINSDB_VERSION 1 28 29/**************************************************************************** 30 We don't store the NetBIOS scope in the wins.tdb. We key off the (utf8) netbios 31 name (65 bytes with the last byte being the name type). 32*****************************************************************************/ 33 34TDB_CONTEXT *wins_tdb; 35 36/**************************************************************************** 37 Delete all the temporary name records on the in-memory linked list. 38*****************************************************************************/ 39 40static void wins_delete_all_tmp_in_memory_records(void) 41{ 42 struct name_record *nr = NULL; 43 struct name_record *nrnext = NULL; 44 45 /* Delete all temporary name records on the wins subnet linked list. */ 46 for( nr = wins_server_subnet->namelist; nr; nr = nrnext) { 47 nrnext = nr->next; 48 DLIST_REMOVE(wins_server_subnet->namelist, nr); 49 SAFE_FREE(nr->data.ip); 50 SAFE_FREE(nr); 51 } 52} 53 54/**************************************************************************** 55 Convert a wins.tdb record to a struct name_record. Add in our global_scope(). 56*****************************************************************************/ 57 58static struct name_record *wins_record_to_name_record(TDB_DATA key, TDB_DATA data) 59{ 60 struct name_record *namerec = NULL; 61 uint16 nb_flags; 62 unsigned char nr_src; 63 uint32 death_time, refresh_time; 64 uint32 id_low, id_high; 65 uint32 saddr; 66 uint32 wins_flags; 67 uint32 num_ips; 68 size_t len; 69 int i; 70 71 if (data.dptr == NULL || data.dsize == 0) { 72 return NULL; 73 } 74 75 /* Min size is "wbddddddd" + 1 ip address (4). */ 76 if (data.dsize < 2 + 1 + (7*4) + 4) { 77 return NULL; 78 } 79 80 len = tdb_unpack(data.dptr, data.dsize, 81 "wbddddddd", 82 &nb_flags, 83 &nr_src, 84 &death_time, 85 &refresh_time, 86 &id_low, 87 &id_high, 88 &saddr, 89 &wins_flags, 90 &num_ips ); 91 92 namerec = SMB_MALLOC_P(struct name_record); 93 if (!namerec) { 94 return NULL; 95 } 96 ZERO_STRUCTP(namerec); 97 98 namerec->data.ip = SMB_MALLOC_ARRAY(struct in_addr, num_ips); 99 if (!namerec->data.ip) { 100 SAFE_FREE(namerec); 101 return NULL; 102 } 103 104 namerec->subnet = wins_server_subnet; 105 push_ascii_nstring(namerec->name.name, (const char *)key.dptr); 106 namerec->name.name_type = key.dptr[sizeof(unstring)]; 107 /* Add the scope. */ 108 push_ascii(namerec->name.scope, global_scope(), 64, STR_TERMINATE); 109 110 /* We're using a byte-by-byte compare, so we must be sure that 111 * unused space doesn't have garbage in it. 112 */ 113 114 for( i = strlen( namerec->name.name ); i < sizeof( namerec->name.name ); i++ ) { 115 namerec->name.name[i] = '\0'; 116 } 117 for( i = strlen( namerec->name.scope ); i < sizeof( namerec->name.scope ); i++ ) { 118 namerec->name.scope[i] = '\0'; 119 } 120 121 namerec->data.nb_flags = nb_flags; 122 namerec->data.source = (enum name_source)nr_src; 123 namerec->data.death_time = (time_t)death_time; 124 namerec->data.refresh_time = (time_t)refresh_time; 125 namerec->data.id = id_low; 126#if defined(HAVE_LONGLONG) 127 namerec->data.id |= ((uint64_t)id_high << 32); 128#endif 129 namerec->data.wins_ip.s_addr = saddr; 130 namerec->data.wins_flags = wins_flags, 131 namerec->data.num_ips = num_ips; 132 133 for (i = 0; i < num_ips; i++) { 134 namerec->data.ip[i].s_addr = IVAL(data.dptr, len + (i*4)); 135 } 136 137 return namerec; 138} 139 140/**************************************************************************** 141 Convert a struct name_record to a wins.tdb record. Ignore the scope. 142*****************************************************************************/ 143 144static TDB_DATA name_record_to_wins_record(const struct name_record *namerec) 145{ 146 TDB_DATA data; 147 size_t len = 0; 148 int i; 149 uint32 id_low = (namerec->data.id & 0xFFFFFFFF); 150#if defined(HAVE_LONGLONG) 151 uint32 id_high = (namerec->data.id >> 32) & 0xFFFFFFFF; 152#else 153 uint32 id_high = 0; 154#endif 155 156 ZERO_STRUCT(data); 157 158 len = (2 + 1 + (7*4)); /* "wbddddddd" */ 159 len += (namerec->data.num_ips * 4); 160 161 data.dptr = (uint8 *)SMB_MALLOC(len); 162 if (!data.dptr) { 163 return data; 164 } 165 data.dsize = len; 166 167 len = tdb_pack(data.dptr, data.dsize, "wbddddddd", 168 namerec->data.nb_flags, 169 (unsigned char)namerec->data.source, 170 (uint32)namerec->data.death_time, 171 (uint32)namerec->data.refresh_time, 172 id_low, 173 id_high, 174 (uint32)namerec->data.wins_ip.s_addr, 175 (uint32)namerec->data.wins_flags, 176 (uint32)namerec->data.num_ips ); 177 178 for (i = 0; i < namerec->data.num_ips; i++) { 179 SIVAL(data.dptr, len + (i*4), namerec->data.ip[i].s_addr); 180 } 181 182 return data; 183} 184 185/**************************************************************************** 186 Create key. Key is UNIX codepage namestring (usually utf8 64 byte len) with 1 byte type. 187*****************************************************************************/ 188 189static TDB_DATA name_to_key(const struct nmb_name *nmbname) 190{ 191 static char keydata[sizeof(unstring) + 1]; 192 TDB_DATA key; 193 194 memset(keydata, '\0', sizeof(keydata)); 195 196 pull_ascii_nstring(keydata, sizeof(unstring), nmbname->name); 197 strupper_m(keydata); 198 keydata[sizeof(unstring)] = nmbname->name_type; 199 key.dptr = (uint8 *)keydata; 200 key.dsize = sizeof(keydata); 201 202 return key; 203} 204 205/**************************************************************************** 206 Lookup a given name in the wins.tdb and create a temporary malloc'ed data struct 207 on the linked list. We will free this later in XXXX(). 208*****************************************************************************/ 209 210struct name_record *find_name_on_wins_subnet(const struct nmb_name *nmbname, bool self_only) 211{ 212 TDB_DATA data, key; 213 struct name_record *nr = NULL; 214 struct name_record *namerec = NULL; 215 216 if (!wins_tdb) { 217 return NULL; 218 } 219 220 key = name_to_key(nmbname); 221 data = tdb_fetch(wins_tdb, key); 222 223 if (data.dsize == 0) { 224 return NULL; 225 } 226 227 namerec = wins_record_to_name_record(key, data); 228 229 /* done with the this */ 230 231 SAFE_FREE( data.dptr ); 232 233 if (!namerec) { 234 return NULL; 235 } 236 237 /* Self names only - these include permanent names. */ 238 if( self_only && (namerec->data.source != SELF_NAME) && (namerec->data.source != PERMANENT_NAME) ) { 239 DEBUG( 9, ( "find_name_on_wins_subnet: self name %s NOT FOUND\n", nmb_namestr(nmbname) ) ); 240 SAFE_FREE(namerec->data.ip); 241 SAFE_FREE(namerec); 242 return NULL; 243 } 244 245 /* Search for this name record on the list. Replace it if found. */ 246 247 for( nr = wins_server_subnet->namelist; nr; nr = nr->next) { 248 if (memcmp(nmbname->name, nr->name.name, 16) == 0) { 249 /* Delete it. */ 250 DLIST_REMOVE(wins_server_subnet->namelist, nr); 251 SAFE_FREE(nr->data.ip); 252 SAFE_FREE(nr); 253 break; 254 } 255 } 256 257 DLIST_ADD(wins_server_subnet->namelist, namerec); 258 return namerec; 259} 260 261/**************************************************************************** 262 Overwrite or add a given name in the wins.tdb. 263*****************************************************************************/ 264 265static bool store_or_replace_wins_namerec(const struct name_record *namerec, int tdb_flag) 266{ 267 TDB_DATA key, data; 268 int ret; 269 270 if (!wins_tdb) { 271 return False; 272 } 273 274 key = name_to_key(&namerec->name); 275 data = name_record_to_wins_record(namerec); 276 277 if (data.dptr == NULL) { 278 return False; 279 } 280 281 ret = tdb_store(wins_tdb, key, data, tdb_flag); 282 283 SAFE_FREE(data.dptr); 284 return (ret == 0) ? True : False; 285} 286 287/**************************************************************************** 288 Overwrite a given name in the wins.tdb. 289*****************************************************************************/ 290 291bool wins_store_changed_namerec(const struct name_record *namerec) 292{ 293 return store_or_replace_wins_namerec(namerec, TDB_REPLACE); 294} 295 296/**************************************************************************** 297 Primary interface into creating and overwriting records in the wins.tdb. 298*****************************************************************************/ 299 300bool add_name_to_wins_subnet(const struct name_record *namerec) 301{ 302 return store_or_replace_wins_namerec(namerec, TDB_INSERT); 303} 304 305/**************************************************************************** 306 Delete a given name in the tdb and remove the temporary malloc'ed data struct 307 on the linked list. 308*****************************************************************************/ 309 310bool remove_name_from_wins_namelist(struct name_record *namerec) 311{ 312 TDB_DATA key; 313 int ret; 314 315 if (!wins_tdb) { 316 return False; 317 } 318 319 key = name_to_key(&namerec->name); 320 ret = tdb_delete(wins_tdb, key); 321 322 DLIST_REMOVE(wins_server_subnet->namelist, namerec); 323 324 /* namerec must be freed by the caller */ 325 326 return (ret == 0) ? True : False; 327} 328 329/**************************************************************************** 330 Dump out the complete namelist. 331*****************************************************************************/ 332 333static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) 334{ 335 struct name_record *namerec = NULL; 336 XFILE *fp = (XFILE *)state; 337 338 if (kbuf.dsize != sizeof(unstring) + 1) { 339 return 0; 340 } 341 342 namerec = wins_record_to_name_record(kbuf, dbuf); 343 if (!namerec) { 344 return 0; 345 } 346 347 dump_name_record(namerec, fp); 348 349 SAFE_FREE(namerec->data.ip); 350 SAFE_FREE(namerec); 351 return 0; 352} 353 354void dump_wins_subnet_namelist(XFILE *fp) 355{ 356 tdb_traverse(wins_tdb, traverse_fn, (void *)fp); 357} 358 359/**************************************************************************** 360 Change the wins owner address in the record. 361*****************************************************************************/ 362 363static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip) 364{ 365 namerec->data.wins_ip=wins_ip; 366} 367 368/**************************************************************************** 369 Create the wins flags based on the nb flags and the input value. 370*****************************************************************************/ 371 372static void update_wins_flag(struct name_record *namerec, int flags) 373{ 374 namerec->data.wins_flags=0x0; 375 376 /* if it's a group, it can be a normal or a special one */ 377 if (namerec->data.nb_flags & NB_GROUP) { 378 if (namerec->name.name_type==0x1C) { 379 namerec->data.wins_flags|=WINS_SGROUP; 380 } else { 381 if (namerec->data.num_ips>1) { 382 namerec->data.wins_flags|=WINS_SGROUP; 383 } else { 384 namerec->data.wins_flags|=WINS_NGROUP; 385 } 386 } 387 } else { 388 /* can be unique or multi-homed */ 389 if (namerec->data.num_ips>1) { 390 namerec->data.wins_flags|=WINS_MHOMED; 391 } else { 392 namerec->data.wins_flags|=WINS_UNIQUE; 393 } 394 } 395 396 /* the node type are the same bits */ 397 namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK; 398 399 /* the static bit is elsewhere */ 400 if (namerec->data.death_time == PERMANENT_TTL) { 401 namerec->data.wins_flags|=WINS_STATIC; 402 } 403 404 /* and add the given bits */ 405 namerec->data.wins_flags|=flags; 406 407 DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n", 408 namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags)); 409} 410 411/**************************************************************************** 412 Return the general ID value and increase it if requested. 413*****************************************************************************/ 414 415static void get_global_id_and_update(uint64_t *current_id, bool update) 416{ 417 /* 418 * it's kept as a static here, to prevent people from messing 419 * with the value directly 420 */ 421 422 static uint64_t general_id = 1; 423 424 DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id)); 425 426 *current_id = general_id; 427 428 if (update) { 429 general_id++; 430 } 431} 432 433/**************************************************************************** 434 Possibly call the WINS hook external program when a WINS change is made. 435 Also stores the changed record back in the wins_tdb. 436*****************************************************************************/ 437 438static void wins_hook(const char *operation, struct name_record *namerec, int ttl) 439{ 440 char *command = NULL; 441 char *cmd = lp_wins_hook(); 442 char *p, *namestr; 443 int i; 444 TALLOC_CTX *ctx = talloc_tos(); 445 446 wins_store_changed_namerec(namerec); 447 448 if (!cmd || !*cmd) { 449 return; 450 } 451 452 for (p=namerec->name.name; *p; p++) { 453 if (!(isalnum((int)*p) || strchr_m("._-",*p))) { 454 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name))); 455 return; 456 } 457 } 458 459 /* Use the name without the nametype (and scope) appended */ 460 461 namestr = nmb_namestr(&namerec->name); 462 if ((p = strchr(namestr, '<'))) { 463 *p = 0; 464 } 465 466 command = talloc_asprintf(ctx, 467 "%s %s %s %02x %d", 468 cmd, 469 operation, 470 namestr, 471 namerec->name.name_type, 472 ttl); 473 if (!command) { 474 return; 475 } 476 477 for (i=0;i<namerec->data.num_ips;i++) { 478 command = talloc_asprintf_append(command, 479 " %s", 480 inet_ntoa(namerec->data.ip[i])); 481 if (!command) { 482 return; 483 } 484 } 485 486 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name))); 487 smbrun(command, NULL); 488 TALLOC_FREE(command); 489} 490 491/**************************************************************************** 492Determine if this packet should be allocated to the WINS server. 493*****************************************************************************/ 494 495bool packet_is_for_wins_server(struct packet_struct *packet) 496{ 497 struct nmb_packet *nmb = &packet->packet.nmb; 498 499 /* Only unicast packets go to a WINS server. */ 500 if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True)) { 501 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n")); 502 return False; 503 } 504 505 /* Check for node status requests. */ 506 if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY) { 507 return False; 508 } 509 510 switch(nmb->header.opcode) { 511 /* 512 * A WINS server issues WACKS, not receives them. 513 */ 514 case NMB_WACK_OPCODE: 515 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n")); 516 return False; 517 /* 518 * A WINS server only processes registration and 519 * release requests, not responses. 520 */ 521 case NMB_NAME_REG_OPCODE: 522 case NMB_NAME_MULTIHOMED_REG_OPCODE: 523 case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */ 524 case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */ 525 if(nmb->header.response) { 526 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n")); 527 return False; 528 } 529 break; 530 531 case NMB_NAME_RELEASE_OPCODE: 532 if(nmb->header.response) { 533 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n")); 534 return False; 535 } 536 break; 537 538 /* 539 * Only process unicast name queries with rd = 1. 540 */ 541 case NMB_NAME_QUERY_OPCODE: 542 if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired) { 543 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n")); 544 return False; 545 } 546 break; 547 } 548 549 return True; 550} 551 552/**************************************************************************** 553Utility function to decide what ttl to give a register/refresh request. 554*****************************************************************************/ 555 556static int get_ttl_from_packet(struct nmb_packet *nmb) 557{ 558 int ttl = nmb->additional->ttl; 559 560 if (ttl < lp_min_wins_ttl()) { 561 ttl = lp_min_wins_ttl(); 562 } 563 564 if (ttl > lp_max_wins_ttl()) { 565 ttl = lp_max_wins_ttl(); 566 } 567 568 return ttl; 569} 570 571/**************************************************************************** 572Load or create the WINS database. 573*****************************************************************************/ 574 575bool initialise_wins(void) 576{ 577 time_t time_now = time(NULL); 578 XFILE *fp; 579 char line[1024]; 580 581 if(!lp_we_are_a_wins_server()) { 582 return True; 583 } 584 585 /* Open the wins.tdb. */ 586 wins_tdb = tdb_open_log(state_path("wins.tdb"), 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST, O_CREAT|O_RDWR, 0600); 587 if (!wins_tdb) { 588 DEBUG(0,("initialise_wins: failed to open wins.tdb. Error was %s\n", 589 strerror(errno) )); 590 return False; 591 } 592 593 tdb_store_int32(wins_tdb, "WINSDB_VERSION", WINSDB_VERSION); 594 595 add_samba_names_to_subnet(wins_server_subnet); 596 597 if((fp = x_fopen(state_path(WINS_LIST),O_RDONLY,0)) == NULL) { 598 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n", 599 WINS_LIST, strerror(errno) )); 600 return True; 601 } 602 603 while (!x_feof(fp)) { 604 char *name_str = NULL; 605 char *ip_str = NULL; 606 char *ttl_str = NULL, *nb_flags_str = NULL; 607 unsigned int num_ips; 608 char *name = NULL; 609 struct in_addr *ip_list = NULL; 610 int type = 0; 611 int nb_flags; 612 int ttl; 613 const char *ptr; 614 char *p = NULL; 615 bool got_token; 616 bool was_ip; 617 int i; 618 unsigned int hash; 619 int version; 620 TALLOC_CTX *frame = NULL; 621 622 /* Read a line from the wins.dat file. Strips whitespace 623 from the beginning and end of the line. */ 624 if (!fgets_slash(line,sizeof(line),fp)) { 625 continue; 626 } 627 628 if (*line == '#') { 629 continue; 630 } 631 632 if (strncmp(line,"VERSION ", 8) == 0) { 633 if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 || 634 version != WINS_VERSION) { 635 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line)); 636 x_fclose(fp); 637 return True; 638 } 639 continue; 640 } 641 642 ptr = line; 643 644 /* 645 * Now we handle multiple IP addresses per name we need 646 * to iterate over the line twice. The first time to 647 * determine how many IP addresses there are, the second 648 * time to actually parse them into the ip_list array. 649 */ 650 651 frame = talloc_stackframe(); 652 if (!next_token_talloc(frame,&ptr,&name_str,NULL)) { 653 DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line )); 654 TALLOC_FREE(frame); 655 continue; 656 } 657 658 if (!next_token_talloc(frame,&ptr,&ttl_str,NULL)) { 659 DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line )); 660 TALLOC_FREE(frame); 661 continue; 662 } 663 664 /* 665 * Determine the number of IP addresses per line. 666 */ 667 num_ips = 0; 668 do { 669 got_token = next_token_talloc(frame,&ptr,&ip_str,NULL); 670 was_ip = False; 671 672 if(got_token && strchr(ip_str, '.')) { 673 num_ips++; 674 was_ip = True; 675 } 676 } while(got_token && was_ip); 677 678 if(num_ips == 0) { 679 DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line )); 680 TALLOC_FREE(frame); 681 continue; 682 } 683 684 if(!got_token) { 685 DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line )); 686 TALLOC_FREE(frame); 687 continue; 688 } 689 690 /* Allocate the space for the ip_list. */ 691 if((ip_list = SMB_MALLOC_ARRAY( struct in_addr, num_ips)) == NULL) { 692 DEBUG(0,("initialise_wins: Malloc fail !\n")); 693 x_fclose(fp); 694 TALLOC_FREE(frame); 695 return False; 696 } 697 698 /* Reset and re-parse the line. */ 699 ptr = line; 700 next_token_talloc(frame,&ptr,&name_str,NULL); 701 next_token_talloc(frame,&ptr,&ttl_str,NULL); 702 for(i = 0; i < num_ips; i++) { 703 next_token_talloc(frame,&ptr, &ip_str, NULL); 704 ip_list[i] = interpret_addr2(ip_str); 705 } 706 next_token_talloc(frame,&ptr,&nb_flags_str,NULL); 707 708 /* 709 * Deal with SELF or REGISTER name encoding. Default is REGISTER 710 * for compatibility with old nmbds. 711 */ 712 713 if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') { 714 DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line)); 715 SAFE_FREE(ip_list); 716 TALLOC_FREE(frame); 717 continue; 718 } 719 720 if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') { 721 nb_flags_str[strlen(nb_flags_str)-1] = '\0'; 722 } 723 724 /* Netbios name. # divides the name from the type (hex): netbios#xx */ 725 name = name_str; 726 727 if((p = strchr(name,'#')) != NULL) { 728 *p = 0; 729 sscanf(p+1,"%x",&type); 730 } 731 732 /* Decode the netbios flags (hex) and the time-to-live (in seconds). */ 733 sscanf(nb_flags_str,"%x",&nb_flags); 734 sscanf(ttl_str,"%d",&ttl); 735 736 /* add all entries that have 60 seconds or more to live */ 737 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) { 738 if(ttl != PERMANENT_TTL) { 739 ttl -= time_now; 740 } 741 742 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n", 743 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); 744 745 (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags, 746 ttl, REGISTER_NAME, num_ips, ip_list ); 747 } else { 748 DEBUG(4, ("initialise_wins: not adding name (ttl problem) " 749 "%s#%02x ttl = %d first IP %s flags = %2x\n", 750 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); 751 } 752 753 TALLOC_FREE(frame); 754 SAFE_FREE(ip_list); 755 } 756 757 x_fclose(fp); 758 return True; 759} 760 761/**************************************************************************** 762Send a WINS WACK (Wait ACKnowledgement) response. 763**************************************************************************/ 764 765static void send_wins_wack_response(int ttl, struct packet_struct *p) 766{ 767 struct nmb_packet *nmb = &p->packet.nmb; 768 unsigned char rdata[2]; 769 770 rdata[0] = rdata[1] = 0; 771 772 /* Taken from nmblib.c - we need to send back almost 773 identical bytes from the requesting packet header. */ 774 775 rdata[0] = (nmb->header.opcode & 0xF) << 3; 776 if (nmb->header.nm_flags.authoritative && nmb->header.response) { 777 rdata[0] |= 0x4; 778 } 779 if (nmb->header.nm_flags.trunc) { 780 rdata[0] |= 0x2; 781 } 782 if (nmb->header.nm_flags.recursion_desired) { 783 rdata[0] |= 0x1; 784 } 785 if (nmb->header.nm_flags.recursion_available && nmb->header.response) { 786 rdata[1] |= 0x80; 787 } 788 if (nmb->header.nm_flags.bcast) { 789 rdata[1] |= 0x10; 790 } 791 792 reply_netbios_packet(p, /* Packet to reply to. */ 793 0, /* Result code. */ 794 NMB_WAIT_ACK, /* nmbd type code. */ 795 NMB_WACK_OPCODE, /* opcode. */ 796 ttl, /* ttl. */ 797 (char *)rdata, /* data to send. */ 798 2); /* data length. */ 799} 800 801/**************************************************************************** 802Send a WINS name registration response. 803**************************************************************************/ 804 805static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p) 806{ 807 struct nmb_packet *nmb = &p->packet.nmb; 808 char rdata[6]; 809 810 memcpy(&rdata[0], &nmb->additional->rdata[0], 6); 811 812 reply_netbios_packet(p, /* Packet to reply to. */ 813 rcode, /* Result code. */ 814 WINS_REG, /* nmbd type code. */ 815 NMB_NAME_REG_OPCODE, /* opcode. */ 816 ttl, /* ttl. */ 817 rdata, /* data to send. */ 818 6); /* data length. */ 819} 820 821/*********************************************************************** 822 Deal with a name refresh request to a WINS server. 823************************************************************************/ 824 825void wins_process_name_refresh_request( struct subnet_record *subrec, 826 struct packet_struct *p ) 827{ 828 struct nmb_packet *nmb = &p->packet.nmb; 829 struct nmb_name *question = &nmb->question.question_name; 830 bool bcast = nmb->header.nm_flags.bcast; 831 uint16 nb_flags = get_nb_flags(nmb->additional->rdata); 832 bool group = (nb_flags & NB_GROUP) ? True : False; 833 struct name_record *namerec = NULL; 834 int ttl = get_ttl_from_packet(nmb); 835 struct in_addr from_ip; 836 struct in_addr our_fake_ip; 837 838 our_fake_ip = interpret_addr2("0.0.0.0"); 839 putip( (char *)&from_ip, &nmb->additional->rdata[2] ); 840 841 if(bcast) { 842 /* 843 * We should only get unicast name refresh packets here. 844 * Anyone trying to refresh broadcast should not be going 845 * to a WINS server. Log an error here. 846 */ 847 if( DEBUGLVL( 0 ) ) { 848 dbgtext( "wins_process_name_refresh_request: " ); 849 dbgtext( "Broadcast name refresh request received " ); 850 dbgtext( "for name %s ", nmb_namestr(question) ); 851 dbgtext( "from IP %s ", inet_ntoa(from_ip) ); 852 dbgtext( "on subnet %s. ", subrec->subnet_name ); 853 dbgtext( "Error - Broadcasts should not be sent " ); 854 dbgtext( "to a WINS server\n" ); 855 } 856 return; 857 } 858 859 if( DEBUGLVL( 3 ) ) { 860 dbgtext( "wins_process_name_refresh_request: " ); 861 dbgtext( "Name refresh for name %s IP %s\n", 862 nmb_namestr(question), inet_ntoa(from_ip) ); 863 } 864 865 /* 866 * See if the name already exists. 867 * If not, handle it as a name registration and return. 868 */ 869 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); 870 871 /* 872 * If this is a refresh request and the name doesn't exist then 873 * treat it like a registration request. This allows us to recover 874 * from errors (tridge) 875 */ 876 if(namerec == NULL) { 877 if( DEBUGLVL( 3 ) ) { 878 dbgtext( "wins_process_name_refresh_request: " ); 879 dbgtext( "Name refresh for name %s ", 880 nmb_namestr( question ) ); 881 dbgtext( "and the name does not exist. Treating " ); 882 dbgtext( "as registration.\n" ); 883 } 884 wins_process_name_registration_request(subrec,p); 885 return; 886 } 887 888 /* 889 * if the name is present but not active, simply remove it 890 * and treat the refresh request as a registration & return. 891 */ 892 if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) { 893 if( DEBUGLVL( 5 ) ) { 894 dbgtext( "wins_process_name_refresh_request: " ); 895 dbgtext( "Name (%s) in WINS ", nmb_namestr(question) ); 896 dbgtext( "was not active - removing it.\n" ); 897 } 898 remove_name_from_namelist( subrec, namerec ); 899 namerec = NULL; 900 wins_process_name_registration_request( subrec, p ); 901 return; 902 } 903 904 /* 905 * Check that the group bits for the refreshing name and the 906 * name in our database match. If not, refuse the refresh. 907 * [crh: Why RFS_ERR instead of ACT_ERR? Is this what MS does?] 908 */ 909 if( (namerec != NULL) && 910 ( (group && !NAME_GROUP(namerec)) 911 || (!group && NAME_GROUP(namerec)) ) ) { 912 if( DEBUGLVL( 3 ) ) { 913 dbgtext( "wins_process_name_refresh_request: " ); 914 dbgtext( "Name %s ", nmb_namestr(question) ); 915 dbgtext( "group bit = %s does not match ", 916 group ? "True" : "False" ); 917 dbgtext( "group bit in WINS for this name.\n" ); 918 } 919 send_wins_name_registration_response(RFS_ERR, 0, p); 920 return; 921 } 922 923 /* 924 * For a unique name check that the person refreshing the name is 925 * one of the registered IP addresses. If not - fail the refresh. 926 * Do the same for group names with a type of 0x1c. 927 * Just return success for unique 0x1d refreshes. For normal group 928 * names update the ttl and return success. 929 */ 930 if( (!group || (group && (question->name_type == 0x1c))) 931 && find_ip_in_name_record(namerec, from_ip) ) { 932 /* 933 * Update the ttl. 934 */ 935 update_name_ttl(namerec, ttl); 936 937 /* 938 * if the record is a replica: 939 * we take ownership and update the version ID. 940 */ 941 if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) { 942 update_wins_owner(namerec, our_fake_ip); 943 get_global_id_and_update(&namerec->data.id, True); 944 } 945 946 send_wins_name_registration_response(0, ttl, p); 947 wins_hook("refresh", namerec, ttl); 948 return; 949 } else if((group && (question->name_type == 0x1c))) { 950 /* 951 * Added by crh for bug #1079. 952 * Fix from Bert Driehuis 953 */ 954 if( DEBUGLVL( 3 ) ) { 955 dbgtext( "wins_process_name_refresh_request: " ); 956 dbgtext( "Name refresh for name %s, ", 957 nmb_namestr(question) ); 958 dbgtext( "but IP address %s ", inet_ntoa(from_ip) ); 959 dbgtext( "is not yet associated with " ); 960 dbgtext( "that name. Treating as registration.\n" ); 961 } 962 wins_process_name_registration_request(subrec,p); 963 return; 964 } else if(group) { 965 /* 966 * Normal groups are all registered with an IP address of 967 * 255.255.255.255 so we can't search for the IP address. 968 */ 969 update_name_ttl(namerec, ttl); 970 wins_hook("refresh", namerec, ttl); 971 send_wins_name_registration_response(0, ttl, p); 972 return; 973 } else if(!group && (question->name_type == 0x1d)) { 974 /* 975 * Special name type - just pretend the refresh succeeded. 976 */ 977 send_wins_name_registration_response(0, ttl, p); 978 return; 979 } else { 980 /* 981 * Fail the refresh. 982 */ 983 if( DEBUGLVL( 3 ) ) { 984 dbgtext( "wins_process_name_refresh_request: " ); 985 dbgtext( "Name refresh for name %s with IP %s ", 986 nmb_namestr(question), inet_ntoa(from_ip) ); 987 dbgtext( "and is IP is not known to the name.\n" ); 988 } 989 send_wins_name_registration_response(RFS_ERR, 0, p); 990 return; 991 } 992} 993 994/*********************************************************************** 995 Deal with a name registration request query success to a client that 996 owned the name. 997 998 We have a locked pointer to the original packet stashed away in the 999 userdata pointer. The success here is actually a failure as it means 1000 the client we queried wants to keep the name, so we must return 1001 a registration failure to the original requestor. 1002************************************************************************/ 1003 1004static void wins_register_query_success(struct subnet_record *subrec, 1005 struct userdata_struct *userdata, 1006 struct nmb_name *question_name, 1007 struct in_addr ip, 1008 struct res_rec *answers) 1009{ 1010 struct packet_struct *orig_reg_packet; 1011 1012 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); 1013 1014 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \ 1015name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) )); 1016 1017 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); 1018 1019 orig_reg_packet->locked = False; 1020 free_packet(orig_reg_packet); 1021} 1022 1023/*********************************************************************** 1024 Deal with a name registration request query failure to a client that 1025 owned the name. 1026 1027 We have a locked pointer to the original packet stashed away in the 1028 userdata pointer. The failure here is actually a success as it means 1029 the client we queried didn't want to keep the name, so we can remove 1030 the old name record and then successfully add the new name. 1031************************************************************************/ 1032 1033static void wins_register_query_fail(struct subnet_record *subrec, 1034 struct response_record *rrec, 1035 struct nmb_name *question_name, 1036 int rcode) 1037{ 1038 struct userdata_struct *userdata = rrec->userdata; 1039 struct packet_struct *orig_reg_packet; 1040 struct name_record *namerec = NULL; 1041 1042 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); 1043 1044 /* 1045 * We want to just add the name, as we now know the original owner 1046 * didn't want it. But we can't just do that as an arbitary 1047 * amount of time may have taken place between the name query 1048 * request and this timeout/error response. So we check that 1049 * the name still exists and is in the same state - if so 1050 * we remove it and call wins_process_name_registration_request() 1051 * as we know it will do the right thing now. 1052 */ 1053 1054 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME); 1055 1056 if ((namerec != NULL) && (namerec->data.source == REGISTER_NAME) && 1057 ip_equal_v4(rrec->packet->ip, *namerec->data.ip)) { 1058 remove_name_from_namelist( subrec, namerec); 1059 namerec = NULL; 1060 } 1061 1062 if(namerec == NULL) { 1063 wins_process_name_registration_request(subrec, orig_reg_packet); 1064 } else { 1065 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between " 1066 "querying for name %s in order to replace it and this reply.\n", 1067 nmb_namestr(question_name) )); 1068 } 1069 1070 orig_reg_packet->locked = False; 1071 free_packet(orig_reg_packet); 1072} 1073 1074/*********************************************************************** 1075 Deal with a name registration request to a WINS server. 1076 1077 Use the following pseudocode : 1078 1079 registering_group 1080 | 1081 | 1082 +--------name exists 1083 | | 1084 | | 1085 | +--- existing name is group 1086 | | | 1087 | | | 1088 | | +--- add name (return). 1089 | | 1090 | | 1091 | +--- exiting name is unique 1092 | | 1093 | | 1094 | +--- query existing owner (return). 1095 | 1096 | 1097 +--------name doesn't exist 1098 | 1099 | 1100 +--- add name (return). 1101 1102 registering_unique 1103 | 1104 | 1105 +--------name exists 1106 | | 1107 | | 1108 | +--- existing name is group 1109 | | | 1110 | | | 1111 | | +--- fail add (return). 1112 | | 1113 | | 1114 | +--- exiting name is unique 1115 | | 1116 | | 1117 | +--- query existing owner (return). 1118 | 1119 | 1120 +--------name doesn't exist 1121 | 1122 | 1123 +--- add name (return). 1124 1125 As can be seen from the above, the two cases may be collapsed onto each 1126 other with the exception of the case where the name already exists and 1127 is a group name. This case we handle with an if statement. 1128 1129************************************************************************/ 1130 1131void wins_process_name_registration_request(struct subnet_record *subrec, 1132 struct packet_struct *p) 1133{ 1134 unstring name; 1135 struct nmb_packet *nmb = &p->packet.nmb; 1136 struct nmb_name *question = &nmb->question.question_name; 1137 bool bcast = nmb->header.nm_flags.bcast; 1138 uint16 nb_flags = get_nb_flags(nmb->additional->rdata); 1139 int ttl = get_ttl_from_packet(nmb); 1140 struct name_record *namerec = NULL; 1141 struct in_addr from_ip; 1142 bool registering_group_name = (nb_flags & NB_GROUP) ? True : False; 1143 struct in_addr our_fake_ip; 1144 1145 our_fake_ip = interpret_addr2("0.0.0.0"); 1146 putip((char *)&from_ip,&nmb->additional->rdata[2]); 1147 1148 if(bcast) { 1149 /* 1150 * We should only get unicast name registration packets here. 1151 * Anyone trying to register broadcast should not be going to a WINS 1152 * server. Log an error here. 1153 */ 1154 1155 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \ 1156received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n", 1157 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); 1158 return; 1159 } 1160 1161 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \ 1162IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) )); 1163 1164 /* 1165 * See if the name already exists. 1166 */ 1167 1168 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); 1169 1170 /* 1171 * if the record exists but NOT in active state, 1172 * consider it dead. 1173 */ 1174 if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) { 1175 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \ 1176not active - removing it.\n", nmb_namestr(question) )); 1177 remove_name_from_namelist( subrec, namerec ); 1178 namerec = NULL; 1179 } 1180 1181 /* 1182 * Deal with the case where the name found was a dns entry. 1183 * Remove it as we now have a NetBIOS client registering the 1184 * name. 1185 */ 1186 1187 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) { 1188 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \ 1189a dns lookup - removing it.\n", nmb_namestr(question) )); 1190 remove_name_from_namelist( subrec, namerec ); 1191 namerec = NULL; 1192 } 1193 1194 /* 1195 * Reject if the name exists and is not a REGISTER_NAME. 1196 * (ie. Don't allow any static names to be overwritten. 1197 */ 1198 1199 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) { 1200 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \ 1201to register name %s. Name already exists in WINS with source type %d.\n", 1202 nmb_namestr(question), namerec->data.source )); 1203 send_wins_name_registration_response(RFS_ERR, 0, p); 1204 return; 1205 } 1206 1207 /* 1208 * Special policy decisions based on MS documentation. 1209 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255. 1210 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent. 1211 */ 1212 1213 /* 1214 * A group name is always added as the local broadcast address, except 1215 * for group names ending in 0x1c. 1216 * Group names with type 0x1c are registered with individual IP addresses. 1217 */ 1218 1219 if(registering_group_name && (question->name_type != 0x1c)) { 1220 from_ip = interpret_addr2("255.255.255.255"); 1221 } 1222 1223 /* 1224 * Ignore all attempts to register a unique 0x1d name, although return success. 1225 */ 1226 1227 if(!registering_group_name && (question->name_type == 0x1d)) { 1228 DEBUG(3,("wins_process_name_registration_request: Ignoring request \ 1229to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) )); 1230 send_wins_name_registration_response(0, ttl, p); 1231 return; 1232 } 1233 1234 /* 1235 * Next two cases are the 'if statement' mentioned above. 1236 */ 1237 1238 if((namerec != NULL) && NAME_GROUP(namerec)) { 1239 if(registering_group_name) { 1240 /* 1241 * If we are adding a group name, the name exists and is also a group entry just add this 1242 * IP address to it and update the ttl. 1243 */ 1244 1245 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n", 1246 inet_ntoa(from_ip), nmb_namestr(question) )); 1247 1248 /* 1249 * Check the ip address is not already in the group. 1250 */ 1251 1252 if(!find_ip_in_name_record(namerec, from_ip)) { 1253 add_ip_to_name_record(namerec, from_ip); 1254 /* we need to update the record for replication */ 1255 get_global_id_and_update(&namerec->data.id, True); 1256 1257 /* 1258 * if the record is a replica, we must change 1259 * the wins owner to us to make the replication updates 1260 * it on the other wins servers. 1261 * And when the partner will receive this record, 1262 * it will update its own record. 1263 */ 1264 1265 update_wins_owner(namerec, our_fake_ip); 1266 } 1267 update_name_ttl(namerec, ttl); 1268 wins_hook("refresh", namerec, ttl); 1269 send_wins_name_registration_response(0, ttl, p); 1270 return; 1271 } else { 1272 1273 /* 1274 * If we are adding a unique name, the name exists in the WINS db 1275 * and is a group name then reject the registration. 1276 * 1277 * explanation: groups have a higher priority than unique names. 1278 */ 1279 1280 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \ 1281already exists in WINS as a GROUP name.\n", nmb_namestr(question) )); 1282 send_wins_name_registration_response(RFS_ERR, 0, p); 1283 return; 1284 } 1285 } 1286 1287 /* 1288 * From here on down we know that if the name exists in the WINS db it is 1289 * a unique name, not a group name. 1290 */ 1291 1292 /* 1293 * If the name exists and is one of our names then check the 1294 * registering IP address. If it's not one of ours then automatically 1295 * reject without doing the query - we know we will reject it. 1296 */ 1297 1298 if ( namerec != NULL ) { 1299 pull_ascii_nstring(name, sizeof(name), namerec->name.name); 1300 if( is_myname(name) ) { 1301 if(!ismyip_v4(from_ip)) { 1302 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \ 1303is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) )); 1304 send_wins_name_registration_response(RFS_ERR, 0, p); 1305 return; 1306 } else { 1307 /* 1308 * It's one of our names and one of our IP's - update the ttl. 1309 */ 1310 update_name_ttl(namerec, ttl); 1311 wins_hook("refresh", namerec, ttl); 1312 send_wins_name_registration_response(0, ttl, p); 1313 return; 1314 } 1315 } 1316 } else { 1317 name[0] = '\0'; 1318 } 1319 1320 /* 1321 * If the name exists and it is a unique registration and the registering IP 1322 * is the same as the (single) already registered IP then just update the ttl. 1323 * 1324 * But not if the record is an active replica. IF it's a replica, it means it can be 1325 * the same client which has moved and not yet expired. So we don't update 1326 * the ttl in this case and go beyond to do a WACK and query the old client 1327 */ 1328 1329 if( !registering_group_name 1330 && (namerec != NULL) 1331 && (namerec->data.num_ips == 1) 1332 && ip_equal_v4( namerec->data.ip[0], from_ip ) 1333 && ip_equal_v4(namerec->data.wins_ip, our_fake_ip) ) { 1334 update_name_ttl( namerec, ttl ); 1335 wins_hook("refresh", namerec, ttl); 1336 send_wins_name_registration_response( 0, ttl, p ); 1337 return; 1338 } 1339 1340 /* 1341 * Finally if the name exists do a query to the registering machine 1342 * to see if they still claim to have the name. 1343 */ 1344 1345 if( namerec != NULL ) { 1346 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1]; 1347 struct userdata_struct *userdata = (struct userdata_struct *)ud; 1348 1349 /* 1350 * First send a WACK to the registering machine. 1351 */ 1352 1353 send_wins_wack_response(60, p); 1354 1355 /* 1356 * When the reply comes back we need the original packet. 1357 * Lock this so it won't be freed and then put it into 1358 * the userdata structure. 1359 */ 1360 1361 p->locked = True; 1362 1363 userdata = (struct userdata_struct *)ud; 1364 1365 userdata->copy_fn = NULL; 1366 userdata->free_fn = NULL; 1367 userdata->userdata_len = sizeof(struct packet_struct *); 1368 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) ); 1369 1370 /* 1371 * Use the new call to send a query directly to an IP address. 1372 * This sends the query directly to the IP address, and ensures 1373 * the recursion desired flag is not set (you were right Luke :-). 1374 * This function should *only* be called from the WINS server 1375 * code. JRA. 1376 */ 1377 1378 pull_ascii_nstring(name, sizeof(name), question->name); 1379 query_name_from_wins_server( *namerec->data.ip, 1380 name, 1381 question->name_type, 1382 wins_register_query_success, 1383 wins_register_query_fail, 1384 userdata ); 1385 return; 1386 } 1387 1388 /* 1389 * Name did not exist - add it. 1390 */ 1391 1392 pull_ascii_nstring(name, sizeof(name), question->name); 1393 add_name_to_subnet( subrec, name, question->name_type, 1394 nb_flags, ttl, REGISTER_NAME, 1, &from_ip); 1395 1396 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) { 1397 get_global_id_and_update(&namerec->data.id, True); 1398 update_wins_owner(namerec, our_fake_ip); 1399 update_wins_flag(namerec, WINS_ACTIVE); 1400 wins_hook("add", namerec, ttl); 1401 } 1402 1403 send_wins_name_registration_response(0, ttl, p); 1404} 1405 1406/*********************************************************************** 1407 Deal with a mutihomed name query success to the machine that 1408 requested the multihomed name registration. 1409 1410 We have a locked pointer to the original packet stashed away in the 1411 userdata pointer. 1412************************************************************************/ 1413 1414static void wins_multihomed_register_query_success(struct subnet_record *subrec, 1415 struct userdata_struct *userdata, 1416 struct nmb_name *question_name, 1417 struct in_addr ip, 1418 struct res_rec *answers) 1419{ 1420 struct packet_struct *orig_reg_packet; 1421 struct nmb_packet *nmb; 1422 struct name_record *namerec = NULL; 1423 struct in_addr from_ip; 1424 int ttl; 1425 struct in_addr our_fake_ip; 1426 1427 our_fake_ip = interpret_addr2("0.0.0.0"); 1428 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); 1429 1430 nmb = &orig_reg_packet->packet.nmb; 1431 1432 putip((char *)&from_ip,&nmb->additional->rdata[2]); 1433 ttl = get_ttl_from_packet(nmb); 1434 1435 /* 1436 * We want to just add the new IP, as we now know the requesting 1437 * machine claims to own it. But we can't just do that as an arbitary 1438 * amount of time may have taken place between the name query 1439 * request and this response. So we check that 1440 * the name still exists and is in the same state - if so 1441 * we just add the extra IP and update the ttl. 1442 */ 1443 1444 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME); 1445 1446 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) { 1447 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \ 1448a subsequent IP address.\n", nmb_namestr(question_name) )); 1449 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); 1450 1451 orig_reg_packet->locked = False; 1452 free_packet(orig_reg_packet); 1453 1454 return; 1455 } 1456 1457 if(!find_ip_in_name_record(namerec, from_ip)) { 1458 add_ip_to_name_record(namerec, from_ip); 1459 } 1460 1461 get_global_id_and_update(&namerec->data.id, True); 1462 update_wins_owner(namerec, our_fake_ip); 1463 update_wins_flag(namerec, WINS_ACTIVE); 1464 update_name_ttl(namerec, ttl); 1465 wins_hook("add", namerec, ttl); 1466 send_wins_name_registration_response(0, ttl, orig_reg_packet); 1467 1468 orig_reg_packet->locked = False; 1469 free_packet(orig_reg_packet); 1470} 1471 1472/*********************************************************************** 1473 Deal with a name registration request query failure to a client that 1474 owned the name. 1475 1476 We have a locked pointer to the original packet stashed away in the 1477 userdata pointer. 1478************************************************************************/ 1479 1480static void wins_multihomed_register_query_fail(struct subnet_record *subrec, 1481 struct response_record *rrec, 1482 struct nmb_name *question_name, 1483 int rcode) 1484{ 1485 struct userdata_struct *userdata = rrec->userdata; 1486 struct packet_struct *orig_reg_packet; 1487 1488 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); 1489 1490 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \ 1491query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) )); 1492 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); 1493 1494 orig_reg_packet->locked = False; 1495 free_packet(orig_reg_packet); 1496 return; 1497} 1498 1499/*********************************************************************** 1500 Deal with a multihomed name registration request to a WINS server. 1501 These cannot be group name registrations. 1502***********************************************************************/ 1503 1504void wins_process_multihomed_name_registration_request( struct subnet_record *subrec, 1505 struct packet_struct *p) 1506{ 1507 struct nmb_packet *nmb = &p->packet.nmb; 1508 struct nmb_name *question = &nmb->question.question_name; 1509 bool bcast = nmb->header.nm_flags.bcast; 1510 uint16 nb_flags = get_nb_flags(nmb->additional->rdata); 1511 int ttl = get_ttl_from_packet(nmb); 1512 struct name_record *namerec = NULL; 1513 struct in_addr from_ip; 1514 bool group = (nb_flags & NB_GROUP) ? True : False; 1515 struct in_addr our_fake_ip; 1516 unstring qname; 1517 1518 our_fake_ip = interpret_addr2("0.0.0.0"); 1519 putip((char *)&from_ip,&nmb->additional->rdata[2]); 1520 1521 if(bcast) { 1522 /* 1523 * We should only get unicast name registration packets here. 1524 * Anyone trying to register broadcast should not be going to a WINS 1525 * server. Log an error here. 1526 */ 1527 1528 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \ 1529received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n", 1530 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); 1531 return; 1532 } 1533 1534 /* 1535 * Only unique names should be registered multihomed. 1536 */ 1537 1538 if(group) { 1539 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \ 1540received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n", 1541 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); 1542 return; 1543 } 1544 1545 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \ 1546IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) )); 1547 1548 /* 1549 * Deal with policy regarding 0x1d names. 1550 */ 1551 1552 if(question->name_type == 0x1d) { 1553 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \ 1554to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) )); 1555 send_wins_name_registration_response(0, ttl, p); 1556 return; 1557 } 1558 1559 /* 1560 * See if the name already exists. 1561 */ 1562 1563 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); 1564 1565 /* 1566 * if the record exists but NOT in active state, 1567 * consider it dead. 1568 */ 1569 1570 if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) { 1571 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question))); 1572 remove_name_from_namelist(subrec, namerec); 1573 namerec = NULL; 1574 } 1575 1576 /* 1577 * Deal with the case where the name found was a dns entry. 1578 * Remove it as we now have a NetBIOS client registering the 1579 * name. 1580 */ 1581 1582 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) { 1583 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \ 1584- removing it.\n", nmb_namestr(question) )); 1585 remove_name_from_namelist( subrec, namerec); 1586 namerec = NULL; 1587 } 1588 1589 /* 1590 * Reject if the name exists and is not a REGISTER_NAME. 1591 * (ie. Don't allow any static names to be overwritten. 1592 */ 1593 1594 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) { 1595 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \ 1596to register name %s. Name already exists in WINS with source type %d.\n", 1597 nmb_namestr(question), namerec->data.source )); 1598 send_wins_name_registration_response(RFS_ERR, 0, p); 1599 return; 1600 } 1601 1602 /* 1603 * Reject if the name exists and is a GROUP name and is active. 1604 */ 1605 1606 if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) { 1607 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \ 1608already exists in WINS as a GROUP name.\n", nmb_namestr(question) )); 1609 send_wins_name_registration_response(RFS_ERR, 0, p); 1610 return; 1611 } 1612 1613 /* 1614 * From here on down we know that if the name exists in the WINS db it is 1615 * a unique name, not a group name. 1616 */ 1617 1618 /* 1619 * If the name exists and is one of our names then check the 1620 * registering IP address. If it's not one of ours then automatically 1621 * reject without doing the query - we know we will reject it. 1622 */ 1623 1624 if((namerec != NULL) && (is_myname(namerec->name.name)) ) { 1625 if(!ismyip_v4(from_ip)) { 1626 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \ 1627is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) )); 1628 send_wins_name_registration_response(RFS_ERR, 0, p); 1629 return; 1630 } else { 1631 /* 1632 * It's one of our names and one of our IP's. Ensure the IP is in the record and 1633 * update the ttl. Update the version ID to force replication. 1634 */ 1635 update_name_ttl(namerec, ttl); 1636 1637 if(!find_ip_in_name_record(namerec, from_ip)) { 1638 get_global_id_and_update(&namerec->data.id, True); 1639 update_wins_owner(namerec, our_fake_ip); 1640 update_wins_flag(namerec, WINS_ACTIVE); 1641 1642 add_ip_to_name_record(namerec, from_ip); 1643 } 1644 1645 wins_hook("refresh", namerec, ttl); 1646 send_wins_name_registration_response(0, ttl, p); 1647 return; 1648 } 1649 } 1650 1651 /* 1652 * If the name exists and is active, check if the IP address is already registered 1653 * to that name. If so then update the ttl and reply success. 1654 */ 1655 1656 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) { 1657 update_name_ttl(namerec, ttl); 1658 1659 /* 1660 * If it's a replica, we need to become the wins owner 1661 * to force the replication 1662 */ 1663 if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) { 1664 get_global_id_and_update(&namerec->data.id, True); 1665 update_wins_owner(namerec, our_fake_ip); 1666 update_wins_flag(namerec, WINS_ACTIVE); 1667 } 1668 1669 wins_hook("refresh", namerec, ttl); 1670 send_wins_name_registration_response(0, ttl, p); 1671 return; 1672 } 1673 1674 /* 1675 * If the name exists do a query to the owner 1676 * to see if they still want the name. 1677 */ 1678 1679 if(namerec != NULL) { 1680 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1]; 1681 struct userdata_struct *userdata = (struct userdata_struct *)ud; 1682 1683 /* 1684 * First send a WACK to the registering machine. 1685 */ 1686 1687 send_wins_wack_response(60, p); 1688 1689 /* 1690 * When the reply comes back we need the original packet. 1691 * Lock this so it won't be freed and then put it into 1692 * the userdata structure. 1693 */ 1694 1695 p->locked = True; 1696 1697 userdata = (struct userdata_struct *)ud; 1698 1699 userdata->copy_fn = NULL; 1700 userdata->free_fn = NULL; 1701 userdata->userdata_len = sizeof(struct packet_struct *); 1702 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) ); 1703 1704 /* 1705 * Use the new call to send a query directly to an IP address. 1706 * This sends the query directly to the IP address, and ensures 1707 * the recursion desired flag is not set (you were right Luke :-). 1708 * This function should *only* be called from the WINS server 1709 * code. JRA. 1710 * 1711 * Note that this packet is sent to the current owner of the name, 1712 * not the person who sent the packet 1713 */ 1714 1715 pull_ascii_nstring( qname, sizeof(qname), question->name); 1716 query_name_from_wins_server( namerec->data.ip[0], 1717 qname, 1718 question->name_type, 1719 wins_multihomed_register_query_success, 1720 wins_multihomed_register_query_fail, 1721 userdata ); 1722 1723 return; 1724 } 1725 1726 /* 1727 * Name did not exist - add it. 1728 */ 1729 1730 pull_ascii_nstring( qname, sizeof(qname), question->name); 1731 add_name_to_subnet( subrec, qname, question->name_type, 1732 nb_flags, ttl, REGISTER_NAME, 1, &from_ip); 1733 1734 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) { 1735 get_global_id_and_update(&namerec->data.id, True); 1736 update_wins_owner(namerec, our_fake_ip); 1737 update_wins_flag(namerec, WINS_ACTIVE); 1738 wins_hook("add", namerec, ttl); 1739 } 1740 1741 send_wins_name_registration_response(0, ttl, p); 1742} 1743 1744/*********************************************************************** 1745 Fetch all *<1b> names from the WINS db and store on the namelist. 1746***********************************************************************/ 1747 1748static int fetch_1b_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) 1749{ 1750 struct name_record *namerec = NULL; 1751 1752 if (kbuf.dsize != sizeof(unstring) + 1) { 1753 return 0; 1754 } 1755 1756 /* Filter out all non-1b names. */ 1757 if (kbuf.dptr[sizeof(unstring)] != 0x1b) { 1758 return 0; 1759 } 1760 1761 namerec = wins_record_to_name_record(kbuf, dbuf); 1762 if (!namerec) { 1763 return 0; 1764 } 1765 1766 DLIST_ADD(wins_server_subnet->namelist, namerec); 1767 return 0; 1768} 1769 1770void fetch_all_active_wins_1b_names(void) 1771{ 1772 tdb_traverse(wins_tdb, fetch_1b_traverse_fn, NULL); 1773} 1774 1775/*********************************************************************** 1776 Deal with the special name query for *<1b>. 1777***********************************************************************/ 1778 1779static void process_wins_dmb_query_request(struct subnet_record *subrec, 1780 struct packet_struct *p) 1781{ 1782 struct name_record *namerec = NULL; 1783 char *prdata; 1784 int num_ips; 1785 1786 /* 1787 * Go through all the ACTIVE names in the WINS db looking for those 1788 * ending in <1b>. Use this to calculate the number of IP 1789 * addresses we need to return. 1790 */ 1791 1792 num_ips = 0; 1793 1794 /* First, clear the in memory list - we're going to re-populate 1795 it with the tdb_traversal in fetch_all_active_wins_1b_names. */ 1796 1797 wins_delete_all_tmp_in_memory_records(); 1798 1799 fetch_all_active_wins_1b_names(); 1800 1801 for( namerec = subrec->namelist; namerec; namerec = namerec->next ) { 1802 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) { 1803 num_ips += namerec->data.num_ips; 1804 } 1805 } 1806 1807 if(num_ips == 0) { 1808 /* 1809 * There are no 0x1b names registered. Return name query fail. 1810 */ 1811 send_wins_name_query_response(NAM_ERR, p, NULL); 1812 return; 1813 } 1814 1815 if((prdata = (char *)SMB_MALLOC( num_ips * 6 )) == NULL) { 1816 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n")); 1817 return; 1818 } 1819 1820 /* 1821 * Go through all the names again in the WINS db looking for those 1822 * ending in <1b>. Add their IP addresses into the list we will 1823 * return. 1824 */ 1825 1826 num_ips = 0; 1827 for( namerec = subrec->namelist; namerec; namerec = namerec->next ) { 1828 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) { 1829 int i; 1830 for(i = 0; i < namerec->data.num_ips; i++) { 1831 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags); 1832 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]); 1833 num_ips++; 1834 } 1835 } 1836 } 1837 1838 /* 1839 * Send back the reply containing the IP list. 1840 */ 1841 1842 reply_netbios_packet(p, /* Packet to reply to. */ 1843 0, /* Result code. */ 1844 WINS_QUERY, /* nmbd type code. */ 1845 NMB_NAME_QUERY_OPCODE, /* opcode. */ 1846 lp_min_wins_ttl(), /* ttl. */ 1847 prdata, /* data to send. */ 1848 num_ips*6); /* data length. */ 1849 1850 SAFE_FREE(prdata); 1851} 1852 1853/**************************************************************************** 1854Send a WINS name query response. 1855**************************************************************************/ 1856 1857void send_wins_name_query_response(int rcode, struct packet_struct *p, 1858 struct name_record *namerec) 1859{ 1860 char rdata[6]; 1861 char *prdata = rdata; 1862 int reply_data_len = 0; 1863 int ttl = 0; 1864 int i; 1865 1866 memset(rdata,'\0',6); 1867 1868 if(rcode == 0) { 1869 ttl = (namerec->data.death_time != PERMANENT_TTL) ? namerec->data.death_time - p->timestamp : lp_max_wins_ttl(); 1870 1871 /* Copy all known ip addresses into the return data. */ 1872 /* Optimise for the common case of one IP address so we don't need a malloc. */ 1873 1874 if( namerec->data.num_ips == 1 ) { 1875 prdata = rdata; 1876 } else { 1877 if((prdata = (char *)SMB_MALLOC( namerec->data.num_ips * 6 )) == NULL) { 1878 DEBUG(0,("send_wins_name_query_response: malloc fail !\n")); 1879 return; 1880 } 1881 } 1882 1883 for(i = 0; i < namerec->data.num_ips; i++) { 1884 set_nb_flags(&prdata[i*6],namerec->data.nb_flags); 1885 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]); 1886 } 1887 1888 sort_query_replies(prdata, i, p->ip); 1889 reply_data_len = namerec->data.num_ips * 6; 1890 } 1891 1892 reply_netbios_packet(p, /* Packet to reply to. */ 1893 rcode, /* Result code. */ 1894 WINS_QUERY, /* nmbd type code. */ 1895 NMB_NAME_QUERY_OPCODE, /* opcode. */ 1896 ttl, /* ttl. */ 1897 prdata, /* data to send. */ 1898 reply_data_len); /* data length. */ 1899 1900 if(prdata != rdata) { 1901 SAFE_FREE(prdata); 1902 } 1903} 1904 1905/*********************************************************************** 1906 Deal with a name query. 1907***********************************************************************/ 1908 1909void wins_process_name_query_request(struct subnet_record *subrec, 1910 struct packet_struct *p) 1911{ 1912 struct nmb_packet *nmb = &p->packet.nmb; 1913 struct nmb_name *question = &nmb->question.question_name; 1914 struct name_record *namerec = NULL; 1915 unstring qname; 1916 1917 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n", 1918 nmb_namestr(question), inet_ntoa(p->ip) )); 1919 1920 /* 1921 * Special name code. If the queried name is *<1b> then search 1922 * the entire WINS database and return a list of all the IP addresses 1923 * registered to any <1b> name. This is to allow domain master browsers 1924 * to discover other domains that may not have a presence on their subnet. 1925 */ 1926 1927 pull_ascii_nstring(qname, sizeof(qname), question->name); 1928 if(strequal( qname, "*") && (question->name_type == 0x1b)) { 1929 process_wins_dmb_query_request( subrec, p); 1930 return; 1931 } 1932 1933 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); 1934 1935 if(namerec != NULL) { 1936 /* 1937 * If the name is not anymore in active state then reply not found. 1938 * it's fair even if we keep it in the cache for days. 1939 */ 1940 if (!WINS_STATE_ACTIVE(namerec)) { 1941 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n", 1942 nmb_namestr(question) )); 1943 send_wins_name_query_response(NAM_ERR, p, namerec); 1944 return; 1945 } 1946 1947 /* 1948 * If it's a DNSFAIL_NAME then reply name not found. 1949 */ 1950 1951 if( namerec->data.source == DNSFAIL_NAME ) { 1952 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n", 1953 nmb_namestr(question) )); 1954 send_wins_name_query_response(NAM_ERR, p, namerec); 1955 return; 1956 } 1957 1958 /* 1959 * If the name has expired then reply name not found. 1960 */ 1961 1962 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < p->timestamp) ) { 1963 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n", 1964 nmb_namestr(question) )); 1965 send_wins_name_query_response(NAM_ERR, p, namerec); 1966 return; 1967 } 1968 1969 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n", 1970 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) )); 1971 1972 send_wins_name_query_response(0, p, namerec); 1973 return; 1974 } 1975 1976 /* 1977 * Name not found in WINS - try a dns query if it's a 0x20 name. 1978 */ 1979 1980 if(lp_dns_proxy() && ((question->name_type == 0x20) || question->name_type == 0)) { 1981 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n", 1982 nmb_namestr(question) )); 1983 1984 queue_dns_query(p, question); 1985 return; 1986 } 1987 1988 /* 1989 * Name not found - return error. 1990 */ 1991 1992 send_wins_name_query_response(NAM_ERR, p, NULL); 1993} 1994 1995/**************************************************************************** 1996Send a WINS name release response. 1997**************************************************************************/ 1998 1999static void send_wins_name_release_response(int rcode, struct packet_struct *p) 2000{ 2001 struct nmb_packet *nmb = &p->packet.nmb; 2002 char rdata[6]; 2003 2004 memcpy(&rdata[0], &nmb->additional->rdata[0], 6); 2005 2006 reply_netbios_packet(p, /* Packet to reply to. */ 2007 rcode, /* Result code. */ 2008 NMB_REL, /* nmbd type code. */ 2009 NMB_NAME_RELEASE_OPCODE, /* opcode. */ 2010 0, /* ttl. */ 2011 rdata, /* data to send. */ 2012 6); /* data length. */ 2013} 2014 2015/*********************************************************************** 2016 Deal with a name release. 2017***********************************************************************/ 2018 2019void wins_process_name_release_request(struct subnet_record *subrec, 2020 struct packet_struct *p) 2021{ 2022 struct nmb_packet *nmb = &p->packet.nmb; 2023 struct nmb_name *question = &nmb->question.question_name; 2024 bool bcast = nmb->header.nm_flags.bcast; 2025 uint16 nb_flags = get_nb_flags(nmb->additional->rdata); 2026 struct name_record *namerec = NULL; 2027 struct in_addr from_ip; 2028 bool releasing_group_name = (nb_flags & NB_GROUP) ? True : False;; 2029 2030 putip((char *)&from_ip,&nmb->additional->rdata[2]); 2031 2032 if(bcast) { 2033 /* 2034 * We should only get unicast name registration packets here. 2035 * Anyone trying to register broadcast should not be going to a WINS 2036 * server. Log an error here. 2037 */ 2038 2039 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \ 2040received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n", 2041 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); 2042 return; 2043 } 2044 2045 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \ 2046IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) )); 2047 2048 /* 2049 * Deal with policy regarding 0x1d names. 2050 */ 2051 2052 if(!releasing_group_name && (question->name_type == 0x1d)) { 2053 DEBUG(3,("wins_process_name_release_request: Ignoring request \ 2054to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) )); 2055 send_wins_name_release_response(0, p); 2056 return; 2057 } 2058 2059 /* 2060 * See if the name already exists. 2061 */ 2062 2063 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); 2064 2065 if( (namerec == NULL) || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) { 2066 send_wins_name_release_response(NAM_ERR, p); 2067 return; 2068 } 2069 2070 /* 2071 * Check that the sending machine has permission to release this name. 2072 * If it's a group name not ending in 0x1c then just say yes and let 2073 * the group time out. 2074 */ 2075 2076 if(releasing_group_name && (question->name_type != 0x1c)) { 2077 send_wins_name_release_response(0, p); 2078 return; 2079 } 2080 2081 /* 2082 * Check that the releasing node is on the list of IP addresses 2083 * for this name. Disallow the release if not. 2084 */ 2085 2086 if(!find_ip_in_name_record(namerec, from_ip)) { 2087 DEBUG(3,("wins_process_name_release_request: Refusing request to \ 2088release name %s as IP %s is not one of the known IP's for this name.\n", 2089 nmb_namestr(question), inet_ntoa(from_ip) )); 2090 send_wins_name_release_response(NAM_ERR, p); 2091 return; 2092 } 2093 2094 /* 2095 * Check if the record is active. IF it's already released 2096 * or tombstoned, refuse the release. 2097 */ 2098 2099 if (!WINS_STATE_ACTIVE(namerec)) { 2100 DEBUG(3,("wins_process_name_release_request: Refusing request to \ 2101release name %s as this record is not active anymore.\n", nmb_namestr(question) )); 2102 send_wins_name_release_response(NAM_ERR, p); 2103 return; 2104 } 2105 2106 /* 2107 * Check if the record is a 0x1c group 2108 * and has more then one ip 2109 * remove only this address. 2110 */ 2111 2112 if(releasing_group_name && (question->name_type == 0x1c) && (namerec->data.num_ips > 1)) { 2113 remove_ip_from_name_record(namerec, from_ip); 2114 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n", 2115 inet_ntoa(from_ip),nmb_namestr(question))); 2116 wins_hook("delete", namerec, 0); 2117 send_wins_name_release_response(0, p); 2118 return; 2119 } 2120 2121 /* 2122 * Send a release response. 2123 * Flag the name as released and update the ttl 2124 */ 2125 2126 namerec->data.wins_flags |= WINS_RELEASED; 2127 update_name_ttl(namerec, EXTINCTION_INTERVAL); 2128 2129 wins_hook("delete", namerec, 0); 2130 send_wins_name_release_response(0, p); 2131} 2132 2133/******************************************************************* 2134 WINS time dependent processing. 2135******************************************************************/ 2136 2137static int wins_processing_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) 2138{ 2139 time_t t = *(time_t *)state; 2140 bool store_record = False; 2141 struct name_record *namerec = NULL; 2142 struct in_addr our_fake_ip; 2143 2144 our_fake_ip = interpret_addr2("0.0.0.0"); 2145 if (kbuf.dsize != sizeof(unstring) + 1) { 2146 return 0; 2147 } 2148 2149 namerec = wins_record_to_name_record(kbuf, dbuf); 2150 if (!namerec) { 2151 return 0; 2152 } 2153 2154 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) { 2155 if( namerec->data.source == SELF_NAME ) { 2156 DEBUG( 3, ( "wins_processing_traverse_fn: Subnet %s not expiring SELF name %s\n", 2157 wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) ); 2158 namerec->data.death_time += 300; 2159 store_record = True; 2160 goto done; 2161 } else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) { 2162 DEBUG(3,("wins_processing_traverse_fn: deleting timed out DNS name %s\n", 2163 nmb_namestr(&namerec->name))); 2164 remove_name_from_wins_namelist(namerec ); 2165 goto done; 2166 } 2167 2168 /* handle records, samba is the wins owner */ 2169 if (ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) { 2170 switch (namerec->data.wins_flags & WINS_STATE_MASK) { 2171 case WINS_ACTIVE: 2172 namerec->data.wins_flags&=~WINS_STATE_MASK; 2173 namerec->data.wins_flags|=WINS_RELEASED; 2174 namerec->data.death_time = t + EXTINCTION_INTERVAL; 2175 DEBUG(3,("wins_processing_traverse_fn: expiring %s\n", 2176 nmb_namestr(&namerec->name))); 2177 store_record = True; 2178 goto done; 2179 case WINS_RELEASED: 2180 namerec->data.wins_flags&=~WINS_STATE_MASK; 2181 namerec->data.wins_flags|=WINS_TOMBSTONED; 2182 namerec->data.death_time = t + EXTINCTION_TIMEOUT; 2183 get_global_id_and_update(&namerec->data.id, True); 2184 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n", 2185 nmb_namestr(&namerec->name))); 2186 store_record = True; 2187 goto done; 2188 case WINS_TOMBSTONED: 2189 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n", 2190 nmb_namestr(&namerec->name))); 2191 remove_name_from_wins_namelist(namerec ); 2192 goto done; 2193 } 2194 } else { 2195 switch (namerec->data.wins_flags & WINS_STATE_MASK) { 2196 case WINS_ACTIVE: 2197 /* that's not as MS says it should be */ 2198 namerec->data.wins_flags&=~WINS_STATE_MASK; 2199 namerec->data.wins_flags|=WINS_TOMBSTONED; 2200 namerec->data.death_time = t + EXTINCTION_TIMEOUT; 2201 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n", 2202 nmb_namestr(&namerec->name))); 2203 store_record = True; 2204 goto done; 2205 case WINS_TOMBSTONED: 2206 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n", 2207 nmb_namestr(&namerec->name))); 2208 remove_name_from_wins_namelist(namerec ); 2209 goto done; 2210 case WINS_RELEASED: 2211 DEBUG(0,("wins_processing_traverse_fn: %s is in released state and\ 2212we are not the wins owner !\n", nmb_namestr(&namerec->name))); 2213 goto done; 2214 } 2215 } 2216 } 2217 2218 done: 2219 2220 if (store_record) { 2221 wins_store_changed_namerec(namerec); 2222 } 2223 2224 SAFE_FREE(namerec->data.ip); 2225 SAFE_FREE(namerec); 2226 2227 return 0; 2228} 2229 2230/******************************************************************* 2231 Time dependent wins processing. 2232******************************************************************/ 2233 2234void initiate_wins_processing(time_t t) 2235{ 2236 static time_t lasttime = 0; 2237 2238 if (!lasttime) { 2239 lasttime = t; 2240 } 2241 if (t - lasttime < 20) { 2242 return; 2243 } 2244 2245 if(!lp_we_are_a_wins_server()) { 2246 lasttime = t; 2247 return; 2248 } 2249 2250 tdb_traverse(wins_tdb, wins_processing_traverse_fn, &t); 2251 2252 wins_delete_all_tmp_in_memory_records(); 2253 2254 wins_write_database(t, True); 2255 2256 lasttime = t; 2257} 2258 2259/******************************************************************* 2260 Write out one record. 2261******************************************************************/ 2262 2263void wins_write_name_record(struct name_record *namerec, XFILE *fp) 2264{ 2265 int i; 2266 struct tm *tm; 2267 2268 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) )); 2269 2270 if( namerec->data.death_time != PERMANENT_TTL ) { 2271 char *ts, *nl; 2272 2273 tm = localtime(&namerec->data.death_time); 2274 if (!tm) { 2275 return; 2276 } 2277 ts = asctime(tm); 2278 if (!ts) { 2279 return; 2280 } 2281 nl = strrchr( ts, '\n' ); 2282 if( NULL != nl ) { 2283 *nl = '\0'; 2284 } 2285 DEBUGADD(4,("TTL = %s ", ts )); 2286 } else { 2287 DEBUGADD(4,("TTL = PERMANENT ")); 2288 } 2289 2290 for (i = 0; i < namerec->data.num_ips; i++) { 2291 DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) )); 2292 } 2293 DEBUGADD(4,("%2x\n", namerec->data.nb_flags )); 2294 2295 if( namerec->data.source == REGISTER_NAME ) { 2296 unstring name; 2297 pull_ascii_nstring(name, sizeof(name), namerec->name.name); 2298 x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */ 2299 (int)namerec->data.death_time); 2300 2301 for (i = 0; i < namerec->data.num_ips; i++) 2302 x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) ); 2303 x_fprintf( fp, "%2xR\n", namerec->data.nb_flags ); 2304 } 2305} 2306 2307/******************************************************************* 2308 Write out the current WINS database. 2309******************************************************************/ 2310 2311static int wins_writedb_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) 2312{ 2313 struct name_record *namerec = NULL; 2314 XFILE *fp = (XFILE *)state; 2315 2316 if (kbuf.dsize != sizeof(unstring) + 1) { 2317 return 0; 2318 } 2319 2320 namerec = wins_record_to_name_record(kbuf, dbuf); 2321 if (!namerec) { 2322 return 0; 2323 } 2324 2325 wins_write_name_record(namerec, fp); 2326 2327 SAFE_FREE(namerec->data.ip); 2328 SAFE_FREE(namerec); 2329 return 0; 2330} 2331 2332 2333void wins_write_database(time_t t, bool background) 2334{ 2335 static time_t last_write_time = 0; 2336 char *fname = NULL; 2337 char *fnamenew = NULL; 2338 2339 XFILE *fp; 2340 2341 if (background) { 2342 if (!last_write_time) { 2343 last_write_time = t; 2344 } 2345 if (t - last_write_time < 120) { 2346 return; 2347 } 2348 2349 } 2350 2351 if(!lp_we_are_a_wins_server()) { 2352 return; 2353 } 2354 2355 /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */ 2356 if (background) { 2357 CatchChild(); 2358 if (sys_fork()) { 2359 return; 2360 } 2361 if (tdb_reopen(wins_tdb)) { 2362 DEBUG(0,("wins_write_database: tdb_reopen failed. Error was %s\n", 2363 strerror(errno))); 2364 _exit(0); 2365 return; 2366 } 2367 } 2368 2369 if (!(fname = state_path(WINS_LIST))) { 2370 goto err_exit; 2371 } 2372 /* This is safe as the 0 length means "don't expand". */ 2373 all_string_sub(fname,"//", "/", 0); 2374 2375 if (asprintf(&fnamenew, "%s.%u", fname, (unsigned int)sys_getpid()) < 0) { 2376 goto err_exit; 2377 } 2378 2379 if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) { 2380 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno))); 2381 goto err_exit; 2382 } 2383 2384 DEBUG(4,("wins_write_database: Dump of WINS name list.\n")); 2385 2386 x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0); 2387 2388 tdb_traverse(wins_tdb, wins_writedb_traverse_fn, fp); 2389 2390 x_fclose(fp); 2391 chmod(fnamenew,0644); 2392 unlink(fname); 2393 rename(fnamenew,fname); 2394 2395 err_exit: 2396 2397 SAFE_FREE(fnamenew); 2398 TALLOC_FREE(fname); 2399 2400 if (background) { 2401 _exit(0); 2402 } 2403} 2404 2405#if 0 2406 Until winsrepl is done. 2407/**************************************************************************** 2408 Process a internal Samba message receiving a wins record. 2409***************************************************************************/ 2410 2411void nmbd_wins_new_entry(struct messaging_context *msg, 2412 void *private_data, 2413 uint32_t msg_type, 2414 struct server_id server_id, 2415 DATA_BLOB *data) 2416{ 2417 WINS_RECORD *record; 2418 struct name_record *namerec = NULL; 2419 struct name_record *new_namerec = NULL; 2420 struct nmb_name question; 2421 bool overwrite=False; 2422 struct in_addr our_fake_ip; 2423 int i; 2424 2425 our_fake_ip = interpret_addr2("0.0.0.0"); 2426 if (buf==NULL) { 2427 return; 2428 } 2429 2430 /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */ 2431 record=(WINS_RECORD *)buf; 2432 2433 make_nmb_name(&question, record->name, record->type); 2434 2435 namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME); 2436 2437 /* record doesn't exist, add it */ 2438 if (namerec == NULL) { 2439 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n", 2440 record->name, record->type, inet_ntoa(record->wins_ip))); 2441 2442 new_namerec=add_name_to_subnet( wins_server_subnet, 2443 record->name, 2444 record->type, 2445 record->nb_flags, 2446 EXTINCTION_INTERVAL, 2447 REGISTER_NAME, 2448 record->num_ips, 2449 record->ip); 2450 2451 if (new_namerec!=NULL) { 2452 update_wins_owner(new_namerec, record->wins_ip); 2453 update_wins_flag(new_namerec, record->wins_flags); 2454 new_namerec->data.id=record->id; 2455 2456 wins_server_subnet->namelist_changed = True; 2457 } 2458 } 2459 2460 /* check if we have a conflict */ 2461 if (namerec != NULL) { 2462 /* both records are UNIQUE */ 2463 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) { 2464 2465 /* the database record is a replica */ 2466 if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) { 2467 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) { 2468 if (ip_equal_v4(namerec->data.wins_ip, record->wins_ip)) 2469 overwrite=True; 2470 } else 2471 overwrite=True; 2472 } else { 2473 /* we are the wins owner of the database record */ 2474 /* the 2 records have the same IP address */ 2475 if (ip_equal_v4(namerec->data.ip[0], record->ip[0])) { 2476 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) 2477 get_global_id_and_update(&namerec->data.id, True); 2478 else 2479 overwrite=True; 2480 2481 } else { 2482 /* the 2 records have different IP address */ 2483 if (namerec->data.wins_flags&WINS_ACTIVE) { 2484 if (record->wins_flags&WINS_TOMBSTONED) 2485 get_global_id_and_update(&namerec->data.id, True); 2486 if (record->wins_flags&WINS_ACTIVE) 2487 /* send conflict challenge to the replica node */ 2488 ; 2489 } else 2490 overwrite=True; 2491 } 2492 2493 } 2494 } 2495 2496 /* the replica is a standard group */ 2497 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) { 2498 /* if the database record is unique and active force a name release */ 2499 if (namerec->data.wins_flags&WINS_UNIQUE) 2500 /* send a release name to the unique node */ 2501 ; 2502 overwrite=True; 2503 2504 } 2505 2506 /* the replica is a special group */ 2507 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) { 2508 if (namerec->data.wins_flags&WINS_ACTIVE) { 2509 for (i=0; i<record->num_ips; i++) 2510 if(!find_ip_in_name_record(namerec, record->ip[i])) 2511 add_ip_to_name_record(namerec, record->ip[i]); 2512 } else { 2513 overwrite=True; 2514 } 2515 } 2516 2517 /* the replica is a multihomed host */ 2518 2519 /* I'm giving up on multi homed. Too much complex to understand */ 2520 2521 if (record->wins_flags&WINS_MHOMED) { 2522 if (! (namerec->data.wins_flags&WINS_ACTIVE)) { 2523 if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP)) 2524 overwrite=True; 2525 } 2526 else { 2527 if (ip_equal_v4(record->wins_ip, namerec->data.wins_ip)) 2528 overwrite=True; 2529 2530 if (ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) 2531 if (namerec->data.wins_flags&WINS_UNIQUE) 2532 get_global_id_and_update(&namerec->data.id, True); 2533 2534 } 2535 2536 if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE) 2537 if (namerec->data.wins_flags&WINS_UNIQUE || 2538 namerec->data.wins_flags&WINS_MHOMED) 2539 if (ip_equal_v4(record->wins_ip, namerec->data.wins_ip)) 2540 overwrite=True; 2541 2542 } 2543 2544 if (overwrite == False) 2545 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n", 2546 record->name, record->type, inet_ntoa(record->wins_ip))); 2547 else { 2548 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n", 2549 record->name, record->type, inet_ntoa(record->wins_ip))); 2550 2551 /* remove the old record and add a new one */ 2552 remove_name_from_namelist( wins_server_subnet, namerec ); 2553 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags, 2554 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip); 2555 if (new_namerec!=NULL) { 2556 update_wins_owner(new_namerec, record->wins_ip); 2557 update_wins_flag(new_namerec, record->wins_flags); 2558 new_namerec->data.id=record->id; 2559 2560 wins_server_subnet->namelist_changed = True; 2561 } 2562 2563 wins_server_subnet->namelist_changed = True; 2564 } 2565 2566 } 2567} 2568#endif 2569