00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "includes.h"
00025
00026 #define WINS_LIST "wins.dat"
00027 #define WINS_VERSION 1
00028 #define WINSDB_VERSION 1
00029
00030
00031
00032
00033
00034
00035 TDB_CONTEXT *wins_tdb;
00036
00037
00038
00039
00040
00041 static void wins_delete_all_tmp_in_memory_records(void)
00042 {
00043 struct name_record *nr = NULL;
00044 struct name_record *nrnext = NULL;
00045
00046
00047 for( nr = wins_server_subnet->namelist; nr; nr = nrnext) {
00048 nrnext = nr->next;
00049 DLIST_REMOVE(wins_server_subnet->namelist, nr);
00050 SAFE_FREE(nr->data.ip);
00051 SAFE_FREE(nr);
00052 }
00053 }
00054
00055
00056
00057
00058
00059 static struct name_record *wins_record_to_name_record(TDB_DATA key, TDB_DATA data)
00060 {
00061 struct name_record *namerec = NULL;
00062 uint16 nb_flags;
00063 unsigned char nr_src;
00064 uint32 death_time, refresh_time;
00065 uint32 id_low, id_high;
00066 uint32 saddr;
00067 uint32 wins_flags;
00068 uint32 num_ips;
00069 size_t len;
00070 int i;
00071
00072 if (data.dptr == NULL || data.dsize == 0) {
00073 return NULL;
00074 }
00075
00076
00077 if (data.dsize < 2 + 1 + (7*4) + 4) {
00078 return NULL;
00079 }
00080
00081 len = tdb_unpack(data.dptr, data.dsize,
00082 "wbddddddd",
00083 &nb_flags,
00084 &nr_src,
00085 &death_time,
00086 &refresh_time,
00087 &id_low,
00088 &id_high,
00089 &saddr,
00090 &wins_flags,
00091 &num_ips );
00092
00093 namerec = SMB_MALLOC_P(struct name_record);
00094 if (!namerec) {
00095 return NULL;
00096 }
00097 ZERO_STRUCTP(namerec);
00098
00099 namerec->data.ip = SMB_MALLOC_ARRAY(struct in_addr, num_ips);
00100 if (!namerec->data.ip) {
00101 SAFE_FREE(namerec);
00102 return NULL;
00103 }
00104
00105 namerec->subnet = wins_server_subnet;
00106 push_ascii_nstring(namerec->name.name, key.dptr);
00107 namerec->name.name_type = key.dptr[sizeof(unstring)];
00108
00109 push_ascii(namerec->name.scope, global_scope(), 64, STR_TERMINATE);
00110
00111
00112
00113
00114
00115 for( i = strlen( namerec->name.name ); i < sizeof( namerec->name.name ); i++ ) {
00116 namerec->name.name[i] = '\0';
00117 }
00118 for( i = strlen( namerec->name.scope ); i < sizeof( namerec->name.scope ); i++ ) {
00119 namerec->name.scope[i] = '\0';
00120 }
00121
00122 namerec->data.nb_flags = nb_flags;
00123 namerec->data.source = (enum name_source)nr_src;
00124 namerec->data.death_time = (time_t)death_time;
00125 namerec->data.refresh_time = (time_t)refresh_time;
00126 namerec->data.id = id_low;
00127 #if defined(HAVE_LONGLONG)
00128 namerec->data.id |= ((SMB_BIG_UINT)id_high << 32);
00129 #endif
00130 namerec->data.wins_ip.s_addr = saddr;
00131 namerec->data.wins_flags = wins_flags,
00132 namerec->data.num_ips = num_ips;
00133
00134 for (i = 0; i < num_ips; i++) {
00135 namerec->data.ip[i].s_addr = IVAL(data.dptr, len + (i*4));
00136 }
00137
00138 return namerec;
00139 }
00140
00141
00142
00143
00144
00145 static TDB_DATA name_record_to_wins_record(const struct name_record *namerec)
00146 {
00147 TDB_DATA data;
00148 size_t len = 0;
00149 int i;
00150 uint32 id_low = (namerec->data.id & 0xFFFFFFFF);
00151 #if defined(HAVE_LONGLONG)
00152 uint32 id_high = (namerec->data.id >> 32) & 0xFFFFFFFF;
00153 #else
00154 uint32 id_high = 0;
00155 #endif
00156
00157 ZERO_STRUCT(data);
00158
00159 len = (2 + 1 + (7*4));
00160 len += (namerec->data.num_ips * 4);
00161
00162 data.dptr = (char *)SMB_MALLOC(len);
00163 if (!data.dptr) {
00164 return data;
00165 }
00166 data.dsize = len;
00167
00168 len = tdb_pack(data.dptr, data.dsize, "wbddddddd",
00169 namerec->data.nb_flags,
00170 (unsigned char)namerec->data.source,
00171 (uint32)namerec->data.death_time,
00172 (uint32)namerec->data.refresh_time,
00173 id_low,
00174 id_high,
00175 (uint32)namerec->data.wins_ip.s_addr,
00176 (uint32)namerec->data.wins_flags,
00177 (uint32)namerec->data.num_ips );
00178
00179 for (i = 0; i < namerec->data.num_ips; i++) {
00180 SIVAL(data.dptr, len + (i*4), namerec->data.ip[i].s_addr);
00181 }
00182
00183 return data;
00184 }
00185
00186
00187
00188
00189
00190 static TDB_DATA name_to_key(const struct nmb_name *nmbname)
00191 {
00192 static char keydata[sizeof(unstring) + 1];
00193 TDB_DATA key;
00194
00195 memset(keydata, '\0', sizeof(keydata));
00196
00197 pull_ascii_nstring(keydata, sizeof(unstring), nmbname->name);
00198 strupper_m(keydata);
00199 keydata[sizeof(unstring)] = nmbname->name_type;
00200 key.dptr = keydata;
00201 key.dsize = sizeof(keydata);
00202
00203 return key;
00204 }
00205
00206
00207
00208
00209
00210
00211 struct name_record *find_name_on_wins_subnet(const struct nmb_name *nmbname, BOOL self_only)
00212 {
00213 TDB_DATA data, key;
00214 struct name_record *nr = NULL;
00215 struct name_record *namerec = NULL;
00216
00217 if (!wins_tdb) {
00218 return NULL;
00219 }
00220
00221 key = name_to_key(nmbname);
00222 data = tdb_fetch(wins_tdb, key);
00223
00224 if (data.dsize == 0) {
00225 return NULL;
00226 }
00227
00228 namerec = wins_record_to_name_record(key, data);
00229
00230
00231
00232 SAFE_FREE( data.dptr );
00233
00234 if (!namerec) {
00235 return NULL;
00236 }
00237
00238
00239 if( self_only && (namerec->data.source != SELF_NAME) && (namerec->data.source != PERMANENT_NAME) ) {
00240 DEBUG( 9, ( "find_name_on_wins_subnet: self name %s NOT FOUND\n", nmb_namestr(nmbname) ) );
00241 SAFE_FREE(namerec->data.ip);
00242 SAFE_FREE(namerec);
00243 return NULL;
00244 }
00245
00246
00247
00248 for( nr = wins_server_subnet->namelist; nr; nr = nr->next) {
00249 if (memcmp(nmbname->name, nr->name.name, 16) == 0) {
00250
00251 DLIST_REMOVE(wins_server_subnet->namelist, nr);
00252 SAFE_FREE(nr->data.ip);
00253 SAFE_FREE(nr);
00254 break;
00255 }
00256 }
00257
00258 DLIST_ADD(wins_server_subnet->namelist, namerec);
00259 return namerec;
00260 }
00261
00262
00263
00264
00265
00266 static BOOL store_or_replace_wins_namerec(const struct name_record *namerec, int tdb_flag)
00267 {
00268 TDB_DATA key, data;
00269 int ret;
00270
00271 if (!wins_tdb) {
00272 return False;
00273 }
00274
00275 key = name_to_key(&namerec->name);
00276 data = name_record_to_wins_record(namerec);
00277
00278 if (data.dptr == NULL) {
00279 return False;
00280 }
00281
00282 ret = tdb_store(wins_tdb, key, data, tdb_flag);
00283
00284 SAFE_FREE(data.dptr);
00285 return (ret == 0) ? True : False;
00286 }
00287
00288
00289
00290
00291
00292 BOOL wins_store_changed_namerec(const struct name_record *namerec)
00293 {
00294 return store_or_replace_wins_namerec(namerec, TDB_REPLACE);
00295 }
00296
00297
00298
00299
00300
00301 BOOL add_name_to_wins_subnet(const struct name_record *namerec)
00302 {
00303 return store_or_replace_wins_namerec(namerec, TDB_INSERT);
00304 }
00305
00306
00307
00308
00309
00310
00311 BOOL remove_name_from_wins_namelist(struct name_record *namerec)
00312 {
00313 TDB_DATA key;
00314 int ret;
00315
00316 if (!wins_tdb) {
00317 return False;
00318 }
00319
00320 key = name_to_key(&namerec->name);
00321 ret = tdb_delete(wins_tdb, key);
00322
00323 DLIST_REMOVE(wins_server_subnet->namelist, namerec);
00324
00325
00326
00327 return (ret == 0) ? True : False;
00328 }
00329
00330
00331
00332
00333
00334 static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
00335 {
00336 struct name_record *namerec = NULL;
00337 XFILE *fp = (XFILE *)state;
00338
00339 if (kbuf.dsize != sizeof(unstring) + 1) {
00340 return 0;
00341 }
00342
00343 namerec = wins_record_to_name_record(kbuf, dbuf);
00344 if (!namerec) {
00345 return 0;
00346 }
00347
00348 dump_name_record(namerec, fp);
00349
00350 SAFE_FREE(namerec->data.ip);
00351 SAFE_FREE(namerec);
00352 return 0;
00353 }
00354
00355 void dump_wins_subnet_namelist(XFILE *fp)
00356 {
00357 tdb_traverse(wins_tdb, traverse_fn, (void *)fp);
00358 }
00359
00360
00361
00362
00363
00364 static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip)
00365 {
00366 namerec->data.wins_ip=wins_ip;
00367 }
00368
00369
00370
00371
00372
00373 static void update_wins_flag(struct name_record *namerec, int flags)
00374 {
00375 namerec->data.wins_flags=0x0;
00376
00377
00378 if (namerec->data.nb_flags & NB_GROUP) {
00379 if (namerec->name.name_type==0x1C) {
00380 namerec->data.wins_flags|=WINS_SGROUP;
00381 } else {
00382 if (namerec->data.num_ips>1) {
00383 namerec->data.wins_flags|=WINS_SGROUP;
00384 } else {
00385 namerec->data.wins_flags|=WINS_NGROUP;
00386 }
00387 }
00388 } else {
00389
00390 if (namerec->data.num_ips>1) {
00391 namerec->data.wins_flags|=WINS_MHOMED;
00392 } else {
00393 namerec->data.wins_flags|=WINS_UNIQUE;
00394 }
00395 }
00396
00397
00398 namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK;
00399
00400
00401 if (namerec->data.death_time == PERMANENT_TTL) {
00402 namerec->data.wins_flags|=WINS_STATIC;
00403 }
00404
00405
00406 namerec->data.wins_flags|=flags;
00407
00408 DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n",
00409 namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags));
00410 }
00411
00412
00413
00414
00415
00416 static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update)
00417 {
00418
00419
00420
00421
00422
00423 static SMB_BIG_UINT general_id = 1;
00424
00425 DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id));
00426
00427 *current_id = general_id;
00428
00429 if (update) {
00430 general_id++;
00431 }
00432 }
00433
00434
00435
00436
00437
00438
00439 static void wins_hook(const char *operation, struct name_record *namerec, int ttl)
00440 {
00441 pstring command;
00442 char *cmd = lp_wins_hook();
00443 char *p, *namestr;
00444 int i;
00445
00446 wins_store_changed_namerec(namerec);
00447
00448 if (!cmd || !*cmd) {
00449 return;
00450 }
00451
00452 for (p=namerec->name.name; *p; p++) {
00453 if (!(isalnum((int)*p) || strchr_m("._-",*p))) {
00454 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
00455 return;
00456 }
00457 }
00458
00459
00460
00461 namestr = nmb_namestr(&namerec->name);
00462 if ((p = strchr(namestr, '<'))) {
00463 *p = 0;
00464 }
00465
00466 p = command;
00467 p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d",
00468 cmd,
00469 operation,
00470 namestr,
00471 namerec->name.name_type,
00472 ttl);
00473
00474 for (i=0;i<namerec->data.num_ips;i++) {
00475 p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.ip[i]));
00476 }
00477
00478 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
00479 smbrun(command, NULL);
00480 }
00481
00482
00483
00484
00485
00486 BOOL packet_is_for_wins_server(struct packet_struct *packet)
00487 {
00488 struct nmb_packet *nmb = &packet->packet.nmb;
00489
00490
00491 if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True)) {
00492 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
00493 return False;
00494 }
00495
00496
00497 if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY) {
00498 return False;
00499 }
00500
00501 switch(nmb->header.opcode) {
00502
00503
00504
00505 case NMB_WACK_OPCODE:
00506 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
00507 return False;
00508
00509
00510
00511
00512 case NMB_NAME_REG_OPCODE:
00513 case NMB_NAME_MULTIHOMED_REG_OPCODE:
00514 case NMB_NAME_REFRESH_OPCODE_8:
00515 case NMB_NAME_REFRESH_OPCODE_9:
00516 if(nmb->header.response) {
00517 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
00518 return False;
00519 }
00520 break;
00521
00522 case NMB_NAME_RELEASE_OPCODE:
00523 if(nmb->header.response) {
00524 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
00525 return False;
00526 }
00527 break;
00528
00529
00530
00531
00532 case NMB_NAME_QUERY_OPCODE:
00533 if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired) {
00534 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
00535 return False;
00536 }
00537 break;
00538 }
00539
00540 return True;
00541 }
00542
00543
00544
00545
00546
00547 static int get_ttl_from_packet(struct nmb_packet *nmb)
00548 {
00549 int ttl = nmb->additional->ttl;
00550
00551 if (ttl < lp_min_wins_ttl()) {
00552 ttl = lp_min_wins_ttl();
00553 }
00554
00555 if (ttl > lp_max_wins_ttl()) {
00556 ttl = lp_max_wins_ttl();
00557 }
00558
00559 return ttl;
00560 }
00561
00562
00563
00564
00565
00566 BOOL initialise_wins(void)
00567 {
00568 time_t time_now = time(NULL);
00569 XFILE *fp;
00570 pstring line;
00571
00572 if(!lp_we_are_a_wins_server()) {
00573 return True;
00574 }
00575
00576
00577 wins_tdb = tdb_open_log(lock_path("wins.tdb"), 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST, O_CREAT|O_RDWR, 0600);
00578 if (!wins_tdb) {
00579 DEBUG(0,("initialise_wins: failed to open wins.tdb. Error was %s\n",
00580 strerror(errno) ));
00581 return False;
00582 }
00583
00584 tdb_store_int32(wins_tdb, "WINSDB_VERSION", WINSDB_VERSION);
00585
00586 add_samba_names_to_subnet(wins_server_subnet);
00587
00588 if((fp = x_fopen(lock_path(WINS_LIST),O_RDONLY,0)) == NULL) {
00589 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
00590 WINS_LIST, strerror(errno) ));
00591 return True;
00592 }
00593
00594 while (!x_feof(fp)) {
00595 pstring name_str, ip_str, ttl_str, nb_flags_str;
00596 unsigned int num_ips;
00597 pstring name;
00598 struct in_addr *ip_list;
00599 int type = 0;
00600 int nb_flags;
00601 int ttl;
00602 const char *ptr;
00603 char *p;
00604 BOOL got_token;
00605 BOOL was_ip;
00606 int i;
00607 unsigned int hash;
00608 int version;
00609
00610
00611
00612 if (!fgets_slash(line,sizeof(pstring),fp))
00613 continue;
00614
00615 if (*line == '#')
00616 continue;
00617
00618 if (strncmp(line,"VERSION ", 8) == 0) {
00619 if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||
00620 version != WINS_VERSION) {
00621 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line));
00622 x_fclose(fp);
00623 return True;
00624 }
00625 continue;
00626 }
00627
00628 ptr = line;
00629
00630
00631
00632
00633
00634
00635
00636
00637 if (!next_token(&ptr,name_str,NULL,sizeof(name_str))) {
00638 DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));
00639 continue;
00640 }
00641
00642 if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str))) {
00643 DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));
00644 continue;
00645 }
00646
00647
00648
00649
00650 num_ips = 0;
00651 do {
00652 got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str));
00653 was_ip = False;
00654
00655 if(got_token && strchr(ip_str, '.')) {
00656 num_ips++;
00657 was_ip = True;
00658 }
00659 } while( got_token && was_ip);
00660
00661 if(num_ips == 0) {
00662 DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line ));
00663 continue;
00664 }
00665
00666 if(!got_token) {
00667 DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line ));
00668 continue;
00669 }
00670
00671
00672 if((ip_list = SMB_MALLOC_ARRAY( struct in_addr, num_ips)) == NULL) {
00673 DEBUG(0,("initialise_wins: Malloc fail !\n"));
00674 x_fclose(fp);
00675 return False;
00676 }
00677
00678
00679 ptr = line;
00680 next_token(&ptr,name_str,NULL,sizeof(name_str));
00681 next_token(&ptr,ttl_str,NULL,sizeof(ttl_str));
00682 for(i = 0; i < num_ips; i++) {
00683 next_token(&ptr, ip_str, NULL, sizeof(ip_str));
00684 ip_list[i] = *interpret_addr2(ip_str);
00685 }
00686 next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str));
00687
00688
00689
00690
00691
00692
00693 if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') {
00694 DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line));
00695 SAFE_FREE(ip_list);
00696 continue;
00697 }
00698
00699 if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') {
00700 nb_flags_str[strlen(nb_flags_str)-1] = '\0';
00701 }
00702
00703
00704 pstrcpy(name,name_str);
00705
00706 if((p = strchr(name,'#')) != NULL) {
00707 *p = 0;
00708 sscanf(p+1,"%x",&type);
00709 }
00710
00711
00712 sscanf(nb_flags_str,"%x",&nb_flags);
00713 sscanf(ttl_str,"%d",&ttl);
00714
00715
00716 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {
00717 if(ttl != PERMANENT_TTL) {
00718 ttl -= time_now;
00719 }
00720
00721 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
00722 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
00723
00724 (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
00725 ttl, REGISTER_NAME, num_ips, ip_list );
00726 } else {
00727 DEBUG(4, ("initialise_wins: not adding name (ttl problem) "
00728 "%s#%02x ttl = %d first IP %s flags = %2x\n",
00729 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
00730 }
00731
00732 SAFE_FREE(ip_list);
00733 }
00734
00735 x_fclose(fp);
00736 return True;
00737 }
00738
00739
00740
00741
00742
00743 static void send_wins_wack_response(int ttl, struct packet_struct *p)
00744 {
00745 struct nmb_packet *nmb = &p->packet.nmb;
00746 unsigned char rdata[2];
00747
00748 rdata[0] = rdata[1] = 0;
00749
00750
00751
00752
00753 rdata[0] = (nmb->header.opcode & 0xF) << 3;
00754 if (nmb->header.nm_flags.authoritative && nmb->header.response) {
00755 rdata[0] |= 0x4;
00756 }
00757 if (nmb->header.nm_flags.trunc) {
00758 rdata[0] |= 0x2;
00759 }
00760 if (nmb->header.nm_flags.recursion_desired) {
00761 rdata[0] |= 0x1;
00762 }
00763 if (nmb->header.nm_flags.recursion_available && nmb->header.response) {
00764 rdata[1] |= 0x80;
00765 }
00766 if (nmb->header.nm_flags.bcast) {
00767 rdata[1] |= 0x10;
00768 }
00769
00770 reply_netbios_packet(p,
00771 0,
00772 NMB_WAIT_ACK,
00773 NMB_WACK_OPCODE,
00774 ttl,
00775 (char *)rdata,
00776 2);
00777 }
00778
00779
00780
00781
00782
00783 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
00784 {
00785 struct nmb_packet *nmb = &p->packet.nmb;
00786 char rdata[6];
00787
00788 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
00789
00790 reply_netbios_packet(p,
00791 rcode,
00792 WINS_REG,
00793 NMB_NAME_REG_OPCODE,
00794 ttl,
00795 rdata,
00796 6);
00797 }
00798
00799
00800
00801
00802
00803 void wins_process_name_refresh_request( struct subnet_record *subrec,
00804 struct packet_struct *p )
00805 {
00806 struct nmb_packet *nmb = &p->packet.nmb;
00807 struct nmb_name *question = &nmb->question.question_name;
00808 BOOL bcast = nmb->header.nm_flags.bcast;
00809 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
00810 BOOL group = (nb_flags & NB_GROUP) ? True : False;
00811 struct name_record *namerec = NULL;
00812 int ttl = get_ttl_from_packet(nmb);
00813 struct in_addr from_ip;
00814 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
00815
00816 putip( (char *)&from_ip, &nmb->additional->rdata[2] );
00817
00818 if(bcast) {
00819
00820
00821
00822
00823
00824 if( DEBUGLVL( 0 ) ) {
00825 dbgtext( "wins_process_name_refresh_request: " );
00826 dbgtext( "Broadcast name refresh request received " );
00827 dbgtext( "for name %s ", nmb_namestr(question) );
00828 dbgtext( "from IP %s ", inet_ntoa(from_ip) );
00829 dbgtext( "on subnet %s. ", subrec->subnet_name );
00830 dbgtext( "Error - Broadcasts should not be sent " );
00831 dbgtext( "to a WINS server\n" );
00832 }
00833 return;
00834 }
00835
00836 if( DEBUGLVL( 3 ) ) {
00837 dbgtext( "wins_process_name_refresh_request: " );
00838 dbgtext( "Name refresh for name %s IP %s\n",
00839 nmb_namestr(question), inet_ntoa(from_ip) );
00840 }
00841
00842
00843
00844
00845
00846 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
00847
00848
00849
00850
00851
00852
00853 if(namerec == NULL) {
00854 if( DEBUGLVL( 3 ) ) {
00855 dbgtext( "wins_process_name_refresh_request: " );
00856 dbgtext( "Name refresh for name %s ",
00857 nmb_namestr( question ) );
00858 dbgtext( "and the name does not exist. Treating " );
00859 dbgtext( "as registration.\n" );
00860 }
00861 wins_process_name_registration_request(subrec,p);
00862 return;
00863 }
00864
00865
00866
00867
00868
00869 if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) {
00870 if( DEBUGLVL( 5 ) ) {
00871 dbgtext( "wins_process_name_refresh_request: " );
00872 dbgtext( "Name (%s) in WINS ", nmb_namestr(question) );
00873 dbgtext( "was not active - removing it.\n" );
00874 }
00875 remove_name_from_namelist( subrec, namerec );
00876 namerec = NULL;
00877 wins_process_name_registration_request( subrec, p );
00878 return;
00879 }
00880
00881
00882
00883
00884
00885
00886 if( (namerec != NULL) &&
00887 ( (group && !NAME_GROUP(namerec))
00888 || (!group && NAME_GROUP(namerec)) ) ) {
00889 if( DEBUGLVL( 3 ) ) {
00890 dbgtext( "wins_process_name_refresh_request: " );
00891 dbgtext( "Name %s ", nmb_namestr(question) );
00892 dbgtext( "group bit = %s does not match ",
00893 group ? "True" : "False" );
00894 dbgtext( "group bit in WINS for this name.\n" );
00895 }
00896 send_wins_name_registration_response(RFS_ERR, 0, p);
00897 return;
00898 }
00899
00900
00901
00902
00903
00904
00905
00906
00907 if( (!group || (group && (question->name_type == 0x1c)))
00908 && find_ip_in_name_record(namerec, from_ip) ) {
00909
00910
00911
00912 update_name_ttl(namerec, ttl);
00913
00914
00915
00916
00917
00918 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
00919 update_wins_owner(namerec, our_fake_ip);
00920 get_global_id_and_update(&namerec->data.id, True);
00921 }
00922
00923 send_wins_name_registration_response(0, ttl, p);
00924 wins_hook("refresh", namerec, ttl);
00925 return;
00926 } else if((group && (question->name_type == 0x1c))) {
00927
00928
00929
00930
00931 if( DEBUGLVL( 3 ) ) {
00932 dbgtext( "wins_process_name_refresh_request: " );
00933 dbgtext( "Name refresh for name %s, ",
00934 nmb_namestr(question) );
00935 dbgtext( "but IP address %s ", inet_ntoa(from_ip) );
00936 dbgtext( "is not yet associated with " );
00937 dbgtext( "that name. Treating as registration.\n" );
00938 }
00939 wins_process_name_registration_request(subrec,p);
00940 return;
00941 } else if(group) {
00942
00943
00944
00945
00946 update_name_ttl(namerec, ttl);
00947 wins_hook("refresh", namerec, ttl);
00948 send_wins_name_registration_response(0, ttl, p);
00949 return;
00950 } else if(!group && (question->name_type == 0x1d)) {
00951
00952
00953
00954 send_wins_name_registration_response(0, ttl, p);
00955 return;
00956 } else {
00957
00958
00959
00960 if( DEBUGLVL( 3 ) ) {
00961 dbgtext( "wins_process_name_refresh_request: " );
00962 dbgtext( "Name refresh for name %s with IP %s ",
00963 nmb_namestr(question), inet_ntoa(from_ip) );
00964 dbgtext( "and is IP is not known to the name.\n" );
00965 }
00966 send_wins_name_registration_response(RFS_ERR, 0, p);
00967 return;
00968 }
00969 }
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981 static void wins_register_query_success(struct subnet_record *subrec,
00982 struct userdata_struct *userdata,
00983 struct nmb_name *question_name,
00984 struct in_addr ip,
00985 struct res_rec *answers)
00986 {
00987 struct packet_struct *orig_reg_packet;
00988
00989 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
00990
00991 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
00992 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
00993
00994 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
00995
00996 orig_reg_packet->locked = False;
00997 free_packet(orig_reg_packet);
00998 }
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010 static void wins_register_query_fail(struct subnet_record *subrec,
01011 struct response_record *rrec,
01012 struct nmb_name *question_name,
01013 int rcode)
01014 {
01015 struct userdata_struct *userdata = rrec->userdata;
01016 struct packet_struct *orig_reg_packet;
01017 struct name_record *namerec = NULL;
01018
01019 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
01032
01033 if ((namerec != NULL) && (namerec->data.source == REGISTER_NAME) &&
01034 ip_equal(rrec->packet->ip, *namerec->data.ip)) {
01035 remove_name_from_namelist( subrec, namerec);
01036 namerec = NULL;
01037 }
01038
01039 if(namerec == NULL) {
01040 wins_process_name_registration_request(subrec, orig_reg_packet);
01041 } else {
01042 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between "
01043 "querying for name %s in order to replace it and this reply.\n",
01044 nmb_namestr(question_name) ));
01045 }
01046
01047 orig_reg_packet->locked = False;
01048 free_packet(orig_reg_packet);
01049 }
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108 void wins_process_name_registration_request(struct subnet_record *subrec,
01109 struct packet_struct *p)
01110 {
01111 unstring name;
01112 struct nmb_packet *nmb = &p->packet.nmb;
01113 struct nmb_name *question = &nmb->question.question_name;
01114 BOOL bcast = nmb->header.nm_flags.bcast;
01115 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
01116 int ttl = get_ttl_from_packet(nmb);
01117 struct name_record *namerec = NULL;
01118 struct in_addr from_ip;
01119 BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;
01120 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
01121
01122 putip((char *)&from_ip,&nmb->additional->rdata[2]);
01123
01124 if(bcast) {
01125
01126
01127
01128
01129
01130
01131 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
01132 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
01133 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
01134 return;
01135 }
01136
01137 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
01138 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
01139
01140
01141
01142
01143
01144 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
01145
01146
01147
01148
01149
01150 if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
01151 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
01152 not active - removing it.\n", nmb_namestr(question) ));
01153 remove_name_from_namelist( subrec, namerec );
01154 namerec = NULL;
01155 }
01156
01157
01158
01159
01160
01161
01162
01163 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
01164 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
01165 a dns lookup - removing it.\n", nmb_namestr(question) ));
01166 remove_name_from_namelist( subrec, namerec );
01167 namerec = NULL;
01168 }
01169
01170
01171
01172
01173
01174
01175 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) {
01176 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
01177 to register name %s. Name already exists in WINS with source type %d.\n",
01178 nmb_namestr(question), namerec->data.source ));
01179 send_wins_name_registration_response(RFS_ERR, 0, p);
01180 return;
01181 }
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195 if(registering_group_name && (question->name_type != 0x1c)) {
01196 from_ip = *interpret_addr2("255.255.255.255");
01197 }
01198
01199
01200
01201
01202
01203 if(!registering_group_name && (question->name_type == 0x1d)) {
01204 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
01205 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
01206 send_wins_name_registration_response(0, ttl, p);
01207 return;
01208 }
01209
01210
01211
01212
01213
01214 if((namerec != NULL) && NAME_GROUP(namerec)) {
01215 if(registering_group_name) {
01216
01217
01218
01219
01220
01221 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
01222 inet_ntoa(from_ip), nmb_namestr(question) ));
01223
01224
01225
01226
01227
01228 if(!find_ip_in_name_record(namerec, from_ip)) {
01229 add_ip_to_name_record(namerec, from_ip);
01230
01231 get_global_id_and_update(&namerec->data.id, True);
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241 update_wins_owner(namerec, our_fake_ip);
01242 }
01243 update_name_ttl(namerec, ttl);
01244 wins_hook("refresh", namerec, ttl);
01245 send_wins_name_registration_response(0, ttl, p);
01246 return;
01247 } else {
01248
01249
01250
01251
01252
01253
01254
01255
01256 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
01257 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
01258 send_wins_name_registration_response(RFS_ERR, 0, p);
01259 return;
01260 }
01261 }
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274 if ( namerec != NULL ) {
01275 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
01276 if( is_myname(name) ) {
01277 if(!ismyip(from_ip)) {
01278 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
01279 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
01280 send_wins_name_registration_response(RFS_ERR, 0, p);
01281 return;
01282 } else {
01283
01284
01285
01286 update_name_ttl(namerec, ttl);
01287 wins_hook("refresh", namerec, ttl);
01288 send_wins_name_registration_response(0, ttl, p);
01289 return;
01290 }
01291 }
01292 } else {
01293 name[0] = '\0';
01294 }
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305 if( !registering_group_name
01306 && (namerec != NULL)
01307 && (namerec->data.num_ips == 1)
01308 && ip_equal( namerec->data.ip[0], from_ip )
01309 && ip_equal(namerec->data.wins_ip, our_fake_ip) ) {
01310 update_name_ttl( namerec, ttl );
01311 wins_hook("refresh", namerec, ttl);
01312 send_wins_name_registration_response( 0, ttl, p );
01313 return;
01314 }
01315
01316
01317
01318
01319
01320
01321 if( namerec != NULL ) {
01322 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
01323 struct userdata_struct *userdata = (struct userdata_struct *)ud;
01324
01325
01326
01327
01328
01329 send_wins_wack_response(60, p);
01330
01331
01332
01333
01334
01335
01336
01337 p->locked = True;
01338
01339 userdata = (struct userdata_struct *)ud;
01340
01341 userdata->copy_fn = NULL;
01342 userdata->free_fn = NULL;
01343 userdata->userdata_len = sizeof(struct packet_struct *);
01344 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354 pull_ascii_nstring(name, sizeof(name), question->name);
01355 query_name_from_wins_server( *namerec->data.ip,
01356 name,
01357 question->name_type,
01358 wins_register_query_success,
01359 wins_register_query_fail,
01360 userdata );
01361 return;
01362 }
01363
01364
01365
01366
01367
01368 pull_ascii_nstring(name, sizeof(name), question->name);
01369 add_name_to_subnet( subrec, name, question->name_type,
01370 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
01371
01372 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
01373 get_global_id_and_update(&namerec->data.id, True);
01374 update_wins_owner(namerec, our_fake_ip);
01375 update_wins_flag(namerec, WINS_ACTIVE);
01376 wins_hook("add", namerec, ttl);
01377 }
01378
01379 send_wins_name_registration_response(0, ttl, p);
01380 }
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
01391 struct userdata_struct *userdata,
01392 struct nmb_name *question_name,
01393 struct in_addr ip,
01394 struct res_rec *answers)
01395 {
01396 struct packet_struct *orig_reg_packet;
01397 struct nmb_packet *nmb;
01398 struct name_record *namerec = NULL;
01399 struct in_addr from_ip;
01400 int ttl;
01401 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
01402
01403 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
01404
01405 nmb = &orig_reg_packet->packet.nmb;
01406
01407 putip((char *)&from_ip,&nmb->additional->rdata[2]);
01408 ttl = get_ttl_from_packet(nmb);
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
01420
01421 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) {
01422 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
01423 a subsequent IP address.\n", nmb_namestr(question_name) ));
01424 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
01425
01426 orig_reg_packet->locked = False;
01427 free_packet(orig_reg_packet);
01428
01429 return;
01430 }
01431
01432 if(!find_ip_in_name_record(namerec, from_ip)) {
01433 add_ip_to_name_record(namerec, from_ip);
01434 }
01435
01436 get_global_id_and_update(&namerec->data.id, True);
01437 update_wins_owner(namerec, our_fake_ip);
01438 update_wins_flag(namerec, WINS_ACTIVE);
01439 update_name_ttl(namerec, ttl);
01440 wins_hook("add", namerec, ttl);
01441 send_wins_name_registration_response(0, ttl, orig_reg_packet);
01442
01443 orig_reg_packet->locked = False;
01444 free_packet(orig_reg_packet);
01445 }
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
01456 struct response_record *rrec,
01457 struct nmb_name *question_name,
01458 int rcode)
01459 {
01460 struct userdata_struct *userdata = rrec->userdata;
01461 struct packet_struct *orig_reg_packet;
01462
01463 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
01464
01465 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
01466 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
01467 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
01468
01469 orig_reg_packet->locked = False;
01470 free_packet(orig_reg_packet);
01471 return;
01472 }
01473
01474
01475
01476
01477
01478
01479 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
01480 struct packet_struct *p)
01481 {
01482 struct nmb_packet *nmb = &p->packet.nmb;
01483 struct nmb_name *question = &nmb->question.question_name;
01484 BOOL bcast = nmb->header.nm_flags.bcast;
01485 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
01486 int ttl = get_ttl_from_packet(nmb);
01487 struct name_record *namerec = NULL;
01488 struct in_addr from_ip;
01489 BOOL group = (nb_flags & NB_GROUP) ? True : False;
01490 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
01491 unstring qname;
01492
01493 putip((char *)&from_ip,&nmb->additional->rdata[2]);
01494
01495 if(bcast) {
01496
01497
01498
01499
01500
01501
01502 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
01503 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
01504 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
01505 return;
01506 }
01507
01508
01509
01510
01511
01512 if(group) {
01513 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
01514 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
01515 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
01516 return;
01517 }
01518
01519 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
01520 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
01521
01522
01523
01524
01525
01526 if(question->name_type == 0x1d) {
01527 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
01528 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
01529 send_wins_name_registration_response(0, ttl, p);
01530 return;
01531 }
01532
01533
01534
01535
01536
01537 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
01538
01539
01540
01541
01542
01543
01544 if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
01545 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question)));
01546 remove_name_from_namelist(subrec, namerec);
01547 namerec = NULL;
01548 }
01549
01550
01551
01552
01553
01554
01555
01556 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
01557 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
01558 - removing it.\n", nmb_namestr(question) ));
01559 remove_name_from_namelist( subrec, namerec);
01560 namerec = NULL;
01561 }
01562
01563
01564
01565
01566
01567
01568 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) {
01569 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
01570 to register name %s. Name already exists in WINS with source type %d.\n",
01571 nmb_namestr(question), namerec->data.source ));
01572 send_wins_name_registration_response(RFS_ERR, 0, p);
01573 return;
01574 }
01575
01576
01577
01578
01579
01580 if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) {
01581 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
01582 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
01583 send_wins_name_registration_response(RFS_ERR, 0, p);
01584 return;
01585 }
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598 if((namerec != NULL) && (is_myname(namerec->name.name)) ) {
01599 if(!ismyip(from_ip)) {
01600 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
01601 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
01602 send_wins_name_registration_response(RFS_ERR, 0, p);
01603 return;
01604 } else {
01605
01606
01607
01608
01609 update_name_ttl(namerec, ttl);
01610
01611 if(!find_ip_in_name_record(namerec, from_ip)) {
01612 get_global_id_and_update(&namerec->data.id, True);
01613 update_wins_owner(namerec, our_fake_ip);
01614 update_wins_flag(namerec, WINS_ACTIVE);
01615
01616 add_ip_to_name_record(namerec, from_ip);
01617 }
01618
01619 wins_hook("refresh", namerec, ttl);
01620 send_wins_name_registration_response(0, ttl, p);
01621 return;
01622 }
01623 }
01624
01625
01626
01627
01628
01629
01630 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) {
01631 update_name_ttl(namerec, ttl);
01632
01633
01634
01635
01636
01637 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
01638 get_global_id_and_update(&namerec->data.id, True);
01639 update_wins_owner(namerec, our_fake_ip);
01640 update_wins_flag(namerec, WINS_ACTIVE);
01641 }
01642
01643 wins_hook("refresh", namerec, ttl);
01644 send_wins_name_registration_response(0, ttl, p);
01645 return;
01646 }
01647
01648
01649
01650
01651
01652
01653 if(namerec != NULL) {
01654 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
01655 struct userdata_struct *userdata = (struct userdata_struct *)ud;
01656
01657
01658
01659
01660
01661 send_wins_wack_response(60, p);
01662
01663
01664
01665
01666
01667
01668
01669 p->locked = True;
01670
01671 userdata = (struct userdata_struct *)ud;
01672
01673 userdata->copy_fn = NULL;
01674 userdata->free_fn = NULL;
01675 userdata->userdata_len = sizeof(struct packet_struct *);
01676 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689 pull_ascii_nstring( qname, sizeof(qname), question->name);
01690 query_name_from_wins_server( namerec->data.ip[0],
01691 qname,
01692 question->name_type,
01693 wins_multihomed_register_query_success,
01694 wins_multihomed_register_query_fail,
01695 userdata );
01696
01697 return;
01698 }
01699
01700
01701
01702
01703
01704 pull_ascii_nstring( qname, sizeof(qname), question->name);
01705 add_name_to_subnet( subrec, qname, question->name_type,
01706 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
01707
01708 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
01709 get_global_id_and_update(&namerec->data.id, True);
01710 update_wins_owner(namerec, our_fake_ip);
01711 update_wins_flag(namerec, WINS_ACTIVE);
01712 wins_hook("add", namerec, ttl);
01713 }
01714
01715 send_wins_name_registration_response(0, ttl, p);
01716 }
01717
01718
01719
01720
01721
01722 static int fetch_1b_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
01723 {
01724 struct name_record *namerec = NULL;
01725
01726 if (kbuf.dsize != sizeof(unstring) + 1) {
01727 return 0;
01728 }
01729
01730
01731 if (kbuf.dptr[sizeof(unstring)] != 0x1b) {
01732 return 0;
01733 }
01734
01735 namerec = wins_record_to_name_record(kbuf, dbuf);
01736 if (!namerec) {
01737 return 0;
01738 }
01739
01740 DLIST_ADD(wins_server_subnet->namelist, namerec);
01741 return 0;
01742 }
01743
01744 void fetch_all_active_wins_1b_names(void)
01745 {
01746 tdb_traverse(wins_tdb, fetch_1b_traverse_fn, NULL);
01747 }
01748
01749
01750
01751
01752
01753 static void process_wins_dmb_query_request(struct subnet_record *subrec,
01754 struct packet_struct *p)
01755 {
01756 struct name_record *namerec = NULL;
01757 char *prdata;
01758 int num_ips;
01759
01760
01761
01762
01763
01764
01765
01766 num_ips = 0;
01767
01768
01769
01770
01771 wins_delete_all_tmp_in_memory_records();
01772
01773 fetch_all_active_wins_1b_names();
01774
01775 for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
01776 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
01777 num_ips += namerec->data.num_ips;
01778 }
01779 }
01780
01781 if(num_ips == 0) {
01782
01783
01784
01785 send_wins_name_query_response(NAM_ERR, p, NULL);
01786 return;
01787 }
01788
01789 if((prdata = (char *)SMB_MALLOC( num_ips * 6 )) == NULL) {
01790 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
01791 return;
01792 }
01793
01794
01795
01796
01797
01798
01799
01800 num_ips = 0;
01801 for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
01802 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
01803 int i;
01804 for(i = 0; i < namerec->data.num_ips; i++) {
01805 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
01806 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
01807 num_ips++;
01808 }
01809 }
01810 }
01811
01812
01813
01814
01815
01816 reply_netbios_packet(p,
01817 0,
01818 WINS_QUERY,
01819 NMB_NAME_QUERY_OPCODE,
01820 lp_min_wins_ttl(),
01821 prdata,
01822 num_ips*6);
01823
01824 SAFE_FREE(prdata);
01825 }
01826
01827
01828
01829
01830
01831 void send_wins_name_query_response(int rcode, struct packet_struct *p,
01832 struct name_record *namerec)
01833 {
01834 char rdata[6];
01835 char *prdata = rdata;
01836 int reply_data_len = 0;
01837 int ttl = 0;
01838 int i;
01839
01840 memset(rdata,'\0',6);
01841
01842 if(rcode == 0) {
01843 ttl = (namerec->data.death_time != PERMANENT_TTL) ? namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
01844
01845
01846
01847
01848 if( namerec->data.num_ips == 1 ) {
01849 prdata = rdata;
01850 } else {
01851 if((prdata = (char *)SMB_MALLOC( namerec->data.num_ips * 6 )) == NULL) {
01852 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
01853 return;
01854 }
01855 }
01856
01857 for(i = 0; i < namerec->data.num_ips; i++) {
01858 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
01859 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
01860 }
01861
01862 sort_query_replies(prdata, i, p->ip);
01863 reply_data_len = namerec->data.num_ips * 6;
01864 }
01865
01866 reply_netbios_packet(p,
01867 rcode,
01868 WINS_QUERY,
01869 NMB_NAME_QUERY_OPCODE,
01870 ttl,
01871 prdata,
01872 reply_data_len);
01873
01874 if(prdata != rdata) {
01875 SAFE_FREE(prdata);
01876 }
01877 }
01878
01879
01880
01881
01882
01883 void wins_process_name_query_request(struct subnet_record *subrec,
01884 struct packet_struct *p)
01885 {
01886 struct nmb_packet *nmb = &p->packet.nmb;
01887 struct nmb_name *question = &nmb->question.question_name;
01888 struct name_record *namerec = NULL;
01889 unstring qname;
01890
01891 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
01892 nmb_namestr(question), inet_ntoa(p->ip) ));
01893
01894
01895
01896
01897
01898
01899
01900
01901 pull_ascii_nstring(qname, sizeof(qname), question->name);
01902 if(strequal( qname, "*") && (question->name_type == 0x1b)) {
01903 process_wins_dmb_query_request( subrec, p);
01904 return;
01905 }
01906
01907 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
01908
01909 if(namerec != NULL) {
01910
01911
01912
01913
01914 if (!WINS_STATE_ACTIVE(namerec)) {
01915 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
01916 nmb_namestr(question) ));
01917 send_wins_name_query_response(NAM_ERR, p, namerec);
01918 return;
01919 }
01920
01921
01922
01923
01924
01925 if( namerec->data.source == DNSFAIL_NAME ) {
01926 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
01927 nmb_namestr(question) ));
01928 send_wins_name_query_response(NAM_ERR, p, namerec);
01929 return;
01930 }
01931
01932
01933
01934
01935
01936 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < p->timestamp) ) {
01937 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
01938 nmb_namestr(question) ));
01939 send_wins_name_query_response(NAM_ERR, p, namerec);
01940 return;
01941 }
01942
01943 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
01944 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
01945
01946 send_wins_name_query_response(0, p, namerec);
01947 return;
01948 }
01949
01950
01951
01952
01953
01954 if(lp_dns_proxy() && ((question->name_type == 0x20) || question->name_type == 0)) {
01955 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
01956 nmb_namestr(question) ));
01957
01958 queue_dns_query(p, question);
01959 return;
01960 }
01961
01962
01963
01964
01965
01966 send_wins_name_query_response(NAM_ERR, p, NULL);
01967 }
01968
01969
01970
01971
01972
01973 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
01974 {
01975 struct nmb_packet *nmb = &p->packet.nmb;
01976 char rdata[6];
01977
01978 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
01979
01980 reply_netbios_packet(p,
01981 rcode,
01982 NMB_REL,
01983 NMB_NAME_RELEASE_OPCODE,
01984 0,
01985 rdata,
01986 6);
01987 }
01988
01989
01990
01991
01992
01993 void wins_process_name_release_request(struct subnet_record *subrec,
01994 struct packet_struct *p)
01995 {
01996 struct nmb_packet *nmb = &p->packet.nmb;
01997 struct nmb_name *question = &nmb->question.question_name;
01998 BOOL bcast = nmb->header.nm_flags.bcast;
01999 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
02000 struct name_record *namerec = NULL;
02001 struct in_addr from_ip;
02002 BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
02003
02004 putip((char *)&from_ip,&nmb->additional->rdata[2]);
02005
02006 if(bcast) {
02007
02008
02009
02010
02011
02012
02013 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
02014 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
02015 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
02016 return;
02017 }
02018
02019 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
02020 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
02021
02022
02023
02024
02025
02026 if(!releasing_group_name && (question->name_type == 0x1d)) {
02027 DEBUG(3,("wins_process_name_release_request: Ignoring request \
02028 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
02029 send_wins_name_release_response(0, p);
02030 return;
02031 }
02032
02033
02034
02035
02036
02037 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
02038
02039 if( (namerec == NULL) || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) {
02040 send_wins_name_release_response(NAM_ERR, p);
02041 return;
02042 }
02043
02044
02045
02046
02047
02048
02049
02050 if(releasing_group_name && (question->name_type != 0x1c)) {
02051 send_wins_name_release_response(0, p);
02052 return;
02053 }
02054
02055
02056
02057
02058
02059
02060 if(!find_ip_in_name_record(namerec, from_ip)) {
02061 DEBUG(3,("wins_process_name_release_request: Refusing request to \
02062 release name %s as IP %s is not one of the known IP's for this name.\n",
02063 nmb_namestr(question), inet_ntoa(from_ip) ));
02064 send_wins_name_release_response(NAM_ERR, p);
02065 return;
02066 }
02067
02068
02069
02070
02071
02072
02073 if (!WINS_STATE_ACTIVE(namerec)) {
02074 DEBUG(3,("wins_process_name_release_request: Refusing request to \
02075 release name %s as this record is not active anymore.\n", nmb_namestr(question) ));
02076 send_wins_name_release_response(NAM_ERR, p);
02077 return;
02078 }
02079
02080
02081
02082
02083
02084
02085
02086 if(releasing_group_name && (question->name_type == 0x1c) && (namerec->data.num_ips > 1)) {
02087 remove_ip_from_name_record(namerec, from_ip);
02088 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
02089 inet_ntoa(from_ip),nmb_namestr(question)));
02090 wins_hook("delete", namerec, 0);
02091 send_wins_name_release_response(0, p);
02092 return;
02093 }
02094
02095
02096
02097
02098
02099
02100 namerec->data.wins_flags |= WINS_RELEASED;
02101 update_name_ttl(namerec, EXTINCTION_INTERVAL);
02102
02103 wins_hook("delete", namerec, 0);
02104 send_wins_name_release_response(0, p);
02105 }
02106
02107
02108
02109
02110
02111 static int wins_processing_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
02112 {
02113 time_t t = *(time_t *)state;
02114 BOOL store_record = False;
02115 struct name_record *namerec = NULL;
02116 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
02117
02118 if (kbuf.dsize != sizeof(unstring) + 1) {
02119 return 0;
02120 }
02121
02122 namerec = wins_record_to_name_record(kbuf, dbuf);
02123 if (!namerec) {
02124 return 0;
02125 }
02126
02127 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) {
02128 if( namerec->data.source == SELF_NAME ) {
02129 DEBUG( 3, ( "wins_processing_traverse_fn: Subnet %s not expiring SELF name %s\n",
02130 wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
02131 namerec->data.death_time += 300;
02132 store_record = True;
02133 goto done;
02134 } else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) {
02135 DEBUG(3,("wins_processing_traverse_fn: deleting timed out DNS name %s\n",
02136 nmb_namestr(&namerec->name)));
02137 remove_name_from_wins_namelist(namerec );
02138 goto done;
02139 }
02140
02141
02142 if (ip_equal(namerec->data.wins_ip, our_fake_ip)) {
02143 switch (namerec->data.wins_flags & WINS_STATE_MASK) {
02144 case WINS_ACTIVE:
02145 namerec->data.wins_flags&=~WINS_STATE_MASK;
02146 namerec->data.wins_flags|=WINS_RELEASED;
02147 namerec->data.death_time = t + EXTINCTION_INTERVAL;
02148 DEBUG(3,("wins_processing_traverse_fn: expiring %s\n",
02149 nmb_namestr(&namerec->name)));
02150 store_record = True;
02151 goto done;
02152 case WINS_RELEASED:
02153 namerec->data.wins_flags&=~WINS_STATE_MASK;
02154 namerec->data.wins_flags|=WINS_TOMBSTONED;
02155 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
02156 get_global_id_and_update(&namerec->data.id, True);
02157 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
02158 nmb_namestr(&namerec->name)));
02159 store_record = True;
02160 goto done;
02161 case WINS_TOMBSTONED:
02162 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
02163 nmb_namestr(&namerec->name)));
02164 remove_name_from_wins_namelist(namerec );
02165 goto done;
02166 }
02167 } else {
02168 switch (namerec->data.wins_flags & WINS_STATE_MASK) {
02169 case WINS_ACTIVE:
02170
02171 namerec->data.wins_flags&=~WINS_STATE_MASK;
02172 namerec->data.wins_flags|=WINS_TOMBSTONED;
02173 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
02174 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
02175 nmb_namestr(&namerec->name)));
02176 store_record = True;
02177 goto done;
02178 case WINS_TOMBSTONED:
02179 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
02180 nmb_namestr(&namerec->name)));
02181 remove_name_from_wins_namelist(namerec );
02182 goto done;
02183 case WINS_RELEASED:
02184 DEBUG(0,("wins_processing_traverse_fn: %s is in released state and\
02185 we are not the wins owner !\n", nmb_namestr(&namerec->name)));
02186 goto done;
02187 }
02188 }
02189 }
02190
02191 done:
02192
02193 if (store_record) {
02194 wins_store_changed_namerec(namerec);
02195 }
02196
02197 SAFE_FREE(namerec->data.ip);
02198 SAFE_FREE(namerec);
02199
02200 return 0;
02201 }
02202
02203
02204
02205
02206
02207 void initiate_wins_processing(time_t t)
02208 {
02209 static time_t lasttime = 0;
02210
02211 if (!lasttime) {
02212 lasttime = t;
02213 }
02214 if (t - lasttime < 20) {
02215 return;
02216 }
02217
02218 if(!lp_we_are_a_wins_server()) {
02219 lasttime = t;
02220 return;
02221 }
02222
02223 tdb_traverse(wins_tdb, wins_processing_traverse_fn, &t);
02224
02225 wins_delete_all_tmp_in_memory_records();
02226
02227 wins_write_database(t, True);
02228
02229 lasttime = t;
02230 }
02231
02232
02233
02234
02235
02236 void wins_write_name_record(struct name_record *namerec, XFILE *fp)
02237 {
02238 int i;
02239 struct tm *tm;
02240
02241 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
02242
02243 if( namerec->data.death_time != PERMANENT_TTL ) {
02244 char *ts, *nl;
02245
02246 tm = localtime(&namerec->data.death_time);
02247 if (!tm) {
02248 return;
02249 }
02250 ts = asctime(tm);
02251 if (!ts) {
02252 return;
02253 }
02254 nl = strrchr( ts, '\n' );
02255 if( NULL != nl ) {
02256 *nl = '\0';
02257 }
02258 DEBUGADD(4,("TTL = %s ", ts ));
02259 } else {
02260 DEBUGADD(4,("TTL = PERMANENT "));
02261 }
02262
02263 for (i = 0; i < namerec->data.num_ips; i++) {
02264 DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
02265 }
02266 DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
02267
02268 if( namerec->data.source == REGISTER_NAME ) {
02269 unstring name;
02270 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
02271 x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type,
02272 (int)namerec->data.death_time);
02273
02274 for (i = 0; i < namerec->data.num_ips; i++)
02275 x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
02276 x_fprintf( fp, "%2xR\n", namerec->data.nb_flags );
02277 }
02278 }
02279
02280
02281
02282
02283
02284 static int wins_writedb_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
02285 {
02286 struct name_record *namerec = NULL;
02287 XFILE *fp = (XFILE *)state;
02288
02289 if (kbuf.dsize != sizeof(unstring) + 1) {
02290 return 0;
02291 }
02292
02293 namerec = wins_record_to_name_record(kbuf, dbuf);
02294 if (!namerec) {
02295 return 0;
02296 }
02297
02298 wins_write_name_record(namerec, fp);
02299
02300 SAFE_FREE(namerec->data.ip);
02301 SAFE_FREE(namerec);
02302 return 0;
02303 }
02304
02305
02306 void wins_write_database(time_t t, BOOL background)
02307 {
02308 static time_t last_write_time = 0;
02309 pstring fname, fnamenew;
02310
02311 XFILE *fp;
02312
02313 if (background) {
02314 if (!last_write_time) {
02315 last_write_time = t;
02316 }
02317 if (t - last_write_time < 120) {
02318 return;
02319 }
02320
02321 }
02322
02323 if(!lp_we_are_a_wins_server()) {
02324 return;
02325 }
02326
02327
02328 if (background) {
02329 CatchChild();
02330 if (sys_fork()) {
02331 return;
02332 }
02333 if (tdb_reopen(wins_tdb)) {
02334 DEBUG(0,("wins_write_database: tdb_reopen failed. Error was %s\n",
02335 strerror(errno)));
02336 _exit(0);
02337 return;
02338 }
02339 }
02340
02341 slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST);
02342 all_string_sub(fname,"//", "/", 0);
02343 slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid());
02344
02345 if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) {
02346 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
02347 if (background) {
02348 _exit(0);
02349 }
02350 return;
02351 }
02352
02353 DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
02354
02355 x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0);
02356
02357 tdb_traverse(wins_tdb, wins_writedb_traverse_fn, fp);
02358
02359 x_fclose(fp);
02360 chmod(fnamenew,0644);
02361 unlink(fname);
02362 rename(fnamenew,fname);
02363 if (background) {
02364 _exit(0);
02365 }
02366 }
02367
02368 #if 0
02369 Until winsrepl is done.
02370
02371
02372
02373
02374 void nmbd_wins_new_entry(int msg_type, struct process_id src,
02375 void *buf, size_t len, void *private_data)
02376 {
02377 WINS_RECORD *record;
02378 struct name_record *namerec = NULL;
02379 struct name_record *new_namerec = NULL;
02380 struct nmb_name question;
02381 BOOL overwrite=False;
02382 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
02383 int i;
02384
02385 if (buf==NULL) {
02386 return;
02387 }
02388
02389
02390 record=(WINS_RECORD *)buf;
02391
02392 make_nmb_name(&question, record->name, record->type);
02393
02394 namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
02395
02396
02397 if (namerec == NULL) {
02398 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
02399 record->name, record->type, inet_ntoa(record->wins_ip)));
02400
02401 new_namerec=add_name_to_subnet( wins_server_subnet,
02402 record->name,
02403 record->type,
02404 record->nb_flags,
02405 EXTINCTION_INTERVAL,
02406 REGISTER_NAME,
02407 record->num_ips,
02408 record->ip);
02409
02410 if (new_namerec!=NULL) {
02411 update_wins_owner(new_namerec, record->wins_ip);
02412 update_wins_flag(new_namerec, record->wins_flags);
02413 new_namerec->data.id=record->id;
02414
02415 wins_server_subnet->namelist_changed = True;
02416 }
02417 }
02418
02419
02420 if (namerec != NULL) {
02421
02422 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
02423
02424
02425 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
02426 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
02427 if (ip_equal(namerec->data.wins_ip, record->wins_ip))
02428 overwrite=True;
02429 } else
02430 overwrite=True;
02431 } else {
02432
02433
02434 if (ip_equal(namerec->data.ip[0], record->ip[0])) {
02435 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
02436 get_global_id_and_update(&namerec->data.id, True);
02437 else
02438 overwrite=True;
02439
02440 } else {
02441
02442 if (namerec->data.wins_flags&WINS_ACTIVE) {
02443 if (record->wins_flags&WINS_TOMBSTONED)
02444 get_global_id_and_update(&namerec->data.id, True);
02445 if (record->wins_flags&WINS_ACTIVE)
02446
02447 ;
02448 } else
02449 overwrite=True;
02450 }
02451
02452 }
02453 }
02454
02455
02456 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {
02457
02458 if (namerec->data.wins_flags&WINS_UNIQUE)
02459
02460 ;
02461 overwrite=True;
02462
02463 }
02464
02465
02466 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
02467 if (namerec->data.wins_flags&WINS_ACTIVE) {
02468 for (i=0; i<record->num_ips; i++)
02469 if(!find_ip_in_name_record(namerec, record->ip[i]))
02470 add_ip_to_name_record(namerec, record->ip[i]);
02471 } else {
02472 overwrite=True;
02473 }
02474 }
02475
02476
02477
02478
02479
02480 if (record->wins_flags&WINS_MHOMED) {
02481 if (! (namerec->data.wins_flags&WINS_ACTIVE)) {
02482 if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP))
02483 overwrite=True;
02484 }
02485 else {
02486 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
02487 overwrite=True;
02488
02489 if (ip_equal(namerec->data.wins_ip, our_fake_ip))
02490 if (namerec->data.wins_flags&WINS_UNIQUE)
02491 get_global_id_and_update(&namerec->data.id, True);
02492
02493 }
02494
02495 if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
02496 if (namerec->data.wins_flags&WINS_UNIQUE ||
02497 namerec->data.wins_flags&WINS_MHOMED)
02498 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
02499 overwrite=True;
02500
02501 }
02502
02503 if (overwrite == False)
02504 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
02505 record->name, record->type, inet_ntoa(record->wins_ip)));
02506 else {
02507 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
02508 record->name, record->type, inet_ntoa(record->wins_ip)));
02509
02510
02511 remove_name_from_namelist( wins_server_subnet, namerec );
02512 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
02513 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
02514 if (new_namerec!=NULL) {
02515 update_wins_owner(new_namerec, record->wins_ip);
02516 update_wins_flag(new_namerec, record->wins_flags);
02517 new_namerec->data.id=record->id;
02518
02519 wins_server_subnet->namelist_changed = True;
02520 }
02521
02522 wins_server_subnet->namelist_changed = True;
02523 }
02524
02525 }
02526 }
02527 #endif