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 uint16 samba_nb_type = 0;
00027
00028
00029
00030
00031
00032
00033 void set_samba_nb_type(void)
00034 {
00035 if( lp_wins_support() || wins_srv_count() ) {
00036 samba_nb_type = NB_HFLAG;
00037 } else {
00038 samba_nb_type = NB_BFLAG;
00039 }
00040 }
00041
00042
00043
00044
00045
00046 static void upcase_name( struct nmb_name *target, const struct nmb_name *source )
00047 {
00048 int i;
00049 unstring targ;
00050 fstring scope;
00051
00052 if( NULL != source ) {
00053 memcpy( target, source, sizeof( struct nmb_name ) );
00054 }
00055
00056 pull_ascii_nstring(targ, sizeof(targ), target->name);
00057 strupper_m( targ );
00058 push_ascii_nstring( target->name, targ);
00059
00060 pull_ascii(scope, target->scope, 64, -1, STR_TERMINATE);
00061 strupper_m( scope );
00062 push_ascii(target->scope, scope, 64, STR_TERMINATE);
00063
00064
00065
00066
00067
00068 for( i = strlen( target->name ); i < sizeof( target->name ); i++ ) {
00069 target->name[i] = '\0';
00070 }
00071 for( i = strlen( target->scope ); i < sizeof( target->scope ); i++ ) {
00072 target->scope[i] = '\0';
00073 }
00074 }
00075
00076
00077
00078
00079
00080 void remove_name_from_namelist(struct subnet_record *subrec,
00081 struct name_record *namerec )
00082 {
00083 if (subrec == wins_server_subnet)
00084 remove_name_from_wins_namelist(namerec);
00085 else {
00086 subrec->namelist_changed = True;
00087 DLIST_REMOVE(subrec->namelist, namerec);
00088 }
00089
00090 SAFE_FREE(namerec->data.ip);
00091 ZERO_STRUCTP(namerec);
00092 SAFE_FREE(namerec);
00093 }
00094
00095
00096
00097
00098
00099 struct name_record *find_name_on_subnet(struct subnet_record *subrec,
00100 const struct nmb_name *nmbname,
00101 BOOL self_only)
00102 {
00103 struct nmb_name uc_name;
00104 struct name_record *name_ret;
00105
00106 upcase_name( &uc_name, nmbname );
00107
00108 if (subrec == wins_server_subnet) {
00109 return find_name_on_wins_subnet(&uc_name, self_only);
00110 }
00111
00112 for( name_ret = subrec->namelist; name_ret; name_ret = name_ret->next) {
00113 if (memcmp(&uc_name, &name_ret->name, sizeof(struct nmb_name)) == 0) {
00114 break;
00115 }
00116 }
00117
00118 if( name_ret ) {
00119
00120 if( self_only && (name_ret->data.source != SELF_NAME) && (name_ret->data.source != PERMANENT_NAME) ) {
00121 DEBUG( 9, ( "find_name_on_subnet: on subnet %s - self name %s NOT FOUND\n",
00122 subrec->subnet_name, nmb_namestr(nmbname) ) );
00123 return NULL;
00124 }
00125
00126 DEBUG( 9, ("find_name_on_subnet: on subnet %s - found name %s source=%d\n",
00127 subrec->subnet_name, nmb_namestr(nmbname), name_ret->data.source) );
00128
00129 return name_ret;
00130 }
00131
00132 DEBUG( 9, ( "find_name_on_subnet: on subnet %s - name %s NOT FOUND\n",
00133 subrec->subnet_name, nmb_namestr(nmbname) ) );
00134
00135 return NULL;
00136 }
00137
00138
00139
00140
00141
00142 struct name_record *find_name_for_remote_broadcast_subnet(struct nmb_name *nmbname,
00143 BOOL self_only)
00144 {
00145 struct subnet_record *subrec;
00146 struct name_record *namerec;
00147
00148 for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) ) {
00149 namerec = find_name_on_subnet(subrec, nmbname, self_only);
00150 if (namerec) {
00151 return namerec;
00152 }
00153 }
00154
00155 return NULL;
00156 }
00157
00158
00159
00160
00161
00162 void update_name_ttl( struct name_record *namerec, int ttl )
00163 {
00164 time_t time_now = time(NULL);
00165
00166 if( namerec->data.death_time != PERMANENT_TTL) {
00167 namerec->data.death_time = time_now + ttl;
00168 }
00169
00170 namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME);
00171
00172 if (namerec->subnet == wins_server_subnet) {
00173 wins_store_changed_namerec(namerec);
00174 } else {
00175 namerec->subnet->namelist_changed = True;
00176 }
00177 }
00178
00179
00180
00181
00182
00183 BOOL add_name_to_subnet( struct subnet_record *subrec,
00184 const char *name,
00185 int type,
00186 uint16 nb_flags,
00187 int ttl,
00188 enum name_source source,
00189 int num_ips,
00190 struct in_addr *iplist)
00191 {
00192 BOOL ret = False;
00193 struct name_record *namerec;
00194 time_t time_now = time(NULL);
00195
00196 namerec = SMB_MALLOC_P(struct name_record);
00197 if( NULL == namerec ) {
00198 DEBUG( 0, ( "add_name_to_subnet: malloc fail.\n" ) );
00199 return False;
00200 }
00201
00202 memset( (char *)namerec, '\0', sizeof(*namerec) );
00203 namerec->data.ip = SMB_MALLOC_ARRAY( struct in_addr, num_ips );
00204 if( NULL == namerec->data.ip ) {
00205 DEBUG( 0, ( "add_name_to_subnet: malloc fail when creating ip_flgs.\n" ) );
00206 ZERO_STRUCTP(namerec);
00207 SAFE_FREE(namerec);
00208 return False;
00209 }
00210
00211 namerec->subnet = subrec;
00212
00213 make_nmb_name(&namerec->name, name, type);
00214 upcase_name(&namerec->name, NULL );
00215
00216
00217 namerec->data.nb_flags = nb_flags | NB_ACTIVE;
00218 namerec->data.wins_flags = WINS_ACTIVE;
00219
00220
00221 if (strequal( my_netbios_names(0), name )) {
00222 namerec->data.nb_flags |= NB_PERM;
00223 }
00224
00225
00226 namerec->data.num_ips = num_ips;
00227 memcpy( (namerec->data.ip), iplist, num_ips * sizeof(struct in_addr) );
00228
00229
00230 namerec->data.source = source;
00231
00232
00233 if (ttl == PERMANENT_TTL) {
00234 namerec->data.death_time = PERMANENT_TTL;
00235 } else {
00236 namerec->data.death_time = time_now + ttl;
00237 }
00238
00239 namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME);
00240
00241 DEBUG( 3, ( "add_name_to_subnet: Added netbios name %s with first IP %s \
00242 ttl=%d nb_flags=%2x to subnet %s\n",
00243 nmb_namestr( &namerec->name ),
00244 inet_ntoa( *iplist ),
00245 ttl,
00246 (unsigned int)nb_flags,
00247 subrec->subnet_name ) );
00248
00249
00250
00251 if (subrec == wins_server_subnet) {
00252 ret = add_name_to_wins_subnet(namerec);
00253
00254 SAFE_FREE(namerec->data.ip);
00255 SAFE_FREE(namerec);
00256 } else {
00257 DLIST_ADD(subrec->namelist, namerec);
00258 subrec->namelist_changed = True;
00259 ret = True;
00260 }
00261
00262 return ret;
00263 }
00264
00265
00266
00267
00268
00269
00270
00271 void standard_success_register(struct subnet_record *subrec,
00272 struct userdata_struct *userdata,
00273 struct nmb_name *nmbname, uint16 nb_flags, int ttl,
00274 struct in_addr registered_ip)
00275 {
00276 struct name_record *namerec;
00277
00278 namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME);
00279 if (namerec == NULL) {
00280 unstring name;
00281 pull_ascii_nstring(name, sizeof(name), nmbname->name);
00282 add_name_to_subnet( subrec, name, nmbname->name_type,
00283 nb_flags, ttl, SELF_NAME, 1, ®istered_ip );
00284 } else {
00285 update_name_ttl( namerec, ttl );
00286 }
00287 }
00288
00289
00290
00291
00292
00293
00294
00295
00296 void standard_fail_register( struct subnet_record *subrec,
00297 struct nmb_name *nmbname )
00298 {
00299 struct name_record *namerec;
00300
00301 namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME);
00302
00303 DEBUG( 0, ( "standard_fail_register: Failed to register/refresh name %s \
00304 on subnet %s\n", nmb_namestr(nmbname), subrec->subnet_name) );
00305
00306
00307 if( namerec ) {
00308 remove_name_from_namelist(subrec, namerec);
00309 }
00310 }
00311
00312
00313
00314
00315
00316 static void remove_nth_ip_in_record( struct name_record *namerec, int ind)
00317 {
00318 if( ind != namerec->data.num_ips ) {
00319 memmove( (char *)(&namerec->data.ip[ind]),
00320 (char *)(&namerec->data.ip[ind+1]),
00321 ( namerec->data.num_ips - ind - 1) * sizeof(struct in_addr) );
00322 }
00323
00324 namerec->data.num_ips--;
00325 if (namerec->subnet == wins_server_subnet) {
00326 wins_store_changed_namerec(namerec);
00327 } else {
00328 namerec->subnet->namelist_changed = True;
00329 }
00330 }
00331
00332
00333
00334
00335
00336 BOOL find_ip_in_name_record( struct name_record *namerec, struct in_addr ip )
00337 {
00338 int i;
00339
00340 for(i = 0; i < namerec->data.num_ips; i++) {
00341 if(ip_equal( namerec->data.ip[i], ip)) {
00342 return True;
00343 }
00344 }
00345
00346 return False;
00347 }
00348
00349
00350
00351
00352
00353 void add_ip_to_name_record( struct name_record *namerec, struct in_addr new_ip )
00354 {
00355 struct in_addr *new_list;
00356
00357
00358 if( find_ip_in_name_record( namerec, new_ip )) {
00359 return;
00360 }
00361
00362 new_list = SMB_MALLOC_ARRAY( struct in_addr, namerec->data.num_ips + 1);
00363 if( NULL == new_list ) {
00364 DEBUG(0,("add_ip_to_name_record: Malloc fail !\n"));
00365 return;
00366 }
00367
00368 memcpy( (char *)new_list, (char *)namerec->data.ip, namerec->data.num_ips * sizeof(struct in_addr) );
00369 new_list[namerec->data.num_ips] = new_ip;
00370
00371 SAFE_FREE(namerec->data.ip);
00372 namerec->data.ip = new_list;
00373 namerec->data.num_ips += 1;
00374
00375 if (namerec->subnet == wins_server_subnet) {
00376 wins_store_changed_namerec(namerec);
00377 } else {
00378 namerec->subnet->namelist_changed = True;
00379 }
00380 }
00381
00382
00383
00384
00385
00386 void remove_ip_from_name_record( struct name_record *namerec,
00387 struct in_addr remove_ip )
00388 {
00389
00390 int i;
00391 int orig_num = namerec->data.num_ips;
00392
00393 for(i = 0; i < orig_num; i++) {
00394 if( ip_equal( remove_ip, namerec->data.ip[i]) ) {
00395 remove_nth_ip_in_record( namerec, i);
00396 break;
00397 }
00398 }
00399 }
00400
00401
00402
00403
00404
00405
00406
00407 void standard_success_release( struct subnet_record *subrec,
00408 struct userdata_struct *userdata,
00409 struct nmb_name *nmbname,
00410 struct in_addr released_ip )
00411 {
00412 struct name_record *namerec;
00413
00414 namerec = find_name_on_subnet( subrec, nmbname, FIND_ANY_NAME );
00415 if( namerec == NULL ) {
00416 DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \
00417 on subnet %s. Name was not found on subnet.\n", nmb_namestr(nmbname), inet_ntoa(released_ip),
00418 subrec->subnet_name) );
00419 return;
00420 } else {
00421 int orig_num = namerec->data.num_ips;
00422
00423 remove_ip_from_name_record( namerec, released_ip );
00424
00425 if( namerec->data.num_ips == orig_num ) {
00426 DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \
00427 on subnet %s. This ip is not known for this name.\n", nmb_namestr(nmbname), inet_ntoa(released_ip), subrec->subnet_name ) );
00428 }
00429 }
00430
00431 if( namerec->data.num_ips == 0 ) {
00432 remove_name_from_namelist( subrec, namerec );
00433 }
00434 }
00435
00436
00437
00438
00439
00440
00441 static void expire_names_on_subnet(struct subnet_record *subrec, time_t t)
00442 {
00443 struct name_record *namerec;
00444 struct name_record *next_namerec;
00445
00446 for( namerec = subrec->namelist; namerec; namerec = next_namerec ) {
00447 next_namerec = namerec->next;
00448 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) {
00449 if( namerec->data.source == SELF_NAME ) {
00450 DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF \
00451 name %s\n", subrec->subnet_name, nmb_namestr(&namerec->name) ) );
00452 namerec->data.death_time += 300;
00453 namerec->subnet->namelist_changed = True;
00454 continue;
00455 }
00456
00457 DEBUG(3,("expire_names_on_subnet: Subnet %s - removing expired name %s\n",
00458 subrec->subnet_name, nmb_namestr(&namerec->name)));
00459
00460 remove_name_from_namelist(subrec, namerec );
00461 }
00462 }
00463 }
00464
00465
00466
00467
00468
00469
00470 void expire_names(time_t t)
00471 {
00472 struct subnet_record *subrec;
00473
00474 for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) ) {
00475 expire_names_on_subnet( subrec, t );
00476 }
00477 }
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487 void add_samba_names_to_subnet( struct subnet_record *subrec )
00488 {
00489 struct in_addr *iplist = &subrec->myip;
00490 int num_ips = 1;
00491
00492
00493
00494 if( (subrec == unicast_subnet) || (subrec == wins_server_subnet) || (subrec == remote_broadcast_subnet) ) {
00495 struct subnet_record *bcast_subrecs;
00496 int i;
00497
00498
00499
00500 num_ips = iface_count();
00501 iplist = SMB_MALLOC_ARRAY( struct in_addr, num_ips);
00502 if( NULL == iplist ) {
00503 DEBUG(0,("add_samba_names_to_subnet: Malloc fail !\n"));
00504 return;
00505 }
00506
00507 for( bcast_subrecs = FIRST_SUBNET, i = 0; bcast_subrecs &&
00508 i < num_ips;
00509 bcast_subrecs = NEXT_SUBNET_EXCLUDING_UNICAST(bcast_subrecs), i++ ) {
00510 iplist[i] = bcast_subrecs->myip;
00511 }
00512 num_ips = i;
00513 }
00514
00515 add_name_to_subnet(subrec,"*",0x0,samba_nb_type, PERMANENT_TTL,
00516 PERMANENT_NAME, num_ips, iplist);
00517 add_name_to_subnet(subrec,"*",0x20,samba_nb_type,PERMANENT_TTL,
00518 PERMANENT_NAME, num_ips, iplist);
00519 add_name_to_subnet(subrec,"__SAMBA__",0x20,samba_nb_type,PERMANENT_TTL,
00520 PERMANENT_NAME, num_ips, iplist);
00521 add_name_to_subnet(subrec,"__SAMBA__",0x00,samba_nb_type,PERMANENT_TTL,
00522 PERMANENT_NAME, num_ips, iplist);
00523
00524 if(iplist != &subrec->myip) {
00525 SAFE_FREE(iplist);
00526 }
00527 }
00528
00529
00530
00531
00532
00533 void dump_name_record( struct name_record *namerec, XFILE *fp)
00534 {
00535 const char *src_type;
00536 struct tm *tm;
00537 int i;
00538
00539 x_fprintf(fp,"\tName = %s\t", nmb_namestr(&namerec->name));
00540 switch(namerec->data.source) {
00541 case LMHOSTS_NAME:
00542 src_type = "LMHOSTS_NAME";
00543 break;
00544 case WINS_PROXY_NAME:
00545 src_type = "WINS_PROXY_NAME";
00546 break;
00547 case REGISTER_NAME:
00548 src_type = "REGISTER_NAME";
00549 break;
00550 case SELF_NAME:
00551 src_type = "SELF_NAME";
00552 break;
00553 case DNS_NAME:
00554 src_type = "DNS_NAME";
00555 break;
00556 case DNSFAIL_NAME:
00557 src_type = "DNSFAIL_NAME";
00558 break;
00559 case PERMANENT_NAME:
00560 src_type = "PERMANENT_NAME";
00561 break;
00562 default:
00563 src_type = "unknown!";
00564 break;
00565 }
00566
00567 x_fprintf(fp,"Source = %s\nb_flags = %x\t", src_type, namerec->data.nb_flags);
00568
00569 if(namerec->data.death_time != PERMANENT_TTL) {
00570 const char *asct;
00571 tm = localtime(&namerec->data.death_time);
00572 if (!tm) {
00573 return;
00574 }
00575 asct = asctime(tm);
00576 if (!asct) {
00577 return;
00578 }
00579 x_fprintf(fp, "death_time = %s\t", asct);
00580 } else {
00581 x_fprintf(fp, "death_time = PERMANENT\t");
00582 }
00583
00584 if(namerec->data.refresh_time != PERMANENT_TTL) {
00585 const char *asct;
00586 tm = localtime(&namerec->data.refresh_time);
00587 if (!tm) {
00588 return;
00589 }
00590 asct = asctime(tm);
00591 if (!asct) {
00592 return;
00593 }
00594 x_fprintf(fp, "refresh_time = %s\n", asct);
00595 } else {
00596 x_fprintf(fp, "refresh_time = PERMANENT\n");
00597 }
00598
00599 x_fprintf(fp, "\t\tnumber of IPS = %d", namerec->data.num_ips);
00600 for(i = 0; i < namerec->data.num_ips; i++) {
00601 x_fprintf(fp, "\t%s", inet_ntoa(namerec->data.ip[i]));
00602 }
00603
00604 x_fprintf(fp, "\n\n");
00605
00606 }
00607
00608
00609
00610
00611
00612
00613 static void dump_subnet_namelist( struct subnet_record *subrec, XFILE *fp)
00614 {
00615 struct name_record *namerec;
00616 x_fprintf(fp, "Subnet %s\n----------------------\n", subrec->subnet_name);
00617 for( namerec = subrec->namelist; namerec; namerec = namerec->next) {
00618 dump_name_record(namerec, fp);
00619 }
00620 }
00621
00622
00623
00624
00625
00626
00627 void dump_all_namelists(void)
00628 {
00629 XFILE *fp;
00630 struct subnet_record *subrec;
00631
00632 fp = x_fopen(lock_path("namelist.debug"),O_WRONLY|O_CREAT|O_TRUNC, 0644);
00633
00634 if (!fp) {
00635 DEBUG(0,("dump_all_namelists: Can't open file %s. Error was %s\n",
00636 "namelist.debug",strerror(errno)));
00637 return;
00638 }
00639
00640 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) {
00641 dump_subnet_namelist( subrec, fp );
00642 }
00643
00644 if (!we_are_a_wins_client()) {
00645 dump_subnet_namelist( unicast_subnet, fp );
00646 }
00647
00648 if (remote_broadcast_subnet->namelist != NULL) {
00649 dump_subnet_namelist( remote_broadcast_subnet, fp );
00650 }
00651
00652 if (wins_server_subnet != NULL) {
00653 dump_wins_subnet_namelist(fp );
00654 }
00655
00656 x_fclose( fp );
00657 }