Unix SMB/Netbios implementation.
Version 1.9.
NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1996
+ Copyright (C) Andrew Tridgell 1994-1997
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
extern pstring scope;
extern struct in_addr ipzero;
-extern struct in_addr ipgrp;
+extern struct in_addr wins_ip;
extern struct subnet_record *subnetlist;
#define WINS_LIST "wins.dat"
+uint16 nb_type = 0; /* samba's NetBIOS name type */
+
+
+/****************************************************************************
+ samba's NetBIOS name type
+
+ XXXX maybe functionality could be set: B, M, P or H name registration
+ and resolution could be set through nb_type. just a thought.
+ ****************************************************************************/
+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 */
+ }
+}
+
/****************************************************************************
true if two netbios names are equal
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;
{
/* self search: self names only */
if ((search&FIND_SELF) == FIND_SELF && ret->source != SELF)
+ {
continue;
-
+ }
+ DEBUG(9,("find_name: found name %s\n", name->name));
return ret;
}
}
+ DEBUG(9,("find_name: name %s NOT FOUND\n", name->name));
return NULL;
}
struct nmb_name *name,
int search, struct in_addr ip)
{
- if (d == NULL) return NULL; /* bad error! */
+ if (d == NULL) return NULL; /* bad error! */
- if ((search & FIND_LOCAL) == 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) != FIND_WINS) return NULL;
-
- /* find WINS subnet record. */
- *d = find_subnet(ipgrp);
+ 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;
+ if (!(search & FIND_WINS)) return NULL;
- DEBUG(4,("find_name on WINS: %s %s search %x\n",
- namestr(name),inet_ntoa(ip), search));
- return find_name((*d)->namelist, name, search);
+ /* find WINS subnet record. */
+ *d = wins_subnet;
+
+ if (*d == NULL) return NULL;
+
+ DEBUG(4,("find_name on WINS: %s %s search %x\n",
+ namestr(name),inet_ntoa(ip), search));
+ return find_name((*d)->namelist, name, search);
}
void dump_names(void)
{
struct name_record *n;
- struct subnet_record *d;
fstring fname, fnamenew;
time_t t = time(NULL);
FILE *f;
-
+
+ if(lp_wins_support() == False || wins_subnet == 0)
+ return;
+
strcpy(fname,lp_lockdir());
trim_string(fname,NULL,"/");
strcat(fname,"/");
if (!f)
{
- DEBUG(4,("Can't open %s - %s\n",fnamenew,strerror(errno)));
+ DEBUG(3,("Can't open %s - %s\n",fnamenew,strerror(errno)));
+ return;
}
- DEBUG(3,("Dump of local name table:\n"));
+ DEBUG(4,("Dump of WINS name table:\n"));
- for (d = subnetlist; d; d = d->next)
- for (n = d->namelist; n; n = n->next)
- {
- if (f && ip_equal(d->bcast_ip, ipgrp) && n->source == REGISTER)
+ for (n = wins_subnet->namelist; n; n = n->next)
+ {
+ int i;
+
+ DEBUG(4,("%15s ", inet_ntoa(wins_subnet->bcast_ip)));
+ DEBUG(4,("%15s ", inet_ntoa(wins_subnet->mask_ip)));
+ DEBUG(4,("%-19s TTL=%ld ",
+ namestr(&n->name),
+ n->death_time?n->death_time-t:0));
+
+ for (i = 0; i < n->num_ips; i++)
{
- fstring data;
+ DEBUG(4,("%15s NB=%2x source=%d",
+ inet_ntoa(n->ip_flgs[i].ip),
+ n->ip_flgs[i].nb_flags,n->source));
+ }
+ DEBUG(4,("\n"));
+
+ if (f && n->source == REGISTER)
+ {
/* XXXX i have little imagination as to how to output nb_flags as
anything other than as a hexadecimal number :-) */
- sprintf(data, "%s#%02x %s %2x %ld",
+ fprintf(f, "%s#%02x %ld ",
n->name.name,n->name.name_type, /* XXXX ignore scope for now */
- inet_ntoa(n->ip),
- n->nb_flags,
n->death_time);
- fprintf(f, "%s\n", data);
+
+ 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);
+ }
+ fprintf(f, "\n");
}
- DEBUG(3,("%15s ", inet_ntoa(d->bcast_ip)));
- DEBUG(3,("%15s ", inet_ntoa(d->mask_ip)));
- DEBUG(3,("%-19s %15s NB=%2x TTL=%ld \n",
- namestr(&n->name),
- inet_ntoa(n->ip),
- n->nb_flags,
- n->death_time?n->death_time-t:0));
- }
+ }
fclose(f);
unlink(fname);
/****************************************************************************
-load a netbios name database file
-****************************************************************************/
+ load a netbios name database file
+
+ XXXX we cannot cope with loading Internet Group names, yet
+ ****************************************************************************/
void load_netbios_names(void)
{
- struct subnet_record *d = find_subnet(ipgrp);
+ struct subnet_record *d = wins_subnet;
fstring fname;
FILE *f;
pstring name;
int type = 0;
- int nb_flags;
+ unsigned int nb_flags;
time_t ttd;
struct in_addr ipaddr;
ptr = line;
if (next_token(&ptr,name_str ,NULL)) ++count;
- if (next_token(&ptr,ip_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 != 4) {
DEBUG(0,("Ill formed wins line"));
- DEBUG(0,("[%s]: name#type ip nb_flags abs_time\n",line));
+ DEBUG(0,("[%s]: name#type abs_time ip nb_flags\n",line));
continue;
}
source = REGISTER;
}
- DEBUG(4, ("add WINS line: %s#%02x %s %ld %2x\n",
- name,type, inet_ntoa(ipaddr), ttd, nb_flags));
+ DEBUG(4, ("add WINS line: %s#%02x %ld %s %2x\n",
+ 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)
+ if (ttd - 60 > time(NULL) || ttd == 0)
{
time_t t = (ttd?ttd-time(NULL):0) / 3;
{
struct name_record *n;
struct name_record *n2=NULL;
+ struct subnet_record *found_subnet = 0;
int search = 0;
BOOL self = source == SELF;
/* add the name to the WINS list if the name comes from a directed query */
search |= wins ? FIND_WINS : FIND_LOCAL;
+
+ /* If it's a local search then we need to set the subnet
+ we are looking at. */
+ if(search & FIND_LOCAL)
+ found_subnet = d;
+
/* search for SELF names only */
search |= self ? FIND_SELF : 0;
if (!wins && type != 0x1b)
{
/* the only broadcast (non-WINS) names we are adding are ours
- (SELF) and PDC type names */
+ (SELF) and Domain Master type names */
return NULL;
}
}
bzero((char *)n,sizeof(*n));
+ n->num_ips = 1; /* XXXX ONLY USE THIS FUNCTION FOR ONE ENTRY */
+ n->ip_flgs = (struct nmb_ip*)malloc(sizeof(*n->ip_flgs) * n->num_ips);
+ if (!n->ip_flgs)
+ {
+ free(n);
+ return NULL;
+ }
+
make_nmb_name(&n->name,name,type,scope);
- if ((n2 = find_name_search(&d, &n->name, search, new_only?ipzero:ip)))
+ if ((n2 = find_name_search(&found_subnet, &n->name, search, new_only?ipzero:ip)))
{
+ free(n->ip_flgs);
free(n);
if (new_only || (n2->source==SELF && source!=SELF)) return n2;
n = n2;
+ d = found_subnet;
}
if (ttl)
n->death_time = time(NULL)+ttl*3;
n->refresh_time = time(NULL)+GET_TTL(ttl);
- n->ip = ip;
- n->nb_flags = nb_flags;
+ /* XXXX only one entry expected with this function */
+ n->ip_flgs[0].ip = ip;
+ n->ip_flgs[0].nb_flags = nb_flags;
+
n->source = source;
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));
+ DEBUG(3,("Added netbios name %s at %s ttl=%d nb_flags=%2x to interface %s\n",
+ namestr(&n->name),inet_ntoa(ip),ttl,nb_flags,
+ ip_equal(d->bcast_ip, wins_ip) ? "WINS" : (char *)inet_ntoa(d->bcast_ip)));
return(n);
}
struct subnet_record *d;
/* expire old names */
- for (d = subnetlist; d; d = d->next)
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
{
for (n = d->namelist; n; n = next)
+ {
+ next = n->next;
+ if (n->death_time && n->death_time < t)
{
- 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)));
- next = n->next;
-
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);
}
- else
- {
- next = n->next;
- }
- }
+ }
}
}
/***************************************************************************
- reply to a name query
+ assume a WINS name is a dns name, and do a gethostbyname() on it.
****************************************************************************/
-struct name_record *search_for_name(struct subnet_record **d,
- struct nmb_name *question,
- struct in_addr ip, int Time, int search)
+struct name_record *dns_name_search(struct nmb_name *question, int 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(d,question,search,ip);
-
- if (*d == NULL) return NULL;
+ int name_type = question->name_type;
+ char *qname = question->name;
+ char *r;
+ BOOL dns_type = (name_type == 0x20 || name_type == 0);
+ struct in_addr dns_ip;
- DEBUG(4,("subnet %s ", inet_ntoa((*d)->bcast_ip)));
+ if (wins_subnet == NULL)
+ return NULL;
- /* 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 && name_type != 0x1b)
+ DEBUG(3,("Search for %s - ", namestr(question)));
+
+ /* 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;
+ DEBUG(3,("types 0x20 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)
+
+ /* look it up with DNS */
+ dns_ip.s_addr = interpret_addr(qname);
+
+ if (!dns_ip.s_addr)
{
- /* 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;
+ /* no luck with DNS. We could possibly recurse here XXXX */
+ DEBUG(3,("not found. no recursion.\n"));
+ /* add the fail to WINS cache of names. give it 1 hour in the cache */
+ add_netbios_entry(wins_subnet,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);
-
- /* 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;
-}
+ DEBUG(3,("found with DNS: %s\n", inet_ntoa(dns_ip)));
+ /* add it to our WINS cache of names. give it 2 hours in the cache */
+ return add_netbios_entry(wins_subnet,qname,name_type,NB_ACTIVE,2*60*60,DNS,dns_ip,
+ True,True);
+}