root/source3/nmbd/nmbd_incomingrequests.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. send_name_release_response
  2. process_name_release_request
  3. send_name_registration_response
  4. process_name_refresh_request
  5. process_name_registration_request
  6. status_compare
  7. process_node_status_request
  8. process_name_query_request

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

/* [<][>][^][v][top][bottom][index][help] */