summaryrefslogtreecommitdiff
path: root/source4/libcli/nbt
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 /source4/libcli/nbt
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)
Diffstat (limited to 'source4/libcli/nbt')
-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
4 files changed, 103 insertions, 71 deletions
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;