implemented a much nicer name_status() interface. It now returns a
authorAndrew Tridgell <tridge@samba.org>
Wed, 20 Dec 2000 03:22:51 +0000 (03:22 +0000)
committerAndrew Tridgell <tridge@samba.org>
Wed, 20 Dec 2000 03:22:51 +0000 (03:22 +0000)
list of structures rather than the dodgy parsing code we had before

this also gets smbw working correctly with no initial workgroup (using
name_status_find on __MSBROWSE__ returns)

source/include/proto.h
source/include/smb.h
source/libsmb/namequery.c
source/smbwrapper/smbw.c
source/utils/nmblookup.c

index 168600a59f54d54055810a98876188b3b324ef77..c92aeae6f10a579d501ac84cd93da7a4ee7c74b3 100644 (file)
@@ -840,8 +840,9 @@ BOOL deal_with_creds(uchar sess_key[8],
 
 /*The following definitions come from  libsmb/namequery.c  */
 
-BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
-                struct in_addr to_ip,char *master,char *rname);
+struct node_status *name_status_query(int fd,struct nmb_name *name,
+                                     struct in_addr to_ip, int *num_names);
+BOOL name_status_find(int type, struct in_addr to_ip, char *name);
 struct in_addr *name_query(int fd,const char *name,int name_type, 
                           BOOL bcast,BOOL recurse,
                           struct in_addr to_ip, int *count);
index f97e7cd9f53ee5725515e05af9c9e29576a0a307..430b51b8b5ee87610666646f5a7712b40fa8b1af 100644 (file)
@@ -1553,6 +1553,16 @@ struct nmb_name {
   unsigned int name_type;
 };
 
+
+/* A netbios node status array element. */
+struct node_status {
+       char name[16];
+       unsigned char type;
+       unsigned char flags;
+};
+
+
+
 #define AGENT_CMD_CON       0
 #define AGENT_CMD_CON_ANON  2
 #define AGENT_CMD_CON_REUSE 1
index fa90691a95c1b631fd0f9520e6ebafe60497b748..59a3856cfb865bd80e08c55af0a2aff14cc3d3aa 100644 (file)
@@ -45,168 +45,155 @@ static int generate_trn_id(void)
 
 
 /****************************************************************************
- Interpret a node status response.
+ parse a node status response into an array of structures
 ****************************************************************************/
-
-static void _interpret_node_status(char *p, char *master,char *rname)
+static struct node_status *parse_node_status(char *p, int *num_names)
 {
-  int numnames = CVAL(p,0);
-  DEBUG(1,("received %d names\n",numnames));
-
-  if (rname) *rname = 0;
-  if (master) *master = 0;
-
-  p += 1;
-  while (numnames--) {
-    char qname[17];
-    int type;
-    fstring flags;
-    int i;
-    *flags = 0;
-    StrnCpy(qname,p,15);
-    type = CVAL(p,15);
-    p += 16;
-
-    fstrcat(flags, (p[0] & 0x80) ? "<GROUP> " : "        ");
-    if ((p[0] & 0x60) == 0x00) fstrcat(flags,"B ");
-    if ((p[0] & 0x60) == 0x20) fstrcat(flags,"P ");
-    if ((p[0] & 0x60) == 0x40) fstrcat(flags,"M ");
-    if ((p[0] & 0x60) == 0x60) fstrcat(flags,"H ");
-    if (p[0] & 0x10) fstrcat(flags,"<DEREGISTERING> ");
-    if (p[0] & 0x08) fstrcat(flags,"<CONFLICT> ");
-    if (p[0] & 0x04) fstrcat(flags,"<ACTIVE> ");
-    if (p[0] & 0x02) fstrcat(flags,"<PERMANENT> ");
-
-    if (master && !*master && type == 0x1d) {
-      StrnCpy(master,qname,15);
-      trim_string(master,NULL," ");
-    }
+       struct node_status *ret;
+       int i;
 
-    if (rname && !*rname && type == 0x20 && !(p[0]&0x80)) {
-      StrnCpy(rname,qname,15);
-      trim_string(rname,NULL," ");
-    }
-      
-    for (i = strlen( qname) ; --i >= 0 ; ) {
-      if (!isprint((int)qname[i])) qname[i] = '.';
-    }
-    DEBUG(1,("\t%-15s <%02x> - %s\n",qname,type,flags));
-    p+=2;
-  }
+       *num_names = CVAL(p,0);
+
+       if (*num_names == 0) return NULL;
+
+       ret = (struct node_status *)malloc(sizeof(struct node_status)* (*num_names));
+       if (!ret) return NULL;
 
-  DEBUG(1,("num_good_sends=%d num_good_receives=%d\n",
-              IVAL(p,20),IVAL(p,24)));
+       p++;
+       for (i=0;i< *num_names;i++) {
+               StrnCpy(ret[i].name,p,15);
+               trim_string(ret[i].name,NULL," ");
+               ret[i].type = CVAL(p,15);
+               ret[i].flags = p[16];
+               p += 18;
+       }
+       return ret;
 }
 
+
 /****************************************************************************
- Internal function handling a netbios name status query on a host.
+do a NBT node status query on an open socket and return an array of
+structures holding the returned names or NULL if the query failed
 **************************************************************************/
-static BOOL internal_name_status(int fd,char *name,int name_type,BOOL recurse,
-                                struct in_addr to_ip,char *master,
-                                char *rname, BOOL verbose,
-                                void (*fn_interpret_node_status)(char *, char *,char *))
+struct node_status *name_status_query(int fd,struct nmb_name *name,
+                                     struct in_addr to_ip, int *num_names)
 {
-  BOOL found=False;
-  int retries = 2;
-  int retry_time = 2000;
-  struct timeval tval;
-  struct packet_struct p;
-  struct packet_struct *p2;
-  struct nmb_packet *nmb = &p.packet.nmb;
-
-  memset((char *)&p,'\0',sizeof(p));
-
-  nmb->header.name_trn_id = generate_trn_id();
-  nmb->header.opcode = 0;
-  nmb->header.response = False;
-  nmb->header.nm_flags.bcast = False;
-  nmb->header.nm_flags.recursion_available = False;
-  nmb->header.nm_flags.recursion_desired = False;
-  nmb->header.nm_flags.trunc = False;
-  nmb->header.nm_flags.authoritative = False;
-  nmb->header.rcode = 0;
-  nmb->header.qdcount = 1;
-  nmb->header.ancount = 0;
-  nmb->header.nscount = 0;
-  nmb->header.arcount = 0;
-
-  make_nmb_name(&nmb->question.question_name,name,name_type);
+       BOOL found=False;
+       int retries = 2;
+       int retry_time = 2000;
+       struct timeval tval;
+       struct packet_struct p;
+       struct packet_struct *p2;
+       struct nmb_packet *nmb = &p.packet.nmb;
+       struct node_status *ret;
+
+       ZERO_STRUCT(p);
+
+       nmb->header.name_trn_id = generate_trn_id();
+       nmb->header.opcode = 0;
+       nmb->header.response = False;
+       nmb->header.nm_flags.bcast = False;
+       nmb->header.nm_flags.recursion_available = False;
+       nmb->header.nm_flags.recursion_desired = False;
+       nmb->header.nm_flags.trunc = False;
+       nmb->header.nm_flags.authoritative = False;
+       nmb->header.rcode = 0;
+       nmb->header.qdcount = 1;
+       nmb->header.ancount = 0;
+       nmb->header.nscount = 0;
+       nmb->header.arcount = 0;
+       nmb->question.question_name = *name;
+       nmb->question.question_type = 0x21;
+       nmb->question.question_class = 0x1;
+
+       p.ip = to_ip;
+       p.port = NMB_PORT;
+       p.fd = fd;
+       p.timestamp = time(NULL);
+       p.packet_type = NMB_PACKET;
+       
+       GetTimeOfDay(&tval);
+  
+       if (!send_packet(&p)) 
+               return NULL;
 
-  nmb->question.question_type = 0x21;
-  nmb->question.question_class = 0x1;
+       retries--;
 
-  p.ip = to_ip;
-  p.port = NMB_PORT;
-  p.fd = fd;
-  p.timestamp = time(NULL);
-  p.packet_type = NMB_PACKET;
+       while (1) {
+               struct timeval tval2;
+               GetTimeOfDay(&tval2);
+               if (TvalDiff(&tval,&tval2) > retry_time) {
+                       if (!retries)
+                               break;
+                       if (!found && !send_packet(&p))
+                               return NULL;
+                       GetTimeOfDay(&tval);
+                       retries--;
+               }
 
-  GetTimeOfDay(&tval);
+               if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {     
+                       struct nmb_packet *nmb2 = &p2->packet.nmb;
+                       debug_nmb_packet(p2);
+                       
+                       if (nmb2->header.opcode != 0 ||
+                           nmb2->header.nm_flags.bcast ||
+                           nmb2->header.rcode ||
+                           !nmb2->header.ancount ||
+                           nmb2->answers->rr_type != 0x21) {
+                               /* XXXX what do we do with this? could be a
+                                  redirect, but we'll discard it for the
+                                  moment */
+                               free_packet(p2);
+                               continue;
+                       }
 
-  if (!send_packet(&p)) 
-    return(False);
+                       ret = parse_node_status(&nmb2->answers->rdata[0], num_names);
+                       free_packet(p2);
+                       return ret;
+               }
+       }
+       
+       return NULL;
+}
 
-  retries--;
 
-  while (1) {
-         struct timeval tval2;
-         GetTimeOfDay(&tval2);
-         if (TvalDiff(&tval,&tval2) > retry_time) {
-                 if (!retries)
-                         break;
-                 if (!found && !send_packet(&p))
-                         return False;
-                 GetTimeOfDay(&tval);
-                 retries--;
-         }
+/****************************************************************************
+find the first type XX name in a node status reply - used for finding
+a servers name given its IP
+return the matched name in *name
+**************************************************************************/
+BOOL name_status_find(int type, struct in_addr to_ip, char *name)
+{
+       struct node_status *status;
+       struct nmb_name nname;
+       int count, i;
+       int sock;
 
-         if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {     
-                 struct nmb_packet *nmb2 = &p2->packet.nmb;
-                 debug_nmb_packet(p2);
+       sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True);
+       if (sock == -1) return False;
 
-                 if (nmb2->header.opcode != 0 ||
-                     nmb2->header.nm_flags.bcast ||
-                     nmb2->header.rcode ||
-                     !nmb2->header.ancount ||
-                     nmb2->answers->rr_type != 0x21) {
-                         /* XXXX what do we do with this? could be a
-                            redirect, but we'll discard it for the
-                            moment */
-                         free_packet(p2);
-                         continue;
-                 }
+       make_nmb_name(&nname, "*", 0);
+       status = name_status_query(sock, &nname, to_ip, &count);
+       close(sock);
+       if (!status) return False;
 
-                 if(fn_interpret_node_status)
-                         (*fn_interpret_node_status)(&nmb2->answers->rdata[0],master,rname);
-                 free_packet(p2);
-                 return(True);
-         }
-  }
+       for (i=0;i<count;i++) {
+               if (status[i].type == type) break;
+       }
+       if (i == count) return False;
 
-  if(verbose)
-         DEBUG(0,("No status response (this is not unusual)\n"));
+       StrnCpy(name, status[i].name, 15);
 
-  return(False);
+       free(status);
+       return True;
 }
 
-/****************************************************************************
- Do a netbios name status query on a host.
- The "master" parameter is a hack used for finding workgroups.
-**************************************************************************/
-BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
-                struct in_addr to_ip,char *master,char *rname)
-{
-       return internal_name_status(fd,name,name_type,recurse,
-                                   to_ip,master,rname,True,
-                                   _interpret_node_status);
-}
 
 /****************************************************************************
  Do a netbios name query to find someones IP.
  Returns an array of IP addresses or NULL if none.
  *count will be set to the number of addresses returned.
 ****************************************************************************/
-
 struct in_addr *name_query(int fd,const char *name,int name_type, 
                           BOOL bcast,BOOL recurse,
                           struct in_addr to_ip, int *count)
@@ -822,30 +809,6 @@ BOOL find_master_ip(char *group, struct in_addr *master_ip)
        return False;
 }
 
-#if !defined(I_HATE_WINDOWS_REPLY_CODE)
-/********************************************************
- Internal function to extract the MACHINE<0x20> name.
-*********************************************************/
-
-static void _lookup_pdc_name(char *p, char *master,char *rname)
-{
-  int numnames = CVAL(p,0);
-
-  *rname = '\0';
-
-  p += 1;
-  while (numnames--) {
-    int type = CVAL(p,15);
-    if(type == 0x20) {
-      StrnCpy(rname,p,15);
-      trim_string(rname,NULL," ");
-      return;
-    }
-    p += 18;
-  }
-}
-#endif /* I_HATE_WINDOWS_REPLY_CODE */
-
 /********************************************************
  Lookup a PDC name given a Domain name and IP address.
 *********************************************************/
@@ -862,17 +825,9 @@ BOOL lookup_pdc_name(const char *srcname, const char *domain, struct in_addr *pd
    * query here... JRA.
    */
 
-  int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
-
-  if(sock == -1)
-    return False;
-
   *pdc_name = '\0';
 
-  ret = internal_name_status(sock,"*SMBSERVER",0x20,True,
-                *pdc_ip,NULL,pdc_name,False,_lookup_pdc_name);
-
-  close(sock);
+  ret = name_status_find(0x20,*pdc_ip,pdc_name);
 
   if(ret && *pdc_name) {
     fstrcpy(ret_name, pdc_name);
index 65a70c9178343f6e7a769afbaaa96766ba57a53a..91009af1c58066533a9b3a92fefd441968964f23 100644 (file)
@@ -261,6 +261,7 @@ static char *smbw_find_workgroup(void)
        char *p;
        struct in_addr *ip_list = NULL;
        int count = 0;
+       int i;
 
        /* first off see if an existing workgroup name exists */
        p = smbw_getshared("WORKGROUP");
@@ -273,12 +274,21 @@ static char *smbw_find_workgroup(void)
        if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) {
                DEBUG(1,("No workgroups found!"));
                return p;
-               
        }
 
-       free((char *)ip_list);
+       for (i=0;i<count;i++) {
+               static fstring name;
+               if (name_status_find(0x1d, ip_list[i], name)) {
+                       slprintf(server, sizeof(server), "%s#1D", name);
+                       if (smbw_server(server, "IPC$")) {
+                               free(ip_list);
+                               return name;
+                       }
+               }
+       }
+
+       free(ip_list);
 
-       DEBUG(0,("Need to do node status code"));
        return p;
 }
 
index 2cdd85fae8561e0e08e6b08302a8d7bbd5331688..4e85f6ac4568b9b85402492bfe27f32939ad5805 100644 (file)
@@ -80,6 +80,55 @@ static void usage(void)
   printf("\n");
 }
 
+/****************************************************************************
+turn a node status flags field into a string
+****************************************************************************/
+static char *node_status_flags(unsigned char flags)
+{
+       static fstring ret;
+       fstrcpy(ret,"");
+       
+       fstrcat(ret, (flags & 0x80) ? "<GROUP> " : "        ");
+       if ((flags & 0x60) == 0x00) fstrcat(ret,"B ");
+       if ((flags & 0x60) == 0x20) fstrcat(ret,"P ");
+       if ((flags & 0x60) == 0x40) fstrcat(ret,"M ");
+       if ((flags & 0x60) == 0x60) fstrcat(ret,"H ");
+       if (flags & 0x10) fstrcat(ret,"<DEREGISTERING> ");
+       if (flags & 0x08) fstrcat(ret,"<CONFLICT> ");
+       if (flags & 0x04) fstrcat(ret,"<ACTIVE> ");
+       if (flags & 0x02) fstrcat(ret,"<PERMANENT> ");
+       
+       return ret;
+}
+
+/****************************************************************************
+do a node status query
+****************************************************************************/
+static void do_node_status(int fd, char *name, int type, struct in_addr ip)
+{
+       struct nmb_name nname;
+       int count, i, j;
+       struct node_status *status;
+       fstring cleanname;
+
+       printf("Looking up status of %s\n",inet_ntoa(ip));
+       make_nmb_name(&nname, name, type);
+       status = name_status_query(fd,&nname,ip, &count);
+       if (status) {
+               for (i=0;i<count;i++) {
+                       fstrcpy(cleanname, status[i].name);
+                       for (j=0;cleanname[j];j++) {
+                               if (!isprint(cleanname[j])) cleanname[j] = '.';
+                       }
+                       printf("\t%-15s <%02x> - %s\n",
+                              cleanname,status[i].type,
+                              node_status_flags(status[i].flags));
+               }
+               free(status);
+       }
+       printf("\n");
+}
+
 
 /****************************************************************************
 send out one query
@@ -125,9 +174,7 @@ static BOOL query_one(char *lookup, unsigned int lookup_type)
           was valid - ie. name_query returned true.
        */
        if (find_status) {
-               printf("Looking up status of %s\n",inet_ntoa(ip_list[0]));
-               name_status(ServerFD,lookup,lookup_type,True,ip_list[0],NULL,NULL);
-               printf("\n");
+               do_node_status(ServerFD, lookup, lookup_type, ip_list[0]);
        }
 
        safe_free(ip_list);
@@ -245,9 +292,7 @@ int main(int argc,char *argv[])
       {
         fstrcpy(lookup,"*");
         ip = *interpret_addr2(argv[i]);
-        printf("Looking up status of %s\n",inet_ntoa(ip));
-        name_status(ServerFD,lookup,lookup_type,True,ip,NULL,NULL);
-        printf("\n");
+       do_node_status(ServerFD, lookup, lookup_type, ip);
         continue;
       }