LCOV - code coverage report
Current view: top level - source3/nmbd - nmbd_winsproxy.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 0 75 0.0 %
Date: 2024-04-13 12:30:31 Functions: 0 5 0.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    NBT netbios routines and daemon - version 2
       4             : 
       5             :    Copyright (C) Jeremy Allison 1994-1998
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             :    
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             :    
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             :    
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "nmbd/nmbd.h"
      24             : 
      25             : /****************************************************************************
      26             : Function called when the name lookup succeeded.
      27             : ****************************************************************************/
      28             : 
      29           0 : static void wins_proxy_name_query_request_success( struct subnet_record *subrec,
      30             :                         struct userdata_struct *userdata,
      31             :                         struct nmb_name *nmbname, struct in_addr ip, struct res_rec *rrec)
      32             : {
      33             :         unstring name;
      34             :         struct packet_struct *original_packet;
      35             :         struct subnet_record *orig_broadcast_subnet;
      36           0 :         struct name_record *namerec = NULL;
      37             :         uint16_t nb_flags;
      38             :         int num_ips;
      39             :         int i;
      40           0 :         int ttl = 3600; /* By default one hour in the cache. */
      41             :         struct in_addr *iplist;
      42             : 
      43             :         /* Extract the original packet and the original broadcast subnet from
      44             :                         the userdata. */
      45             : 
      46           0 :         memcpy( (char *)&orig_broadcast_subnet, userdata->data, sizeof(struct subnet_record *) );
      47           0 :         memcpy( (char *)&original_packet, &userdata->data[sizeof(struct subnet_record *)],
      48             :                         sizeof(struct packet_struct *) );
      49             : 
      50           0 :         if (rrec) {
      51           0 :                 nb_flags = get_nb_flags( rrec->rdata );
      52           0 :                 num_ips = rrec->rdlength / 6;
      53             :         } else {
      54           0 :                 nb_flags = 0;
      55           0 :                 num_ips = 0;
      56             :         }
      57             : 
      58           0 :         if(num_ips == 0) {
      59           0 :                 DEBUG(0,("wins_proxy_name_query_request_success: Invalid number of IP records (0) \
      60             : returned for name %s.\n", nmb_namestr(nmbname) ));
      61           0 :                 return;
      62             :         }
      63             : 
      64           0 :         if(num_ips == 1) {
      65           0 :                 iplist = &ip;
      66             :         } else {
      67           0 :                 if((iplist = SMB_MALLOC_ARRAY( struct in_addr, num_ips )) == NULL) {
      68           0 :                         DEBUG(0,("wins_proxy_name_query_request_success: malloc fail !\n"));
      69           0 :                         return;
      70             :                 }
      71             : 
      72           0 :                 for(i = 0; i < num_ips; i++) {
      73           0 :                         putip( (char *)&iplist[i], (char *)&rrec->rdata[ (i*6) + 2]);
      74             :                 }
      75             :         }
      76             : 
      77             :         /* Add the queried name to the original subnet as a WINS_PROXY_NAME. */
      78             : 
      79           0 :         if(rrec->ttl == PERMANENT_TTL) {
      80           0 :                 ttl = lp_max_ttl();
      81             :         }
      82             : 
      83           0 :         pull_ascii_nstring(name, sizeof(name), nmbname->name);
      84           0 :         add_name_to_subnet( orig_broadcast_subnet, name,
      85           0 :                                         nmbname->name_type, nb_flags, ttl,
      86             :                                         WINS_PROXY_NAME, num_ips, iplist );
      87             : 
      88           0 :         if(iplist != &ip) {
      89           0 :                 SAFE_FREE(iplist);
      90             :         }
      91             : 
      92           0 :         namerec = find_name_on_subnet(orig_broadcast_subnet, nmbname, FIND_ANY_NAME);
      93           0 :         if (!namerec) {
      94           0 :                 DEBUG(0,("wins_proxy_name_query_request_success: failed to add "
      95             :                         "name %s to subnet %s !\n",
      96             :                         name,
      97             :                         orig_broadcast_subnet->subnet_name ));
      98           0 :                 return;
      99             :         }
     100             : 
     101             :         /*
     102             :          * Check that none of the IP addresses we are returning is on the
     103             :          * same broadcast subnet as the original requesting packet. If it
     104             :          * is then don't reply (although we still need to add the name
     105             :          * to the cache) as the actual machine will be replying also
     106             :          * and we don't want two replies to a broadcast query.
     107             :          */
     108             : 
     109           0 :         if(namerec && original_packet->packet.nmb.header.nm_flags.bcast) {
     110           0 :                 for( i = 0; i < namerec->data.num_ips; i++) {
     111           0 :                         if( same_net_v4( namerec->data.ip[i], orig_broadcast_subnet->myip,
     112           0 :                                         orig_broadcast_subnet->mask_ip ) ) {
     113           0 :                                 DEBUG( 5, ( "wins_proxy_name_query_request_success: name %s is a WINS \
     114             : proxy name and is also on the same subnet (%s) as the requester. \
     115             : Not replying.\n", nmb_namestr(&namerec->name), orig_broadcast_subnet->subnet_name ) );
     116           0 :                                 return;
     117             :                         }
     118             :                 }
     119             :         }
     120             : 
     121             :         /* Finally reply to the original name query. */
     122           0 :         reply_netbios_packet(original_packet,                /* Packet to reply to. */
     123             :                                 0,                              /* Result code. */
     124             :                                 NMB_QUERY,                      /* nmbd type code. */
     125             :                                 NMB_NAME_QUERY_OPCODE,          /* opcode. */
     126             :                                 ttl,                            /* ttl. */
     127           0 :                                 rrec->rdata,                    /* data to send. */
     128             :                                 rrec->rdlength);                /* data length. */
     129             : }
     130             : 
     131             : /****************************************************************************
     132             : Function called when the name lookup failed.
     133             : ****************************************************************************/
     134             : 
     135           0 : static void wins_proxy_name_query_request_fail(struct subnet_record *subrec,
     136             :                                     struct response_record *rrec,
     137             :                                     struct nmb_name *question_name, int fail_code)
     138             : {
     139           0 :         DEBUG(4,("wins_proxy_name_query_request_fail: WINS server returned error code %d for lookup \
     140             : of name %s.\n", fail_code, nmb_namestr(question_name) ));
     141           0 : }
     142             : 
     143             : /****************************************************************************
     144             : Function to make a deep copy of the userdata we will need when the WINS
     145             : proxy query returns.
     146             : ****************************************************************************/
     147             : 
     148           0 : static struct userdata_struct *wins_proxy_userdata_copy_fn(struct userdata_struct *userdata)
     149             : {
     150             :         struct packet_struct *p, *copy_of_p;
     151           0 :         struct userdata_struct *new_userdata = (struct userdata_struct *)SMB_MALLOC( userdata->userdata_len );
     152             : 
     153           0 :         if(new_userdata == NULL)
     154           0 :                 return NULL;
     155             : 
     156           0 :         new_userdata->copy_fn = userdata->copy_fn;
     157           0 :         new_userdata->free_fn = userdata->free_fn;
     158           0 :         new_userdata->userdata_len = userdata->userdata_len;
     159             : 
     160             :         /* Copy the subnet_record pointer. */
     161           0 :         memcpy( new_userdata->data, userdata->data, sizeof(struct subnet_record *) );
     162             : 
     163             :         /* Extract the pointer to the packet struct */
     164           0 :         memcpy((char *)&p, &userdata->data[sizeof(struct subnet_record *)], sizeof(struct packet_struct *) );
     165             : 
     166             :         /* Do a deep copy of the packet. */
     167           0 :         if((copy_of_p = copy_packet(p)) == NULL) {
     168           0 :                 SAFE_FREE(new_userdata);
     169           0 :                 return NULL;
     170             :         }
     171             : 
     172             :         /* Lock the copy. */
     173           0 :         copy_of_p->locked = True;
     174             : 
     175           0 :         memcpy( &new_userdata->data[sizeof(struct subnet_record *)], (char *)&copy_of_p,
     176             :                 sizeof(struct packet_struct *) );
     177             : 
     178           0 :         return new_userdata;
     179             : }
     180             : 
     181             : /****************************************************************************
     182             : Function to free the deep copy of the userdata we used when the WINS
     183             : proxy query returned.
     184             : ****************************************************************************/
     185             : 
     186           0 : static void wins_proxy_userdata_free_fn(struct userdata_struct *userdata)
     187             : {
     188             :         struct packet_struct *p;
     189             : 
     190             :         /* Extract the pointer to the packet struct */
     191           0 :         memcpy((char *)&p, &userdata->data[sizeof(struct subnet_record *)],
     192             :                 sizeof(struct packet_struct *));
     193             : 
     194             :         /* Unlock the packet. */
     195           0 :         p->locked = False;
     196             : 
     197           0 :         free_packet(p);
     198           0 :         ZERO_STRUCTP(userdata);
     199           0 :         SAFE_FREE(userdata);
     200           0 : }
     201             : 
     202             : /****************************************************************************
     203             :  Make a WINS query on behalf of a broadcast client name query request.
     204             : ****************************************************************************/
     205             : 
     206           0 : void make_wins_proxy_name_query_request( struct subnet_record *subrec, 
     207             :                                          struct packet_struct *incoming_packet,
     208             :                                          struct nmb_name *question_name)
     209             : {
     210             :         union {
     211             :             struct userdata_struct ud;
     212             :             char c[sizeof(struct userdata_struct) + sizeof(struct subrec *) + 
     213             :                 sizeof(struct packet_struct *)+sizeof(long*)];
     214             :         } ud;
     215           0 :         struct userdata_struct *userdata = &ud.ud;
     216             :         unstring qname;
     217             : 
     218           0 :         memset(&ud, '\0', sizeof(ud));
     219             :  
     220           0 :         userdata->copy_fn = wins_proxy_userdata_copy_fn;
     221           0 :         userdata->free_fn = wins_proxy_userdata_free_fn;
     222           0 :         userdata->userdata_len = sizeof(ud);
     223           0 :         memcpy( userdata->data, (char *)&subrec, sizeof(struct subnet_record *));
     224           0 :         memcpy( &userdata->data[sizeof(struct subnet_record *)], (char *)&incoming_packet,
     225             :                         sizeof(struct packet_struct *));
     226             : 
     227             :         /* Now use the unicast subnet to query the name with the WINS server. */
     228           0 :         pull_ascii_nstring(qname, sizeof(qname), question_name->name);
     229           0 :         query_name( unicast_subnet, qname, question_name->name_type,
     230             :                 wins_proxy_name_query_request_success,
     231             :                 wins_proxy_name_query_request_fail,
     232             :                 userdata);
     233           0 : }

Generated by: LCOV version 1.14