summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/namedbname.c36
-rw-r--r--source/nameserv.c27
-rw-r--r--source/nameservreply.c65
3 files changed, 81 insertions, 47 deletions
diff --git a/source/namedbname.c b/source/namedbname.c
index 58b62bd0cbc..1f16553b0f4 100644
--- a/source/namedbname.c
+++ b/source/namedbname.c
@@ -173,27 +173,25 @@ struct name_record *find_name_search(struct subnet_record **d,
{
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 = 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));
+ return find_name((*d)->namelist, name, search);
}
diff --git a/source/nameserv.c b/source/nameserv.c
index 26c2f330dac..c8bbb528116 100644
--- a/source/nameserv.c
+++ b/source/nameserv.c
@@ -160,11 +160,7 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags)
**************************************************************************/
void add_my_names(void)
{
- BOOL wins = lp_wins_support();
struct subnet_record *d;
-
- struct in_addr ip = ipzero;
-
/* each subnet entry, including WINS pseudo-subnet, has SELF names */
/* XXXX if there was a transport layer added to samba (ipx/spx etc) then
@@ -173,20 +169,23 @@ void add_my_names(void)
for (d = subnetlist; d; d = d->next)
{
- add_my_name_entry(d, myname,0x20,nb_type|NB_ACTIVE);
- add_my_name_entry(d, myname,0x03,nb_type|NB_ACTIVE);
- add_my_name_entry(d, myname,0x00,nb_type|NB_ACTIVE);
- add_my_name_entry(d, myname,0x1f,nb_type|NB_ACTIVE);
+ BOOL wins = lp_wins_support() && ip_equal(d->bcast_ip,ipgrp);
+ add_my_name_entry(d, myname,0x20,nb_type|NB_ACTIVE);
+ add_my_name_entry(d, myname,0x03,nb_type|NB_ACTIVE);
+ add_my_name_entry(d, myname,0x00,nb_type|NB_ACTIVE);
+ add_my_name_entry(d, myname,0x1f,nb_type|NB_ACTIVE);
+
/* these names are added permanently (ttl of zero) and will NOT be
refreshed with the WINS server */
- add_netbios_entry(d,"*",0x0,nb_type|NB_ACTIVE,0,SELF,ip,False,wins);
- add_netbios_entry(d,"__SAMBA__",0x20,nb_type|NB_ACTIVE,0,SELF,ip,False,wins);
- add_netbios_entry(d,"__SAMBA__",0x00,nb_type|NB_ACTIVE,0,SELF,ip,False,wins);
-
+ add_netbios_entry(d,"*",0x0,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
+ add_netbios_entry(d,"*",0x20,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
+ add_netbios_entry(d,"__SAMBA__",0x20,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
+ add_netbios_entry(d,"__SAMBA__",0x00,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
+
if (lp_domain_logons()) {
- /* XXXX the 0x1c is apparently something to do with domain logons */
- add_my_name_entry(d, lp_workgroup(),0x1c,nb_type|NB_ACTIVE|NB_GROUP);
+ /* XXXX the 0x1c is apparently something to do with domain logons */
+ add_my_name_entry(d, lp_workgroup(),0x1c,nb_type|NB_ACTIVE|NB_GROUP);
}
}
if (lp_domain_master() && (d = find_subnet(ipgrp)))
diff --git a/source/nameservreply.c b/source/nameservreply.c
index b77f9958b81..b01c2c25b4c 100644
--- a/source/nameservreply.c
+++ b/source/nameservreply.c
@@ -310,6 +310,29 @@ void reply_name_reg(struct packet_struct *p)
}
}
+/* this is used to sort names for a name status into a sensible order
+ we put our own names first, then in alphabetical order */
+static int status_compare(char *n1,char *n2)
+{
+ extern pstring myname;
+ int l1,l2,l3;
+
+ /* its a bit tricky because the names are space padded */
+ for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++) ;
+ for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++) ;
+ l3 = strlen(myname);
+
+ if ((l1==l3) && strncmp(n1,myname,l3) == 0 &&
+ (l2!=l3 || strncmp(n2,myname,l3) != 0))
+ return -1;
+
+ if ((l2==l3) && strncmp(n2,myname,l3) == 0 &&
+ (l1!=l3 || strncmp(n1,myname,l3) != 0))
+ return 1;
+
+ return memcmp(n1,n2,18);
+}
+
/****************************************************************************
reply to a name status query
@@ -323,15 +346,14 @@ void reply_name_status(struct packet_struct *p)
char *qname = nmb->question.question_name.name;
int ques_type = nmb->question.question_name.name_type;
char rdata[MAX_DGRAM_SIZE];
- char *countptr, *buf, *bufend;
- int names_added;
+ char *countptr, *buf, *bufend, *buf0;
+ int names_added,i;
struct name_record *n;
struct subnet_record *d = NULL;
- int search = FIND_SELF | FIND_WINS;
+ int search = FIND_SELF | FIND_WINS | FIND_LOCAL;
- BOOL bcast = nmb->header.nm_flags.bcast;
-
- if (!(d = find_req_subnet(p->ip, bcast)))
+ /* NOTE: we always treat a name status lookup as a bcast */
+ if (!(d = find_req_subnet(p->ip, True)))
{
DEBUG(3,("Name status req: bcast %s not known\n",
inet_ntoa(p->ip)));
@@ -339,10 +361,8 @@ void reply_name_status(struct packet_struct *p)
}
DEBUG(3,("Name status for name %s %s\n",
- namestr(&nmb->question.question_name), inet_ntoa(p->ip)));
-
- if (bcast)
- search |= FIND_LOCAL;
+ namestr(&nmb->question.question_name),
+ inet_ntoa(p->ip)));
n = find_name_search(&d, &nmb->question.question_name,
search, p->ip);
@@ -353,7 +373,8 @@ void reply_name_status(struct packet_struct *p)
bufend = &rdata[MAX_DGRAM_SIZE] - 18;
countptr = buf = rdata;
buf += 1;
-
+ buf0 = buf;
+
names_added = 0;
n = d->namelist;
@@ -368,9 +389,11 @@ void reply_name_status(struct packet_struct *p)
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 ||
- strequal(qname, n->name.name))
+ if (!strequal(n->name.name,"*") &&
+ !strequal(n->name.name,"__SAMBA__") &&
+ (name_type < 0x1b || name_type > 0x20 ||
+ ques_type < 0x1b || ques_type > 0x20 ||
+ strequal(qname, n->name.name)))
{
/* start with first bit of putting info in buffer: the name */
bzero(buf,18);
@@ -387,6 +410,20 @@ void reply_name_status(struct packet_struct *p)
}
}
+ /* remove duplicate names */
+ qsort(buf0,names_added,18,QSORT_CAST status_compare);
+
+ for (i=1;i<names_added;i++) {
+ if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) {
+ names_added--;
+ if (names_added == i) break;
+ memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i));
+ i--;
+ }
+ }
+
+ buf = buf0 + 18*names_added;
+
n = n->next;
if (!n)