mirror of
https://github.com/samba-team/samba.git
synced 2024-12-24 21:34:56 +03:00
55f400bd84
This is merely updating the Copyright statements from 1997 to 1998.
It's a once a year thing :-).
NO OTHER CHANGES WERE MADE.
Jeremy.
(This used to be commit b9c1697723
)
306 lines
8.2 KiB
C
306 lines
8.2 KiB
C
/*
|
|
Unix SMB/Netbios implementation.
|
|
Version 1.9.
|
|
name query routines
|
|
Copyright (C) Andrew Tridgell 1994-1998
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
|
|
|
#include "includes.h"
|
|
|
|
extern pstring scope;
|
|
extern int DEBUGLEVEL;
|
|
|
|
|
|
/****************************************************************************
|
|
interpret a node status response
|
|
****************************************************************************/
|
|
static void _interpret_node_status(char *p, char *master,char *rname)
|
|
{
|
|
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;
|
|
|
|
strcat(flags, (p[0] & 0x80) ? "<GROUP> " : " ");
|
|
if ((p[0] & 0x60) == 0x00) strcat(flags,"B ");
|
|
if ((p[0] & 0x60) == 0x20) strcat(flags,"P ");
|
|
if ((p[0] & 0x60) == 0x40) strcat(flags,"M ");
|
|
if ((p[0] & 0x60) == 0x60) strcat(flags,"H ");
|
|
if (p[0] & 0x10) strcat(flags,"<DEREGISTERING> ");
|
|
if (p[0] & 0x08) strcat(flags,"<CONFLICT> ");
|
|
if (p[0] & 0x04) strcat(flags,"<ACTIVE> ");
|
|
if (p[0] & 0x02) strcat(flags,"<PERMANENT> ");
|
|
|
|
if (master && !*master && type == 0x1d) {
|
|
StrnCpy(master,qname,15);
|
|
trim_string(master,NULL," ");
|
|
}
|
|
|
|
if (rname && !*rname && type == 0x20 && !(p[0]&0x80)) {
|
|
StrnCpy(rname,qname,15);
|
|
trim_string(rname,NULL," ");
|
|
}
|
|
|
|
for (i = strlen( qname) ; --i >= 0 ; ) {
|
|
if (!isprint(qname[i])) qname[i] = '.';
|
|
}
|
|
DEBUG(1,("\t%-15s <%02x> - %s\n",qname,type,flags));
|
|
p+=2;
|
|
}
|
|
DEBUG(1,("num_good_sends=%d num_good_receives=%d\n",
|
|
IVAL(p,20),IVAL(p,24)));
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
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,
|
|
void (*fn)())
|
|
{
|
|
BOOL found=False;
|
|
int retries = 2;
|
|
int retry_time = 5000;
|
|
struct timeval tval;
|
|
struct packet_struct p;
|
|
struct packet_struct *p2;
|
|
struct nmb_packet *nmb = &p.packet.nmb;
|
|
static int name_trn_id = 0;
|
|
|
|
bzero((char *)&p,sizeof(p));
|
|
|
|
if (!name_trn_id) name_trn_id = (time(NULL)%(unsigned)0x7FFF) +
|
|
(getpid()%(unsigned)100);
|
|
name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
|
|
|
|
nmb->header.name_trn_id = name_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,scope);
|
|
|
|
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(False);
|
|
|
|
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--;
|
|
}
|
|
|
|
if ((p2=receive_packet(fd,NMB_PACKET,90)))
|
|
{
|
|
struct nmb_packet *nmb2 = &p2->packet.nmb;
|
|
debug_nmb_packet(p2);
|
|
|
|
if (nmb->header.name_trn_id != nmb2->header.name_trn_id ||
|
|
!nmb2->header.response) {
|
|
/* its not for us - maybe deal with it later */
|
|
if (fn)
|
|
fn(p2);
|
|
else
|
|
free_packet(p2);
|
|
continue;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
_interpret_node_status(&nmb2->answers->rdata[0], master,rname);
|
|
free_packet(p2);
|
|
return(True);
|
|
}
|
|
}
|
|
|
|
|
|
DEBUG(0,("No status response (this is not unusual)\n"));
|
|
|
|
return(False);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
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,char *name,int name_type,
|
|
BOOL bcast,BOOL recurse,
|
|
struct in_addr to_ip, int *count, void (*fn)())
|
|
{
|
|
BOOL found=False;
|
|
int i, retries = 3;
|
|
int retry_time = bcast?250:2000;
|
|
struct timeval tval;
|
|
struct packet_struct p;
|
|
struct packet_struct *p2;
|
|
struct nmb_packet *nmb = &p.packet.nmb;
|
|
static int name_trn_id = 0;
|
|
struct in_addr *ip_list = NULL;
|
|
|
|
bzero((char *)&p,sizeof(p));
|
|
(*count) = 0;
|
|
|
|
if (!name_trn_id) name_trn_id = (time(NULL)%(unsigned)0x7FFF) +
|
|
(getpid()%(unsigned)100);
|
|
name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
|
|
|
|
nmb->header.name_trn_id = name_trn_id;
|
|
nmb->header.opcode = 0;
|
|
nmb->header.response = False;
|
|
nmb->header.nm_flags.bcast = bcast;
|
|
nmb->header.nm_flags.recursion_available = False;
|
|
nmb->header.nm_flags.recursion_desired = recurse;
|
|
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,scope);
|
|
|
|
nmb->question.question_type = 0x20;
|
|
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;
|
|
|
|
retries--;
|
|
|
|
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--;
|
|
}
|
|
|
|
if ((p2=receive_packet(fd,NMB_PACKET,90)))
|
|
{
|
|
struct nmb_packet *nmb2 = &p2->packet.nmb;
|
|
debug_nmb_packet(p2);
|
|
|
|
if (nmb->header.name_trn_id != nmb2->header.name_trn_id ||
|
|
!nmb2->header.response) {
|
|
/* its not for us - maybe deal with it later
|
|
(put it on the queue?) */
|
|
if (fn)
|
|
fn(p2);
|
|
else
|
|
free_packet(p2);
|
|
continue;
|
|
}
|
|
|
|
if (nmb2->header.opcode != 0 ||
|
|
nmb2->header.nm_flags.bcast ||
|
|
nmb2->header.rcode ||
|
|
!nmb2->header.ancount) {
|
|
/* XXXX what do we do with this? could be a redirect, but
|
|
we'll discard it for the moment */
|
|
free_packet(p2);
|
|
continue;
|
|
}
|
|
|
|
ip_list = (struct in_addr *)Realloc(ip_list, sizeof(ip_list[0]) *
|
|
((*count)+nmb2->answers->rdlength/6));
|
|
if (ip_list) {
|
|
DEBUG(fn?3:2,("Got a positive name query response from %s ( ",
|
|
inet_ntoa(p2->ip)));
|
|
for (i=0;i<nmb2->answers->rdlength/6;i++) {
|
|
putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
|
|
DEBUG(fn?3:2,("%s ",inet_ntoa(ip_list[(*count)])));
|
|
(*count)++;
|
|
}
|
|
DEBUG(fn?3:2,(")\n"));
|
|
}
|
|
found=True; retries=0;
|
|
free_packet(p2);
|
|
if (fn) break;
|
|
}
|
|
}
|
|
|
|
return ip_list;
|
|
}
|