1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

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 commit is contained in:
Andrew Tridgell 2005-01-21 11:18:56 +00:00 committed by Gerald (Jerry) Carter
parent c1cae6b3b1
commit 239c310f25
20 changed files with 453 additions and 2769 deletions

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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"

View File

@ -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;
};

View File

@ -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);
}

View File

@ -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);
}

View File

@ -28,6 +28,16 @@
#define NBT_MAX_PACKET_SIZE 2048
#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
*/
@ -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;

File diff suppressed because it is too large Load Diff

View File

@ -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);
}

View File

@ -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;

View File

@ -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 {

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
r->generic.out.pdc_name = talloc_strdup(mem_ctx, sys_inet_ntoa(ip));
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, address);
return NT_STATUS_OK;
}

View File

@ -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);

View File

@ -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;