summaryrefslogtreecommitdiffstats
path: root/source/nmbd/nmbd_incomingrequests.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/nmbd/nmbd_incomingrequests.c')
-rw-r--r--source/nmbd/nmbd_incomingrequests.c354
1 files changed, 197 insertions, 157 deletions
diff --git a/source/nmbd/nmbd_incomingrequests.c b/source/nmbd/nmbd_incomingrequests.c
index 834f237a2c2..dbbb7315787 100644
--- a/source/nmbd/nmbd_incomingrequests.c
+++ b/source/nmbd/nmbd_incomingrequests.c
@@ -1,5 +1,6 @@
/*
- Unix SMB/CIFS implementation.
+ Unix SMB/Netbios implementation.
+ Version 1.9.
NBT netbios routines and daemon - version 2
Copyright (C) Andrew Tridgell 1994-1998
Copyright (C) Luke Kenneth Casson Leighton 1994-1998
@@ -66,6 +67,7 @@ void process_name_release_request(struct subnet_record *subrec,
struct name_record *namerec;
int rcode = 0;
+ START_PROFILE(name_release);
putip((char *)&owner_ip,&nmb->additional->rdata[2]);
if(!bcast)
@@ -82,7 +84,7 @@ received for name %s from IP %s on subnet %s. Error - should be sent to WINS ser
nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name));
send_name_release_response(FMT_ERR, p);
- return;
+ goto done;
}
DEBUG(3,("process_name_release_request: Name release on name %s, \
@@ -92,7 +94,7 @@ subnet %s from owner IP %s\n",
/* If someone is releasing a broadcast group name, just ignore it. */
if( group && !ismyip(owner_ip) )
- return;
+ goto done;
/*
* Code to work around a bug in FTP OnNet software NBT implementation.
@@ -106,7 +108,7 @@ subnet %s from owner IP %s\n",
DEBUG(6,("process_name_release_request: FTP OnNet bug workaround. Ignoring \
group release name %s from IP %s on subnet %s with no group bit set.\n",
nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name ));
- return;
+ goto done;
}
namerec = find_name_on_subnet(subrec, &nmb->question.question_name, FIND_ANY_NAME);
@@ -123,10 +125,12 @@ on subnet %s being rejected as it is one of our names.\n",
}
if(rcode == 0)
- return;
+ goto done;
/* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
send_name_release_response(rcode, p);
+done:
+ END_PROFILE(name_release);
}
/****************************************************************************
@@ -162,6 +166,7 @@ void process_name_refresh_request(struct subnet_record *subrec,
BOOL bcast = nmb->header.nm_flags.bcast;
struct in_addr from_ip;
+ START_PROFILE(name_refresh);
putip((char *)&from_ip,&nmb->additional->rdata[2]);
if(!bcast)
@@ -179,7 +184,7 @@ received for name %s from IP %s on subnet %s.\n",
DEBUG(0,("Error - should be sent to WINS server\n"));
send_name_registration_response(FMT_ERR, 0, p);
- return;
+ goto done;
}
/* Just log a message. We really don't care about broadcast name
@@ -188,6 +193,8 @@ received for name %s from IP %s on subnet %s.\n",
DEBUG(3,("process_name_refresh_request: Name refresh for name %s \
IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
+done:
+ END_PROFILE(name_refresh);
}
/****************************************************************************
@@ -206,6 +213,7 @@ void process_name_registration_request(struct subnet_record *subrec,
int ttl = nmb->additional->ttl;
struct in_addr from_ip;
+ START_PROFILE(name_registration);
putip((char *)&from_ip,&nmb->additional->rdata[2]);
if(!bcast)
@@ -222,7 +230,7 @@ received for name %s from IP %s on subnet %s. Error - should be sent to WINS ser
nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
send_name_registration_response(FMT_ERR, 0, p);
- return;
+ goto done;
}
DEBUG(3,("process_name_registration_request: Name registration for name %s \
@@ -256,7 +264,7 @@ IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet
register a name that's a group name as a unique name */
send_name_registration_response(ACT_ERR, 0, p);
- return;
+ goto done;
}
else if(namerec != NULL)
{
@@ -266,7 +274,7 @@ IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet
DEBUG(3,("process_name_registration_request: Updated name record %s \
with IP %s on subnet %s\n",nmb_namestr(&namerec->name),inet_ntoa(from_ip), subrec->subnet_name));
- return;
+ goto done;
}
}
else
@@ -280,9 +288,11 @@ with IP %s on subnet %s\n",nmb_namestr(&namerec->name),inet_ntoa(from_ip), subre
{
/* Disallow group names when we have a unique name. */
send_name_registration_response(ACT_ERR, 0, p);
- return;
+ goto done;
}
}
+done:
+ END_PROFILE(name_registration);
}
/****************************************************************************
@@ -326,6 +336,7 @@ void process_node_status_request(struct subnet_record *subrec, struct packet_str
int names_added,i;
struct name_record *namerec;
+ START_PROFILE(node_status);
DEBUG(3,("process_node_status_request: status request for name %s from IP %s on \
subnet %s.\n", nmb_namestr(&nmb->question.question_name), inet_ntoa(p->ip),
subrec->subnet_name));
@@ -337,7 +348,7 @@ subnet %s.\n", nmb_namestr(&nmb->question.question_name), inet_ntoa(p->ip),
subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
inet_ntoa(p->ip), subrec->subnet_name));
- return;
+ goto done;
}
/* this is not an exact calculation. the 46 is for the stats buffer
@@ -434,6 +445,8 @@ subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
0, /* ttl. */
rdata, /* data to send. */
PTR_DIFF(buf,rdata)); /* data length. */
+done:
+ END_PROFILE(node_status);
}
@@ -449,151 +462,178 @@ For broadcast name queries:
void process_name_query_request(struct subnet_record *subrec, struct packet_struct *p)
{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question = &nmb->question.question_name;
- int name_type = question->name_type;
- BOOL bcast = nmb->header.nm_flags.bcast;
- int ttl=0;
- int rcode = 0;
- char *prdata = NULL;
- char rdata[6];
- BOOL success = False;
- struct name_record *namerec = NULL;
- int reply_data_len = 0;
- int i;
-
- DEBUG(3,("process_name_query_request: Name query from %s on subnet %s for name %s\n",
- inet_ntoa(p->ip), subrec->subnet_name, nmb_namestr(question)));
+ struct nmb_packet *nmb = &p->packet.nmb;
+ struct nmb_name *question = &nmb->question.question_name;
+ int name_type = question->name_type;
+ BOOL bcast = nmb->header.nm_flags.bcast;
+ int ttl=0;
+ int rcode = 0;
+ char *prdata = NULL;
+ char rdata[6];
+ BOOL success = False;
+ struct name_record *namerec = NULL;
+ int reply_data_len = 0;
+ int i;
+
+ START_PROFILE(name_query);
+ DEBUG(3,("process_name_query_request: Name query from %s on subnet %s for name %s\n",
+ inet_ntoa(p->ip), subrec->subnet_name, nmb_namestr(question)));
- /* Look up the name in the cache - if the request is a broadcast request that
- came from a subnet we don't know about then search all the broadcast subnets
- for a match (as we don't know what interface the request came in on). */
-
- if(subrec == remote_broadcast_subnet)
- namerec = find_name_for_remote_broadcast_subnet( question, FIND_ANY_NAME);
- else
- namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
-
- /* Check if it is a name that expired */
- if (namerec &&
- ((namerec->data.death_time != PERMANENT_TTL) &&
- (namerec->data.death_time < p->timestamp))) {
- DEBUG(5,("process_name_query_request: expired name %s\n", nmb_namestr(&namerec->name)));
- namerec = NULL;
- }
-
- if (namerec) {
- /*
- * Always respond to unicast queries.
- * Don't respond to broadcast queries unless the query is for
- * a name we own, a Primary Domain Controller name, or a WINS_PROXY
- * name with type 0 or 0x20. WINS_PROXY names are only ever added
- * into the namelist if we were configured as a WINS proxy.
- */
-
- if (!bcast ||
- (bcast && ((name_type == 0x1b) ||
- (namerec->data.source == SELF_NAME) ||
- (namerec->data.source == PERMANENT_NAME) ||
- ((namerec->data.source == WINS_PROXY_NAME) &&
- ((name_type == 0) || (name_type == 0x20)))))) {
- /* The requested name is a directed query, or it's SELF or PERMANENT or WINS_PROXY,
- or it's a Domain Master type. */
-
- /*
- * If this is a WINS_PROXY_NAME, then ceck that none of the IP
- * addresses we are returning is on the same broadcast subnet
- * as the requesting packet. If it is then don't reply as the
- * actual machine will be replying also and we don't want two
- * replies to a broadcast query.
- */
-
- if (namerec->data.source == WINS_PROXY_NAME) {
- for( i = 0; i < namerec->data.num_ips; i++) {
- if (same_net(namerec->data.ip[i], subrec->myip, subrec->mask_ip)) {
- DEBUG(5,("process_name_query_request: name %s is a WINS proxy name and is also on the same subnet (%s) as the requestor. Not replying.\n",
- nmb_namestr(&namerec->name), subrec->subnet_name ));
- return;
- }
- }
- }
-
- ttl = (namerec->data.death_time != PERMANENT_TTL) ?
- namerec->data.death_time - p->timestamp : lp_max_ttl();
-
- /* Copy all known ip addresses into the return data. */
- /* Optimise for the common case of one IP address so
- we don't need a malloc. */
-
- if (namerec->data.num_ips == 1) {
- prdata = rdata;
- } else {
- if ((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL) {
- DEBUG(0,("process_name_query_request: malloc fail !\n"));
- return;
- }
- }
-
- for (i = 0; i < namerec->data.num_ips; i++) {
- set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
- putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
- }
-
- sort_query_replies(prdata, i, p->ip);
-
- reply_data_len = namerec->data.num_ips * 6;
- success = True;
- }
- }
-
- /*
- * If a machine is broadcasting a name lookup request and we have lp_wins_proxy()
- * set we should initiate a WINS query here. On success we add the resolved name
- * into our namelist with a type of WINS_PROXY_NAME and then reply to the query.
- */
-
- if(!success && (namerec == NULL) && we_are_a_wins_client() && lp_wins_proxy() &&
- bcast && (subrec != remote_broadcast_subnet)) {
- make_wins_proxy_name_query_request( subrec, p, question );
- return;
- }
-
- if (!success && bcast) {
- if(prdata != rdata)
- SAFE_FREE(prdata);
- return; /* Never reply with a negative response to broadcasts. */
- }
-
- /*
- * Final check. From observation, if a unicast packet is sent
- * to a non-WINS server with the recursion desired bit set
- * then never send a negative response.
- */
-
- if(!success && !bcast && nmb->header.nm_flags.recursion_desired) {
- if(prdata != rdata)
- SAFE_FREE(prdata);
- return;
- }
-
- if (success) {
- rcode = 0;
- DEBUG(3,("OK\n"));
- } else {
- rcode = NAM_ERR;
- DEBUG(3,("UNKNOWN\n"));
- }
-
- /* See rfc1002.txt 4.2.13. */
-
- reply_netbios_packet(p, /* Packet to reply to. */
- rcode, /* Result code. */
- NMB_QUERY, /* nmbd type code. */
- NMB_NAME_QUERY_OPCODE, /* opcode. */
- ttl, /* ttl. */
- prdata, /* data to send. */
- reply_data_len); /* data length. */
-
- if(prdata != rdata)
- SAFE_FREE(prdata);
+ /* Look up the name in the cache - if the request is a broadcast request that
+ came from a subnet we don't know about then search all the broadcast subnets
+ for a match (as we don't know what interface the request came in on). */
+
+ if(subrec == remote_broadcast_subnet)
+ namerec = find_name_for_remote_broadcast_subnet( question, FIND_ANY_NAME);
+ else
+ namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
+
+
+ /* Check if it is a name that expired */
+ if( namerec
+ && ( (namerec->data.death_time != PERMANENT_TTL)
+ && (namerec->data.death_time < p->timestamp) ) )
+ {
+ DEBUG(5,("process_name_query_request: expired name %s\n", nmb_namestr(&namerec->name)));
+ namerec = NULL;
+ }
+
+ if (namerec)
+ {
+
+ /*
+ * Always respond to unicast queries.
+ * Don't respond to broadcast queries unless the query is for
+ * a name we own, a Primary Domain Controller name, or a WINS_PROXY
+ * name with type 0 or 0x20. WINS_PROXY names are only ever added
+ * into the namelist if we were configured as a WINS proxy.
+ */
+
+ if( !bcast
+ || ( bcast
+ && ( (name_type == 0x1b)
+ || (namerec->data.source == SELF_NAME)
+ || (namerec->data.source == PERMANENT_NAME)
+ || ( (namerec->data.source == WINS_PROXY_NAME)
+ && ( (name_type == 0) || (name_type == 0x20) )
+ )
+ )
+ )
+ )
+ {
+
+ /* The requested name is a directed query, or it's SELF or PERMANENT or WINS_PROXY,
+ or it's a Domain Master type. */
+
+ /*
+ * If this is a WINS_PROXY_NAME, then ceck that none of the IP
+ * addresses we are returning is on the same broadcast subnet
+ * as the requesting packet. If it is then don't reply as the
+ * actual machine will be replying also and we don't want two
+ * replies to a broadcast query.
+ */
+
+ if( namerec->data.source == WINS_PROXY_NAME )
+ {
+ for( i = 0; i < namerec->data.num_ips; i++)
+ {
+ if(same_net( namerec->data.ip[i], subrec->myip, subrec->mask_ip ))
+ {
+ DEBUG(5,("process_name_query_request: name %s is a WINS proxy name and is also \
+on the same subnet (%s) as the requestor. Not replying.\n",
+ nmb_namestr(&namerec->name), subrec->subnet_name ));
+ goto done;
+ }
+ }
+ }
+
+ ttl = (namerec->data.death_time != PERMANENT_TTL) ?
+ namerec->data.death_time - p->timestamp : lp_max_ttl();
+
+ /* Copy all known ip addresses into the return data. */
+ /* Optimise for the common case of one IP address so
+ we don't need a malloc. */
+
+ if( namerec->data.num_ips == 1 )
+ prdata = rdata;
+ else
+ {
+ if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL)
+ {
+ DEBUG(0,("process_name_query_request: malloc fail !\n"));
+ goto done;
+ }
+ }
+
+ for( i = 0; i < namerec->data.num_ips; i++ )
+ {
+ set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
+ putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
+ }
+
+ sort_query_replies(prdata, i, p->ip);
+
+ reply_data_len = namerec->data.num_ips * 6;
+ success = True;
+ }
+ }
+
+ /*
+ * If a machine is broadcasting a name lookup request and we have lp_wins_proxy()
+ * set we should initiate a WINS query here. On success we add the resolved name
+ * into our namelist with a type of WINS_PROXY_NAME and then reply to the query.
+ */
+
+ if(!success && (namerec == NULL) && we_are_a_wins_client() && lp_wins_proxy() &&
+ bcast && (subrec != remote_broadcast_subnet))
+ {
+ make_wins_proxy_name_query_request( subrec, p, question );
+ goto done;
+ }
+
+ if (!success && bcast)
+ {
+ if((prdata != rdata) && (prdata != NULL))
+ SAFE_FREE(prdata);
+ goto done; /* Never reply with a negative response to broadcasts. */
+ }
+
+ /*
+ * Final check. From observation, if a unicast packet is sent
+ * to a non-WINS server with the recursion desired bit set
+ * then never send a negative response.
+ */
+
+ if(!success && !bcast && nmb->header.nm_flags.recursion_desired)
+ {
+ if((prdata != rdata) && (prdata != NULL))
+ SAFE_FREE(prdata);
+ goto done;
+ }
+
+ if (success)
+ {
+ rcode = 0;
+ DEBUG(3,("OK\n"));
+ }
+ else
+ {
+ rcode = NAM_ERR;
+ DEBUG(3,("UNKNOWN\n"));
+ }
+
+ /* See rfc1002.txt 4.2.13. */
+
+ reply_netbios_packet(p, /* Packet to reply to. */
+ rcode, /* Result code. */
+ NMB_QUERY, /* nmbd type code. */
+ NMB_NAME_QUERY_OPCODE, /* opcode. */
+ ttl, /* ttl. */
+ prdata, /* data to send. */
+ reply_data_len); /* data length. */
+
+ if((prdata != rdata) && (prdata != NULL))
+ SAFE_FREE(prdata);
+done:
+ END_PROFILE(name_query);
}