summaryrefslogtreecommitdiff
path: root/source4/nmbd/nmbd_incomingrequests.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/nmbd/nmbd_incomingrequests.c')
-rw-r--r--source4/nmbd/nmbd_incomingrequests.c596
1 files changed, 0 insertions, 596 deletions
diff --git a/source4/nmbd/nmbd_incomingrequests.c b/source4/nmbd/nmbd_incomingrequests.c
deleted file mode 100644
index 916f7763f2..0000000000
--- a/source4/nmbd/nmbd_incomingrequests.c
+++ /dev/null
@@ -1,596 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
-
- 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- This file contains all the code to process NetBIOS requests coming
- in on port 137. It does not deal with the code needed to service
- WINS server requests, but only broadcast and unicast requests.
-
-*/
-
-#include "includes.h"
-
-/****************************************************************************
-Send a name release response.
-**************************************************************************/
-
-static void send_name_release_response(int rcode, struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- char rdata[6];
-
- memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
-
- reply_netbios_packet(p, /* Packet to reply to. */
- rcode, /* Result code. */
- NMB_REL, /* nmbd type code. */
- NMB_NAME_RELEASE_OPCODE, /* opcode. */
- 0, /* ttl. */
- rdata, /* data to send. */
- 6); /* data length. */
-}
-
-/****************************************************************************
-Process a name release packet on a broadcast subnet.
-Ignore it if it's not one of our names.
-****************************************************************************/
-
-void process_name_release_request(struct subnet_record *subrec,
- struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct in_addr owner_ip;
- struct nmb_name *question = &nmb->question.question_name;
- BOOL bcast = nmb->header.nm_flags.bcast;
- uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
- BOOL group = (nb_flags & NB_GROUP) ? True : False;
- struct name_record *namerec;
- int rcode = 0;
-
- putip((char *)&owner_ip,&nmb->additional->rdata[2]);
-
- if(!bcast)
- {
- /* We should only get broadcast name release packets here.
- Anyone trying to release unicast should be going to a WINS
- server. If the code gets here, then either we are not a wins
- server and they sent it anyway, or we are a WINS server and
- the request was malformed. Either way, log an error here.
- and send an error reply back.
- */
- DEBUG(0,("process_name_release_request: unicast name release request \
-received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
- nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name));
-
- send_name_release_response(FMT_ERR, p);
- return;
- }
-
- DEBUG(3,("process_name_release_request: Name release on name %s, \
-subnet %s from owner IP %s\n",
- nmb_namestr(&nmb->question.question_name),
- subrec->subnet_name, inet_ntoa(owner_ip)));
-
- /* If someone is releasing a broadcast group name, just ignore it. */
- if( group && !ismyip(owner_ip) )
- return;
-
- /*
- * Code to work around a bug in FTP OnNet software NBT implementation.
- * They do a broadcast name release for WORKGROUP<0> and WORKGROUP<1e>
- * names and *don't set the group bit* !!!!!
- */
-
- if( !group && !ismyip(owner_ip) && strequal(question->name, lp_workgroup()) &&
- ((question->name_type == 0x0) || (question->name_type == 0x1e)))
- {
- 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;
- }
-
- namerec = find_name_on_subnet(subrec, &nmb->question.question_name, FIND_ANY_NAME);
-
- /* We only care about someone trying to release one of our names. */
- if( namerec
- && ( (namerec->data.source == SELF_NAME)
- || (namerec->data.source == PERMANENT_NAME) ) )
- {
- rcode = ACT_ERR;
- DEBUG(0, ("process_name_release_request: Attempt to release name %s from IP %s \
-on subnet %s being rejected as it is one of our names.\n",
- nmb_namestr(&nmb->question.question_name), inet_ntoa(owner_ip), subrec->subnet_name));
- }
-
- if(rcode == 0)
- return;
-
- /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
- send_name_release_response(rcode, p);
-}
-
-/****************************************************************************
-Send a name registration response.
-**************************************************************************/
-
-static void send_name_registration_response(int rcode, int ttl, struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- char rdata[6];
-
- memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
-
- reply_netbios_packet(p, /* Packet to reply to. */
- rcode, /* Result code. */
- NMB_REG, /* nmbd type code. */
- NMB_NAME_REG_OPCODE, /* opcode. */
- ttl, /* ttl. */
- rdata, /* data to send. */
- 6); /* data length. */
-}
-
-/****************************************************************************
-Process a name refresh request on a broadcast subnet.
-**************************************************************************/
-
-void process_name_refresh_request(struct subnet_record *subrec,
- struct packet_struct *p)
-{
-
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question = &nmb->question.question_name;
- BOOL bcast = nmb->header.nm_flags.bcast;
- struct in_addr from_ip;
-
- putip((char *)&from_ip,&nmb->additional->rdata[2]);
-
- if(!bcast)
- {
- /* We should only get broadcast name refresh packets here.
- Anyone trying to refresh unicast should be going to a WINS
- server. If the code gets here, then either we are not a wins
- server and they sent it anyway, or we are a WINS server and
- the request was malformed. Either way, log an error here.
- and send an error reply back.
- */
- DEBUG(0,("process_name_refresh_request: unicast name registration request \
-received for name %s from IP %s on subnet %s.\n",
- nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
- DEBUG(0,("Error - should be sent to WINS server\n"));
-
- send_name_registration_response(FMT_ERR, 0, p);
- return;
- }
-
- /* Just log a message. We really don't care about broadcast name
- refreshes. */
-
- 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));
-
-}
-
-/****************************************************************************
-Process a name registration request on a broadcast subnet.
-**************************************************************************/
-
-void process_name_registration_request(struct subnet_record *subrec,
- struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question = &nmb->question.question_name;
- BOOL bcast = nmb->header.nm_flags.bcast;
- uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
- BOOL group = (nb_flags & NB_GROUP) ? True : False;
- struct name_record *namerec = NULL;
- int ttl = nmb->additional->ttl;
- struct in_addr from_ip;
-
- putip((char *)&from_ip,&nmb->additional->rdata[2]);
-
- if(!bcast)
- {
- /* We should only get broadcast name registration packets here.
- Anyone trying to register unicast should be going to a WINS
- server. If the code gets here, then either we are not a wins
- server and they sent it anyway, or we are a WINS server and
- the request was malformed. Either way, log an error here.
- and send an error reply back.
- */
- DEBUG(0,("process_name_registration_request: unicast name registration request \
-received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
- nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
-
- send_name_registration_response(FMT_ERR, 0, p);
- return;
- }
-
- DEBUG(3,("process_name_registration_request: Name registration for name %s \
-IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
-
- /* See if the name already exists. */
- namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
-
- /*
- * If the name being registered exists and is a WINS_PROXY_NAME
- * then delete the WINS proxy name entry so we don't reply erroneously
- * later to queries.
- */
-
- if((namerec != NULL) && (namerec->data.source == WINS_PROXY_NAME))
- {
- remove_name_from_namelist( subrec, namerec );
- namerec = NULL;
- }
-
- if (!group)
- {
- /* Unique name. */
-
- if( (namerec != NULL)
- && ( (namerec->data.source == SELF_NAME)
- || (namerec->data.source == PERMANENT_NAME)
- || NAME_GROUP(namerec) ) )
- {
- /* No-one can register one of Samba's names, nor can they
- register a name that's a group name as a unique name */
-
- send_name_registration_response(ACT_ERR, 0, p);
- return;
- }
- else if(namerec != NULL)
- {
- /* Update the namelist record with the new information. */
- namerec->data.ip[0] = from_ip;
- update_name_ttl(namerec, ttl);
-
- 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;
- }
- }
- else
- {
- /* Group name. */
-
- if( (namerec != NULL)
- && !NAME_GROUP(namerec)
- && ( (namerec->data.source == SELF_NAME)
- || (namerec->data.source == PERMANENT_NAME) ) )
- {
- /* Disallow group names when we have a unique name. */
- send_name_registration_response(ACT_ERR, 0, p);
- return;
- }
- }
-}
-
-/****************************************************************************
-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)
-{
- int l1,l2,l3;
-
- /* It's 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(lp_netbios_name());
-
- if ((l1==l3) && strncmp(n1,lp_netbios_name(),l3) == 0 &&
- (l2!=l3 || strncmp(n2,lp_netbios_name(),l3) != 0))
- return -1;
-
- if ((l2==l3) && strncmp(n2,lp_netbios_name(),l3) == 0 &&
- (l1!=l3 || strncmp(n1,lp_netbios_name(),l3) != 0))
- return 1;
-
- return memcmp(n1,n2,18);
-}
-
-
-/****************************************************************************
- Process a node status query
- ****************************************************************************/
-
-void process_node_status_request(struct subnet_record *subrec, struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- 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, *buf0;
- int names_added,i;
- struct name_record *namerec;
-
- 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));
-
- if((namerec = find_name_on_subnet(subrec, &nmb->question.question_name,
- FIND_SELF_NAME)) == 0)
- {
- DEBUG(1,("process_node_status_request: status request for name %s from IP %s on \
-subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
- inet_ntoa(p->ip), subrec->subnet_name));
-
- return;
- }
-
- /* this is not an exact calculation. the 46 is for the stats buffer
- and the 60 is to leave room for the header etc */
- bufend = &rdata[MAX_DGRAM_SIZE] - (18 + 46 + 60);
- countptr = buf = rdata;
- buf += 1;
- buf0 = buf;
-
- names_added = 0;
-
- namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
-
- while (buf < bufend)
- {
- if( (namerec->data.source == SELF_NAME)
- || (namerec->data.source == PERMANENT_NAME) )
- {
- int name_type = namerec->name.name_type;
-
- if (!strequal(namerec->name.name,"*") &&
- !strequal(namerec->name.name,"__SAMBA__") &&
- (name_type < 0x1b || name_type >= 0x20 ||
- ques_type < 0x1b || ques_type >= 0x20 ||
- strequal(qname, namerec->name.name)))
- {
- /* Start with the name. */
- memset(buf,'\0',18);
- slprintf(buf, 17, "%-15.15s",namerec->name.name);
- strupper(buf);
-
- /* Put the name type and netbios flags in the buffer. */
- buf[15] = name_type;
- set_nb_flags( &buf[16],namerec->data.nb_flags );
- buf[16] |= NB_ACTIVE; /* all our names are active */
-
- buf += 18;
-
- names_added++;
- }
- }
-
- /* Remove duplicate names. */
- if (names_added > 1) {
- 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;
-
- namerec = (struct name_record *)ubi_trNext( namerec );
-
- if (!namerec)
- {
- /* End of the subnet specific name list. Now
- add the names on the unicast subnet . */
- struct subnet_record *uni_subrec = unicast_subnet;
-
- if (uni_subrec != subrec)
- {
- subrec = uni_subrec;
- namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
- }
- }
- if (!namerec)
- break;
-
- }
-
- SCVAL(countptr,0,names_added);
-
- /* We don't send any stats as they could be used to attack
- the protocol. */
- memset(buf,'\0',46);
-
- buf += 46;
-
- /* Send a NODE STATUS RESPONSE */
- reply_netbios_packet(p, /* Packet to reply to. */
- 0, /* Result code. */
- NMB_STATUS, /* nmbd type code. */
- NMB_NAME_QUERY_OPCODE, /* opcode. */
- 0, /* ttl. */
- rdata, /* data to send. */
- PTR_DIFF(buf,rdata)); /* data length. */
-}
-
-
-/***************************************************************************
-Process a name query.
-
-For broadcast name queries:
-
- - Only reply if the query is for one of YOUR names.
- - NEVER send a negative response to a broadcast query.
-
-****************************************************************************/
-
-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)));
-
- /* 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);
-}