1
0
mirror of https://github.com/samba-team/samba.git synced 2025-05-27 17:05:51 +03:00

severe debugging session for nmbd. in fact, i'm surprised that browsing

in 1.9.16 works at all!

question and resource record types for queries and response netbios
packets sorted out properly (see rfc1002.txt 4.2.1.3).

receipt of browser announcement packets were playing up

lkcl
This commit is contained in:
Samba Release Account -
parent 89675f8ae8
commit b289db62f1
7 changed files with 126 additions and 122 deletions

View File

@ -149,10 +149,11 @@ struct name_record *find_name(struct name_record *n,
if (name_equal(&ret->name,name))
{
/* self search: self names only */
if ((search&FIND_SELF) == FIND_SELF &&
ret->source != SELF)
if ((search&FIND_SELF) == FIND_SELF && ret->source != SELF)
{
continue;
}
return ret;
}
}

View File

@ -87,22 +87,25 @@ struct subnet_record *find_subnet(struct in_addr bcast_ip)
the source ip address. a subnet 255.255.255.255 represents the
WINS list. */
for (d = subnetlist; d; d = d->next)
for (d = subnetlist; d; d = d->next)
{
if (ip_equal(bcast_ip, wins_ip))
{
if (ip_equal(bcast_ip, d->bcast_ip))
{
return d;
}
if (ip_equal(bcast_ip, d->bcast_ip))
{
return d;
}
}
else if (same_net(bcast_ip, d->bcast_ip, d->mask_ip))
{
return(d);
if (!ip_equal(d->bcast_ip, wins_ip))
{
return d;
}
}
}
return (NULL);
return (NULL);
}

View File

@ -141,28 +141,29 @@ void initiate_netbios_packet(uint16 *id,
make_nmb_name(&nmb->question.question_name,name,name_type,scope);
nmb->question.question_type = quest_type;
nmb->question.question_type = 0x20;
nmb->question.question_class = 0x1;
if (quest_type == NMB_REG ||
quest_type == NMB_REG_REFRESH ||
quest_type == NMB_REL)
{
{
nmb->additional = &additional_rec;
bzero((char *)nmb->additional,sizeof(*nmb->additional));
nmb->additional->rr_name = nmb->question.question_name;
nmb->additional->rr_type = nmb->question.question_type;
nmb->additional->rr_class = nmb->question.question_class;
nmb->additional->rr_type = 0x20;
nmb->additional->rr_class = 0x1;
if (quest_type == NMB_REG || quest_type == NMB_REG_REFRESH)
nmb->additional->ttl = lp_max_ttl();
nmb->additional->ttl = lp_max_ttl();
else
nmb->additional->ttl = 0;
nmb->additional->ttl = 0;
nmb->additional->rdlength = 6;
nmb->additional->rdata[0] = nb_flags;
putip(&nmb->additional->rdata[2],(char *)iface_ip(to_ip));
}
}
p.ip = to_ip;
p.port = NMB_PORT;
@ -492,58 +493,60 @@ void run_packet_queue()
***************************************************************************/
void listen_for_packets(BOOL run_election)
{
fd_set fds;
int selrtn;
struct timeval timeout;
fd_set fds;
int selrtn;
struct timeval timeout;
try_again:
FD_ZERO(&fds);
FD_SET(ClientNMB,&fds);
FD_SET(ClientDGRAM,&fds);
FD_ZERO(&fds);
FD_SET(ClientNMB,&fds);
FD_SET(ClientDGRAM,&fds);
/* during elections and when expecting a netbios response packet we
need to send election packets at tighter intervals
/* during elections and when expecting a netbios response packet we
need to send election packets at tighter intervals
ideally it needs to be the interval (in ms) between time now and
the time we are expecting the next netbios packet */
ideally it needs to be the interval (in ms) between time now and
the time we are expecting the next netbios packet */
timeout.tv_sec = (run_election||num_response_packets) ? 1:NMBD_SELECT_LOOP;
timeout.tv_usec = 0;
timeout.tv_sec = (run_election||num_response_packets) ? 1 : NMBD_SELECT_LOOP;
timeout.tv_usec = 0;
selrtn = sys_select(&fds,&timeout);
selrtn = sys_select(&fds,&timeout);
if (FD_ISSET(ClientNMB,&fds))
{
struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET);
if (packet) {
if (ismyip(packet->ip) &&
(packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
DEBUG(7,("discarding own packet from %s:%d\n",
inet_ntoa(packet->ip),packet->port));
free_packet(packet);
goto try_again;
} else {
queue_packet(packet);
if (FD_ISSET(ClientNMB,&fds))
{
struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET);
if (packet)
{
if (ismyip(packet->ip) && packet->port == NMB_PORT)
{
DEBUG(7,("discarding own packet from %s:%d\n",
inet_ntoa(packet->ip),packet->port));
free_packet(packet);
}
else
{
queue_packet(packet);
}
}
}
}
}
if (FD_ISSET(ClientDGRAM,&fds))
{
struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET);
if (packet) {
if (ismyip(packet->ip) &&
(packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
DEBUG(7,("discarding own packet from %s:%d\n",
inet_ntoa(packet->ip),packet->port));
free_packet(packet);
goto try_again;
} else {
queue_packet(packet);
if (FD_ISSET(ClientDGRAM,&fds))
{
struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET);
if (packet)
{
if (ismyip(packet->ip) && packet->port == DGRAM_PORT)
{
DEBUG(7,("discarding own packet from %s:%d\n",
inet_ntoa(packet->ip),packet->port));
free_packet(packet);
}
else
{
queue_packet(packet);
}
}
}
}
}
}

View File

@ -134,25 +134,28 @@ static void dead_netbios_entry(struct subnet_record *d,
on that subnet. if we are using a WINS server, then the WINS
server must be dead or deaf.
*/
if (n->bcast)
if (n->num_msgs == 0)
{
/* broadcast method: implicit acceptance of the name registration
by not receiving any objections. */
if (n->bcast)
{
/* broadcast method: implicit acceptance of the name registration
by not receiving any objections. */
/* IMPORTANT: see response_name_reg() */
/* IMPORTANT: see response_name_reg() */
name_register_work(d,n->name.name,n->name.name_type,
n->nb_flags, n->ttl, n->reply_to_ip, n->bcast);
}
else if (n->num_msgs == 0)
{
/* received no response. rfc1001.txt states that after retrying,
we should assume the WINS server is dead, and fall back to
broadcasting (see bits about M nodes: can't find any right
now) */
name_register_work(d,n->name.name,n->name.name_type,
n->nb_flags, n->ttl, n->reply_to_ip, n->bcast);
}
else
{
/* received no response. rfc1001.txt states that after retrying,
we should assume the WINS server is dead, and fall back to
broadcasting (see bits about M nodes: can't find any right
now) */
DEBUG(1,("WINS server did not respond to name registration!\n"));
/* XXXX whoops. we have problems. must deal with this */
DEBUG(1,("WINS server did not respond to name registration!\n"));
/* XXXX whoops. we have problems. must deal with this */
}
}
break;
}

View File

@ -127,9 +127,9 @@ void reply_name_release(struct packet_struct *p)
}
if (bcast)
search &= FIND_LOCAL;
search |= FIND_LOCAL;
else
search &= FIND_WINS;
search |= FIND_WINS;
n = find_name_search(&d, &nmb->question.question_name,
search, ip);
@ -183,7 +183,7 @@ void reply_name_reg(struct packet_struct *p)
putip((char *)&from_ip,&nmb->additional->rdata[2]);
ip = from_ip;
DEBUG(3,("Name registration for name %s at %s\n",
DEBUG(3,("Name registration for name %s at %s - ",
namestr(question),inet_ntoa(ip)));
if (group)
@ -201,15 +201,16 @@ void reply_name_reg(struct packet_struct *p)
}
if (bcast)
search &= FIND_LOCAL;
search |= FIND_LOCAL;
else
search &= FIND_WINS;
search |= FIND_WINS;
/* see if the name already exists */
n = find_name_search(&d, question, search, from_ip);
if (n)
{
DEBUG(3,("found\n"));
if (!group) /* unique names */
{
if (n->source == SELF || NAME_GROUP(n->ip_flgs[0].nb_flags))
@ -259,6 +260,7 @@ void reply_name_reg(struct packet_struct *p)
}
else
{
DEBUG(3,("not found\n"));
/* add the name to our name/subnet, or WINS, database */
n = add_netbios_entry(d,qname,qname_type,nb_flags,ttl,REGISTER,ip,
True,!bcast);
@ -458,10 +460,8 @@ void reply_name_status(struct packet_struct *p)
reply_netbios_packet(p,nmb->header.name_trn_id,
0,NMB_STATUS,0,True,
&nmb->question.question_name,
nmb->question.question_type,
nmb->question.question_class,
0,
rdata,PTR_DIFF(buf,rdata));
0x21, 0x01,
0, rdata,PTR_DIFF(buf,rdata));
}
@ -549,8 +549,8 @@ void reply_name_query(struct packet_struct *p)
n = find_name_search(&d, question, search, p->ip);
/* it is a name that already failed DNS lookup or it's expired */
if (n->source == DNSFAIL ||
(n->death_time && n->death_time < p->timestamp))
if (n && (n->source == DNSFAIL ||
(n->death_time && n->death_time < p->timestamp)))
{
success = False;
}
@ -625,8 +625,7 @@ void reply_name_query(struct packet_struct *p)
reply_netbios_packet(p,nmb->header.name_trn_id,
rcode,NMB_QUERY,0,True,
&nmb->question.question_name,
nmb->question.question_type,
nmb->question.question_class,
0x20, 0x01,
ttl,
rdata, success ? 6 : 0);
}

View File

@ -46,12 +46,12 @@ extern struct in_addr ipzero;
response for a reg release received. samba has asked a WINS server if it
could release a name.
**************************************************************************/
static void response_name_release(struct subnet_record *d,
struct packet_struct *p)
static void response_name_release(struct nmb_name *ans_name,
struct subnet_record *d, 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;
char *name = ans_name->name;
int type = ans_name->name_type;
DEBUG(4,("response name release received\n"));
@ -70,14 +70,12 @@ static void response_name_release(struct subnet_record *d,
else
{
DEBUG(2,("name release for different ip! %s %s\n",
inet_ntoa(found_ip),
namestr(&nmb->question.question_name)));
inet_ntoa(found_ip), namestr(ans_name)));
}
}
else
{
DEBUG(2,("name release for %s rejected!\n",
namestr(&nmb->question.question_name)));
DEBUG(2,("name release for %s rejected!\n", namestr(ans_name)));
/* XXXX PANIC! what to do if it's one of samba's own names? */
@ -91,12 +89,13 @@ static void response_name_release(struct subnet_record *d,
/****************************************************************************
response for a reg request received
**************************************************************************/
static void response_name_reg(struct subnet_record *d, struct packet_struct *p)
static void response_name_reg(struct nmb_name *ans_name,
struct subnet_record *d, 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;
BOOL bcast = nmb->header.nm_flags.bcast;
char *name = ans_name->name;
int type = ans_name->name_type;
DEBUG(4,("response name registration received!\n"));
@ -114,8 +113,7 @@ static void response_name_reg(struct subnet_record *d, struct packet_struct *p)
}
else
{
DEBUG(1,("name registration for %s rejected!\n",
namestr(&nmb->question.question_name)));
DEBUG(2,("name registration for %s rejected!\n", namestr(ans_name)));
/* oh dear. we have problems. possibly unbecome a master browser. */
name_unregister_work(d,name,type);
@ -527,7 +525,7 @@ void debug_state_type(int state)
(responses for certain types of operations are only expected from one host)
****************************************************************************/
static BOOL response_problem_check(struct response_record *n,
struct nmb_packet *nmb, char *qname)
struct nmb_packet *nmb, char *ans_name)
{
switch (nmb->answers->rr_type)
{
@ -584,7 +582,7 @@ static BOOL response_problem_check(struct response_record *n,
case NAME_QUERY_SRV_CHK:
case NAME_QUERY_MST_CHK:
{
if (!strequal(qname,n->name.name))
if (!strequal(ans_name,n->name.name))
{
/* one subnet, one master browser per workgroup */
/* XXXX force an election? */
@ -694,13 +692,13 @@ static void response_process(struct subnet_record *d, struct packet_struct *p,
{
case NAME_RELEASE:
{
response_name_release(d, p);
response_name_release(ans_name, d, p);
break;
}
case NAME_REGISTER:
{
response_name_reg(d, p);
response_name_reg(ans_name, d, p);
break;
}
@ -763,9 +761,7 @@ static void response_process(struct subnet_record *d, struct packet_struct *p,
void response_netbios_packet(struct packet_struct *p)
{
struct nmb_packet *nmb = &p->packet.nmb;
struct nmb_name *question = &nmb->question.question_name;
struct nmb_name *ans_name = NULL;
char *qname = question->name;
BOOL bcast = nmb->header.nm_flags.bcast;
struct response_record *n;
struct subnet_record *d = NULL;
@ -809,7 +805,7 @@ void response_netbios_packet(struct packet_struct *p)
debug_state_type(n->state);
/* problem checking: multiple responses etc */
if (response_problem_check(n, nmb, qname))
if (response_problem_check(n, nmb, ans_name->name))
return;
/* now deal with the current state */

View File

@ -175,8 +175,7 @@ BOOL same_context(struct dgram_packet *dgram)
static void process_announce(struct packet_struct *p,uint16 command,char *buf)
{
struct dgram_packet *dgram = &p->packet.dgram;
struct in_addr ip = dgram->header.source_ip;
struct subnet_record *d = find_subnet(ip);
struct subnet_record *d = find_subnet(p->ip);
int update_count = CVAL(buf,0);
int ttl = IVAL(buf,1)/1000;
@ -213,7 +212,7 @@ static void process_announce(struct packet_struct *p,uint16 command,char *buf)
dgram->dest_name.name_type != 0x1))
{
DEBUG(0,("Announce(%d) from %s should be __MSBROWSE__(1) not %s\n",
command, inet_ntoa(ip), namestr(&dgram->dest_name)));
command, inet_ntoa(p->ip), namestr(&dgram->dest_name)));
return;
}
@ -243,6 +242,9 @@ static void process_announce(struct packet_struct *p,uint16 command,char *buf)
dgram->dest_name.name_type == 0x1e))
add = True;
DEBUG(4,("search for workgroup: %s (add? %s)\n",
work_name, BOOLSTR(add)));
if (!(work = find_workgroupstruct(d, work_name,add)))
return;
@ -265,7 +267,7 @@ static void process_announce(struct packet_struct *p,uint16 command,char *buf)
if (command == ANN_LocalMasterAnnouncement)
{
add_browser_entry(serv_name,dgram->dest_name.name_type,
work->work_group,30,ip,True);
work->work_group,30,p->ip,True);
}
}
@ -275,27 +277,25 @@ static void process_announce(struct packet_struct *p,uint16 command,char *buf)
static void process_master_announce(struct packet_struct *p,char *buf)
{
struct dgram_packet *dgram = &p->packet.dgram;
struct in_addr ip = dgram->header.source_ip;
struct subnet_record *d = find_subnet(ip);
struct subnet_record *mydomain = find_subnet(*iface_bcast(ip));
struct subnet_record *d = find_subnet(p->ip);
char *name = buf;
struct work_record *work;
name[15] = 0;
DEBUG(3,("Master Announce from %s (%s)\n",name,inet_ntoa(ip)));
DEBUG(3,("Master Announce from %s (%s)\n",name,inet_ntoa(p->ip)));
if (same_context(dgram)) return;
if (!d || !mydomain) return;
if (!d) return;
if (!lp_domain_master()) return;
for (work = mydomain->workgrouplist; work; work = work->next)
for (work = d->workgrouplist; work; work = work->next)
{
if (AM_MASTER(work))
{
/* merge browse lists with them */
add_browser_entry(name,0x1b, work->work_group,30,ip,True);
add_browser_entry(name,0x1b, work->work_group,30,p->ip,True);
}
}
}
@ -316,13 +316,12 @@ static void process_master_announce(struct packet_struct *p,char *buf)
static void process_rcv_backup_list(struct packet_struct *p,char *buf)
{
struct dgram_packet *dgram = &p->packet.dgram;
struct in_addr ip = dgram->header.source_ip;
int count = CVAL(buf,0);
uint32 info = IVAL(buf,1); /* XXXX caller's incremental info */
char *buf1;
DEBUG(3,("Receive Backup ack for %s from %s total=%d info=%d\n",
namestr(&dgram->dest_name), inet_ntoa(ip),
namestr(&dgram->dest_name), inet_ntoa(p->ip),
count, info));
if (same_context(dgram)) return;
@ -336,7 +335,7 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf)
/* struct subnet_record *d; */
DEBUG(4,("Searching for backup browser %s at %s...\n",
buf1, inet_ntoa(ip)));
buf1, inet_ntoa(p->ip)));
/* XXXX assume name is a DNS name NOT a netbios name. a more complete
approach is to use reply_name_query functionality to find the name */