static void register_name_timeout_response(struct subnet_record *subrec, struct response_record *rrec) { /* * If we are registering unicast, then NOT getting a response is an * error - we do not have the name. If we are registering broadcast, * then we don't expect to get a response. */ struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; bool bcast = sent_nmb->header.nm_flags.bcast; bool success = False; struct nmb_name *question_name = &sent_nmb->question.question_name; uint16_t nb_flags = 0; int ttl = 0; struct in_addr registered_ip; if (bcast) { if(rrec->num_msgs == 0) { /* Not receiving a message is success for broadcast registration. */ success = True; /* Pull the success values from the original request packet. */ nb_flags = get_nb_flags(sent_nmb->additional->rdata); ttl = sent_nmb->additional->ttl; putip(®istered_ip,&sent_nmb->additional->rdata[2]); } } else { /* wins timeouts are special */ wins_registration_timeout(subrec, rrec); return; } DEBUG(5,("register_name_timeout_response: %s in registering name %s on subnet %s.\n", success ? "success" : "failure", nmb_namestr(question_name), subrec->subnet_name)); if(success) { /* Enter the registered name into the subnet name database before calling the success function. */ standard_success_register(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip); if( rrec->success_fn) (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip); } else { struct nmb_name qname = *question_name; if( rrec->fail_fn) (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name); /* Remove the name. */ standard_fail_register( subrec, &qname); } /* Ensure we don't retry. */ remove_response_record(subrec, rrec); }
static void register_name_response(struct subnet_record *subrec, struct response_record *rrec, struct packet_struct *p) { /* * If we are registering broadcast, then getting a response is an * error - we do not have the name. If we are registering unicast, * then we expect to get a response. */ struct nmb_packet *nmb = &p->packet.nmb; BOOL bcast = nmb->header.nm_flags.bcast; BOOL success = True; struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name; struct nmb_name *answer_name = &nmb->answers->rr_name; struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; int ttl = 0; uint16 nb_flags = 0; struct in_addr register_ip; fstring reg_name; putip(®ister_ip,&sent_nmb->additional->rdata[2]); fstrcpy(reg_name, inet_ntoa(register_ip)); if (subrec == unicast_subnet) { /* we know that this wins server is definately alive - for the moment! */ wins_srv_alive(rrec->packet->ip, register_ip); } /* Sanity check. Ensure that the answer name in the incoming packet is the same as the requested name in the outgoing packet. */ if(!question_name || !answer_name) { DEBUG(0,("register_name_response: malformed response (%s is NULL).\n", question_name ? "question_name" : "answer_name" )); return; } if(!nmb_name_equal(question_name, answer_name)) { DEBUG(0,("register_name_response: Answer name %s differs from question name %s.\n", nmb_namestr(answer_name), nmb_namestr(question_name))); return; } if(bcast) { /* * Special hack to cope with old Samba nmbd's. * Earlier versions of Samba (up to 1.9.16p11) respond * to a broadcast name registration of WORKGROUP<1b> when * they should not. Hence, until these versions are gone, * we should treat such errors as success for this particular * case only. [email protected]. */ #if 1 /* OLD_SAMBA_SERVER_HACK */ unstring ans_name; pull_ascii_nstring(ans_name, sizeof(ans_name), answer_name->name); if((nmb->header.rcode == ACT_ERR) && strequal(lp_workgroup(), ans_name) && (answer_name->name_type == 0x1b)) { /* Pretend we did not get this. */ rrec->num_msgs--; DEBUG(5,("register_name_response: Ignoring broadcast response to registration of name %s due to old Samba server bug.\n", nmb_namestr(answer_name))); return; } #endif /* OLD_SAMBA_SERVER_HACK */ /* Someone else has the name. Log the problem. */ 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", nmb_namestr(answer_name), reg_name, subrec->subnet_name, nmb->header.rcode, inet_ntoa(p->ip))); success = False; } else { /* Unicast - check to see if the response allows us to have the name. */ if (nmb->header.opcode == NMB_WACK_OPCODE) { /* WINS server is telling us to wait. Pretend we didn't get the response but don't send out any more register requests. */ DEBUG(5,("register_name_response: WACK from WINS server %s in registering name %s IP %s\n", inet_ntoa(p->ip), nmb_namestr(answer_name), reg_name)); rrec->repeat_count = 0; /* How long we should wait for. */ rrec->repeat_time = p->timestamp + nmb->answers->ttl; rrec->num_msgs--; return; } else if (nmb->header.rcode != 0) { /* Error code - we didn't get the name. */ success = False; DEBUG(0,("register_name_response: %sserver at IP %s rejected our name registration of %s IP %s with error code %d.\n", subrec==unicast_subnet?"WINS ":"", inet_ntoa(p->ip), nmb_namestr(answer_name), reg_name, nmb->header.rcode)); } else { success = True; /* Get the data we need to pass to the success function. */ nb_flags = get_nb_flags(nmb->answers->rdata); ttl = nmb->answers->ttl; /* send off a registration for the next IP, if any */ wins_next_registration(rrec); } } DEBUG(5,("register_name_response: %s in registering %sname %s IP %s with %s.\n", success ? "success" : "failure", subrec==unicast_subnet?"WINS ":"", nmb_namestr(answer_name), reg_name, inet_ntoa(rrec->packet->ip))); if(success) { /* Enter the registered name into the subnet name database before calling the success function. */ standard_success_register(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip); if( rrec->success_fn) (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip); } else { if( rrec->fail_fn) (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name); /* Remove the name. */ standard_fail_register( subrec, rrec, question_name); } /* Ensure we don't retry. */ remove_response_record(subrec, rrec); }