From 6f33f3e4c26564602d5d13c7459938955b56a16e Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 23 Sep 2008 06:58:17 +0200 Subject: s4-nbt: move libcli/nbt up one level. Guenther --- source4/libcli/nbt/libnbt.h | 351 --------------------- source4/libcli/nbt/namequery.c | 235 -------------- source4/libcli/nbt/namerefresh.c | 302 ------------------ source4/libcli/nbt/nameregister.c | 442 -------------------------- source4/libcli/nbt/namerelease.c | 135 -------- source4/libcli/nbt/nbtname.c | 648 -------------------------------------- source4/libcli/nbt/nbtsocket.c | 521 ------------------------------ source4/libcli/nbt/pynbt.c | 408 ------------------------ 8 files changed, 3042 deletions(-) delete mode 100644 source4/libcli/nbt/libnbt.h delete mode 100644 source4/libcli/nbt/namequery.c delete mode 100644 source4/libcli/nbt/namerefresh.c delete mode 100644 source4/libcli/nbt/nameregister.c delete mode 100644 source4/libcli/nbt/namerelease.c delete mode 100644 source4/libcli/nbt/nbtname.c delete mode 100644 source4/libcli/nbt/nbtsocket.c delete mode 100644 source4/libcli/nbt/pynbt.c (limited to 'source4/libcli') diff --git a/source4/libcli/nbt/libnbt.h b/source4/libcli/nbt/libnbt.h deleted file mode 100644 index 8529ec362b..0000000000 --- a/source4/libcli/nbt/libnbt.h +++ /dev/null @@ -1,351 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - a raw async NBT library - - 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 3 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, see . -*/ - -#ifndef __LIBNBT_H__ -#define __LIBNBT_H__ - -#include "librpc/gen_ndr/nbt.h" -#include "librpc/ndr/libndr.h" - -/* - possible states for pending requests -*/ -enum nbt_request_state {NBT_REQUEST_SEND, - NBT_REQUEST_WAIT, - NBT_REQUEST_DONE, - NBT_REQUEST_TIMEOUT, - NBT_REQUEST_ERROR}; - -/* - a nbt name request -*/ -struct nbt_name_request { - struct nbt_name_request *next, *prev; - - enum nbt_request_state state; - - NTSTATUS status; - - /* the socket this was on */ - struct nbt_name_socket *nbtsock; - - /* where to send the request */ - struct socket_address *dest; - - /* timeout between retries */ - int timeout; - - /* how many retries to send on timeout */ - int num_retries; - - /* whether we have received a WACK */ - bool received_wack; - - /* the timeout event */ - struct timed_event *te; - - /* the name transaction id */ - uint16_t name_trn_id; - - /* is it a reply? */ - bool is_reply; - - /* the encoded request */ - DATA_BLOB encoded; - - /* shall we allow multiple replies? */ - bool allow_multiple_replies; - - unsigned int num_replies; - struct nbt_name_reply { - struct nbt_name_packet *packet; - struct socket_address *dest; - } *replies; - - /* information on what to do on completion */ - struct { - void (*fn)(struct nbt_name_request *); - void *private_data; - } async; -}; - - - -/* - context structure for operations on name queries -*/ -struct nbt_name_socket { - struct socket_context *sock; - struct event_context *event_ctx; - struct smb_iconv_convenience *iconv_convenience; - - /* a queue of requests pending to be sent */ - struct nbt_name_request *send_queue; - - /* the fd event */ - struct fd_event *fde; - - /* mapping from name_trn_id to pending event */ - struct idr_context *idr; - - /* how many requests are waiting for a reply */ - uint16_t num_pending; - - /* what to do with incoming request packets */ - struct { - void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *, - struct socket_address *); - void *private_data; - } incoming; - - /* what to do with unexpected replies */ - struct { - void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *, - struct socket_address *); - void *private_data; - } unexpected; -}; - - -/* a simple name query */ -struct nbt_name_query { - struct { - struct nbt_name name; - const char *dest_addr; - uint16_t dest_port; - bool broadcast; - bool wins_lookup; - int timeout; /* in seconds */ - int retries; - } in; - struct { - const char *reply_from; - struct nbt_name name; - int16_t num_addrs; - const char **reply_addrs; - } out; -}; - -/* a simple name status query */ -struct nbt_name_status { - struct { - struct nbt_name name; - const char *dest_addr; - uint16_t dest_port; - int timeout; /* in seconds */ - int retries; - } in; - struct { - const char *reply_from; - struct nbt_name name; - struct nbt_rdata_status status; - } out; -}; - -/* a name registration request */ -struct nbt_name_register { - struct { - struct nbt_name name; - const char *dest_addr; - uint16_t dest_port; - const char *address; - uint16_t nb_flags; - bool register_demand; - bool broadcast; - bool multi_homed; - uint32_t ttl; - int timeout; /* in seconds */ - int retries; - } in; - struct { - const char *reply_from; - struct nbt_name name; - const char *reply_addr; - uint8_t rcode; - } out; -}; - -/* a send 3 times then demand name broadcast name registration */ -struct nbt_name_register_bcast { - struct { - struct nbt_name name; - const char *dest_addr; - uint16_t dest_port; - const char *address; - uint16_t nb_flags; - uint32_t ttl; - } in; -}; - - -/* wins name register with multiple wins servers to try and multiple - addresses to register */ -struct nbt_name_register_wins { - struct { - struct nbt_name name; - const char **wins_servers; - uint16_t wins_port; - const char **addresses; - uint16_t nb_flags; - uint32_t ttl; - } in; - struct { - const char *wins_server; - uint8_t rcode; - } out; -}; - - - -/* a name refresh request */ -struct nbt_name_refresh { - struct { - struct nbt_name name; - const char *dest_addr; - uint16_t dest_port; - const char *address; - uint16_t nb_flags; - bool broadcast; - uint32_t ttl; - int timeout; /* in seconds */ - int retries; - } in; - struct { - const char *reply_from; - struct nbt_name name; - const char *reply_addr; - uint8_t rcode; - } out; -}; - -/* wins name refresh with multiple wins servers to try and multiple - addresses to register */ -struct nbt_name_refresh_wins { - struct { - struct nbt_name name; - const char **wins_servers; - uint16_t wins_port; - const char **addresses; - uint16_t nb_flags; - uint32_t ttl; - } in; - struct { - const char *wins_server; - uint8_t rcode; - } out; -}; - - -/* a name release request */ -struct nbt_name_release { - struct { - struct nbt_name name; - const char *dest_addr; - uint16_t dest_port; - 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; -}; - -struct nbt_name_socket *nbt_name_socket_init(TALLOC_CTX *mem_ctx, - struct event_context *event_ctx, - struct smb_iconv_convenience *iconv_convenience); -struct nbt_name_request *nbt_name_query_send(struct nbt_name_socket *nbtsock, - struct nbt_name_query *io); -NTSTATUS nbt_name_query_recv(struct nbt_name_request *req, - TALLOC_CTX *mem_ctx, struct nbt_name_query *io); -NTSTATUS nbt_name_query(struct nbt_name_socket *nbtsock, - TALLOC_CTX *mem_ctx, struct nbt_name_query *io); -struct nbt_name_request *nbt_name_status_send(struct nbt_name_socket *nbtsock, - struct nbt_name_status *io); -NTSTATUS nbt_name_status_recv(struct nbt_name_request *req, - TALLOC_CTX *mem_ctx, struct nbt_name_status *io); -NTSTATUS nbt_name_status(struct nbt_name_socket *nbtsock, - TALLOC_CTX *mem_ctx, struct nbt_name_status *io); - -NTSTATUS nbt_name_dup(TALLOC_CTX *mem_ctx, struct nbt_name *name, struct nbt_name *newname); -NTSTATUS nbt_name_to_blob(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience, DATA_BLOB *blob, struct nbt_name *name); -NTSTATUS nbt_name_from_blob(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, struct nbt_name *name); -void nbt_choose_called_name(TALLOC_CTX *mem_ctx, struct nbt_name *n, const char *name, int type); -char *nbt_name_string(TALLOC_CTX *mem_ctx, const struct nbt_name *name); -NTSTATUS nbt_name_register(struct nbt_name_socket *nbtsock, - TALLOC_CTX *mem_ctx, struct nbt_name_register *io); -NTSTATUS nbt_name_refresh(struct nbt_name_socket *nbtsock, - TALLOC_CTX *mem_ctx, struct nbt_name_refresh *io); -NTSTATUS nbt_name_release(struct nbt_name_socket *nbtsock, - TALLOC_CTX *mem_ctx, struct nbt_name_release *io); -NTSTATUS nbt_name_register_wins(struct nbt_name_socket *nbtsock, - TALLOC_CTX *mem_ctx, - struct nbt_name_register_wins *io); -NTSTATUS nbt_name_refresh_wins(struct nbt_name_socket *nbtsock, - TALLOC_CTX *mem_ctx, - struct nbt_name_refresh_wins *io); -NTSTATUS nbt_name_register_recv(struct nbt_name_request *req, - TALLOC_CTX *mem_ctx, struct nbt_name_register *io); -struct nbt_name_request *nbt_name_register_send(struct nbt_name_socket *nbtsock, - struct nbt_name_register *io); -NTSTATUS nbt_name_release_recv(struct nbt_name_request *req, - TALLOC_CTX *mem_ctx, struct nbt_name_release *io); - -struct nbt_name_request *nbt_name_release_send(struct nbt_name_socket *nbtsock, - struct nbt_name_release *io); - -NTSTATUS nbt_name_refresh_recv(struct nbt_name_request *req, - TALLOC_CTX *mem_ctx, struct nbt_name_refresh *io); - -NTSTATUS nbt_set_incoming_handler(struct nbt_name_socket *nbtsock, - void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *, - struct socket_address *), - void *private_data); -NTSTATUS nbt_name_reply_send(struct nbt_name_socket *nbtsock, - struct socket_address *dest, - struct nbt_name_packet *request); - - -NDR_SCALAR_PROTO(wrepl_nbt_name, const struct nbt_name *); -NDR_SCALAR_PROTO(nbt_string, const char *); -NDR_BUFFER_PROTO(nbt_name, struct nbt_name); -NTSTATUS nbt_rcode_to_ntstatus(uint8_t rcode); - -struct composite_context; -struct composite_context *nbt_name_register_bcast_send(struct nbt_name_socket *nbtsock, - struct nbt_name_register_bcast *io); -NTSTATUS nbt_name_register_bcast_recv(struct composite_context *c); -struct composite_context *nbt_name_register_wins_send(struct nbt_name_socket *nbtsock, - struct nbt_name_register_wins *io); -NTSTATUS nbt_name_refresh_wins_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, - struct nbt_name_refresh_wins *io); -struct composite_context *nbt_name_refresh_wins_send(struct nbt_name_socket *nbtsock, - struct nbt_name_refresh_wins *io); -NTSTATUS nbt_name_register_wins_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, - struct nbt_name_register_wins *io); - - -#endif /* __LIBNBT_H__ */ diff --git a/source4/libcli/nbt/namequery.c b/source4/libcli/nbt/namequery.c deleted file mode 100644 index 2e1bcd818b..0000000000 --- a/source4/libcli/nbt/namequery.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - make nbt name query requests - - 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 3 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, see . -*/ - -#include "includes.h" -#include "libcli/nbt/libnbt.h" -#include "libcli/nbt/nbt_proto.h" -#include "lib/socket/socket.h" -#include "param/param.h" - -/** - send a nbt name query -*/ -_PUBLIC_ struct nbt_name_request *nbt_name_query_send(struct nbt_name_socket *nbtsock, - struct nbt_name_query *io) -{ - struct nbt_name_request *req; - struct nbt_name_packet *packet; - struct socket_address *dest; - - packet = talloc_zero(nbtsock, struct nbt_name_packet); - if (packet == NULL) return NULL; - - packet->qdcount = 1; - packet->operation = NBT_OPCODE_QUERY; - if (io->in.broadcast) { - packet->operation |= NBT_FLAG_BROADCAST; - } - if (io->in.wins_lookup) { - packet->operation |= NBT_FLAG_RECURSION_DESIRED; - } - - 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; - - dest = socket_address_from_strings(packet, nbtsock->sock->backend_name, - io->in.dest_addr, io->in.dest_port); - if (dest == NULL) goto failed; - req = nbt_name_request_send(nbtsock, dest, 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 name query reply -*/ -_PUBLIC_ NTSTATUS nbt_name_query_recv(struct nbt_name_request *req, - TALLOC_CTX *mem_ctx, struct nbt_name_query *io) -{ - NTSTATUS status; - struct nbt_name_packet *packet; - int i; - - 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].dest->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 status; - } - - 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+1); - if (io->out.reply_addrs == NULL) { - talloc_free(req); - return NT_STATUS_NO_MEMORY; - } - - for (i=0;iout.num_addrs;i++) { - io->out.reply_addrs[i] = talloc_steal(io->out.reply_addrs, - packet->answers[0].rdata.netbios.addresses[i].ipaddr); - } - io->out.reply_addrs[i] = NULL; - - talloc_steal(mem_ctx, io->out.name.name); - talloc_steal(mem_ctx, io->out.name.scope); - - talloc_free(req); - - return NT_STATUS_OK; -} - -/** - wait for a name query reply -*/ -_PUBLIC_ NTSTATUS nbt_name_query(struct nbt_name_socket *nbtsock, - TALLOC_CTX *mem_ctx, struct nbt_name_query *io) -{ - struct nbt_name_request *req = nbt_name_query_send(nbtsock, io); - return nbt_name_query_recv(req, mem_ctx, io); -} - - -/** - send a nbt name status -*/ -_PUBLIC_ struct nbt_name_request *nbt_name_status_send(struct nbt_name_socket *nbtsock, - struct nbt_name_status *io) -{ - struct nbt_name_request *req; - struct nbt_name_packet *packet; - struct socket_address *dest; - - packet = talloc_zero(nbtsock, struct nbt_name_packet); - if (packet == NULL) return NULL; - - packet->qdcount = 1; - packet->operation = NBT_OPCODE_QUERY; - - 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_STATUS; - packet->questions[0].question_class = NBT_QCLASS_IP; - - dest = socket_address_from_strings(packet, nbtsock->sock->backend_name, - io->in.dest_addr, io->in.dest_port); - if (dest == NULL) goto failed; - req = nbt_name_request_send(nbtsock, dest, 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 name status reply -*/ -_PUBLIC_ NTSTATUS nbt_name_status_recv(struct nbt_name_request *req, - TALLOC_CTX *mem_ctx, struct nbt_name_status *io) -{ - NTSTATUS status; - struct nbt_name_packet *packet; - int i; - - 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].dest->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) { - talloc_free(req); - return NT_STATUS_INVALID_NETWORK_RESPONSE; - } - - io->out.name = packet->answers[0].name; - talloc_steal(mem_ctx, io->out.name.name); - talloc_steal(mem_ctx, io->out.name.scope); - - io->out.status = packet->answers[0].rdata.status; - talloc_steal(mem_ctx, io->out.status.names); - for (i=0;iout.status.num_names;i++) { - talloc_steal(io->out.status.names, io->out.status.names[i].name); - } - - - talloc_free(req); - - return NT_STATUS_OK; -} - -/** - wait for a name status reply -*/ -_PUBLIC_ NTSTATUS nbt_name_status(struct nbt_name_socket *nbtsock, - TALLOC_CTX *mem_ctx, struct nbt_name_status *io) -{ - struct nbt_name_request *req = nbt_name_status_send(nbtsock, io); - return nbt_name_status_recv(req, mem_ctx, io); -} - - diff --git a/source4/libcli/nbt/namerefresh.c b/source4/libcli/nbt/namerefresh.c deleted file mode 100644 index b939c97740..0000000000 --- a/source4/libcli/nbt/namerefresh.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - send out a name refresh 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 3 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, see . -*/ - -#include "includes.h" -#include "libcli/nbt/libnbt.h" -#include "libcli/nbt/nbt_proto.h" -#include "libcli/composite/composite.h" -#include "lib/socket/socket.h" -#include "param/param.h" - -/* - send a nbt name refresh request -*/ -struct nbt_name_request *nbt_name_refresh_send(struct nbt_name_socket *nbtsock, - struct nbt_name_refresh *io) -{ - struct nbt_name_request *req; - struct nbt_name_packet *packet; - struct socket_address *dest; - - packet = talloc_zero(nbtsock, struct nbt_name_packet); - if (packet == NULL) return NULL; - - packet->qdcount = 1; - packet->arcount = 1; - packet->operation = NBT_OPCODE_REFRESH; - 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 = io->in.ttl; - 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); - - dest = socket_address_from_strings(nbtsock, - nbtsock->sock->backend_name, - io->in.dest_addr, io->in.dest_port); - if (dest == NULL) goto failed; - req = nbt_name_request_send(nbtsock, dest, 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 refresh reply -*/ -_PUBLIC_ NTSTATUS nbt_name_refresh_recv(struct nbt_name_request *req, - TALLOC_CTX *mem_ctx, struct nbt_name_refresh *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].dest->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 refresh request -*/ -_PUBLIC_ NTSTATUS nbt_name_refresh(struct nbt_name_socket *nbtsock, - TALLOC_CTX *mem_ctx, struct nbt_name_refresh *io) -{ - struct nbt_name_request *req = nbt_name_refresh_send(nbtsock, io); - return nbt_name_refresh_recv(req, mem_ctx, io); -} - - - -/** - a wins name refresh with multiple WINS servers and multiple - addresses to refresh. Try each WINS server in turn, until we get a - reply for each address -*/ -struct refresh_wins_state { - struct nbt_name_socket *nbtsock; - struct nbt_name_refresh *io; - const char **wins_servers; - uint16_t wins_port; - const char **addresses; - int address_idx; - struct nbt_name_request *req; -}; - - -/** - state handler for WINS multi-homed multi-server name refresh -*/ -static void name_refresh_wins_handler(struct nbt_name_request *req) -{ - struct composite_context *c = talloc_get_type(req->async.private_data, - struct composite_context); - struct refresh_wins_state *state = talloc_get_type(c->private_data, - struct refresh_wins_state); - NTSTATUS status; - - status = nbt_name_refresh_recv(state->req, state, state->io); - if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { - /* the refresh timed out - try the next WINS server */ - state->wins_servers++; - state->address_idx = 0; - if (state->wins_servers[0] == NULL) { - c->state = COMPOSITE_STATE_ERROR; - c->status = status; - goto done; - } - state->io->in.dest_addr = state->wins_servers[0]; - state->io->in.dest_port = state->wins_port; - state->io->in.address = state->addresses[0]; - state->req = nbt_name_refresh_send(state->nbtsock, state->io); - if (state->req == NULL) { - c->state = COMPOSITE_STATE_ERROR; - c->status = NT_STATUS_NO_MEMORY; - } else { - state->req->async.fn = name_refresh_wins_handler; - state->req->async.private_data = c; - } - } else if (!NT_STATUS_IS_OK(status)) { - c->state = COMPOSITE_STATE_ERROR; - c->status = status; - } else { - if (state->io->out.rcode == 0 && - state->addresses[state->address_idx+1] != NULL) { - /* refresh our next address */ - state->io->in.address = state->addresses[++(state->address_idx)]; - state->req = nbt_name_refresh_send(state->nbtsock, state->io); - if (state->req == NULL) { - c->state = COMPOSITE_STATE_ERROR; - c->status = NT_STATUS_NO_MEMORY; - } else { - state->req->async.fn = name_refresh_wins_handler; - state->req->async.private_data = c; - } - } else { - c->state = COMPOSITE_STATE_DONE; - c->status = NT_STATUS_OK; - } - } - -done: - if (c->state >= COMPOSITE_STATE_DONE && - c->async.fn) { - c->async.fn(c); - } -} - -/** - the async send call for a multi-server WINS refresh -*/ -_PUBLIC_ struct composite_context *nbt_name_refresh_wins_send(struct nbt_name_socket *nbtsock, - struct nbt_name_refresh_wins *io) -{ - struct composite_context *c; - struct refresh_wins_state *state; - - c = talloc_zero(nbtsock, struct composite_context); - if (c == NULL) goto failed; - - state = talloc(c, struct refresh_wins_state); - if (state == NULL) goto failed; - - state->io = talloc(state, struct nbt_name_refresh); - if (state->io == NULL) goto failed; - - state->wins_port = io->in.wins_port; - state->wins_servers = str_list_copy(state, io->in.wins_servers); - if (state->wins_servers == NULL || - state->wins_servers[0] == NULL) goto failed; - - state->addresses = str_list_copy(state, io->in.addresses); - if (state->addresses == NULL || - state->addresses[0] == NULL) goto failed; - - state->io->in.name = io->in.name; - state->io->in.dest_addr = state->wins_servers[0]; - state->io->in.dest_port = state->wins_port; - state->io->in.address = io->in.addresses[0]; - state->io->in.nb_flags = io->in.nb_flags; - state->io->in.broadcast = false; - state->io->in.ttl = io->in.ttl; - state->io->in.timeout = 2; - state->io->in.retries = 2; - - state->nbtsock = nbtsock; - state->address_idx = 0; - - state->req = nbt_name_refresh_send(nbtsock, state->io); - if (state->req == NULL) goto failed; - - state->req->async.fn = name_refresh_wins_handler; - state->req->async.private_data = c; - - c->private_data = state; - c->state = COMPOSITE_STATE_IN_PROGRESS; - c->event_ctx = nbtsock->event_ctx; - - return c; - -failed: - talloc_free(c); - return NULL; -} - -/* - multi-homed WINS name refresh - recv side -*/ -_PUBLIC_ NTSTATUS nbt_name_refresh_wins_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, - struct nbt_name_refresh_wins *io) -{ - NTSTATUS status; - status = composite_wait(c); - if (NT_STATUS_IS_OK(status)) { - struct refresh_wins_state *state = - talloc_get_type(c->private_data, struct refresh_wins_state); - io->out.wins_server = talloc_steal(mem_ctx, state->wins_servers[0]); - io->out.rcode = state->io->out.rcode; - } - talloc_free(c); - return status; -} - -/* - multi-homed WINS refresh - sync interface -*/ -_PUBLIC_ NTSTATUS nbt_name_refresh_wins(struct nbt_name_socket *nbtsock, - TALLOC_CTX *mem_ctx, - struct nbt_name_refresh_wins *io) -{ - struct composite_context *c = nbt_name_refresh_wins_send(nbtsock, io); - return nbt_name_refresh_wins_recv(c, mem_ctx, io); -} diff --git a/source4/libcli/nbt/nameregister.c b/source4/libcli/nbt/nameregister.c deleted file mode 100644 index c50f9b3b3a..0000000000 --- a/source4/libcli/nbt/nameregister.c +++ /dev/null @@ -1,442 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - send out a name registration 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 3 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, see . -*/ - -#include "includes.h" -#include "libcli/nbt/libnbt.h" -#include "libcli/nbt/nbt_proto.h" -#include "libcli/composite/composite.h" -#include "lib/socket/socket.h" -#include "librpc/gen_ndr/ndr_nbt.h" -#include "param/param.h" - -/* - send a nbt name registration request -*/ -struct nbt_name_request *nbt_name_register_send(struct nbt_name_socket *nbtsock, - struct nbt_name_register *io) -{ - struct nbt_name_request *req; - struct nbt_name_packet *packet; - struct socket_address *dest; - - packet = talloc_zero(nbtsock, struct nbt_name_packet); - if (packet == NULL) return NULL; - - packet->qdcount = 1; - packet->arcount = 1; - if (io->in.multi_homed) { - packet->operation = NBT_OPCODE_MULTI_HOME_REG; - } else { - packet->operation = NBT_OPCODE_REGISTER; - } - if (io->in.broadcast) { - packet->operation |= NBT_FLAG_BROADCAST; - } - if (io->in.register_demand) { - packet->operation |= NBT_FLAG_RECURSION_DESIRED; - } - - 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 = io->in.ttl; - 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); - if (packet->additional[0].rdata.netbios.addresses[0].ipaddr == NULL) goto failed; - - dest = socket_address_from_strings(packet, nbtsock->sock->backend_name, - io->in.dest_addr, io->in.dest_port); - if (dest == NULL) goto failed; - req = nbt_name_request_send(nbtsock, dest, 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 registration reply -*/ -_PUBLIC_ NTSTATUS nbt_name_register_recv(struct nbt_name_request *req, - TALLOC_CTX *mem_ctx, struct nbt_name_register *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].dest->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 registration request -*/ -_PUBLIC_ NTSTATUS nbt_name_register(struct nbt_name_socket *nbtsock, - TALLOC_CTX *mem_ctx, struct nbt_name_register *io) -{ - struct nbt_name_request *req = nbt_name_register_send(nbtsock, io); - return nbt_name_register_recv(req, mem_ctx, io); -} - - -/* - a 4 step broadcast registration. 3 lots of name registration requests, followed by - a name registration demand -*/ -struct register_bcast_state { - struct nbt_name_socket *nbtsock; - struct nbt_name_register *io; - struct nbt_name_request *req; -}; - - -/* - state handler for 4 stage name registration -*/ -static void name_register_bcast_handler(struct nbt_name_request *req) -{ - struct composite_context *c = talloc_get_type(req->async.private_data, struct composite_context); - struct register_bcast_state *state = talloc_get_type(c->private_data, struct register_bcast_state); - NTSTATUS status; - - status = nbt_name_register_recv(state->req, state, state->io); - if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { - if (state->io->in.register_demand == true) { - /* all done */ - c->state = COMPOSITE_STATE_DONE; - c->status = NT_STATUS_OK; - goto done; - } - - /* the registration timed out - good, send the demand */ - state->io->in.register_demand = true; - state->io->in.retries = 0; - state->req = nbt_name_register_send(state->nbtsock, state->io); - if (state->req == NULL) { - c->state = COMPOSITE_STATE_ERROR; - c->status = NT_STATUS_NO_MEMORY; - } else { - state->req->async.fn = name_register_bcast_handler; - state->req->async.private_data = c; - } - } else if (!NT_STATUS_IS_OK(status)) { - c->state = COMPOSITE_STATE_ERROR; - c->status = status; - } else { - c->state = COMPOSITE_STATE_ERROR; - c->status = NT_STATUS_CONFLICTING_ADDRESSES; - DEBUG(3,("Name registration conflict from %s for %s with ip %s - rcode %d\n", - state->io->out.reply_from, - nbt_name_string(state, &state->io->out.name), - state->io->out.reply_addr, - state->io->out.rcode)); - } - -done: - if (c->state >= COMPOSITE_STATE_DONE && - c->async.fn) { - c->async.fn(c); - } -} - -/* - the async send call for a 4 stage name registration -*/ -_PUBLIC_ struct composite_context *nbt_name_register_bcast_send(struct nbt_name_socket *nbtsock, - struct nbt_name_register_bcast *io) -{ - struct composite_context *c; - struct register_bcast_state *state; - - c = talloc_zero(nbtsock, struct composite_context); - if (c == NULL) goto failed; - - state = talloc(c, struct register_bcast_state); - if (state == NULL) goto failed; - - state->io = talloc(state, struct nbt_name_register); - if (state->io == NULL) goto failed; - - state->io->in.name = io->in.name; - state->io->in.dest_addr = io->in.dest_addr; - state->io->in.dest_port = io->in.dest_port; - state->io->in.address = io->in.address; - state->io->in.nb_flags = io->in.nb_flags; - state->io->in.register_demand = false; - state->io->in.broadcast = true; - state->io->in.multi_homed = false; - state->io->in.ttl = io->in.ttl; - state->io->in.timeout = 1; - state->io->in.retries = 2; - - state->nbtsock = nbtsock; - - state->req = nbt_name_register_send(nbtsock, state->io); - if (state->req == NULL) goto failed; - - state->req->async.fn = name_register_bcast_handler; - state->req->async.private_data = c; - - c->private_data = state; - c->state = COMPOSITE_STATE_IN_PROGRESS; - c->event_ctx = nbtsock->event_ctx; - - return c; - -failed: - talloc_free(c); - return NULL; -} - -/* - broadcast 4 part name register - recv -*/ -_PUBLIC_ NTSTATUS nbt_name_register_bcast_recv(struct composite_context *c) -{ - NTSTATUS status; - status = composite_wait(c); - talloc_free(c); - return status; -} - -/* - broadcast 4 part name register - sync interface -*/ -NTSTATUS nbt_name_register_bcast(struct nbt_name_socket *nbtsock, - struct nbt_name_register_bcast *io) -{ - struct composite_context *c = nbt_name_register_bcast_send(nbtsock, io); - return nbt_name_register_bcast_recv(c); -} - - -/* - a wins name register with multiple WINS servers and multiple - addresses to register. Try each WINS server in turn, until we get a - reply for each address -*/ -struct register_wins_state { - struct nbt_name_socket *nbtsock; - struct nbt_name_register *io; - const char **wins_servers; - uint16_t wins_port; - const char **addresses; - int address_idx; - struct nbt_name_request *req; -}; - - -/* - state handler for WINS multi-homed multi-server name register -*/ -static void name_register_wins_handler(struct nbt_name_request *req) -{ - struct composite_context *c = talloc_get_type(req->async.private_data, - struct composite_context); - struct register_wins_state *state = talloc_get_type(c->private_data, - struct register_wins_state); - NTSTATUS status; - - status = nbt_name_register_recv(state->req, state, state->io); - if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { - /* the register timed out - try the next WINS server */ - state->wins_servers++; - state->address_idx = 0; - if (state->wins_servers[0] == NULL) { - c->state = COMPOSITE_STATE_ERROR; - c->status = status; - goto done; - } - state->io->in.dest_addr = state->wins_servers[0]; - state->io->in.dest_port = state->wins_port; - state->io->in.address = state->addresses[0]; - state->req = nbt_name_register_send(state->nbtsock, state->io); - if (state->req == NULL) { - c->state = COMPOSITE_STATE_ERROR; - c->status = NT_STATUS_NO_MEMORY; - } else { - state->req->async.fn = name_register_wins_handler; - state->req->async.private_data = c; - } - } else if (!NT_STATUS_IS_OK(status)) { - c->state = COMPOSITE_STATE_ERROR; - c->status = status; - } else { - if (state->io->out.rcode == 0 && - state->addresses[state->address_idx+1] != NULL) { - /* register our next address */ - state->io->in.address = state->addresses[++(state->address_idx)]; - state->req = nbt_name_register_send(state->nbtsock, state->io); - if (state->req == NULL) { - c->state = COMPOSITE_STATE_ERROR; - c->status = NT_STATUS_NO_MEMORY; - } else { - state->req->async.fn = name_register_wins_handler; - state->req->async.private_data = c; - } - } else { - c->state = COMPOSITE_STATE_DONE; - c->status = NT_STATUS_OK; - } - } - -done: - if (c->state >= COMPOSITE_STATE_DONE && - c->async.fn) { - c->async.fn(c); - } -} - -/* - the async send call for a multi-server WINS register -*/ -_PUBLIC_ struct composite_context *nbt_name_register_wins_send(struct nbt_name_socket *nbtsock, - struct nbt_name_register_wins *io) -{ - struct composite_context *c; - struct register_wins_state *state; - - c = talloc_zero(nbtsock, struct composite_context); - if (c == NULL) goto failed; - - state = talloc(c, struct register_wins_state); - if (state == NULL) goto failed; - - state->io = talloc(state, struct nbt_name_register); - if (state->io == NULL) goto failed; - - state->wins_port = io->in.wins_port; - state->wins_servers = str_list_copy(state, io->in.wins_servers); - if (state->wins_servers == NULL || - state->wins_servers[0] == NULL) goto failed; - - state->addresses = str_list_copy(state, io->in.addresses); - if (state->addresses == NULL || - state->addresses[0] == NULL) goto failed; - - state->io->in.name = io->in.name; - state->io->in.dest_addr = state->wins_servers[0]; - state->io->in.dest_port = state->wins_port; - state->io->in.address = io->in.addresses[0]; - state->io->in.nb_flags = io->in.nb_flags; - state->io->in.broadcast = false; - state->io->in.register_demand = false; - state->io->in.multi_homed = (io->in.nb_flags & NBT_NM_GROUP)?false:true; - state->io->in.ttl = io->in.ttl; - state->io->in.timeout = 3; - state->io->in.retries = 2; - - state->nbtsock = nbtsock; - state->address_idx = 0; - - state->req = nbt_name_register_send(nbtsock, state->io); - if (state->req == NULL) goto failed; - - state->req->async.fn = name_register_wins_handler; - state->req->async.private_data = c; - - c->private_data = state; - c->state = COMPOSITE_STATE_IN_PROGRESS; - c->event_ctx = nbtsock->event_ctx; - - return c; - -failed: - talloc_free(c); - return NULL; -} - -/* - multi-homed WINS name register - recv side -*/ -_PUBLIC_ NTSTATUS nbt_name_register_wins_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, - struct nbt_name_register_wins *io) -{ - NTSTATUS status; - status = composite_wait(c); - if (NT_STATUS_IS_OK(status)) { - struct register_wins_state *state = - talloc_get_type(c->private_data, struct register_wins_state); - io->out.wins_server = talloc_steal(mem_ctx, state->wins_servers[0]); - io->out.rcode = state->io->out.rcode; - } - talloc_free(c); - return status; -} - -/* - multi-homed WINS register - sync interface -*/ -_PUBLIC_ NTSTATUS nbt_name_register_wins(struct nbt_name_socket *nbtsock, - TALLOC_CTX *mem_ctx, - struct nbt_name_register_wins *io) -{ - struct composite_context *c = nbt_name_register_wins_send(nbtsock, io); - return nbt_name_register_wins_recv(c, mem_ctx, io); -} diff --git a/source4/libcli/nbt/namerelease.c b/source4/libcli/nbt/namerelease.c deleted file mode 100644 index ba3af41752..0000000000 --- a/source4/libcli/nbt/namerelease.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - 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 3 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, see . -*/ - -#include "includes.h" -#include "libcli/nbt/libnbt.h" -#include "libcli/nbt/nbt_proto.h" -#include "lib/socket/socket.h" -#include "param/param.h" - -/* - send a nbt name release request -*/ -_PUBLIC_ 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; - struct socket_address *dest; - - 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); - - dest = socket_address_from_strings(packet, nbtsock->sock->backend_name, - io->in.dest_addr, io->in.dest_port); - if (dest == NULL) goto failed; - req = nbt_name_request_send(nbtsock, dest, 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 -*/ -_PUBLIC_ 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].dest->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 -*/ -_PUBLIC_ 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); -} diff --git a/source4/libcli/nbt/nbtname.c b/source4/libcli/nbt/nbtname.c deleted file mode 100644 index 338cb21089..0000000000 --- a/source4/libcli/nbt/nbtname.c +++ /dev/null @@ -1,648 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - manipulate nbt name structures - - 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 3 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, see . -*/ - -/* - see rfc1002 for the detailed format of compressed names -*/ - -#include "includes.h" -#include "librpc/gen_ndr/ndr_nbt.h" -#include "librpc/gen_ndr/ndr_misc.h" -#include "system/locale.h" - -/* don't allow an unlimited number of name components */ -#define MAX_COMPONENTS 10 - -/** - print a nbt string -*/ -_PUBLIC_ void ndr_print_nbt_string(struct ndr_print *ndr, const char *name, const char *s) -{ - ndr_print_string(ndr, name, s); -} - -/* - pull one component of a nbt_string -*/ -static enum ndr_err_code ndr_pull_component(struct ndr_pull *ndr, - uint8_t **component, - uint32_t *offset, - uint32_t *max_offset) -{ - uint8_t len; - uint_t loops = 0; - while (loops < 5) { - if (*offset >= ndr->data_size) { - return ndr_pull_error(ndr, NDR_ERR_STRING, - "BAD NBT NAME component"); - } - len = ndr->data[*offset]; - if (len == 0) { - *offset += 1; - *max_offset = MAX(*max_offset, *offset); - *component = NULL; - return NDR_ERR_SUCCESS; - } - if ((len & 0xC0) == 0xC0) { - /* its a label pointer */ - if (1 + *offset >= ndr->data_size) { - return ndr_pull_error(ndr, NDR_ERR_STRING, - "BAD NBT NAME component"); - } - *max_offset = MAX(*max_offset, *offset + 2); - *offset = ((len&0x3F)<<8) | ndr->data[1 + *offset]; - *max_offset = MAX(*max_offset, *offset); - loops++; - continue; - } - if ((len & 0xC0) != 0) { - /* its a reserved length field */ - return ndr_pull_error(ndr, NDR_ERR_STRING, - "BAD NBT NAME component"); - } - if (*offset + len + 2 > ndr->data_size) { - return ndr_pull_error(ndr, NDR_ERR_STRING, - "BAD NBT NAME component"); - } - *component = (uint8_t*)talloc_strndup(ndr, (const char *)&ndr->data[1 + *offset], len); - NDR_ERR_HAVE_NO_MEMORY(*component); - *offset += len + 1; - *max_offset = MAX(*max_offset, *offset); - return NDR_ERR_SUCCESS; - } - - /* too many pointers */ - return ndr_pull_error(ndr, NDR_ERR_STRING, "BAD NBT NAME component"); -} - -/** - pull a nbt_string from the wire -*/ -_PUBLIC_ enum ndr_err_code ndr_pull_nbt_string(struct ndr_pull *ndr, int ndr_flags, const char **s) -{ - uint32_t offset = ndr->offset; - uint32_t max_offset = offset; - unsigned num_components; - char *name; - - if (!(ndr_flags & NDR_SCALARS)) { - return NDR_ERR_SUCCESS; - } - - name = NULL; - - /* break up name into a list of components */ - for (num_components=0;num_componentsoffset = max_offset; - - return NDR_ERR_SUCCESS; -} - -/** - push a nbt string to the wire -*/ -_PUBLIC_ enum ndr_err_code ndr_push_nbt_string(struct ndr_push *ndr, int ndr_flags, const char *s) -{ - if (!(ndr_flags & NDR_SCALARS)) { - return NDR_ERR_SUCCESS; - } - - while (s && *s) { - enum ndr_err_code ndr_err; - char *compname; - size_t complen; - uint32_t offset; - - /* see if we have pushed the remaing string allready, - * if so we use a label pointer to this string - */ - ndr_err = ndr_token_retrieve_cmp_fn(&ndr->nbt_string_list, s, &offset, (comparison_fn_t)strcmp, false); - if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - uint8_t b[2]; - - if (offset > 0x3FFF) { - return ndr_push_error(ndr, NDR_ERR_STRING, - "offset for nbt string label pointer %u[%08X] > 0x00003FFF", - offset, offset); - } - - b[0] = 0xC0 | (offset>>8); - b[1] = (offset & 0xFF); - - return ndr_push_bytes(ndr, b, 2); - } - - complen = strcspn(s, "."); - - /* we need to make sure the length fits into 6 bytes */ - if (complen >= 0x3F) { - return ndr_push_error(ndr, NDR_ERR_STRING, - "component length %u[%08X] > 0x00003F", - (unsigned)complen, (unsigned)complen); - } - - compname = talloc_asprintf(ndr, "%c%*.*s", - (unsigned char)complen, - (unsigned char)complen, - (unsigned char)complen, s); - NDR_ERR_HAVE_NO_MEMORY(compname); - - /* remember the current componemt + the rest of the string - * so it can be reused later - */ - NDR_CHECK(ndr_token_store(ndr, &ndr->nbt_string_list, s, ndr->offset)); - - /* push just this component into the blob */ - NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)compname, complen+1)); - talloc_free(compname); - - s += complen; - if (*s == '.') s++; - } - - /* if we reach the end of the string and have pushed the last component - * without using a label pointer, we need to terminate the string - */ - return ndr_push_bytes(ndr, (const uint8_t *)"", 1); -} - - -/* - decompress a 'compressed' name component - */ -static bool decompress_name(char *name, enum nbt_name_type *type) -{ - int i; - for (i=0;name[2*i];i++) { - uint8_t c1 = name[2*i]; - uint8_t c2 = name[1+(2*i)]; - if (c1 < 'A' || c1 > 'P' || - c2 < 'A' || c2 > 'P') { - return false; - } - name[i] = ((c1-'A')<<4) | (c2-'A'); - } - name[i] = 0; - if (i == 16) { - *type = (enum nbt_name_type)(name[15]); - name[15] = 0; - i--; - } else { - *type = NBT_NAME_CLIENT; - } - - /* trim trailing spaces */ - for (;i>0 && name[i-1]==' ';i--) { - name[i-1] = 0; - } - - return true; -} - - -/* - compress a name component - */ -static uint8_t *compress_name(TALLOC_CTX *mem_ctx, - const uint8_t *name, enum nbt_name_type type) -{ - uint8_t *cname; - int i; - uint8_t pad_char; - - if (strlen((const char *)name) > 15) { - return NULL; - } - - cname = talloc_array(mem_ctx, uint8_t, 33); - if (cname == NULL) return NULL; - - for (i=0;name[i];i++) { - cname[2*i] = 'A' + (name[i]>>4); - cname[1+2*i] = 'A' + (name[i]&0xF); - } - if (strcmp((const char *)name, "*") == 0) { - pad_char = 0; - } else { - pad_char = ' '; - } - for (;i<15;i++) { - cname[2*i] = 'A' + (pad_char>>4); - cname[1+2*i] = 'A' + (pad_char&0xF); - } - - pad_char = type; - cname[2*i] = 'A' + (pad_char>>4); - cname[1+2*i] = 'A' + (pad_char&0xF); - - cname[32] = 0; - return cname; -} - - -/** - pull a nbt name from the wire -*/ -_PUBLIC_ enum ndr_err_code ndr_pull_nbt_name(struct ndr_pull *ndr, int ndr_flags, struct nbt_name *r) -{ - uint8_t *scope; - char *cname; - const char *s; - bool ok; - - if (!(ndr_flags & NDR_SCALARS)) { - return NDR_ERR_SUCCESS; - } - - NDR_CHECK(ndr_pull_nbt_string(ndr, ndr_flags, &s)); - - scope = (uint8_t *)strchr(s, '.'); - if (scope) { - *scope = 0; - r->scope = talloc_strdup(ndr->current_mem_ctx, (const char *)&scope[1]); - NDR_ERR_HAVE_NO_MEMORY(r->scope); - } else { - r->scope = NULL; - } - - cname = discard_const_p(char, s); - - /* the first component is limited to 16 bytes in the DOS charset, - which is 32 in the 'compressed' form */ - if (strlen(cname) > 32) { - return ndr_pull_error(ndr, NDR_ERR_STRING, - "NBT NAME cname > 32"); - } - - /* decompress the first component */ - ok = decompress_name(cname, &r->type); - if (!ok) { - return ndr_pull_error(ndr, NDR_ERR_STRING, - "NBT NAME failed to decompress"); - } - - r->name = talloc_strdup(ndr->current_mem_ctx, cname); - NDR_ERR_HAVE_NO_MEMORY(r->name); - - talloc_free(cname); - - return NDR_ERR_SUCCESS; -} - -/** - push a nbt name to the wire -*/ -_PUBLIC_ enum ndr_err_code ndr_push_nbt_name(struct ndr_push *ndr, int ndr_flags, const struct nbt_name *r) -{ - uint8_t *cname, *fullname; - enum ndr_err_code ndr_err; - - if (!(ndr_flags & NDR_SCALARS)) { - return NDR_ERR_SUCCESS; - } - - if (strlen(r->name) > 15) { - return ndr_push_error(ndr, NDR_ERR_STRING, - "nbt_name longer as 15 chars: %s", - r->name); - } - - cname = compress_name(ndr, (const uint8_t *)r->name, r->type); - NDR_ERR_HAVE_NO_MEMORY(cname); - - if (r->scope) { - fullname = (uint8_t *)talloc_asprintf(ndr, "%s.%s", cname, r->scope); - NDR_ERR_HAVE_NO_MEMORY(fullname); - talloc_free(cname); - } else { - fullname = cname; - } - - ndr_err = ndr_push_nbt_string(ndr, ndr_flags, (const char *)fullname); - - return ndr_err; -} - - -/** - copy a nbt name structure -*/ -_PUBLIC_ 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 -*/ -_PUBLIC_ NTSTATUS nbt_name_to_blob(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience, DATA_BLOB *blob, struct nbt_name *name) -{ - enum ndr_err_code ndr_err; - - ndr_err = ndr_push_struct_blob(blob, mem_ctx, iconv_convenience, name, (ndr_push_flags_fn_t)ndr_push_nbt_name); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - return ndr_map_error2ntstatus(ndr_err); - } - - return NT_STATUS_OK; -} - -/** - pull a nbt name from a blob -*/ -_PUBLIC_ NTSTATUS nbt_name_from_blob(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, struct nbt_name *name) -{ - enum ndr_err_code ndr_err; - - ndr_err = ndr_pull_struct_blob(blob, mem_ctx, NULL, name, - (ndr_pull_flags_fn_t)ndr_pull_nbt_name); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - return ndr_map_error2ntstatus(ndr_err); - } - - return NT_STATUS_OK; -} - - -/** - 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 -*/ -_PUBLIC_ 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 ((name == NULL) || is_ipaddress(name)) { - n->name = "*SMBSERVER"; - return; - } - if (strlen(name) > 15) { - const char *p = strchr(name, '.'); - char *s; - if (p - name > 15) { - n->name = "*SMBSERVER"; - return; - } - s = talloc_strndup(mem_ctx, name, PTR_DIFF(p, name)); - n->name = talloc_strdup_upper(mem_ctx, s); - return; - } - - n->name = talloc_strdup_upper(mem_ctx, name); -} - - -/* - escape a string into a form containing only a small set of characters, - the rest is hex encoded. This is similar to URL encoding -*/ -static const char *nbt_hex_encode(TALLOC_CTX *mem_ctx, const char *s) -{ - int i, len; - char *ret; - const char *valid_chars = "_-.$@ "; -#define NBT_CHAR_ALLOW(c) (isalnum((unsigned char)c) || strchr(valid_chars, c)) - - for (len=i=0;s[i];i++,len++) { - if (!NBT_CHAR_ALLOW(s[i])) { - len += 2; - } - } - - ret = talloc_array(mem_ctx, char, len+1); - if (ret == NULL) return NULL; - - for (len=i=0;s[i];i++) { - if (NBT_CHAR_ALLOW(s[i])) { - ret[len++] = s[i]; - } else { - snprintf(&ret[len], 4, "%%%02x", (unsigned char)s[i]); - len += 3; - } - } - ret[len] = 0; - - return ret; -} - - -/** - form a string for a NBT name -*/ -_PUBLIC_ char *nbt_name_string(TALLOC_CTX *mem_ctx, const struct nbt_name *name) -{ - TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); - char *ret; - if (name->scope) { - ret = talloc_asprintf(mem_ctx, "%s<%02x>-%s", - nbt_hex_encode(tmp_ctx, name->name), - name->type, - nbt_hex_encode(tmp_ctx, name->scope)); - } else { - ret = talloc_asprintf(mem_ctx, "%s<%02x>", - nbt_hex_encode(tmp_ctx, name->name), - name->type); - } - talloc_free(tmp_ctx); - return ret; -} - -/** - pull a nbt name, WINS Replication uses another on wire format for nbt name -*/ -_PUBLIC_ enum ndr_err_code ndr_pull_wrepl_nbt_name(struct ndr_pull *ndr, int ndr_flags, const struct nbt_name **_r) -{ - struct nbt_name *r; - uint8_t *namebuf; - uint32_t namebuf_len; - - if (!(ndr_flags & NDR_SCALARS)) { - return NDR_ERR_SUCCESS; - } - - NDR_CHECK(ndr_pull_align(ndr, 4)); - NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &namebuf_len)); - if (namebuf_len < 1 || namebuf_len > 255) { - return ndr_pull_error(ndr, NDR_ERR_ALLOC, "value out of range"); - } - NDR_PULL_ALLOC_N(ndr, namebuf, namebuf_len); - NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, namebuf, namebuf_len)); - - NDR_PULL_ALLOC(ndr, r); - - /* oh wow, what a nasty bug in windows ... */ - if (namebuf[0] == 0x1b && namebuf_len >= 16) { - namebuf[0] = namebuf[15]; - namebuf[15] = 0x1b; - } - - if (namebuf_len < 17) { - r->type = 0x00; - - r->name = talloc_strndup(r, (char *)namebuf, namebuf_len); - if (!r->name) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "out of memory"); - - r->scope= NULL; - - talloc_free(namebuf); - *_r = r; - return NDR_ERR_SUCCESS; - } - - r->type = namebuf[15]; - - namebuf[15] = '\0'; - trim_string((char *)namebuf, NULL, " "); - r->name = talloc_strdup(r, (char *)namebuf); - if (!r->name) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "out of memory"); - - if (namebuf_len > 18) { - r->scope = talloc_strndup(r, (char *)(namebuf+17), namebuf_len-17); - if (!r->scope) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "out of memory"); - } else { - r->scope = NULL; - } - - talloc_free(namebuf); - *_r = r; - return NDR_ERR_SUCCESS; -} - -/** - push a nbt name, WINS Replication uses another on wire format for nbt name -*/ -_PUBLIC_ enum ndr_err_code ndr_push_wrepl_nbt_name(struct ndr_push *ndr, int ndr_flags, const struct nbt_name *r) -{ - uint8_t *namebuf; - uint32_t namebuf_len; - uint32_t _name_len; - uint32_t scope_len = 0; - - if (r == NULL) { - return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, - "wrepl_nbt_name NULL pointer"); - } - - if (!(ndr_flags & NDR_SCALARS)) { - return NDR_ERR_SUCCESS; - } - - _name_len = strlen(r->name); - if (_name_len > 15) { - return ndr_push_error(ndr, NDR_ERR_STRING, - "wrepl_nbt_name longer as 15 chars: %s", - r->name); - } - - if (r->scope) { - scope_len = strlen(r->scope); - } - if (scope_len > 238) { - return ndr_push_error(ndr, NDR_ERR_STRING, - "wrepl_nbt_name scope longer as 238 chars: %s", - r->scope); - } - - namebuf = (uint8_t *)talloc_asprintf(ndr, "%-15s%c%s", - r->name, 'X', - (r->scope?r->scope:"")); - if (!namebuf) return ndr_push_error(ndr, NDR_ERR_ALLOC, "out of memory"); - - namebuf_len = strlen((char *)namebuf) + 1; - - /* - * we need to set the type here, and use a place-holder in the talloc_asprintf() - * as the type can be 0x00, and then the namebuf_len = strlen(namebuf); would give wrong results - */ - namebuf[15] = r->type; - - /* oh wow, what a nasty bug in windows ... */ - if (r->type == 0x1b) { - namebuf[15] = namebuf[0]; - namebuf[0] = 0x1b; - } - - NDR_CHECK(ndr_push_align(ndr, 4)); - NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, namebuf_len)); - NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, namebuf, namebuf_len)); - - talloc_free(namebuf); - return NDR_ERR_SUCCESS; -} - -_PUBLIC_ void ndr_print_wrepl_nbt_name(struct ndr_print *ndr, const char *name, const struct nbt_name *r) -{ - char *s = nbt_name_string(ndr, r); - ndr_print_string(ndr, name, s); - talloc_free(s); -} - -_PUBLIC_ enum ndr_err_code ndr_push_nbt_res_rec(struct ndr_push *ndr, int ndr_flags, const struct nbt_res_rec *r) -{ - { - uint32_t _flags_save_STRUCT = ndr->flags; - ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX); - if (ndr_flags & NDR_SCALARS) { - NDR_CHECK(ndr_push_align(ndr, 4)); - NDR_CHECK(ndr_push_nbt_name(ndr, NDR_SCALARS, &r->name)); - NDR_CHECK(ndr_push_nbt_qtype(ndr, NDR_SCALARS, r->rr_type)); - NDR_CHECK(ndr_push_nbt_qclass(ndr, NDR_SCALARS, r->rr_class)); - NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->ttl)); - NDR_CHECK(ndr_push_set_switch_value(ndr, &r->rdata, ((((r->rr_type) == NBT_QTYPE_NETBIOS) && ((r->rdata).data.length == 2))?0:r->rr_type))); - NDR_CHECK(ndr_push_nbt_rdata(ndr, NDR_SCALARS, &r->rdata)); - } - if (ndr_flags & NDR_BUFFERS) { - } - ndr->flags = _flags_save_STRUCT; - } - return NDR_ERR_SUCCESS; -} diff --git a/source4/libcli/nbt/nbtsocket.c b/source4/libcli/nbt/nbtsocket.c deleted file mode 100644 index 49f175b8a3..0000000000 --- a/source4/libcli/nbt/nbtsocket.c +++ /dev/null @@ -1,521 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - low level socket handling for nbt requests - - 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 3 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, see . -*/ - -#include "includes.h" -#include "lib/events/events.h" -#include "lib/util/dlinklist.h" -#include "libcli/nbt/libnbt.h" -#include "lib/socket/socket.h" -#include "librpc/gen_ndr/ndr_nbt.h" -#include "param/param.h" - -#define NBT_MAX_REPLIES 1000 - -/* - destroy a pending request -*/ -static int nbt_name_request_destructor(struct nbt_name_request *req) -{ - if (req->state == NBT_REQUEST_SEND) { - DLIST_REMOVE(req->nbtsock->send_queue, req); - } - if (req->state == NBT_REQUEST_WAIT) { - req->nbtsock->num_pending--; - } - if (req->name_trn_id != 0 && !req->is_reply) { - idr_remove(req->nbtsock->idr, req->name_trn_id); - req->name_trn_id = 0; - } - if (req->te) { - talloc_free(req->te); - req->te = NULL; - } - if (req->nbtsock->send_queue == NULL) { - EVENT_FD_NOT_WRITEABLE(req->nbtsock->fde); - } - if (req->nbtsock->num_pending == 0 && - req->nbtsock->incoming.handler == NULL) { - EVENT_FD_NOT_READABLE(req->nbtsock->fde); - } - return 0; -} - - -/* - handle send events on a nbt name socket -*/ -static void nbt_name_socket_send(struct nbt_name_socket *nbtsock) -{ - struct nbt_name_request *req = nbtsock->send_queue; - TALLOC_CTX *tmp_ctx = talloc_new(nbtsock); - NTSTATUS status; - - while ((req = nbtsock->send_queue)) { - size_t len; - - len = req->encoded.length; - status = socket_sendto(nbtsock->sock, &req->encoded, &len, - req->dest); - if (NT_STATUS_IS_ERR(status)) goto failed; - - if (!NT_STATUS_IS_OK(status)) { - talloc_free(tmp_ctx); - return; - } - - DLIST_REMOVE(nbtsock->send_queue, req); - req->state = NBT_REQUEST_WAIT; - if (req->is_reply) { - talloc_free(req); - } else { - EVENT_FD_READABLE(nbtsock->fde); - nbtsock->num_pending++; - } - } - - EVENT_FD_NOT_WRITEABLE(nbtsock->fde); - talloc_free(tmp_ctx); - return; - -failed: - DLIST_REMOVE(nbtsock->send_queue, req); - nbt_name_request_destructor(req); - req->status = status; - req->state = NBT_REQUEST_ERROR; - talloc_free(tmp_ctx); - if (req->async.fn) { - req->async.fn(req); - } else if (req->is_reply) { - talloc_free(req); - } - return; -} - - -/* - handle a request timeout -*/ -static void nbt_name_socket_timeout(struct event_context *ev, struct timed_event *te, - struct timeval t, void *private) -{ - struct nbt_name_request *req = talloc_get_type(private, - struct nbt_name_request); - - if (req->num_retries != 0) { - req->num_retries--; - req->te = event_add_timed(req->nbtsock->event_ctx, req, - timeval_add(&t, req->timeout, 0), - nbt_name_socket_timeout, req); - if (req->state != NBT_REQUEST_SEND) { - req->state = NBT_REQUEST_SEND; - DLIST_ADD_END(req->nbtsock->send_queue, req, - struct nbt_name_request *); - } - EVENT_FD_WRITEABLE(req->nbtsock->fde); - return; - } - - nbt_name_request_destructor(req); - 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); - } else if (req->is_reply) { - talloc_free(req); - } -} - - - -/** - handle recv events on a nbt name socket -*/ -static void nbt_name_socket_recv(struct nbt_name_socket *nbtsock) -{ - TALLOC_CTX *tmp_ctx = talloc_new(nbtsock); - NTSTATUS status; - enum ndr_err_code ndr_err; - struct socket_address *src; - DATA_BLOB blob; - size_t nread, dsize; - struct nbt_name_packet *packet; - struct nbt_name_request *req; - - status = socket_pending(nbtsock->sock, &dsize); - if (!NT_STATUS_IS_OK(status)) { - talloc_free(tmp_ctx); - return; - } - - blob = data_blob_talloc(tmp_ctx, NULL, dsize); - if (blob.data == NULL) { - talloc_free(tmp_ctx); - return; - } - - status = socket_recvfrom(nbtsock->sock, blob.data, blob.length, &nread, - tmp_ctx, &src); - if (!NT_STATUS_IS_OK(status)) { - talloc_free(tmp_ctx); - return; - } - - packet = talloc(tmp_ctx, struct nbt_name_packet); - if (packet == NULL) { - talloc_free(tmp_ctx); - return; - } - - /* parse the request */ - ndr_err = ndr_pull_struct_blob(&blob, packet, nbtsock->iconv_convenience, packet, - (ndr_pull_flags_fn_t)ndr_pull_nbt_name_packet); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - status = ndr_map_error2ntstatus(ndr_err); - DEBUG(2,("Failed to parse incoming NBT name packet - %s\n", - nt_errstr(status))); - talloc_free(tmp_ctx); - return; - } - - if (DEBUGLVL(10)) { - DEBUG(10,("Received nbt packet of length %d from %s:%d\n", - (int)blob.length, src->addr, src->port)); - NDR_PRINT_DEBUG(nbt_name_packet, packet); - } - - /* if its not a reply then pass it off to the incoming request - handler, if any */ - if (!(packet->operation & NBT_FLAG_REPLY)) { - if (nbtsock->incoming.handler) { - nbtsock->incoming.handler(nbtsock, packet, src); - } - talloc_free(tmp_ctx); - return; - } - - /* find the matching request */ - req = (struct nbt_name_request *)idr_find(nbtsock->idr, - packet->name_trn_id); - if (req == NULL) { - if (nbtsock->unexpected.handler) { - nbtsock->unexpected.handler(nbtsock, packet, src); - } else { - DEBUG(10,("Failed to match request for incoming name packet id 0x%04x on %p\n", - packet->name_trn_id, nbtsock)); - } - talloc_free(tmp_ctx); - return; - } - - /* if this is a WACK response, this we need to go back to waiting, - but perhaps increase the timeout */ - if ((packet->operation & NBT_OPCODE) == NBT_OPCODE_WACK) { - if (req->received_wack || packet->ancount < 1) { - nbt_name_request_destructor(req); - req->status = NT_STATUS_INVALID_NETWORK_RESPONSE; - req->state = NBT_REQUEST_ERROR; - goto done; - } - talloc_free(req->te); - /* we know we won't need any more retries - the server - has received our request */ - req->num_retries = 0; - req->received_wack = true; - /* although there can be a timeout in the packet, w2k3 screws it up, - so better to set it ourselves */ - req->timeout = lp_parm_int(global_loadparm, NULL, "nbt", "wack_timeout", 30); - req->te = event_add_timed(req->nbtsock->event_ctx, req, - timeval_current_ofs(req->timeout, 0), - nbt_name_socket_timeout, req); - talloc_free(tmp_ctx); - return; - } - - - req->replies = talloc_realloc(req, req->replies, struct nbt_name_reply, req->num_replies+1); - if (req->replies == NULL) { - nbt_name_request_destructor(req); - req->state = NBT_REQUEST_ERROR; - req->status = NT_STATUS_NO_MEMORY; - goto done; - } - - talloc_steal(req, src); - req->replies[req->num_replies].dest = src; - talloc_steal(req, packet); - req->replies[req->num_replies].packet = packet; - req->num_replies++; - - /* if we don't want multiple replies then we are done */ - if (req->allow_multiple_replies && - req->num_replies < NBT_MAX_REPLIES) { - talloc_free(tmp_ctx); - return; - } - - nbt_name_request_destructor(req); - req->state = NBT_REQUEST_DONE; - req->status = NT_STATUS_OK; - -done: - talloc_free(tmp_ctx); - if (req->async.fn) { - req->async.fn(req); - } -} - -/* - handle fd events on a nbt_name_socket -*/ -static void nbt_name_socket_handler(struct event_context *ev, struct fd_event *fde, - uint16_t flags, void *private) -{ - struct nbt_name_socket *nbtsock = talloc_get_type(private, - struct nbt_name_socket); - if (flags & EVENT_FD_WRITE) { - nbt_name_socket_send(nbtsock); - } - if (flags & EVENT_FD_READ) { - nbt_name_socket_recv(nbtsock); - } -} - - -/* - initialise a nbt_name_socket. The event_ctx is optional, if provided - then operations will use that event context -*/ -_PUBLIC_ struct nbt_name_socket *nbt_name_socket_init(TALLOC_CTX *mem_ctx, - struct event_context *event_ctx, - struct smb_iconv_convenience *iconv_convenience) -{ - struct nbt_name_socket *nbtsock; - NTSTATUS status; - - nbtsock = talloc(mem_ctx, struct nbt_name_socket); - if (nbtsock == NULL) goto failed; - - nbtsock->event_ctx = talloc_reference(nbtsock, event_ctx); - if (nbtsock->event_ctx == NULL) goto failed; - - status = socket_create("ip", SOCKET_TYPE_DGRAM, &nbtsock->sock, 0); - if (!NT_STATUS_IS_OK(status)) goto failed; - - socket_set_option(nbtsock->sock, "SO_BROADCAST", "1"); - - talloc_steal(nbtsock, nbtsock->sock); - - nbtsock->idr = idr_init(nbtsock); - if (nbtsock->idr == NULL) goto failed; - - nbtsock->send_queue = NULL; - nbtsock->num_pending = 0; - nbtsock->incoming.handler = NULL; - nbtsock->unexpected.handler = NULL; - nbtsock->iconv_convenience = iconv_convenience; - - nbtsock->fde = event_add_fd(nbtsock->event_ctx, nbtsock, - socket_get_fd(nbtsock->sock), 0, - nbt_name_socket_handler, nbtsock); - - return nbtsock; - -failed: - talloc_free(nbtsock); - return NULL; -} - -/* - send off a nbt name request -*/ -struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock, - struct socket_address *dest, - struct nbt_name_packet *request, - int timeout, int retries, - bool allow_multiple_replies) -{ - struct nbt_name_request *req; - int id; - enum ndr_err_code ndr_err; - - req = talloc_zero(nbtsock, struct nbt_name_request); - if (req == NULL) goto failed; - - req->nbtsock = nbtsock; - req->allow_multiple_replies = allow_multiple_replies; - req->state = NBT_REQUEST_SEND; - req->is_reply = false; - req->timeout = timeout; - req->num_retries = retries; - req->dest = dest; - if (talloc_reference(req, dest) == NULL) goto failed; - - /* we select a random transaction id unless the user supplied one */ - if (request->name_trn_id == 0) { - id = idr_get_new_random(req->nbtsock->idr, req, UINT16_MAX); - } else { - if (idr_find(req->nbtsock->idr, request->name_trn_id)) goto failed; - id = idr_get_new_above(req->nbtsock->idr, req, request->name_trn_id, - UINT16_MAX); - } - if (id == -1) goto failed; - - request->name_trn_id = id; - req->name_trn_id = id; - - req->te = event_add_timed(nbtsock->event_ctx, req, - timeval_current_ofs(req->timeout, 0), - nbt_name_socket_timeout, req); - - talloc_set_destructor(req, nbt_name_request_destructor); - - ndr_err = ndr_push_struct_blob(&req->encoded, req, - req->nbtsock->iconv_convenience, - request, - (ndr_push_flags_fn_t)ndr_push_nbt_name_packet); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) goto failed; - - DLIST_ADD_END(nbtsock->send_queue, req, struct nbt_name_request *); - - if (DEBUGLVL(10)) { - DEBUG(10,("Queueing nbt packet to %s:%d\n", - req->dest->addr, req->dest->port)); - NDR_PRINT_DEBUG(nbt_name_packet, request); - } - - EVENT_FD_WRITEABLE(nbtsock->fde); - - return req; - -failed: - talloc_free(req); - return NULL; -} - - -/* - send off a nbt name reply -*/ -_PUBLIC_ NTSTATUS nbt_name_reply_send(struct nbt_name_socket *nbtsock, - struct socket_address *dest, - struct nbt_name_packet *request) -{ - struct nbt_name_request *req; - enum ndr_err_code ndr_err; - - req = talloc_zero(nbtsock, struct nbt_name_request); - NT_STATUS_HAVE_NO_MEMORY(req); - - req->nbtsock = nbtsock; - req->dest = dest; - if (talloc_reference(req, dest) == NULL) goto failed; - req->state = NBT_REQUEST_SEND; - req->is_reply = true; - - talloc_set_destructor(req, nbt_name_request_destructor); - - if (DEBUGLVL(10)) { - NDR_PRINT_DEBUG(nbt_name_packet, request); - } - - ndr_err = ndr_push_struct_blob(&req->encoded, req, - req->nbtsock->iconv_convenience, - request, - (ndr_push_flags_fn_t)ndr_push_nbt_name_packet); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - talloc_free(req); - return ndr_map_error2ntstatus(ndr_err); - } - - DLIST_ADD_END(nbtsock->send_queue, req, struct nbt_name_request *); - - EVENT_FD_WRITEABLE(nbtsock->fde); - - return NT_STATUS_OK; - -failed: - talloc_free(req); - return NT_STATUS_NO_MEMORY; -} - -/* - wait for a nbt request to complete -*/ -NTSTATUS nbt_name_request_recv(struct nbt_name_request *req) -{ - if (!req) return NT_STATUS_NO_MEMORY; - - while (req->state < NBT_REQUEST_DONE) { - if (event_loop_once(req->nbtsock->event_ctx) != 0) { - req->state = NBT_REQUEST_ERROR; - req->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR; - break; - } - } - return req->status; -} - - -/* - setup a handler for incoming requests -*/ -_PUBLIC_ NTSTATUS nbt_set_incoming_handler(struct nbt_name_socket *nbtsock, - void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *, - struct socket_address *), - void *private) -{ - nbtsock->incoming.handler = handler; - nbtsock->incoming.private_data = private; - EVENT_FD_READABLE(nbtsock->fde); - return NT_STATUS_OK; -} - - -/* - turn a NBT rcode into a NTSTATUS -*/ -_PUBLIC_ NTSTATUS nbt_rcode_to_ntstatus(uint8_t rcode) -{ - int i; - struct { - enum nbt_rcode rcode; - NTSTATUS status; - } map[] = { - { NBT_RCODE_FMT, NT_STATUS_INVALID_PARAMETER }, - { NBT_RCODE_SVR, NT_STATUS_SERVER_DISABLED }, - { NBT_RCODE_NAM, NT_STATUS_OBJECT_NAME_NOT_FOUND }, - { NBT_RCODE_IMP, NT_STATUS_NOT_SUPPORTED }, - { NBT_RCODE_RFS, NT_STATUS_ACCESS_DENIED }, - { NBT_RCODE_ACT, NT_STATUS_ADDRESS_ALREADY_EXISTS }, - { NBT_RCODE_CFT, NT_STATUS_CONFLICTING_ADDRESSES } - }; - for (i=0;i 2008 - - 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 3 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, see . -*/ - -#include "includes.h" -#include -#include "libcli/util/pyerrors.h" -#include "libcli/nbt/libnbt.h" -#include "lib/events/events.h" -#include "param/param.h" - -PyAPI_DATA(PyTypeObject) nbt_node_Type; - -typedef struct { - PyObject_HEAD - TALLOC_CTX *mem_ctx; - struct nbt_name_socket *socket; -} nbt_node_Object; - -static void py_nbt_node_dealloc(PyObject *obj) -{ - talloc_free(((nbt_node_Object *)obj)->mem_ctx); - PyObject_Del(obj); -} - -static PyObject *py_nbt_node_init(PyTypeObject *self, PyObject *args, PyObject *kwargs) -{ - struct event_context *ev; - nbt_node_Object *ret = PyObject_New(nbt_node_Object, &nbt_node_Type); - - ret->mem_ctx = talloc_new(NULL); - if (ret->mem_ctx == NULL) - return NULL; - - ev = s4_event_context_init(ret->mem_ctx); - ret->socket = nbt_name_socket_init(ret->mem_ctx, ev, lp_iconv_convenience(global_loadparm)); - return (PyObject *)ret; -} - -static bool PyObject_AsDestinationTuple(PyObject *obj, const char **dest_addr, uint16_t *dest_port) -{ - if (PyString_Check(obj)) { - *dest_addr = PyString_AsString(obj); - *dest_port = NBT_NAME_SERVICE_PORT; - return true; - } - - if (PyTuple_Check(obj)) { - if (PyTuple_Size(obj) < 1) { - PyErr_SetString(PyExc_TypeError, "Destination tuple size invalid"); - return false; - } - - if (!PyString_Check(PyTuple_GetItem(obj, 0))) { - PyErr_SetString(PyExc_TypeError, "Destination tuple first element not string"); - return false; - } - - *dest_addr = PyString_AsString(obj); - - if (PyTuple_Size(obj) == 1) { - *dest_port = NBT_NAME_SERVICE_PORT; - return true; - } else if (PyInt_Check(PyTuple_GetItem(obj, 1))) { - *dest_port = PyInt_AsLong(PyTuple_GetItem(obj, 1)); - return true; - } else { - PyErr_SetString(PyExc_TypeError, "Destination tuple second element not a port"); - return false; - } - } - - PyErr_SetString(PyExc_TypeError, "Destination tuple second element not a port"); - return false; -} - -static bool PyObject_AsNBTName(PyObject *obj, struct nbt_name_socket *socket, struct nbt_name *name) -{ - if (PyTuple_Check(obj)) { - if (PyTuple_Size(obj) == 2) { - name->name = PyString_AsString(PyTuple_GetItem(obj, 0)); - name->type = PyInt_AsLong(PyTuple_GetItem(obj, 1)); - name->scope = NULL; - return true; - } else if (PyTuple_Size(obj) == 3) { - name->name = PyString_AsString(PyTuple_GetItem(obj, 0)); - name->scope = PyString_AsString(PyTuple_GetItem(obj, 1)); - name->type = PyInt_AsLong(PyTuple_GetItem(obj, 2)); - return true; - } else { - PyErr_SetString(PyExc_TypeError, "Invalid tuple size"); - return false; - } - } - - if (PyString_Check(obj)) { - /* FIXME: Parse string to be able to interpret things like RHONWYN<02> ? */ - name->name = PyString_AsString(obj); - name->scope = NULL; - name->type = 0; - return true; - } - - PyErr_SetString(PyExc_TypeError, "Invalid type for object"); - return false; -} - -static PyObject *PyObject_FromNBTName(struct nbt_name_socket *socket, struct smb_iconv_convenience *ic, - struct nbt_name *name) -{ - if (name->scope) { - return Py_BuildValue("(ssi)", name->name, name->scope, name->type); - } else { - return Py_BuildValue("(si)", name->name, name->type); - } -} - -static PyObject *py_nbt_name_query(PyObject *self, PyObject *args, PyObject *kwargs) -{ - nbt_node_Object *node = (nbt_node_Object *)self; - PyObject *ret, *reply_addrs, *py_dest, *py_name; - struct nbt_name_query io; - NTSTATUS status; - int i; - - const char *kwnames[] = { "name", "dest", "broadcast", "wins", "timeout", - "retries", NULL }; - io.in.broadcast = true; - io.in.wins_lookup = false; - io.in.timeout = 0; - io.in.retries = 3; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|bbii:query_name", - discard_const_p(char *, kwnames), - &py_name, &py_dest, - &io.in.broadcast, &io.in.wins_lookup, - &io.in.timeout, &io.in.retries)) { - return NULL; - } - - if (!PyObject_AsDestinationTuple(py_dest, &io.in.dest_addr, &io.in.dest_port)) - return NULL; - - if (!PyObject_AsNBTName(py_name, node->socket, &io.in.name)) - return NULL; - - status = nbt_name_query(node->socket, NULL, &io); - - if (NT_STATUS_IS_ERR(status)) { - PyErr_SetNTSTATUS(status); - return NULL; - } - - ret = PyTuple_New(3); - if (ret == NULL) - return NULL; - PyTuple_SetItem(ret, 0, PyString_FromString(io.out.reply_from)); - - py_name = PyObject_FromNBTName(node->socket, lp_iconv_convenience(global_loadparm), &io.out.name); - if (py_name == NULL) - return NULL; - - PyTuple_SetItem(ret, 1, py_name); - - reply_addrs = PyList_New(io.out.num_addrs); - if (reply_addrs == NULL) { - Py_DECREF(ret); - return NULL; - } - - for (i = 0; i < io.out.num_addrs; i++) { - PyList_SetItem(reply_addrs, i, PyString_FromString(io.out.reply_addrs[i])); - } - - PyTuple_SetItem(ret, 2, reply_addrs); - return ret; -} - -static PyObject *py_nbt_name_status(PyObject *self, PyObject *args, PyObject *kwargs) -{ - nbt_node_Object *node = (nbt_node_Object *)self; - PyObject *ret, *py_dest, *py_name, *py_names; - struct nbt_name_status io; - int i; - NTSTATUS status; - - const char *kwnames[] = { "name", "dest", "timeout", "retries", NULL }; - - io.in.timeout = 0; - io.in.retries = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|ii:name_status", - discard_const_p(char *, kwnames), - &py_name, &py_dest, - &io.in.timeout, &io.in.retries)) { - return NULL; - } - - if (!PyObject_AsDestinationTuple(py_dest, &io.in.dest_addr, &io.in.dest_port)) - return NULL; - - if (!PyObject_AsNBTName(py_name, node->socket, &io.in.name)) - return NULL; - - status = nbt_name_status(node->socket, NULL, &io); - - if (NT_STATUS_IS_ERR(status)) { - PyErr_SetNTSTATUS(status); - return NULL; - } - - ret = PyTuple_New(3); - if (ret == NULL) - return NULL; - PyTuple_SetItem(ret, 0, PyString_FromString(io.out.reply_from)); - - py_name = PyObject_FromNBTName(node->socket, lp_iconv_convenience(global_loadparm), &io.out.name); - if (py_name == NULL) - return NULL; - - PyTuple_SetItem(ret, 1, py_name); - - py_names = PyList_New(io.out.status.num_names); - - for (i = 0; i < io.out.status.num_names; i++) { - PyList_SetItem(py_names, i, Py_BuildValue("(sii)", - io.out.status.names[i].name, - io.out.status.names[i].nb_flags, - io.out.status.names[i].type)); - } - - PyTuple_SetItem(ret, 2, py_names); - - return ret; -} - -static PyObject *py_nbt_name_register(PyObject *self, PyObject *args, PyObject *kwargs) -{ - nbt_node_Object *node = (nbt_node_Object *)self; - PyObject *ret, *py_dest, *py_name; - struct nbt_name_register io; - NTSTATUS status; - - const char *kwnames[] = { "name", "address", "dest", "register_demand", "broadcast", - "multi_homed", "ttl", "timeout", "retries", NULL }; - - io.in.broadcast = true; - io.in.multi_homed = true; - io.in.register_demand = true; - io.in.timeout = 0; - io.in.retries = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OsO|bbbiii:query_name", - discard_const_p(char *, kwnames), - &py_name, &io.in.address, &py_dest, - &io.in.register_demand, - &io.in.broadcast, &io.in.multi_homed, - &io.in.ttl, &io.in.timeout, &io.in.retries)) { - return NULL; - } - - if (!PyObject_AsDestinationTuple(py_dest, &io.in.dest_addr, &io.in.dest_port)) - return NULL; - - if (!PyObject_AsNBTName(py_name, node->socket, &io.in.name)) - return NULL; - - status = nbt_name_register(node->socket, NULL, &io); - - if (NT_STATUS_IS_ERR(status)) { - PyErr_SetNTSTATUS(status); - return NULL; - } - - ret = PyTuple_New(3); - if (ret == NULL) - return NULL; - PyTuple_SetItem(ret, 0, PyString_FromString(io.out.reply_from)); - - py_name = PyObject_FromNBTName(node->socket, lp_iconv_convenience(global_loadparm), &io.out.name); - if (py_name == NULL) - return NULL; - - PyTuple_SetItem(ret, 1, py_name); - - PyTuple_SetItem(ret, 2, PyString_FromString(io.out.reply_addr)); - - PyTuple_SetItem(ret, 3, PyInt_FromLong(io.out.rcode)); - - return ret; -} - -static PyObject *py_nbt_name_refresh(PyObject *self, PyObject *args, PyObject *kwargs) -{ - nbt_node_Object *node = (nbt_node_Object *)self; - PyObject *ret, *py_dest, *py_name; - struct nbt_name_refresh io; - NTSTATUS status; - - const char *kwnames[] = { "name", "address", "dest", "nb_flags", "broadcast", - "ttl", "timeout", "retries", NULL }; - - io.in.broadcast = true; - io.in.nb_flags = 0; - io.in.timeout = 0; - io.in.retries = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OsO|ibiii:query_name", - discard_const_p(char *, kwnames), - &py_name, &io.in.address, &py_dest, - &io.in.nb_flags, - &io.in.broadcast, - &io.in.ttl, &io.in.timeout, &io.in.retries)) { - return NULL; - } - - if (!PyObject_AsDestinationTuple(py_dest, &io.in.dest_addr, &io.in.dest_port)) - return NULL; - - if (!PyObject_AsNBTName(py_name, node->socket, &io.in.name)) - return NULL; - - status = nbt_name_refresh(node->socket, NULL, &io); - - if (NT_STATUS_IS_ERR(status)) { - PyErr_SetNTSTATUS(status); - return NULL; - } - - ret = PyTuple_New(3); - if (ret == NULL) - return NULL; - PyTuple_SetItem(ret, 0, PyString_FromString(io.out.reply_from)); - - py_name = PyObject_FromNBTName(node->socket, lp_iconv_convenience(global_loadparm), &io.out.name); - if (py_name == NULL) - return NULL; - - PyTuple_SetItem(ret, 1, py_name); - - PyTuple_SetItem(ret, 2, PyString_FromString(io.out.reply_addr)); - - PyTuple_SetItem(ret, 3, PyInt_FromLong(io.out.rcode)); - - return ret; -} - -static PyObject *py_nbt_name_release(PyObject *self, PyObject *args, PyObject *kwargs) -{ - return Py_None; /* FIXME */ -} - -static PyMethodDef py_nbt_methods[] = { - { "query_name", (PyCFunction)py_nbt_name_query, METH_VARARGS|METH_KEYWORDS, - "S.query_name(name, dest, broadcast=True, wins=False, timeout=0, retries=3) -> (reply_from, name, reply_addr)\n" - "Query for a NetBIOS name" }, - { "register_name", (PyCFunction)py_nbt_name_register, METH_VARARGS|METH_KEYWORDS, - "S.register_name(name, address, dest, register_demand=True, broadcast=True, multi_homed=True, ttl=0, timeout=0, retries=0) -> (reply_from, name, reply_addr, rcode)\n" - "Register a new name" }, - { "release_name", (PyCFunction)py_nbt_name_release, METH_VARARGS|METH_KEYWORDS, "S.release_name(name, address, dest, nb_flags=0, broadcast=true, timeout=0, retries=3) -> (reply_from, name, reply_addr, rcode)\n" - "release a previously registered name" }, - { "refresh_name", (PyCFunction)py_nbt_name_refresh, METH_VARARGS|METH_KEYWORDS, "S.refresh_name(name, address, dest, nb_flags=0, broadcast=True, ttl=0, timeout=0, retries=0) -> (reply_from, name, reply_addr, rcode)\n" - "release a previously registered name" }, - { "name_status", (PyCFunction)py_nbt_name_status, METH_VARARGS|METH_KEYWORDS, - "S.name_status(name, dest, timeout=0, retries=0) -> (reply_from, name, status)\n" - "Find the status of a name" }, - - { NULL } -}; - -PyTypeObject nbt_node_Type = { - PyObject_HEAD_INIT(NULL) 0, - .tp_name = "netbios.Node", - .tp_basicsize = sizeof(nbt_node_Object), - .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, - .tp_new = py_nbt_node_init, - .tp_dealloc = py_nbt_node_dealloc, - .tp_methods = py_nbt_methods, - .tp_doc = "Node()\n" - "Create a new NetBIOS node\n" -}; - -void initnetbios(void) -{ - PyObject *mod; - if (PyType_Ready(&nbt_node_Type) < 0) - return; - - mod = Py_InitModule3("netbios", NULL, "NetBIOS over TCP/IP support"); - - Py_INCREF((PyObject *)&nbt_node_Type); - PyModule_AddObject(mod, "Node", (PyObject *)&nbt_node_Type); -} -- cgit