summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2005-01-21 11:18:56 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:09:03 -0500
commit2383787f199c51cdc202a3cef5822a9fe6b8774c (patch)
tree52419b4e736f5ae1727561a3c9831e899edb35c5
parentf1aaef3015864f9323711127a4964a8eceff6a52 (diff)
downloadsamba-2383787f199c51cdc202a3cef5822a9fe6b8774c.tar.gz
samba-2383787f199c51cdc202a3cef5822a9fe6b8774c.tar.bz2
samba-2383787f199c51cdc202a3cef5822a9fe6b8774c.zip
r4891: - added a generic resolve_name() async interface in libcli/resolve/,
which will eventually try all resolution methods setup in smb.conf - only resolution backend at the moment is bcast, which does a parallel broadcast to all configured network interfaces, and takes the first reply that comes in (this nicely demonstrates how to do parallel requests using the async APIs) - converted all the existing code to use the new resolve_name() api - removed all the old nmb code (yay!) (This used to be commit 239c310f255e43dd2d1c2433f666c9faaacbdce3)
-rw-r--r--source4/client/client.c9
-rw-r--r--source4/libcli/cliconnect.c8
-rw-r--r--source4/libcli/composite/connect.c47
-rw-r--r--source4/libcli/config.mk18
-rw-r--r--source4/libcli/namequery.c1104
-rw-r--r--source4/libcli/namequery_dc.c27
-rw-r--r--source4/libcli/nbt/libnbt.h6
-rw-r--r--source4/libcli/nbt/namequery.c66
-rw-r--r--source4/libcli/nbt/nbtname.c54
-rw-r--r--source4/libcli/nbt/nbtsocket.c48
-rw-r--r--source4/libcli/nmblib.c1316
-rw-r--r--source4/libcli/raw/clisocket.c16
-rw-r--r--source4/libcli/raw/clitransport.c47
-rw-r--r--source4/libcli/raw/libcliraw.h3
-rw-r--r--source4/libcli/resolve/bcast.c163
-rw-r--r--source4/libcli/resolve/resolve.c51
-rw-r--r--source4/libcli/unexpected.c170
-rw-r--r--source4/libnet/libnet_rpc.c27
-rw-r--r--source4/torture/rpc/xplogin.c11
-rw-r--r--source4/torture/torture.c29
20 files changed, 452 insertions, 2768 deletions
diff --git a/source4/client/client.c b/source4/client/client.c
index 6c777bca50..a3631fd710 100644
--- a/source4/client/client.c
+++ b/source4/client/client.c
@@ -3105,11 +3105,14 @@ handle a message operation
****************************************************************************/
static int do_message_op(void)
{
- struct nmb_name called, calling;
+ struct nbt_name called, calling;
const char *server_name;
- make_nmb_name(&calling, lp_netbios_name(), 0x0);
- choose_called_name(&called, desthost, name_type);
+ calling.name = lp_netbios_name();
+ calling.type = NBT_NAME_CLIENT;
+ calling.scope = NULL;
+
+ nbt_choose_called_name(NULL, &called, desthost, name_type);
server_name = dest_ip ? dest_ip : desthost;
diff --git a/source4/libcli/cliconnect.c b/source4/libcli/cliconnect.c
index 0f916d1eb1..aaed36eb05 100644
--- a/source4/libcli/cliconnect.c
+++ b/source4/libcli/cliconnect.c
@@ -1,7 +1,9 @@
/*
Unix SMB/CIFS implementation.
+
client connect/disconnect routines
- Copyright (C) Andrew Tridgell 2003
+
+ Copyright (C) Andrew Tridgell 2003-2005
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
@@ -49,8 +51,8 @@ BOOL smbcli_socket_connect(struct smbcli_state *cli, const char *server)
/* wrapper around smbcli_transport_connect() */
BOOL smbcli_transport_establish(struct smbcli_state *cli,
- struct nmb_name *calling,
- struct nmb_name *called)
+ struct nbt_name *calling,
+ struct nbt_name *called)
{
return smbcli_transport_connect(cli->transport, calling, called);
}
diff --git a/source4/libcli/composite/connect.c b/source4/libcli/composite/connect.c
index 891d16b4e6..7e08aab0d5 100644
--- a/source4/libcli/composite/connect.c
+++ b/source4/libcli/composite/connect.c
@@ -26,7 +26,8 @@
#include "libcli/composite/composite.h"
/* the stages of this call */
-enum connect_stage {CONNECT_SOCKET,
+enum connect_stage {CONNECT_RESOLVE,
+ CONNECT_SOCKET,
CONNECT_SESSION_REQUEST,
CONNECT_NEGPROT,
CONNECT_SESSION_SETUP,
@@ -209,7 +210,7 @@ static NTSTATUS connect_socket(struct smbcli_composite *c,
{
struct connect_state *state = talloc_get_type(c->private, struct connect_state);
NTSTATUS status;
- struct nmb_name calling, called;
+ struct nbt_name calling, called;
status = smbcli_sock_connect_recv(state->creq);
NT_STATUS_NOT_OK_RETURN(status);
@@ -225,8 +226,11 @@ static NTSTATUS connect_socket(struct smbcli_composite *c,
return connect_send_negprot(c, io);
}
- make_nmb_name(&calling, io->in.calling_name, 0x0);
- choose_called_name(&called, io->in.called_name, 0x20);
+ calling.name = io->in.calling_name;
+ calling.type = NBT_NAME_CLIENT;
+ calling.scope = NULL;
+
+ nbt_choose_called_name(state, &called, io->in.called_name, NBT_NAME_SERVER);
state->req = smbcli_transport_connect_send(state->transport, &calling, &called);
NT_STATUS_HAVE_NO_MEMORY(state->req);
@@ -239,6 +243,29 @@ static NTSTATUS connect_socket(struct smbcli_composite *c,
}
+/*
+ called when name resolution is finished
+*/
+static NTSTATUS connect_resolve(struct smbcli_composite *c,
+ struct smb_composite_connect *io)
+{
+ struct connect_state *state = talloc_get_type(c->private, struct connect_state);
+ NTSTATUS status;
+ const char *address;
+
+ status = resolve_name_recv(state->creq, state, &address);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ state->creq = smbcli_sock_connect_send(state->sock, address, state->io->in.port);
+ NT_STATUS_HAVE_NO_MEMORY(state->creq);
+
+ c->stage = CONNECT_SOCKET;
+ state->creq->async.private = c;
+ state->creq->async.fn = composite_handler;
+
+ return NT_STATUS_OK;
+}
+
/*
handle and dispatch state transitions
@@ -248,6 +275,9 @@ static void state_handler(struct smbcli_composite *c)
struct connect_state *state = talloc_get_type(c->private, struct connect_state);
switch (c->stage) {
+ case CONNECT_RESOLVE:
+ c->status = connect_resolve(c, state->io);
+ break;
case CONNECT_SOCKET:
c->status = connect_socket(c, state->io);
break;
@@ -301,6 +331,7 @@ struct smbcli_composite *smb_composite_connect_send(struct smb_composite_connect
{
struct smbcli_composite *c;
struct connect_state *state;
+ struct nbt_name name;
c = talloc_zero(NULL, struct smbcli_composite);
if (c == NULL) goto failed;
@@ -314,11 +345,15 @@ struct smbcli_composite *smb_composite_connect_send(struct smb_composite_connect
state->io = io;
c->state = SMBCLI_REQUEST_SEND;
- c->stage = CONNECT_SOCKET;
+ c->stage = CONNECT_RESOLVE;
c->event_ctx = state->sock->event.ctx;
c->private = state;
- state->creq = smbcli_sock_connect_send(state->sock, io->in.dest_host, io->in.port);
+ name.name = io->in.dest_host;
+ name.type = NBT_NAME_SERVER;
+ name.scope = NULL;
+
+ state->creq = resolve_name_send(&name, c->event_ctx);
if (state->creq == NULL) goto failed;
state->creq->async.private = c;
diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk
index 87866db66d..21cfed8987 100644
--- a/source4/libcli/config.mk
+++ b/source4/libcli/config.mk
@@ -8,15 +8,9 @@ ADD_OBJ_FILES = libcli/util/asn1.o \
libcli/util/smbdes.o \
libcli/util/smbencrypt.o
-[SUBSYSTEM::LIBCLI_NMB]
-ADD_OBJ_FILES = libcli/unexpected.o \
- libcli/namecache.o \
- libcli/nmblib.o \
- libcli/namequery.o
-REQUIRED_SUBSYSTEMS = RPC_NDR_LSA
-
[SUBSYSTEM::LIBCLI_LSA]
ADD_OBJ_FILES = libcli/util/clilsa.o
+REQUIRED_SUBSYSTEMS = RPC_NDR_LSA
[SUBSYSTEM::LIBCLI_COMPOSITE]
ADD_OBJ_FILES = \
@@ -33,6 +27,12 @@ ADD_OBJ_FILES = \
libcli/nbt/namequery.o
REQUIRED_SUBSYSTEMS = NDR_NBT
+[SUBSYSTEM::LIBCLI_RESOLVE]
+ADD_OBJ_FILES = \
+ libcli/resolve/resolve.o \
+ libcli/resolve/bcast.o
+REQUIRED_SUBSYSTEMS = LIBCLI_NBT
+
[SUBSYSTEM::LIBCLI]
-REQUIRED_SUBSYSTEMS = LIBCLI_RAW LIBCLI_UTILS LIBCLI_AUTH LIBCLI_NMB \
- LIBCLI_COMPOSITE LIBCLI_NBT
+REQUIRED_SUBSYSTEMS = LIBCLI_RAW LIBCLI_UTILS LIBCLI_AUTH \
+ LIBCLI_COMPOSITE LIBCLI_NBT LIBCLI_RESOLVE
diff --git a/source4/libcli/namequery.c b/source4/libcli/namequery.c
deleted file mode 100644
index c440a604c7..0000000000
--- a/source4/libcli/namequery.c
+++ /dev/null
@@ -1,1104 +0,0 @@
-/*
- 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"
-#include "system/network.h"
-#include "system/time.h"
-
-/* A netbios node status array element. */
-struct node_status {
- char name[16];
- uint8_t type;
- uint8_t flags;
-};
-
-
-/* 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(getpid());
- }
-
- trn_id = sys_random();
-
- return trn_id % (uint_t)0x7FFF;
-}
-
-
-/****************************************************************************
- parse a node status response into an array of structures
-****************************************************************************/
-static struct node_status *parse_node_status(char *p, int *num_names)
-{
- struct node_status *ret;
- int i;
-
- *num_names = CVAL(p,0);
-
- if (*num_names == 0) return NULL;
-
- ret = malloc_array_p(struct node_status, *num_names);
- if (!ret) return NULL;
-
- 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;
- DEBUG(10, ("%s#%02x: flags = 0x%02x\n", ret[i].name,
- ret[i].type, ret[i].flags));
- }
- 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
-**************************************************************************/
-struct node_status *node_status_query(int fd,struct nmb_name *name,
- struct ipv4_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;
- 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;
-
- 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);
- 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 ipv4_addr to_ip, char *name)
-{
- struct node_status *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, sys_inet_ntoa(to_ip)));
-
- 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);
- 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(name, status[i].name, 16, 15, STR_TERMINATE);
- result = True;
-
- done:
- SAFE_FREE(status);
-
- DEBUG(10, ("name_status_find: name %sfound", result ? "" : "not "));
-
- if (result)
- DEBUGADD(10, (", ip address is %s", sys_inet_ntoa(to_ip)));
-
- DEBUG(10, ("\n"));
-
- return result;
-}
-
-
-/*
- comparison function used by sort_ip_list
-*/
-int ip_compare(struct ipv4_addr *ip1, struct ipv4_addr *ip2)
-{
- int max_bits1=0, max_bits2=0;
- int num_interfaces = iface_count();
- int i;
-
- for (i=0;i<num_interfaces;i++) {
- struct ipv4_addr ip;
- int bits1, bits2;
- ip = *iface_n_bcast(i);
- bits1 = matching_quad_bits((uint8_t *)&ip1->addr, (uint8_t *)&ip.addr);
- bits2 = matching_quad_bits((uint8_t *)&ip2->addr, (uint8_t *)&ip.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;
-}
-
-/*
- 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 ipv4_addr *iplist, int count)
-{
- if (count <= 1) {
- return;
- }
-
- qsort(iplist, count, sizeof(struct ipv4_addr), QSORT_CAST ip_compare);
-}
-
-
-/****************************************************************************
- 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 ipv4_addr *name_query(int fd,const char *name,int name_type,
- BOOL bcast,BOOL recurse,
- struct ipv4_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 ipv4_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 ipv4_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 */
- DEBUG(3,("Negative name query response, rcode 0x%02x: ", nmb2->header.rcode ));
- switch( nmb2->header.rcode ) {
- case 0x01:
- DEBUG(3,("Request was invalidly formatted.\n" ));
- break;
- case 0x02:
- DEBUG(3,("Problem with NBNS, cannot process name.\n"));
- break;
- case 0x03:
- DEBUG(3,("The name requested does not exist.\n" ));
- break;
- case 0x04:
- DEBUG(3,("Unsupported request error.\n" ));
- break;
- case 0x05:
- DEBUG(3,("Query refused error.\n" ));
- break;
- default:
- DEBUG(3,("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 = realloc_p(ip_list,
- struct ipv4_addr,
- (*count) + nmb2->answers->rdlength/6);
-
- if (!tmp_ip_list) {
- DEBUG(0,("name_query: realloc_p failed.\n"));
- SAFE_FREE(ip_list);
- }
-
- ip_list = tmp_ip_list;
-
- if (ip_list) {
- DEBUG(2,("Got a positive name query response from %s ( ", sys_inet_ntoa(p2->ip)));
- for (i=0;i<nmb2->answers->rdlength/6;i++) {
- putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
- DEBUGADD(2,("%s ",sys_inet_ntoa(ip_list[(*count)])));
- (*count)++;
- }
- DEBUGADD(2,(")\n"));
- }
-
- found=True;
- retries=0;
- /* We add the flags back ... */
- if (nmb2->header.response)
- (*flags) |= NM_FLAGS_RS;
- if (nmb2->header.nm_flags.authoritative)
- (*flags) |= NM_FLAGS_AA;
- if (nmb2->header.nm_flags.trunc)
- (*flags) |= NM_FLAGS_TC;
- if (nmb2->header.nm_flags.recursion_desired)
- (*flags) |= NM_FLAGS_RD;
- if (nmb2->header.nm_flags.recursion_available)
- (*flags) |= NM_FLAGS_RA;
- if (nmb2->header.nm_flags.bcast)
- (*flags) |= NM_FLAGS_B;
- free_packet(p2);
- /*
- * If we're doing a unicast lookup we only
- * expect one reply. Don't wait the full 2
- * seconds if we got one. JRA.
- */
- if(!bcast && found)
- break;
- }
- }
-
- if (timed_out) {
- *timed_out = True;
- }
-
- /* sort the ip list so we choose close servers first if possible */
- sort_ip_list(ip_list, *count);
-
- return ip_list;
-}
-
-/********************************************************
- Resolve via "bcast" method.
-*********************************************************/
-
-BOOL name_resolve_bcast(const char *name, int name_type,
- struct ipv4_addr **return_ip_list, int *return_count)
-{
- int sock, i;
- int num_interfaces = iface_count();
-
- if (lp_disable_netbios()) {
- DEBUG(5,("name_resolve_bcast(%s#%02x): netbios is disabled\n", name, name_type));
- return False;
- }
-
- *return_ip_list = NULL;
- *return_count = 0;
-
- /*
- * "bcast" means do a broadcast lookup on all the local interfaces.
- */
-
- DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
-
- sock = open_socket_in( SOCK_DGRAM, 0, 3,
- interpret_addr(lp_socket_address()), True );
-
- if (sock == -1) return False;
-
- set_socket_options(sock,"SO_BROADCAST");
- /*
- * Lookup the name on all the interfaces, return on
- * the first successful match.
- */
- for( i = num_interfaces-1; i >= 0; i--) {
- struct ipv4_addr sendto_ip;
- int flags;
- /* Done this way to fix compiler error on IRIX 5.x */
- sendto_ip = *iface_n_bcast(i);
- *return_ip_list = name_query(sock, name, name_type, True,
- True, sendto_ip, return_count, &flags, NULL);
- if(*return_ip_list != NULL) {
- close(sock);
- return True;
- }
- }
-
- close(sock);
- return False;
-}
-
-/********************************************************
- Resolve via "wins" method.
-*********************************************************/
-BOOL resolve_wins(TALLOC_CTX *mem_ctx, const char *name, int name_type,
- struct ipv4_addr **return_iplist, int *return_count)
-{
- int sock, t, i;
- char **wins_tags;
- struct ipv4_addr src_ip;
-
- if (lp_disable_netbios()) {
- DEBUG(5,("resolve_wins(%s#%02x): netbios is disabled\n", name, name_type));
- return False;
- }
-
- *return_iplist = NULL;
- *return_count = 0;
-
- DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
-
- if (wins_srv_count() < 1) {
- DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
- return False;
- }
-
- /* we try a lookup on each of the WINS tags in turn */
- wins_tags = wins_srv_tags();
-
- if (!wins_tags) {
- /* huh? no tags?? give up in disgust */
- return False;
- }
-
- /* the address we will be sending from */
- src_ip = interpret_addr2(lp_socket_address());
-
- /* in the worst case we will try every wins server with every
- tag! */
- for (t=0; wins_tags && wins_tags[t]; t++) {
- int srv_count = wins_srv_count_tag(wins_tags[t]);
- for (i=0; i<srv_count; i++) {
- struct ipv4_addr wins_ip;
- int flags;
- BOOL timed_out;
-
- wins_ip = wins_srv_ip_tag(wins_tags[t], src_ip);
-
- if (global_in_nmbd && ismyip(wins_ip)) {
- /* yikes! we'll loop forever */
- continue;
- }
-
- /* skip any that have been unresponsive lately */
- if (wins_srv_is_dead(wins_ip, src_ip)) {
- continue;
- }
-
- DEBUG(3,("resolve_wins: using WINS server %s and tag '%s'\n", sys_inet_ntoa(wins_ip), wins_tags[t]));
-
- sock = open_socket_in(SOCK_DGRAM, 0, 3, src_ip.addr, True);
- if (sock == -1) {
- continue;
- }
-
- *return_iplist = name_query(sock,name,name_type, False,
- True, wins_ip, return_count, &flags,
- &timed_out);
- if (*return_iplist != NULL) {
- goto success;
- }
- close(sock);
-
- if (timed_out) {
- /* Timed out wating for WINS server to respond. Mark it dead. */
- wins_srv_died(wins_ip, src_ip);
- } else {
- /* The name definately isn't in this
- group of WINS servers. goto the next group */
- break;
- }
- }
- }
-
- wins_srv_tags_free(wins_tags);
- return False;
-
-success:
- wins_srv_tags_free(wins_tags);
- close(sock);
- return True;
-}
-
-/********************************************************
- Resolve via "hosts" method.
-*********************************************************/
-
-static BOOL resolve_hosts(const char *name,
- struct ipv4_addr **return_iplist, int *return_count)
-{
- /*
- * "host" means do a localhost, or dns lookup.
- */
- struct hostent *hp;
-
- *return_iplist = NULL;
- *return_count = 0;
-
- DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
-
- if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
- struct ipv4_addr return_ip;
- putip((char *)&return_ip,(char *)hp->h_addr);
- *return_iplist = malloc_p(struct ipv4_addr);
- if(*return_iplist == NULL) {
- DEBUG(3,("resolve_hosts: malloc fail !\n"));
- return False;
- }
- **return_iplist = return_ip;
- *return_count = 1;
- return True;
- }
- return False;
-}
-
-/********************************************************
- Internal interface to resolve a name into an IP address.
- Use this function if the string is either an IP address, DNS
- or host name or NetBIOS name. This uses the name switch in the
- smb.conf to determine the order of name resolution.
-*********************************************************/
-
-static BOOL internal_resolve_name(TALLOC_CTX *mem_ctx, const char *name, int name_type,
- struct ipv4_addr **return_iplist, int *return_count)
-{
- char *name_resolve_list;
- fstring tok;
- const char *ptr;
- BOOL allones = (strcmp(name,"255.255.255.255") == 0);
- BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
- BOOL is_address = is_ipaddress(name);
- BOOL result = False;
- struct ipv4_addr *nodupes_iplist;
- int i;
-
- *return_iplist = NULL;
- *return_count = 0;
-
- DEBUG(10, ("internal_resolve_name: looking up %s#%x\n", name, name_type));
-
- if (allzeros || allones || is_address) {
- *return_iplist = malloc_p(struct ipv4_addr);
- if(*return_iplist == NULL) {
- DEBUG(3,("internal_resolve_name: malloc fail !\n"));
- return False;
- }
- if(is_address) {
- /* if it's in the form of an IP address then get the lib to interpret it */
- if (((*return_iplist)->addr = inet_addr(name)) == 0xFFFFFFFF ){
- DEBUG(1,("internal_resolve_name: inet_addr failed on %s\n", name));
- return False;
- }
- } else {
- (*return_iplist)->addr = allones ? 0xFFFFFFFF : 0;
- *return_count = 1;
- }
- return True;
- }
-
- /* Check netbios name cache */
-
- if (namecache_fetch(mem_ctx, name, name_type, return_iplist, return_count)) {
-
- /* This could be a negative response */
-
- return (*return_count > 0);
- }
-
- name_resolve_list = talloc_strdup(mem_ctx, lp_name_resolve_order());
- ptr = name_resolve_list;
- if (!ptr || !*ptr)
- ptr = "host";
-
- while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
- if((strequal(tok, "host") || strequal(tok, "hosts"))) {
- if (name_type == 0x20) {
- if (resolve_hosts(name, return_iplist, return_count)) {
- result = True;
- goto done;
- }
- }
- } else if(strequal( tok, "lmhosts")) {
- /* REWRITE: add back in? */
- DEBUG(2,("resolve_name: REWRITE: add lmhosts back?? %s\n", tok));
- } else if(strequal( tok, "wins")) {
- /* don't resolve 1D via WINS */
- if (name_type != 0x1D &&
- resolve_wins(mem_ctx, name, name_type, return_iplist, return_count)) {
- result = True;
- goto done;
- }
- } else if(strequal( tok, "bcast")) {
- if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
- result = True;
- goto done;
- }
- } else {
- DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
- }
- }
-
- /* All of the resolve_* functions above have returned false. */
-
- SAFE_FREE(*return_iplist);
- *return_count = 0;
-
- return False;
-
- done:
-
- /* Remove duplicate entries. Some queries, notably #1c (domain
- controllers) return the PDC in iplist[0] and then all domain
- controllers including the PDC in iplist[1..n]. Iterating over
- the iplist when the PDC is down will cause two sets of timeouts. */
-
- if (*return_count && (nodupes_iplist = malloc_array_p(struct ipv4_addr, *return_count))) {
- int nodupes_count = 0;
-
- /* Iterate over return_iplist looking for duplicates */
-
- for (i = 0; i < *return_count; i++) {
- BOOL is_dupe = False;
- int j;
-
- for (j = i + 1; j < *return_count; j++) {
- if (ipv4_equal((*return_iplist)[i],
- (*return_iplist)[j])) {
- is_dupe = True;
- break;
- }
- }
-
- if (!is_dupe) {
-
- /* This one not a duplicate */
-
- nodupes_iplist[nodupes_count] = (*return_iplist)[i];
- nodupes_count++;
- }
- }
-
- /* Switcheroo with original list */
-
- free(*return_iplist);
-
- *return_iplist = nodupes_iplist;
- *return_count = nodupes_count;
- }
-
- /* Save in name cache */
- for (i = 0; i < *return_count && DEBUGLEVEL == 100; i++)
- DEBUG(100, ("Storing name %s of type %d (ip: %s)\n", name,
- name_type, sys_inet_ntoa((*return_iplist)[i])));
-
- namecache_store(mem_ctx, name, name_type, *return_count, *return_iplist);
-
- /* Display some debugging info */
-
- DEBUG(10, ("internal_resolve_name: returning %d addresses: ",
- *return_count));
-
- for (i = 0; i < *return_count; i++)
- DEBUGADD(10, ("%s ", sys_inet_ntoa((*return_iplist)[i])));
-
- DEBUG(10, ("\n"));
-
- return result;
-}
-
-/********************************************************
- Internal interface to resolve a name into one IP address.
- Use this function if the string is either an IP address, DNS
- or host name or NetBIOS name. This uses the name switch in the
- smb.conf to determine the order of name resolution.
-*********************************************************/
-BOOL resolve_name(TALLOC_CTX *mem_ctx, const char *name, struct ipv4_addr *return_ip, int name_type)
-{
- struct ipv4_addr *ip_list = NULL;
- int count = 0;
-
- if (is_ipaddress(name)) {
- *return_ip = interpret_addr2(name);
- return True;
- }
-
- if (internal_resolve_name(mem_ctx, name, name_type, &ip_list, &count)) {
- int i;
- /* only return valid addresses for TCP connections */
- for (i=0; i<count; i++) {
- const char *ip_str = sys_inet_ntoa(ip_list[i]);
- if (ip_str &&
- strcmp(ip_str, "255.255.255.255") != 0 &&
- strcmp(ip_str, "0.0.0.0") != 0) {
- *return_ip = ip_list[i];
- SAFE_FREE(ip_list);
- return True;
- }
- }
- }
- SAFE_FREE(ip_list);
- return False;
-}
-
-/********************************************************
- Find the IP address of the master browser or DMB for a workgroup.
-*********************************************************/
-
-BOOL find_master_ip(TALLOC_CTX *mem_ctx, const char *group, struct ipv4_addr *master_ip)
-{
- struct ipv4_addr *ip_list = NULL;
- int count = 0;
-
- if (lp_disable_netbios()) {
- DEBUG(5,("find_master_ip(%s): netbios is disabled\n", group));
- return False;
- }
-
- if (internal_resolve_name(mem_ctx, group, 0x1D, &ip_list, &count)) {
- *master_ip = ip_list[0];
- SAFE_FREE(ip_list);
- return True;
- }
- if(internal_resolve_name(mem_ctx, group, 0x1B, &ip_list, &count)) {
- *master_ip = ip_list[0];
- SAFE_FREE(ip_list);
- return True;
- }
-
- SAFE_FREE(ip_list);
- return False;
-}
-
-/********************************************************
- Lookup a DC name given a Domain name and IP address.
-*********************************************************/
-
-BOOL lookup_dc_name(const char *srcname, const char *domain,
- struct ipv4_addr *dc_ip, char *ret_name)
-{
-#if !defined(I_HATE_WINDOWS_REPLY_CODE)
- fstring dc_name;
- BOOL ret;
-
- if (lp_disable_netbios()) {
- DEBUG(5,("lookup_dc_name(%s): netbios is disabled\n", domain));
- return False;
- }
-
- /*
- * Due to the fact win WinNT *sucks* we must do a node status
- * query here... JRA.
- */
-
- *dc_name = '\0';
-
- ret = name_status_find(domain, 0x1c, 0x20, *dc_ip, dc_name);
-
- if(ret && *dc_name) {
- fstrcpy(ret_name, dc_name);
- return True;
- }
-
- return False;
-
-#else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
-
-JRA - This code is broken with BDC rollover - we need to do a full
-NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all...
-
- int retries = 3;
- int retry_time = 2000;
- struct timeval tval;
- struct packet_struct p;
- struct dgram_packet *dgram = &p.packet.dgram;
- char *ptr,*p2;
- char tmp[4];
- int len;
- struct sockaddr_in sock_name;
- int sock_len = sizeof(sock_name);
- const char *mailslot = NET_LOGON_MAILSLOT;
- char *mailslot_name;
- char buffer[1024];
- char *bufp;
- int dgm_id = generate_trn_id();
- int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
-
- if(sock == -1)
- return False;
-
- /* Find out the transient UDP port we have been allocated. */
- if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
- DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
- strerror(errno)));
- close(sock);
- return False;
- }
-
- /*
- * Create the request data.
- */
-
- memset(buffer,'\0',sizeof(buffer));
- bufp = buffer;
- SSVAL(bufp,0,QUERYFORPDC);
- bufp += 2;
- fstrcpy(bufp,srcname);
- bufp += (strlen(bufp) + 1);
- slprintf(bufp, sizeof(fstring)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
- mailslot_name = bufp;
- bufp += (strlen(bufp) + 1);
- bufp = ALIGN2(bufp, buffer);
- bufp += push_ucs2(NULL, bufp, srcname, sizeof(buffer) - (bufp - buffer), STR_TERMINATE);
-
- SIVAL(bufp,0,1);
- SSVAL(bufp,4,0xFFFF);
- SSVAL(bufp,6,0xFFFF);
- bufp += 8;
- len = PTR_DIFF(bufp,buffer);
-
- memset((char *)&p,'\0',sizeof(p));
-
- /* DIRECT GROUP or UNIQUE datagram. */
- dgram->header.msg_type = 0x10;
- dgram->header.flags.node_type = M_NODE;
- dgram->header.flags.first = True;
- dgram->header.flags.more = False;
- dgram->header.dgm_id = dgm_id;
- dgram->header.source_ip = *iface_ip(*pdc_ip);
- dgram->header.source_port = ntohs(sock_name.sin_port);
- dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
- dgram->header.packet_offset = 0;
-
- make_nmb_name(&dgram->source_name,srcname,0);
- make_nmb_name(&dgram->dest_name,domain,0x1C);
-
- ptr = &dgram->data[0];
-
- /* Setup the smb part. */
- ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
- memcpy(tmp,ptr,4);
- set_message(ptr,17,17 + len,True);
- memcpy(ptr,tmp,4);
-
- CVAL(ptr,smb_com) = SMBtrans;
- SSVAL(ptr,smb_vwv1,len);
- SSVAL(ptr,smb_vwv11,len);
- SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
- SSVAL(ptr,smb_vwv13,3);
- SSVAL(ptr,smb_vwv14,1);
- SSVAL(ptr,smb_vwv15,1);
- SSVAL(ptr,smb_vwv16,2);
- p2 = smb_buf(ptr);
- pstrcpy(p2,mailslot);
- p2 = skip_string(p2,1);
-
- memcpy(p2,buffer,len);
- p2 += len;
-
- dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
-
- p.ip = *pdc_ip;
- p.port = DGRAM_PORT;
- p.fd = sock;
- p.timestamp = time(NULL);
- p.packet_type = DGRAM_PACKET;
-
- GetTimeOfDay(&tval);
-
- if (!send_packet(&p)) {
- DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
- close(sock);
- return False;
- }
-
- retries--;
-
- while (1) {
- struct timeval tval2;
- struct packet_struct *p_ret;
-
- GetTimeOfDay(&tval2);
- if (TvalDiff(&tval,&tval2) > retry_time) {
- if (!retries)
- break;
- if (!send_packet(&p)) {
- DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
- close(sock);
- return False;
- }
- GetTimeOfDay(&tval);
- retries--;
- }
-
- if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
- struct dgram_packet *dgram2 = &p_ret->packet.dgram;
- char *buf;
- char *buf2;
-
- buf = &dgram2->data[0];
- buf -= 4;
-
- if (CVAL(buf,smb_com) != SMBtrans) {
- DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (uint_t)
- CVAL(buf,smb_com), (uint_t)SMBtrans ));
- free_packet(p_ret);
- continue;
- }
-
- len = SVAL(buf,smb_vwv11);
- buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
-
- if (len <= 0) {
- DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
- free_packet(p_ret);
- continue;
- }
-
- DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
- nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
- sys_inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
-
- if(SVAL(buf2,0) != QUERYFORPDC_R) {
- DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
- (uint_t)SVAL(buf,0), (uint_t)QUERYFORPDC_R ));
- free_packet(p_ret);
- continue;
- }
-
- buf2 += 2;
- /* Note this is safe as it is a bounded strcpy. */
- fstrcpy(ret_name, buf2);
- ret_name[sizeof(fstring)-1] = '\0';
- close(sock);
- free_packet(p_ret);
- return True;
- }
- }
-
- close(sock);
- return False;
-#endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
-}
-
-/********************************************************
- Get the IP address list of the primary domain controller
- for a domain.
-*********************************************************/
-
-BOOL get_pdc_ip(TALLOC_CTX *mem_ctx, const char *domain, struct ipv4_addr *ip)
-{
- struct ipv4_addr *ip_list;
- int count;
- int i = 0;
-
- /* Look up #1B name */
-
- if (!internal_resolve_name(mem_ctx, domain, 0x1b, &ip_list, &count))
- return False;
-
- /* if we get more than 1 IP back we have to assume it is a
- multi-homed PDC and not a mess up */
-
- if ( count > 1 ) {
- DEBUG(6,("get_pdc_ip: PDC has %d IP addresses!\n", count));
-
- /* look for a local net */
- for ( i=0; i<count; i++ ) {
- if ( is_local_net( ip_list[i] ) )
- break;
- }
-
- /* if we hit then end then just grab the first
- one from the list */
-
- if ( i == count )
- i = 0;
- }
-
- *ip = ip_list[i];
-
- SAFE_FREE(ip_list);
-
- return True;
-}
-
diff --git a/source4/libcli/namequery_dc.c b/source4/libcli/namequery_dc.c
deleted file mode 100644
index 49aa42a744..0000000000
--- a/source4/libcli/namequery_dc.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- Winbind daemon connection manager
-
- Copyright (C) Tim Potter 2001
- Copyright (C) Andrew Bartlett 2002
-
- 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"
-
-
diff --git a/source4/libcli/nbt/libnbt.h b/source4/libcli/nbt/libnbt.h
index 3658f1dd77..a7788f791b 100644
--- a/source4/libcli/nbt/libnbt.h
+++ b/source4/libcli/nbt/libnbt.h
@@ -62,6 +62,12 @@ struct nbt_name_request {
const char *reply_addr;
int reply_port;
} *replies;
+
+ /* information on what to do on completion */
+ struct {
+ void (*fn)(struct nbt_name_request *);
+ void *private;
+ } async;
};
diff --git a/source4/libcli/nbt/namequery.c b/source4/libcli/nbt/namequery.c
index 23a63ede11..05d5e55491 100644
--- a/source4/libcli/nbt/namequery.c
+++ b/source4/libcli/nbt/namequery.c
@@ -209,69 +209,3 @@ NTSTATUS nbt_name_status(struct nbt_name_socket *nbtsock,
}
-/*
- some test functions - will be removed when nbt is hooked in everywhere
-*/
-void test_name_status(const char *name, const char *addr)
-{
- struct nbt_name_status io;
- NTSTATUS status;
- TALLOC_CTX *tmp_ctx = talloc_new(NULL);
- struct nbt_name_socket *nbtsock;
- int i;
-
- nbtsock = nbt_name_socket_init(tmp_ctx, NULL);
-
- io.in.name.name = name;
- io.in.name.scope = NULL;
- io.in.name.type = NBT_NAME_CLIENT;
- io.in.dest_addr = addr;
- io.in.timeout = 5;
-
- status = nbt_name_status(nbtsock, tmp_ctx, &io);
- if (!NT_STATUS_IS_OK(status)) {
- printf("status failed for %s - %s\n", name, nt_errstr(status));
- talloc_free(tmp_ctx);
- exit(1);
- return;
- }
-
- printf("Received %d names for %s\n", io.out.status.num_names, io.out.name.name);
- for (i=0;i<io.out.status.num_names;i++) {
- printf("\t%s#%02x 0x%04x\n",
- io.out.status.names[i].name,
- io.out.status.names[i].type,
- io.out.status.names[i].nb_flags);
- }
- talloc_free(tmp_ctx);
-}
-
-
-void test_name_query(const char *name)
-{
- struct nbt_name_query io;
- NTSTATUS status;
- TALLOC_CTX *tmp_ctx = talloc_new(NULL);
- struct nbt_name_socket *nbtsock;
-
- nbtsock = nbt_name_socket_init(tmp_ctx, NULL);
-
- io.in.name.name = name;
- io.in.name.scope = NULL;
- io.in.name.type = NBT_NAME_SERVER;
- io.in.dest_addr = "255.255.255.255";
- io.in.broadcast = True;
- io.in.wins_lookup = False;
- io.in.timeout = 5;
-
- status = nbt_name_query(nbtsock, tmp_ctx, &io);
- if (!NT_STATUS_IS_OK(status)) {
- printf("query failed for %s - %s\n", name, nt_errstr(status));
- } else {
- printf("response %s is at %s\n", io.out.name.name, io.out.reply_addr);
- test_name_status("*", io.out.reply_addr);
- }
-
- talloc_free(tmp_ctx);
-}
-
diff --git a/source4/libcli/nbt/nbtname.c b/source4/libcli/nbt/nbtname.c
index c2da1a0ab4..8c46379f0b 100644
--- a/source4/libcli/nbt/nbtname.c
+++ b/source4/libcli/nbt/nbtname.c
@@ -283,3 +283,57 @@ NTSTATUS ndr_push_nbt_name(struct ndr_push *ndr, int ndr_flags, struct nbt_name
return NT_STATUS_OK;
}
+
+
+/*
+ copy a nbt name structure
+*/
+NTSTATUS nbt_name_dup(TALLOC_CTX *mem_ctx, struct nbt_name *name, struct nbt_name *newname)
+{
+ *newname = *name;
+ newname->name = talloc_strdup(mem_ctx, newname->name);
+ NT_STATUS_HAVE_NO_MEMORY(newname->name);
+ newname->scope = talloc_strdup(mem_ctx, newname->scope);
+ if (name->scope) {
+ NT_STATUS_HAVE_NO_MEMORY(newname->scope);
+ }
+ return NT_STATUS_OK;
+}
+
+/*
+ push a nbt name into a blob
+*/
+NTSTATUS nbt_name_to_blob(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, struct nbt_name *name)
+{
+ return ndr_push_struct_blob(blob, mem_ctx, name,
+ (ndr_push_flags_fn_t)ndr_push_nbt_name);
+}
+
+/*
+ choose a name to use when calling a server in a NBT session request.
+ we use heuristics to see if the name we have been given is a IP
+ address, or a too-long name. If it is then use *SMBSERVER, or a
+ truncated name
+*/
+void nbt_choose_called_name(TALLOC_CTX *mem_ctx,
+ struct nbt_name *n, const char *name, int type)
+{
+ n->scope = NULL;
+ n->type = type;
+
+ if (is_ipaddress(name)) {
+ n->name = "*SMBSERVER";
+ return;
+ }
+ if (strlen(name) > 15) {
+ const char *p = strchr(name, '.');
+ if (p - name > 15) {
+ n->name = "*SMBSERVER";
+ return;
+ }
+ n->name = talloc_strndup(mem_ctx, name, PTR_DIFF(p, name));
+ return;
+ }
+
+ n->name = talloc_strdup(mem_ctx, name);
+}
diff --git a/source4/libcli/nbt/nbtsocket.c b/source4/libcli/nbt/nbtsocket.c
index 896ed68e98..6d5b450a31 100644
--- a/source4/libcli/nbt/nbtsocket.c
+++ b/source4/libcli/nbt/nbtsocket.c
@@ -29,6 +29,16 @@
#define NBT_MAX_REPLIES 1000
/*
+ destroy a nbt socket
+*/
+static int nbtsock_destructor(void *ptr)
+{
+ struct nbt_name_socket *nbtsock = talloc_get_type(ptr, struct nbt_name_socket);
+ event_remove_fd(nbtsock->event_ctx, nbtsock->fde);
+ return 0;
+}
+
+/*
destroy a pending request
*/
static int nbt_name_request_destructor(void *ptr)
@@ -111,6 +121,9 @@ failed:
nbt_name_request_destructor(req);
req->status = status;
req->state = NBT_REQUEST_ERROR;
+ if (req->async.fn) {
+ req->async.fn(req);
+ }
talloc_free(tmp_ctx);
return;
}
@@ -184,6 +197,9 @@ static void nbt_name_socket_recv(struct nbt_name_socket *nbtsock)
req->state = NBT_REQUEST_DONE;
req->status = NT_STATUS_NO_MEMORY;
talloc_free(tmp_ctx);
+ if (req->async.fn) {
+ req->async.fn(req);
+ }
return;
}
@@ -192,15 +208,18 @@ static void nbt_name_socket_recv(struct nbt_name_socket *nbtsock)
req->replies[req->num_replies].packet = talloc_steal(req, packet);
req->num_replies++;
+ talloc_free(tmp_ctx);
+
/* if we don't want multiple replies then we are done */
if (!req->allow_multiple_replies ||
req->num_replies == NBT_MAX_REPLIES) {
nbt_name_request_destructor(req);
req->state = NBT_REQUEST_DONE;
req->status = NT_STATUS_OK;
+ if (req->async.fn) {
+ req->async.fn(req);
+ }
}
-
- talloc_free(tmp_ctx);
}
/*
@@ -257,6 +276,8 @@ struct nbt_name_socket *nbt_name_socket_init(TALLOC_CTX *mem_ctx,
fde.private = nbtsock;
nbtsock->fde = event_add_fd(nbtsock->event_ctx, &fde);
+ talloc_set_destructor(nbtsock, nbtsock_destructor);
+
return nbtsock;
failed:
@@ -273,8 +294,16 @@ static void nbt_name_socket_timeout(struct event_context *ev, struct timed_event
struct nbt_name_request *req = talloc_get_type(te->private,
struct nbt_name_request);
nbt_name_request_destructor(req);
- req->state = NBT_REQUEST_TIMEOUT;
- req->status = NT_STATUS_IO_TIMEOUT;
+ if (req->num_replies == 0) {
+ req->state = NBT_REQUEST_TIMEOUT;
+ req->status = NT_STATUS_IO_TIMEOUT;
+ } else {
+ req->state = NBT_REQUEST_DONE;
+ req->status = NT_STATUS_OK;
+ }
+ if (req->async.fn) {
+ req->async.fn(req);
+ }
}
/*
@@ -300,14 +329,20 @@ struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock,
req->allow_multiple_replies = allow_multiple_replies;
req->state = NBT_REQUEST_SEND;
+ /* we select a random transaction id unless the user supplied one */
if (req->request->name_trn_id == 0) {
req->request->name_trn_id = random() % UINT16_MAX;
}
+ /* choose the next available transaction id >= the one asked for.
+ The strange 2nd call is to try to make the ids less guessable
+ and less likely to collide. It's not possible to make NBT secure
+ to ID guessing, but this at least makes accidential collisions
+ less likely */
id = idr_get_new_above(req->nbtsock->idr, req,
req->request->name_trn_id, UINT16_MAX);
if (id == -1) {
- id = idr_get_new_above(req->nbtsock->idr, req, 1+(random()%10000),
+ id = idr_get_new_above(req->nbtsock->idr, req, 1+(random()%(UINT16_MAX/2)),
UINT16_MAX);
}
if (id == -1) goto failed;
@@ -341,6 +376,9 @@ NTSTATUS nbt_name_request_recv(struct nbt_name_request *req)
if (event_loop_once(req->nbtsock->event_ctx) != 0) {
req->state = NBT_REQUEST_ERROR;
req->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
+ if (req->async.fn) {
+ req->async.fn(req);
+ }
}
}
return req->status;
diff --git a/source4/libcli/nmblib.c b/source4/libcli/nmblib.c
deleted file mode 100644
index 0a3f72ba74..0000000000
--- a/source4/libcli/nmblib.c
+++ /dev/null
@@ -1,1316 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios library 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"
-#include "system/network.h"
-#include "system/time.h"
-#include "system/iconv.h"
-
-static const struct opcode_names {
- const char *nmb_opcode_name;
- int opcode;
-} nmb_header_opcode_names[] = {
- {"Query", 0 },
- {"Registration", 5 },
- {"Release", 6 },
- {"WACK", 7 },
- {"Refresh", 8 },
- {"Refresh(altcode)", 9 },
- {"Multi-homed Registration", 15 },
- {0, -1 }
-};
-
-/****************************************************************************
- * Lookup a nmb opcode name.
- ****************************************************************************/
-static const char *lookup_opcode_name( int opcode )
-{
- const struct opcode_names *op_namep;
- int i;
-
- for(i = 0; nmb_header_opcode_names[i].nmb_opcode_name != 0; i++) {
- op_namep = &nmb_header_opcode_names[i];
- if(opcode == op_namep->opcode)
- return op_namep->nmb_opcode_name;
- }
- return "<unknown opcode>";
-}
-
-/****************************************************************************
- print out a res_rec structure
- ****************************************************************************/
-static void debug_nmb_res_rec(struct res_rec *res, const char *hdr)
-{
- int i, j;
-
- DEBUGADD( 4, ( " %s: nmb_name=%s rr_type=%d rr_class=%d ttl=%d\n",
- hdr,
- nmb_namestr(&res->rr_name),
- res->rr_type,
- res->rr_class,
- res->ttl ) );
-
- if( res->rdlength == 0 || res->rdata == NULL )
- return;
-
- for (i = 0; i < res->rdlength; i+= 16)
- {
- DEBUGADD(4, (" %s %3x char ", hdr, i));
-
- for (j = 0; j < 16; j++)
- {
- uint8_t x = res->rdata[i+j];
- if (x < 32 || x > 127) x = '.';
-
- if (i+j >= res->rdlength) break;
- DEBUGADD(4, ("%c", x));
- }
-
- DEBUGADD(4, (" hex "));
-
- for (j = 0; j < 16; j++)
- {
- if (i+j >= res->rdlength) break;
- DEBUGADD(4, ("%02X", (uint8_t)res->rdata[i+j]));
- }
-
- DEBUGADD(4, ("\n"));
- }
-}
-
-/****************************************************************************
- process a nmb packet
- ****************************************************************************/
-void debug_nmb_packet(struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
-
- if (DEBUGLVL(4)) {
- DEBUG(4, ("nmb packet from %s(%d) header: id=%d opcode=%s(%d) response=%s\n",
- sys_inet_ntoa(p->ip), p->port,
- nmb->header.name_trn_id,
- lookup_opcode_name(nmb->header.opcode),
- nmb->header.opcode,
- BOOLSTR(nmb->header.response)));
- DEBUG(4, (" header: flags: bcast=%s rec_avail=%s rec_des=%s trunc=%s auth=%s\n",
- BOOLSTR(nmb->header.nm_flags.bcast),
- BOOLSTR(nmb->header.nm_flags.recursion_available),
- BOOLSTR(nmb->header.nm_flags.recursion_desired),
- BOOLSTR(nmb->header.nm_flags.trunc),
- BOOLSTR(nmb->header.nm_flags.authoritative)));
- DEBUG(4, (" header: rcode=%d qdcount=%d ancount=%d nscount=%d arcount=%d\n",
- nmb->header.rcode,
- nmb->header.qdcount,
- nmb->header.ancount,
- nmb->header.nscount,
- nmb->header.arcount));
- }
-
- if (nmb->header.qdcount)
- {
- DEBUGADD( 4, ( " question: q_name=%s q_type=%d q_class=%d\n",
- nmb_namestr(&nmb->question.question_name),
- nmb->question.question_type,
- nmb->question.question_class) );
- }
-
- if (nmb->answers && nmb->header.ancount)
- {
- debug_nmb_res_rec(nmb->answers,"answers");
- }
- if (nmb->nsrecs && nmb->header.nscount)
- {
- debug_nmb_res_rec(nmb->nsrecs,"nsrecs");
- }
- if (nmb->additional && nmb->header.arcount)
- {
- debug_nmb_res_rec(nmb->additional,"additional");
- }
-}
-
-/*******************************************************************
- handle "compressed" name pointers
- ******************************************************************/
-static BOOL handle_name_ptrs(uint8_t *ubuf,int *offset,int length,
- BOOL *got_pointer,int *ret)
-{
- int loop_count=0;
-
- while ((ubuf[*offset] & 0xC0) == 0xC0) {
- if (!*got_pointer) (*ret) += 2;
- (*got_pointer)=True;
- (*offset) = ((ubuf[*offset] & ~0xC0)<<8) | ubuf[(*offset)+1];
- if (loop_count++ == 10 || (*offset) < 0 || (*offset)>(length-2)) {
- return(False);
- }
- }
- return(True);
-}
-
-/*******************************************************************
- parse a nmb name from "compressed" format to something readable
- return the space taken by the name, or 0 if the name is invalid
- ******************************************************************/
-static int parse_nmb_name(char *inbuf,int ofs,int length, struct nmb_name *name)
-{
- int m,n=0;
- uint8_t *ubuf = (uint8_t *)inbuf;
- int ret = 0;
- BOOL got_pointer=False;
- int loop_count=0;
- int offset = ofs;
-
- if (length - offset < 2)
- return(0);
-
- /* handle initial name pointers */
- if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret))
- return(0);
-
- m = ubuf[offset];
-
- if (!m)
- return(0);
- if ((m & 0xC0) || offset+m+2 > length)
- return(0);
-
- memset((char *)name,'\0',sizeof(*name));
-
- /* the "compressed" part */
- if (!got_pointer)
- ret += m + 2;
- offset++;
- while (m > 0) {
- uint8_t c1,c2;
- c1 = ubuf[offset++]-'A';
- c2 = ubuf[offset++]-'A';
- if ((c1 & 0xF0) || (c2 & 0xF0) || (n > sizeof(name->name)-1))
- return(0);
- name->name[n++] = (c1<<4) | c2;
- m -= 2;
- }
- name->name[n] = 0;
-
- if (n==16) {
- /* parse out the name type,
- its always in the 16th byte of the name */
- name->name_type = ((uint8_t)name->name[15]) & 0xff;
-
- /* remove trailing spaces */
- name->name[15] = 0;
- n = 14;
- while (n && name->name[n]==' ')
- name->name[n--] = 0;
- }
-
- /* now the domain parts (if any) */
- n = 0;
- while (ubuf[offset]) {
- /* we can have pointers within the domain part as well */
- if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret))
- return(0);
-
- m = ubuf[offset];
- /*
- * Don't allow null domain parts.
- */
- if (!m)
- return(0);
- if (!got_pointer)
- ret += m+1;
- if (n)
- name->scope[n++] = '.';
- if (m+2+offset>length || n+m+1>sizeof(name->scope))
- return(0);
- offset++;
- while (m--)
- name->scope[n++] = (char)ubuf[offset++];
-
- /*
- * Watch for malicious loops.
- */
- if (loop_count++ == 10)
- return 0;
- }
- name->scope[n++] = 0;
-
- return(ret);
-}
-
-
-/*******************************************************************
- put a compressed nmb name into a buffer. return the length of the
- compressed name
-
- compressed names are really weird. The "compression" doubles the
- size. The idea is that it also means that compressed names conform
- to the doman name system. See RFC1002.
- ******************************************************************/
-static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
-{
- int ret,m;
- fstring buf1;
- char *p;
-
- if (strcmp(name->name,"*") == 0) {
- /* special case for wildcard name */
- memset(buf1,'\0',20);
- buf1[0] = '*';
- buf1[15] = name->name_type;
- } else {
- slprintf(buf1, sizeof(buf1) - 1,"%-15.15s%c",name->name,name->name_type);
- }
-
- buf[offset] = 0x20;
-
- ret = 34;
-
- for (m=0;m<16;m++) {
- buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF);
- buf[offset+2+2*m] = 'A' + (buf1[m]&0xF);
- }
- offset += 33;
-
- buf[offset] = 0;
-
- if (name->scope[0]) {
- /* XXXX this scope handling needs testing */
- ret += strlen(name->scope) + 1;
- pstrcpy(&buf[offset+1],name->scope);
-
- p = &buf[offset+1];
- while ((p = strchr_m(p,'.'))) {
- buf[offset] = PTR_DIFF(p,&buf[offset+1]);
- offset += (buf[offset] + 1);
- p = &buf[offset+1];
- }
- buf[offset] = strlen(&buf[offset+1]);
- }
-
- return(ret);
-}
-
-/*******************************************************************
- useful for debugging messages
- ******************************************************************/
-char *nmb_namestr(struct nmb_name *n)
-{
- static int i=0;
- static fstring ret[4];
- char *p = ret[i];
-
- if (!n->scope[0])
- slprintf(p,sizeof(fstring)-1, "%s<%02x>",n->name,n->name_type);
- else
- slprintf(p,sizeof(fstring)-1, "%s<%02x>.%s",n->name,n->name_type,n->scope);
-
- i = (i+1)%4;
- return(p);
-}
-
-/*******************************************************************
- allocate and parse some resource records
- ******************************************************************/
-static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length,
- struct res_rec **recs, int count)
-{
- int i;
- *recs = malloc_array_p(struct res_rec, count);
- if (!*recs) return(False);
-
- memset((char *)*recs,'\0',sizeof(**recs)*count);
-
- for (i=0;i<count;i++) {
- int l = parse_nmb_name(inbuf,*offset,length,&(*recs)[i].rr_name);
- (*offset) += l;
- if (!l || (*offset)+10 > length) {
- SAFE_FREE(*recs);
- return(False);
- }
- (*recs)[i].rr_type = RSVAL(inbuf,(*offset));
- (*recs)[i].rr_class = RSVAL(inbuf,(*offset)+2);
- (*recs)[i].ttl = RIVAL(inbuf,(*offset)+4);
- (*recs)[i].rdlength = RSVAL(inbuf,(*offset)+8);
- (*offset) += 10;
- if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) ||
- (*offset)+(*recs)[i].rdlength > length) {
- SAFE_FREE(*recs);
- return(False);
- }
- memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength);
- (*offset) += (*recs)[i].rdlength;
- }
- return(True);
-}
-
-/*******************************************************************
- put a resource record into a packet
- ******************************************************************/
-static int put_res_rec(char *buf,int offset,struct res_rec *recs,int count)
-{
- int ret=0;
- int i;
-
- for (i=0;i<count;i++) {
- int l = put_nmb_name(buf,offset,&recs[i].rr_name);
- offset += l;
- ret += l;
- RSSVAL(buf,offset,recs[i].rr_type);
- RSSVAL(buf,offset+2,recs[i].rr_class);
- RSIVAL(buf,offset+4,recs[i].ttl);
- RSSVAL(buf,offset+8,recs[i].rdlength);
- memcpy(buf+offset+10,recs[i].rdata,recs[i].rdlength);
- offset += 10+recs[i].rdlength;
- ret += 10+recs[i].rdlength;
- }
-
- return(ret);
-}
-
-/*******************************************************************
- put a compressed name pointer record into a packet
- ******************************************************************/
-static int put_compressed_name_ptr(uint8_t *buf,int offset,struct res_rec *rec,int ptr_offset)
-{
- int ret=0;
- buf[offset] = (0xC0 | ((ptr_offset >> 8) & 0xFF));
- buf[offset+1] = (ptr_offset & 0xFF);
- offset += 2;
- ret += 2;
- RSSVAL(buf,offset,rec->rr_type);
- RSSVAL(buf,offset+2,rec->rr_class);
- RSIVAL(buf,offset+4,rec->ttl);
- RSSVAL(buf,offset+8,rec->rdlength);
- memcpy(buf+offset+10,rec->rdata,rec->rdlength);
- offset += 10+rec->rdlength;
- ret += 10+rec->rdlength;
-
- return(ret);
-}
-
-/*******************************************************************
- parse a dgram packet. Return False if the packet can't be parsed
- or is invalid for some reason, True otherwise
-
- this is documented in section 4.4.1 of RFC1002
- ******************************************************************/
-static BOOL parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
-{
- int offset;
- int flags;
-
- memset((char *)dgram,'\0',sizeof(*dgram));
-
- if (length < 14) return(False);
-
- dgram->header.msg_type = CVAL(inbuf,0);
- flags = CVAL(inbuf,1);
- dgram->header.flags.node_type = (enum node_type)((flags>>2)&3);
- if (flags & 1) dgram->header.flags.more = True;
- if (flags & 2) dgram->header.flags.first = True;
- dgram->header.dgm_id = RSVAL(inbuf,2);
- putip((char *)&dgram->header.source_ip,inbuf+4);
- dgram->header.source_port = RSVAL(inbuf,8);
- dgram->header.dgm_length = RSVAL(inbuf,10);
- dgram->header.packet_offset = RSVAL(inbuf,12);
-
- offset = 14;
-
- if (dgram->header.msg_type == 0x10 ||
- dgram->header.msg_type == 0x11 ||
- dgram->header.msg_type == 0x12) {
- offset += parse_nmb_name(inbuf,offset,length,&dgram->source_name);
- offset += parse_nmb_name(inbuf,offset,length,&dgram->dest_name);
- }
-
- if (offset >= length || (length-offset > sizeof(dgram->data)))
- return(False);
-
- dgram->datasize = length-offset;
- memcpy(dgram->data,inbuf+offset,dgram->datasize);
-
- return(True);
-}
-
-
-/*******************************************************************
- parse a nmb packet. Return False if the packet can't be parsed
- or is invalid for some reason, True otherwise
- ******************************************************************/
-static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
-{
- int nm_flags,offset;
-
- memset((char *)nmb,'\0',sizeof(*nmb));
-
- if (length < 12) return(False);
-
- /* parse the header */
- nmb->header.name_trn_id = RSVAL(inbuf,0);
-
- DEBUG(10,("parse_nmb: packet id = %d\n", nmb->header.name_trn_id));
-
- nmb->header.opcode = (CVAL(inbuf,2) >> 3) & 0xF;
- nmb->header.response = ((CVAL(inbuf,2)>>7)&1)?True:False;
- nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
- nmb->header.nm_flags.bcast = (nm_flags&1)?True:False;
- nmb->header.nm_flags.recursion_available = (nm_flags&8)?True:False;
- nmb->header.nm_flags.recursion_desired = (nm_flags&0x10)?True:False;
- nmb->header.nm_flags.trunc = (nm_flags&0x20)?True:False;
- nmb->header.nm_flags.authoritative = (nm_flags&0x40)?True:False;
- nmb->header.rcode = CVAL(inbuf,3) & 0xF;
- nmb->header.qdcount = RSVAL(inbuf,4);
- nmb->header.ancount = RSVAL(inbuf,6);
- nmb->header.nscount = RSVAL(inbuf,8);
- nmb->header.arcount = RSVAL(inbuf,10);
-
- if (nmb->header.qdcount) {
- offset = parse_nmb_name(inbuf,12,length,&nmb->question.question_name);
- if (!offset) return(False);
-
- if (length - (12+offset) < 4) return(False);
- nmb->question.question_type = RSVAL(inbuf,12+offset);
- nmb->question.question_class = RSVAL(inbuf,12+offset+2);
-
- offset += 12+4;
- } else {
- offset = 12;
- }
-
- /* and any resource records */
- if (nmb->header.ancount &&
- !parse_alloc_res_rec(inbuf,&offset,length,&nmb->answers,
- nmb->header.ancount))
- return(False);
-
- if (nmb->header.nscount &&
- !parse_alloc_res_rec(inbuf,&offset,length,&nmb->nsrecs,
- nmb->header.nscount))
- return(False);
-
- if (nmb->header.arcount &&
- !parse_alloc_res_rec(inbuf,&offset,length,&nmb->additional,
- nmb->header.arcount))
- return(False);
-
- return(True);
-}
-
-/*******************************************************************
- 'Copy constructor' for an nmb packet
- ******************************************************************/
-static struct packet_struct *copy_nmb_packet(struct packet_struct *packet)
-{
- struct nmb_packet *nmb;
- struct nmb_packet *copy_nmb;
- struct packet_struct *pkt_copy;
-
- if(( pkt_copy = malloc_p(struct packet_struct)) == NULL)
- {
- DEBUG(0,("copy_nmb_packet: malloc fail.\n"));
- return NULL;
- }
-
- /* Structure copy of entire thing. */
-
- *pkt_copy = *packet;
-
- /* Ensure this copy is not locked. */
- pkt_copy->locked = False;
-
- /* Ensure this copy has no resource records. */
- nmb = &packet->packet.nmb;
- copy_nmb = &pkt_copy->packet.nmb;
-
- copy_nmb->answers = NULL;
- copy_nmb->nsrecs = NULL;
- copy_nmb->additional = NULL;
-
- /* Now copy any resource records. */
-
- if (nmb->answers)
- {
- if((copy_nmb->answers = malloc_array_p(struct res_rec, nmb->header.ancount)) == NULL)
- goto free_and_exit;
- memcpy((char *)copy_nmb->answers, (char *)nmb->answers,
- nmb->header.ancount * sizeof(struct res_rec));
- }
- if (nmb->nsrecs)
- {
- if((copy_nmb->nsrecs = malloc_array_p(struct res_rec, nmb->header.nscount)) == NULL)
- goto free_and_exit;
- memcpy((char *)copy_nmb->nsrecs, (char *)nmb->nsrecs,
- nmb->header.nscount * sizeof(struct res_rec));
- }
- if (nmb->additional)
- {
- if((copy_nmb->additional = malloc_array_p(struct res_rec, nmb->header.arcount)) == NULL)
- goto free_and_exit;
- memcpy((char *)copy_nmb->additional, (char *)nmb->additional,
- nmb->header.arcount * sizeof(struct res_rec));
- }
-
- return pkt_copy;
-
-free_and_exit:
-
- SAFE_FREE(copy_nmb->answers);
- SAFE_FREE(copy_nmb->nsrecs);
- SAFE_FREE(copy_nmb->additional);
- SAFE_FREE(pkt_copy);
-
- DEBUG(0,("copy_nmb_packet: malloc fail in resource records.\n"));
- return NULL;
-}
-
-/*******************************************************************
- 'Copy constructor' for a dgram packet
- ******************************************************************/
-static struct packet_struct *copy_dgram_packet(struct packet_struct *packet)
-{
- struct packet_struct *pkt_copy;
-
- if(( pkt_copy = malloc_p(struct packet_struct)) == NULL)
- {
- DEBUG(0,("copy_dgram_packet: malloc fail.\n"));
- return NULL;
- }
-
- /* Structure copy of entire thing. */
-
- *pkt_copy = *packet;
-
- /* Ensure this copy is not locked. */
- pkt_copy->locked = False;
-
- /* There are no additional pointers in a dgram packet,
- we are finished. */
- return pkt_copy;
-}
-
-/*******************************************************************
- 'Copy constructor' for a generic packet
- ******************************************************************/
-struct packet_struct *copy_packet(struct packet_struct *packet)
-{
- if(packet->packet_type == NMB_PACKET)
- return copy_nmb_packet(packet);
- else if (packet->packet_type == DGRAM_PACKET)
- return copy_dgram_packet(packet);
- return NULL;
-}
-
-/*******************************************************************
- free up any resources associated with an nmb packet
- ******************************************************************/
-static void free_nmb_packet(struct nmb_packet *nmb)
-{
- SAFE_FREE(nmb->answers);
- SAFE_FREE(nmb->nsrecs);
- SAFE_FREE(nmb->additional);
-}
-
-/*******************************************************************
- free up any resources associated with a dgram packet
- ******************************************************************/
-static void free_dgram_packet(struct dgram_packet *nmb)
-{
- /* We have nothing to do for a dgram packet. */
-}
-
-/*******************************************************************
- free up any resources associated with a packet
- ******************************************************************/
-void free_packet(struct packet_struct *packet)
-{
- if (packet->locked)
- return;
- if (packet->packet_type == NMB_PACKET)
- free_nmb_packet(&packet->packet.nmb);
- else if (packet->packet_type == DGRAM_PACKET)
- free_dgram_packet(&packet->packet.dgram);
- ZERO_STRUCTPN(packet);
- SAFE_FREE(packet);
-}
-
-/*******************************************************************
-parse a packet buffer into a packet structure
- ******************************************************************/
-struct packet_struct *parse_packet(char *buf,int length,
- enum packet_type packet_type)
-{
- struct packet_struct *p;
- BOOL ok=False;
-
- p = malloc_p(struct packet_struct);
- if (!p) return(NULL);
-
- p->next = NULL;
- p->prev = NULL;
- p->locked = False;
- p->timestamp = time(NULL);
- p->packet_type = packet_type;
-
- switch (packet_type) {
- case NMB_PACKET:
- ok = parse_nmb(buf,length,&p->packet.nmb);
- break;
-
- case DGRAM_PACKET:
- ok = parse_dgram(buf,length,&p->packet.dgram);
- break;
- }
-
- if (!ok) {
- free_packet(p);
- return NULL;
- }
-
- return p;
-}
-
-/*******************************************************************
- read a packet from a socket and parse it, returning a packet ready
- to be used or put on the queue. This assumes a UDP socket
- ******************************************************************/
-struct packet_struct *read_packet(int fd,enum packet_type packet_type)
-{
- struct packet_struct *packet;
- char buf[MAX_DGRAM_SIZE];
- int length;
- struct ipv4_addr addr;
- int port;
-
- length = read_udp_socket(fd, buf, sizeof(buf), &addr, &port);
- if (length < MIN_DGRAM_SIZE) return(NULL);
-
- packet = parse_packet(buf, length, packet_type);
- if (!packet) return NULL;
-
- packet->fd = fd;
- packet->ip = addr;
- packet->port = port;
-
- DEBUG(5,("Received a packet of len %d from (%s) port %d\n",
- length, sys_inet_ntoa(packet->ip), packet->port));
-
- return packet;
-}
-
-
-/*******************************************************************
- send a udp packet on a already open socket
- ******************************************************************/
-static BOOL send_udp(int fd,char *buf,int len,struct ipv4_addr ip,int port)
-{
- BOOL ret = False;
- int i;
- struct sockaddr_in sock_out;
-
- /* set the address and port */
- memset((char *)&sock_out,'\0',sizeof(sock_out));
- putip((char *)&sock_out.sin_addr,(char *)&ip);
- sock_out.sin_port = htons( port );
- sock_out.sin_family = AF_INET;
-
- DEBUG( 5, ( "Sending a packet of len %d to (%s) on port %d\n",
- len, sys_inet_ntoa(ip), port ) );
-
- /*
- * Patch to fix asynch error notifications from Linux kernel.
- */
-
- for (i = 0; i < 5; i++) {
- ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out, sizeof(sock_out)) >= 0);
- if (ret || errno != ECONNREFUSED)
- break;
- }
-
- if (!ret)
- DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",
- sys_inet_ntoa(ip),port,strerror(errno)));
-
- return(ret);
-}
-
-/*******************************************************************
- build a dgram packet ready for sending
-
- XXXX This currently doesn't handle packets too big for one
- datagram. It should split them and use the packet_offset, more and
- first flags to handle the fragmentation. Yuck.
-
- [...but it isn't clear that we would ever need to send a
- a fragmented NBT Datagram. The IP layer does its own
- fragmentation to ensure that messages can fit into the path
- MTU. It *is* important to be able to receive and rebuild
- fragmented NBT datagrams, just in case someone out there
- really has implemented this 'feature'. crh -)------ ]
-
- ******************************************************************/
-static int build_dgram(char *buf,struct packet_struct *p)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- uint8_t *ubuf = (uint8_t *)buf;
- int offset=0;
-
- /* put in the header */
- ubuf[0] = dgram->header.msg_type;
- ubuf[1] = (((int)dgram->header.flags.node_type)<<2);
- if (dgram->header.flags.more) ubuf[1] |= 1;
- if (dgram->header.flags.first) ubuf[1] |= 2;
- RSSVAL(ubuf,2,dgram->header.dgm_id);
- putip(ubuf+4,(char *)&dgram->header.source_ip);
- RSSVAL(ubuf,8,dgram->header.source_port);
- RSSVAL(ubuf,12,dgram->header.packet_offset);
-
- offset = 14;
-
- if (dgram->header.msg_type == 0x10 ||
- dgram->header.msg_type == 0x11 ||
- dgram->header.msg_type == 0x12) {
- offset += put_nmb_name((char *)ubuf,offset,&dgram->source_name);
- offset += put_nmb_name((char *)ubuf,offset,&dgram->dest_name);
- }
-
- memcpy(ubuf+offset,dgram->data,dgram->datasize);
- offset += dgram->datasize;
-
- /* automatically set the dgm_length
- * NOTE: RFC1002 says the dgm_length does *not*
- * include the fourteen-byte header. crh
- */
- dgram->header.dgm_length = (offset - 14);
- RSSVAL(ubuf,10,dgram->header.dgm_length);
-
- return(offset);
-}
-
-/*******************************************************************
- Build a nmb name
-*******************************************************************/
-
-void make_nmb_name( struct nmb_name *n, const char *name, int type)
-{
- memset( (char *)n, '\0', sizeof(struct nmb_name) );
- push_ascii(n->name, name, 16, STR_TERMINATE|STR_UPPER);
- n->name_type = (uint_t)type & 0xFF;
- StrnCpy( n->scope, lp_netbios_scope(), 63 );
- strupper( n->scope );
-}
-
-/*******************************************************************
- Compare two nmb names
- ******************************************************************/
-
-BOOL nmb_name_equal(struct nmb_name *n1, struct nmb_name *n2)
-{
- return ((n1->name_type == n2->name_type) &&
- strequal(n1->name ,n2->name ) &&
- strequal(n1->scope,n2->scope));
-}
-
-/*******************************************************************
- build a nmb packet ready for sending
-
- XXXX this currently relies on not being passed something that expands
- to a packet too big for the buffer. Eventually this should be
- changed to set the trunc bit so the receiver can request the rest
- via tcp (when that becomes supported)
- ******************************************************************/
-static int build_nmb(char *buf,struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- uint8_t *ubuf = (uint8_t *)buf;
- int offset=0;
-
- /* put in the header */
- RSSVAL(ubuf,offset,nmb->header.name_trn_id);
- ubuf[offset+2] = (nmb->header.opcode & 0xF) << 3;
- if (nmb->header.response) ubuf[offset+2] |= (1<<7);
- if (nmb->header.nm_flags.authoritative &&
- nmb->header.response) ubuf[offset+2] |= 0x4;
- if (nmb->header.nm_flags.trunc) ubuf[offset+2] |= 0x2;
- if (nmb->header.nm_flags.recursion_desired) ubuf[offset+2] |= 0x1;
- if (nmb->header.nm_flags.recursion_available &&
- nmb->header.response) ubuf[offset+3] |= 0x80;
- if (nmb->header.nm_flags.bcast) ubuf[offset+3] |= 0x10;
- ubuf[offset+3] |= (nmb->header.rcode & 0xF);
-
- RSSVAL(ubuf,offset+4,nmb->header.qdcount);
- RSSVAL(ubuf,offset+6,nmb->header.ancount);
- RSSVAL(ubuf,offset+8,nmb->header.nscount);
- RSSVAL(ubuf,offset+10,nmb->header.arcount);
-
- offset += 12;
- if (nmb->header.qdcount) {
- /* XXXX this doesn't handle a qdcount of > 1 */
- offset += put_nmb_name((char *)ubuf,offset,&nmb->question.question_name);
- RSSVAL(ubuf,offset,nmb->question.question_type);
- RSSVAL(ubuf,offset+2,nmb->question.question_class);
- offset += 4;
- }
-
- if (nmb->header.ancount)
- offset += put_res_rec((char *)ubuf,offset,nmb->answers,
- nmb->header.ancount);
-
- if (nmb->header.nscount)
- offset += put_res_rec((char *)ubuf,offset,nmb->nsrecs,
- nmb->header.nscount);
-
- /*
- * The spec says we must put compressed name pointers
- * in the following outgoing packets :
- * NAME_REGISTRATION_REQUEST, NAME_REFRESH_REQUEST,
- * NAME_RELEASE_REQUEST.
- */
-
- if((nmb->header.response == False) &&
- ((nmb->header.opcode == NMB_NAME_REG_OPCODE) ||
- (nmb->header.opcode == NMB_NAME_RELEASE_OPCODE) ||
- (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_8) ||
- (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_9) ||
- (nmb->header.opcode == NMB_NAME_MULTIHOMED_REG_OPCODE)) &&
- (nmb->header.arcount == 1)) {
-
- offset += put_compressed_name_ptr(ubuf,offset,nmb->additional,12);
-
- } else if (nmb->header.arcount) {
- offset += put_res_rec((char *)ubuf,offset,nmb->additional,
- nmb->header.arcount);
- }
- return(offset);
-}
-
-
-/*******************************************************************
-linearise a packet
- ******************************************************************/
-int build_packet(char *buf, struct packet_struct *p)
-{
- int len = 0;
-
- switch (p->packet_type) {
- case NMB_PACKET:
- len = build_nmb(buf,p);
- break;
-
- case DGRAM_PACKET:
- len = build_dgram(buf,p);
- break;
- }
-
- return len;
-}
-
-/*******************************************************************
- send a packet_struct
- ******************************************************************/
-BOOL send_packet(struct packet_struct *p)
-{
- char buf[1024];
- int len=0;
-
- memset(buf,'\0',sizeof(buf));
-
- len = build_packet(buf, p);
-
- if (!len) return(False);
-
- return(send_udp(p->fd,buf,len,p->ip,p->port));
-}
-
-/****************************************************************************
- receive a packet with timeout on a open UDP filedescriptor
- The timeout is in milliseconds
- ***************************************************************************/
-struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
-{
- fd_set fds;
- struct timeval timeout;
- int ret;
-
- FD_ZERO(&fds);
- FD_SET(fd,&fds);
- timeout.tv_sec = t/1000;
- timeout.tv_usec = 1000*(t%1000);
-
- if ((ret = sys_select_intr(fd+1,&fds,NULL,NULL,&timeout)) == -1) {
- /* errno should be EBADF or EINVAL. */
- DEBUG(0,("select returned -1, errno = %s (%d)\n", strerror(errno), errno));
- return NULL;
- }
-
- if (ret == 0) /* timeout */
- return NULL;
-
- if (FD_ISSET(fd,&fds))
- return(read_packet(fd,type));
-
- return(NULL);
-}
-
-
-/****************************************************************************
- receive a UDP/137 packet either via UDP or from the unexpected packet
- queue. The packet must be a reply packet and have the specified trn_id
- The timeout is in milliseconds
- ***************************************************************************/
-struct packet_struct *receive_nmb_packet(int fd, int t, int trn_id)
-{
- struct packet_struct *p;
-
- p = receive_packet(fd, NMB_PACKET, t);
-
- if (p && p->packet.nmb.header.response &&
- p->packet.nmb.header.name_trn_id == trn_id) {
- return p;
- }
- if (p) free_packet(p);
-
- /* try the unexpected packet queue */
- return receive_unexpected(NMB_PACKET, trn_id, NULL);
-}
-
-/****************************************************************************
- receive a UDP/138 packet either via UDP or from the unexpected packet
- queue. The packet must be a reply packet and have the specified mailslot name
- The timeout is in milliseconds
- ***************************************************************************/
-struct packet_struct *receive_dgram_packet(int fd, int t, const char *mailslot_name)
-{
- struct packet_struct *p;
-
- p = receive_packet(fd, DGRAM_PACKET, t);
-
- if (p && match_mailslot_name(p, mailslot_name)) {
- return p;
- }
- if (p) free_packet(p);
-
- /* try the unexpected packet queue */
- return receive_unexpected(DGRAM_PACKET, 0, mailslot_name);
-}
-
-
-/****************************************************************************
- see if a datagram has the right mailslot name
-***************************************************************************/
-BOOL match_mailslot_name(struct packet_struct *p, const char *mailslot_name)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- char *buf;
-
- buf = &dgram->data[0];
- buf -= 4;
-
- buf = smb_buf(buf);
-
- if (memcmp(buf, mailslot_name, strlen(mailslot_name)+1) == 0) {
- return True;
- }
-
- return False;
-}
-
-
-/****************************************************************************
-return the number of bits that match between two 4 character buffers
- ***************************************************************************/
-int matching_quad_bits(uint8_t *p1, uint8_t *p2)
-{
- int i, j, ret = 0;
- for (i=0; i<4; i++) {
- if (p1[i] != p2[i]) break;
- ret += 8;
- }
-
- if (i==4) return ret;
-
- for (j=0; j<8; j++) {
- if ((p1[i] & (1<<(7-j))) != (p2[i] & (1<<(7-j)))) break;
- ret++;
- }
-
- return ret;
-}
-
-
-static uint8_t sort_ip[4];
-
-/****************************************************************************
-compare two query reply records
- ***************************************************************************/
-static int name_query_comp(uint8_t *p1, uint8_t *p2)
-{
- return matching_quad_bits(p2+2, sort_ip) - matching_quad_bits(p1+2, sort_ip);
-}
-
-/****************************************************************************
-sort a set of 6 byte name query response records so that the IPs that
-have the most leading bits in common with the specified address come first
- ***************************************************************************/
-void sort_query_replies(char *data, int n, struct ipv4_addr ip)
-{
- if (n <= 1) return;
-
- putip(sort_ip, (char *)&ip);
-
- qsort(data, n, 6, QSORT_CAST name_query_comp);
-}
-
-
-#define TRUNCATE_NETBIOS_NAME 1
-
-/*******************************************************************
- convert, possibly using a stupid microsoft-ism which has destroyed
- the transport independence of netbios (for CIFS vendors that usually
- use the Win95-type methods, not for NT to NT communication, which uses
- DCE/RPC and therefore full-length unicode strings...) a dns name into
- a netbios name.
-
- the netbios name (NOT necessarily null-terminated) is truncated to 15
- characters.
-
- ******************************************************************/
-char *dns_to_netbios_name(char *dns_name)
-{
- static char netbios_name[16];
- int i;
- StrnCpy(netbios_name, dns_name, 15);
- netbios_name[15] = 0;
-
-#ifdef TRUNCATE_NETBIOS_NAME
- /* ok. this is because of a stupid microsoft-ism. if the called host
- name contains a '.', microsoft clients expect you to truncate the
- netbios name up to and including the '.' this even applies, by
- mistake, to workgroup (domain) names, which is _really_ daft.
- */
- for (i = 15; i >= 0; i--)
- {
- if (netbios_name[i] == '.')
- {
- netbios_name[i] = 0;
- break;
- }
- }
-#endif /* TRUNCATE_NETBIOS_NAME */
-
- return netbios_name;
-}
-
-
-/****************************************************************************
-interpret the weird netbios "name". Return the name type
-****************************************************************************/
-static int name_interpret(char *in,char *out)
-{
- int ret;
- int len = (*in++) / 2;
-
- *out=0;
-
- if (len > 30 || len<1) return(0);
-
- while (len--)
- {
- if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
- *out = 0;
- return(0);
- }
- *out = ((in[0]-'A')<<4) + (in[1]-'A');
- in += 2;
- out++;
- }
- *out = 0;
- ret = out[-1];
-
-#ifdef NETBIOS_SCOPE
- /* Handle any scope names */
- while(*in)
- {
- *out++ = '.'; /* Scope names are separated by periods */
- len = *(uint8_t *)in++;
- StrnCpy(out, in, len);
- out += len;
- *out=0;
- in += len;
- }
-#endif
- return(ret);
-}
-
-
-/****************************************************************************
-return the number of bytes that would be occupied by the result of
-name_mangle()
-****************************************************************************/
-uint_t nbt_mangled_name_len(void)
-{
- const char *scope = lp_netbios_scope();
- uint_t ret = 34;
- if (scope && *scope) {
- ret += strlen(scope) + 1;
- }
- return ret;
-}
-
-/****************************************************************************
-mangle a name into netbios format
-
- Note: <Out> must be nbt_mangled_name_len() in length
-****************************************************************************/
-int name_mangle(char *In, char *Out, char name_type)
-{
- int i;
- int c;
- int len;
- char buf[20];
- char *p = Out;
- const char *scope = lp_netbios_scope();
-
- /* Safely copy the input string, In, into buf[]. */
- memset( buf, 0, 20 );
- if (strcmp(In,"*") == 0) {
- buf[0] = '*';
- } else {
- slprintf( buf, sizeof(buf) - 1, "%-15.15s%c", In, name_type);
- }
-
- /* Place the length of the first field into the output buffer. */
- p[0] = 32;
- p++;
-
- /* Now convert the name to the rfc1001/1002 format. */
- for ( i = 0; i < 16; i++ ) {
- c = toupper( buf[i] );
- p[i*2] = ( (c >> 4) & 0xF ) + 'A';
- p[(i*2)+1] = (c & 0xF) + 'A';
- }
- p += 32;
- p[0] = '\0';
-
- if (!scope || !*scope) {
- return name_len(Out);
- }
-
- /* Add the scope string. */
- for (i = 0, len = 0; scope[i]; i++, len++) {
- switch(scope[i]) {
- case '.':
- p[0] = len;
- p += (len + 1);
- len = -1;
- break;
- default:
- p[len+1] = scope[i];
- break;
- }
- }
-
- p[0] = len;
- if (len > 0) {
- p[len+1] = 0;
- }
-
- return name_len(Out);
-}
-
-/****************************************************************************
-find a pointer to a netbios name
-****************************************************************************/
-static char *name_ptr(char *buf,int ofs)
-{
- uint8_t c = *(uint8_t *)(buf+ofs);
-
- if ((c & 0xC0) == 0xC0)
- {
- uint16_t l = RSVAL(buf, ofs) & 0x3FFF;
- DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
- return(buf + l);
- }
- else
- return(buf+ofs);
-}
-
-/****************************************************************************
-extract a netbios name from a buf
-****************************************************************************/
-int name_extract(char *buf,int ofs,char *name)
-{
- char *p = name_ptr(buf,ofs);
- int d = PTR_DIFF(p,buf+ofs);
- pstrcpy(name,"");
- if (d < -50 || d > 50) return(0);
- return(name_interpret(p,name));
-}
-
-/****************************************************************************
-return the total storage length of a mangled name
-****************************************************************************/
-int name_len(char *s1)
-{
- /* NOTE: this argument _must_ be unsigned */
- uint8_t *s = (uint8_t *)s1;
- int len;
-
- /* If the two high bits of the byte are set, return 2. */
- if (0xC0 == (*s & 0xC0))
- return(2);
-
- /* Add up the length bytes. */
- for (len = 1; (*s); s += (*s) + 1) {
- len += *s + 1;
- SMB_ASSERT(len < 80);
- }
-
- return(len);
-} /* name_len */
-
-
-/*
- choose a name to use when calling a server in a NBT session request.
- we use heuristics to see if the name we have been given is a IP
- address, or a too-long name. If it is then use *SMBSERVER, or a
- truncated name
-*/
-void choose_called_name(struct nmb_name *n, const char *name, int type)
-{
- if (is_ipaddress(name)) {
- make_nmb_name(n, "*SMBSERVER", type);
- return;
- }
- if (strlen(name) > 16) {
- const char *p = strchr(name, '.');
- char name2[17];
- if (p - name > 16) {
- make_nmb_name(n, "*SMBSERVER", type);
- return;
- }
- strlcpy(name2, name, 1+(p-name));
- make_nmb_name(n, name2, type);
- return;
- }
-
- /* looks OK */
- make_nmb_name(n, name, type);
-}
diff --git a/source4/libcli/raw/clisocket.c b/source4/libcli/raw/clisocket.c
index 0edb95e1a1..e981049535 100644
--- a/source4/libcli/raw/clisocket.c
+++ b/source4/libcli/raw/clisocket.c
@@ -326,10 +326,11 @@ resolve a hostname and connect
****************************************************************************/
BOOL smbcli_sock_connect_byname(struct smbcli_socket *sock, const char *host, int port)
{
- int name_type = 0x20;
- struct ipv4_addr ip;
- char *name, *p;
+ int name_type = NBT_NAME_SERVER;
+ const char *address;
NTSTATUS status;
+ struct nbt_name nbt_name;
+ char *name, *p;
name = talloc_strdup(sock, host);
@@ -339,13 +340,18 @@ BOOL smbcli_sock_connect_byname(struct smbcli_socket *sock, const char *host, in
*p = 0;
}
- if (!resolve_name(name, name, &ip, name_type)) {
+ nbt_name.name = name;
+ nbt_name.type = name_type;
+ nbt_name.scope = NULL;
+
+ status = resolve_name(&nbt_name, sock, &address);
+ if (!NT_STATUS_IS_OK(status)) {
return False;
}
sock->hostname = name;
- status = smbcli_sock_connect(sock, sys_inet_ntoa(ip), port);
+ status = smbcli_sock_connect(sock, address, port);
return NT_STATUS_IS_OK(status);
}
diff --git a/source4/libcli/raw/clitransport.c b/source4/libcli/raw/clitransport.c
index e6d40639c6..918f18fa40 100644
--- a/source4/libcli/raw/clitransport.c
+++ b/source4/libcli/raw/clitransport.c
@@ -145,41 +145,52 @@ static void smbcli_transport_write_disable(struct smbcli_transport *transport)
send a session request
*/
struct smbcli_request *smbcli_transport_connect_send(struct smbcli_transport *transport,
- struct nmb_name *calling,
- struct nmb_name *called)
+ struct nbt_name *calling,
+ struct nbt_name *called)
{
uint8_t *p;
- int len = NBT_HDR_SIZE;
struct smbcli_request *req;
+ DATA_BLOB calling_blob, called_blob;
+ TALLOC_CTX *tmp_ctx = talloc_new(transport);
+ NTSTATUS status;
- if (called) {
- transport->called = *called;
- }
+ status = nbt_name_dup(transport, called, &transport->called);
+ if (!NT_STATUS_IS_OK(status)) goto failed;
+
+ status = nbt_name_to_blob(tmp_ctx, &calling_blob, calling);
+ if (!NT_STATUS_IS_OK(status)) goto failed;
+
+ status = nbt_name_to_blob(tmp_ctx, &called_blob, called);
+ if (!NT_STATUS_IS_OK(status)) goto failed;
/* allocate output buffer */
req = smbcli_request_setup_nonsmb(transport,
- NBT_HDR_SIZE + 2*nbt_mangled_name_len());
- if (req == NULL) return NULL;
+ NBT_HDR_SIZE +
+ calling_blob.length + called_blob.length);
+ if (req == NULL) goto failed;
/* put in the destination name */
p = req->out.buffer + NBT_HDR_SIZE;
- name_mangle(called->name, (char *)p, called->name_type);
- len += name_len((char *)p);
+ memcpy(p, called_blob.data, called_blob.length);
+ p += called_blob.length;
- /* and my name */
- p = req->out.buffer+len;
- name_mangle(calling->name, (char *)p, calling->name_type);
- len += name_len((char *)p);
+ memcpy(p, calling_blob.data, calling_blob.length);
+ p += calling_blob.length;
- _smb_setlen(req->out.buffer,len-4);
+ _smb_setlen(req->out.buffer, PTR_DIFF(p, req->out.buffer)-4);
SCVAL(req->out.buffer,0,0x81);
if (!smbcli_request_send(req)) {
smbcli_request_destroy(req);
- return NULL;
+ goto failed;
}
+ talloc_free(tmp_ctx);
return req;
+
+failed:
+ talloc_free(tmp_ctx);
+ return NULL;
}
/*
@@ -237,8 +248,8 @@ NTSTATUS smbcli_transport_connect_recv(struct smbcli_request *req)
send a session request (if needed)
*/
BOOL smbcli_transport_connect(struct smbcli_transport *transport,
- struct nmb_name *calling,
- struct nmb_name *called)
+ struct nbt_name *calling,
+ struct nbt_name *called)
{
struct smbcli_request *req;
NTSTATUS status;
diff --git a/source4/libcli/raw/libcliraw.h b/source4/libcli/raw/libcliraw.h
index 4047a5d369..d7414a237e 100644
--- a/source4/libcli/raw/libcliraw.h
+++ b/source4/libcli/raw/libcliraw.h
@@ -21,6 +21,7 @@
*/
#include "request.h"
+#include "librpc/gen_ndr/ndr_nbt.h"
struct smbcli_tree; /* forward declare */
struct smbcli_request; /* forward declare */
@@ -151,7 +152,7 @@ struct smbcli_transport {
/* remember the called name - some sub-protocols require us to
know the server name */
- struct nmb_name called;
+ struct nbt_name called;
/* a buffer for partially received SMB packets. */
struct {
diff --git a/source4/libcli/resolve/bcast.c b/source4/libcli/resolve/bcast.c
new file mode 100644
index 0000000000..b2d37fbfbb
--- /dev/null
+++ b/source4/libcli/resolve/bcast.c
@@ -0,0 +1,163 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ broadcast name resolution module
+
+ Copyright (C) Andrew Tridgell 2005
+
+ 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"
+#include "system/network.h"
+#include "libcli/raw/libcliraw.h"
+#include "libcli/nbt/libnbt.h"
+#include "libcli/composite/composite.h"
+
+struct bcast_state {
+ struct nbt_name name;
+ struct nbt_name_socket *nbtsock;
+ int num_queries;
+ struct nbt_name_request **queries;
+ struct nbt_name_query *io_queries;
+ const char *reply_addr;
+};
+
+/*
+ handle events during broadcast name resolution
+*/
+static void bcast_handler(struct nbt_name_request *req)
+{
+ struct smbcli_composite *c = talloc_get_type(req->async.private,
+ struct smbcli_composite);
+ struct bcast_state *state = talloc_get_type(c->private, struct bcast_state);
+ int i;
+
+ for (i=0;i<state->num_queries;i++) {
+ if (req == state->queries[i]) break;
+ }
+ if (i == state->num_queries) {
+ /* not for us?! */
+ c->status = NT_STATUS_INTERNAL_ERROR;
+ c->state = SMBCLI_REQUEST_ERROR;
+ goto done;
+ }
+
+ c->status = nbt_name_query_recv(req, state, &state->io_queries[i]);
+ if (!NT_STATUS_IS_OK(c->status)) {
+ c->state = SMBCLI_REQUEST_ERROR;
+ } else {
+ c->state = SMBCLI_REQUEST_DONE;
+ state->reply_addr = talloc_steal(state, state->io_queries[i].out.reply_addr);
+ }
+
+done:
+ talloc_free(state->nbtsock);
+ if (c->async.fn) {
+ c->async.fn(c);
+ }
+}
+
+/*
+ broadcast name resolution method - async send
+ */
+struct smbcli_composite *resolve_name_bcast_send(struct nbt_name *name,
+ struct event_context *event_ctx)
+{
+ struct smbcli_composite *c;
+ struct bcast_state *state;
+ int i;
+ NTSTATUS status;
+
+ c = talloc_zero(NULL, struct smbcli_composite);
+ if (c == NULL) goto failed;
+
+ state = talloc(c, struct bcast_state);
+ if (state == NULL) goto failed;
+
+ status = nbt_name_dup(state, name, &state->name);
+ if (!NT_STATUS_IS_OK(status)) goto failed;
+
+ state->nbtsock = nbt_name_socket_init(state, event_ctx);
+ if (state->nbtsock == NULL) goto failed;
+
+ state->num_queries = iface_count();
+
+ state->io_queries = talloc_array(state, struct nbt_name_query, state->num_queries);
+ if (!state->io_queries) goto failed;
+
+ state->queries = talloc_array(state, struct nbt_name_request *, state->num_queries);
+ if (!state->queries) goto failed;
+
+ for (i=0;i<state->num_queries;i++) {
+ struct ipv4_addr *ip = iface_n_bcast(i);
+ const char *addr = sys_inet_ntoa(*ip);
+ if (!addr) goto failed;
+
+ state->io_queries[i].in.name = state->name;
+ state->io_queries[i].in.dest_addr = talloc_strdup(state->io_queries, addr);
+ if (!state->io_queries[i].in.dest_addr) goto failed;
+ state->io_queries[i].in.broadcast = True;
+ state->io_queries[i].in.wins_lookup = False;
+ state->io_queries[i].in.timeout = lp_parm_int(-1, "nbt", "bcastTimeout", 5);
+
+ state->queries[i] = nbt_name_query_send(state->nbtsock, &state->io_queries[i]);
+ if (!state->queries[i]) goto failed;
+
+ state->queries[i]->async.fn = bcast_handler;
+ state->queries[i]->async.private = c;
+ }
+
+ c->state = SMBCLI_REQUEST_SEND;
+ c->private = state;
+ c->event_ctx = state->nbtsock->event_ctx;
+
+ return c;
+
+failed:
+ talloc_free(c);
+ return NULL;
+}
+
+/*
+ broadcast name resolution method - recv side
+ */
+NTSTATUS resolve_name_bcast_recv(struct smbcli_composite *c,
+ TALLOC_CTX *mem_ctx, const char **reply_addr)
+{
+ NTSTATUS status;
+
+ status = smb_composite_wait(c);
+
+ if (NT_STATUS_IS_OK(status)) {
+ struct bcast_state *state = talloc_get_type(c->private, struct bcast_state);
+ *reply_addr = talloc_steal(mem_ctx, state->reply_addr);
+ }
+
+ talloc_free(c);
+ return status;
+}
+
+/*
+ broadcast name resolution method - sync call
+ */
+NTSTATUS resolve_name_bcast(struct nbt_name *name,
+ TALLOC_CTX *mem_ctx,
+ const char **reply_addr)
+{
+ struct smbcli_composite *c = resolve_name_bcast_send(name, NULL);
+ return resolve_name_bcast_recv(c, mem_ctx, reply_addr);
+}
+
diff --git a/source4/libcli/resolve/resolve.c b/source4/libcli/resolve/resolve.c
new file mode 100644
index 0000000000..e83b11c95e
--- /dev/null
+++ b/source4/libcli/resolve/resolve.c
@@ -0,0 +1,51 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ general name resolution interface
+
+ Copyright (C) Andrew Tridgell 2005
+
+ 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"
+#include "libcli/raw/libcliraw.h"
+#include "libcli/composite/composite.h"
+
+/*
+ general name resolution - async send
+ */
+struct smbcli_composite *resolve_name_send(struct nbt_name *name, struct event_context *event_ctx)
+{
+ return resolve_name_bcast_send(name, event_ctx);
+}
+
+/*
+ general name resolution method - recv side
+ */
+NTSTATUS resolve_name_recv(struct smbcli_composite *c,
+ TALLOC_CTX *mem_ctx, const char **reply_addr)
+{
+ return resolve_name_bcast_recv(c, mem_ctx, reply_addr);
+}
+
+/*
+ general name resolution - sync call
+ */
+NTSTATUS resolve_name(struct nbt_name *name, TALLOC_CTX *mem_ctx, const char **reply_addr)
+{
+ struct smbcli_composite *c = resolve_name_send(name, NULL);
+ return resolve_name_recv(c, mem_ctx, reply_addr);
+}
diff --git a/source4/libcli/unexpected.c b/source4/libcli/unexpected.c
deleted file mode 100644
index 264b9d7b33..0000000000
--- a/source4/libcli/unexpected.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- handle unexpected packets
- Copyright (C) Andrew Tridgell 2000
-
- 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"
-
-static struct tdb_wrap *tdbd = NULL;
-
-/* the key type used in the unexpeceted packet database */
-struct unexpected_key {
- enum packet_type packet_type;
- time_t timestamp;
- int count;
-};
-
-
-
-/****************************************************************************
- all unexpected packets are passed in here, to be stored in a unexpected
- packet database. This allows nmblookup and other tools to receive packets
- erroneoously sent to the wrong port by broken MS systems
- **************************************************************************/
-void unexpected_packet(struct packet_struct *p)
-{
- static int count;
- TDB_DATA kbuf, dbuf;
- struct unexpected_key key;
- char buf[1024];
- int len=0;
-
- if (!tdbd) {
- char *path = smbd_tmp_path(NULL, "unexpected.tdb");
- tdbd = tdb_wrap_open(NULL, path, 0,
- TDB_DEFAULT,
- O_RDWR | O_CREAT, 0644);
- talloc_free(path);
- if (!tdbd) {
- return;
- }
- }
-
- memset(buf,'\0',sizeof(buf));
-
- len = build_packet(buf, p);
-
- key.packet_type = p->packet_type;
- key.timestamp = p->timestamp;
- key.count = count++;
-
- kbuf.dptr = (char *)&key;
- kbuf.dsize = sizeof(key);
- dbuf.dptr = buf;
- dbuf.dsize = len;
-
- tdb_store(tdbd->tdb, kbuf, dbuf, TDB_REPLACE);
-}
-
-
-static time_t lastt;
-
-/****************************************************************************
-delete the record if it is too old
- **************************************************************************/
-static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
-{
- struct unexpected_key key;
-
- memcpy(&key, kbuf.dptr, sizeof(key));
-
- if (lastt - key.timestamp > NMBD_UNEXPECTED_TIMEOUT) {
- tdb_delete(ttdb, kbuf);
- }
-
- return 0;
-}
-
-
-/****************************************************************************
-delete all old unexpected packets
- **************************************************************************/
-void clear_unexpected(time_t t)
-{
- if (!tdbd) return;
-
- if ((lastt != 0) && (t < lastt + NMBD_UNEXPECTED_TIMEOUT))
- return;
-
- lastt = t;
-
- tdb_traverse(tdbd->tdb, traverse_fn, NULL);
-}
-
-
-static struct packet_struct *matched_packet;
-static int match_id;
-static enum packet_type match_type;
-static const char *match_name;
-
-/****************************************************************************
-tdb traversal fn to find a matching 137 packet
- **************************************************************************/
-static int traverse_match(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
-{
- struct unexpected_key key;
- struct packet_struct *p;
-
- memcpy(&key, kbuf.dptr, sizeof(key));
-
- if (key.packet_type != match_type) return 0;
-
- p = parse_packet(dbuf.dptr, dbuf.dsize, match_type);
-
- if ((match_type == NMB_PACKET &&
- p->packet.nmb.header.name_trn_id == match_id) ||
- (match_type == DGRAM_PACKET &&
- match_mailslot_name(p, match_name))) {
- matched_packet = p;
- return -1;
- }
-
- free_packet(p);
-
- return 0;
-}
-
-
-/****************************************************************************
-check for a particular packet in the unexpected packet queue
- **************************************************************************/
-struct packet_struct *receive_unexpected(enum packet_type packet_type, int id,
- const char *mailslot_name)
-{
- struct tdb_wrap *tdb2;
- char *path;
-
- path = smbd_tmp_path(NULL, "unexpected.tdb");
- tdb2 = tdb_wrap_open(NULL, path, 0, 0, O_RDONLY, 0);
- talloc_free(path);
- if (!tdb2) {
- return NULL;
- }
-
- matched_packet = NULL;
- match_id = id;
- match_type = packet_type;
- match_name = mailslot_name;
-
- tdb_traverse(tdb2->tdb, traverse_match, NULL);
-
- talloc_free(tdb2);
-
- return matched_packet;
-}
diff --git a/source4/libnet/libnet_rpc.c b/source4/libnet/libnet_rpc.c
index b4b33bf4c0..1f546d89a4 100644
--- a/source4/libnet/libnet_rpc.c
+++ b/source4/libnet/libnet_rpc.c
@@ -19,29 +19,34 @@
*/
#include "includes.h"
+#include "libcli/nbt/libnbt.h"
#include "libnet/libnet.h"
/* find a domain pdc generic */
-static NTSTATUS libnet_find_pdc_generic(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_find_pdc *r)
+static NTSTATUS libnet_find_pdc_generic(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
+ union libnet_find_pdc *r)
{
- BOOL ret;
- struct ipv4_addr ip;
+ const char *address;
+ NTSTATUS status;
+ struct nbt_name name;
if (is_ipaddress(r->generic.in.domain_name)) {
r->generic.out.pdc_name = r->generic.in.domain_name;
return NT_STATUS_OK;
}
- ret = get_pdc_ip(mem_ctx, r->generic.in.domain_name, &ip);
- if (!ret) {
- /* fallback to a workstation name */
- ret = resolve_name(mem_ctx, r->generic.in.domain_name, &ip, 0x20);
- if (!ret) {
- return NT_STATUS_NO_LOGON_SERVERS;
- }
+ name.name = r->generic.in.domain_name;
+ name.type = NBT_NAME_PDC;
+ name.scope = NULL;
+
+ status = resolve_name(&name, mem_ctx, &address);
+ if (!NT_STATUS_IS_OK(status)) {
+ name.type = NBT_NAME_SERVER;
+ status = resolve_name(&name, mem_ctx, &address);
}
+ NT_STATUS_NOT_OK_RETURN(status);
- r->generic.out.pdc_name = talloc_strdup(mem_ctx, sys_inet_ntoa(ip));
+ r->generic.out.pdc_name = talloc_strdup(mem_ctx, address);
return NT_STATUS_OK;
}
diff --git a/source4/torture/rpc/xplogin.c b/source4/torture/rpc/xplogin.c
index 6dcd456fdb..8acf3c4eb7 100644
--- a/source4/torture/rpc/xplogin.c
+++ b/source4/torture/rpc/xplogin.c
@@ -62,12 +62,15 @@ static NTSTATUS after_negprot(struct smbcli_transport **dst_transport,
talloc_set_destructor(transport, destroy_transport);
{
- struct nmb_name calling;
- struct nmb_name called;
+ struct nbt_name calling;
+ struct nbt_name called;
/* send a NBT session request, if applicable */
- make_nmb_name(&calling, my_name, 0x0);
- choose_called_name(&called, dest_host, 0x20);
+ calling.name = my_name;
+ calling.type = NBT_NAME_CLIENT;
+ calling.scope = NULL;
+
+ nbt_choose_called_name(transport, &called, dest_host, NBT_NAME_SERVER);
if (!smbcli_transport_connect(transport, &calling, &called)) {
talloc_free(transport);
diff --git a/source4/torture/torture.c b/source4/torture/torture.c
index b2219c617c..63793b41da 100644
--- a/source4/torture/torture.c
+++ b/source4/torture/torture.c
@@ -44,12 +44,15 @@ BOOL torture_showall = False;
static struct smbcli_state *open_nbt_connection(void)
{
- struct nmb_name called, calling;
+ struct nbt_name called, calling;
struct smbcli_state *cli;
const char *host = lp_parm_string(-1, "torture", "host");
- make_nmb_name(&calling, lp_netbios_name(), 0x0);
- choose_called_name(&called, host, 0x20);
+ calling.name = lp_netbios_name();
+ calling.type = NBT_NAME_CLIENT;
+ calling.scope = NULL;
+
+ nbt_choose_called_name(NULL, &called, host, NBT_NAME_SERVER);
cli = smbcli_state_init(NULL);
if (!cli) {
@@ -63,23 +66,9 @@ static struct smbcli_state *open_nbt_connection(void)
}
if (!smbcli_transport_establish(cli, &calling, &called)) {
- /*
- * Well, that failed, try *SMBSERVER ...
- * However, we must reconnect as well ...
- */
- if (!smbcli_socket_connect(cli, host)) {
- printf("Failed to connect with %s\n", host);
- return False;
- }
-
- make_nmb_name(&called, "*SMBSERVER", 0x20);
- if (!smbcli_transport_establish(cli, &calling, &called)) {
- printf("%s rejected the session\n",host);
- printf("We tried with a called name of %s & %s\n",
- host, "*SMBSERVER");
- smbcli_shutdown(cli);
- return NULL;
- }
+ printf("%s rejected the session\n",host);
+ smbcli_shutdown(cli);
+ return NULL;
}
return cli;