1/* 2 Unix SMB/CIFS implementation. 3 NBT netbios routines and daemon - version 2 4 5 Copyright (C) Jeremy Allison 1994-2003 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 2 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, write to the Free Software 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 21*/ 22 23#include "includes.h" 24 25#define WINS_LIST "wins.dat" 26#define WINS_VERSION 1 27 28/**************************************************************************** 29 Change the wins owner address in the record. 30*****************************************************************************/ 31 32static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip) 33{ 34 if (namerec==NULL) 35 return; 36 namerec->data.wins_ip=wins_ip; 37} 38 39/**************************************************************************** 40 Create the wins flags based on the nb flags and the input value. 41*****************************************************************************/ 42 43static void update_wins_flag(struct name_record *namerec, int flags) 44{ 45 if (namerec==NULL) 46 return; 47 48 namerec->data.wins_flags=0x0; 49 50 /* if it's a group, it can be a normal or a special one */ 51 if (namerec->data.nb_flags & NB_GROUP) { 52 if (namerec->name.name_type==0x1C) 53 namerec->data.wins_flags|=WINS_SGROUP; 54 else 55 if (namerec->data.num_ips>1) 56 namerec->data.wins_flags|=WINS_SGROUP; 57 else 58 namerec->data.wins_flags|=WINS_NGROUP; 59 } else { 60 /* can be unique or multi-homed */ 61 if (namerec->data.num_ips>1) 62 namerec->data.wins_flags|=WINS_MHOMED; 63 else 64 namerec->data.wins_flags|=WINS_UNIQUE; 65 } 66 67 /* the node type are the same bits */ 68 namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK; 69 70 /* the static bit is elsewhere */ 71 if (namerec->data.death_time == PERMANENT_TTL) 72 namerec->data.wins_flags|=WINS_STATIC; 73 74 /* and add the given bits */ 75 namerec->data.wins_flags|=flags; 76 77 DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n", 78 namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags)); 79} 80 81/**************************************************************************** 82 Return the general ID value and increase it if requested. 83*****************************************************************************/ 84 85static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update) 86{ 87 /* 88 * it's kept as a static here, to prevent people from messing 89 * with the value directly 90 */ 91 92 static SMB_BIG_UINT general_id = 1; 93 94 DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id)); 95 96 *current_id = general_id; 97 98 if (update) 99 general_id++; 100} 101 102/**************************************************************************** 103 Possibly call the WINS hook external program when a WINS change is made. 104*****************************************************************************/ 105 106static void wins_hook(const char *operation, struct name_record *namerec, int ttl) 107{ 108 pstring command; 109 char *cmd = lp_wins_hook(); 110 char *p, *namestr; 111 int i; 112 113 if (!cmd || !*cmd) return; 114 115 for (p=namerec->name.name; *p; p++) { 116 if (!(isalnum((int)*p) || strchr_m("._-",*p))) { 117 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name))); 118 return; 119 } 120 } 121 122 /* Use the name without the nametype (and scope) appended */ 123 124 namestr = nmb_namestr(&namerec->name); 125 if ((p = strchr(namestr, '<'))) 126 *p = 0; 127 128 p = command; 129 p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d", 130 cmd, 131 operation, 132 namestr, 133 namerec->name.name_type, 134 ttl); 135 136 for (i=0;i<namerec->data.num_ips;i++) { 137 p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.ip[i])); 138 } 139 140 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name))); 141 smbrun(command, NULL); 142} 143 144 145/**************************************************************************** 146Determine if this packet should be allocated to the WINS server. 147*****************************************************************************/ 148 149BOOL packet_is_for_wins_server(struct packet_struct *packet) 150{ 151 struct nmb_packet *nmb = &packet->packet.nmb; 152 153 /* Only unicast packets go to a WINS server. */ 154 if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True)) { 155 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n")); 156 return False; 157 } 158 159 /* Check for node status requests. */ 160 if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY) 161 return False; 162 163 switch(nmb->header.opcode) { 164 /* 165 * A WINS server issues WACKS, not receives them. 166 */ 167 case NMB_WACK_OPCODE: 168 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n")); 169 return False; 170 /* 171 * A WINS server only processes registration and 172 * release requests, not responses. 173 */ 174 case NMB_NAME_REG_OPCODE: 175 case NMB_NAME_MULTIHOMED_REG_OPCODE: 176 case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */ 177 case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */ 178 if(nmb->header.response) { 179 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n")); 180 return False; 181 } 182 break; 183 184 case NMB_NAME_RELEASE_OPCODE: 185 if(nmb->header.response) { 186 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n")); 187 return False; 188 } 189 break; 190 191 /* 192 * Only process unicast name queries with rd = 1. 193 */ 194 case NMB_NAME_QUERY_OPCODE: 195 if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired) { 196 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n")); 197 return False; 198 } 199 break; 200 } 201 202 return True; 203} 204 205/**************************************************************************** 206Utility function to decide what ttl to give a register/refresh request. 207*****************************************************************************/ 208 209static int get_ttl_from_packet(struct nmb_packet *nmb) 210{ 211 int ttl = nmb->additional->ttl; 212 213 if(ttl < lp_min_wins_ttl() ) 214 ttl = lp_min_wins_ttl(); 215 216 if(ttl > lp_max_wins_ttl() ) 217 ttl = lp_max_wins_ttl(); 218 219 return ttl; 220} 221 222/**************************************************************************** 223Load or create the WINS database. 224*****************************************************************************/ 225 226BOOL initialise_wins(void) 227{ 228 time_t time_now = time(NULL); 229 XFILE *fp; 230 pstring line; 231 232 if(!lp_we_are_a_wins_server()) 233 return True; 234 235 add_samba_names_to_subnet(wins_server_subnet); 236 237 if((fp = x_fopen(lock_path(WINS_LIST),O_RDONLY,0)) == NULL) { 238 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n", 239 WINS_LIST, strerror(errno) )); 240 return True; 241 } 242 243 while (!x_feof(fp)) { 244 pstring name_str, ip_str, ttl_str, nb_flags_str; 245 unsigned int num_ips; 246 pstring name; 247 struct in_addr *ip_list; 248 int type = 0; 249 int nb_flags; 250 int ttl; 251 const char *ptr; 252 char *p; 253 BOOL got_token; 254 BOOL was_ip; 255 int i; 256 unsigned int hash; 257 int version; 258 259 /* Read a line from the wins.dat file. Strips whitespace 260 from the beginning and end of the line. */ 261 if (!fgets_slash(line,sizeof(pstring),fp)) 262 continue; 263 264 if (*line == '#') 265 continue; 266 267 if (strncmp(line,"VERSION ", 8) == 0) { 268 if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 || 269 version != WINS_VERSION) { 270 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line)); 271 x_fclose(fp); 272 return True; 273 } 274 continue; 275 } 276 277 ptr = line; 278 279 /* 280 * Now we handle multiple IP addresses per name we need 281 * to iterate over the line twice. The first time to 282 * determine how many IP addresses there are, the second 283 * time to actually parse them into the ip_list array. 284 */ 285 286 if (!next_token(&ptr,name_str,NULL,sizeof(name_str))) { 287 DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line )); 288 continue; 289 } 290 291 if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str))) { 292 DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line )); 293 continue; 294 } 295 296 /* 297 * Determine the number of IP addresses per line. 298 */ 299 num_ips = 0; 300 do { 301 got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str)); 302 was_ip = False; 303 304 if(got_token && strchr(ip_str, '.')) { 305 num_ips++; 306 was_ip = True; 307 } 308 } while( got_token && was_ip); 309 310 if(num_ips == 0) { 311 DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line )); 312 continue; 313 } 314 315 if(!got_token) { 316 DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line )); 317 continue; 318 } 319 320 /* Allocate the space for the ip_list. */ 321 if((ip_list = SMB_MALLOC_ARRAY( struct in_addr, num_ips)) == NULL) { 322 DEBUG(0,("initialise_wins: Malloc fail !\n")); 323 return False; 324 } 325 326 /* Reset and re-parse the line. */ 327 ptr = line; 328 next_token(&ptr,name_str,NULL,sizeof(name_str)); 329 next_token(&ptr,ttl_str,NULL,sizeof(ttl_str)); 330 for(i = 0; i < num_ips; i++) { 331 next_token(&ptr, ip_str, NULL, sizeof(ip_str)); 332 ip_list[i] = *interpret_addr2(ip_str); 333 } 334 next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str)); 335 336 /* 337 * Deal with SELF or REGISTER name encoding. Default is REGISTER 338 * for compatibility with old nmbds. 339 */ 340 341 if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') { 342 DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line)); 343 SAFE_FREE(ip_list); 344 continue; 345 } 346 347 if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') 348 nb_flags_str[strlen(nb_flags_str)-1] = '\0'; 349 350 /* Netbios name. # divides the name from the type (hex): netbios#xx */ 351 pstrcpy(name,name_str); 352 353 if((p = strchr(name,'#')) != NULL) { 354 *p = 0; 355 sscanf(p+1,"%x",&type); 356 } 357 358 /* Decode the netbios flags (hex) and the time-to-live (in seconds). */ 359 sscanf(nb_flags_str,"%x",&nb_flags); 360 sscanf(ttl_str,"%d",&ttl); 361 362 /* add all entries that have 60 seconds or more to live */ 363 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) { 364 if(ttl != PERMANENT_TTL) 365 ttl -= time_now; 366 367 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n", 368 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); 369 370 (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags, 371 ttl, REGISTER_NAME, num_ips, ip_list ); 372 } else { 373 DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n", 374 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); 375 } 376 377 SAFE_FREE(ip_list); 378 } 379 380 x_fclose(fp); 381 return True; 382} 383 384/**************************************************************************** 385Send a WINS WACK (Wait ACKnowledgement) response. 386**************************************************************************/ 387 388static void send_wins_wack_response(int ttl, struct packet_struct *p) 389{ 390 struct nmb_packet *nmb = &p->packet.nmb; 391 unsigned char rdata[2]; 392 393 rdata[0] = rdata[1] = 0; 394 395 /* Taken from nmblib.c - we need to send back almost 396 identical bytes from the requesting packet header. */ 397 398 rdata[0] = (nmb->header.opcode & 0xF) << 3; 399 if (nmb->header.nm_flags.authoritative && nmb->header.response) 400 rdata[0] |= 0x4; 401 if (nmb->header.nm_flags.trunc) 402 rdata[0] |= 0x2; 403 if (nmb->header.nm_flags.recursion_desired) 404 rdata[0] |= 0x1; 405 if (nmb->header.nm_flags.recursion_available && nmb->header.response) 406 rdata[1] |= 0x80; 407 if (nmb->header.nm_flags.bcast) 408 rdata[1] |= 0x10; 409 410 reply_netbios_packet(p, /* Packet to reply to. */ 411 0, /* Result code. */ 412 NMB_WAIT_ACK, /* nmbd type code. */ 413 NMB_WACK_OPCODE, /* opcode. */ 414 ttl, /* ttl. */ 415 (char *)rdata, /* data to send. */ 416 2); /* data length. */ 417} 418 419/**************************************************************************** 420Send a WINS name registration response. 421**************************************************************************/ 422 423static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p) 424{ 425 struct nmb_packet *nmb = &p->packet.nmb; 426 char rdata[6]; 427 428 memcpy(&rdata[0], &nmb->additional->rdata[0], 6); 429 430 reply_netbios_packet(p, /* Packet to reply to. */ 431 rcode, /* Result code. */ 432 WINS_REG, /* nmbd type code. */ 433 NMB_NAME_REG_OPCODE, /* opcode. */ 434 ttl, /* ttl. */ 435 rdata, /* data to send. */ 436 6); /* data length. */ 437} 438 439/*********************************************************************** 440 Deal with a name refresh request to a WINS server. 441************************************************************************/ 442 443void wins_process_name_refresh_request( struct subnet_record *subrec, 444 struct packet_struct *p ) 445{ 446 struct nmb_packet *nmb = &p->packet.nmb; 447 struct nmb_name *question = &nmb->question.question_name; 448 BOOL bcast = nmb->header.nm_flags.bcast; 449 uint16 nb_flags = get_nb_flags(nmb->additional->rdata); 450 BOOL group = (nb_flags & NB_GROUP) ? True : False; 451 struct name_record *namerec = NULL; 452 int ttl = get_ttl_from_packet(nmb); 453 struct in_addr from_ip; 454 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); 455 456 putip( (char *)&from_ip, &nmb->additional->rdata[2] ); 457 458 if(bcast) { 459 /* 460 * We should only get unicast name refresh packets here. 461 * Anyone trying to refresh broadcast should not be going 462 * to a WINS server. Log an error here. 463 */ 464 if( DEBUGLVL( 0 ) ) { 465 dbgtext( "wins_process_name_refresh_request: " ); 466 dbgtext( "Broadcast name refresh request received " ); 467 dbgtext( "for name %s ", nmb_namestr(question) ); 468 dbgtext( "from IP %s ", inet_ntoa(from_ip) ); 469 dbgtext( "on subnet %s. ", subrec->subnet_name ); 470 dbgtext( "Error - Broadcasts should not be sent " ); 471 dbgtext( "to a WINS server\n" ); 472 } 473 return; 474 } 475 476 if( DEBUGLVL( 3 ) ) { 477 dbgtext( "wins_process_name_refresh_request: " ); 478 dbgtext( "Name refresh for name %s IP %s\n", 479 nmb_namestr(question), inet_ntoa(from_ip) ); 480 } 481 482 /* 483 * See if the name already exists. 484 * If not, handle it as a name registration and return. 485 */ 486 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); 487 488 /* 489 * If this is a refresh request and the name doesn't exist then 490 * treat it like a registration request. This allows us to recover 491 * from errors (tridge) 492 */ 493 if(namerec == NULL) { 494 if( DEBUGLVL( 3 ) ) { 495 dbgtext( "wins_process_name_refresh_request: " ); 496 dbgtext( "Name refresh for name %s ", 497 nmb_namestr( question ) ); 498 dbgtext( "and the name does not exist. Treating " ); 499 dbgtext( "as registration.\n" ); 500 } 501 wins_process_name_registration_request(subrec,p); 502 return; 503 } 504 505 /* 506 * if the name is present but not active, simply remove it 507 * and treat the refresh request as a registration & return. 508 */ 509 if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) { 510 if( DEBUGLVL( 5 ) ) { 511 dbgtext( "wins_process_name_refresh_request: " ); 512 dbgtext( "Name (%s) in WINS ", nmb_namestr(question) ); 513 dbgtext( "was not active - removing it.\n" ); 514 } 515 remove_name_from_namelist( subrec, namerec ); 516 namerec = NULL; 517 wins_process_name_registration_request( subrec, p ); 518 return; 519 } 520 521 /* 522 * Check that the group bits for the refreshing name and the 523 * name in our database match. If not, refuse the refresh. 524 * [crh: Why RFS_ERR instead of ACT_ERR? Is this what MS does?] 525 */ 526 if( (namerec != NULL) && 527 ( (group && !NAME_GROUP(namerec)) 528 || (!group && NAME_GROUP(namerec)) ) ) { 529 if( DEBUGLVL( 3 ) ) { 530 dbgtext( "wins_process_name_refresh_request: " ); 531 dbgtext( "Name %s ", nmb_namestr(question) ); 532 dbgtext( "group bit = %s does not match ", 533 group ? "True" : "False" ); 534 dbgtext( "group bit in WINS for this name.\n" ); 535 } 536 send_wins_name_registration_response(RFS_ERR, 0, p); 537 return; 538 } 539 540 /* 541 * For a unique name check that the person refreshing the name is 542 * one of the registered IP addresses. If not - fail the refresh. 543 * Do the same for group names with a type of 0x1c. 544 * Just return success for unique 0x1d refreshes. For normal group 545 * names update the ttl and return success. 546 */ 547 if( (!group || (group && (question->name_type == 0x1c))) 548 && find_ip_in_name_record(namerec, from_ip) ) { 549 /* 550 * Update the ttl. 551 */ 552 update_name_ttl(namerec, ttl); 553 554 /* 555 * if the record is a replica: 556 * we take ownership and update the version ID. 557 */ 558 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) { 559 update_wins_owner(namerec, our_fake_ip); 560 get_global_id_and_update(&namerec->data.id, True); 561 } 562 563 send_wins_name_registration_response(0, ttl, p); 564 wins_hook("refresh", namerec, ttl); 565 return; 566 } else if((group && (question->name_type == 0x1c))) { 567 /* 568 * Added by crh for bug #1079. 569 * Fix from Bert Driehuis 570 */ 571 if( DEBUGLVL( 3 ) ) { 572 dbgtext( "wins_process_name_refresh_request: " ); 573 dbgtext( "Name refresh for name %s, ", 574 nmb_namestr(question) ); 575 dbgtext( "but IP address %s ", inet_ntoa(from_ip) ); 576 dbgtext( "is not yet associated with " ); 577 dbgtext( "that name. Treating as registration.\n" ); 578 } 579 wins_process_name_registration_request(subrec,p); 580 return; 581 } else if(group) { 582 /* 583 * Normal groups are all registered with an IP address of 584 * 255.255.255.255 so we can't search for the IP address. 585 */ 586 update_name_ttl(namerec, ttl); 587 send_wins_name_registration_response(0, ttl, p); 588 return; 589 } else if(!group && (question->name_type == 0x1d)) { 590 /* 591 * Special name type - just pretend the refresh succeeded. 592 */ 593 send_wins_name_registration_response(0, ttl, p); 594 return; 595 } else { 596 /* 597 * Fail the refresh. 598 */ 599 if( DEBUGLVL( 3 ) ) { 600 dbgtext( "wins_process_name_refresh_request: " ); 601 dbgtext( "Name refresh for name %s with IP %s ", 602 nmb_namestr(question), inet_ntoa(from_ip) ); 603 dbgtext( "and is IP is not known to the name.\n" ); 604 } 605 send_wins_name_registration_response(RFS_ERR, 0, p); 606 return; 607 } 608} 609 610/*********************************************************************** 611 Deal with a name registration request query success to a client that 612 owned the name. 613 614 We have a locked pointer to the original packet stashed away in the 615 userdata pointer. The success here is actually a failure as it means 616 the client we queried wants to keep the name, so we must return 617 a registration failure to the original requestor. 618************************************************************************/ 619 620static void wins_register_query_success(struct subnet_record *subrec, 621 struct userdata_struct *userdata, 622 struct nmb_name *question_name, 623 struct in_addr ip, 624 struct res_rec *answers) 625{ 626 struct packet_struct *orig_reg_packet; 627 628 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); 629 630 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \ 631name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) )); 632 633 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); 634 635 orig_reg_packet->locked = False; 636 free_packet(orig_reg_packet); 637} 638 639/*********************************************************************** 640 Deal with a name registration request query failure to a client that 641 owned the name. 642 643 We have a locked pointer to the original packet stashed away in the 644 userdata pointer. The failure here is actually a success as it means 645 the client we queried didn't want to keep the name, so we can remove 646 the old name record and then successfully add the new name. 647************************************************************************/ 648 649static void wins_register_query_fail(struct subnet_record *subrec, 650 struct response_record *rrec, 651 struct nmb_name *question_name, 652 int rcode) 653{ 654 struct userdata_struct *userdata = rrec->userdata; 655 struct packet_struct *orig_reg_packet; 656 struct name_record *namerec = NULL; 657 658 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); 659 660 /* 661 * We want to just add the name, as we now know the original owner 662 * didn't want it. But we can't just do that as an arbitary 663 * amount of time may have taken place between the name query 664 * request and this timeout/error response. So we check that 665 * the name still exists and is in the same state - if so 666 * we remove it and call wins_process_name_registration_request() 667 * as we know it will do the right thing now. 668 */ 669 670 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME); 671 672 if( (namerec != NULL) && (namerec->data.source == REGISTER_NAME) && ip_equal(rrec->packet->ip, *namerec->data.ip) ) { 673 remove_name_from_namelist( subrec, namerec); 674 namerec = NULL; 675 } 676 677 if(namerec == NULL) 678 wins_process_name_registration_request(subrec, orig_reg_packet); 679 else 680 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \ 681querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) )); 682 683 orig_reg_packet->locked = False; 684 free_packet(orig_reg_packet); 685} 686 687/*********************************************************************** 688 Deal with a name registration request to a WINS server. 689 690 Use the following pseudocode : 691 692 registering_group 693 | 694 | 695 +--------name exists 696 | | 697 | | 698 | +--- existing name is group 699 | | | 700 | | | 701 | | +--- add name (return). 702 | | 703 | | 704 | +--- exiting name is unique 705 | | 706 | | 707 | +--- query existing owner (return). 708 | 709 | 710 +--------name doesn't exist 711 | 712 | 713 +--- add name (return). 714 715 registering_unique 716 | 717 | 718 +--------name exists 719 | | 720 | | 721 | +--- existing name is group 722 | | | 723 | | | 724 | | +--- fail add (return). 725 | | 726 | | 727 | +--- exiting name is unique 728 | | 729 | | 730 | +--- query existing owner (return). 731 | 732 | 733 +--------name doesn't exist 734 | 735 | 736 +--- add name (return). 737 738 As can be seen from the above, the two cases may be collapsed onto each 739 other with the exception of the case where the name already exists and 740 is a group name. This case we handle with an if statement. 741 742************************************************************************/ 743 744void wins_process_name_registration_request(struct subnet_record *subrec, 745 struct packet_struct *p) 746{ 747 unstring name; 748 struct nmb_packet *nmb = &p->packet.nmb; 749 struct nmb_name *question = &nmb->question.question_name; 750 BOOL bcast = nmb->header.nm_flags.bcast; 751 uint16 nb_flags = get_nb_flags(nmb->additional->rdata); 752 int ttl = get_ttl_from_packet(nmb); 753 struct name_record *namerec = NULL; 754 struct in_addr from_ip; 755 BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False; 756 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); 757 758 putip((char *)&from_ip,&nmb->additional->rdata[2]); 759 760 if(bcast) { 761 /* 762 * We should only get unicast name registration packets here. 763 * Anyone trying to register broadcast should not be going to a WINS 764 * server. Log an error here. 765 */ 766 767 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \ 768received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n", 769 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); 770 return; 771 } 772 773 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \ 774IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) )); 775 776 /* 777 * See if the name already exists. 778 */ 779 780 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); 781 782 /* 783 * if the record exists but NOT in active state, 784 * consider it dead. 785 */ 786 if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) { 787 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \ 788not active - removing it.\n", nmb_namestr(question) )); 789 remove_name_from_namelist( subrec, namerec ); 790 namerec = NULL; 791 } 792 793 /* 794 * Deal with the case where the name found was a dns entry. 795 * Remove it as we now have a NetBIOS client registering the 796 * name. 797 */ 798 799 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) { 800 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \ 801a dns lookup - removing it.\n", nmb_namestr(question) )); 802 remove_name_from_namelist( subrec, namerec ); 803 namerec = NULL; 804 } 805 806 /* 807 * Reject if the name exists and is not a REGISTER_NAME. 808 * (ie. Don't allow any static names to be overwritten. 809 */ 810 811 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) { 812 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \ 813to register name %s. Name already exists in WINS with source type %d.\n", 814 nmb_namestr(question), namerec->data.source )); 815 send_wins_name_registration_response(RFS_ERR, 0, p); 816 return; 817 } 818 819 /* 820 * Special policy decisions based on MS documentation. 821 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255. 822 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent. 823 */ 824 825 /* 826 * A group name is always added as the local broadcast address, except 827 * for group names ending in 0x1c. 828 * Group names with type 0x1c are registered with individual IP addresses. 829 */ 830 831 if(registering_group_name && (question->name_type != 0x1c)) 832 from_ip = *interpret_addr2("255.255.255.255"); 833 834 /* 835 * Ignore all attempts to register a unique 0x1d name, although return success. 836 */ 837 838 if(!registering_group_name && (question->name_type == 0x1d)) { 839 DEBUG(3,("wins_process_name_registration_request: Ignoring request \ 840to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) )); 841 send_wins_name_registration_response(0, ttl, p); 842 return; 843 } 844 845 /* 846 * Next two cases are the 'if statement' mentioned above. 847 */ 848 849 if((namerec != NULL) && NAME_GROUP(namerec)) { 850 if(registering_group_name) { 851 /* 852 * If we are adding a group name, the name exists and is also a group entry just add this 853 * IP address to it and update the ttl. 854 */ 855 856 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n", 857 inet_ntoa(from_ip), nmb_namestr(question) )); 858 859 /* 860 * Check the ip address is not already in the group. 861 */ 862 863 if(!find_ip_in_name_record(namerec, from_ip)) { 864 add_ip_to_name_record(namerec, from_ip); 865 /* we need to update the record for replication */ 866 get_global_id_and_update(&namerec->data.id, True); 867 868 /* 869 * if the record is a replica, we must change 870 * the wins owner to us to make the replication updates 871 * it on the other wins servers. 872 * And when the partner will receive this record, 873 * it will update its own record. 874 */ 875 876 update_wins_owner(namerec, our_fake_ip); 877 } 878 update_name_ttl(namerec, ttl); 879 send_wins_name_registration_response(0, ttl, p); 880 return; 881 } else { 882 883 /* 884 * If we are adding a unique name, the name exists in the WINS db 885 * and is a group name then reject the registration. 886 * 887 * explanation: groups have a higher priority than unique names. 888 */ 889 890 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \ 891already exists in WINS as a GROUP name.\n", nmb_namestr(question) )); 892 send_wins_name_registration_response(RFS_ERR, 0, p); 893 return; 894 } 895 } 896 897 /* 898 * From here on down we know that if the name exists in the WINS db it is 899 * a unique name, not a group name. 900 */ 901 902 /* 903 * If the name exists and is one of our names then check the 904 * registering IP address. If it's not one of ours then automatically 905 * reject without doing the query - we know we will reject it. 906 */ 907 908 if ( namerec != NULL ) 909 pull_ascii_nstring(name, sizeof(name), namerec->name.name); 910 911 if( is_myname(name) ) { 912 if(!ismyip(from_ip)) { 913 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \ 914is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) )); 915 send_wins_name_registration_response(RFS_ERR, 0, p); 916 return; 917 } else { 918 /* 919 * It's one of our names and one of our IP's - update the ttl. 920 */ 921 update_name_ttl(namerec, ttl); 922 send_wins_name_registration_response(0, ttl, p); 923 wins_hook("refresh", namerec, ttl); 924 return; 925 } 926 } 927 928 /* 929 * If the name exists and it is a unique registration and the registering IP 930 * is the same as the (single) already registered IP then just update the ttl. 931 * 932 * But not if the record is an active replica. IF it's a replica, it means it can be 933 * the same client which has moved and not yet expired. So we don't update 934 * the ttl in this case and go beyond to do a WACK and query the old client 935 */ 936 937 if( !registering_group_name 938 && (namerec != NULL) 939 && (namerec->data.num_ips == 1) 940 && ip_equal( namerec->data.ip[0], from_ip ) 941 && ip_equal(namerec->data.wins_ip, our_fake_ip) ) { 942 update_name_ttl( namerec, ttl ); 943 send_wins_name_registration_response( 0, ttl, p ); 944 wins_hook("refresh", namerec, ttl); 945 return; 946 } 947 948 /* 949 * Finally if the name exists do a query to the registering machine 950 * to see if they still claim to have the name. 951 */ 952 953 if( namerec != NULL ) { 954 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1]; 955 struct userdata_struct *userdata = (struct userdata_struct *)ud; 956 957 /* 958 * First send a WACK to the registering machine. 959 */ 960 961 send_wins_wack_response(60, p); 962 963 /* 964 * When the reply comes back we need the original packet. 965 * Lock this so it won't be freed and then put it into 966 * the userdata structure. 967 */ 968 969 p->locked = True; 970 971 userdata = (struct userdata_struct *)ud; 972 973 userdata->copy_fn = NULL; 974 userdata->free_fn = NULL; 975 userdata->userdata_len = sizeof(struct packet_struct *); 976 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) ); 977 978 /* 979 * Use the new call to send a query directly to an IP address. 980 * This sends the query directly to the IP address, and ensures 981 * the recursion desired flag is not set (you were right Luke :-). 982 * This function should *only* be called from the WINS server 983 * code. JRA. 984 */ 985 986 pull_ascii_nstring(name, sizeof(name), question->name); 987 query_name_from_wins_server( *namerec->data.ip, 988 name, 989 question->name_type, 990 wins_register_query_success, 991 wins_register_query_fail, 992 userdata ); 993 return; 994 } 995 996 /* 997 * Name did not exist - add it. 998 */ 999 1000 pull_ascii_nstring(name, sizeof(name), question->name); 1001 add_name_to_subnet( subrec, name, question->name_type, 1002 nb_flags, ttl, REGISTER_NAME, 1, &from_ip); 1003 1004 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) { 1005 get_global_id_and_update(&namerec->data.id, True); 1006 update_wins_owner(namerec, our_fake_ip); 1007 update_wins_flag(namerec, WINS_ACTIVE); 1008 wins_hook("add", namerec, ttl); 1009 } 1010 1011 send_wins_name_registration_response(0, ttl, p); 1012} 1013 1014/*********************************************************************** 1015 Deal with a mutihomed name query success to the machine that 1016 requested the multihomed name registration. 1017 1018 We have a locked pointer to the original packet stashed away in the 1019 userdata pointer. 1020************************************************************************/ 1021 1022static void wins_multihomed_register_query_success(struct subnet_record *subrec, 1023 struct userdata_struct *userdata, 1024 struct nmb_name *question_name, 1025 struct in_addr ip, 1026 struct res_rec *answers) 1027{ 1028 struct packet_struct *orig_reg_packet; 1029 struct nmb_packet *nmb; 1030 struct name_record *namerec = NULL; 1031 struct in_addr from_ip; 1032 int ttl; 1033 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); 1034 1035 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); 1036 1037 nmb = &orig_reg_packet->packet.nmb; 1038 1039 putip((char *)&from_ip,&nmb->additional->rdata[2]); 1040 ttl = get_ttl_from_packet(nmb); 1041 1042 /* 1043 * We want to just add the new IP, as we now know the requesting 1044 * machine claims to own it. But we can't just do that as an arbitary 1045 * amount of time may have taken place between the name query 1046 * request and this response. So we check that 1047 * the name still exists and is in the same state - if so 1048 * we just add the extra IP and update the ttl. 1049 */ 1050 1051 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME); 1052 1053 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) { 1054 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \ 1055a subsequent IP address.\n", nmb_namestr(question_name) )); 1056 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); 1057 1058 orig_reg_packet->locked = False; 1059 free_packet(orig_reg_packet); 1060 1061 return; 1062 } 1063 1064 if(!find_ip_in_name_record(namerec, from_ip)) 1065 add_ip_to_name_record(namerec, from_ip); 1066 1067 get_global_id_and_update(&namerec->data.id, True); 1068 update_wins_owner(namerec, our_fake_ip); 1069 update_wins_flag(namerec, WINS_ACTIVE); 1070 update_name_ttl(namerec, ttl); 1071 send_wins_name_registration_response(0, ttl, orig_reg_packet); 1072 wins_hook("add", namerec, ttl); 1073 1074 orig_reg_packet->locked = False; 1075 free_packet(orig_reg_packet); 1076} 1077 1078/*********************************************************************** 1079 Deal with a name registration request query failure to a client that 1080 owned the name. 1081 1082 We have a locked pointer to the original packet stashed away in the 1083 userdata pointer. 1084************************************************************************/ 1085 1086static void wins_multihomed_register_query_fail(struct subnet_record *subrec, 1087 struct response_record *rrec, 1088 struct nmb_name *question_name, 1089 int rcode) 1090{ 1091 struct userdata_struct *userdata = rrec->userdata; 1092 struct packet_struct *orig_reg_packet; 1093 1094 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); 1095 1096 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \ 1097query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) )); 1098 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); 1099 1100 orig_reg_packet->locked = False; 1101 free_packet(orig_reg_packet); 1102 return; 1103} 1104 1105/*********************************************************************** 1106 Deal with a multihomed name registration request to a WINS server. 1107 These cannot be group name registrations. 1108***********************************************************************/ 1109 1110void wins_process_multihomed_name_registration_request( struct subnet_record *subrec, 1111 struct packet_struct *p) 1112{ 1113 struct nmb_packet *nmb = &p->packet.nmb; 1114 struct nmb_name *question = &nmb->question.question_name; 1115 BOOL bcast = nmb->header.nm_flags.bcast; 1116 uint16 nb_flags = get_nb_flags(nmb->additional->rdata); 1117 int ttl = get_ttl_from_packet(nmb); 1118 struct name_record *namerec = NULL; 1119 struct in_addr from_ip; 1120 BOOL group = (nb_flags & NB_GROUP) ? True : False; 1121 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); 1122 unstring qname; 1123 1124 putip((char *)&from_ip,&nmb->additional->rdata[2]); 1125 1126 if(bcast) { 1127 /* 1128 * We should only get unicast name registration packets here. 1129 * Anyone trying to register broadcast should not be going to a WINS 1130 * server. Log an error here. 1131 */ 1132 1133 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \ 1134received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n", 1135 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); 1136 return; 1137 } 1138 1139 /* 1140 * Only unique names should be registered multihomed. 1141 */ 1142 1143 if(group) { 1144 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \ 1145received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n", 1146 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); 1147 return; 1148 } 1149 1150 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \ 1151IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) )); 1152 1153 /* 1154 * Deal with policy regarding 0x1d names. 1155 */ 1156 1157 if(question->name_type == 0x1d) { 1158 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \ 1159to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) )); 1160 send_wins_name_registration_response(0, ttl, p); 1161 return; 1162 } 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 1175 if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) { 1176 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not 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_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \ 1189- 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_multihomed_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 * Reject if the name exists and is a GROUP name and is active. 1209 */ 1210 1211 if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) { 1212 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \ 1213already exists in WINS as a GROUP name.\n", nmb_namestr(question) )); 1214 send_wins_name_registration_response(RFS_ERR, 0, p); 1215 return; 1216 } 1217 1218 /* 1219 * From here on down we know that if the name exists in the WINS db it is 1220 * a unique name, not a group name. 1221 */ 1222 1223 /* 1224 * If the name exists and is one of our names then check the 1225 * registering IP address. If it's not one of ours then automatically 1226 * reject without doing the query - we know we will reject it. 1227 */ 1228 1229 if((namerec != NULL) && (is_myname(namerec->name.name)) ) { 1230 if(!ismyip(from_ip)) { 1231 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \ 1232is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) )); 1233 send_wins_name_registration_response(RFS_ERR, 0, p); 1234 return; 1235 } else { 1236 /* 1237 * It's one of our names and one of our IP's. Ensure the IP is in the record and 1238 * update the ttl. Update the version ID to force replication. 1239 */ 1240 if(!find_ip_in_name_record(namerec, from_ip)) { 1241 get_global_id_and_update(&namerec->data.id, True); 1242 update_wins_owner(namerec, our_fake_ip); 1243 update_wins_flag(namerec, WINS_ACTIVE); 1244 1245 add_ip_to_name_record(namerec, from_ip); 1246 wins_hook("add", namerec, ttl); 1247 } else { 1248 wins_hook("refresh", namerec, ttl); 1249 } 1250 1251 update_name_ttl(namerec, ttl); 1252 send_wins_name_registration_response(0, ttl, p); 1253 return; 1254 } 1255 } 1256 1257 /* 1258 * If the name exists and is active, check if the IP address is already registered 1259 * to that name. If so then update the ttl and reply success. 1260 */ 1261 1262 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) { 1263 update_name_ttl(namerec, ttl); 1264 1265 /* 1266 * If it's a replica, we need to become the wins owner 1267 * to force the replication 1268 */ 1269 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) { 1270 get_global_id_and_update(&namerec->data.id, True); 1271 update_wins_owner(namerec, our_fake_ip); 1272 update_wins_flag(namerec, WINS_ACTIVE); 1273 } 1274 1275 send_wins_name_registration_response(0, ttl, p); 1276 wins_hook("refresh", namerec, ttl); 1277 return; 1278 } 1279 1280 /* 1281 * If the name exists do a query to the owner 1282 * to see if they still want the name. 1283 */ 1284 1285 if(namerec != NULL) { 1286 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1]; 1287 struct userdata_struct *userdata = (struct userdata_struct *)ud; 1288 1289 /* 1290 * First send a WACK to the registering machine. 1291 */ 1292 1293 send_wins_wack_response(60, p); 1294 1295 /* 1296 * When the reply comes back we need the original packet. 1297 * Lock this so it won't be freed and then put it into 1298 * the userdata structure. 1299 */ 1300 1301 p->locked = True; 1302 1303 userdata = (struct userdata_struct *)ud; 1304 1305 userdata->copy_fn = NULL; 1306 userdata->free_fn = NULL; 1307 userdata->userdata_len = sizeof(struct packet_struct *); 1308 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) ); 1309 1310 /* 1311 * Use the new call to send a query directly to an IP address. 1312 * This sends the query directly to the IP address, and ensures 1313 * the recursion desired flag is not set (you were right Luke :-). 1314 * This function should *only* be called from the WINS server 1315 * code. JRA. 1316 * 1317 * Note that this packet is sent to the current owner of the name, 1318 * not the person who sent the packet 1319 */ 1320 1321 pull_ascii_nstring( qname, sizeof(qname), question->name); 1322 query_name_from_wins_server( namerec->data.ip[0], 1323 qname, 1324 question->name_type, 1325 wins_multihomed_register_query_success, 1326 wins_multihomed_register_query_fail, 1327 userdata ); 1328 1329 return; 1330 } 1331 1332 /* 1333 * Name did not exist - add it. 1334 */ 1335 1336 pull_ascii_nstring( qname, sizeof(qname), question->name); 1337 add_name_to_subnet( subrec, qname, question->name_type, 1338 nb_flags, ttl, REGISTER_NAME, 1, &from_ip); 1339 1340 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) { 1341 get_global_id_and_update(&namerec->data.id, True); 1342 update_wins_owner(namerec, our_fake_ip); 1343 update_wins_flag(namerec, WINS_ACTIVE); 1344 wins_hook("add", namerec, ttl); 1345 } 1346 1347 send_wins_name_registration_response(0, ttl, p); 1348} 1349 1350/*********************************************************************** 1351 Deal with the special name query for *<1b>. 1352***********************************************************************/ 1353 1354static void process_wins_dmb_query_request(struct subnet_record *subrec, 1355 struct packet_struct *p) 1356{ 1357 struct name_record *namerec = NULL; 1358 char *prdata; 1359 int num_ips; 1360 1361 /* 1362 * Go through all the ACTIVE names in the WINS db looking for those 1363 * ending in <1b>. Use this to calculate the number of IP 1364 * addresses we need to return. 1365 */ 1366 1367 num_ips = 0; 1368 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); 1369 namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) { 1370 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b ) 1371 num_ips += namerec->data.num_ips; 1372 } 1373 1374 if(num_ips == 0) { 1375 /* 1376 * There are no 0x1b names registered. Return name query fail. 1377 */ 1378 send_wins_name_query_response(NAM_ERR, p, NULL); 1379 return; 1380 } 1381 1382 if((prdata = (char *)SMB_MALLOC( num_ips * 6 )) == NULL) { 1383 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n")); 1384 return; 1385 } 1386 1387 /* 1388 * Go through all the names again in the WINS db looking for those 1389 * ending in <1b>. Add their IP addresses into the list we will 1390 * return. 1391 */ 1392 1393 num_ips = 0; 1394 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); 1395 namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) { 1396 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) { 1397 int i; 1398 for(i = 0; i < namerec->data.num_ips; i++) { 1399 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags); 1400 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]); 1401 num_ips++; 1402 } 1403 } 1404 } 1405 1406 /* 1407 * Send back the reply containing the IP list. 1408 */ 1409 1410 reply_netbios_packet(p, /* Packet to reply to. */ 1411 0, /* Result code. */ 1412 WINS_QUERY, /* nmbd type code. */ 1413 NMB_NAME_QUERY_OPCODE, /* opcode. */ 1414 lp_min_wins_ttl(), /* ttl. */ 1415 prdata, /* data to send. */ 1416 num_ips*6); /* data length. */ 1417 1418 SAFE_FREE(prdata); 1419} 1420 1421/**************************************************************************** 1422Send a WINS name query response. 1423**************************************************************************/ 1424 1425void send_wins_name_query_response(int rcode, struct packet_struct *p, 1426 struct name_record *namerec) 1427{ 1428 char rdata[6]; 1429 char *prdata = rdata; 1430 int reply_data_len = 0; 1431 int ttl = 0; 1432 int i; 1433 1434 memset(rdata,'\0',6); 1435 1436 if(rcode == 0) { 1437 ttl = (namerec->data.death_time != PERMANENT_TTL) ? namerec->data.death_time - p->timestamp : lp_max_wins_ttl(); 1438 1439 /* Copy all known ip addresses into the return data. */ 1440 /* Optimise for the common case of one IP address so we don't need a malloc. */ 1441 1442 if( namerec->data.num_ips == 1 ) { 1443 prdata = rdata; 1444 } else { 1445 if((prdata = (char *)SMB_MALLOC( namerec->data.num_ips * 6 )) == NULL) { 1446 DEBUG(0,("send_wins_name_query_response: malloc fail !\n")); 1447 return; 1448 } 1449 } 1450 1451 for(i = 0; i < namerec->data.num_ips; i++) { 1452 set_nb_flags(&prdata[i*6],namerec->data.nb_flags); 1453 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]); 1454 } 1455 1456 sort_query_replies(prdata, i, p->ip); 1457 reply_data_len = namerec->data.num_ips * 6; 1458 } 1459 1460 reply_netbios_packet(p, /* Packet to reply to. */ 1461 rcode, /* Result code. */ 1462 WINS_QUERY, /* nmbd type code. */ 1463 NMB_NAME_QUERY_OPCODE, /* opcode. */ 1464 ttl, /* ttl. */ 1465 prdata, /* data to send. */ 1466 reply_data_len); /* data length. */ 1467 1468 if(prdata != rdata) 1469 SAFE_FREE(prdata); 1470} 1471 1472/*********************************************************************** 1473 Deal with a name query. 1474***********************************************************************/ 1475 1476void wins_process_name_query_request(struct subnet_record *subrec, 1477 struct packet_struct *p) 1478{ 1479 struct nmb_packet *nmb = &p->packet.nmb; 1480 struct nmb_name *question = &nmb->question.question_name; 1481 struct name_record *namerec = NULL; 1482 unstring qname; 1483 1484 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n", 1485 nmb_namestr(question), inet_ntoa(p->ip) )); 1486 1487 /* 1488 * Special name code. If the queried name is *<1b> then search 1489 * the entire WINS database and return a list of all the IP addresses 1490 * registered to any <1b> name. This is to allow domain master browsers 1491 * to discover other domains that may not have a presence on their subnet. 1492 */ 1493 1494 pull_ascii_nstring(qname, sizeof(qname), question->name); 1495 if(strequal( qname, "*") && (question->name_type == 0x1b)) { 1496 process_wins_dmb_query_request( subrec, p); 1497 return; 1498 } 1499 1500 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); 1501 1502 if(namerec != NULL) { 1503 /* 1504 * If the name is not anymore in active state then reply not found. 1505 * it's fair even if we keep it in the cache for days. 1506 */ 1507 if (!WINS_STATE_ACTIVE(namerec)) { 1508 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n", 1509 nmb_namestr(question) )); 1510 send_wins_name_query_response(NAM_ERR, p, namerec); 1511 return; 1512 } 1513 1514 /* 1515 * If it's a DNSFAIL_NAME then reply name not found. 1516 */ 1517 1518 if( namerec->data.source == DNSFAIL_NAME ) { 1519 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n", 1520 nmb_namestr(question) )); 1521 send_wins_name_query_response(NAM_ERR, p, namerec); 1522 return; 1523 } 1524 1525 /* 1526 * If the name has expired then reply name not found. 1527 */ 1528 1529 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < p->timestamp) ) { 1530 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n", 1531 nmb_namestr(question) )); 1532 send_wins_name_query_response(NAM_ERR, p, namerec); 1533 return; 1534 } 1535 1536 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n", 1537 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) )); 1538 1539 send_wins_name_query_response(0, p, namerec); 1540 return; 1541 } 1542 1543 /* 1544 * Name not found in WINS - try a dns query if it's a 0x20 name. 1545 */ 1546 1547 if(lp_dns_proxy() && ((question->name_type == 0x20) || question->name_type == 0)) { 1548 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n", 1549 nmb_namestr(question) )); 1550 1551 queue_dns_query(p, question, &namerec); 1552 return; 1553 } 1554 1555 /* 1556 * Name not found - return error. 1557 */ 1558 1559 send_wins_name_query_response(NAM_ERR, p, NULL); 1560} 1561 1562/**************************************************************************** 1563Send a WINS name release response. 1564**************************************************************************/ 1565 1566static void send_wins_name_release_response(int rcode, struct packet_struct *p) 1567{ 1568 struct nmb_packet *nmb = &p->packet.nmb; 1569 char rdata[6]; 1570 1571 memcpy(&rdata[0], &nmb->additional->rdata[0], 6); 1572 1573 reply_netbios_packet(p, /* Packet to reply to. */ 1574 rcode, /* Result code. */ 1575 NMB_REL, /* nmbd type code. */ 1576 NMB_NAME_RELEASE_OPCODE, /* opcode. */ 1577 0, /* ttl. */ 1578 rdata, /* data to send. */ 1579 6); /* data length. */ 1580} 1581 1582/*********************************************************************** 1583 Deal with a name release. 1584***********************************************************************/ 1585 1586void wins_process_name_release_request(struct subnet_record *subrec, 1587 struct packet_struct *p) 1588{ 1589 struct nmb_packet *nmb = &p->packet.nmb; 1590 struct nmb_name *question = &nmb->question.question_name; 1591 BOOL bcast = nmb->header.nm_flags.bcast; 1592 uint16 nb_flags = get_nb_flags(nmb->additional->rdata); 1593 struct name_record *namerec = NULL; 1594 struct in_addr from_ip; 1595 BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;; 1596 1597 putip((char *)&from_ip,&nmb->additional->rdata[2]); 1598 1599 if(bcast) { 1600 /* 1601 * We should only get unicast name registration packets here. 1602 * Anyone trying to register broadcast should not be going to a WINS 1603 * server. Log an error here. 1604 */ 1605 1606 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \ 1607received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n", 1608 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); 1609 return; 1610 } 1611 1612 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \ 1613IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) )); 1614 1615 /* 1616 * Deal with policy regarding 0x1d names. 1617 */ 1618 1619 if(!releasing_group_name && (question->name_type == 0x1d)) { 1620 DEBUG(3,("wins_process_name_release_request: Ignoring request \ 1621to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) )); 1622 send_wins_name_release_response(0, p); 1623 return; 1624 } 1625 1626 /* 1627 * See if the name already exists. 1628 */ 1629 1630 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); 1631 1632 if( (namerec == NULL) || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) { 1633 send_wins_name_release_response(NAM_ERR, p); 1634 return; 1635 } 1636 1637 /* 1638 * Check that the sending machine has permission to release this name. 1639 * If it's a group name not ending in 0x1c then just say yes and let 1640 * the group time out. 1641 */ 1642 1643 if(releasing_group_name && (question->name_type != 0x1c)) { 1644 send_wins_name_release_response(0, p); 1645 return; 1646 } 1647 1648 /* 1649 * Check that the releasing node is on the list of IP addresses 1650 * for this name. Disallow the release if not. 1651 */ 1652 1653 if(!find_ip_in_name_record(namerec, from_ip)) { 1654 DEBUG(3,("wins_process_name_release_request: Refusing request to \ 1655release name %s as IP %s is not one of the known IP's for this name.\n", 1656 nmb_namestr(question), inet_ntoa(from_ip) )); 1657 send_wins_name_release_response(NAM_ERR, p); 1658 return; 1659 } 1660 1661 /* 1662 * Check if the record is active. IF it's already released 1663 * or tombstoned, refuse the release. 1664 */ 1665 1666 if (!WINS_STATE_ACTIVE(namerec)) { 1667 DEBUG(3,("wins_process_name_release_request: Refusing request to \ 1668release name %s as this record is not active anymore.\n", nmb_namestr(question) )); 1669 send_wins_name_release_response(NAM_ERR, p); 1670 return; 1671 } 1672 1673 /* 1674 * Check if the record is a 0x1c group 1675 * and has more then one ip 1676 * remove only this address. 1677 */ 1678 1679 if(releasing_group_name && (question->name_type == 0x1c) && (namerec->data.num_ips > 1)) { 1680 remove_ip_from_name_record(namerec, from_ip); 1681 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n", 1682 inet_ntoa(from_ip),nmb_namestr(question))); 1683 send_wins_name_release_response(0, p); 1684 return; 1685 } 1686 1687 /* 1688 * Send a release response. 1689 * Flag the name as released and update the ttl 1690 */ 1691 1692 send_wins_name_release_response(0, p); 1693 1694 namerec->data.wins_flags |= WINS_RELEASED; 1695 update_name_ttl(namerec, EXTINCTION_INTERVAL); 1696 1697 wins_hook("delete", namerec, 0); 1698} 1699 1700/******************************************************************* 1701 WINS time dependent processing. 1702******************************************************************/ 1703 1704void initiate_wins_processing(time_t t) 1705{ 1706 static time_t lasttime = 0; 1707 struct name_record *namerec; 1708 struct name_record *next_namerec; 1709 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); 1710 1711 if (!lasttime) 1712 lasttime = t; 1713 if (t - lasttime < 20) 1714 return; 1715 1716 lasttime = t; 1717 1718 if(!lp_we_are_a_wins_server()) 1719 return; 1720 1721 for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); 1722 namerec; 1723 namerec = next_namerec ) { 1724 next_namerec = (struct name_record *)ubi_trNext( namerec ); 1725 1726 if( (namerec->data.death_time != PERMANENT_TTL) 1727 && (namerec->data.death_time < t) ) { 1728 1729 if( namerec->data.source == SELF_NAME ) { 1730 DEBUG( 3, ( "initiate_wins_processing: Subnet %s not expiring SELF name %s\n", 1731 wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) ); 1732 namerec->data.death_time += 300; 1733 namerec->subnet->namelist_changed = True; 1734 continue; 1735 } else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) { 1736 DEBUG(3,("initiate_wins_processing: deleting timed out DNS name %s\n", 1737 nmb_namestr(&namerec->name))); 1738 remove_name_from_namelist( wins_server_subnet, namerec ); 1739 continue; 1740 } 1741 1742 /* handle records, samba is the wins owner */ 1743 if (ip_equal(namerec->data.wins_ip, our_fake_ip)) { 1744 switch (namerec->data.wins_flags | WINS_STATE_MASK) { 1745 case WINS_ACTIVE: 1746 namerec->data.wins_flags&=~WINS_STATE_MASK; 1747 namerec->data.wins_flags|=WINS_RELEASED; 1748 namerec->data.death_time = t + EXTINCTION_INTERVAL; 1749 DEBUG(3,("initiate_wins_processing: expiring %s\n", nmb_namestr(&namerec->name))); 1750 break; 1751 case WINS_RELEASED: 1752 namerec->data.wins_flags&=~WINS_STATE_MASK; 1753 namerec->data.wins_flags|=WINS_TOMBSTONED; 1754 namerec->data.death_time = t + EXTINCTION_TIMEOUT; 1755 get_global_id_and_update(&namerec->data.id, True); 1756 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name))); 1757 break; 1758 case WINS_TOMBSTONED: 1759 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name))); 1760 remove_name_from_namelist( wins_server_subnet, namerec ); 1761 break; 1762 } 1763 } else { 1764 switch (namerec->data.wins_flags | WINS_STATE_MASK) { 1765 case WINS_ACTIVE: 1766 /* that's not as MS says it should be */ 1767 namerec->data.wins_flags&=~WINS_STATE_MASK; 1768 namerec->data.wins_flags|=WINS_TOMBSTONED; 1769 namerec->data.death_time = t + EXTINCTION_TIMEOUT; 1770 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name))); 1771 case WINS_TOMBSTONED: 1772 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name))); 1773 remove_name_from_namelist( wins_server_subnet, namerec ); 1774 break; 1775 case WINS_RELEASED: 1776 DEBUG(0,("initiate_wins_processing: %s is in released state and\ 1777we are not the wins owner !\n", nmb_namestr(&namerec->name))); 1778 break; 1779 } 1780 } 1781 1782 } 1783 } 1784 1785 if(wins_server_subnet->namelist_changed) 1786 wins_write_database(True); 1787 1788 wins_server_subnet->namelist_changed = False; 1789} 1790 1791/******************************************************************* 1792 Write out the current WINS database. 1793******************************************************************/ 1794 1795void wins_write_database(BOOL background) 1796{ 1797 struct name_record *namerec; 1798 pstring fname, fnamenew; 1799 1800 XFILE *fp; 1801 1802 if(!lp_we_are_a_wins_server()) 1803 return; 1804 1805 /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */ 1806 if (background) { 1807 CatchChild(); 1808 if (sys_fork()) { 1809 return; 1810 } 1811 } 1812 1813 slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST); 1814 all_string_sub(fname,"//", "/", 0); 1815 slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid()); 1816 1817 if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) { 1818 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno))); 1819 if (background) { 1820 _exit(0); 1821 } 1822 return; 1823 } 1824 1825 DEBUG(4,("wins_write_database: Dump of WINS name list.\n")); 1826 1827 x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0); 1828 1829 for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) { 1830 int i; 1831 struct tm *tm; 1832 1833 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) )); 1834 1835 if( namerec->data.death_time != PERMANENT_TTL ) { 1836 char *ts, *nl; 1837 1838 tm = LocalTime(&namerec->data.death_time); 1839 ts = asctime(tm); 1840 nl = strrchr( ts, '\n' ); 1841 if( NULL != nl ) 1842 *nl = '\0'; 1843 DEBUGADD(4,("TTL = %s ", ts )); 1844 } else { 1845 DEBUGADD(4,("TTL = PERMANENT ")); 1846 } 1847 1848 for (i = 0; i < namerec->data.num_ips; i++) 1849 DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) )); 1850 DEBUGADD(4,("%2x\n", namerec->data.nb_flags )); 1851 1852 if( namerec->data.source == REGISTER_NAME ) { 1853 unstring name; 1854 pull_ascii_nstring(name, sizeof(name), namerec->name.name); 1855 x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */ 1856 (int)namerec->data.death_time); 1857 1858 for (i = 0; i < namerec->data.num_ips; i++) 1859 x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) ); 1860 x_fprintf( fp, "%2xR\n", namerec->data.nb_flags ); 1861 } 1862 } 1863 1864 x_fclose(fp); 1865 chmod(fnamenew,0644); 1866 unlink(fname); 1867 rename(fnamenew,fname); 1868 if (background) { 1869 _exit(0); 1870 } 1871} 1872 1873/**************************************************************************** 1874 Process a internal Samba message receiving a wins record. 1875***************************************************************************/ 1876 1877void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len) 1878{ 1879 WINS_RECORD *record; 1880 struct name_record *namerec = NULL; 1881 struct name_record *new_namerec = NULL; 1882 struct nmb_name question; 1883 BOOL overwrite=False; 1884 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); 1885 int i; 1886 1887 if (buf==NULL) 1888 return; 1889 1890 /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */ 1891 record=(WINS_RECORD *)buf; 1892 1893 make_nmb_name(&question, record->name, record->type); 1894 1895 namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME); 1896 1897 /* record doesn't exist, add it */ 1898 if (namerec == NULL) { 1899 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n", 1900 record->name, record->type, inet_ntoa(record->wins_ip))); 1901 1902 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags, 1903 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip); 1904 if (new_namerec!=NULL) { 1905 update_wins_owner(new_namerec, record->wins_ip); 1906 update_wins_flag(new_namerec, record->wins_flags); 1907 new_namerec->data.id=record->id; 1908 1909 wins_server_subnet->namelist_changed = True; 1910 } 1911 } 1912 1913 /* check if we have a conflict */ 1914 if (namerec != NULL) { 1915 /* both records are UNIQUE */ 1916 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) { 1917 1918 /* the database record is a replica */ 1919 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) { 1920 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) { 1921 if (ip_equal(namerec->data.wins_ip, record->wins_ip)) 1922 overwrite=True; 1923 } else 1924 overwrite=True; 1925 } else { 1926 /* we are the wins owner of the database record */ 1927 /* the 2 records have the same IP address */ 1928 if (ip_equal(namerec->data.ip[0], record->ip[0])) { 1929 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) 1930 get_global_id_and_update(&namerec->data.id, True); 1931 else 1932 overwrite=True; 1933 1934 } else { 1935 /* the 2 records have different IP address */ 1936 if (namerec->data.wins_flags&WINS_ACTIVE) { 1937 if (record->wins_flags&WINS_TOMBSTONED) 1938 get_global_id_and_update(&namerec->data.id, True); 1939 if (record->wins_flags&WINS_ACTIVE) 1940 /* send conflict challenge to the replica node */ 1941 ; 1942 } else 1943 overwrite=True; 1944 } 1945 1946 } 1947 } 1948 1949 /* the replica is a standard group */ 1950 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) { 1951 /* if the database record is unique and active force a name release */ 1952 if (namerec->data.wins_flags&WINS_UNIQUE) 1953 /* send a release name to the unique node */ 1954 ; 1955 overwrite=True; 1956 1957 } 1958 1959 /* the replica is a special group */ 1960 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) { 1961 if (namerec->data.wins_flags&WINS_ACTIVE) { 1962 for (i=0; i<record->num_ips; i++) 1963 if(!find_ip_in_name_record(namerec, record->ip[i])) 1964 add_ip_to_name_record(namerec, record->ip[i]); 1965 } else { 1966 overwrite=True; 1967 } 1968 } 1969 1970 /* the replica is a multihomed host */ 1971 1972 /* I'm giving up on multi homed. Too much complex to understand */ 1973 1974 if (record->wins_flags&WINS_MHOMED) { 1975 if (! (namerec->data.wins_flags&WINS_ACTIVE)) { 1976 if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP)) 1977 overwrite=True; 1978 } 1979 else { 1980 if (ip_equal(record->wins_ip, namerec->data.wins_ip)) 1981 overwrite=True; 1982 1983 if (ip_equal(namerec->data.wins_ip, our_fake_ip)) 1984 if (namerec->data.wins_flags&WINS_UNIQUE) 1985 get_global_id_and_update(&namerec->data.id, True); 1986 1987 } 1988 1989 if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE) 1990 if (namerec->data.wins_flags&WINS_UNIQUE || 1991 namerec->data.wins_flags&WINS_MHOMED) 1992 if (ip_equal(record->wins_ip, namerec->data.wins_ip)) 1993 overwrite=True; 1994 1995 } 1996 1997 if (overwrite == False) 1998 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n", 1999 record->name, record->type, inet_ntoa(record->wins_ip))); 2000 else { 2001 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n", 2002 record->name, record->type, inet_ntoa(record->wins_ip))); 2003 2004 /* remove the old record and add a new one */ 2005 remove_name_from_namelist( wins_server_subnet, namerec ); 2006 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags, 2007 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip); 2008 if (new_namerec!=NULL) { 2009 update_wins_owner(new_namerec, record->wins_ip); 2010 update_wins_flag(new_namerec, record->wins_flags); 2011 new_namerec->data.id=record->id; 2012 2013 wins_server_subnet->namelist_changed = True; 2014 } 2015 2016 wins_server_subnet->namelist_changed = True; 2017 } 2018 2019 } 2020} 2021