root/source3/nmbd/nmbd_winsserver.c

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

DEFINITIONS

This source file includes following definitions.
  1. wins_delete_all_tmp_in_memory_records
  2. wins_record_to_name_record
  3. name_record_to_wins_record
  4. name_to_key
  5. find_name_on_wins_subnet
  6. store_or_replace_wins_namerec
  7. wins_store_changed_namerec
  8. add_name_to_wins_subnet
  9. remove_name_from_wins_namelist
  10. traverse_fn
  11. dump_wins_subnet_namelist
  12. update_wins_owner
  13. update_wins_flag
  14. get_global_id_and_update
  15. wins_hook
  16. packet_is_for_wins_server
  17. get_ttl_from_packet
  18. initialise_wins
  19. send_wins_wack_response
  20. send_wins_name_registration_response
  21. wins_process_name_refresh_request
  22. wins_register_query_success
  23. wins_register_query_fail
  24. wins_process_name_registration_request
  25. wins_multihomed_register_query_success
  26. wins_multihomed_register_query_fail
  27. wins_process_multihomed_name_registration_request
  28. fetch_1b_traverse_fn
  29. fetch_all_active_wins_1b_names
  30. process_wins_dmb_query_request
  31. send_wins_name_query_response
  32. wins_process_name_query_request
  33. send_wins_name_release_response
  34. wins_process_name_release_request
  35. wins_processing_traverse_fn
  36. initiate_wins_processing
  37. wins_write_name_record
  38. wins_writedb_traverse_fn
  39. wins_write_database
  40. nmbd_wins_new_entry

   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 
  34 TDB_CONTEXT *wins_tdb;
  35 
  36 /****************************************************************************
  37  Delete all the temporary name records on the in-memory linked list.
  38 *****************************************************************************/
  39 
  40 static void wins_delete_all_tmp_in_memory_records(void)
     /* [<][>][^][v][top][bottom][index][help] */
  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 
  58 static struct name_record *wins_record_to_name_record(TDB_DATA key, TDB_DATA data)
     /* [<][>][^][v][top][bottom][index][help] */
  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 
 144 static TDB_DATA name_record_to_wins_record(const struct name_record *namerec)
     /* [<][>][^][v][top][bottom][index][help] */
 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 
 189 static TDB_DATA name_to_key(const struct nmb_name *nmbname)
     /* [<][>][^][v][top][bottom][index][help] */
 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 
 210 struct name_record *find_name_on_wins_subnet(const struct nmb_name *nmbname, bool self_only)
     /* [<][>][^][v][top][bottom][index][help] */
 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 
 265 static bool store_or_replace_wins_namerec(const struct name_record *namerec, int tdb_flag)
     /* [<][>][^][v][top][bottom][index][help] */
 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 
 291 bool wins_store_changed_namerec(const struct name_record *namerec)
     /* [<][>][^][v][top][bottom][index][help] */
 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 
 300 bool add_name_to_wins_subnet(const struct name_record *namerec)
     /* [<][>][^][v][top][bottom][index][help] */
 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 
 310 bool remove_name_from_wins_namelist(struct name_record *namerec)
     /* [<][>][^][v][top][bottom][index][help] */
 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 
 333 static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
     /* [<][>][^][v][top][bottom][index][help] */
 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 
 354 void dump_wins_subnet_namelist(XFILE *fp)
     /* [<][>][^][v][top][bottom][index][help] */
 355 {
 356         tdb_traverse(wins_tdb, traverse_fn, (void *)fp);
 357 }
 358 
 359 /****************************************************************************
 360  Change the wins owner address in the record.
 361 *****************************************************************************/
 362 
 363 static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip)
     /* [<][>][^][v][top][bottom][index][help] */
 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 
 372 static void update_wins_flag(struct name_record *namerec, int flags)
     /* [<][>][^][v][top][bottom][index][help] */
 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 
 415 static void get_global_id_and_update(uint64_t *current_id, bool update)
     /* [<][>][^][v][top][bottom][index][help] */
 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 
 438 static void wins_hook(const char *operation, struct name_record *namerec, int ttl)
     /* [<][>][^][v][top][bottom][index][help] */
 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 /****************************************************************************
 492 Determine if this packet should be allocated to the WINS server.
 493 *****************************************************************************/
 494 
 495 bool packet_is_for_wins_server(struct packet_struct *packet)
     /* [<][>][^][v][top][bottom][index][help] */
 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 /****************************************************************************
 553 Utility function to decide what ttl to give a register/refresh request.
 554 *****************************************************************************/
 555 
 556 static int get_ttl_from_packet(struct nmb_packet *nmb)
     /* [<][>][^][v][top][bottom][index][help] */
 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 /****************************************************************************
 572 Load or create the WINS database.
 573 *****************************************************************************/
 574 
 575 bool initialise_wins(void)
     /* [<][>][^][v][top][bottom][index][help] */
 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 /****************************************************************************
 762 Send a WINS WACK (Wait ACKnowledgement) response.
 763 **************************************************************************/
 764 
 765 static void send_wins_wack_response(int ttl, struct packet_struct *p)
     /* [<][>][^][v][top][bottom][index][help] */
 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 /****************************************************************************
 802 Send a WINS name registration response.
 803 **************************************************************************/
 804 
 805 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
     /* [<][>][^][v][top][bottom][index][help] */
 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 
 825 void wins_process_name_refresh_request( struct subnet_record *subrec,
     /* [<][>][^][v][top][bottom][index][help] */
 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 
1004 static void wins_register_query_success(struct subnet_record *subrec,
     /* [<][>][^][v][top][bottom][index][help] */
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 \
1015 name %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 
1033 static void wins_register_query_fail(struct subnet_record *subrec,
     /* [<][>][^][v][top][bottom][index][help] */
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 
1131 void wins_process_name_registration_request(struct subnet_record *subrec,
     /* [<][>][^][v][top][bottom][index][help] */
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 \
1156 received 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 \
1162 IP %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 \
1176 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_name_registration_request: Name (%s) in WINS was \
1189 a 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 \
1201 to 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 \
1229 to 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 \
1281 already 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 \
1303 is 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 
1414 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
     /* [<][>][^][v][top][bottom][index][help] */
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 \
1448 a 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 
1480 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
     /* [<][>][^][v][top][bottom][index][help] */
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 \
1491 query 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 
1504 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
     /* [<][>][^][v][top][bottom][index][help] */
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 \
1529 received 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 \
1540 received 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 \
1546 IP %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 \
1554 to 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 \
1596 to 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 \
1608 already 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 \
1627 is 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 
1748 static int fetch_1b_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
     /* [<][>][^][v][top][bottom][index][help] */
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 
1770 void fetch_all_active_wins_1b_names(void)
     /* [<][>][^][v][top][bottom][index][help] */
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    
1779 static void process_wins_dmb_query_request(struct subnet_record *subrec,  
     /* [<][>][^][v][top][bottom][index][help] */
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 /****************************************************************************
1854 Send a WINS name query response.
1855 **************************************************************************/
1856 
1857 void send_wins_name_query_response(int rcode, struct packet_struct *p, 
     /* [<][>][^][v][top][bottom][index][help] */
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 
1909 void wins_process_name_query_request(struct subnet_record *subrec, 
     /* [<][>][^][v][top][bottom][index][help] */
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 /****************************************************************************
1996 Send a WINS name release response.
1997 **************************************************************************/
1998 
1999 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
     /* [<][>][^][v][top][bottom][index][help] */
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 
2019 void wins_process_name_release_request(struct subnet_record *subrec,
     /* [<][>][^][v][top][bottom][index][help] */
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 \
2040 received 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 \
2046 IP %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 \
2054 to 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 \
2088 release 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 \
2101 release 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 
2137 static int wins_processing_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
     /* [<][>][^][v][top][bottom][index][help] */
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\
2212 we 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 
2234 void initiate_wins_processing(time_t t)
     /* [<][>][^][v][top][bottom][index][help] */
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 
2263 void wins_write_name_record(struct name_record *namerec, XFILE *fp)
     /* [<][>][^][v][top][bottom][index][help] */
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 
2311 static int wins_writedb_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
     /* [<][>][^][v][top][bottom][index][help] */
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 
2333 void wins_write_database(time_t t, bool background)
     /* [<][>][^][v][top][bottom][index][help] */
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 
2411 void nmbd_wins_new_entry(struct messaging_context *msg,
     /* [<][>][^][v][top][bottom][index][help] */
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

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