diff options
author | Andrew Tridgell <tridge@samba.org> | 1996-06-04 15:14:47 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 1996-06-04 15:14:47 +0000 |
commit | a2641cfe00b7857056fd8fd1e020aae7ea817690 (patch) | |
tree | 39bcd37ec9240fb1a285a50fb12303cb2a865363 /source3/nameserv.c | |
parent | 5607ff396c375976e440f9c955a313ddd58e3bbd (diff) | |
download | samba-a2641cfe00b7857056fd8fd1e020aae7ea817690.tar.gz samba-a2641cfe00b7857056fd8fd1e020aae7ea817690.tar.xz samba-a2641cfe00b7857056fd8fd1e020aae7ea817690.zip |
Did more integration of Lukes code ready for the first release.
I've now got WINS registration working, and refresh working. Its
looking pretty good so far, but needs lots of testing.
(This used to be commit 045014aa57721b9701ca379bcab055b908773184)
Diffstat (limited to 'source3/nameserv.c')
-rw-r--r-- | source3/nameserv.c | 1246 |
1 files changed, 628 insertions, 618 deletions
diff --git a/source3/nameserv.c b/source3/nameserv.c index 4cd9b099f0..176d955853 100644 --- a/source3/nameserv.c +++ b/source3/nameserv.c @@ -206,20 +206,20 @@ struct name_record *add_netbios_entry(char *name, int type, int nb_flags, int tt ****************************************************************************/ void remove_name_entry(char *name,int type) { - if (lp_wins_support()) - { - /* we are a WINS server. */ - remove_netbios_name(name,type,SELF,myip); - } - else - { - struct in_addr ip; - ip = ipzero; - - queue_netbios_pkt_wins(ClientNMB,NMB_REL,NAME_RELEASE, - name, type, 0, - False, True, ip); - } + if (lp_wins_support()) + { + /* we are a WINS server. */ + remove_netbios_name(name,type,SELF,myip); + } + else + { + struct in_addr ip; + ip = ipzero; + + queue_netbios_pkt_wins(ClientNMB,NMB_REL,NAME_RELEASE, + name, type, 0, + False, True, ip); + } } @@ -228,20 +228,18 @@ void remove_name_entry(char *name,int type) ****************************************************************************/ void add_name_entry(char *name,int type,int nb_flags) { - if (lp_wins_support()) - { - /* we are a WINS server. */ - add_netbios_entry(name,type,nb_flags,0,SELF,myip); - } - else - { - struct in_addr ip; - ip = ipzero; - - queue_netbios_pkt_wins(ClientNMB,NMB_REG,NAME_REGISTER, - name, type, nb_flags, - False, True, ip); - } + /* always add our own entries */ + add_netbios_entry(name,type,nb_flags,0,SELF,myip); + + if (!lp_wins_support()) + { + struct in_addr ip; + ip = ipzero; + + queue_netbios_pkt_wins(ClientNMB,NMB_REG,NAME_REGISTER, + name, type, nb_flags, + False, True, ip); + } } @@ -250,52 +248,67 @@ void add_name_entry(char *name,int type,int nb_flags) **************************************************************************/ void add_my_names(void) { - struct in_addr ip; + struct in_addr ip; - ip = ipzero; - - add_netbios_entry(myname,0x20,NB_ACTIVE,0,SELF,ip); - add_netbios_entry(myname,0x03,NB_ACTIVE,0,SELF,ip); - add_netbios_entry(myname,0x00,NB_ACTIVE,0,SELF,ip); - add_netbios_entry(myname,0x1f,NB_ACTIVE,0,SELF,ip); - add_netbios_entry("*",0x01,NB_ACTIVE,0,SELF,ip); - add_netbios_entry("__SAMBA__",0x20,NB_ACTIVE,0,SELF,ip); - add_netbios_entry("__SAMBA__",0x00,NB_ACTIVE,0,SELF,ip); - - if (lp_wins_support()) { - add_netbios_entry(inet_ntoa(myip),0x01,NB_ACTIVE,0,SELF,ip); /* nt as? */ - } + ip = ipzero; + + add_name_entry(myname,0x20,NB_ACTIVE); + add_name_entry(myname,0x03,NB_ACTIVE); + add_name_entry(myname,0x00,NB_ACTIVE); + add_name_entry(myname,0x1f,NB_ACTIVE); + + add_netbios_entry("*",0x0,NB_ACTIVE,0,SELF,ip); + add_netbios_entry("__SAMBA__",0x20,NB_ACTIVE,0,SELF,ip); + add_netbios_entry("__SAMBA__",0x00,NB_ACTIVE,0,SELF,ip); + + if (lp_wins_support()) { + add_netbios_entry(inet_ntoa(myip),0x01,NB_ACTIVE,0,SELF,ip); /* nt as? */ + } } /******************************************************************* - expires old names in the namelist + refresh my own names ******************************************************************/ -void expire_names(time_t t) +void refresh_my_names(time_t t) { - struct name_record *n; - struct name_record *next; - - /* expire old names */ - for (n = namelist; n; n = next) - { - if (n->death_time && n->death_time < t) - { - DEBUG(3,("Removing dead name %s\n", namestr(&n->name))); - - next = n->next; + static time_t lasttime = 0; - if (n->prev) n->prev->next = n->next; - if (n->next) n->next->prev = n->prev; + if (t - lasttime < REFRESH_TIME) + return; + lasttime = t; - if (namelist == n) namelist = n->next; + add_my_names(); +} - free(n); - } - else - { - next = n->next; - } +/******************************************************************* + expires old names in the namelist + ******************************************************************/ +void expire_names(time_t t) +{ + struct name_record *n; + struct name_record *next; + + /* expire old names */ + for (n = namelist; n; n = next) + { + if (n->death_time && n->death_time < t) + { + DEBUG(3,("Removing dead name %s\n", namestr(&n->name))); + + next = n->next; + + if (n->prev) n->prev->next = n->next; + if (n->next) n->next->prev = n->prev; + + if (namelist == n) namelist = n->next; + + free(n); } + else + { + next = n->next; + } + } } @@ -304,27 +317,27 @@ response for a reg release received **************************************************************************/ void response_name_release(struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - char *name = nmb->question.question_name.name; - int type = nmb->question.question_name.name_type; - - DEBUG(4,("response name release received\n")); - - if (nmb->header.rcode == 0 && nmb->answers->rdata) - { - struct in_addr found_ip; - putip((char*)&found_ip,&nmb->answers->rdata[2]); - - if (ip_equal(found_ip, myip)) - { - remove_netbios_name(name,type,SELF,found_ip); - } - } - else + struct nmb_packet *nmb = &p->packet.nmb; + char *name = nmb->question.question_name.name; + int type = nmb->question.question_name.name_type; + + DEBUG(4,("response name release received\n")); + + if (nmb->header.rcode == 0 && nmb->answers->rdata) + { + struct in_addr found_ip; + putip((char*)&found_ip,&nmb->answers->rdata[2]); + + if (ip_equal(found_ip, myip)) { - DEBUG(1,("name registration for %s rejected!\n", - namestr(&nmb->question.question_name))); + remove_netbios_name(name,type,SELF,found_ip); } + } + else + { + DEBUG(1,("name registration for %s rejected!\n", + namestr(&nmb->question.question_name))); + } } @@ -333,49 +346,49 @@ reply to a name release ****************************************************************************/ void reply_name_release(struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct in_addr ip; - int rcode=0; - int opcode = nmb->header.opcode; - int nb_flags = nmb->additional->rdata[0]; - BOOL bcast = nmb->header.nm_flags.bcast; - struct name_record *n; - char rdata[6]; - - putip((char *)&ip,&nmb->additional->rdata[2]); - - DEBUG(3,("Name release on name %s rcode=%d\n", + struct nmb_packet *nmb = &p->packet.nmb; + struct in_addr ip; + int rcode=0; + int opcode = nmb->header.opcode; + int nb_flags = nmb->additional->rdata[0]; + BOOL bcast = nmb->header.nm_flags.bcast; + struct name_record *n; + char rdata[6]; + + putip((char *)&ip,&nmb->additional->rdata[2]); + + DEBUG(3,("Name release on name %s rcode=%d\n", namestr(&nmb->question.question_name),rcode)); - - n = find_name_search(&nmb->question.question_name, FIND_GLOBAL, ip); - - /* XXXX under what conditions should we reject the removal?? */ - if (n && n->nb_flags == nb_flags && ip_equal(n->ip,ip)) - { - /* success = True; - rcode = 6; */ - - remove_name(n); - n = NULL; - } - - if (bcast) return; - - /*if (success)*/ - { - rdata[0] = nb_flags; - rdata[1] = 0; - putip(&rdata[2],(char *)&ip); - } - - /* Send a NAME RELEASE RESPONSE */ - reply_netbios_packet(p,nmb->header.name_trn_id,rcode,opcode, - &nmb->question.question_name, - nmb->question.question_type, - nmb->question.question_class, - 0, - rdata, 6 /*success ? 6 : 0*/); - /* XXXX reject packet never tested: cannot tell what to do */ + + n = find_name_search(&nmb->question.question_name, FIND_GLOBAL, ip); + + /* XXXX under what conditions should we reject the removal?? */ + if (n && n->nb_flags == nb_flags && ip_equal(n->ip,ip)) + { + /* success = True; + rcode = 6; */ + + remove_name(n); + n = NULL; + } + + if (bcast) return; + + /*if (success)*/ + { + rdata[0] = nb_flags; + rdata[1] = 0; + putip(&rdata[2],(char *)&ip); + } + + /* Send a NAME RELEASE RESPONSE */ + reply_netbios_packet(p,nmb->header.name_trn_id,rcode,opcode, + &nmb->question.question_name, + nmb->question.question_type, + nmb->question.question_class, + 0, + rdata, 6 /*success ? 6 : 0*/); + /* XXXX reject packet never tested: cannot tell what to do */ } @@ -384,30 +397,30 @@ response for a reg request received **************************************************************************/ void response_name_reg(struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - char *name = nmb->question.question_name.name; - int type = nmb->question.question_name.name_type; - - DEBUG(4,("response name registration received!\n")); - - if (nmb->header.rcode == 0 && nmb->answers->rdata) - { - int nb_flags = nmb->answers->rdata[0]; - struct in_addr found_ip; - int ttl = nmb->answers->ttl; - enum name_source source = REGISTER; - - putip((char*)&found_ip,&nmb->answers->rdata[2]); - - if (ip_equal(found_ip, myip)) source = SELF; - - add_netbios_entry(name,type,nb_flags,ttl,source,found_ip); - } - else - { - DEBUG(1,("name registration for %s rejected!\n", - namestr(&nmb->question.question_name))); - } + struct nmb_packet *nmb = &p->packet.nmb; + char *name = nmb->question.question_name.name; + int type = nmb->question.question_name.name_type; + + DEBUG(4,("response name registration received!\n")); + + if (nmb->header.rcode == 0 && nmb->answers->rdata) + { + int nb_flags = nmb->answers->rdata[0]; + struct in_addr found_ip; + int ttl = nmb->answers->ttl; + enum name_source source = REGISTER; + + putip((char*)&found_ip,&nmb->answers->rdata[2]); + + if (ip_equal(found_ip, myip)) source = SELF; + + add_netbios_entry(name,type,nb_flags,ttl,source,found_ip); + } + else + { + DEBUG(1,("name registration for %s rejected!\n", + namestr(&nmb->question.question_name))); + } } @@ -416,92 +429,92 @@ reply to a reg request **************************************************************************/ void reply_name_reg(struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - char *qname = nmb->question.question_name.name; - int name_type = nmb->question.question_name.name_type; - - BOOL bcast = nmb->header.nm_flags.bcast; - - int ttl = GET_TTL(nmb->additional->ttl); - int nb_flags = nmb->additional->rdata[0]; - BOOL group = (nb_flags&0x80); - int rcode = 0; - int opcode = nmb->header.opcode; - struct name_record *n = NULL; - int success = True; - char rdata[6]; - struct in_addr ip, from_ip; - - putip((char *)&from_ip,&nmb->additional->rdata[2]); - ip = from_ip; - - DEBUG(3,("Name registration for name %s at %s rcode=%d\n", - namestr(question),inet_ntoa(ip),rcode)); - - if (group) - { - /* apparently we should return 255.255.255.255 for group queries - (email from MS) */ - ip = *interpret_addr2("255.255.255.255"); - } - - /* see if the name already exists */ - n = find_name_search(question, FIND_GLOBAL, from_ip); - - if (n) - { - if (!group && !ip_equal(ip,n->ip) && question->name_type != 0x3) - { - if (n->source == SELF) - { - rcode = 6; - success = False; - } - else - { - n->ip = ip; - n->death_time = ttl?p->timestamp+ttl*3:0; - DEBUG(3,("%s changed owner to %s\n", - namestr(&n->name),inet_ntoa(n->ip))); - } - } - else - { - /* refresh the name */ - if (n->source != SELF) - { - n->death_time = ttl?p->timestamp + ttl*3:0; - } - } - } - else + struct nmb_packet *nmb = &p->packet.nmb; + struct nmb_name *question = &nmb->question.question_name; + char *qname = nmb->question.question_name.name; + int name_type = nmb->question.question_name.name_type; + + BOOL bcast = nmb->header.nm_flags.bcast; + + int ttl = GET_TTL(nmb->additional->ttl); + int nb_flags = nmb->additional->rdata[0]; + BOOL group = (nb_flags&0x80); + int rcode = 0; + int opcode = nmb->header.opcode; + struct name_record *n = NULL; + int success = True; + char rdata[6]; + struct in_addr ip, from_ip; + + putip((char *)&from_ip,&nmb->additional->rdata[2]); + ip = from_ip; + + DEBUG(3,("Name registration for name %s at %s rcode=%d\n", + namestr(question),inet_ntoa(ip),rcode)); + + if (group) + { + /* apparently we should return 255.255.255.255 for group queries + (email from MS) */ + ip = *interpret_addr2("255.255.255.255"); + } + + /* see if the name already exists */ + n = find_name_search(question, FIND_GLOBAL, from_ip); + + if (n) + { + if (!group && !ip_equal(ip,n->ip) && question->name_type != 0x3) { - /* add the name to our subnet/name database */ - n = add_netbios_entry(qname,name_type,nb_flags,ttl,REGISTER,ip); + if (n->source == SELF) + { + rcode = 6; + success = False; + } + else + { + n->ip = ip; + n->death_time = ttl?p->timestamp+ttl*3:0; + DEBUG(3,("%s changed owner to %s\n", + namestr(&n->name),inet_ntoa(n->ip))); + } } - - if (bcast) return; - - update_from_reg(nmb->question.question_name.name, - nmb->question.question_name.name_type, from_ip); - - /* XXXX don't know how to reject a name register: stick info in anyway - and guess that it doesn't matter if info is there! */ - /*if (success)*/ + else { - rdata[0] = nb_flags; - rdata[1] = 0; - putip(&rdata[2],(char *)&ip); + /* refresh the name */ + if (n->source != SELF) + { + n->death_time = ttl?p->timestamp + ttl*3:0; + } } - - /* Send a NAME REGISTRATION RESPONSE */ - reply_netbios_packet(p,nmb->header.name_trn_id,rcode,opcode, - &nmb->question.question_name, - nmb->question.question_type, - nmb->question.question_class, - ttl, - rdata, 6 /*success ? 6 : 0*/); + } + else + { + /* add the name to our subnet/name database */ + n = add_netbios_entry(qname,name_type,nb_flags,ttl,REGISTER,ip); + } + + if (bcast) return; + + update_from_reg(nmb->question.question_name.name, + nmb->question.question_name.name_type, from_ip); + + /* XXXX don't know how to reject a name register: stick info in anyway + and guess that it doesn't matter if info is there! */ + /*if (success)*/ + { + rdata[0] = nb_flags; + rdata[1] = 0; + putip(&rdata[2],(char *)&ip); + } + + /* Send a NAME REGISTRATION RESPONSE */ + reply_netbios_packet(p,nmb->header.name_trn_id,rcode,opcode, + &nmb->question.question_name, + nmb->question.question_type, + nmb->question.question_class, + ttl, + rdata, 6 /*success ? 6 : 0*/); } @@ -510,107 +523,107 @@ reply to a name status query ****************************************************************************/ void reply_name_status(struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - char *qname = nmb->question.question_name.name; - int ques_type = nmb->question.question_name.name_type; - BOOL wildcard = (qname[0] == '*'); - char rdata[MAX_DGRAM_SIZE]; - char *countptr, *buf; - int count, names_added; - struct name_record *n; - - DEBUG(3,("Name status for name %s %s\n", + struct nmb_packet *nmb = &p->packet.nmb; + char *qname = nmb->question.question_name.name; + int ques_type = nmb->question.question_name.name_type; + BOOL wildcard = (qname[0] == '*'); + char rdata[MAX_DGRAM_SIZE]; + char *countptr, *buf; + int count, names_added; + struct name_record *n; + + DEBUG(3,("Name status for name %s %s\n", namestr(&nmb->question.question_name), inet_ntoa(p->ip))); - - /* find a name: if it's a wildcard, search the entire database. - if not, search for source SELF names only */ - n = find_name_search(&nmb->question.question_name, - wildcard ? FIND_GLOBAL : FIND_SELF, p->ip); - - if (!wildcard && (!n || n->source != SELF)) return; - - for (count=0, n = namelist ; n; n = n->next) - { - int name_type = n->name.name_type; - - if (n->source != SELF) continue; - - if (name_type >= 0x1b && name_type <= 0x20 && - ques_type >= 0x1b && ques_type <= 0x20) - { - if (!strequal(qname, n->name.name)) continue; - } - - count++; - } - - /* XXXX hack, we should calculate exactly how many will fit */ - count = MIN(count,(sizeof(rdata) - 64) / 18); - - countptr = buf = rdata; - buf += 1; - - names_added = 0; - - for (n = namelist ; n && count >= 0; n = n->next) - { - int name_type = n->name.name_type; - - if (n->source != SELF) continue; - - /* start with first bit of putting info in buffer: the name */ - - bzero(buf,18); - StrnCpy(buf,n->name.name,15); - strupper(buf); - - /* now check if we want to exclude other workgroup names - from the response. if we don't exclude them, windows clients - get confused and will respond with an error for NET VIEW */ - - if (name_type >= 0x1b && name_type <= 0x20 && - ques_type >= 0x1b && ques_type <= 0x20) - { - if (!strequal(qname, n->name.name)) continue; - } - - /* carry on putting name info in buffer */ - - buf[15] = name_type; - buf[16] = n->nb_flags; - - buf += 18; - - count--; - names_added++; - } - - if (count < 0) + + /* find a name: if it's a wildcard, search the entire database. + if not, search for source SELF names only */ + n = find_name_search(&nmb->question.question_name, + wildcard ? FIND_GLOBAL : FIND_SELF, p->ip); + + if (!wildcard && (!n || n->source != SELF)) return; + + for (count=0, n = namelist ; n; n = n->next) + { + int name_type = n->name.name_type; + + if (n->source != SELF) continue; + + if (name_type >= 0x1b && name_type <= 0x20 && + ques_type >= 0x1b && ques_type <= 0x20) { - DEBUG(3, (("too many names: missing a few!\n"))); + if (!strequal(qname, n->name.name)) continue; } - - SCVAL(countptr,0,names_added); - - /* XXXXXXX we should fill in more fields of the statistics structure */ - bzero(buf,64); + + count++; + } + + /* XXXX hack, we should calculate exactly how many will fit */ + count = MIN(count,(sizeof(rdata) - 64) / 18); + + countptr = buf = rdata; + buf += 1; + + names_added = 0; + + for (n = namelist ; n && count >= 0; n = n->next) + { + int name_type = n->name.name_type; + + if (n->source != SELF) continue; + + /* start with first bit of putting info in buffer: the name */ + + bzero(buf,18); + StrnCpy(buf,n->name.name,15); + strupper(buf); + + /* now check if we want to exclude other workgroup names + from the response. if we don't exclude them, windows clients + get confused and will respond with an error for NET VIEW */ + + if (name_type >= 0x1b && name_type <= 0x20 && + ques_type >= 0x1b && ques_type <= 0x20) { - extern int num_good_sends,num_good_receives; - SIVAL(buf,20,num_good_sends); - SIVAL(buf,24,num_good_receives); + if (!strequal(qname, n->name.name)) continue; } - - SIVAL(buf,46,0xFFB8E5); /* undocumented - used by NT */ - - buf += 64; - - /* Send a POSITIVE NAME STATUS RESPONSE */ - reply_netbios_packet(p,nmb->header.name_trn_id,0,0, - &nmb->question.question_name, - nmb->question.question_type, - nmb->question.question_class, - 0, - rdata,PTR_DIFF(buf,rdata)); + + /* carry on putting name info in buffer */ + + buf[15] = name_type; + buf[16] = n->nb_flags; + + buf += 18; + + count--; + names_added++; + } + + if (count < 0) + { + DEBUG(3, (("too many names: missing a few!\n"))); + } + + SCVAL(countptr,0,names_added); + + /* XXXXXXX we should fill in more fields of the statistics structure */ + bzero(buf,64); + { + extern int num_good_sends,num_good_receives; + SIVAL(buf,20,num_good_sends); + SIVAL(buf,24,num_good_receives); + } + + SIVAL(buf,46,0xFFB8E5); /* undocumented - used by NT */ + + buf += 64; + + /* Send a POSITIVE NAME STATUS RESPONSE */ + reply_netbios_packet(p,nmb->header.name_trn_id,0,0, + &nmb->question.question_name, + nmb->question.question_type, + nmb->question.question_class, + 0, + rdata,PTR_DIFF(buf,rdata)); } @@ -620,73 +633,73 @@ reply to a name query struct name_record *search_for_name(struct nmb_name *question, struct in_addr ip, int Time, int search) { - int name_type = question->name_type; - char *qname = question->name; - BOOL dns_type = name_type == 0x20 || name_type == 0; - - struct name_record *n; - - DEBUG(3,("Search for %s from %s - ", namestr(question), inet_ntoa(ip))); - - /* first look up name in cache */ - n = find_name_search(question,search,ip); - - /* now try DNS lookup. */ - if (!n) - { - struct in_addr dns_ip; - unsigned long a; - - /* only do DNS lookups if the query is for type 0x20 or type 0x0 */ - if (!dns_type) - { - DEBUG(3,("types 0x20 0x1b 0x0 only: name not found\n")); - return NULL; - } - - /* look it up with DNS */ - a = interpret_addr(qname); - - putip((char *)&dns_ip,(char *)&a); - - if (!a) - { - /* no luck with DNS. We could possibly recurse here XXXX */ - /* if this isn't a bcast then we should send a negative reply XXXX */ - DEBUG(3,("no recursion\n")); - add_netbios_entry(qname,name_type,NB_ACTIVE,60*60,DNSFAIL,dns_ip); - return NULL; - } - - /* add it to our cache of names. give it 2 hours in the cache */ - n = add_netbios_entry(qname,name_type,NB_ACTIVE,2*60*60,DNS,dns_ip); - - /* failed to add it? yikes! */ - if (!n) return NULL; - } - - /* is our entry already dead? */ - if (n->death_time) + int name_type = question->name_type; + char *qname = question->name; + BOOL dns_type = name_type == 0x20 || name_type == 0; + + struct name_record *n; + + DEBUG(3,("Search for %s from %s - ", namestr(question), inet_ntoa(ip))); + + /* first look up name in cache */ + n = find_name_search(question,search,ip); + + /* now try DNS lookup. */ + if (!n) + { + struct in_addr dns_ip; + unsigned long a; + + /* only do DNS lookups if the query is for type 0x20 or type 0x0 */ + if (!dns_type) { - if (n->death_time < Time) return False; + DEBUG(3,("types 0x20 0x1b 0x0 only: name not found\n")); + return NULL; } - - /* it may have been an earlier failure */ - if (n->source == DNSFAIL) + + /* look it up with DNS */ + a = interpret_addr(qname); + + putip((char *)&dns_ip,(char *)&a); + + if (!a) { - DEBUG(3,("DNSFAIL\n")); - return NULL; + /* no luck with DNS. We could possibly recurse here XXXX */ + /* if this isn't a bcast then we should send a negative reply XXXX */ + DEBUG(3,("no recursion\n")); + add_netbios_entry(qname,name_type,NB_ACTIVE,60*60,DNSFAIL,dns_ip); + return NULL; } - - DEBUG(3,("OK %s\n",inet_ntoa(n->ip))); - - return n; + + /* add it to our cache of names. give it 2 hours in the cache */ + n = add_netbios_entry(qname,name_type,NB_ACTIVE,2*60*60,DNS,dns_ip); + + /* failed to add it? yikes! */ + if (!n) return NULL; + } + + /* is our entry already dead? */ + if (n->death_time) + { + if (n->death_time < Time) return False; + } + + /* it may have been an earlier failure */ + if (n->source == DNSFAIL) + { + DEBUG(3,("DNSFAIL\n")); + return NULL; + } + + DEBUG(3,("OK %s\n",inet_ntoa(n->ip))); + + return n; } /* XXXX i think we should only do this if we are a WINS proxy if (!n && bcast) { - // now try look up the name at the primary domain controller + // now try look up the name at the primary domain controller if (*lp_domain_controller()) { struct in_addr dom_ip; @@ -729,78 +742,80 @@ with directed name queries: ****************************************************************************/ extern void reply_name_query(struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - int name_type = question->name_type; - BOOL dns_type = name_type == 0x20 || name_type == 0; - BOOL bcast = nmb->header.nm_flags.bcast; - int ttl=0; - int rcode = 0; - int nb_flags = 0; - struct in_addr retip; - char rdata[6]; - - struct in_addr gp_ip = *interpret_addr2("255.255.255.255"); - BOOL success = True; - - struct name_record *n; - enum name_search search = dns_type || name_type == 0x1b ? - FIND_GLOBAL : FIND_SELF; - - DEBUG(3,("Name query ")); - - if ((n = search_for_name(question,p->ip,p->timestamp, search))) - { - /* don't respond to broadcast queries unless the query is for - a name we own or it is for a Primary Domain Controller name */ - if (bcast && n->source != SELF && name_type != 0x1b) - { - /* never reply with a negative response to broadcast queries */ - return; - } - - /* name is directed query, or it's self, or it's a PDC type name */ - ttl = n->death_time - p->timestamp; - retip = n->ip; - nb_flags = n->nb_flags; - } - else - { - if (bcast) return; /* never reply negative response to bcasts */ - success = False; - } - - /* if asking for a group name (type 0x1e) return 255.255.255.255 */ - if (ip_equal(retip, gp_ip) && name_type == 0x1e) retip = gp_ip; - - /* if the IP is 0 then substitute my IP - we should see which one is on the - right interface for the caller to do this right XXX */ - if (zero_ip(retip)) retip = myip; - - if (success) - { - rcode = 0; - DEBUG(3,("OK %s\n",inet_ntoa(retip))); - } - else - { - rcode = 3; - DEBUG(3,("UNKNOWN\n")); - } - - if (success) + struct nmb_packet *nmb = &p->packet.nmb; + struct nmb_name *question = &nmb->question.question_name; + int name_type = question->name_type; + BOOL dns_type = name_type == 0x20 || name_type == 0; + BOOL bcast = nmb->header.nm_flags.bcast; + int ttl=0; + int rcode = 0; + int nb_flags = 0; + struct in_addr retip; + char rdata[6]; + + struct in_addr gp_ip = *interpret_addr2("255.255.255.255"); + BOOL success = True; + + struct name_record *n; + enum name_search search = dns_type || name_type == 0x1b ? + FIND_GLOBAL : FIND_SELF; + + DEBUG(3,("Name query ")); + + if ((n = search_for_name(question,p->ip,p->timestamp, search))) + { + /* don't respond to broadcast queries unless the query is for + a name we own or it is for a Primary Domain Controller name */ + if (bcast && n->source != SELF && name_type != 0x1b) { - rdata[0] = nb_flags; - rdata[1] = 0; - putip(&rdata[2],(char *)&retip); + if (!lp_wins_proxy() || same_net(p->ip,n->ip,Netmask)) { + /* never reply with a negative response to broadcast queries */ + return; + } } - - reply_netbios_packet(p,nmb->header.name_trn_id,rcode,0, - &nmb->question.question_name, - nmb->question.question_type, - nmb->question.question_class, - ttl, - rdata, success ? 6 : 0); + + /* we will reply */ + ttl = n->death_time - p->timestamp; + retip = n->ip; + nb_flags = n->nb_flags; + } + else + { + if (bcast) return; /* never reply negative response to bcasts */ + success = False; + } + + /* if asking for a group name (type 0x1e) return 255.255.255.255 */ + if (ip_equal(retip, gp_ip) && name_type == 0x1e) retip = gp_ip; + + /* if the IP is 0 then substitute my IP - we should see which one is on the + right interface for the caller to do this right XXX */ + if (zero_ip(retip)) retip = myip; + + if (success) + { + rcode = 0; + DEBUG(3,("OK %s\n",inet_ntoa(retip))); + } + else + { + rcode = 3; + DEBUG(3,("UNKNOWN\n")); + } + + if (success) + { + rdata[0] = nb_flags; + rdata[1] = 0; + putip(&rdata[2],(char *)&retip); + } + + reply_netbios_packet(p,nmb->header.name_trn_id,rcode,0, + &nmb->question.question_name, + nmb->question.question_type, + nmb->question.question_class, + ttl, + rdata, success ? 6 : 0); } @@ -809,174 +824,169 @@ response from a name query ****************************************************************************/ static void response_netbios_packet(struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - char *qname = question->name; - BOOL bcast = nmb->header.nm_flags.bcast; - struct name_response_record *n; - - if (nmb->answers == NULL) - { - DEBUG(3,("NMB packet response from %s (bcast=%s) - UNKNOWN\n", - inet_ntoa(p->ip), - BOOLSTR(bcast))); - return; - } - - if (nmb->answers->rr_type == NMB_STATUS) - { - DEBUG(3,("Name status ")); - } - - if (nmb->answers->rr_type == NMB_QUERY) - { - DEBUG(3,("Name query ")); - } - - if (nmb->answers->rr_type == NMB_REG) - { - DEBUG(3,("Name registration ")); - } - - if (nmb->answers->rr_type == NMB_REL) - { - DEBUG(3,("Name release ")); - } - - DEBUG(3,("response for %s from %s (bcast=%s)\n", - namestr(&nmb->answers->rr_name), - inet_ntoa(p->ip), - BOOLSTR(bcast))); - - if (!(n = find_name_query(nmb->header.name_trn_id))) - { - DEBUG(3,("unknown response (received too late or from nmblookup?)\n")); - return; - } - - n->num_msgs++; /* count number of responses received */ - - switch (n->cmd_type) - { - case MASTER_SERVER_CHECK : DEBUG(4,("MASTER_SVR_CHECK\n")); break; - case SERVER_CHECK : DEBUG(4,("SERVER_CHECK\n")); break; - case FIND_MASTER : DEBUG(4,("FIND_MASTER\n")); break; - case NAME_STATUS_MASTER_CHECK: DEBUG(4,("NAME_STAT_MST_CHK\n")); break; - case NAME_STATUS_CHECK : DEBUG(4,("NAME_STATUS_CHECK\n")); break; - case CHECK_MASTER : DEBUG(4,("CHECK_MASTER\n")); break; - case NAME_CONFIRM_QUERY : DEBUG(4,("NAME_CONFIRM_QUERY\n")); break; - default: break; - } - switch (n->cmd_type) - { - case MASTER_SERVER_CHECK: - case SERVER_CHECK: - case FIND_MASTER: - { - if (nmb->answers->rr_type == NMB_QUERY) - { - enum cmd_type cmd = (n->cmd_type == MASTER_SERVER_CHECK) ? - NAME_STATUS_MASTER_CHECK : - NAME_STATUS_CHECK; - if (n->num_msgs > 1 && !strequal(qname,n->name.name)) - { - /* one subnet, one master browser per workgroup */ - /* XXXX force an election? */ - DEBUG(1,("more than one master browser replied!\n")); - } - - /* initiate a name status check on the server that replied */ - queue_netbios_packet(ClientNMB,NMB_STATUS, cmd, - nmb->answers->rr_name.name, - nmb->answers->rr_name.name_type,0, - False,False,n->to_ip); - } - else - { - DEBUG(1,("Name query reply has wrong answer rr_type\n")); - } - break; - } + struct nmb_packet *nmb = &p->packet.nmb; + struct nmb_name *question = &nmb->question.question_name; + char *qname = question->name; + BOOL bcast = nmb->header.nm_flags.bcast; + struct name_response_record *n; + + if (nmb->answers == NULL) + { + DEBUG(3,("NMB packet response from %s (bcast=%s) - UNKNOWN\n", + inet_ntoa(p->ip), + BOOLSTR(bcast))); + return; + } + + if (nmb->answers->rr_type == NMB_STATUS) { + DEBUG(3,("Name status ")); + } - case NAME_STATUS_MASTER_CHECK: - case NAME_STATUS_CHECK: - { - if (nmb->answers->rr_type == NMB_STATUS) - { - /* NMB_STATUS arrives: contains the workgroup name - and server name we require */ - struct nmb_name name; - fstring serv_name; + if (nmb->answers->rr_type == NMB_QUERY) { + DEBUG(3,("Name query ")); + } - if (interpret_node_status(nmb->answers->rdata, - &name,0x1d,serv_name,n->to_ip)) - { - if (*serv_name) - { - sync_server(n->cmd_type,serv_name, - name.name,name.name_type, - n->to_ip); - } - } - else - { - DEBUG(1,("No 0x1d name type in interpret_node_status()\n")); - } - } - else - { - DEBUG(1,("Name status reply has wrong answer rr_type\n")); - } - break; - } + if (nmb->answers->rr_type == NMB_REG) { + DEBUG(3,("Name registration ")); + } - case CHECK_MASTER: - { - /* no action required here. it's when NO responses are received - that we need to do something (see expire_name_query_entries) */ + if (nmb->answers->rr_type == NMB_REL) { + DEBUG(3,("Name release ")); + } - DEBUG(4, ("Master browser exists for %s at %s\n", - namestr(&n->name), - inet_ntoa(n->to_ip))); - if (n->num_msgs > 1) - { - DEBUG(1,("more than one master browser!\n")); - } - if (nmb->answers->rr_type != NMB_QUERY) - { - DEBUG(1,("Name query reply has wrong answer rr_type\n")); - } - break; - } - case NAME_CONFIRM_QUERY: - { - DEBUG(4, ("Name query at WINS server: %s at %s - ", - namestr(&n->name), - inet_ntoa(n->to_ip))); - if (nmb->header.rcode == 0 && nmb->answers->rdata) - { - int nb_flags = nmb->answers->rdata[0]; - struct in_addr found_ip; - putip((char*)&found_ip,&nmb->answers->rdata[2]); - - DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip))); - add_netbios_entry(nmb->answers->rr_name.name, - nmb->answers->rr_name.name_type, - nb_flags,GET_TTL(0),STATUS_QUERY,found_ip); - } - else - { - DEBUG(4, (" NEGATIVE RESPONSE\n")); - } + DEBUG(3,("response for %s from %s (bcast=%s)\n", + namestr(&nmb->answers->rr_name), + inet_ntoa(p->ip), + BOOLSTR(bcast))); + + if (!(n = find_name_query(nmb->header.name_trn_id))) { + DEBUG(3,("unknown response (received too late or from nmblookup?)\n")); + return; + } - break; - } - default: - { - DEBUG(0,("unknown command received in response_netbios_packet\n")); - break; - } - } + n->num_msgs++; /* count number of responses received */ + + switch (n->cmd_type) + { + case MASTER_SERVER_CHECK : DEBUG(4,("MASTER_SVR_CHECK\n")); break; + case SERVER_CHECK : DEBUG(4,("SERVER_CHECK\n")); break; + case FIND_MASTER : DEBUG(4,("FIND_MASTER\n")); break; + case NAME_STATUS_MASTER_CHECK: DEBUG(4,("NAME_STAT_MST_CHK\n")); break; + case NAME_STATUS_CHECK : DEBUG(4,("NAME_STATUS_CHECK\n")); break; + case CHECK_MASTER : DEBUG(4,("CHECK_MASTER\n")); break; + case NAME_CONFIRM_QUERY : DEBUG(4,("NAME_CONFIRM_QUERY\n")); break; + default: break; + } + switch (n->cmd_type) + { + case MASTER_SERVER_CHECK: + case SERVER_CHECK: + case FIND_MASTER: + { + if (nmb->answers->rr_type == NMB_QUERY) + { + enum cmd_type cmd = (n->cmd_type == MASTER_SERVER_CHECK) ? + NAME_STATUS_MASTER_CHECK : + NAME_STATUS_CHECK; + if (n->num_msgs > 1 && !strequal(qname,n->name.name)) + { + /* one subnet, one master browser per workgroup */ + /* XXXX force an election? */ + DEBUG(1,("more than one master browser replied!\n")); + } + + /* initiate a name status check on the server that replied */ + queue_netbios_packet(ClientNMB,NMB_STATUS, cmd, + nmb->answers->rr_name.name, + nmb->answers->rr_name.name_type,0, + False,False,n->to_ip); + } + else + { + DEBUG(1,("Name query reply has wrong answer rr_type\n")); + } + break; + } + + case NAME_STATUS_MASTER_CHECK: + case NAME_STATUS_CHECK: + { + if (nmb->answers->rr_type == NMB_STATUS) + { + /* NMB_STATUS arrives: contains the workgroup name + and server name we require */ + struct nmb_name name; + fstring serv_name; + + if (interpret_node_status(nmb->answers->rdata, + &name,0x1d,serv_name,n->to_ip)) + { + if (*serv_name) + { + sync_server(n->cmd_type,serv_name, + name.name,name.name_type, + n->to_ip); + } + } + else + { + DEBUG(1,("No 0x1d name type in interpret_node_status()\n")); + } + } + else + { + DEBUG(1,("Name status reply has wrong answer rr_type\n")); + } + break; + } + + case CHECK_MASTER: + { + /* no action required here. it's when NO responses are received + that we need to do something (see expire_name_query_entries) */ + + DEBUG(4, ("Master browser exists for %s at %s\n", + namestr(&n->name), + inet_ntoa(n->to_ip))); + if (n->num_msgs > 1) + { + DEBUG(1,("more than one master browser!\n")); + } + if (nmb->answers->rr_type != NMB_QUERY) + { + DEBUG(1,("Name query reply has wrong answer rr_type\n")); + } + break; + } + case NAME_CONFIRM_QUERY: + { + DEBUG(4, ("Name query at WINS server: %s at %s - ", + namestr(&n->name), + inet_ntoa(n->to_ip))); + if (nmb->header.rcode == 0 && nmb->answers->rdata) + { + int nb_flags = nmb->answers->rdata[0]; + struct in_addr found_ip; + putip((char*)&found_ip,&nmb->answers->rdata[2]); + + DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip))); + add_netbios_entry(nmb->answers->rr_name.name, + nmb->answers->rr_name.name_type, + nb_flags,GET_TTL(0),STATUS_QUERY,found_ip); + } + else + { + DEBUG(4, (" NEGATIVE RESPONSE\n")); + } + + break; + } + default: + { + DEBUG(0,("unknown command received in response_netbios_packet\n")); + break; + } + } } |