From 5a2f52b79e28530c454cb488a44588147640f061 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 2 Oct 1996 14:09:22 +0000 Subject: - a huge pile of changes from Luke which implement the browse.conf stuff and also fix a pile of nmbd bugs. Unfortunately I found it very hard to disentangle the new features from the bug fixes so I am putting in the new code. I hope this is the last big pile of changes to the 1.9.16 series! (This used to be commit 20b6203dac4bbb43e4e7bea0b214496d76d679d9) --- source3/namedbname.c | 283 ++++++++++++++++++++++++++++----------------------- 1 file changed, 158 insertions(+), 125 deletions(-) (limited to 'source3/namedbname.c') diff --git a/source3/namedbname.c b/source3/namedbname.c index 1f16553b0f..f084424a29 100644 --- a/source3/namedbname.c +++ b/source3/namedbname.c @@ -27,6 +27,10 @@ 04 jul 96: lkcl@pires.co.uk created module namedbname containing name database functions + + 30 July 96: David.Chappell@mail.trincoll.edu + Expanded multiple workgroup domain master browser support. + */ #include "includes.h" @@ -43,6 +47,16 @@ extern struct subnet_record *subnetlist; uint16 nb_type = 0; /* samba's NetBIOS name type */ +static char *source_description[] = +{ + "STATUS_QUERY", + "LMHOSTS", + "REG", + "SELF", + "DNS", + "DNSFAIL" +}; + /**************************************************************************** samba's NetBIOS name type @@ -52,14 +66,14 @@ uint16 nb_type = 0; /* samba's NetBIOS name type */ ****************************************************************************/ void set_samba_nb_type(void) { - if (lp_wins_support() || (*lp_wins_server())) - { - nb_type = NB_MFLAG; /* samba is a 'hybrid' node type */ - } - else - { - nb_type = NB_BFLAG; /* samba is broadcast-only node type */ - } + if (lp_wins_support() || (*lp_wins_server())) + { + nb_type = NB_MFLAG; /* samba is a 'hybrid' node type */ + } + else + { + nb_type = NB_BFLAG; /* samba is broadcast-only node type */ + } } @@ -69,7 +83,7 @@ void set_samba_nb_type(void) BOOL name_equal(struct nmb_name *n1,struct nmb_name *n2) { return n1->name_type == n2->name_type && - strequal(n1->name ,n2->name ) && + strequal(n1->name ,n2->name ) && strequal(n1->scope,n2->scope); } @@ -140,22 +154,22 @@ void remove_name(struct subnet_record *d, struct name_record *n) find a name in a namelist. **************************************************************************/ struct name_record *find_name(struct name_record *n, - struct nmb_name *name, - int search) + struct nmb_name *name, + int search) { - struct name_record *ret; + struct name_record *ret; - for (ret = n; ret; ret = ret->next) - { - if (name_equal(&ret->name,name)) - { - /* self search: self names only */ - if ((search&FIND_SELF) == FIND_SELF && ret->source != SELF) - continue; - - return ret; - } - } + for (ret = n; ret; ret = ret->next) + { + if (name_equal(&ret->name,name)) + { + /* self search: self names only */ + if ((search&FIND_SELF) == FIND_SELF && ret->source != SELF) + continue; + + return ret; + } + } return NULL; } @@ -168,29 +182,31 @@ struct name_record *find_name(struct name_record *n, FIND_WINS - look for names in the WINS record **************************************************************************/ struct name_record *find_name_search(struct subnet_record **d, - struct nmb_name *name, - int search, struct in_addr ip) + struct nmb_name *name, + int search, struct in_addr ip) { - if (d == NULL) return NULL; /* bad error! */ - - if (search & FIND_LOCAL) { - if (*d != NULL) { - struct name_record *n = find_name((*d)->namelist, name, search); - DEBUG(4,("find_name on local: %s %s search %x\n", - namestr(name),inet_ntoa(ip), search)); - if (n) return n; - } + if (d == NULL) return NULL; /* bad error! */ + + if (search & FIND_LOCAL) + { + if (*d != NULL) + { + struct name_record *n = find_name((*d)->namelist, name, search); + DEBUG(4,("find_name on local: %s %s search %x\n", + namestr(name),inet_ntoa(ip), search)); + if (n) return n; + } } - if (!(search & FIND_WINS)) return NULL; + if ((search & FIND_WINS) != FIND_WINS) return NULL; /* find WINS subnet record. */ *d = find_subnet(ipgrp); - + if (*d == NULL) return NULL; - + DEBUG(4,("find_name on WINS: %s %s search %x\n", - namestr(name),inet_ntoa(ip), search)); + namestr(name),inet_ntoa(ip), search)); return find_name((*d)->namelist, name, search); } @@ -228,20 +244,18 @@ void dump_names(void) { int i; - DEBUG(3,("%15s ", inet_ntoa(d->bcast_ip))); - DEBUG(3,("%15s ", inet_ntoa(d->mask_ip))); - DEBUG(3,("%-19s TTL=%ld ", - namestr(&n->name), - n->death_time?n->death_time-t:0)); + DEBUG(3,("%-15s ", inet_ntoa(d->bcast_ip))); + DEBUG(3,("%-19s TTL=%7ld %s ", + namestr(&n->name), + n->death_time?n->death_time-t:0, source_description[n->source])); for (i = 0; i < n->num_ips; i++) { - DEBUG(3,("%15s NB=%2x source=%d", - inet_ntoa(n->ip_flgs[i].ip), - n->ip_flgs[i].nb_flags,n->source)); - + DEBUG(3,("%-15s NB=%2x ", + inet_ntoa(n->ip_flgs[i].ip), + (unsigned char)n->ip_flgs[i].nb_flags)); } - DEBUG(3,("\n")); + DEBUG(3,("\n")); if (f && ip_equal(d->bcast_ip, ipgrp) && n->source == REGISTER) { @@ -249,16 +263,16 @@ void dump_names(void) anything other than as a hexadecimal number :-) */ fprintf(f, "%s#%02x %ld ", - n->name.name,n->name.name_type, /* XXXX ignore scope for now */ - n->death_time); + n->name.name,n->name.name_type, /* XXXX ignore scope for now */ + n->death_time); for (i = 0; i < n->num_ips; i++) { fprintf(f, "%s %2x ", - inet_ntoa(n->ip_flgs[i].ip), - n->ip_flgs[i].nb_flags); + inet_ntoa(n->ip_flgs[i].ip), + (unsigned char)n->ip_flgs[i].nb_flags); } - fprintf(f, "\n"); + fprintf(f, "\n"); } } @@ -307,12 +321,12 @@ void load_netbios_names(void) int type = 0; unsigned int nb_flags; time_t ttd; - struct in_addr ipaddr; + struct in_addr ipaddr; - enum name_source source; + enum name_source source; char *ptr; - int count = 0; + int count = 0; char *p; @@ -320,20 +334,20 @@ void load_netbios_names(void) if (*line == '#') continue; - ptr = line; + ptr = line; - if (next_token(&ptr,name_str ,NULL)) ++count; - if (next_token(&ptr,ttd_str ,NULL)) ++count; - if (next_token(&ptr,ip_str ,NULL)) ++count; - if (next_token(&ptr,nb_flags_str,NULL)) ++count; + if (next_token(&ptr,name_str ,NULL)) ++count; + if (next_token(&ptr,ttd_str ,NULL)) ++count; + if (next_token(&ptr,ip_str ,NULL)) ++count; + if (next_token(&ptr,nb_flags_str,NULL)) ++count; - if (count <= 0) continue; + if (count <= 0) continue; - if (count != 4) { - DEBUG(0,("Ill formed wins line")); - DEBUG(0,("[%s]: name#type abs_time ip nb_flags\n",line)); - continue; - } + if (count != 4) { + DEBUG(0,("Ill formed wins line")); + DEBUG(0,("[%s]: name#type abs_time ip nb_flags\n",line)); + continue; + } /* netbios name. # divides the name from the type (hex): netbios#xx */ strcpy(name,name_str); @@ -341,15 +355,15 @@ void load_netbios_names(void) p = strchr(name,'#'); if (p) { - *p = 0; - sscanf(p+1,"%x",&type); + *p = 0; + sscanf(p+1,"%x",&type); } /* decode the netbios flags (hex) and the time-to-die (seconds) */ - sscanf(nb_flags_str,"%x",&nb_flags); - sscanf(ttd_str,"%ld",&ttd); + sscanf(nb_flags_str,"%x",&nb_flags); + sscanf(ttd_str,"%ld",&ttd); - ipaddr = *interpret_addr2(ip_str); + ipaddr = *interpret_addr2(ip_str); if (ip_equal(ipaddr,ipzero)) { source = SELF; @@ -360,7 +374,7 @@ void load_netbios_names(void) } DEBUG(4, ("add WINS line: %s#%02x %ld %s %2x\n", - name,type, ttd, inet_ntoa(ipaddr), nb_flags)); + name,type, ttd, inet_ntoa(ipaddr), nb_flags)); /* add all entries that have 60 seconds or more to live */ if (ttd - 60 > time(NULL) || ttd == 0) @@ -380,8 +394,8 @@ void load_netbios_names(void) remove an entry from the name list ****************************************************************************/ void remove_netbios_name(struct subnet_record *d, - char *name,int type, enum name_source source, - struct in_addr ip) + char *name,int type, enum name_source source, + struct in_addr ip) { struct nmb_name nn; struct name_record *n; @@ -405,14 +419,22 @@ void remove_netbios_name(struct subnet_record *d, ****************************************************************************/ struct name_record *add_netbios_entry(struct subnet_record *d, - char *name, int type, int nb_flags, - int ttl, enum name_source source, struct in_addr ip, - BOOL new_only,BOOL wins) + char *name, int type, int nb_flags, + int ttl, enum name_source source, struct in_addr ip, + BOOL new_only,BOOL wins) { struct name_record *n; struct name_record *n2=NULL; int search = 0; - BOOL self = source == SELF; + BOOL self; + + if (iface_ip(ip)) + { + source = SELF; + putip(&ip, &ipzero); + } + + self = source == SELF; /* add the name to the WINS list if the name comes from a directed query */ search |= wins ? FIND_WINS : FIND_LOCAL; @@ -465,46 +487,57 @@ struct name_record *add_netbios_entry(struct subnet_record *d, if (!n2) add_name(d,n); DEBUG(3,("Added netbios name %s at %s ttl=%d nb_flags=%2x\n", - namestr(&n->name),inet_ntoa(ip),ttl,nb_flags)); + namestr(&n->name),inet_ntoa(ip),ttl,nb_flags)); return(n); } /******************************************************************* - expires old names in the namelist + expires or refreshes old names in the namelist + + if the name is a samba SELF name, it must be refreshed rather than + removed. ******************************************************************/ -void expire_names(time_t t) +void check_expire_names(time_t t) { - struct name_record *n; - struct name_record *next; - struct subnet_record *d; - - /* expire old names */ - for (d = subnetlist; d; d = d->next) - { - for (n = d->namelist; n; n = next) - { - next = n->next; - if (n->death_time && n->death_time < t) - { - if (n->source == SELF) { - DEBUG(3,("not expiring SELF name %s\n", namestr(&n->name))); - n->death_time += 300; - continue; - } - DEBUG(3,("Removing dead name %s\n", namestr(&n->name))); - - if (n->prev) n->prev->next = n->next; - if (n->next) n->next->prev = n->prev; - - if (d->namelist == n) d->namelist = n->next; - - free(n->ip_flgs); - free(n); - } - } - } + struct name_record *n; + struct name_record *next; + struct subnet_record *d; + + /* expire old names */ + for (d = subnetlist; d; d = d->next) + { + for (n = d->namelist; n; n = next) + { + next = n->next; + + if (n->death_time && n->death_time < t) + { + if (n->source == SELF) + { + /* refresh the samba name. if this refresh fails + for any reason, it will be deleted. + */ + DEBUG(3,("Refreshing SELF name %s\n", namestr(&n->name))); + add_my_name_entry(d, -1, + n->name.name, n->name.name_type, + n->ip_flgs[0].nb_flags); + continue; + } + + DEBUG(3,("Removing dead name %s\n", namestr(&n->name))); + + if (n->prev) n->prev->next = n->next; + if (n->next) n->next->prev = n->prev; + + if (d->namelist == n) d->namelist = n->next; + + free(n->ip_flgs); + free(n); + } + } + } } @@ -512,8 +545,8 @@ void expire_names(time_t t) reply to a name query ****************************************************************************/ struct name_record *search_for_name(struct subnet_record **d, - struct nmb_name *question, - struct in_addr ip, int Time, int search) + struct nmb_name *question, + struct in_addr ip, int Time, int search) { int name_type = question->name_type; char *qname = question->name; @@ -538,10 +571,10 @@ struct name_record *search_for_name(struct subnet_record **d, /* only do DNS lookups if the query is for type 0x20 or type 0x0 */ if (!dns_type && name_type != 0x1b) - { - DEBUG(3,("types 0x20 0x1b 0x0 only: name not found\n")); - return NULL; - } + { + DEBUG(3,("types 0x20 0x1b 0x0 only: name not found\n")); + return NULL; + } /* look it up with DNS */ a = interpret_addr(qname); @@ -549,18 +582,18 @@ struct name_record *search_for_name(struct subnet_record **d, putip((char *)&dns_ip,(char *)&a); if (!a) - { - /* no luck with DNS. We could possibly recurse here XXXX */ - DEBUG(3,("no recursion.\n")); + { + /* no luck with DNS. We could possibly recurse here XXXX */ + DEBUG(3,("no recursion.\n")); /* add the fail to our WINS cache of names. give it 1 hour in the cache */ - add_netbios_entry(*d,qname,name_type,NB_ACTIVE,60*60,DNSFAIL,dns_ip, - True, True); - return NULL; - } + add_netbios_entry(*d,qname,name_type,NB_ACTIVE,60*60,DNSFAIL,dns_ip, + True, True); + return NULL; + } /* add it to our WINS cache of names. give it 2 hours in the cache */ n = add_netbios_entry(*d,qname,name_type,NB_ACTIVE,2*60*60,DNS,dns_ip, - True,True); + True,True); /* failed to add it? yikes! */ if (!n) return NULL; -- cgit