diff options
author | Andrew Tridgell <tridge@samba.org> | 2000-12-20 03:22:51 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2000-12-20 03:22:51 +0000 |
commit | abb9a2de72073a8a6f332b60d74af9eb6c3d6f25 (patch) | |
tree | d7814a9822c7c0481e227a5620db122d595264c2 | |
parent | 7bf9d8ce4bb7e96a4c72f674e21d015b1ef1481e (diff) | |
download | samba-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.h | 5 | ||||
-rw-r--r-- | source3/include/smb.h | 10 | ||||
-rw-r--r-- | source3/libsmb/namequery.c | 289 | ||||
-rw-r--r-- | source3/smbwrapper/smbw.c | 16 | ||||
-rw-r--r-- | source3/utils/nmblookup.c | 57 |
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; } |