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:
parent
c1cae6b3b1
commit
239c310f25
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
@ -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"
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
163
source/libcli/resolve/bcast.c
Normal file
163
source/libcli/resolve/bcast.c
Normal 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);
|
||||
}
|
||||
|
51
source/libcli/resolve/resolve.c
Normal file
51
source/libcli/resolve/resolve.c
Normal 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);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user