/* return the IP of the currently active wins server for the given tag, or the zero IP otherwise */ struct in_addr wins_srv_ip_tag(const char *tag, struct in_addr src_ip) { const char **list; int i; struct tagged_ip t_ip; /* if we are a wins server then we always just talk to ourselves */ if (lp_we_are_a_wins_server()) { struct in_addr loopback_ip; loopback_ip.s_addr = htonl(INADDR_LOOPBACK); return loopback_ip; } list = lp_wins_server_list(); if (!list || !list[0]) { struct in_addr ip; zero_ip_v4(&ip); return ip; } /* find the first live one for this tag */ for (i=0; list[i]; i++) { parse_ip(&t_ip, list[i]); if (strcmp(tag, t_ip.tag) != 0) { /* not for the right tag. Move along */ continue; } if (!wins_srv_is_dead(t_ip.ip, src_ip)) { fstring src_name; fstrcpy(src_name, inet_ntoa(src_ip)); DEBUG(6,("Current wins server for tag '%s' with source %s is %s\n", tag, src_name, inet_ntoa(t_ip.ip))); return t_ip.ip; } } /* they're all dead - try the first one until they revive */ for (i=0; list[i]; i++) { parse_ip(&t_ip, list[i]); if (strcmp(tag, t_ip.tag) != 0) { continue; } return t_ip.ip; } /* this can't happen?? */ zero_ip_v4(&t_ip.ip); return t_ip.ip; }
/* mark a wins server as temporarily dead */ void wins_srv_died(struct in_addr wins_ip, struct in_addr src_ip) { char *keystr; if (is_zero_ip_v4(wins_ip) || wins_srv_is_dead(wins_ip, src_ip)) return; keystr = wins_srv_keystr(wins_ip, src_ip); gencache_set(keystr, "DOWN", time(NULL) + DEATH_TIME); SAFE_FREE(keystr); DEBUG(4,("Marking wins server %s dead for %u seconds from source %s\n", inet_ntoa(wins_ip), DEATH_TIME, inet_ntoa(src_ip))); }
static void wins_registration_timeout(struct subnet_record *subrec, struct response_record *rrec) { struct userdata_struct *userdata = rrec->userdata; struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; struct nmb_name *nmbname = &sent_nmb->question.question_name; struct in_addr register_ip; fstring src_addr; putip(®ister_ip,&sent_nmb->additional->rdata[2]); fstrcpy(src_addr, inet_ntoa(register_ip)); DEBUG(2,("wins_registration_timeout: WINS server %s timed out registering IP %s\n", inet_ntoa(rrec->packet->ip), src_addr)); /* mark it temporarily dead for this source address */ wins_srv_died(rrec->packet->ip, register_ip); /* if we have some userdata then use that to work out what wins server to try next */ if (userdata) { const char *tag = (const char *)userdata->data; /* try the next wins server in our failover list for this tag */ rrec->packet->ip = wins_srv_ip_tag(tag, register_ip); } /* if we have run out of wins servers for this tag then they must all have timed out. We treat this as *success*, not failure, and go into our standard name refresh mode. This copes with all the wins servers being down */ if (wins_srv_is_dead(rrec->packet->ip, register_ip)) { uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata); int ttl = sent_nmb->additional->ttl; standard_success_register(subrec, userdata, nmbname, nb_flags, ttl, register_ip); if(rrec->success_fn) { (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, nmbname, nb_flags, ttl, register_ip); } /* send off a registration for the next IP, if any */ wins_next_registration(rrec); /* don't need to send this packet any more */ remove_response_record(subrec, rrec); return; } /* we will be moving to the next WINS server for this group, send it immediately */ rrec->repeat_count = 2; rrec->repeat_time = time(NULL) + 1; rrec->in_expiration_processing = False; DEBUG(6,("Retrying register of name %s IP %s with WINS server %s\n", nmb_namestr(nmbname), src_addr, inet_ntoa(rrec->packet->ip))); /* notice that we don't remove the response record. This keeps us trying to register with each of our failover wins servers */ }