LCOV - code coverage report
Current view: top level - source3/nmbd - nmbd_incomingrequests.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 138 226 61.1 %
Date: 2021-09-23 10:06:22 Functions: 5 8 62.5 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    NBT netbios routines and daemon - version 2
       4             :    Copyright (C) Andrew Tridgell 1994-1998
       5             :    Copyright (C) Luke Kenneth Casson Leighton 1994-1998
       6             :    Copyright (C) Jeremy Allison 1994-2003
       7             :    
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             :    
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             :    
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             :    
      21             :    This file contains all the code to process NetBIOS requests coming
      22             :    in on port 137. It does not deal with the code needed to service
      23             :    WINS server requests, but only broadcast and unicast requests.
      24             : 
      25             : */
      26             : 
      27             : #include "includes.h"
      28             : #include "nmbd/nmbd.h"
      29             : 
      30             : /****************************************************************************
      31             : Send a name release response.
      32             : **************************************************************************/
      33             : 
      34           0 : static void send_name_release_response(int rcode, struct packet_struct *p)
      35             : {
      36           0 :         struct nmb_packet *nmb = &p->packet.nmb;
      37             :         char rdata[6];
      38             : 
      39           0 :         memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
      40             :   
      41           0 :         reply_netbios_packet(p,                       /* Packet to reply to. */
      42             :                         rcode,                        /* Result code. */
      43             :                         NMB_REL,                      /* nmbd type code. */
      44             :                         NMB_NAME_RELEASE_OPCODE,      /* opcode. */
      45             :                         0,                            /* ttl. */
      46             :                         rdata,                        /* data to send. */
      47             :                         6);                           /* data length. */
      48           0 : }
      49             : 
      50             : /****************************************************************************
      51             : Process a name release packet on a broadcast subnet.
      52             : Ignore it if it's not one of our names.
      53             : ****************************************************************************/
      54             : 
      55           0 : void process_name_release_request(struct subnet_record *subrec, 
      56             :                                   struct packet_struct *p)
      57             : {
      58           0 :         struct nmb_packet *nmb = &p->packet.nmb;
      59             :         struct in_addr owner_ip;
      60           0 :         struct nmb_name *question = &nmb->question.question_name;
      61             :         unstring qname;
      62           0 :         bool bcast = nmb->header.nm_flags.bcast;
      63           0 :         uint16_t nb_flags = get_nb_flags(nmb->additional->rdata);
      64           0 :         bool group = (nb_flags & NB_GROUP) ? True : False;
      65             :         struct name_record *namerec;
      66           0 :         int rcode = 0;
      67             :   
      68           0 :         putip((char *)&owner_ip,&nmb->additional->rdata[2]);  
      69             :   
      70           0 :         if(!bcast) {
      71             :                 /* We should only get broadcast name release packets here.
      72             :                    Anyone trying to release unicast should be going to a WINS
      73             :                    server. If the code gets here, then either we are not a wins
      74             :                    server and they sent it anyway, or we are a WINS server and
      75             :                    the request was malformed. Either way, log an error here.
      76             :                    and send an error reply back.
      77             :                 */
      78           0 :                 DEBUG(0,("process_name_release_request: unicast name release request \
      79             : received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
      80             :                         nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name));      
      81             : 
      82           0 :                 send_name_release_response(FMT_ERR, p);
      83           0 :                 return;
      84             :         }
      85             : 
      86           0 :         DEBUG(3,("process_name_release_request: Name release on name %s, \
      87             : subnet %s from owner IP %s\n",
      88             :                 nmb_namestr(&nmb->question.question_name),
      89             :                 subrec->subnet_name, inet_ntoa(owner_ip)));
      90             :   
      91             :         /* If someone is releasing a broadcast group name, just ignore it. */
      92           0 :         if( group && !ismyip_v4(owner_ip) )
      93           0 :                 return;
      94             : 
      95             :         /*
      96             :          * Code to work around a bug in FTP OnNet software NBT implementation.
      97             :          * They do a broadcast name release for WORKGROUP<0> and WORKGROUP<1e>
      98             :          * names and *don't set the group bit* !!!!!
      99             :          */
     100             : 
     101           0 :         pull_ascii_nstring(qname, sizeof(qname), question->name);
     102           0 :         if( !group && !ismyip_v4(owner_ip) && strequal(qname, lp_workgroup()) && 
     103           0 :                         ((question->name_type == 0x0) || (question->name_type == 0x1e))) {
     104           0 :                 DEBUG(6,("process_name_release_request: FTP OnNet bug workaround. Ignoring \
     105             : group release name %s from IP %s on subnet %s with no group bit set.\n",
     106             :                         nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name ));
     107           0 :                 return;
     108             :         }
     109             : 
     110           0 :         namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
     111             : 
     112             :         /* We only care about someone trying to release one of our names. */
     113           0 :         if( namerec && ( (namerec->data.source == SELF_NAME)
     114           0 :                         || (namerec->data.source == PERMANENT_NAME) ) ) {
     115           0 :                 rcode = ACT_ERR;
     116           0 :                 DEBUG(0, ("process_name_release_request: Attempt to release name %s from IP %s \
     117             : on subnet %s being rejected as it is one of our names.\n", 
     118             :                 nmb_namestr(&nmb->question.question_name), inet_ntoa(owner_ip), subrec->subnet_name));
     119             :         }
     120             : 
     121           0 :         if(rcode == 0)
     122           0 :                 return;
     123             : 
     124             :         /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
     125           0 :         send_name_release_response(rcode, p);
     126             : }
     127             : 
     128             : /****************************************************************************
     129             : Send a name registration response.
     130             : **************************************************************************/
     131             : 
     132           7 : static void send_name_registration_response(int rcode, int ttl, struct packet_struct *p)
     133             : {
     134           7 :         struct nmb_packet *nmb = &p->packet.nmb;
     135             :         char rdata[6];
     136             : 
     137           7 :         memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
     138             :   
     139           7 :         reply_netbios_packet(p,                                /* Packet to reply to. */
     140             :                                 rcode,                         /* Result code. */
     141             :                                 NMB_REG,                       /* nmbd type code. */
     142             :                                 NMB_NAME_REG_OPCODE,           /* opcode. */
     143             :                                 ttl,                           /* ttl. */
     144             :                                 rdata,                         /* data to send. */
     145             :                                 6);                            /* data length. */
     146           7 : }
     147             : 
     148             : /****************************************************************************
     149             : Process a name refresh request on a broadcast subnet.
     150             : **************************************************************************/
     151             :      
     152           0 : void process_name_refresh_request(struct subnet_record *subrec,
     153             :                                   struct packet_struct *p)
     154             : {    
     155           0 :         struct nmb_packet *nmb = &p->packet.nmb;
     156           0 :         struct nmb_name *question = &nmb->question.question_name;
     157           0 :         bool bcast = nmb->header.nm_flags.bcast;
     158             :         struct in_addr from_ip;
     159             :   
     160           0 :         putip((char *)&from_ip,&nmb->additional->rdata[2]);
     161             : 
     162           0 :         if(!bcast) { 
     163             :                 /* We should only get broadcast name refresh packets here.
     164             :                    Anyone trying to refresh unicast should be going to a WINS
     165             :                    server. If the code gets here, then either we are not a wins
     166             :                    server and they sent it anyway, or we are a WINS server and
     167             :                    the request was malformed. Either way, log an error here.
     168             :                    and send an error reply back.
     169             :                 */
     170           0 :                 DEBUG(0,("process_name_refresh_request: unicast name registration request \
     171             : received for name %s from IP %s on subnet %s.\n",
     172             :                         nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
     173           0 :                 DEBUG(0,("Error - should be sent to WINS server\n"));
     174             :     
     175           0 :                 send_name_registration_response(FMT_ERR, 0, p);
     176           0 :                 return;
     177             :         } 
     178             : 
     179             :         /* Just log a message. We really don't care about broadcast name refreshes. */
     180             :      
     181           0 :         DEBUG(3,("process_name_refresh_request: Name refresh for name %s \
     182             : IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
     183             : }
     184             :     
     185             : /****************************************************************************
     186             : Process a name registration request on a broadcast subnet.
     187             : **************************************************************************/
     188             : 
     189        1928 : void process_name_registration_request(struct subnet_record *subrec, 
     190             :                                        struct packet_struct *p)
     191             : {
     192        1928 :         struct nmb_packet *nmb = &p->packet.nmb;
     193        1928 :         struct nmb_name *question = &nmb->question.question_name;
     194        1928 :         bool bcast = nmb->header.nm_flags.bcast;
     195        1928 :         uint16_t nb_flags = get_nb_flags(nmb->additional->rdata);
     196        1928 :         bool group = (nb_flags & NB_GROUP) ? True : False;
     197        1928 :         struct name_record *namerec = NULL;
     198        1928 :         int ttl = nmb->additional->ttl;
     199             :         struct in_addr from_ip;
     200             :   
     201        1928 :         putip((char *)&from_ip,&nmb->additional->rdata[2]);
     202             :   
     203        1928 :         if(!bcast) {
     204             :                 /* We should only get broadcast name registration packets here.
     205             :                    Anyone trying to register unicast should be going to a WINS
     206             :                    server. If the code gets here, then either we are not a wins
     207             :                    server and they sent it anyway, or we are a WINS server and
     208             :                    the request was malformed. Either way, log an error here.
     209             :                    and send an error reply back.
     210             :                 */
     211           0 :                 DEBUG(0,("process_name_registration_request: unicast name registration request \
     212             : received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
     213             :                         nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));      
     214             : 
     215           0 :                 send_name_registration_response(FMT_ERR, 0, p);
     216           0 :                 return;
     217             :         }
     218             : 
     219        1928 :         DEBUG(3,("process_name_registration_request: Name registration for name %s \
     220             : IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
     221             :   
     222             :         /* See if the name already exists. */
     223        1928 :         namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
     224             :  
     225             :         /* 
     226             :          * If the name being registered exists and is a WINS_PROXY_NAME 
     227             :          * then delete the WINS proxy name entry so we don't reply erroneously
     228             :          * later to queries.
     229             :          */
     230             : 
     231        1928 :         if((namerec != NULL) && (namerec->data.source == WINS_PROXY_NAME)) {
     232           0 :                 remove_name_from_namelist( subrec, namerec );
     233           0 :                 namerec = NULL;
     234             :         }
     235             : 
     236        1928 :         if (!group) {
     237             :                 /* Unique name. */
     238             : 
     239        1146 :                 if( (namerec != NULL)
     240           6 :                                 && ( (namerec->data.source == SELF_NAME)
     241           0 :                                 || (namerec->data.source == PERMANENT_NAME)
     242           0 :                                 || NAME_GROUP(namerec) ) ) {
     243             :                         /* No-one can register one of Samba's names, nor can they
     244             :                                 register a name that's a group name as a unique name */
     245             : 
     246           6 :                         send_name_registration_response(ACT_ERR, 0, p);
     247           6 :                         return;
     248        1140 :                 } else if(namerec != NULL) {
     249             :                         /* Update the namelist record with the new information. */
     250           0 :                         namerec->data.ip[0] = from_ip;
     251           0 :                         update_name_ttl(namerec, ttl);
     252             : 
     253           0 :                         DEBUG(3,("process_name_registration_request: Updated name record %s \
     254             : with IP %s on subnet %s\n",nmb_namestr(&namerec->name),inet_ntoa(from_ip), subrec->subnet_name));
     255           0 :                         return;
     256             :                 }
     257             :         } else {
     258             :                 /* Group name. */
     259             : 
     260         782 :                 if( (namerec != NULL)
     261         207 :                                 && !NAME_GROUP(namerec)
     262           1 :                                 && ( (namerec->data.source == SELF_NAME)
     263           0 :                                 || (namerec->data.source == PERMANENT_NAME) ) ) {
     264             :                         /* Disallow group names when we have a unique name. */
     265           1 :                         send_name_registration_response(ACT_ERR, 0, p);  
     266           1 :                         return;  
     267             :                 }  
     268             :         }
     269             : }
     270             : 
     271             : /****************************************************************************
     272             : This is used to sort names for a name status into a sensible order.
     273             : We put our own names first, then in alphabetical order.
     274             : **************************************************************************/
     275             : 
     276        4222 : static int status_compare(char *n1,char *n2)
     277             : {
     278             :         unstring name1, name2;
     279             :         int l1,l2,l3;
     280             : 
     281        4222 :         memset(name1, '\0', sizeof(name1));
     282        4222 :         memset(name2, '\0', sizeof(name2));
     283        4222 :         pull_ascii_nstring(name1, sizeof(name1), n1);
     284        4222 :         pull_ascii_nstring(name2, sizeof(name2), n2);
     285        4222 :         n1 = name1;
     286        4222 :         n2 = name2;
     287             : 
     288             :         /* It's a bit tricky because the names are space padded */
     289        6101 :         for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++)
     290             :                 ;
     291        5712 :         for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++)
     292             :                 ;
     293        4222 :         l3 = strlen(lp_netbios_name());
     294             : 
     295        4222 :         if ((l1==l3) && strncmp(n1,lp_netbios_name(),l3) == 0 &&
     296         768 :                         (l2!=l3 || strncmp(n2,lp_netbios_name(),l3) != 0))
     297         826 :                 return -1;
     298             : 
     299        3396 :         if ((l2==l3) && strncmp(n2,lp_netbios_name(),l3) == 0 &&
     300         720 :                         (l1!=l3 || strncmp(n1,lp_netbios_name(),l3) != 0))
     301         454 :                 return 1;
     302             : 
     303        2942 :         return memcmp(n1,n2,sizeof(name1));
     304             : }
     305             : 
     306             : /****************************************************************************
     307             :   Process a node status query
     308             :   ****************************************************************************/
     309             : 
     310          50 : void process_node_status_request(struct subnet_record *subrec, struct packet_struct *p)
     311             : {
     312          50 :         struct nmb_packet *nmb = &p->packet.nmb;
     313             :         unstring qname;
     314          50 :         int ques_type = nmb->question.question_name.name_type;
     315             :         char rdata[MAX_DGRAM_SIZE];
     316             :         char *countptr, *buf, *bufend, *buf0;
     317             :         int names_added,i;
     318          50 :         struct name_record *namerec = NULL;
     319             : 
     320          50 :         pull_ascii_nstring(qname, sizeof(qname), nmb->question.question_name.name);
     321             : 
     322          50 :         DEBUG(3,("process_node_status_request: status request for name %s from IP %s on \
     323             : subnet %s.\n", nmb_namestr(&nmb->question.question_name), inet_ntoa(p->ip), subrec->subnet_name));
     324             : 
     325          50 :         if(find_name_on_subnet(subrec, &nmb->question.question_name, FIND_SELF_NAME) == 0) {
     326           0 :                 DEBUG(1,("process_node_status_request: status request for name %s from IP %s on \
     327             : subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
     328             :                         inet_ntoa(p->ip), subrec->subnet_name));
     329             : 
     330           0 :                 return;
     331             :         }
     332             :  
     333             :         /* this is not an exact calculation. the 46 is for the stats buffer
     334             :                 and the 60 is to leave room for the header etc */
     335          50 :         bufend = &rdata[MAX_DGRAM_SIZE-1] - (18 + 46 + 60);
     336          50 :         countptr = buf = rdata;
     337          50 :         buf += 1;
     338          50 :         buf0 = buf;
     339             : 
     340          50 :         names_added = 0;
     341             : 
     342          50 :         namerec = subrec->namelist;
     343             : 
     344         625 :         while (PTR_DIFF(bufend, buf) > 0) {
     345         576 :                 if( (namerec->data.source == SELF_NAME) || (namerec->data.source == PERMANENT_NAME) ) {
     346         576 :                         int name_type = namerec->name.name_type;
     347             :                         unstring name;
     348             : 
     349         576 :                         pull_ascii_nstring(name, sizeof(name), namerec->name.name);
     350         576 :                         if (!strupper_m(name)) {
     351           0 :                                 DEBUG(2,("strupper_m %s failed\n", name));
     352           0 :                                 return;
     353             :                         }
     354        1037 :                         if (!strequal(name,"*") &&
     355         839 :                                         !strequal(name,"__SAMBA__") &&
     356         188 :                                         (name_type < 0x1b || name_type >= 0x20 || 
     357          68 :                                         ques_type < 0x1b || ques_type >= 0x20 ||
     358          34 :                                         strequal(qname, name))) {
     359             :                                 /* Start with the name. */
     360             :                                 size_t len;
     361         376 :                                 push_ascii_nstring(buf, name);
     362         376 :                                 len = strlen(buf);
     363         376 :                                 memset(buf + len, ' ', MAX_NETBIOSNAME_LEN - len - 1);
     364         376 :                                 buf[MAX_NETBIOSNAME_LEN - 1] = '\0';
     365             : 
     366             :                                 /* Put the name type and netbios flags in the buffer. */
     367             : 
     368         376 :                                 buf[15] = name_type;
     369         376 :                                 set_nb_flags( &buf[16],namerec->data.nb_flags );
     370         376 :                                 buf[16] |= NB_ACTIVE; /* all our names are active */
     371             : 
     372         376 :                                 buf += 18;
     373             : 
     374         376 :                                 names_added++;
     375             :                         }
     376             :                 }
     377             : 
     378             :                 /* Remove duplicate names. */
     379         576 :                 if (names_added > 1) {
     380             :                         /* TODO: should use a real type and
     381             :                            TYPESAFE_QSORT() */
     382         526 :                         qsort( buf0, names_added, 18, QSORT_CAST status_compare );
     383             :                 }
     384             : 
     385        3176 :                 for( i=1; i < names_added ; i++ ) {
     386        2600 :                         if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) {
     387           0 :                                 names_added--;
     388           0 :                                 if (names_added == i)
     389           0 :                                         break;
     390           0 :                                 memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i));
     391           0 :                                 i--;
     392             :                         }
     393             :                 }
     394             : 
     395         576 :                 buf = buf0 + 18*names_added;
     396             : 
     397         576 :                 namerec = namerec->next;
     398             : 
     399         576 :                 if (!namerec) {
     400             :                         /* End of the subnet specific name list. Now 
     401             :                                 add the names on the unicast subnet . */
     402          50 :                         struct subnet_record *uni_subrec = unicast_subnet;
     403             : 
     404          50 :                         if (uni_subrec != subrec) {
     405           0 :                                 subrec = uni_subrec;
     406           0 :                                 namerec = subrec->namelist;
     407             :                         }
     408             :                 }
     409         576 :                 if (!namerec)
     410          50 :                         break;
     411             : 
     412             :         }
     413             :   
     414          50 :         SCVAL(countptr,0,names_added);
     415             :   
     416             :         /* We don't send any stats as they could be used to attack
     417             :                 the protocol. */
     418          50 :         memset(buf,'\0',46);
     419             :   
     420          50 :         buf += 46;
     421             :   
     422             :         /* Send a NODE STATUS RESPONSE */
     423          50 :         reply_netbios_packet(p,                               /* Packet to reply to. */
     424             :                                 0,                            /* Result code. */
     425             :                                 NMB_STATUS,                   /* nmbd type code. */
     426             :                                 NMB_NAME_QUERY_OPCODE,        /* opcode. */
     427             :                                 0,                            /* ttl. */
     428             :                                 rdata,                        /* data to send. */
     429          50 :                                 PTR_DIFF(buf,rdata));         /* data length. */
     430             : }
     431             : 
     432             : 
     433             : /***************************************************************************
     434             : Process a name query.
     435             : 
     436             : For broadcast name queries:
     437             : 
     438             :   - Only reply if the query is for one of YOUR names.
     439             :   - NEVER send a negative response to a broadcast query.
     440             : 
     441             : ****************************************************************************/
     442             : 
     443        3068 : void process_name_query_request(struct subnet_record *subrec, struct packet_struct *p)
     444             : {
     445        3068 :         struct nmb_packet *nmb = &p->packet.nmb;
     446        3068 :         struct nmb_name *question = &nmb->question.question_name;
     447        3068 :         int name_type = question->name_type;
     448        3068 :         bool bcast = nmb->header.nm_flags.bcast;
     449        3068 :         int ttl=0;
     450        3068 :         int rcode = 0;
     451        3068 :         char *prdata = NULL;
     452             :         char rdata[6];
     453        3068 :         bool success = False;
     454        3068 :         struct name_record *namerec = NULL;
     455        3068 :         int reply_data_len = 0;
     456             :         int i;
     457             :         
     458        3068 :         DEBUG(3,("process_name_query_request: Name query from %s on subnet %s for name %s\n", 
     459             :                  inet_ntoa(p->ip), subrec->subnet_name, nmb_namestr(question)));
     460             :   
     461             :         /* Look up the name in the cache - if the request is a broadcast request that
     462             :            came from a subnet we don't know about then search all the broadcast subnets
     463             :            for a match (as we don't know what interface the request came in on). */
     464             : 
     465        3068 :         if(subrec == remote_broadcast_subnet)
     466           0 :                 namerec = find_name_for_remote_broadcast_subnet( question, FIND_ANY_NAME);
     467             :         else
     468        3068 :                 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
     469             : 
     470             :         /* Check if it is a name that expired */
     471        3785 :         if (namerec && 
     472         783 :             ((namerec->data.death_time != PERMANENT_TTL) && 
     473           0 :              (namerec->data.death_time < p->timestamp))) {
     474           0 :                 DEBUG(5,("process_name_query_request: expired name %s\n", nmb_namestr(&namerec->name)));
     475           0 :                 namerec = NULL;
     476             :         }
     477             : 
     478        3068 :         if (namerec) {
     479             :                 /* 
     480             :                  * Always respond to unicast queries.
     481             :                  * Don't respond to broadcast queries unless the query is for
     482             :                  * a name we own, a Primary Domain Controller name, or a WINS_PROXY 
     483             :                  * name with type 0 or 0x20. WINS_PROXY names are only ever added
     484             :                  * into the namelist if we were configured as a WINS proxy.
     485             :                  */
     486             :                 
     487         783 :                 if (!bcast || 
     488        1189 :                     (bcast && ((name_type == 0x1b) ||
     489         680 :                                (namerec->data.source == SELF_NAME) ||
     490          87 :                                (namerec->data.source == PERMANENT_NAME) ||
     491           0 :                                ((namerec->data.source == WINS_PROXY_NAME) &&
     492           0 :                                 ((name_type == 0) || (name_type == 0x20)))))) {
     493             :                         /* The requested name is a directed query, or it's SELF or PERMANENT or WINS_PROXY, 
     494             :                            or it's a Domain Master type. */
     495             : 
     496             :                         /*
     497             :                          * If this is a WINS_PROXY_NAME, then ceck that none of the IP 
     498             :                          * addresses we are returning is on the same broadcast subnet 
     499             :                          * as the requesting packet. If it is then don't reply as the 
     500             :                          * actual machine will be replying also and we don't want two 
     501             :                          * replies to a broadcast query.
     502             :                          */
     503             :                         
     504         783 :                         if (namerec->data.source == WINS_PROXY_NAME) {
     505           0 :                                 for( i = 0; i < namerec->data.num_ips; i++) {
     506           0 :                                         if (same_net_v4(namerec->data.ip[i], subrec->myip, subrec->mask_ip)) {
     507           0 :                                                 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", 
     508             :                                                          nmb_namestr(&namerec->name), subrec->subnet_name ));
     509        2285 :                                                 return;
     510             :                                         }
     511             :                                 }
     512             :                         }
     513             : 
     514         783 :                         ttl = (namerec->data.death_time != PERMANENT_TTL) ?
     515          66 :                                 namerec->data.death_time - p->timestamp : lp_max_ttl();
     516             : 
     517             :                         /* Copy all known ip addresses into the return data. */
     518             :                         /* Optimise for the common case of one IP address so 
     519             :                            we don't need a malloc. */
     520             : 
     521         783 :                         if (namerec->data.num_ips == 1) {
     522         783 :                                 prdata = rdata;
     523             :                         } else {
     524           0 :                                 if ((prdata = (char *)SMB_MALLOC( namerec->data.num_ips * 6 )) == NULL) {
     525           0 :                                         DEBUG(0,("process_name_query_request: malloc fail !\n"));
     526           0 :                                         return;
     527             :                                 }
     528             :                         }
     529             : 
     530        1566 :                         for (i = 0; i < namerec->data.num_ips; i++) {
     531         783 :                                 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
     532         783 :                                 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
     533             :                         }
     534             : 
     535         783 :                         sort_query_replies(prdata, i, p->ip);
     536             :                         
     537         783 :                         reply_data_len = namerec->data.num_ips * 6;
     538         783 :                         success = True;
     539             :                 }
     540             :         }
     541             : 
     542             :         /*
     543             :          * If a machine is broadcasting a name lookup request and we have lp_wins_proxy()
     544             :          * set we should initiate a WINS query here. On success we add the resolved name 
     545             :          * into our namelist with a type of WINS_PROXY_NAME and then reply to the query.
     546             :          */
     547             :         
     548        3068 :         if(!success && (namerec == NULL) && we_are_a_wins_client() && lp_wins_proxy() && 
     549           0 :            bcast && (subrec != remote_broadcast_subnet)) {
     550           0 :                 make_wins_proxy_name_query_request( subrec, p, question );
     551           0 :                 return;
     552             :         }
     553             : 
     554        3068 :         if (!success && bcast) {
     555        2285 :                 if(prdata != rdata)
     556        2285 :                         SAFE_FREE(prdata);
     557        2285 :                 return; /* Never reply with a negative response to broadcasts. */
     558             :         }
     559             : 
     560             :         /* 
     561             :          * Final check. From observation, if a unicast packet is sent
     562             :          * to a non-WINS server with the recursion desired bit set
     563             :          * then never send a negative response.
     564             :          */
     565             :         
     566         783 :         if(!success && !bcast && nmb->header.nm_flags.recursion_desired) {
     567           0 :                 if(prdata != rdata)
     568           0 :                         SAFE_FREE(prdata);
     569           0 :                 return;
     570             :         }
     571             : 
     572         783 :         if (success) {
     573         783 :                 rcode = 0;
     574         783 :                 DEBUG(3,("OK\n"));
     575             :         } else {
     576           0 :                 rcode = NAM_ERR;
     577           0 :                 DEBUG(3,("UNKNOWN\n"));      
     578             :         }
     579             : 
     580             :         /* See rfc1002.txt 4.2.13. */
     581             : 
     582         783 :         reply_netbios_packet(p,                              /* Packet to reply to. */
     583             :                              rcode,                          /* Result code. */
     584             :                              NMB_QUERY,                      /* nmbd type code. */
     585             :                              NMB_NAME_QUERY_OPCODE,          /* opcode. */
     586             :                              ttl,                            /* ttl. */
     587             :                              prdata,                         /* data to send. */
     588             :                              reply_data_len);                /* data length. */
     589             :         
     590         783 :         if(prdata != rdata)
     591           0 :                 SAFE_FREE(prdata);
     592             : }

Generated by: LCOV version 1.13