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 int DEBUGLEVEL;
extern pstring scope;
+extern fstring myworkgroup;
extern struct in_addr ipzero;
+extern struct in_addr wins_ip;
+extern struct in_addr ipzero;
+
#define GET_TTL(ttl) ((ttl)?MIN(ttl,lp_max_ttl()):lp_max_ttl())
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"));
- if (nmb->header.rcode == 0 && nmb->answers->rdata)
+ if (nmb->header.rcode == 0 && nmb->answers && nmb->answers->rdata)
{
/* IMPORTANT: see expire_netbios_response_entries() */
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? */
/****************************************************************************
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"));
- if (nmb->header.rcode == 0 && nmb->answers->rdata)
+#if 1
+ /* This code is neccesitated due to bugs in earlier versions of
+ Samba (up to 1.9.16p11). They respond to a broadcast
+ name registration of WORKGROUP<1b> when they should
+ not. Hence, until these versions are gone, we should
+ treat such errors as success for this particular
+ case only. jallison@whistle.com.
+ */
+ if ( ((d != wins_client_subnet) && (nmb->header.rcode == 6) && strequal(myworkgroup, name) &&
+ (type == 0x1b)) ||
+ (nmb->header.rcode == 0 && nmb->answers && nmb->answers->rdata))
+#else
+ if (nmb->header.rcode == 0 && nmb->answers && nmb->answers->rdata)
+#endif
{
/* IMPORTANT: see expire_netbios_response_entries() */
}
else
{
- DEBUG(1,("name registration for %s rejected!\n",
- namestr(&nmb->question.question_name)));
+ DEBUG(2,("name registration for %s rejected by ip %s!\n",
+ namestr(ans_name), inet_ntoa(p->ip)));
/* oh dear. we have problems. possibly unbecome a master browser. */
name_unregister_work(d,name,type);
}
}
-
-/****************************************************************************
- response from a name query announce host
- NAME_QUERY_ANNOUNCE_HOST is dealt with here
- ****************************************************************************/
-static void response_announce_host(struct nmb_name *ans_name,
- struct nmb_packet *nmb,
- struct response_record *n, struct subnet_record *d)
-{
- DEBUG(4, ("Name query at %s ip %s - ",
- namestr(&n->name), inet_ntoa(n->send_ip)));
-
- if (!name_equal(&n->name, ans_name))
- {
- /* someone gave us the wrong name as a reply. oops. */
- /* XXXX should say to them 'oi! release that name!' */
-
- DEBUG(4,("unexpected name received: %s\n", namestr(ans_name)));
- return;
- }
-
- if (nmb->header.rcode == 0 && nmb->answers->rdata)
- {
- /* we had sent out a name query to the current owner
- of a name because someone else wanted it. now they
- have responded saying that they still want the name,
- so the other host can't have it.
- */
-
- /* first check all the details are correct */
-
- int nb_flags = nmb->answers->rdata[0];
- struct in_addr found_ip;
-
- putip((char*)&found_ip,&nmb->answers->rdata[2]);
-
- if (nb_flags != n->nb_flags)
- {
- /* someone gave us the wrong nb_flags as a reply. oops. */
- /* XXXX should say to them 'oi! release that name!' */
-
- DEBUG(4,("expected nb_flags: %d\n", n->nb_flags));
- DEBUG(4,("unexpected nb_flags: %d\n", nb_flags));
- return;
- }
-
- /* do an announce host */
- do_announce_host(ANN_HostAnnouncement,
- n->my_name , 0x00, d->myip,
- n->name.name, 0x1d, found_ip,
- n->ttl,
- n->my_name, n->server_type, n->my_comment);
- }
- else
- {
- /* XXXX negative name query response. no master exists. oops */
- }
-}
-
-
/****************************************************************************
response from a name query server check. states of type NAME_QUERY_DOM_SRV_CHK,
NAME_QUERY_SRV_CHK, and NAME_QUERY_FIND_MST dealt with here.
****************************************************************************/
static void response_server_check(struct nmb_name *ans_name,
- struct response_record *n, struct subnet_record *d)
+ struct response_record *n, struct subnet_record *d, struct packet_struct *p)
{
+ struct nmb_packet *nmb = &p->packet.nmb;
+ struct in_addr send_ip;
+ enum state_type cmd;
+
+ /* This next fix was from Bernhard Laeser <nlaesb@ascom.ch>
+ who noticed we were replying directly back to the server
+ we sent to - rather than reading the response.
+ */
+
+ if (nmb->header.rcode == 0 && nmb->answers && nmb->answers->rdata)
+ putip((char*)&send_ip,&nmb->answers->rdata[2]);
+ else
+ {
+
+ DEBUG(2,("response_server_check: name query for %s failed\n",
+ namestr(ans_name)));
+ return;
+ }
+
/* issue another state: this time to do a name status check */
- enum state_type cmd = (n->state == NAME_QUERY_DOM_SRV_CHK) ?
+ cmd = (n->state == NAME_QUERY_DOM_SRV_CHK) ?
NAME_STATUS_DOM_SRV_CHK : NAME_STATUS_SRV_CHK;
- /* initiate a name status check on the server that replied */
+ /* initiate a name status check on address given in the reply
+ record. In addition, the workgroup being checked has been stored
+ in the response_record->my_name (see announce_master) we
+ also propagate this into the same field. */
queue_netbios_packet(d,ClientNMB,NMB_STATUS, cmd,
ans_name->name, ans_name->name_type,
- 0,0,0,NULL,NULL,
- False,False,n->send_ip,n->reply_to_ip);
+ 0,0,0,n->my_name,NULL,
+ False,False,send_ip,n->reply_to_ip, 0);
}
char *p, struct nmb_name *name,int t,
char *serv_name, struct in_addr ip, BOOL bcast)
{
- int level = t==0x20 ? 4 : 0;
int numnames = CVAL(p,0);
BOOL found = False;
- DEBUG(level,("received %d names\n",numnames));
+ DEBUG(4,("received %d names\n",numnames));
p += 1;
if (NAME_MFLAG (nb_flags)) { strcat(flags,"M "); }
if (NAME_HFLAG (nb_flags)) { strcat(flags,"H "); }
if (NAME_DEREG (nb_flags)) { strcat(flags,"<DEREGISTERING> "); }
- if (NAME_CONFLICT (nb_flags)) { strcat(flags,"<CONFLICT> "); add=True;}
+ if (NAME_CONFLICT (nb_flags)) { strcat(flags,"<CONFLICT> "); }
if (NAME_ACTIVE (nb_flags)) { strcat(flags,"<ACTIVE> "); add=True; }
if (NAME_PERMANENT(nb_flags)) { strcat(flags,"<PERMANENT> "); add=True;}
-
- /* might as well update our namelist while we're at it */
- if (add)
- {
- struct in_addr nameip;
- enum name_source src;
-
- if (ismyip(ip)) {
- nameip = ipzero;
- src = SELF;
- } else {
- nameip = ip;
- src = STATUS_QUERY;
- }
- add_netbios_entry(d,qname,type,nb_flags,2*60*60,src,nameip,True,bcast);
- }
/* we want the server name */
- if (serv_name && !*serv_name && !group && t == 0)
+ if (serv_name && !*serv_name && !group && type == 0x20)
{
StrnCpy(serv_name,qname,15);
serv_name[15] = 0;
{
/* take a guess at some of the name types we're going to ask for.
evaluate whether they are group names or no... */
- if (((t == 0x1b || t == 0x1d ) && !group) ||
- ((t == 0x20 || t == 0x1c || t == 0x1e) && group))
+ if (((t == 0x1b || t == 0x1d || t == 0x20 ) && !group) ||
+ ((t == 0x1c || t == 0x1e ) && group))
{
found = True;
make_nmb_name(name,qname,type,scope);
}
}
- DEBUG(level,("\t%s(0x%x)\t%s\n",qname,type,flags));
+ DEBUG(4,("\t%s(0x%x)\t%s\n",qname,type,flags));
}
- DEBUG(level,("num_good_sends=%d num_good_receives=%d\n",
+ DEBUG(4,("num_good_sends=%d num_good_receives=%d\n",
IVAL(p,20),IVAL(p,24)));
return found;
}
struct nmb_name name;
fstring serv_name;
- if (interpret_node_status(d,nmb->answers->rdata,
- &name,name.name_type,serv_name,ip,bcast))
+ if (nmb->answers &&
+ interpret_node_status(d,nmb->answers->rdata,
+ &name,0x20,serv_name,ip,bcast))
{
if (*serv_name)
{
+ /* response_record->my_name contains the
+ workgroup name to sync with. See
+ response_server_check() */
sync_server(n->state,serv_name,
- name.name,name.name_type, n->send_ip);
+ n->my_name,name.name_type, d, n->send_ip);
}
}
else
{
- DEBUG(1,("No 0x1d name type in interpret_node_status()\n"));
+ DEBUG(1,("No 0x20 name type in interpret_node_status()\n"));
}
}
return;
}
- if (nmb->header.rcode == 0 && nmb->answers->rdata)
+ if (nmb->header.rcode == 0 && nmb->answers && nmb->answers->rdata)
{
/* we had sent out a name query to the current owner
of a name because someone else wanted it. now they
}
/* register the old or the new owners' ip */
- add_name_respond(d, n->fd, d->myip, n->response_id,&n->name,n->nb_flags,
+ add_name_respond(d, n->fd, d->myip, n->reply_id,&n->name,n->nb_flags,
GET_TTL(0), register_ip,
new_owner, n->reply_to_ip);
+
+ remove_response_record(d,n); /* remove the response record */
}
struct nmb_name *ans_name, BOOL bcast,
struct response_record *n, struct subnet_record *d)
{
- DEBUG(4, ("Name query at %s ip %s - ",
- namestr(&n->name), inet_ntoa(n->send_ip)));
+ DEBUG(4, ("Name query at %s ip %s - ",
+ namestr(&n->name), inet_ntoa(n->send_ip)));
- if (!name_equal(&n->name, ans_name))
- {
- /* someone gave us the wrong name as a reply. oops. */
- DEBUG(4,("unexpected name received: %s\n", namestr(ans_name)));
- return;
- }
-
- if (nmb->header.rcode == 0 && nmb->answers->rdata)
+ if (!name_equal(&n->name, ans_name))
{
- int nb_flags = nmb->answers->rdata[0];
- struct in_addr found_ip;
-
- putip((char*)&found_ip,&nmb->answers->rdata[2]);
-
- if (!ip_equal(n->send_ip, found_ip))
- {
- /* someone gave us the wrong ip as a reply. oops. */
- DEBUG(4,("expected ip: %s\n", inet_ntoa(n->send_ip)));
- DEBUG(4,("unexpected ip: %s\n", inet_ntoa(found_ip)));
- return;
- }
-
- DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip)));
+ /* someone gave us the wrong name as a reply. oops. */
+ DEBUG(4,("unexpected name received: %s\n", namestr(ans_name)));
+ return;
+ }
- if (n->state == NAME_QUERY_SYNC_LOCAL ||
- n->state == NAME_QUERY_SYNC_REMOTE)
- {
- struct work_record *work = NULL;
- if ((work = find_workgroupstruct(d, ans_name->name, False)))
- {
- BOOL local_list_only = n->state == NAME_QUERY_SYNC_LOCAL;
+ if (nmb->header.rcode == 0 && nmb->answers && nmb->answers->rdata)
+ {
+ int nb_flags = nmb->answers->rdata[0];
+ struct in_addr found_ip;
+
+ putip((char*)&found_ip,&nmb->answers->rdata[2]);
+
+ if (!ip_equal(n->send_ip, found_ip))
+ {
+ /* someone gave us the wrong ip as a reply. oops. */
+ DEBUG(4,("expected ip: %s\n", inet_ntoa(n->send_ip)));
+ DEBUG(4,("unexpected ip: %s\n", inet_ntoa(found_ip)));
+ return;
+ }
- /* the server is there: sync quick before it (possibly) dies! */
- sync_browse_lists(d, work, ans_name->name, ans_name->name_type,
- found_ip, local_list_only);
- }
- }
- else
- {
- /* update our netbios name list (re-register it if necessary) */
- add_netbios_entry(d, ans_name->name, ans_name->name_type,
- nb_flags,GET_TTL(0),REGISTER,
- found_ip,False,!bcast);
- }
+ DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip)));
+
+ if (n->state == NAME_QUERY_SYNC_LOCAL ||
+ n->state == NAME_QUERY_SYNC_REMOTE)
+ {
+ struct work_record *work = NULL;
+ /* We cheat here as we know that the workgroup name has
+ been placed in the my_comment field of the
+ response_record struct by the code in
+ start_sync_browse_entry().
+ */
+ if ((work = find_workgroupstruct(d, n->my_comment, False)))
+ {
+ BOOL local_list_only = n->state == NAME_QUERY_SYNC_LOCAL;
+
+ /* the server is there: sync quick before it (possibly) dies! */
+ sync_browse_lists(d, work, ans_name->name, ans_name->name_type,
+ found_ip, local_list_only);
+ }
}
- else
+ else
{
- DEBUG(4, (" NEGATIVE RESPONSE!\n"));
+ struct subnet_record *add_rec = (!bcast) ? wins_client_subnet : d;
- if (n->state == NAME_QUERY_CONFIRM)
- {
- /* XXXX remove_netbios_entry()? */
- /* lots of things we ought to do, here. if we get here,
- then we're in a mess: our name database doesn't match
- reality. sort it out
+ /* update our netbios name list (re-register it if necessary) */
+ add_netbios_entry(add_rec, ans_name->name, ans_name->name_type,
+ nb_flags,GET_TTL(0),REGISTER,
+ found_ip,False);
+ }
+ }
+ else
+ {
+ DEBUG(4, (" NEGATIVE RESPONSE!\n"));
+
+ if (n->state == NAME_QUERY_CONFIRM)
+ {
+ /* XXXX remove_netbios_entry()? */
+ /* lots of things we ought to do, here. if we get here,
+ then we're in a mess: our name database doesn't match
+ reality. sort it out
*/
- remove_netbios_name(d,n->name.name, n->name.name_type,
- REGISTER,n->send_ip);
- }
+ remove_netbios_name(d,n->name.name, n->name.name_type, REGISTER);
}
+ }
}
+/****************************************************************************
+ response from a name query for DOMAIN<1b>
+ NAME_QUERY_DOMAIN is dealt with here - we are trying to become a domain
+ master browser and WINS replied - check it's our address.
+ ****************************************************************************/
+static void response_name_query_domain(struct nmb_name *ans_name,
+ struct nmb_packet *nmb,
+ struct response_record *n, struct subnet_record *d)
+{
+ DEBUG(4, ("response_name_query_domain: Got %s response from %s for query \
+for %s\n", nmb->header.rcode == 0 ? "success" : "failure",
+ inet_ntoa(n->send_ip), namestr(ans_name)));
+
+ /* Check the name is correct and ip address returned is our own. If it is then we
+ just remove the response record.
+ */
+ if (name_equal(&n->name, ans_name) && (nmb->header.rcode == 0) && nmb->answers && (nmb->answers->rdata))
+ {
+ struct in_addr found_ip;
+
+ putip((char*)&found_ip,&nmb->answers->rdata[2]);
+ /* Samba 1.9.16p11 servers seem to return the broadcast address for this
+ query. */
+ if (ismyip(found_ip) || ip_equal(wins_ip, found_ip) || ip_equal(ipzero, found_ip))
+ {
+ DEBUG(4, ("response_name_query_domain: WINS server returned our ip \
+address. Pretending we never received response.\n"));
+ n->num_msgs = 0;
+ n->repeat_count = 0;
+ n->repeat_time = 0;
+ }
+ else
+ {
+ DEBUG(0,("response_name_query_domain: WINS server already has a \
+domain master browser registered %s at address %s\n",
+ namestr(ans_name), inet_ntoa(found_ip)));
+ }
+ }
+ else
+ {
+ /* Negative/incorrect response. No domain master
+ browser was registered - pretend we didn't get this response.
+ */
+ n->num_msgs = 0;
+ n->repeat_count = 0;
+ n->repeat_time = 0;
+ }
+
+}
/****************************************************************************
report the response record type
static void debug_rr_type(int rr_type)
{
switch (rr_type)
- {
- case NMB_STATUS: DEBUG(3,("Name status ")); break;
- case NMB_QUERY : DEBUG(3,("Name query ")); break;
- case NMB_REG : DEBUG(3,("Name registration ")); break;
- case NMB_REL : DEBUG(3,("Name release ")); break;
- default : DEBUG(1,("wrong response packet type received")); break;
- }
+ {
+ case NMB_STATUS: DEBUG(3,("Name status ")); break;
+ case NMB_QUERY : DEBUG(3,("Name query ")); break;
+ case NMB_REG : DEBUG(3,("Name registration ")); break;
+ case NMB_REL : DEBUG(3,("Name release ")); break;
+ default : DEBUG(1,("wrong response packet type received")); break;
+ }
}
/****************************************************************************
{
/* report the state type to help debugging */
switch (state)
- {
- case NAME_QUERY_DOM_SRV_CHK : DEBUG(4,("MASTER_SVR_CHECK\n")); break;
+ {
+ case NAME_QUERY_DOM_SRV_CHK : DEBUG(4,("NAME_QUERY_DOM_SRV_CHK\n")); break;
case NAME_QUERY_SRV_CHK : DEBUG(4,("NAME_QUERY_SRV_CHK\n")); break;
case NAME_QUERY_FIND_MST : DEBUG(4,("NAME_QUERY_FIND_MST\n")); break;
case NAME_QUERY_MST_CHK : DEBUG(4,("NAME_QUERY_MST_CHK\n")); break;
case NAME_QUERY_CONFIRM : DEBUG(4,("NAME_QUERY_CONFIRM\n")); break;
case NAME_QUERY_SYNC_LOCAL : DEBUG(4,("NAME_QUERY_SYNC_LOCAL\n")); break;
case NAME_QUERY_SYNC_REMOTE : DEBUG(4,("NAME_QUERY_SYNC_REMOTE\n")); break;
- case NAME_QUERY_ANNOUNCE_HOST: DEBUG(4,("NAME_QUERY_ANNCE_HOST\n"));break;
-
+ case NAME_QUERY_DOMAIN : DEBUG(4,("NAME_QUERY_DOMAIN\n")); break;
+
case NAME_REGISTER : DEBUG(4,("NAME_REGISTER\n")); break;
case NAME_REGISTER_CHALLENGE : DEBUG(4,("NAME_REGISTER_CHALLENGE\n"));break;
-
+
case NAME_RELEASE : DEBUG(4,("NAME_RELEASE\n")); break;
-
- case NAME_STATUS_DOM_SRV_CHK : DEBUG(4,("NAME_STAT_MST_CHK\n")); break;
+
+ case NAME_STATUS_DOM_SRV_CHK : DEBUG(4,("NAME_STATUS_DOM_SRV_CHK\n")); break;
case NAME_STATUS_SRV_CHK : DEBUG(4,("NAME_STATUS_SRV_CHK\n")); break;
-
+
default: break;
- }
+ }
}
/****************************************************************************
(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)
- {
- case NMB_REL:
{
+ case NMB_REL:
+ {
if (n->num_msgs > 1)
- {
+ {
DEBUG(1,("more than one release name response received!\n"));
return True;
- }
+ }
break;
- }
+ }
case NMB_REG:
- {
+ {
if (n->num_msgs > 1)
- {
+ {
DEBUG(1,("more than one register name response received!\n"));
return True;
- }
+ }
break;
- }
-
+ }
+
case NMB_QUERY:
- {
- if (n->num_msgs > 1)
- {
- if (nmb->header.rcode == 0 && nmb->answers->rdata)
+ {
+ if (n->num_msgs > 1)
+ {
+ if (nmb->header.rcode == 0 && nmb->answers && nmb->answers->rdata)
+ {
+ int nb_flags = nmb->answers->rdata[0];
+
+ if ((!NAME_GROUP(nb_flags)))
{
- int nb_flags = nmb->answers->rdata[0];
-
- if ((!NAME_GROUP(nb_flags)))
+ /* oh dear. more than one person responded to a
+ unique name.
+ there is either a network problem, a
+ configuration problem
+ or a server is mis-behaving */
+
+ /* XXXX mark the name as in conflict, and then let the
+ person who just responded know that they
+ must also mark it
+ as in conflict, and therefore must NOT use it.
+ see rfc1001.txt 15.1.3.5 */
+
+ /* this may cause problems for some
+ early versions of nmbd */
+
+ switch (n->state)
+ {
+ case NAME_QUERY_FIND_MST:
{
- /* oh dear. more than one person responded to a unique name.
- there is either a network problem, a configuration problem
- or a server is mis-behaving */
-
- /* XXXX mark the name as in conflict, and then let the
- person who just responded know that they must also mark it
- as in conflict, and therefore must NOT use it.
- see rfc1001.txt 15.1.3.5 */
-
- /* this may cause problems for some early versions of nmbd */
-
- switch (n->state)
- {
- case NAME_QUERY_FIND_MST:
- {
- /* query for ^1^2__MSBROWSE__^2^1 expect lots of responses */
- return False;
- }
- case NAME_QUERY_ANNOUNCE_HOST:
- case NAME_QUERY_DOM_SRV_CHK:
- case NAME_QUERY_SRV_CHK:
- case NAME_QUERY_MST_CHK:
- {
- if (!strequal(qname,n->name.name))
- {
- /* one subnet, one master browser per workgroup */
- /* XXXX force an election? */
-
- DEBUG(3,("more than one master browser replied!\n"));
- return True;
- }
- break;
- }
- default: break;
- }
- DEBUG(3,("Unique Name conflict detected!\n"));
- return True;
+ /* query for ^1^2__MSBROWSE__^2^1 expect
+ lots of responses */
+ return False;
}
+ case NAME_QUERY_DOM_SRV_CHK:
+ case NAME_QUERY_SRV_CHK:
+ case NAME_QUERY_MST_CHK:
+ {
+ if (!strequal(ans_name,n->name.name))
+ {
+ /* one subnet, one master browser
+ per workgroup */
+ /* XXXX force an election? */
+
+ DEBUG(3,("more than one master browser replied!\n"));
+ return True;
+ }
+ break;
+ }
+ default: break;
+ }
+ DEBUG(3,("Unique Name conflict detected!\n"));
+ return True;
}
- else
- {
- /* we have received a negative reply, having already received
- at least one response (pos/neg). something's really wrong! */
-
- DEBUG(3,("wierd name query problem detected!\n"));
- return True;
- }
- }
+ }
+ else
+ {
+ /* we have received a negative reply,
+ having already received
+ at least one response (pos/neg).
+ something's really wrong! */
+
+ DEBUG(3,("wierd name query problem detected!\n"));
+ return True;
+ }
+ }
+ }
}
- }
return False;
}
+#if 0
/****************************************************************************
check that the response received is compatible with the response record
****************************************************************************/
{
case NAME_RELEASE:
{
- if (nmb->answers->rr_type != NMB_REL)
+ if (nmb->answers->rr_type != 0x20)
{
DEBUG(1,("Name release reply has wrong answer rr_type\n"));
return False;
case NAME_REGISTER:
{
- if (nmb->answers->rr_type != NMB_REG)
+ if (nmb->answers->rr_type != 0x20)
{
DEBUG(1,("Name register reply has wrong answer rr_type\n"));
return False;
case NAME_REGISTER_CHALLENGE: /* this is a query: we then do a register */
case NAME_QUERY_CONFIRM:
- case NAME_QUERY_ANNOUNCE_HOST:
case NAME_QUERY_SYNC_LOCAL:
case NAME_QUERY_SYNC_REMOTE:
case NAME_QUERY_DOM_SRV_CHK:
case NAME_QUERY_FIND_MST:
case NAME_QUERY_MST_CHK:
{
- if (nmb->answers->rr_type != NMB_QUERY)
+ if (nmb->answers->rr_type != 0x20)
{
DEBUG(1,("Name query reply has wrong answer rr_type\n"));
return False;
case NAME_STATUS_DOM_SRV_CHK:
case NAME_STATUS_SRV_CHK:
{
- if (nmb->answers->rr_type != NMB_STATUS)
+ if (nmb->answers->rr_type != 0x21)
{
DEBUG(1,("Name status reply has wrong answer rr_type\n"));
return False;
}
return True;
}
+#endif
/****************************************************************************
process the response packet received
****************************************************************************/
static void response_process(struct subnet_record *d, struct packet_struct *p,
- struct response_record *n, struct nmb_packet *nmb,
- BOOL bcast, struct nmb_name *ans_name)
+ struct response_record *n, struct nmb_packet *nmb,
+ BOOL bcast, struct nmb_name *ans_name)
{
switch (n->state)
- {
- case NAME_RELEASE:
{
- response_name_release(d, p);
+ case NAME_RELEASE:
+ {
+ response_name_release(ans_name, d, p);
break;
- }
+ }
case NAME_REGISTER:
- {
- response_name_reg(d, p);
+ {
+ response_name_reg(ans_name, d, p);
break;
- }
+ }
case NAME_REGISTER_CHALLENGE:
- {
+ {
response_name_query_register(nmb, ans_name, n, d);
break;
- }
+ }
case NAME_QUERY_DOM_SRV_CHK:
case NAME_QUERY_SRV_CHK:
case NAME_QUERY_FIND_MST:
- {
- response_server_check(ans_name, n, d);
- break;
- }
-
+ {
+ response_server_check(ans_name, n, d, p);
+ break;
+ }
+
case NAME_STATUS_DOM_SRV_CHK:
case NAME_STATUS_SRV_CHK:
- {
- response_name_status_check(p->ip, nmb, bcast, n, d);
- break;
- }
-
- case NAME_QUERY_ANNOUNCE_HOST:
- {
- response_announce_host(ans_name, nmb, n, d);
- break;
- }
-
+ {
+ response_name_status_check(p->ip, nmb, bcast, n, d);
+ break;
+ }
+
case NAME_QUERY_CONFIRM:
case NAME_QUERY_SYNC_LOCAL:
case NAME_QUERY_SYNC_REMOTE:
- {
- response_name_query_sync(nmb, ans_name, bcast, n, d);
- break;
- }
+ {
+ response_name_query_sync(nmb, ans_name, bcast, n, d);
+ break;
+ }
case NAME_QUERY_MST_CHK:
- {
- /* no action required here. it's when NO responses are received
- that we need to do something. see expire_name_query_entries() */
+ {
+ /* 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 (just checking!)\n",
- namestr(&n->name), inet_ntoa(n->send_ip)));
- break;
- }
-
+ DEBUG(4, ("Master browser exists for %s at %s (just checking!)\n",
+ namestr(&n->name), inet_ntoa(n->send_ip)));
+ break;
+ }
+
+ case NAME_QUERY_DOMAIN:
+ {
+ /* We were asking to be a domain master browser, and someone
+ replied. If it was the WINS server and the IP it is
+ returning is our own - then remove the record and pretend
+ we didn't get a response. Else we do nothing and let
+ dead_netbios_entry deal with it.
+ We can only become domain master browser
+ when no broadcast responses are received and WINS
+ either contains no entry for the DOMAIN<1b> name or
+ contains our IP address.
+ */
+ response_name_query_domain(ans_name, nmb, n, d);
+ break;
+ }
default:
- {
- DEBUG(1,("unknown state type received in response_netbios_packet\n"));
- break;
+ {
+ DEBUG(1,("unknown state type received in response_netbios_packet\n"));
+ break;
+ }
}
- }
}
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;
if (!(n = find_response_record(&d,nmb->header.name_trn_id))) {
- DEBUG(2,("unknown netbios response (received late or from nmblookup?)\n"));
+ DEBUG(2,("unknown netbios response id %d (received late or from nmblookup?)\n",
+ nmb->header.name_trn_id));
return;
}
if (!d)
- {
- DEBUG(2,("response packet: subnet %s not known\n", inet_ntoa(p->ip)));
- return;
- }
+ {
+ DEBUG(2,("response packet: subnet %s not known\n", inet_ntoa(p->ip)));
+ return;
+ }
/* args wrong way round: spotted by ccm@shentel.net */
if (!same_net(d->bcast_ip, p->ip, d->mask_ip)) /* copes with WINS 'subnet' */
- {
- DEBUG(2,("response from %s. ", inet_ntoa(p->ip)));
- DEBUG(2,("expected on subnet %s. hmm.\n", inet_ntoa(d->bcast_ip)));
- return;
- }
-
- if (nmb->answers == NULL)
- {
- /* hm. the packet received was a response, but with no answer. wierd! */
- DEBUG(2,("NMB packet response from %s (bcast=%s) - UNKNOWN\n",
- inet_ntoa(p->ip), BOOLSTR(bcast)));
- return;
+ {
+ DEBUG(2,("response from %s. ", inet_ntoa(p->ip)));
+ DEBUG(2,("expected on subnet %s. hmm.\n", inet_ntoa(d->bcast_ip)));
+ }
+
+ if (nmb->answers == NULL) {
+ /* if there is no name is the response then the name is the one
+ we queried on */
+ ans_name = &n->name;
+ } else {
+ ans_name = &nmb->answers->rr_name;
+ debug_rr_type(nmb->answers->rr_type);
}
- ans_name = &nmb->answers->rr_name;
- DEBUG(3,("response for %s from %s (bcast=%s)\n",
- namestr(ans_name), inet_ntoa(p->ip), BOOLSTR(bcast)));
+ DEBUG(3,("response for %s from %s(%d) (bcast=%s)\n",
+ namestr(ans_name), inet_ntoa(p->ip), p->port, BOOLSTR(bcast)));
- debug_rr_type(nmb->answers->rr_type);
-
n->num_msgs++; /* count number of responses received */
n->repeat_count = 0; /* don't resend: see expire_netbios_packets() */
-
+
debug_state_type(n->state);
-
+
/* problem checking: multiple responses etc */
- if (response_problem_check(n, nmb, qname))
- return;
-
- /* now check whether the 'state' has received the correct type of response */
- if (!response_compatible(n, nmb))
+ if (nmb->answers && response_problem_check(n, nmb, ans_name->name))
return;
-
+
/* now deal with the current state */
response_process(d, p, n, nmb, bcast, ans_name);
}
-
-