Line data Source code
1 : /* 2 : Unix SMB/CIFS implementation. 3 : 4 : send out a name release request 5 : 6 : Copyright (C) Andrew Tridgell 2005 7 : 8 : This program is free software; you can redistribute it and/or modify 9 : it under the terms of the GNU General Public License as published by 10 : the Free Software Foundation; either version 3 of the License, or 11 : (at your option) any later version. 12 : 13 : This program is distributed in the hope that it will be useful, 14 : but WITHOUT ANY WARRANTY; without even the implied warranty of 15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 : GNU General Public License for more details. 17 : 18 : You should have received a copy of the GNU General Public License 19 : along with this program. If not, see <http://www.gnu.org/licenses/>. 20 : */ 21 : 22 : #include "includes.h" 23 : #include "../libcli/nbt/libnbt.h" 24 : #include "../libcli/nbt/nbt_proto.h" 25 : #include "lib/socket/socket.h" 26 : 27 : /* 28 : send a nbt name release request 29 : */ 30 220 : _PUBLIC_ struct nbt_name_request *nbt_name_release_send(struct nbt_name_socket *nbtsock, 31 : struct nbt_name_release *io) 32 : { 33 0 : struct nbt_name_request *req; 34 0 : struct nbt_name_packet *packet; 35 0 : struct socket_address *dest; 36 : 37 220 : packet = talloc_zero(nbtsock, struct nbt_name_packet); 38 220 : if (packet == NULL) return NULL; 39 : 40 220 : packet->qdcount = 1; 41 220 : packet->arcount = 1; 42 220 : packet->operation = NBT_OPCODE_RELEASE; 43 220 : if (io->in.broadcast) { 44 0 : packet->operation |= NBT_FLAG_BROADCAST; 45 : } 46 : 47 220 : packet->questions = talloc_array(packet, struct nbt_name_question, 1); 48 220 : if (packet->questions == NULL) goto failed; 49 : 50 220 : packet->questions[0].name = io->in.name; 51 220 : packet->questions[0].question_type = NBT_QTYPE_NETBIOS; 52 220 : packet->questions[0].question_class = NBT_QCLASS_IP; 53 : 54 220 : packet->additional = talloc_array(packet, struct nbt_res_rec, 1); 55 220 : if (packet->additional == NULL) goto failed; 56 : 57 220 : packet->additional[0].name = io->in.name; 58 220 : packet->additional[0].rr_type = NBT_QTYPE_NETBIOS; 59 220 : packet->additional[0].rr_class = NBT_QCLASS_IP; 60 220 : packet->additional[0].ttl = 0; 61 220 : packet->additional[0].rdata.netbios.length = 6; 62 220 : packet->additional[0].rdata.netbios.addresses = talloc_array(packet->additional, 63 : struct nbt_rdata_address, 1); 64 220 : if (packet->additional[0].rdata.netbios.addresses == NULL) goto failed; 65 220 : packet->additional[0].rdata.netbios.addresses[0].nb_flags = io->in.nb_flags; 66 440 : packet->additional[0].rdata.netbios.addresses[0].ipaddr = 67 220 : talloc_strdup(packet->additional, io->in.address); 68 : 69 220 : dest = socket_address_from_strings(packet, nbtsock->sock->backend_name, 70 220 : io->in.dest_addr, io->in.dest_port); 71 220 : if (dest == NULL) goto failed; 72 220 : req = nbt_name_request_send(nbtsock, nbtsock, dest, packet, 73 : io->in.timeout, io->in.retries, false); 74 220 : if (req == NULL) goto failed; 75 : 76 220 : talloc_free(packet); 77 220 : return req; 78 : 79 0 : failed: 80 0 : talloc_free(packet); 81 0 : return NULL; 82 : } 83 : 84 : /* 85 : wait for a release reply 86 : */ 87 220 : _PUBLIC_ NTSTATUS nbt_name_release_recv(struct nbt_name_request *req, 88 : TALLOC_CTX *mem_ctx, struct nbt_name_release *io) 89 : { 90 0 : NTSTATUS status; 91 0 : struct nbt_name_packet *packet; 92 : 93 220 : status = nbt_name_request_recv(req); 94 220 : if (!NT_STATUS_IS_OK(status) || 95 219 : req->num_replies == 0) { 96 1 : talloc_free(req); 97 1 : return status; 98 : } 99 : 100 219 : packet = req->replies[0].packet; 101 219 : io->out.reply_from = talloc_steal(mem_ctx, req->replies[0].dest->addr); 102 : 103 219 : if (packet->ancount != 1 || 104 219 : packet->answers[0].rr_type != NBT_QTYPE_NETBIOS || 105 219 : packet->answers[0].rr_class != NBT_QCLASS_IP) { 106 0 : talloc_free(req); 107 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE; 108 : } 109 : 110 219 : io->out.rcode = packet->operation & NBT_RCODE; 111 219 : io->out.name = packet->answers[0].name; 112 219 : if (packet->answers[0].rdata.netbios.length < 6) { 113 0 : talloc_free(req); 114 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE; 115 : } 116 219 : io->out.reply_addr = talloc_steal(mem_ctx, 117 : packet->answers[0].rdata.netbios.addresses[0].ipaddr); 118 219 : talloc_steal(mem_ctx, io->out.name.name); 119 219 : talloc_steal(mem_ctx, io->out.name.scope); 120 : 121 219 : talloc_free(req); 122 : 123 219 : return NT_STATUS_OK; 124 : } 125 : 126 : /* 127 : synchronous name release request 128 : */ 129 210 : _PUBLIC_ NTSTATUS nbt_name_release(struct nbt_name_socket *nbtsock, 130 : TALLOC_CTX *mem_ctx, struct nbt_name_release *io) 131 : { 132 210 : struct nbt_name_request *req = nbt_name_release_send(nbtsock, io); 133 210 : return nbt_name_release_recv(req, mem_ctx, io); 134 : }