diff options
author | Andrew Tridgell <tridge@samba.org> | 2005-01-21 11:18:56 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:09:03 -0500 |
commit | 2383787f199c51cdc202a3cef5822a9fe6b8774c (patch) | |
tree | 52419b4e736f5ae1727561a3c9831e899edb35c5 /source4/libcli/nbt | |
parent | f1aaef3015864f9323711127a4964a8eceff6a52 (diff) | |
download | samba-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.h | 6 | ||||
-rw-r--r-- | source4/libcli/nbt/namequery.c | 66 | ||||
-rw-r--r-- | source4/libcli/nbt/nbtname.c | 54 | ||||
-rw-r--r-- | source4/libcli/nbt/nbtsocket.c | 48 |
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; |