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
00027 static void wins_next_registration(struct response_record *rrec);
00028
00029
00030
00031
00032
00033
00034 static void register_name_response(struct subnet_record *subrec,
00035 struct response_record *rrec, struct packet_struct *p)
00036 {
00037
00038
00039
00040
00041
00042
00043 struct nmb_packet *nmb = &p->packet.nmb;
00044 BOOL bcast = nmb->header.nm_flags.bcast;
00045 BOOL success = True;
00046 struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
00047 struct nmb_name *answer_name = &nmb->answers->rr_name;
00048 struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
00049 int ttl = 0;
00050 uint16 nb_flags = 0;
00051 struct in_addr register_ip;
00052 fstring reg_name;
00053
00054 putip(®ister_ip,&sent_nmb->additional->rdata[2]);
00055 fstrcpy(reg_name, inet_ntoa(register_ip));
00056
00057 if (subrec == unicast_subnet) {
00058
00059 wins_srv_alive(rrec->packet->ip, register_ip);
00060 }
00061
00062
00063
00064
00065 if(!question_name || !answer_name) {
00066 DEBUG(0,("register_name_response: malformed response (%s is NULL).\n",
00067 question_name ? "question_name" : "answer_name" ));
00068 return;
00069 }
00070
00071 if(!nmb_name_equal(question_name, answer_name)) {
00072 DEBUG(0,("register_name_response: Answer name %s differs from question name %s.\n",
00073 nmb_namestr(answer_name), nmb_namestr(question_name)));
00074 return;
00075 }
00076
00077 if(bcast) {
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 #if 1
00088 unstring ans_name;
00089 pull_ascii_nstring(ans_name, sizeof(ans_name), answer_name->name);
00090 if((nmb->header.rcode == ACT_ERR) && strequal(lp_workgroup(), ans_name) &&
00091 (answer_name->name_type == 0x1b)) {
00092
00093 rrec->num_msgs--;
00094
00095 DEBUG(5,("register_name_response: Ignoring broadcast response to registration of name %s due to old Samba server bug.\n",
00096 nmb_namestr(answer_name)));
00097 return;
00098 }
00099 #endif
00100
00101
00102 DEBUG(1,("register_name_response: Failed to register name %s IP %s on subnet %s via broadcast. Error code was %d. Reject came from IP %s\n",
00103 nmb_namestr(answer_name),
00104 reg_name,
00105 subrec->subnet_name, nmb->header.rcode, inet_ntoa(p->ip)));
00106 success = False;
00107 } else {
00108
00109 if (nmb->header.opcode == NMB_WACK_OPCODE) {
00110
00111
00112
00113 DEBUG(5,("register_name_response: WACK from WINS server %s in registering name %s IP %s\n",
00114 inet_ntoa(p->ip), nmb_namestr(answer_name), reg_name));
00115
00116 rrec->repeat_count = 0;
00117
00118 rrec->repeat_time = p->timestamp + nmb->answers->ttl;
00119 rrec->num_msgs--;
00120 return;
00121 } else if (nmb->header.rcode != 0) {
00122
00123 success = False;
00124
00125 DEBUG(0,("register_name_response: %sserver at IP %s rejected our name registration of %s IP %s with error code %d.\n",
00126 subrec==unicast_subnet?"WINS ":"",
00127 inet_ntoa(p->ip),
00128 nmb_namestr(answer_name),
00129 reg_name,
00130 nmb->header.rcode));
00131 } else {
00132 success = True;
00133
00134 nb_flags = get_nb_flags(nmb->answers->rdata);
00135 ttl = nmb->answers->ttl;
00136
00137
00138 wins_next_registration(rrec);
00139 }
00140 }
00141
00142 DEBUG(5,("register_name_response: %s in registering %sname %s IP %s with %s.\n",
00143 success ? "success" : "failure",
00144 subrec==unicast_subnet?"WINS ":"",
00145 nmb_namestr(answer_name),
00146 reg_name,
00147 inet_ntoa(rrec->packet->ip)));
00148
00149 if(success) {
00150
00151
00152 standard_success_register(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip);
00153 if( rrec->success_fn)
00154 (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip);
00155 } else {
00156 struct nmb_name qname = *question_name;
00157 if( rrec->fail_fn)
00158 (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
00159
00160 standard_fail_register( subrec, &qname);
00161 }
00162
00163
00164 remove_response_record(subrec, rrec);
00165 }
00166
00167
00168
00169
00170
00171 static void wins_registration_timeout(struct subnet_record *subrec,
00172 struct response_record *rrec)
00173 {
00174 struct userdata_struct *userdata = rrec->userdata;
00175 struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
00176 struct nmb_name *nmbname = &sent_nmb->question.question_name;
00177 struct in_addr register_ip;
00178 fstring src_addr;
00179
00180 putip(®ister_ip,&sent_nmb->additional->rdata[2]);
00181
00182 fstrcpy(src_addr, inet_ntoa(register_ip));
00183
00184 DEBUG(2,("wins_registration_timeout: WINS server %s timed out registering IP %s\n",
00185 inet_ntoa(rrec->packet->ip), src_addr));
00186
00187
00188 wins_srv_died(rrec->packet->ip, register_ip);
00189
00190
00191
00192 if (userdata) {
00193 const char *tag = (const char *)userdata->data;
00194
00195
00196
00197 rrec->packet->ip = wins_srv_ip_tag(tag, register_ip);
00198 }
00199
00200
00201
00202
00203
00204 if (wins_srv_is_dead(rrec->packet->ip, register_ip)) {
00205 uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
00206 int ttl = sent_nmb->additional->ttl;
00207
00208 standard_success_register(subrec, userdata, nmbname, nb_flags, ttl, register_ip);
00209 if(rrec->success_fn) {
00210 (*(register_name_success_function)rrec->success_fn)(subrec,
00211 rrec->userdata,
00212 nmbname,
00213 nb_flags,
00214 ttl,
00215 register_ip);
00216 }
00217
00218
00219 wins_next_registration(rrec);
00220
00221
00222 remove_response_record(subrec, rrec);
00223 return;
00224 }
00225
00226
00227
00228 rrec->repeat_count = 2;
00229 rrec->repeat_time = time(NULL) + 1;
00230 rrec->in_expiration_processing = False;
00231
00232 DEBUG(6,("Retrying register of name %s IP %s with WINS server %s\n",
00233 nmb_namestr(nmbname), src_addr, inet_ntoa(rrec->packet->ip)));
00234
00235
00236
00237 }
00238
00239
00240
00241
00242
00243 static void register_name_timeout_response(struct subnet_record *subrec,
00244 struct response_record *rrec)
00245 {
00246
00247
00248
00249
00250
00251
00252 struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
00253 BOOL bcast = sent_nmb->header.nm_flags.bcast;
00254 BOOL success = False;
00255 struct nmb_name *question_name = &sent_nmb->question.question_name;
00256 uint16 nb_flags = 0;
00257 int ttl = 0;
00258 struct in_addr registered_ip;
00259
00260 if (bcast) {
00261 if(rrec->num_msgs == 0) {
00262
00263 success = True;
00264
00265
00266 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
00267 ttl = sent_nmb->additional->ttl;
00268 putip(®istered_ip,&sent_nmb->additional->rdata[2]);
00269 }
00270 } else {
00271
00272 wins_registration_timeout(subrec, rrec);
00273 return;
00274 }
00275
00276 DEBUG(5,("register_name_timeout_response: %s in registering name %s on subnet %s.\n",
00277 success ? "success" : "failure", nmb_namestr(question_name), subrec->subnet_name));
00278 if(success) {
00279
00280
00281 standard_success_register(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
00282 if( rrec->success_fn)
00283 (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
00284 } else {
00285 struct nmb_name qname = *question_name;
00286 if( rrec->fail_fn)
00287 (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
00288
00289 standard_fail_register( subrec, &qname);
00290 }
00291
00292
00293 remove_response_record(subrec, rrec);
00294 }
00295
00296
00297
00298
00299
00300 static void multihomed_register_one(struct nmb_name *nmbname,
00301 uint16 nb_flags,
00302 register_name_success_function success_fn,
00303 register_name_fail_function fail_fn,
00304 struct in_addr ip,
00305 const char *tag)
00306 {
00307 struct userdata_struct *userdata;
00308 struct in_addr wins_ip = wins_srv_ip_tag(tag, ip);
00309 fstring ip_str;
00310
00311 userdata = (struct userdata_struct *)SMB_MALLOC(sizeof(*userdata) + strlen(tag) + 1);
00312 if (!userdata) {
00313 DEBUG(0,("Failed to allocate userdata structure!\n"));
00314 return;
00315 }
00316 ZERO_STRUCTP(userdata);
00317 userdata->userdata_len = strlen(tag) + 1;
00318 strlcpy(userdata->data, tag, userdata->userdata_len);
00319
00320 fstrcpy(ip_str, inet_ntoa(ip));
00321
00322 DEBUG(6,("Registering name %s IP %s with WINS server %s using tag '%s'\n",
00323 nmb_namestr(nmbname), ip_str, inet_ntoa(wins_ip), tag));
00324
00325 if (queue_register_multihomed_name(unicast_subnet,
00326 register_name_response,
00327 register_name_timeout_response,
00328 success_fn,
00329 fail_fn,
00330 userdata,
00331 nmbname,
00332 nb_flags,
00333 ip,
00334 wins_ip) == NULL) {
00335 DEBUG(0,("multihomed_register_one: Failed to send packet trying to register name %s IP %s\n",
00336 nmb_namestr(nmbname), inet_ntoa(ip)));
00337 }
00338
00339 free(userdata);
00340 }
00341
00342
00343
00344
00345
00346
00347 static void wins_next_registration(struct response_record *rrec)
00348 {
00349 struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
00350 struct nmb_name *nmbname = &sent_nmb->question.question_name;
00351 uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
00352 struct userdata_struct *userdata = rrec->userdata;
00353 const char *tag;
00354 struct in_addr last_ip;
00355 struct subnet_record *subrec;
00356
00357 putip(&last_ip,&sent_nmb->additional->rdata[2]);
00358
00359 if (!userdata) {
00360
00361 return;
00362 }
00363
00364 tag = (const char *)userdata->data;
00365
00366 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
00367 if (ip_equal(last_ip, subrec->myip)) {
00368 subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec);
00369 break;
00370 }
00371 }
00372
00373 if (!subrec) {
00374
00375 return;
00376 }
00377
00378 switch (sent_nmb->header.opcode) {
00379 case NMB_NAME_MULTIHOMED_REG_OPCODE:
00380 multihomed_register_one(nmbname, nb_flags, NULL, NULL, subrec->myip, tag);
00381 break;
00382 case NMB_NAME_REFRESH_OPCODE_8:
00383 queue_wins_refresh(nmbname,
00384 register_name_response,
00385 register_name_timeout_response,
00386 nb_flags, subrec->myip, tag);
00387 break;
00388 }
00389 }
00390
00391
00392
00393
00394
00395 static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags,
00396 register_name_success_function success_fn,
00397 register_name_fail_function fail_fn)
00398 {
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 int num_ips=0;
00419 int i, t;
00420 struct subnet_record *subrec;
00421 char **wins_tags;
00422 struct in_addr *ip_list;
00423 unstring name;
00424
00425 for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) )
00426 num_ips++;
00427
00428 if((ip_list = SMB_MALLOC_ARRAY(struct in_addr, num_ips))==NULL) {
00429 DEBUG(0,("multihomed_register_name: malloc fail !\n"));
00430 return;
00431 }
00432
00433 for (subrec = FIRST_SUBNET, i = 0;
00434 subrec;
00435 subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec), i++ ) {
00436 ip_list[i] = subrec->myip;
00437 }
00438
00439 pull_ascii_nstring(name, sizeof(name), nmbname->name);
00440 add_name_to_subnet(unicast_subnet, name, nmbname->name_type,
00441 nb_flags, lp_max_ttl(), SELF_NAME,
00442 num_ips, ip_list);
00443
00444
00445 wins_tags = wins_srv_tags();
00446
00447
00448
00449
00450
00451
00452
00453 for (t=0; wins_tags && wins_tags[t]; t++) {
00454 multihomed_register_one(nmbname, nb_flags,
00455 success_fn, fail_fn,
00456 ip_list[0],
00457 wins_tags[t]);
00458 }
00459
00460 wins_srv_tags_free(wins_tags);
00461
00462 SAFE_FREE(ip_list);
00463 }
00464
00465
00466
00467
00468
00469 void register_name(struct subnet_record *subrec,
00470 const char *name, int type, uint16 nb_flags,
00471 register_name_success_function success_fn,
00472 register_name_fail_function fail_fn,
00473 struct userdata_struct *userdata)
00474 {
00475 struct nmb_name nmbname;
00476 nstring nname;
00477
00478 errno = 0;
00479 push_ascii_nstring(nname, name);
00480 if (errno == E2BIG) {
00481 unstring tname;
00482 pull_ascii_nstring(tname, sizeof(tname), nname);
00483 DEBUG(0,("register_name: NetBIOS name %s is too long. Truncating to %s\n",
00484 name, tname));
00485 make_nmb_name(&nmbname, tname, type);
00486 } else {
00487 make_nmb_name(&nmbname, name, type);
00488 }
00489
00490
00491
00492
00493
00494 nb_flags |= NB_ACTIVE;
00495
00496 if (subrec == unicast_subnet) {
00497
00498
00499
00500 multihomed_register_name(&nmbname, nb_flags,
00501 success_fn, fail_fn);
00502 return;
00503 }
00504
00505 if (queue_register_name(subrec,
00506 register_name_response,
00507 register_name_timeout_response,
00508 success_fn,
00509 fail_fn,
00510 userdata,
00511 &nmbname,
00512 nb_flags) == NULL) {
00513 DEBUG(0,("register_name: Failed to send packet trying to register name %s\n",
00514 nmb_namestr(&nmbname)));
00515 }
00516 }
00517
00518
00519
00520
00521
00522 void wins_refresh_name(struct name_record *namerec)
00523 {
00524 int t;
00525 char **wins_tags;
00526
00527
00528 wins_tags = wins_srv_tags();
00529
00530 for (t=0; wins_tags && wins_tags[t]; t++) {
00531 queue_wins_refresh(&namerec->name,
00532 register_name_response,
00533 register_name_timeout_response,
00534 namerec->data.nb_flags,
00535 namerec->data.ip[0], wins_tags[t]);
00536 }
00537
00538 wins_srv_tags_free(wins_tags);
00539 }