summaryrefslogtreecommitdiff
path: root/source3/nameserv.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/nameserv.c')
-rw-r--r--source3/nameserv.c1246
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;
+ }
+ }
}