summaryrefslogtreecommitdiff
path: root/source3/libsmb/namequery.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libsmb/namequery.c')
-rw-r--r--source3/libsmb/namequery.c289
1 files changed, 122 insertions, 167 deletions
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);