summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2000-12-20 03:22:51 +0000
committerAndrew Tridgell <tridge@samba.org>2000-12-20 03:22:51 +0000
commitabb9a2de72073a8a6f332b60d74af9eb6c3d6f25 (patch)
treed7814a9822c7c0481e227a5620db122d595264c2
parent7bf9d8ce4bb7e96a4c72f674e21d015b1ef1481e (diff)
downloadsamba-abb9a2de72073a8a6f332b60d74af9eb6c3d6f25.tar.gz
samba-abb9a2de72073a8a6f332b60d74af9eb6c3d6f25.tar.bz2
samba-abb9a2de72073a8a6f332b60d74af9eb6c3d6f25.zip
implemented a much nicer name_status() interface. It now returns a
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) (This used to be commit f2be88a8738a39ca5c98936edb7537cd701348a1)
-rw-r--r--source3/include/proto.h5
-rw-r--r--source3/include/smb.h10
-rw-r--r--source3/libsmb/namequery.c289
-rw-r--r--source3/smbwrapper/smbw.c16
-rw-r--r--source3/utils/nmblookup.c57
5 files changed, 199 insertions, 178 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 168600a59f..c92aeae6f1 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -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);
diff --git a/source3/include/smb.h b/source3/include/smb.h
index f97e7cd9f5..430b51b8b5 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -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
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index fa90691a95..59a3856cfb 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -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);
diff --git a/source3/smbwrapper/smbw.c b/source3/smbwrapper/smbw.c
index 65a70c9178..91009af1c5 100644
--- a/source3/smbwrapper/smbw.c
+++ b/source3/smbwrapper/smbw.c
@@ -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;
}
diff --git a/source3/utils/nmblookup.c b/source3/utils/nmblookup.c
index 2cdd85fae8..4e85f6ac45 100644
--- a/source3/utils/nmblookup.c
+++ b/source3/utils/nmblookup.c
@@ -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;
}