LCOV - code coverage report
Current view: top level - source3/nmbd - nmbd_incomingrequests.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 155 225 68.9 %
Date: 2024-04-21 15:09:00 Functions: 6 8 75.0 %

          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          10 : void process_name_release_request(struct subnet_record *subrec,
      56             :                                   struct packet_struct *p)
      57             : {
      58          10 :         struct nmb_packet *nmb = &p->packet.nmb;
      59             :         struct in_addr owner_ip;
      60          10 :         struct nmb_name *question = &nmb->question.question_name;
      61             :         unstring qname;
      62          10 :         bool bcast = nmb->header.nm_flags.bcast;
      63          10 :         uint16_t nb_flags = get_nb_flags(nmb->additional->rdata);
      64          10 :         bool group = (nb_flags & NB_GROUP) ? True : False;
      65             :         struct name_record *namerec;
      66          10 :         int rcode = 0;
      67             : 
      68          10 :         putip((char *)&owner_ip,&nmb->additional->rdata[2]);
      69             : 
      70          10 :         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          10 :                 return;
      84             :         }
      85             : 
      86          10 :         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          10 :         if( group && !ismyip_v4(owner_ip) )
      93           5 :                 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           5 :         pull_ascii_nstring(qname, sizeof(qname), question->name);
     102           5 :         if( !group && !ismyip_v4(owner_ip) && strequal(qname, lp_workgroup()) &&
     103           4 :                         ((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           5 :         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           5 :         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           5 :         if(rcode == 0)
     122           5 :                 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          12 : static void send_name_registration_response(int rcode, int ttl, struct packet_struct *p)
     133             : {
     134          12 :         struct nmb_packet *nmb = &p->packet.nmb;
     135             :         char rdata[6];
     136             : 
     137          12 :         memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
     138             : 
     139          12 :         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          12 : }
     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        3522 : void process_name_registration_request(struct subnet_record *subrec,
     190             :                                        struct packet_struct *p)
     191             : {
     192        3522 :         struct nmb_packet *nmb = &p->packet.nmb;
     193        3522 :         struct nmb_name *question = &nmb->question.question_name;
     194        3522 :         bool bcast = nmb->header.nm_flags.bcast;
     195        3522 :         uint16_t nb_flags = get_nb_flags(nmb->additional->rdata);
     196        3522 :         bool group = (nb_flags & NB_GROUP) ? True : False;
     197        3522 :         struct name_record *namerec = NULL;
     198        3522 :         int ttl = nmb->additional->ttl;
     199             :         struct in_addr from_ip;
     200             : 
     201        3522 :         putip((char *)&from_ip,&nmb->additional->rdata[2]);
     202             : 
     203        3522 :         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          12 :                 return;
     217             :         }
     218             : 
     219        3522 :         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        3522 :         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        3522 :         if((namerec != NULL) && (namerec->data.source == WINS_PROXY_NAME)) {
     232           0 :                 remove_name_from_namelist( subrec, namerec );
     233           0 :                 namerec = NULL;
     234             :         }
     235             : 
     236        3522 :         if (!group) {
     237             :                 /* Unique name. */
     238             : 
     239        2154 :                 if( (namerec != NULL)
     240          12 :                                 && ( (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          12 :                         send_name_registration_response(ACT_ERR, 0, p);
     247          12 :                         return;
     248        2142 :                 } 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        1368 :                 if( (namerec != NULL)
     261         319 :                                 && !NAME_GROUP(namerec)
     262           0 :                                 && ( (namerec->data.source == SELF_NAME)
     263           0 :                                 || (namerec->data.source == PERMANENT_NAME) ) ) {
     264             :                         /* Disallow group names when we have a unique name. */
     265           0 :                         send_name_registration_response(ACT_ERR, 0, p);
     266           0 :                         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        5530 : static int status_compare(char *n1,char *n2)
     277             : {
     278             :         unstring name1, name2;
     279             :         int l1,l2,l3;
     280             : 
     281        5530 :         memset(name1, '\0', sizeof(name1));
     282        5530 :         memset(name2, '\0', sizeof(name2));
     283        5530 :         pull_ascii_nstring(name1, sizeof(name1), n1);
     284        5530 :         pull_ascii_nstring(name2, sizeof(name2), n2);
     285        5530 :         n1 = name1;
     286        5530 :         n2 = name2;
     287             : 
     288             :         /* It's a bit tricky because the names are space padded */
     289       66116 :         for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++)
     290             :                 ;
     291       62187 :         for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++)
     292             :                 ;
     293        5530 :         l3 = strlen(lp_netbios_name());
     294             : 
     295        5530 :         if ((l1==l3) && strncmp(n1,lp_netbios_name(),l3) == 0 &&
     296         846 :                         (l2!=l3 || strncmp(n2,lp_netbios_name(),l3) != 0))
     297         974 :                 return -1;
     298             : 
     299        4556 :         if ((l2==l3) && strncmp(n2,lp_netbios_name(),l3) == 0 &&
     300         810 :                         (l1!=l3 || strncmp(n1,lp_netbios_name(),l3) != 0))
     301         509 :                 return 1;
     302             : 
     303        4047 :         return memcmp(n1,n2,sizeof(name1));
     304             : }
     305             : 
     306             : /****************************************************************************
     307             :   Process a node status query
     308             :   ****************************************************************************/
     309             : 
     310          52 : void process_node_status_request(struct subnet_record *subrec, struct packet_struct *p)
     311             : {
     312          52 :         struct nmb_packet *nmb = &p->packet.nmb;
     313             :         unstring qname;
     314          52 :         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          52 :         struct name_record *namerec = NULL;
     319             : 
     320          52 :         pull_ascii_nstring(qname, sizeof(qname), nmb->question.question_name.name);
     321             : 
     322          52 :         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          52 :         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          52 :         bufend = &rdata[MAX_DGRAM_SIZE-1] - (18 + 46 + 60);
     336          52 :         countptr = buf = rdata;
     337          52 :         buf += 1;
     338          52 :         buf0 = buf;
     339             : 
     340          52 :         names_added = 0;
     341             : 
     342          52 :         namerec = subrec->namelist;
     343             : 
     344         655 :         while (PTR_DIFF(bufend, buf) > 0) {
     345         655 :                 if( (namerec->data.source == SELF_NAME) || (namerec->data.source == PERMANENT_NAME) ) {
     346         655 :                         int name_type = namerec->name.name_type;
     347             :                         unstring name;
     348             : 
     349         655 :                         pull_ascii_nstring(name, sizeof(name), namerec->name.name);
     350         655 :                         if (!strupper_m(name)) {
     351           0 :                                 DEBUG(2,("strupper_m %s failed\n", name));
     352           0 :                                 return;
     353             :                         }
     354         655 :                         if (!strequal(name,"*") &&
     355         551 :                                         !strequal(name,"__SAMBA__") &&
     356         233 :                                         (name_type < 0x1b || name_type >= 0x20 ||
     357         122 :                                         ques_type < 0x1b || ques_type >= 0x20 ||
     358          61 :                                         strequal(qname, name))) {
     359             :                                 /* Start with the name. */
     360             :                                 size_t len;
     361         447 :                                 push_ascii_nstring(buf, name);
     362         447 :                                 len = strlen(buf);
     363         447 :                                 memset(buf + len, ' ', MAX_NETBIOSNAME_LEN - len - 1);
     364         447 :                                 buf[MAX_NETBIOSNAME_LEN - 1] = '\0';
     365             : 
     366             :                                 /* Put the name type and netbios flags in the buffer. */
     367             : 
     368         447 :                                 buf[15] = name_type;
     369         447 :                                 set_nb_flags( &buf[16],namerec->data.nb_flags );
     370         447 :                                 buf[16] |= NB_ACTIVE; /* all our names are active */
     371             : 
     372         447 :                                 names_added++;
     373             :                         }
     374             :                 }
     375             : 
     376             :                 /* Remove duplicate names. */
     377         655 :                 if (names_added > 1) {
     378             :                         /* TODO: should use a real type and
     379             :                            TYPESAFE_QSORT() */
     380         603 :                         qsort( buf0, names_added, 18, QSORT_CAST status_compare );
     381             :                 }
     382             : 
     383        3975 :                 for( i=1; i < names_added ; i++ ) {
     384        3320 :                         if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) {
     385           0 :                                 names_added--;
     386           0 :                                 if (names_added == i)
     387           0 :                                         break;
     388           0 :                                 memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i));
     389           0 :                                 i--;
     390             :                         }
     391             :                 }
     392             : 
     393         655 :                 buf = buf0 + 18*names_added;
     394             : 
     395         655 :                 namerec = namerec->next;
     396             : 
     397         655 :                 if (!namerec) {
     398             :                         /* End of the subnet specific name list. Now
     399             :                                 add the names on the unicast subnet . */
     400          52 :                         struct subnet_record *uni_subrec = unicast_subnet;
     401             : 
     402          52 :                         if (uni_subrec != subrec) {
     403           0 :                                 subrec = uni_subrec;
     404           0 :                                 namerec = subrec->namelist;
     405             :                         }
     406             :                 }
     407         655 :                 if (!namerec)
     408          52 :                         break;
     409             : 
     410             :         }
     411             : 
     412          52 :         SCVAL(countptr,0,names_added);
     413             : 
     414             :         /* We don't send any stats as they could be used to attack
     415             :                 the protocol. */
     416          52 :         memset(buf,'\0',46);
     417             : 
     418          52 :         buf += 46;
     419             : 
     420             :         /* Send a NODE STATUS RESPONSE */
     421          52 :         reply_netbios_packet(p,                               /* Packet to reply to. */
     422             :                                 0,                            /* Result code. */
     423             :                                 NMB_STATUS,                   /* nmbd type code. */
     424             :                                 NMB_NAME_QUERY_OPCODE,        /* opcode. */
     425             :                                 0,                            /* ttl. */
     426             :                                 rdata,                        /* data to send. */
     427          52 :                                 PTR_DIFF(buf,rdata));         /* data length. */
     428             : }
     429             : 
     430             : 
     431             : /***************************************************************************
     432             : Process a name query.
     433             : 
     434             : For broadcast name queries:
     435             : 
     436             :   - Only reply if the query is for one of YOUR names.
     437             :   - NEVER send a negative response to a broadcast query.
     438             : 
     439             : ****************************************************************************/
     440             : 
     441        4396 : void process_name_query_request(struct subnet_record *subrec, struct packet_struct *p)
     442             : {
     443        4396 :         struct nmb_packet *nmb = &p->packet.nmb;
     444        4396 :         struct nmb_name *question = &nmb->question.question_name;
     445        4396 :         int name_type = question->name_type;
     446        4396 :         bool bcast = nmb->header.nm_flags.bcast;
     447        4396 :         int ttl=0;
     448        4396 :         int rcode = 0;
     449        4396 :         char *prdata = NULL;
     450             :         char rdata[6];
     451        4396 :         bool success = False;
     452        4396 :         struct name_record *namerec = NULL;
     453        4396 :         int reply_data_len = 0;
     454             :         int i;
     455             : 
     456        4396 :         DEBUG(3,("process_name_query_request: Name query from %s on subnet %s for name %s\n",
     457             :                  inet_ntoa(p->ip), subrec->subnet_name, nmb_namestr(question)));
     458             : 
     459             :         /* Look up the name in the cache - if the request is a broadcast request that
     460             :            came from a subnet we don't know about then search all the broadcast subnets
     461             :            for a match (as we don't know what interface the request came in on). */
     462             : 
     463        4396 :         if(subrec == remote_broadcast_subnet)
     464           0 :                 namerec = find_name_for_remote_broadcast_subnet( question, FIND_ANY_NAME);
     465             :         else
     466        4396 :                 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
     467             : 
     468             :         /* Check if it is a name that expired */
     469        4396 :         if (namerec &&
     470         827 :             ((namerec->data.death_time != PERMANENT_TTL) &&
     471           0 :              (namerec->data.death_time < p->timestamp))) {
     472           0 :                 DEBUG(5,("process_name_query_request: expired name %s\n", nmb_namestr(&namerec->name)));
     473           0 :                 namerec = NULL;
     474             :         }
     475             : 
     476        4396 :         if (namerec) {
     477             :                 /*
     478             :                  * Always respond to unicast queries.
     479             :                  * Don't respond to broadcast queries unless the query is for
     480             :                  * a name we own, a Primary Domain Controller name, or a WINS_PROXY
     481             :                  * name with type 0 or 0x20. WINS_PROXY names are only ever added
     482             :                  * into the namelist if we were configured as a WINS proxy.
     483             :                  */
     484             : 
     485         827 :                 if (!bcast ||
     486         612 :                     (bcast && ((name_type == 0x1b) ||
     487         612 :                                (namerec->data.source == SELF_NAME) ||
     488         129 :                                (namerec->data.source == PERMANENT_NAME) ||
     489           0 :                                ((namerec->data.source == WINS_PROXY_NAME) &&
     490           0 :                                 ((name_type == 0) || (name_type == 0x20)))))) {
     491             :                         /* The requested name is a directed query, or it's SELF or PERMANENT or WINS_PROXY,
     492             :                            or it's a Domain Master type. */
     493             : 
     494             :                         /*
     495             :                          * If this is a WINS_PROXY_NAME, then check that none of the IP
     496             :                          * addresses we are returning is on the same broadcast subnet
     497             :                          * as the requesting packet. If it is then don't reply as the
     498             :                          * actual machine will be replying also and we don't want two
     499             :                          * replies to a broadcast query.
     500             :                          */
     501             : 
     502         827 :                         if (namerec->data.source == WINS_PROXY_NAME) {
     503           0 :                                 for( i = 0; i < namerec->data.num_ips; i++) {
     504           0 :                                         if (same_net_v4(namerec->data.ip[i], subrec->myip, subrec->mask_ip)) {
     505           0 :                                                 DEBUG(5,("process_name_query_request: name %s is a WINS proxy name and is also on the same subnet (%s) as the requester. Not replying.\n",
     506             :                                                          nmb_namestr(&namerec->name), subrec->subnet_name ));
     507        3569 :                                                 return;
     508             :                                         }
     509             :                                 }
     510             :                         }
     511             : 
     512         827 :                         ttl = (namerec->data.death_time != PERMANENT_TTL) ?
     513         827 :                                 namerec->data.death_time - p->timestamp : lp_max_ttl();
     514             : 
     515             :                         /* Copy all known ip addresses into the return data. */
     516             :                         /* Optimise for the common case of one IP address so
     517             :                            we don't need a malloc. */
     518             : 
     519         827 :                         if (namerec->data.num_ips == 1) {
     520         827 :                                 prdata = rdata;
     521             :                         } else {
     522           0 :                                 if ((prdata = (char *)SMB_MALLOC( namerec->data.num_ips * 6 )) == NULL) {
     523           0 :                                         DEBUG(0,("process_name_query_request: malloc fail !\n"));
     524           0 :                                         return;
     525             :                                 }
     526             :                         }
     527             : 
     528        1654 :                         for (i = 0; i < namerec->data.num_ips; i++) {
     529         827 :                                 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
     530         827 :                                 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
     531             :                         }
     532             : 
     533         827 :                         sort_query_replies(prdata, i, p->ip);
     534             : 
     535         827 :                         reply_data_len = namerec->data.num_ips * 6;
     536         827 :                         success = True;
     537             :                 }
     538             :         }
     539             : 
     540             :         /*
     541             :          * If a machine is broadcasting a name lookup request and we have lp_wins_proxy()
     542             :          * set we should initiate a WINS query here. On success we add the resolved name
     543             :          * into our namelist with a type of WINS_PROXY_NAME and then reply to the query.
     544             :          */
     545             : 
     546        4396 :         if(!success && (namerec == NULL) && we_are_a_wins_client() && lp_wins_proxy() &&
     547           0 :            bcast && (subrec != remote_broadcast_subnet)) {
     548           0 :                 make_wins_proxy_name_query_request( subrec, p, question );
     549           0 :                 return;
     550             :         }
     551             : 
     552        4396 :         if (!success && bcast) {
     553        3569 :                 if(prdata != rdata)
     554        3569 :                         SAFE_FREE(prdata);
     555        3569 :                 return; /* Never reply with a negative response to broadcasts. */
     556             :         }
     557             : 
     558             :         /*
     559             :          * Final check. From observation, if a unicast packet is sent
     560             :          * to a non-WINS server with the recursion desired bit set
     561             :          * then never send a negative response.
     562             :          */
     563             : 
     564         827 :         if(!success && !bcast && nmb->header.nm_flags.recursion_desired) {
     565           0 :                 if(prdata != rdata)
     566           0 :                         SAFE_FREE(prdata);
     567           0 :                 return;
     568             :         }
     569             : 
     570         827 :         if (success) {
     571         827 :                 rcode = 0;
     572         827 :                 DEBUG(3,("OK\n"));
     573             :         } else {
     574           0 :                 rcode = NAM_ERR;
     575           0 :                 DEBUG(3,("UNKNOWN\n"));
     576             :         }
     577             : 
     578             :         /* See rfc1002.txt 4.2.13. */
     579             : 
     580         827 :         reply_netbios_packet(p,                              /* Packet to reply to. */
     581             :                              rcode,                          /* Result code. */
     582             :                              NMB_QUERY,                      /* nmbd type code. */
     583             :                              NMB_NAME_QUERY_OPCODE,          /* opcode. */
     584             :                              ttl,                            /* ttl. */
     585             :                              prdata,                         /* data to send. */
     586             :                              reply_data_len);                /* data length. */
     587             : 
     588         827 :         if(prdata != rdata)
     589           0 :                 SAFE_FREE(prdata);
     590             : }

Generated by: LCOV version 1.14