⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 namequery.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*    Unix SMB/CIFS implementation.   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"/* nmbd.c sets this to True. */BOOL global_in_nmbd = False;/**************************************************************************** Generate a random trn_id.****************************************************************************/static int generate_trn_id(void){	static int trn_id;	if (trn_id == 0) {		sys_srandom(sys_getpid());	}	trn_id = sys_random();	return trn_id % (unsigned)0x7FFF;}/**************************************************************************** Parse a node status response into an array of structures.****************************************************************************/static NODE_STATUS_STRUCT *parse_node_status(char *p, int *num_names, struct node_status_extra *extra){	NODE_STATUS_STRUCT *ret;	int i;	*num_names = CVAL(p,0);	if (*num_names == 0)		return NULL;	ret = SMB_MALLOC_ARRAY(NODE_STATUS_STRUCT,*num_names);	if (!ret)		return NULL;	p++;	for (i=0;i< *num_names;i++) {		StrnCpy(ret[i].name,p,15);		trim_char(ret[i].name,'\0',' ');		ret[i].type = CVAL(p,15);		ret[i].flags = p[16];		p += 18;		DEBUG(10, ("%s#%02x: flags = 0x%02x\n", ret[i].name, 			   ret[i].type, ret[i].flags));	}	/*	 * Also, pick up the MAC address ...	 */	if (extra) {		memcpy(&extra->mac_addr, p, 6); /* Fill in the mac addr */	}	return ret;}/**************************************************************************** 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.**************************************************************************/NODE_STATUS_STRUCT *node_status_query(int fd,struct nmb_name *name,				      struct in_addr to_ip, int *num_names,				      struct node_status_extra *extra){	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;	NODE_STATUS_STRUCT *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;	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_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;			}			ret = parse_node_status(&nmb2->answers->rdata[0], num_names, extra);			free_packet(p2);			return ret;		}	}		return NULL;}/**************************************************************************** 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(const char *q_name, int q_type, int type, struct in_addr to_ip, fstring name){	NODE_STATUS_STRUCT *status = NULL;	struct nmb_name nname;	int count, i;	int sock;	BOOL result = False;	if (lp_disable_netbios()) {		DEBUG(5,("name_status_find(%s#%02x): netbios is disabled\n", q_name, q_type));		return False;	}	DEBUG(10, ("name_status_find: looking up %s#%02x at %s\n", q_name, 		   q_type, inet_ntoa(to_ip)));	/* Check the cache first. */	if (namecache_status_fetch(q_name, q_type, type, to_ip, name))		return True;	sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True);	if (sock == -1)		goto done;	/* W2K PDC's seem not to respond to '*'#0. JRA */	make_nmb_name(&nname, q_name, q_type);	status = node_status_query(sock, &nname, to_ip, &count, NULL);	close(sock);	if (!status)		goto done;	for (i=0;i<count;i++) {		if (status[i].type == type)			break;	}	if (i == count)		goto done;	pull_ascii_nstring(name, sizeof(fstring), status[i].name);	/* Store the result in the cache. */	/* but don't store an entry for 0x1c names here.  Here we have 	   a single host and DOMAIN<0x1c> names should be a list of hosts */	   	if ( q_type != 0x1c )		namecache_status_store(q_name, q_type, type, to_ip, name);	result = True; done:	SAFE_FREE(status);	DEBUG(10, ("name_status_find: name %sfound", result ? "" : "not "));	if (result)		DEBUGADD(10, (", name %s ip address is %s", name, inet_ntoa(to_ip)));	DEBUG(10, ("\n"));		return result;}/*  comparison function used by sort_ip_list*/static int ip_compare(struct in_addr *ip1, struct in_addr *ip2){	int max_bits1=0, max_bits2=0;	int num_interfaces = iface_count();	int i;	for (i=0;i<num_interfaces;i++) {		struct in_addr ip;		int bits1, bits2;		ip = *iface_n_bcast(i);		bits1 = matching_quad_bits((uchar *)&ip1->s_addr, (uchar *)&ip.s_addr);		bits2 = matching_quad_bits((uchar *)&ip2->s_addr, (uchar *)&ip.s_addr);		max_bits1 = MAX(bits1, max_bits1);		max_bits2 = MAX(bits2, max_bits2);	}			/* bias towards directly reachable IPs */	if (iface_local(*ip1)) {		max_bits1 += 32;	}	if (iface_local(*ip2)) {		max_bits2 += 32;	}	return max_bits2 - max_bits1;}/******************************************************************* compare 2 ldap IPs by nearness to our interfaces - used in qsort*******************************************************************/static int ip_service_compare(struct ip_service *ip1, struct ip_service *ip2){	int result;		if ( (result = ip_compare(&ip1->ip, &ip2->ip)) != 0 )		return result;			if ( ip1->port > ip2->port )		return 1;		if ( ip1->port < ip2->port )		return -1;			return 0;}/*  sort an IP list so that names that are close to one of our interfaces   are at the top. This prevents the problem where a WINS server returns an IP that  is not reachable from our subnet as the first match*/static void sort_ip_list(struct in_addr *iplist, int count){	if (count <= 1) {		return;	}	qsort(iplist, count, sizeof(struct in_addr), QSORT_CAST ip_compare);	}static void sort_ip_list2(struct ip_service *iplist, int count){	if (count <= 1) {		return;	}	qsort(iplist, count, sizeof(struct ip_service), QSORT_CAST ip_service_compare);	}/********************************************************************** Remove any duplicate address/port pairs in the list  *********************************************************************/static int remove_duplicate_addrs2( struct ip_service *iplist, int count ){	int i, j;		DEBUG(10,("remove_duplicate_addrs2: looking for duplicate address/port pairs\n"));		/* one loop to remove duplicates */	for ( i=0; i<count; i++ ) {		if ( is_zero_ip(iplist[i].ip) )			continue;							for ( j=i+1; j<count; j++ ) {			if ( ip_service_equal(iplist[i], iplist[j]) )				zero_ip(&iplist[j].ip);		}	}				/* one loop to clean up any holes we left */	/* first ip should never be a zero_ip() */	for (i = 0; i<count; ) {		if ( is_zero_ip(iplist[i].ip) ) {			if (i != count-1 )				memmove(&iplist[i], &iplist[i+1], (count - i - 1)*sizeof(iplist[i]));			count--;			continue;		}		i++;	}	return count;}/**************************************************************************** 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. *timed_out is set if we failed by timing out****************************************************************************/struct in_addr *name_query(int fd,const char *name,int name_type, 			   BOOL bcast,BOOL recurse,			   struct in_addr to_ip, int *count, int *flags,			   BOOL *timed_out){	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;	struct in_addr *ip_list = NULL;	if (lp_disable_netbios()) {		DEBUG(5,("name_query(%s#%02x): netbios is disabled\n", name, name_type));		return NULL;	}	if (timed_out) {		*timed_out = False;	}		memset((char *)&p,'\0',sizeof(p));	(*count) = 0;	(*flags) = 0;		nmb->header.name_trn_id = generate_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);		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;		struct in_addr *tmp_ip_list;				GetTimeOfDay(&tval2);		if (TvalDiff(&tval,&tval2) > retry_time) {			if (!retries)				break;			if (!found && !send_packet(&p))				return NULL;			GetTimeOfDay(&tval);			retries--;		}				if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {     			struct nmb_packet *nmb2 = &p2->packet.nmb;			debug_nmb_packet(p2);						/* If we get a Negative Name Query Response from a WINS			 * server, we should report it and give up.			 */			if( 0 == nmb2->header.opcode		/* A query response   */			    && !(bcast)			/* from a WINS server */			    && nmb2->header.rcode		/* Error returned     */				) {								if( DEBUGLVL( 3 ) ) {					/* Only executed if DEBUGLEVEL >= 3 */					dbgtext( "Negative name query response, rcode 0x%02x: ", nmb2->header.rcode );					switch( nmb2->header.rcode ) {					case 0x01:						dbgtext( "Request was invalidly formatted.\n" );						break;					case 0x02:						dbgtext( "Problem with NBNS, cannot process name.\n");						break;					case 0x03:						dbgtext( "The name requested does not exist.\n" );						break;					case 0x04:						dbgtext( "Unsupported request error.\n" );						break;					case 0x05:						dbgtext( "Query refused error.\n" );						break;					default:						dbgtext( "Unrecognized error code.\n" );						break;					}				}				free_packet(p2);				return( NULL );			}						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;			}						tmp_ip_list = SMB_REALLOC_ARRAY( ip_list, struct in_addr,						(*count) + nmb2->answers->rdlength/6 );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -