diff options
Diffstat (limited to 'source4/libcli/nbt')
-rw-r--r-- | source4/libcli/nbt/libnbt.h | 20 | ||||
-rw-r--r-- | source4/libcli/nbt/namequery.c | 16 | ||||
-rw-r--r-- | source4/libcli/nbt/namerelease.c | 129 |
3 files changed, 160 insertions, 5 deletions
diff --git a/source4/libcli/nbt/libnbt.h b/source4/libcli/nbt/libnbt.h index 63711490fe..5a53510ccf 100644 --- a/source4/libcli/nbt/libnbt.h +++ b/source4/libcli/nbt/libnbt.h @@ -138,7 +138,6 @@ struct nbt_name_query { struct nbt_name name; int16_t num_addrs; const char **reply_addrs; - uint8_t rcode; } out; }; @@ -154,7 +153,6 @@ struct nbt_name_status { const char *reply_from; struct nbt_name name; struct nbt_rdata_status status; - uint8_t rcode; } out; }; @@ -247,3 +245,21 @@ struct nbt_name_refresh_wins { }; +/* a name release request */ +struct nbt_name_release { + struct { + struct nbt_name name; + const char *dest_addr; + const char *address; + uint16_t nb_flags; + BOOL broadcast; + int timeout; /* in seconds */ + int retries; + } in; + struct { + const char *reply_from; + struct nbt_name name; + const char *reply_addr; + uint8_t rcode; + } out; +}; diff --git a/source4/libcli/nbt/namequery.c b/source4/libcli/nbt/namequery.c index 32fcad2052..5907c45b87 100644 --- a/source4/libcli/nbt/namequery.c +++ b/source4/libcli/nbt/namequery.c @@ -84,14 +84,19 @@ NTSTATUS nbt_name_query_recv(struct nbt_name_request *req, packet = req->replies[0].packet; io->out.reply_from = talloc_steal(mem_ctx, req->replies[0].reply_addr); + if ((packet->operation & NBT_RCODE) != 0) { + status = nbt_rcode_to_ntstatus(packet->operation & NBT_RCODE); + talloc_free(req); + return status; + } + if (packet->ancount != 1 || packet->answers[0].rr_type != NBT_QTYPE_NETBIOS || packet->answers[0].rr_class != NBT_QCLASS_IP) { talloc_free(req); - return NT_STATUS_INVALID_NETWORK_RESPONSE; + return status; } - io->out.rcode = packet->operation & NBT_RCODE; io->out.name = packet->answers[0].name; io->out.num_addrs = packet->answers[0].rdata.netbios.length / 6; io->out.reply_addrs = talloc_array(mem_ctx, const char *, io->out.num_addrs); @@ -178,6 +183,12 @@ NTSTATUS nbt_name_status_recv(struct nbt_name_request *req, packet = req->replies[0].packet; io->out.reply_from = talloc_steal(mem_ctx, req->replies[0].reply_addr); + if ((packet->operation & NBT_RCODE) != 0) { + status = nbt_rcode_to_ntstatus(packet->operation & NBT_RCODE); + talloc_free(req); + return status; + } + if (packet->ancount != 1 || packet->answers[0].rr_type != NBT_QTYPE_STATUS || packet->answers[0].rr_class != NBT_QCLASS_IP) { @@ -185,7 +196,6 @@ NTSTATUS nbt_name_status_recv(struct nbt_name_request *req, return NT_STATUS_INVALID_NETWORK_RESPONSE; } - io->out.rcode = packet->operation & NBT_RCODE; io->out.name = packet->answers[0].name; talloc_steal(mem_ctx, io->out.name.name); talloc_steal(mem_ctx, io->out.name.scope); diff --git a/source4/libcli/nbt/namerelease.c b/source4/libcli/nbt/namerelease.c new file mode 100644 index 0000000000..208c73d386 --- /dev/null +++ b/source4/libcli/nbt/namerelease.c @@ -0,0 +1,129 @@ +/* + Unix SMB/CIFS implementation. + + send out a name release request + + 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/nbt/libnbt.h" + +/* + send a nbt name release request +*/ +struct nbt_name_request *nbt_name_release_send(struct nbt_name_socket *nbtsock, + struct nbt_name_release *io) +{ + struct nbt_name_request *req; + struct nbt_name_packet *packet; + + packet = talloc_zero(nbtsock, struct nbt_name_packet); + if (packet == NULL) return NULL; + + packet->qdcount = 1; + packet->arcount = 1; + packet->operation = NBT_OPCODE_RELEASE; + if (io->in.broadcast) { + packet->operation |= NBT_FLAG_BROADCAST; + } + + packet->questions = talloc_array(packet, struct nbt_name_question, 1); + if (packet->questions == NULL) goto failed; + + packet->questions[0].name = io->in.name; + packet->questions[0].question_type = NBT_QTYPE_NETBIOS; + packet->questions[0].question_class = NBT_QCLASS_IP; + + packet->additional = talloc_array(packet, struct nbt_res_rec, 1); + if (packet->additional == NULL) goto failed; + + packet->additional[0].name = io->in.name; + packet->additional[0].rr_type = NBT_QTYPE_NETBIOS; + packet->additional[0].rr_class = NBT_QCLASS_IP; + packet->additional[0].ttl = 0; + packet->additional[0].rdata.netbios.length = 6; + packet->additional[0].rdata.netbios.addresses = talloc_array(packet->additional, + struct nbt_rdata_address, 1); + if (packet->additional[0].rdata.netbios.addresses == NULL) goto failed; + packet->additional[0].rdata.netbios.addresses[0].nb_flags = io->in.nb_flags; + packet->additional[0].rdata.netbios.addresses[0].ipaddr = + talloc_strdup(packet->additional, io->in.address); + + req = nbt_name_request_send(nbtsock, io->in.dest_addr, lp_nbt_port(), packet, + io->in.timeout, io->in.retries, False); + if (req == NULL) goto failed; + + talloc_free(packet); + return req; + +failed: + talloc_free(packet); + return NULL; +} + +/* + wait for a release reply +*/ +NTSTATUS nbt_name_release_recv(struct nbt_name_request *req, + TALLOC_CTX *mem_ctx, struct nbt_name_release *io) +{ + NTSTATUS status; + struct nbt_name_packet *packet; + + status = nbt_name_request_recv(req); + if (!NT_STATUS_IS_OK(status) || + req->num_replies == 0) { + talloc_free(req); + return status; + } + + packet = req->replies[0].packet; + io->out.reply_from = talloc_steal(mem_ctx, req->replies[0].reply_addr); + + if (packet->ancount != 1 || + packet->answers[0].rr_type != NBT_QTYPE_NETBIOS || + packet->answers[0].rr_class != NBT_QCLASS_IP) { + talloc_free(req); + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + io->out.rcode = packet->operation & NBT_RCODE; + io->out.name = packet->answers[0].name; + if (packet->answers[0].rdata.netbios.length < 6) { + talloc_free(req); + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + io->out.reply_addr = talloc_steal(mem_ctx, + packet->answers[0].rdata.netbios.addresses[0].ipaddr); + talloc_steal(mem_ctx, io->out.name.name); + talloc_steal(mem_ctx, io->out.name.scope); + + talloc_free(req); + + return NT_STATUS_OK; +} + +/* + synchronous name release request +*/ +NTSTATUS nbt_name_release(struct nbt_name_socket *nbtsock, + TALLOC_CTX *mem_ctx, struct nbt_name_release *io) +{ + struct nbt_name_request *req = nbt_name_release_send(nbtsock, io); + return nbt_name_release_recv(req, mem_ctx, io); +} |