00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "includes.h"
00029
00030
00031
00032
00033
00034 static void send_name_release_response(int rcode, struct packet_struct *p)
00035 {
00036 struct nmb_packet *nmb = &p->packet.nmb;
00037 char rdata[6];
00038
00039 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
00040
00041 reply_netbios_packet(p,
00042 rcode,
00043 NMB_REL,
00044 NMB_NAME_RELEASE_OPCODE,
00045 0,
00046 rdata,
00047 6);
00048 }
00049
00050
00051
00052
00053
00054
00055 void process_name_release_request(struct subnet_record *subrec,
00056 struct packet_struct *p)
00057 {
00058 struct nmb_packet *nmb = &p->packet.nmb;
00059 struct in_addr owner_ip;
00060 struct nmb_name *question = &nmb->question.question_name;
00061 unstring qname;
00062 BOOL bcast = nmb->header.nm_flags.bcast;
00063 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
00064 BOOL group = (nb_flags & NB_GROUP) ? True : False;
00065 struct name_record *namerec;
00066 int rcode = 0;
00067
00068 putip((char *)&owner_ip,&nmb->additional->rdata[2]);
00069
00070 if(!bcast) {
00071
00072
00073
00074
00075
00076
00077
00078 DEBUG(0,("process_name_release_request: unicast name release request \
00079 received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
00080 nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name));
00081
00082 send_name_release_response(FMT_ERR, p);
00083 return;
00084 }
00085
00086 DEBUG(3,("process_name_release_request: Name release on name %s, \
00087 subnet %s from owner IP %s\n",
00088 nmb_namestr(&nmb->question.question_name),
00089 subrec->subnet_name, inet_ntoa(owner_ip)));
00090
00091
00092 if( group && !ismyip(owner_ip) )
00093 return;
00094
00095
00096
00097
00098
00099
00100
00101 pull_ascii_nstring(qname, sizeof(qname), question->name);
00102 if( !group && !ismyip(owner_ip) && strequal(qname, lp_workgroup()) &&
00103 ((question->name_type == 0x0) || (question->name_type == 0x1e))) {
00104 DEBUG(6,("process_name_release_request: FTP OnNet bug workaround. Ignoring \
00105 group release name %s from IP %s on subnet %s with no group bit set.\n",
00106 nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name ));
00107 return;
00108 }
00109
00110 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
00111
00112
00113 if( namerec && ( (namerec->data.source == SELF_NAME)
00114 || (namerec->data.source == PERMANENT_NAME) ) ) {
00115 rcode = ACT_ERR;
00116 DEBUG(0, ("process_name_release_request: Attempt to release name %s from IP %s \
00117 on subnet %s being rejected as it is one of our names.\n",
00118 nmb_namestr(&nmb->question.question_name), inet_ntoa(owner_ip), subrec->subnet_name));
00119 }
00120
00121 if(rcode == 0)
00122 return;
00123
00124
00125 send_name_release_response(rcode, p);
00126 }
00127
00128
00129
00130
00131
00132 static void send_name_registration_response(int rcode, int ttl, struct packet_struct *p)
00133 {
00134 struct nmb_packet *nmb = &p->packet.nmb;
00135 char rdata[6];
00136
00137 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
00138
00139 reply_netbios_packet(p,
00140 rcode,
00141 NMB_REG,
00142 NMB_NAME_REG_OPCODE,
00143 ttl,
00144 rdata,
00145 6);
00146 }
00147
00148
00149
00150
00151
00152 void process_name_refresh_request(struct subnet_record *subrec,
00153 struct packet_struct *p)
00154 {
00155 struct nmb_packet *nmb = &p->packet.nmb;
00156 struct nmb_name *question = &nmb->question.question_name;
00157 BOOL bcast = nmb->header.nm_flags.bcast;
00158 struct in_addr from_ip;
00159
00160 putip((char *)&from_ip,&nmb->additional->rdata[2]);
00161
00162 if(!bcast) {
00163
00164
00165
00166
00167
00168
00169
00170 DEBUG(0,("process_name_refresh_request: unicast name registration request \
00171 received for name %s from IP %s on subnet %s.\n",
00172 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
00173 DEBUG(0,("Error - should be sent to WINS server\n"));
00174
00175 send_name_registration_response(FMT_ERR, 0, p);
00176 return;
00177 }
00178
00179
00180
00181 DEBUG(3,("process_name_refresh_request: Name refresh for name %s \
00182 IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
00183 }
00184
00185
00186
00187
00188
00189 void process_name_registration_request(struct subnet_record *subrec,
00190 struct packet_struct *p)
00191 {
00192 struct nmb_packet *nmb = &p->packet.nmb;
00193 struct nmb_name *question = &nmb->question.question_name;
00194 BOOL bcast = nmb->header.nm_flags.bcast;
00195 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
00196 BOOL group = (nb_flags & NB_GROUP) ? True : False;
00197 struct name_record *namerec = NULL;
00198 int ttl = nmb->additional->ttl;
00199 struct in_addr from_ip;
00200
00201 putip((char *)&from_ip,&nmb->additional->rdata[2]);
00202
00203 if(!bcast) {
00204
00205
00206
00207
00208
00209
00210
00211 DEBUG(0,("process_name_registration_request: unicast name registration request \
00212 received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
00213 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
00214
00215 send_name_registration_response(FMT_ERR, 0, p);
00216 return;
00217 }
00218
00219 DEBUG(3,("process_name_registration_request: Name registration for name %s \
00220 IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
00221
00222
00223 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
00224
00225
00226
00227
00228
00229
00230
00231 if((namerec != NULL) && (namerec->data.source == WINS_PROXY_NAME)) {
00232 remove_name_from_namelist( subrec, namerec );
00233 namerec = NULL;
00234 }
00235
00236 if (!group) {
00237
00238
00239 if( (namerec != NULL)
00240 && ( (namerec->data.source == SELF_NAME)
00241 || (namerec->data.source == PERMANENT_NAME)
00242 || NAME_GROUP(namerec) ) ) {
00243
00244
00245
00246 send_name_registration_response(ACT_ERR, 0, p);
00247 return;
00248 } else if(namerec != NULL) {
00249
00250 namerec->data.ip[0] = from_ip;
00251 update_name_ttl(namerec, ttl);
00252
00253 DEBUG(3,("process_name_registration_request: Updated name record %s \
00254 with IP %s on subnet %s\n",nmb_namestr(&namerec->name),inet_ntoa(from_ip), subrec->subnet_name));
00255 return;
00256 }
00257 } else {
00258
00259
00260 if( (namerec != NULL)
00261 && !NAME_GROUP(namerec)
00262 && ( (namerec->data.source == SELF_NAME)
00263 || (namerec->data.source == PERMANENT_NAME) ) ) {
00264
00265 send_name_registration_response(ACT_ERR, 0, p);
00266 return;
00267 }
00268 }
00269 }
00270
00271
00272
00273
00274
00275
00276 static int status_compare(char *n1,char *n2)
00277 {
00278 unstring name1, name2;
00279 int l1,l2,l3;
00280
00281 memset(name1, '\0', sizeof(name1));
00282 memset(name2, '\0', sizeof(name2));
00283 pull_ascii_nstring(name1, sizeof(name1), n1);
00284 pull_ascii_nstring(name2, sizeof(name2), n2);
00285 n1 = name1;
00286 n2 = name2;
00287
00288
00289 for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++)
00290 ;
00291 for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++)
00292 ;
00293 l3 = strlen(global_myname());
00294
00295 if ((l1==l3) && strncmp(n1,global_myname(),l3) == 0 &&
00296 (l2!=l3 || strncmp(n2,global_myname(),l3) != 0))
00297 return -1;
00298
00299 if ((l2==l3) && strncmp(n2,global_myname(),l3) == 0 &&
00300 (l1!=l3 || strncmp(n1,global_myname(),l3) != 0))
00301 return 1;
00302
00303 return memcmp(n1,n2,sizeof(name1));
00304 }
00305
00306
00307
00308
00309
00310 void process_node_status_request(struct subnet_record *subrec, struct packet_struct *p)
00311 {
00312 struct nmb_packet *nmb = &p->packet.nmb;
00313 unstring qname;
00314 int ques_type = nmb->question.question_name.name_type;
00315 char rdata[MAX_DGRAM_SIZE];
00316 char *countptr, *buf, *bufend, *buf0;
00317 int names_added,i;
00318 struct name_record *namerec;
00319
00320 pull_ascii_nstring(qname, sizeof(qname), nmb->question.question_name.name);
00321
00322 DEBUG(3,("process_node_status_request: status request for name %s from IP %s on \
00323 subnet %s.\n", nmb_namestr(&nmb->question.question_name), inet_ntoa(p->ip), subrec->subnet_name));
00324
00325 if((namerec = find_name_on_subnet(subrec, &nmb->question.question_name, FIND_SELF_NAME)) == 0) {
00326 DEBUG(1,("process_node_status_request: status request for name %s from IP %s on \
00327 subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
00328 inet_ntoa(p->ip), subrec->subnet_name));
00329
00330 return;
00331 }
00332
00333
00334
00335 bufend = &rdata[MAX_DGRAM_SIZE] - (18 + 46 + 60);
00336 countptr = buf = rdata;
00337 buf += 1;
00338 buf0 = buf;
00339
00340 names_added = 0;
00341
00342 namerec = subrec->namelist;
00343
00344 while (buf < bufend) {
00345 if( (namerec->data.source == SELF_NAME) || (namerec->data.source == PERMANENT_NAME) ) {
00346 int name_type = namerec->name.name_type;
00347 unstring name;
00348
00349 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
00350 strupper_m(name);
00351 if (!strequal(name,"*") &&
00352 !strequal(name,"__SAMBA__") &&
00353 (name_type < 0x1b || name_type >= 0x20 ||
00354 ques_type < 0x1b || ques_type >= 0x20 ||
00355 strequal(qname, name))) {
00356
00357 size_t len;
00358 push_ascii_nstring(buf, name);
00359 len = strlen(buf);
00360 memset(buf + len, ' ', MAX_NETBIOSNAME_LEN - len - 1);
00361 buf[MAX_NETBIOSNAME_LEN - 1] = '\0';
00362
00363
00364
00365 buf[15] = name_type;
00366 set_nb_flags( &buf[16],namerec->data.nb_flags );
00367 buf[16] |= NB_ACTIVE;
00368
00369 buf += 18;
00370
00371 names_added++;
00372 }
00373 }
00374
00375
00376 if (names_added > 1) {
00377 qsort( buf0, names_added, 18, QSORT_CAST status_compare );
00378 }
00379
00380 for( i=1; i < names_added ; i++ ) {
00381 if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) {
00382 names_added--;
00383 if (names_added == i)
00384 break;
00385 memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i));
00386 i--;
00387 }
00388 }
00389
00390 buf = buf0 + 18*names_added;
00391
00392 namerec = namerec->next;
00393
00394 if (!namerec) {
00395
00396
00397 struct subnet_record *uni_subrec = unicast_subnet;
00398
00399 if (uni_subrec != subrec) {
00400 subrec = uni_subrec;
00401 namerec = subrec->namelist;
00402 }
00403 }
00404 if (!namerec)
00405 break;
00406
00407 }
00408
00409 SCVAL(countptr,0,names_added);
00410
00411
00412
00413 memset(buf,'\0',46);
00414
00415 buf += 46;
00416
00417
00418 reply_netbios_packet(p,
00419 0,
00420 NMB_STATUS,
00421 NMB_NAME_QUERY_OPCODE,
00422 0,
00423 rdata,
00424 PTR_DIFF(buf,rdata));
00425 }
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438 void process_name_query_request(struct subnet_record *subrec, struct packet_struct *p)
00439 {
00440 struct nmb_packet *nmb = &p->packet.nmb;
00441 struct nmb_name *question = &nmb->question.question_name;
00442 int name_type = question->name_type;
00443 BOOL bcast = nmb->header.nm_flags.bcast;
00444 int ttl=0;
00445 int rcode = 0;
00446 char *prdata = NULL;
00447 char rdata[6];
00448 BOOL success = False;
00449 struct name_record *namerec = NULL;
00450 int reply_data_len = 0;
00451 int i;
00452
00453 DEBUG(3,("process_name_query_request: Name query from %s on subnet %s for name %s\n",
00454 inet_ntoa(p->ip), subrec->subnet_name, nmb_namestr(question)));
00455
00456
00457
00458
00459
00460 if(subrec == remote_broadcast_subnet)
00461 namerec = find_name_for_remote_broadcast_subnet( question, FIND_ANY_NAME);
00462 else
00463 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
00464
00465
00466 if (namerec &&
00467 ((namerec->data.death_time != PERMANENT_TTL) &&
00468 (namerec->data.death_time < p->timestamp))) {
00469 DEBUG(5,("process_name_query_request: expired name %s\n", nmb_namestr(&namerec->name)));
00470 namerec = NULL;
00471 }
00472
00473 if (namerec) {
00474
00475
00476
00477
00478
00479
00480
00481
00482 if (!bcast ||
00483 (bcast && ((name_type == 0x1b) ||
00484 (namerec->data.source == SELF_NAME) ||
00485 (namerec->data.source == PERMANENT_NAME) ||
00486 ((namerec->data.source == WINS_PROXY_NAME) &&
00487 ((name_type == 0) || (name_type == 0x20)))))) {
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499 if (namerec->data.source == WINS_PROXY_NAME) {
00500 for( i = 0; i < namerec->data.num_ips; i++) {
00501 if (same_net(namerec->data.ip[i], subrec->myip, subrec->mask_ip)) {
00502 DEBUG(5,("process_name_query_request: name %s is a WINS proxy name and is also on the same subnet (%s) as the requestor. Not replying.\n",
00503 nmb_namestr(&namerec->name), subrec->subnet_name ));
00504 return;
00505 }
00506 }
00507 }
00508
00509 ttl = (namerec->data.death_time != PERMANENT_TTL) ?
00510 namerec->data.death_time - p->timestamp : lp_max_ttl();
00511
00512
00513
00514
00515
00516 if (namerec->data.num_ips == 1) {
00517 prdata = rdata;
00518 } else {
00519 if ((prdata = (char *)SMB_MALLOC( namerec->data.num_ips * 6 )) == NULL) {
00520 DEBUG(0,("process_name_query_request: malloc fail !\n"));
00521 return;
00522 }
00523 }
00524
00525 for (i = 0; i < namerec->data.num_ips; i++) {
00526 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
00527 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
00528 }
00529
00530 sort_query_replies(prdata, i, p->ip);
00531
00532 reply_data_len = namerec->data.num_ips * 6;
00533 success = True;
00534 }
00535 }
00536
00537
00538
00539
00540
00541
00542
00543 if(!success && (namerec == NULL) && we_are_a_wins_client() && lp_wins_proxy() &&
00544 bcast && (subrec != remote_broadcast_subnet)) {
00545 make_wins_proxy_name_query_request( subrec, p, question );
00546 return;
00547 }
00548
00549 if (!success && bcast) {
00550 if(prdata != rdata)
00551 SAFE_FREE(prdata);
00552 return;
00553 }
00554
00555
00556
00557
00558
00559
00560
00561 if(!success && !bcast && nmb->header.nm_flags.recursion_desired) {
00562 if(prdata != rdata)
00563 SAFE_FREE(prdata);
00564 return;
00565 }
00566
00567 if (success) {
00568 rcode = 0;
00569 DEBUG(3,("OK\n"));
00570 } else {
00571 rcode = NAM_ERR;
00572 DEBUG(3,("UNKNOWN\n"));
00573 }
00574
00575
00576
00577 reply_netbios_packet(p,
00578 rcode,
00579 NMB_QUERY,
00580 NMB_NAME_QUERY_OPCODE,
00581 ttl,
00582 prdata,
00583 reply_data_len);
00584
00585 if(prdata != rdata)
00586 SAFE_FREE(prdata);
00587 }