home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 July & August / Pcwk78a98.iso / Wtestowe / Clico / UNIX / SAMBA / SOURCE / SAMBA.TAR / samba-1.9.17 / source / namequery.c < prev    next >
C/C++ Source or Header  |  1997-05-08  |  8KB  |  296 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    name query routines
  5.    Copyright (C) Andrew Tridgell 1994-1997
  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 2 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, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.    
  21. */
  22.  
  23. #include "includes.h"
  24.  
  25. extern pstring scope;
  26. extern int DEBUGLEVEL;
  27.  
  28.  
  29. /****************************************************************************
  30. interpret a node status response
  31. ****************************************************************************/
  32. static void _interpret_node_status(char *p, char *master,char *rname)
  33. {
  34.   int numnames = CVAL(p,0);
  35.   DEBUG(1,("received %d names\n",numnames));
  36.  
  37.   if (rname) *rname = 0;
  38.   if (master) *master = 0;
  39.  
  40.   p += 1;
  41.   while (numnames--)
  42.     {
  43.       char qname[17];
  44.       int type;
  45.       fstring flags;
  46.       int i;
  47.       *flags = 0;
  48.       StrnCpy(qname,p,15);
  49.       type = CVAL(p,15);
  50.       p += 16;
  51.  
  52.       strcat(flags, (p[0] & 0x80) ? "<GROUP> " : "        ");
  53.       if ((p[0] & 0x60) == 0x00) strcat(flags,"B ");
  54.       if ((p[0] & 0x60) == 0x20) strcat(flags,"P ");
  55.       if ((p[0] & 0x60) == 0x40) strcat(flags,"M ");
  56.       if ((p[0] & 0x60) == 0x60) strcat(flags,"H ");
  57.       if (p[0] & 0x10) strcat(flags,"<DEREGISTERING> ");
  58.       if (p[0] & 0x08) strcat(flags,"<CONFLICT> ");
  59.       if (p[0] & 0x04) strcat(flags,"<ACTIVE> ");
  60.       if (p[0] & 0x02) strcat(flags,"<PERMANENT> ");
  61.  
  62.       if (master && !*master && type == 0x1d) {
  63.     StrnCpy(master,qname,15);
  64.     trim_string(master,NULL," ");
  65.       }
  66.  
  67.       if (rname && !*rname && type == 0x20 && !(p[0]&0x80)) {
  68.     StrnCpy(rname,qname,15);
  69.     trim_string(rname,NULL," ");
  70.       }
  71.       
  72.       for (i = strlen( qname) ; --i >= 0 ; ) {
  73.     if (!isprint(qname[i])) qname[i] = '.';
  74.       }
  75.       DEBUG(1,("\t%-15s <%02x> - %s\n",qname,type,flags));
  76.       p+=2;
  77.     }
  78.   DEBUG(1,("num_good_sends=%d num_good_receives=%d\n",
  79.            IVAL(p,20),IVAL(p,24)));
  80. }
  81.  
  82.  
  83. /****************************************************************************
  84.   do a netbios name status query on a host
  85.  
  86.   the "master" parameter is a hack used for finding workgroups.
  87.   **************************************************************************/
  88. BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
  89.          struct in_addr to_ip,char *master,char *rname,
  90.          void (*fn)())
  91. {
  92.   BOOL found=False;
  93.   int retries = 2;
  94.   int retry_time = 5000;
  95.   struct timeval tval;
  96.   struct packet_struct p;
  97.   struct packet_struct *p2;
  98.   struct nmb_packet *nmb = &p.packet.nmb;
  99.   static int name_trn_id = 0;
  100.  
  101.   bzero((char *)&p,sizeof(p));
  102.  
  103.   if (!name_trn_id) name_trn_id = (time(NULL)%(unsigned)0x7FFF) + 
  104.     (getpid()%(unsigned)100);
  105.   name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
  106.  
  107.   nmb->header.name_trn_id = name_trn_id;
  108.   nmb->header.opcode = 0;
  109.   nmb->header.response = False;
  110.   nmb->header.nm_flags.bcast = False;
  111.   nmb->header.nm_flags.recursion_available = False;
  112.   nmb->header.nm_flags.recursion_desired = False;
  113.   nmb->header.nm_flags.trunc = False;
  114.   nmb->header.nm_flags.authoritative = False;
  115.   nmb->header.rcode = 0;
  116.   nmb->header.qdcount = 1;
  117.   nmb->header.ancount = 0;
  118.   nmb->header.nscount = 0;
  119.   nmb->header.arcount = 0;
  120.  
  121.   make_nmb_name(&nmb->question.question_name,name,name_type,scope);
  122.  
  123.   nmb->question.question_type = 0x21;
  124.   nmb->question.question_class = 0x1;
  125.  
  126.   p.ip = to_ip;
  127.   p.port = NMB_PORT;
  128.   p.fd = fd;
  129.   p.timestamp = time(NULL);
  130.   p.packet_type = NMB_PACKET;
  131.  
  132.   GetTimeOfDay(&tval);
  133.  
  134.   if (!send_packet(&p)) 
  135.     return(False);
  136.  
  137.   retries--;
  138.  
  139.   while (1)
  140.     {
  141.       struct timeval tval2;
  142.       GetTimeOfDay(&tval2);
  143.       if (TvalDiff(&tval,&tval2) > retry_time) {
  144.     if (!retries) break;
  145.     if (!found && !send_packet(&p))
  146.       return False;
  147.     GetTimeOfDay(&tval);
  148.     retries--;
  149.       }
  150.  
  151.       if ((p2=receive_packet(fd,NMB_PACKET,90)))
  152.     {     
  153.       struct nmb_packet *nmb2 = &p2->packet.nmb;
  154.       debug_nmb_packet(p2);
  155.  
  156.       if (nmb->header.name_trn_id != nmb2->header.name_trn_id ||
  157.           !nmb2->header.response) {
  158.         /* its not for us - maybe deal with it later */
  159.         if (fn) 
  160.           fn(p2);
  161.         else
  162.           free_packet(p2);
  163.         continue;
  164.       }
  165.       
  166.       if (nmb2->header.opcode != 0 ||
  167.           nmb2->header.nm_flags.bcast ||
  168.           nmb2->header.rcode ||
  169.           !nmb2->header.ancount ||
  170.           nmb2->answers->rr_type != 0x21) {
  171.         /* XXXX what do we do with this? could be a redirect, but
  172.            we'll discard it for the moment */
  173.         free_packet(p2);
  174.         continue;
  175.       }
  176.  
  177.       _interpret_node_status(&nmb2->answers->rdata[0], master,rname);
  178.       free_packet(p2);
  179.       return(True);
  180.     }
  181.     }
  182.   
  183.  
  184.   DEBUG(0,("No status response (this is not unusual)\n"));
  185.  
  186.   return(False);
  187. }
  188.  
  189.  
  190. /****************************************************************************
  191.   do a netbios name query to find someones IP
  192.   ****************************************************************************/
  193. BOOL name_query(int fd,char *name,int name_type, 
  194.         BOOL bcast,BOOL recurse,
  195.         struct in_addr to_ip, struct in_addr *ip,void (*fn)())
  196. {
  197.   BOOL found=False;
  198.   int retries = 3;
  199.   int retry_time = bcast?250:2000;
  200.   struct timeval tval;
  201.   struct packet_struct p;
  202.   struct packet_struct *p2;
  203.   struct nmb_packet *nmb = &p.packet.nmb;
  204.   static int name_trn_id = 0;
  205.  
  206.   bzero((char *)&p,sizeof(p));
  207.  
  208.   if (!name_trn_id) name_trn_id = (time(NULL)%(unsigned)0x7FFF) + 
  209.     (getpid()%(unsigned)100);
  210.   name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
  211.  
  212.   nmb->header.name_trn_id = name_trn_id;
  213.   nmb->header.opcode = 0;
  214.   nmb->header.response = False;
  215.   nmb->header.nm_flags.bcast = bcast;
  216.   nmb->header.nm_flags.recursion_available = False;
  217.   nmb->header.nm_flags.recursion_desired = True;
  218.   nmb->header.nm_flags.trunc = False;
  219.   nmb->header.nm_flags.authoritative = False;
  220.   nmb->header.rcode = 0;
  221.   nmb->header.qdcount = 1;
  222.   nmb->header.ancount = 0;
  223.   nmb->header.nscount = 0;
  224.   nmb->header.arcount = 0;
  225.  
  226.   make_nmb_name(&nmb->question.question_name,name,name_type,scope);
  227.  
  228.   nmb->question.question_type = 0x20;
  229.   nmb->question.question_class = 0x1;
  230.  
  231.   p.ip = to_ip;
  232.   p.port = NMB_PORT;
  233.   p.fd = fd;
  234.   p.timestamp = time(NULL);
  235.   p.packet_type = NMB_PACKET;
  236.  
  237.   GetTimeOfDay(&tval);
  238.  
  239.   if (!send_packet(&p)) 
  240.     return(False);
  241.  
  242.   retries--;
  243.  
  244.   while (1)
  245.     {
  246.       struct timeval tval2;
  247.       GetTimeOfDay(&tval2);
  248.       if (TvalDiff(&tval,&tval2) > retry_time) {
  249.     if (!retries) break;
  250.     if (!found && !send_packet(&p))
  251.       return False;
  252.     GetTimeOfDay(&tval);
  253.     retries--;
  254.       }
  255.  
  256.       if ((p2=receive_packet(fd,NMB_PACKET,90)))
  257.     {     
  258.       struct nmb_packet *nmb2 = &p2->packet.nmb;
  259.       debug_nmb_packet(p2);
  260.  
  261.       if (nmb->header.name_trn_id != nmb2->header.name_trn_id ||
  262.           !nmb2->header.response) {
  263.         /* its not for us - maybe deal with it later 
  264.            (put it on the queue?) */
  265.         if (fn) 
  266.           fn(p2);
  267.         else
  268.           free_packet(p2);
  269.         continue;
  270.       }
  271.       
  272.       if (nmb2->header.opcode != 0 ||
  273.           nmb2->header.nm_flags.bcast ||
  274.           nmb2->header.rcode ||
  275.           !nmb2->header.ancount) {
  276.         /* XXXX what do we do with this? could be a redirect, but
  277.            we'll discard it for the moment */
  278.         free_packet(p2);
  279.         continue;
  280.       }
  281.  
  282.       if (ip) {
  283.         putip((char *)ip,&nmb2->answers->rdata[2]);
  284.         DEBUG(fn?3:2,("Got a positive name query response from %s",
  285.               inet_ntoa(p2->ip)));
  286.         DEBUG(fn?3:2,(" (%s)\n",inet_ntoa(*ip)));
  287.       }
  288.       found=True; retries=0;
  289.       free_packet(p2);
  290.       if (fn) break;
  291.     }
  292.     }
  293.  
  294.   return(found);
  295. }
  296.