[PATCH] Make NetBIOS traffic always go through nmbd
Volker Lendecke
Volker.Lendecke at SerNet.DE
Wed Mar 21 11:09:21 UTC 2018
Hi!
Attached find a patchset that makes us more like Windows regarding
netbios traffic: All outgoing packets go through nmbd or nbt_server,
making them come from port 137/138. This is done by opening the
already existing "unexpected" pipe also for outgoing packets.
This should in the future obsolete the "disable netbios" parameter.
Either you run nmbd/nbt_server or you don't.
It has survived a few private autobuilds.
Review appreciated!
Thanks, Volker
--
Besuchen Sie die verinice.XP 2018 in Berlin,
Anwenderkonferenz für Informationssicherheit
vom 21.-23.03.2018 im Sofitel Kurfürstendamm
Info & Anmeldung hier: http://veriniceXP.org
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:kontakt at sernet.de
-------------- next part --------------
From 0e4bcedee653105a8cff8560548fff56a2117fb4 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 16 Jan 2018 16:47:00 +0100
Subject: [PATCH 01/32] libnmb: Factor out nb_packet_recv_send
This only replaces the nb_packet_reader parameter with a
tstream_context. nb_packet_read_send is the used API, and we'll use the
core logic in nmbd as well.
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/libsmb/unexpected.c | 98 +++++++++++++++++++++++++++++++++++----------
1 file changed, 77 insertions(+), 21 deletions(-)
diff --git a/source3/libsmb/unexpected.c b/source3/libsmb/unexpected.c
index ced46969b88..55e2a1007db 100644
--- a/source3/libsmb/unexpected.c
+++ b/source3/libsmb/unexpected.c
@@ -654,40 +654,40 @@ NTSTATUS nb_packet_reader_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
return NT_STATUS_OK;
}
-struct nb_packet_read_state {
+struct nb_packet_recv_state {
struct nb_packet_client_header hdr;
uint8_t *buf;
size_t buflen;
};
-static ssize_t nb_packet_read_more(uint8_t *buf, size_t buflen, void *p);
-static void nb_packet_read_done(struct tevent_req *subreq);
+static ssize_t nb_packet_recv_more(uint8_t *buf, size_t buflen, void *p);
+static void nb_packet_recv_done(struct tevent_req *subreq);
-struct tevent_req *nb_packet_read_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct nb_packet_reader *reader)
+static struct tevent_req *nb_packet_recv_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct tstream_context *sock)
{
struct tevent_req *req, *subreq;
- struct nb_packet_read_state *state;
+ struct nb_packet_recv_state *state;
- req = tevent_req_create(mem_ctx, &state, struct nb_packet_read_state);
+ req = tevent_req_create(mem_ctx, &state, struct nb_packet_recv_state);
if (req == NULL) {
return NULL;
}
- subreq = tstream_read_packet_send(state, ev, reader->sock,
+ subreq = tstream_read_packet_send(state, ev, sock,
sizeof(struct nb_packet_client_header),
- nb_packet_read_more, state);
+ nb_packet_recv_more, state);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
- tevent_req_set_callback(subreq, nb_packet_read_done, req);
+ tevent_req_set_callback(subreq, nb_packet_recv_done, req);
return req;
}
-static ssize_t nb_packet_read_more(uint8_t *buf, size_t buflen, void *p)
+static ssize_t nb_packet_recv_more(uint8_t *buf, size_t buflen, void *p)
{
- struct nb_packet_read_state *state = talloc_get_type_abort(
- p, struct nb_packet_read_state);
+ struct nb_packet_recv_state *state = talloc_get_type_abort(
+ p, struct nb_packet_recv_state);
if (buflen > sizeof(struct nb_packet_client_header)) {
/*
@@ -699,12 +699,12 @@ static ssize_t nb_packet_read_more(uint8_t *buf, size_t buflen, void *p)
return state->hdr.len;
}
-static void nb_packet_read_done(struct tevent_req *subreq)
+static void nb_packet_recv_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(
subreq, struct tevent_req);
- struct nb_packet_read_state *state = tevent_req_data(
- req, struct nb_packet_read_state);
+ struct nb_packet_recv_state *state = tevent_req_data(
+ req, struct nb_packet_recv_state);
ssize_t nread;
int err;
@@ -717,11 +717,12 @@ static void nb_packet_read_done(struct tevent_req *subreq)
tevent_req_done(req);
}
-NTSTATUS nb_packet_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
- struct packet_struct **ppacket)
+static NTSTATUS nb_packet_recv_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ struct packet_struct **ppacket)
{
- struct nb_packet_read_state *state = tevent_req_data(
- req, struct nb_packet_read_state);
+ struct nb_packet_recv_state *state = tevent_req_data(
+ req, struct nb_packet_recv_state);
struct nb_packet_client_header hdr;
struct packet_struct *packet;
NTSTATUS status;
@@ -747,3 +748,58 @@ NTSTATUS nb_packet_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
tevent_req_received(req);
return NT_STATUS_OK;
}
+
+struct nb_packet_read_state {
+ struct packet_struct *pkt;
+};
+
+static void nb_packet_read_done(struct tevent_req *subreq);
+
+struct tevent_req *nb_packet_read_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct nb_packet_reader *reader)
+{
+ struct tevent_req *req, *subreq;
+ struct nb_packet_read_state *state;
+
+ req = tevent_req_create(mem_ctx, &state, struct nb_packet_read_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ subreq = nb_packet_recv_send(state, ev, reader->sock);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, nb_packet_read_done, req);
+ return req;
+}
+
+static void nb_packet_read_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct nb_packet_read_state *state = tevent_req_data(
+ req, struct nb_packet_read_state);
+ NTSTATUS status;
+
+ status = nb_packet_recv_recv(subreq, state, &state->pkt);
+ TALLOC_FREE(subreq);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS nb_packet_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ struct packet_struct **ppacket)
+{
+ struct nb_packet_read_state *state = tevent_req_data(
+ req, struct nb_packet_read_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+ *ppacket = talloc_move(mem_ctx, &state->pkt);
+ return NT_STATUS_OK;
+}
--
2.11.0
From 7e78a421eee313460d67159130868e475dd8f379 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 23 Jan 2018 21:26:28 +0100
Subject: [PATCH 02/32] libnmb: Add "pkt_receiver" to nb_packet_server
This is the nmbd side of the "unexpected" socket that is right now used
to push unexpected, incoming 137/138 packets to netbios clients. This is
the first step to replace the MSG_SEND_PACKET mechanism for nmbd to
proxy packets.
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/libsmb/unexpected.c | 15 +++++++++++----
source3/libsmb/unexpected.h | 11 +++++++----
source3/nmbd/nmbd_packets.c | 1 +
3 files changed, 19 insertions(+), 8 deletions(-)
diff --git a/source3/libsmb/unexpected.c b/source3/libsmb/unexpected.c
index 55e2a1007db..bf23d4959c5 100644
--- a/source3/libsmb/unexpected.c
+++ b/source3/libsmb/unexpected.c
@@ -46,6 +46,8 @@ struct nb_packet_server {
struct tevent_fd *listen_fde;
int max_clients;
int num_clients;
+ void (*pkt_receiver)(struct packet_struct *pkt, void *private_data);
+ void *private_data;
struct nb_packet_client *clients;
};
@@ -72,10 +74,13 @@ static void nb_packet_server_listener(struct tevent_context *ev,
uint16_t flags,
void *private_data);
-NTSTATUS nb_packet_server_create(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- int max_clients,
- struct nb_packet_server **presult)
+NTSTATUS nb_packet_server_create(
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ int max_clients,
+ void (*pkt_receiver)(struct packet_struct *pkt, void *private_data),
+ void *private_data,
+ struct nb_packet_server **presult)
{
struct nb_packet_server *result;
NTSTATUS status;
@@ -88,6 +93,8 @@ NTSTATUS nb_packet_server_create(TALLOC_CTX *mem_ctx,
}
result->ev = ev;
result->max_clients = max_clients;
+ result->pkt_receiver = pkt_receiver;
+ result->private_data = private_data;
result->listen_sock = create_pipe_sock(
nmbd_socket_dir(), "unexpected", 0755);
diff --git a/source3/libsmb/unexpected.h b/source3/libsmb/unexpected.h
index 270976b7f65..b06b8763549 100644
--- a/source3/libsmb/unexpected.h
+++ b/source3/libsmb/unexpected.h
@@ -27,10 +27,13 @@
struct nb_packet_server;
struct nb_packet_reader;
-NTSTATUS nb_packet_server_create(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- int max_clients,
- struct nb_packet_server **presult);
+NTSTATUS nb_packet_server_create(
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ int max_clients,
+ void (*pkt_receiver)(struct packet_struct *pkt, void *private_data),
+ void *private_data,
+ struct nb_packet_server **presult);
void nb_packet_dispatch(struct nb_packet_server *server,
struct packet_struct *p);
struct tevent_req *nb_packet_reader_send(TALLOC_CTX *mem_ctx,
diff --git a/source3/nmbd/nmbd_packets.c b/source3/nmbd/nmbd_packets.c
index bbcb9582ec5..48d135ac1f8 100644
--- a/source3/nmbd/nmbd_packets.c
+++ b/source3/nmbd/nmbd_packets.c
@@ -43,6 +43,7 @@ bool nmbd_init_packet_server(void)
status = nb_packet_server_create(
NULL, nmbd_event_context(),
lp_parm_int(-1, "nmbd", "unexpected_clients", 200),
+ NULL, NULL,
&packet_server);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("ERROR: nb_packet_server_create failed: %s\n",
--
2.11.0
From d049a01a7e66224ebf79f83740a934f40c70d159 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 23 Jan 2018 21:41:58 +0100
Subject: [PATCH 03/32] libnmb: Read packets from the unexpected pipe in nmbd
Not hooked into nmbd yet, stay tuned
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/libsmb/unexpected.c | 45 ++++++++++++++++++++++++++++++++-------------
1 file changed, 32 insertions(+), 13 deletions(-)
diff --git a/source3/libsmb/unexpected.c b/source3/libsmb/unexpected.c
index bf23d4959c5..6d7a8452073 100644
--- a/source3/libsmb/unexpected.c
+++ b/source3/libsmb/unexpected.c
@@ -73,6 +73,12 @@ static void nb_packet_server_listener(struct tevent_context *ev,
struct tevent_fd *fde,
uint16_t flags,
void *private_data);
+static struct tevent_req *nb_packet_recv_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct tstream_context *sock);
+static NTSTATUS nb_packet_recv_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ struct packet_struct **ppacket);
NTSTATUS nb_packet_server_create(
TALLOC_CTX *mem_ctx,
@@ -299,11 +305,9 @@ static void nb_packet_got_query(struct tevent_req *req)
}
tevent_req_set_callback(req, nb_packet_client_ack_done, client);
- req = tstream_read_packet_send(client, client->server->ev,
- client->sock, 1, NULL, NULL);
+ req = nb_packet_recv_send(client, client->server->ev, client->sock);
if (req == NULL) {
- DEBUG(10, ("Could not activate reader for client exit "
- "detection\n"));
+ DBG_DEBUG("nb_packet_recv_send for client packets failed\n");
TALLOC_FREE(client);
return;
}
@@ -334,17 +338,32 @@ static void nb_packet_client_read_done(struct tevent_req *req)
{
struct nb_packet_client *client = tevent_req_callback_data(
req, struct nb_packet_client);
- ssize_t nread;
- uint8_t *buf;
- int err;
+ struct nb_packet_server *server = client->server;
+ struct packet_struct *pkt;
+ NTSTATUS status;
- nread = tstream_read_packet_recv(req, talloc_tos(), &buf, &err);
- TALLOC_FREE(req);
- if (nread == 1) {
- DEBUG(10, ("Protocol error, received data on write-only "
- "unexpected socket: 0x%2.2x\n", (*buf)));
+ status = nb_packet_recv_recv(req, client, &pkt);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("Failed to read client packet: %s\n",
+ nt_errstr(status));
+ TALLOC_FREE(client);
+ return;
+ }
+
+ if (server->pkt_receiver != NULL) {
+ server->pkt_receiver(pkt, server->private_data);
}
- TALLOC_FREE(client);
+
+ TALLOC_FREE(pkt);
+
+ req = nb_packet_recv_send(client, client->server->ev, client->sock);
+ if (req == NULL) {
+ DBG_DEBUG("nb_packet_recv_send for client packets failed\n");
+ TALLOC_FREE(client);
+ return;
+ }
+ tevent_req_set_callback(req, nb_packet_client_read_done,
+ client);
}
static void nb_packet_client_send(struct nb_packet_client *client,
--
2.11.0
From 929127cf9d5ddd75d1d6f9fb74888ff6d74b4cc5 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 23 Jan 2018 21:53:29 +0100
Subject: [PATCH 04/32] nmbd: Accept packets and on the unexpected pipe
One semantic change from the SEND_PACKET message is that packet_proxy
does the broadcasting for NMB packets. This will be useful in broadcast
lookup: The netbios client code (nmblookup et al) don't have to
enumerate interfaces anymore, this will be done by nmbd.
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/nmbd/nmbd_packets.c | 64 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 63 insertions(+), 1 deletion(-)
diff --git a/source3/nmbd/nmbd_packets.c b/source3/nmbd/nmbd_packets.c
index 48d135ac1f8..45c967d75fb 100644
--- a/source3/nmbd/nmbd_packets.c
+++ b/source3/nmbd/nmbd_packets.c
@@ -36,6 +36,68 @@ bool rescan_listen_set = False;
static struct nb_packet_server *packet_server;
+static void packet_proxy(struct packet_struct *pkt, void *private_data)
+{
+ struct subnet_record *subrec;
+ struct sockaddr_storage ss;
+ const struct sockaddr_storage *pss;
+ const struct in_addr *local_ip;
+
+ if ((pkt->packet_type != NMB_PACKET) &&
+ (pkt->packet_type != DGRAM_PACKET)) {
+ DBG_NOTICE("Discarding invalid packet type %d\n",
+ pkt->packet_type);
+ return;
+ }
+
+ in_addr_to_sockaddr_storage(&ss, pkt->ip);
+
+ if ((pkt->packet_type == NMB_PACKET) &&
+ pkt->packet.nmb.header.nm_flags.bcast) {
+ /* Broadcast packet */
+ for (subrec = FIRST_SUBNET; subrec != NULL;
+ subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
+ pkt->send_fd = (pkt->packet_type == NMB_PACKET) ?
+ subrec->nmb_sock : subrec->dgram_sock;
+ pkt->ip = subrec->bcast_ip;
+ pkt->port = 137;
+ send_packet(pkt);
+ }
+ return;
+ }
+
+ pss = iface_ip((struct sockaddr *)(void *)&ss);
+
+ if (pss == NULL) {
+ DBG_NOTICE("Could not find ip for packet\n");
+ return;
+ }
+
+ local_ip = &((const struct sockaddr_in *)pss)->sin_addr;
+ subrec = FIRST_SUBNET;
+
+ pkt->recv_fd = -1;
+ pkt->send_fd = (pkt->packet_type == NMB_PACKET) ?
+ subrec->nmb_sock : subrec->dgram_sock;
+
+ for (subrec = FIRST_SUBNET; subrec != NULL;
+ subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
+ if (ip_equal_v4(*local_ip, subrec->myip)) {
+ pkt->send_fd = (pkt->packet_type == NMB_PACKET) ?
+ subrec->nmb_sock : subrec->dgram_sock;
+ break;
+ }
+ }
+
+ if (pkt->packet_type == DGRAM_PACKET) {
+ pkt->port = 138;
+ pkt->packet.dgram.header.source_ip.s_addr = local_ip->s_addr;
+ pkt->packet.dgram.header.source_port = 138;
+ }
+
+ send_packet(pkt);
+}
+
bool nmbd_init_packet_server(void)
{
NTSTATUS status;
@@ -43,7 +105,7 @@ bool nmbd_init_packet_server(void)
status = nb_packet_server_create(
NULL, nmbd_event_context(),
lp_parm_int(-1, "nmbd", "unexpected_clients", 200),
- NULL, NULL,
+ packet_proxy, NULL,
&packet_server);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("ERROR: nb_packet_server_create failed: %s\n",
--
2.11.0
From 6e278560d2a3814aeb9b674547cefc3113609635 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 25 Jan 2018 15:13:38 +0100
Subject: [PATCH 05/32] nmbd: Queue broadcast packets also locally
This will make nmbd answer locally if it can
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/nmbd/nmbd_packets.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/source3/nmbd/nmbd_packets.c b/source3/nmbd/nmbd_packets.c
index 45c967d75fb..4cb2eb2b9d2 100644
--- a/source3/nmbd/nmbd_packets.c
+++ b/source3/nmbd/nmbd_packets.c
@@ -54,6 +54,8 @@ static void packet_proxy(struct packet_struct *pkt, void *private_data)
if ((pkt->packet_type == NMB_PACKET) &&
pkt->packet.nmb.header.nm_flags.bcast) {
+ struct packet_struct *pkt_copy;
+
/* Broadcast packet */
for (subrec = FIRST_SUBNET; subrec != NULL;
subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
@@ -63,6 +65,13 @@ static void packet_proxy(struct packet_struct *pkt, void *private_data)
pkt->port = 137;
send_packet(pkt);
}
+
+ pkt_copy = copy_packet(pkt);
+ if (pkt_copy != NULL) {
+ pkt_copy->recv_fd = -1;
+ pkt_copy->send_fd = -1;
+ queue_packet(pkt_copy);
+ }
return;
}
@@ -1079,6 +1088,11 @@ void reply_netbios_packet(struct packet_struct *orig_packet,
debug_nmb_packet(&packet);
+ if (packet.send_fd == -1) {
+ nb_packet_dispatch(packet_server, &packet);
+ return;
+ }
+
if(loopback_this_packet) {
struct packet_struct *lo_packet;
DEBUG(5,("reply_netbios_packet: sending packet to ourselves.\n"));
--
2.11.0
From b6a4ce28e5ba3f8fc74ba0a68d4dc32462d985f0 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Mon, 29 Jan 2018 19:23:53 +0100
Subject: [PATCH 06/32] nbt_server: Shorten a line in wscript_build
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source4/nbt_server/wscript_build | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/source4/nbt_server/wscript_build b/source4/nbt_server/wscript_build
index 9d0c24a14e2..632d5fbe41d 100644
--- a/source4/nbt_server/wscript_build
+++ b/source4/nbt_server/wscript_build
@@ -36,7 +36,14 @@ bld.SAMBA_SUBSYSTEM('NBTD_DGRAM',
bld.SAMBA_SUBSYSTEM('NBT_SERVER',
- source='interfaces.c register.c query.c nodestatus.c defense.c packet.c irpc.c',
+ source='''
+ interfaces.c
+ register.c
+ query.c
+ nodestatus.c
+ defense.c
+ packet.c
+ irpc.c''',
autoproto='nbt_server_proto.h',
deps='cli-nbt NBTD_WINS NBTD_DGRAM service',
enabled=bld.AD_DC_BUILD_IS_ENABLED()
--
2.11.0
From d994a8129f6bf43c4c1b12b3f1d1dd0b97e9cd49 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 2 Feb 2018 13:30:44 +0100
Subject: [PATCH 07/32] nbt_server: Factor out nbtd_name_query_reply_packet
Separate logic from transport
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source4/nbt_server/packet.c | 101 +++++++++++++++++++++++++++++---------------
1 file changed, 67 insertions(+), 34 deletions(-)
diff --git a/source4/nbt_server/packet.c b/source4/nbt_server/packet.c
index 2857f1aa9b4..e6b36022972 100644
--- a/source4/nbt_server/packet.c
+++ b/source4/nbt_server/packet.c
@@ -94,32 +94,27 @@ bool nbtd_self_packet(struct nbt_name_socket *nbtsock,
return false;
}
-
-/*
- send a name query reply
-*/
-void nbtd_name_query_reply(struct nbt_name_socket *nbtsock,
- struct nbt_name_packet *request_packet,
- struct socket_address *src,
- struct nbt_name *name, uint32_t ttl,
- uint16_t nb_flags, const char **addresses)
+struct nbt_name_packet *nbtd_name_query_reply_packet(
+ TALLOC_CTX *mem_ctx, uint16_t trn_id, uint32_t ttl, uint16_t nb_flags,
+ const struct nbt_name *name,
+ const char **addresses, size_t num_addresses)
{
struct nbt_name_packet *packet;
- size_t num_addresses = str_list_length(addresses);
- struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
- struct nbtd_interface);
- struct nbtd_server *nbtsrv = iface->nbtsrv;
- int i;
+ size_t i;
+ struct nbt_res_rec *answer;
+ struct nbt_rdata_netbios *rdata;
+ NTSTATUS status;
if (num_addresses == 0) {
- DEBUG(3,("No addresses in name query reply - failing\n"));
- return;
+ return NULL;
}
- packet = talloc_zero(nbtsock, struct nbt_name_packet);
- if (packet == NULL) return;
+ packet = talloc_zero(mem_ctx, struct nbt_name_packet);
+ if (packet == NULL) {
+ return NULL;
+ }
- packet->name_trn_id = request_packet->name_trn_id;
+ packet->name_trn_id = trn_id;
packet->ancount = 1;
packet->operation =
NBT_FLAG_REPLY |
@@ -129,23 +124,62 @@ void nbtd_name_query_reply(struct nbt_name_socket *nbtsock,
NBT_FLAG_RECURSION_AVAIL;
packet->answers = talloc_array(packet, struct nbt_res_rec, 1);
- if (packet->answers == NULL) goto failed;
+ if (packet->answers == NULL) {
+ goto failed;
+ }
+ answer = packet->answers;
- packet->answers[0].name = *name;
- packet->answers[0].rr_type = NBT_QTYPE_NETBIOS;
- packet->answers[0].rr_class = NBT_QCLASS_IP;
- packet->answers[0].ttl = ttl;
- packet->answers[0].rdata.netbios.length = num_addresses*6;
- packet->answers[0].rdata.netbios.addresses =
- talloc_array(packet->answers, struct nbt_rdata_address, num_addresses);
- if (packet->answers[0].rdata.netbios.addresses == NULL) goto failed;
-
- for (i=0;i<num_addresses;i++) {
- struct nbt_rdata_address *addr =
- &packet->answers[0].rdata.netbios.addresses[i];
+ status = nbt_name_dup(packet->answers, name, &answer->name);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto failed;
+ }
+ answer->rr_type = NBT_QTYPE_NETBIOS;
+ answer->rr_class = NBT_QCLASS_IP;
+ answer->ttl = ttl;
+
+ rdata = &answer->rdata.netbios;
+ rdata->length = num_addresses*6;
+ rdata->addresses = talloc_array(
+ packet->answers, struct nbt_rdata_address, num_addresses);
+ if (rdata->addresses == NULL) {
+ goto failed;
+ }
+
+ for (i=0; i<num_addresses; i++) {
+ struct nbt_rdata_address *addr = &rdata->addresses[i];
addr->nb_flags = nb_flags;
addr->ipaddr = talloc_strdup(packet->answers, addresses[i]);
- if (addr->ipaddr == NULL) goto failed;
+ if (addr->ipaddr == NULL) {
+ goto failed;
+ }
+ }
+
+ return packet;
+
+failed:
+ TALLOC_FREE(packet);
+ return NULL;
+}
+
+/*
+ send a name query reply
+*/
+void nbtd_name_query_reply(struct nbt_name_socket *nbtsock,
+ struct nbt_name_packet *request_packet,
+ struct socket_address *src,
+ struct nbt_name *name, uint32_t ttl,
+ uint16_t nb_flags, const char **addresses)
+{
+ struct nbt_name_packet *packet;
+ struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
+ struct nbtd_interface);
+ struct nbtd_server *nbtsrv = iface->nbtsrv;
+
+ packet = nbtd_name_query_reply_packet(
+ nbtsock, request_packet->name_trn_id, ttl, nb_flags,
+ name, addresses, str_list_length(addresses));
+ if (packet == NULL) {
+ return;
}
DEBUG(7,("Sending name query reply for %s at %s to %s:%d\n",
@@ -154,7 +188,6 @@ void nbtd_name_query_reply(struct nbt_name_socket *nbtsock,
nbtsrv->stats.total_sent++;
nbt_name_reply_send(nbtsock, src, packet);
-failed:
talloc_free(packet);
}
--
2.11.0
From 27f5aa7f1de6e3bbb9eb433711d31b67f31d6a7e Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 2 Feb 2018 15:03:16 +0100
Subject: [PATCH 08/32] nbt_server: Factor out nbtd_node_status_reply_packet
Separate logic from transport
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source4/nbt_server/nodestatus.c | 135 ++++++++++++++++++++++++++--------------
1 file changed, 90 insertions(+), 45 deletions(-)
diff --git a/source4/nbt_server/nodestatus.c b/source4/nbt_server/nodestatus.c
index f71746ab300..42a5357214d 100644
--- a/source4/nbt_server/nodestatus.c
+++ b/source4/nbt_server/nodestatus.c
@@ -26,6 +26,92 @@
#include "lib/socket/socket.h"
#include "librpc/gen_ndr/ndr_nbt.h"
+struct nbt_name_packet *nbtd_node_status_reply_packet(
+ TALLOC_CTX *mem_ctx, uint16_t trn_id,
+ const struct nbt_name *name, struct nbtd_interface *iface)
+{
+ struct nbtd_iface_name *iname;
+ struct nbt_name_packet *packet;
+ struct nbt_res_rec *answer;
+ struct nbt_rdata_status *stat;
+ uint32_t num_names;
+ NTSTATUS status;
+
+ num_names = 0;
+ for (iname = iface->names; iname != NULL; iname = iname->next) {
+ if ((iname->nb_flags & NBT_NM_ACTIVE) == 0) {
+ continue;
+ }
+ if (strcmp(iname->name.name, "*") == 0) {
+ continue;
+ }
+ num_names += 1;
+ }
+
+ packet = talloc_zero(mem_ctx, struct nbt_name_packet);
+ if (packet == NULL) {
+ return NULL;
+ }
+
+ packet->name_trn_id = trn_id;
+ packet->ancount = 1;
+ packet->operation = NBT_OPCODE_QUERY | NBT_FLAG_REPLY
+ | NBT_FLAG_AUTHORITATIVE;
+
+ packet->answers = talloc_array(packet, struct nbt_res_rec, 1);
+ if (packet->answers == NULL) {
+ goto failed;
+ }
+
+ answer = &packet->answers[0];
+
+ status = nbt_name_dup(packet->answers, name, &answer->name);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto failed;
+ }
+
+ answer->rr_type = NBT_QTYPE_STATUS;
+ answer->rr_class = NBT_QCLASS_IP;
+ answer->ttl = 0;
+
+ stat = &packet->answers[0].rdata.status;
+
+ stat->num_names = num_names;
+ stat->names = talloc_zero_array(
+ packet->answers, struct nbt_status_name, num_names);
+ if (stat->names == NULL) {
+ goto failed;
+ }
+
+ num_names = 0;
+ for (iname = iface->names; iname != NULL; iname = iname->next) {
+ struct nbt_status_name *n = &stat->names[num_names];
+
+ if ((iname->nb_flags & NBT_NM_ACTIVE) == 0) {
+ continue;
+ }
+ if (strcmp(iname->name.name, "*") == 0) {
+ continue;
+ }
+
+ n->name = talloc_asprintf(stat->names, "%-15s",
+ iname->name.name);
+ if (n->name == NULL) {
+ goto failed;
+ }
+ n->type = iname->name.type;
+ n->nb_flags = iname->nb_flags;
+
+ num_names += 1;
+ }
+
+ return packet;
+
+failed:
+ TALLOC_FREE(packet);
+ return NULL;
+}
+
/*
send a name status reply
*/
@@ -36,53 +122,13 @@ static void nbtd_node_status_reply(struct nbt_name_socket *nbtsock,
struct nbtd_interface *iface)
{
struct nbt_name_packet *packet;
- uint32_t name_count;
- struct nbtd_iface_name *iname;
struct nbtd_server *nbtsrv = iface->nbtsrv;
-
- /* work out how many names to send */
- name_count = 0;
- for (iname=iface->names;iname;iname=iname->next) {
- if ((iname->nb_flags & NBT_NM_ACTIVE) &&
- strcmp(iname->name.name, "*") != 0) {
- name_count++;
- }
- }
-
- packet = talloc_zero(nbtsock, struct nbt_name_packet);
- if (packet == NULL) return;
- packet->name_trn_id = request_packet->name_trn_id;
- packet->ancount = 1;
- packet->operation = NBT_OPCODE_QUERY | NBT_FLAG_REPLY | NBT_FLAG_AUTHORITATIVE;
-
- packet->answers = talloc_array(packet, struct nbt_res_rec, 1);
- if (packet->answers == NULL) goto failed;
-
- packet->answers[0].name = *name;
- packet->answers[0].rr_type = NBT_QTYPE_STATUS;
- packet->answers[0].rr_class = NBT_QCLASS_IP;
- packet->answers[0].ttl = 0;
- packet->answers[0].rdata.status.num_names = name_count;
- packet->answers[0].rdata.status.names = talloc_array(packet->answers,
- struct nbt_status_name, name_count);
- if (packet->answers[0].rdata.status.names == NULL) goto failed;
-
- name_count = 0;
- for (iname=iface->names;iname;iname=iname->next) {
- if ((iname->nb_flags & NBT_NM_ACTIVE) &&
- strcmp(iname->name.name, "*") != 0) {
- struct nbt_status_name *n = &packet->answers[0].rdata.status.names[name_count];
- n->name = talloc_asprintf(packet->answers, "%-15s", iname->name.name);
- if (n->name == NULL) goto failed;
- n->type = iname->name.type;
- n->nb_flags = iname->nb_flags;
- name_count++;
- }
+ packet = nbtd_node_status_reply_packet(
+ nbtsock, request_packet->name_trn_id, name, iface);
+ if (packet == NULL) {
+ return;
}
- /* we deliberately don't fill in the statistics structure as
- it could lead to giving attackers too much information */
- ZERO_STRUCT(packet->answers[0].rdata.status.statistics);
DEBUG(7,("Sending node status reply for %s to %s:%d\n",
nbt_name_string(packet, name), src->addr, src->port));
@@ -90,7 +136,6 @@ static void nbtd_node_status_reply(struct nbt_name_socket *nbtsock,
nbtsrv->stats.total_sent++;
nbt_name_reply_send(nbtsock, src, packet);
-failed:
talloc_free(packet);
}
--
2.11.0
From b4a91902f6844e34e644a916d59ca2e03f600245 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sun, 4 Feb 2018 12:16:14 +0000
Subject: [PATCH 09/32] libnbt: Add an explicit "mem_ctx" to name_request_send
Signed-off-by: Volker Lendecke <vl at samba.org>
---
libcli/nbt/namequery.c | 4 ++--
libcli/nbt/namerefresh.c | 2 +-
libcli/nbt/nameregister.c | 2 +-
libcli/nbt/namerelease.c | 2 +-
libcli/nbt/nbt_proto.h | 3 ++-
libcli/nbt/nbtsocket.c | 5 +++--
6 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/libcli/nbt/namequery.c b/libcli/nbt/namequery.c
index e344235faa8..49ab10c3c02 100644
--- a/libcli/nbt/namequery.c
+++ b/libcli/nbt/namequery.c
@@ -56,7 +56,7 @@ _PUBLIC_ struct nbt_name_request *nbt_name_query_send(struct nbt_name_socket *nb
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,
+ req = nbt_name_request_send(nbtsock, nbtsock, dest, packet,
io->in.timeout, io->in.retries, false);
if (req == NULL) goto failed;
@@ -160,7 +160,7 @@ _PUBLIC_ struct nbt_name_request *nbt_name_status_send(struct nbt_name_socket *n
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,
+ req = nbt_name_request_send(nbtsock, nbtsock, dest, packet,
io->in.timeout, io->in.retries, false);
if (req == NULL) goto failed;
diff --git a/libcli/nbt/namerefresh.c b/libcli/nbt/namerefresh.c
index b525356c747..b3aef76a5c6 100644
--- a/libcli/nbt/namerefresh.c
+++ b/libcli/nbt/namerefresh.c
@@ -72,7 +72,7 @@ struct nbt_name_request *nbt_name_refresh_send(struct nbt_name_socket *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,
+ req = nbt_name_request_send(nbtsock, nbtsock, dest, packet,
io->in.timeout, io->in.retries, false);
if (req == NULL) goto failed;
diff --git a/libcli/nbt/nameregister.c b/libcli/nbt/nameregister.c
index ff5418c85e5..8e8271d5731 100644
--- a/libcli/nbt/nameregister.c
+++ b/libcli/nbt/nameregister.c
@@ -80,7 +80,7 @@ struct nbt_name_request *nbt_name_register_send(struct nbt_name_socket *nbtsock,
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,
+ req = nbt_name_request_send(nbtsock, nbtsock, dest, packet,
io->in.timeout, io->in.retries, false);
if (req == NULL) goto failed;
diff --git a/libcli/nbt/namerelease.c b/libcli/nbt/namerelease.c
index 8f4698169d8..68c8252078b 100644
--- a/libcli/nbt/namerelease.c
+++ b/libcli/nbt/namerelease.c
@@ -69,7 +69,7 @@ _PUBLIC_ struct nbt_name_request *nbt_name_release_send(struct nbt_name_socket *
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,
+ req = nbt_name_request_send(nbtsock, nbtsock, dest, packet,
io->in.timeout, io->in.retries, false);
if (req == NULL) goto failed;
diff --git a/libcli/nbt/nbt_proto.h b/libcli/nbt/nbt_proto.h
index 281ce25a864..e6ee46bab86 100644
--- a/libcli/nbt/nbt_proto.h
+++ b/libcli/nbt/nbt_proto.h
@@ -33,7 +33,8 @@
/* The following definitions come from ../libcli/nbt/nbtsocket.c */
-struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock,
+struct nbt_name_request *nbt_name_request_send(TALLOC_CTX *mem_ctx,
+ struct nbt_name_socket *nbtsock,
struct socket_address *dest,
struct nbt_name_packet *request,
int timeout, int retries,
diff --git a/libcli/nbt/nbtsocket.c b/libcli/nbt/nbtsocket.c
index 711e39cbdc5..94ec4627d80 100644
--- a/libcli/nbt/nbtsocket.c
+++ b/libcli/nbt/nbtsocket.c
@@ -367,7 +367,8 @@ failed:
/*
send off a nbt name request
*/
-struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock,
+struct nbt_name_request *nbt_name_request_send(TALLOC_CTX *mem_ctx,
+ struct nbt_name_socket *nbtsock,
struct socket_address *dest,
struct nbt_name_packet *request,
int timeout, int retries,
@@ -377,7 +378,7 @@ struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock,
int id;
enum ndr_err_code ndr_err;
- req = talloc_zero(nbtsock, struct nbt_name_request);
+ req = talloc_zero(mem_ctx, struct nbt_name_request);
if (req == NULL) goto failed;
req->nbtsock = nbtsock;
--
2.11.0
From 40ad1ac30ddb9b96e89b5a469dce35c00b90eda0 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sun, 25 Feb 2018 13:00:39 +0100
Subject: [PATCH 10/32] libdgram: Fix an error path memleak
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source4/libcli/dgram/mailslot.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/source4/libcli/dgram/mailslot.c b/source4/libcli/dgram/mailslot.c
index 466c603432d..bae26e06c8c 100644
--- a/source4/libcli/dgram/mailslot.c
+++ b/source4/libcli/dgram/mailslot.c
@@ -171,6 +171,7 @@ NTSTATUS dgram_mailslot_send(struct nbt_dgram_socket *dgmsock,
packet.dgram_id = generate_random() % UINT16_MAX;
src = socket_get_my_addr(dgmsock->sock, tmp_ctx);
if (!src) {
+ talloc_free(tmp_ctx);
return NT_STATUS_NO_MEMORY;
}
packet.src_addr = src->addr;
--
2.11.0
From b98cd4c4220c9783e60d8b2bba8b3d051e046bb1 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sun, 25 Feb 2018 13:06:52 +0100
Subject: [PATCH 11/32] libnbt: Factor out dgram_mailslot_init
Separate logic from transport
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source4/libcli/dgram/libdgram.h | 8 +++
source4/libcli/dgram/mailslot.c | 116 ++++++++++++++++++++++++++++------------
2 files changed, 90 insertions(+), 34 deletions(-)
diff --git a/source4/libcli/dgram/libdgram.h b/source4/libcli/dgram/libdgram.h
index 0f313a67cf5..1aa0c65958e 100644
--- a/source4/libcli/dgram/libdgram.h
+++ b/source4/libcli/dgram/libdgram.h
@@ -83,6 +83,14 @@ struct dgram_mailslot_handler {
/* prototypes */
+struct nbt_dgram_packet *dgram_mailslot_init(
+ TALLOC_CTX *mem_ctx,
+ enum dgram_msg_type msg_type,
+ struct nbt_name *src_name,
+ const char *src_address,
+ struct nbt_name *dest_name,
+ const char *mailslot_name,
+ DATA_BLOB *request);
NTSTATUS nbt_dgram_send(struct nbt_dgram_socket *dgmsock,
struct nbt_dgram_packet *packet,
struct socket_address *dest);
diff --git a/source4/libcli/dgram/mailslot.c b/source4/libcli/dgram/mailslot.c
index bae26e06c8c..3d65e4c6f00 100644
--- a/source4/libcli/dgram/mailslot.c
+++ b/source4/libcli/dgram/mailslot.c
@@ -36,6 +36,7 @@
#include "../lib/util/dlinklist.h"
#include "libcli/dgram/libdgram.h"
#include "lib/socket/socket.h"
+#include "libcli/nbt/libnbt.h"
/*
destroy a mailslot handler
@@ -141,50 +142,48 @@ struct dgram_mailslot_handler *dgram_mailslot_temp(struct nbt_dgram_socket *dgms
return NULL;
}
-
-/*
- send a mailslot request
-*/
-NTSTATUS dgram_mailslot_send(struct nbt_dgram_socket *dgmsock,
- enum dgram_msg_type msg_type,
- const char *mailslot_name,
- struct nbt_name *dest_name,
- struct socket_address *dest,
- struct nbt_name *src_name,
- DATA_BLOB *request)
+struct nbt_dgram_packet *dgram_mailslot_init(
+ TALLOC_CTX *mem_ctx,
+ enum dgram_msg_type msg_type,
+ struct nbt_name *src_name,
+ const char *src_address,
+ struct nbt_name *dest_name,
+ const char *mailslot_name,
+ DATA_BLOB *request)
{
- TALLOC_CTX *tmp_ctx = talloc_new(dgmsock);
- struct nbt_dgram_packet packet;
+ struct nbt_dgram_packet *packet;
struct dgram_message *msg;
struct dgram_smb_packet *smb;
struct smb_trans_body *trans;
- struct socket_address *src;
NTSTATUS status;
- if (dest->port == 0) {
- return NT_STATUS_INVALID_PARAMETER;
+ packet = talloc_zero(mem_ctx, struct nbt_dgram_packet);
+ if (packet == NULL) {
+ return NULL;
}
- ZERO_STRUCT(packet);
- packet.msg_type = msg_type;
- packet.flags = DGRAM_FLAG_FIRST | DGRAM_NODE_NBDD;
- packet.dgram_id = generate_random() % UINT16_MAX;
- src = socket_get_my_addr(dgmsock->sock, tmp_ctx);
- if (!src) {
- talloc_free(tmp_ctx);
- return NT_STATUS_NO_MEMORY;
- }
- packet.src_addr = src->addr;
- packet.src_port = src->port;
+ packet->msg_type = msg_type;
+ packet->flags = DGRAM_FLAG_FIRST | DGRAM_NODE_NBDD;
+ packet->dgram_id = generate_random() % UINT16_MAX;
+ packet->src_addr = src_address;
+ packet->src_port = NBT_DGRAM_SERVICE_PORT;
- msg = &packet.data.msg;
- /* this length calculation is very crude - it should be based on gensize
- calls */
+ msg = &packet->data.msg;
+ /*
+ * This length calculation is very crude - it should be based
+ * on gensize calls
+ */
msg->length = 138 + strlen(mailslot_name) + request->length;
msg->offset = 0;
- msg->source_name = *src_name;
- msg->dest_name = *dest_name;
+ status = nbt_name_dup(packet, src_name, &msg->source_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
+ status = nbt_name_dup(packet, dest_name, &msg->dest_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
msg->dgram_body_type = DGRAM_SMB;
smb = &msg->body.smb;
@@ -199,9 +198,58 @@ NTSTATUS dgram_mailslot_send(struct nbt_dgram_socket *dgmsock,
trans->priority = 1;
trans->_class = 2;
trans->mailslot_name = mailslot_name;
- trans->data = *request;
- status = nbt_dgram_send(dgmsock, &packet, dest);
+ trans->data = data_blob_talloc(packet,
+ request->data,
+ request->length);
+ if (trans->data.data == NULL) {
+ goto fail;
+ }
+
+ return packet;
+fail:
+ TALLOC_FREE(packet);
+ return NULL;
+}
+
+/*
+ send a mailslot request
+*/
+NTSTATUS dgram_mailslot_send(struct nbt_dgram_socket *dgmsock,
+ enum dgram_msg_type msg_type,
+ const char *mailslot_name,
+ struct nbt_name *dest_name,
+ struct socket_address *dest,
+ struct nbt_name *src_name,
+ DATA_BLOB *request)
+{
+ TALLOC_CTX *tmp_ctx = talloc_new(dgmsock);
+ struct nbt_dgram_packet *packet;
+ struct socket_address *src;
+ NTSTATUS status;
+
+ if (dest->port == 0) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ src = socket_get_my_addr(dgmsock->sock, tmp_ctx);
+ if (!src) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ packet = dgram_mailslot_init(tmp_ctx,
+ msg_type,
+ src_name,
+ src->addr,
+ dest_name,
+ mailslot_name,
+ request);
+ if (packet == NULL) {
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = nbt_dgram_send(dgmsock, packet, dest);
talloc_free(tmp_ctx);
--
2.11.0
From ff5b465f1c033f527aa7dd561c5fae8ff950367f Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Mon, 5 Mar 2018 14:55:50 +0100
Subject: [PATCH 12/32] nbt_server: Make nbtd_mailslot_netlogon_reply public
Will be used in the next commit
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source4/nbt_server/dgram/netlogon.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source4/nbt_server/dgram/netlogon.c b/source4/nbt_server/dgram/netlogon.c
index 1fee1d8cc1e..52ae96de727 100644
--- a/source4/nbt_server/dgram/netlogon.c
+++ b/source4/nbt_server/dgram/netlogon.c
@@ -179,7 +179,7 @@ static NTSTATUS nbtd_netlogon_samlogon(
return NT_STATUS_OK;
}
-static NTSTATUS nbtd_mailslot_netlogon_reply(
+NTSTATUS nbtd_mailslot_netlogon_reply(
struct nbtd_interface *iface,
struct nbt_dgram_packet *packet,
struct socket_address *src,
--
2.11.0
From a72220c61ee729764a2e25a7870a77d584d0d6d2 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Mon, 29 Jan 2018 19:25:34 +0100
Subject: [PATCH 13/32] nbt_server: Add "unexpected" pipe server
This adds the same functionality to the source4 nbt server that nmbd does as
well: It offers the "unexpected" socket to send and receive netbios port 137
and 138 udp packets. The structure of the nbt_server is significantly different
from nmbd, so we have to implement a bit of the logic in this server piece.
We need this for the AD DC case.
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source4/nbt_server/nbt_server.c | 16 +
source4/nbt_server/nbt_server.h | 4 +
source4/nbt_server/unexpected_pipe.c | 1014 ++++++++++++++++++++++++++++++++++
source4/nbt_server/wscript_build | 1 +
4 files changed, 1035 insertions(+)
create mode 100644 source4/nbt_server/unexpected_pipe.c
diff --git a/source4/nbt_server/nbt_server.c b/source4/nbt_server/nbt_server.c
index 834c72f5f7c..ffe9dbee7c0 100644
--- a/source4/nbt_server/nbt_server.c
+++ b/source4/nbt_server/nbt_server.c
@@ -29,6 +29,7 @@
#include "auth/auth.h"
#include "dsdb/samdb/samdb.h"
#include "param/param.h"
+#include "dynconfig.h"
NTSTATUS server_service_nbtd_init(TALLOC_CTX *);
@@ -40,6 +41,7 @@ static void nbtd_task_init(struct task_server *task)
struct nbtd_server *nbtsrv;
NTSTATUS status;
struct interface *ifaces;
+ const char *nmbd_socket_dir;
load_interface_list(task, task->lp_ctx, &ifaces);
@@ -86,6 +88,20 @@ static void nbtd_task_init(struct task_server *task)
return;
}
+ nmbd_socket_dir = lpcfg_parm_string(
+ task->lp_ctx, NULL, "nmbd", "socket dir");
+
+ status = nbtd_server_init_unexpected_pipe(
+ nbtsrv, task->event_ctx, nbtsrv,
+ nmbd_socket_dir ? nmbd_socket_dir : get_dyn_NMBDSOCKETDIR(),
+ &nbtsrv->unexpected);
+ if (!NT_STATUS_IS_OK(status)) {
+ task_server_terminate(
+ task, "nbtd failed to listen on the unexpected pipe",
+ true);
+ return;
+ }
+
nbtd_register_irpc(nbtsrv);
/* start the process of registering our names on all interfaces */
diff --git a/source4/nbt_server/nbt_server.h b/source4/nbt_server/nbt_server.h
index c80e5bfca07..b93938484eb 100644
--- a/source4/nbt_server/nbt_server.h
+++ b/source4/nbt_server/nbt_server.h
@@ -25,6 +25,8 @@
#include "librpc/gen_ndr/irpc.h"
#include "lib/messaging/irpc.h"
+struct nbtd_unexpected_server;
+
/*
a list of our registered names on each interface
*/
@@ -78,6 +80,8 @@ struct nbtd_server {
struct nbtd_statistics stats;
struct ldb_context *sam_ctx;
+
+ struct nbtd_unexpected_server *unexpected;
};
diff --git a/source4/nbt_server/unexpected_pipe.c b/source4/nbt_server/unexpected_pipe.c
new file mode 100644
index 00000000000..7b75ede7669
--- /dev/null
+++ b/source4/nbt_server/unexpected_pipe.c
@@ -0,0 +1,1014 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * "unexpected" pipe server
+ *
+ * Copyright (C) Volker Lendecke 2018
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include "../lib/util/dlinklist.h"
+#include "system/network.h"
+#include "nbt_server/nbt_server.h"
+#include "lib/socket/socket.h"
+#include "lib/tsocket/tsocket.h"
+#include "smbd/service_task.h"
+#include "librpc/gen_ndr/ndr_nbt.h"
+#include "libcli/nbt/nbt_proto.h"
+#include "source4/nbt_server/dgram/proto.h"
+
+struct nbtd_unexpected_client;
+
+struct nbtd_unexpected_server {
+ struct nbtd_server *nbtd;
+ struct tevent_fd *listen_fde;
+ int sock;
+ struct nbtd_unexpected_client *clients;
+};
+
+/*
+ * Copy from source3/libsmb/unexpected.c
+ */
+enum packet_type {NMB_PACKET, DGRAM_PACKET};
+struct nb_packet_query {
+ enum packet_type type;
+ size_t mailslot_namelen;
+ int trn_id;
+};
+struct nb_packet_client_header {
+ size_t len;
+ enum packet_type type;
+ time_t timestamp;
+ struct in_addr ip;
+ int port;
+};
+
+struct nbtd_unexpected_client {
+ struct nbtd_unexpected_client *prev, *next;
+ struct nbtd_unexpected_server *server;
+ struct tstream_context *sock;
+ struct tevent_queue *out_queue;
+
+ size_t nread;
+
+ struct nb_packet_query query;
+ char *mailslot;
+ struct iovec ack_iov;
+
+ struct nb_packet_client_header hdr;
+ uint8_t buf[1024];
+};
+
+static int nbtd_unexpected_server_destructor(struct nbtd_unexpected_server *s);
+static void nb_unexpected_server_listener(
+ struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags,
+ void *private_data);
+
+NTSTATUS nbtd_server_init_unexpected_pipe(
+ TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+ struct nbtd_server *nbtd, const char *socket_dir,
+ struct nbtd_unexpected_server **psrv)
+{
+ struct nbtd_unexpected_server *srv;
+ struct sockaddr_un sunaddr = { .sun_family = AF_UNIX };
+ int len, ret;
+ NTSTATUS status;
+ bool ok;
+
+ srv = talloc_zero(mem_ctx, struct nbtd_unexpected_server);
+ if (srv == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ srv->nbtd = nbtd;
+
+ len = snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path),
+ "%s/unexpected", socket_dir);
+ if ((size_t)len >= sizeof(sunaddr.sun_path)) {
+ status = NT_STATUS_NAME_TOO_LONG;
+ goto done;
+ }
+
+ ok = directory_create_or_exist(socket_dir, 0755);
+ if (!ok) {
+ status = map_nt_error_from_unix_common(errno);
+ goto done;
+ }
+
+ srv->sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (srv->sock == -1) {
+ status = map_nt_error_from_unix_common(errno);
+ goto done;
+ }
+ talloc_set_destructor(srv, nbtd_unexpected_server_destructor);
+
+ unlink(sunaddr.sun_path);
+
+ ret = bind(srv->sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
+ if (ret == -1) {
+ status = map_nt_error_from_unix_common(errno);
+ goto done;
+ }
+
+ ret = listen(srv->sock, 5);
+ if (ret == -1) {
+ status = map_nt_error_from_unix_common(errno);
+ goto done;
+ }
+
+ srv->listen_fde = tevent_add_fd(
+ ev, srv, srv->sock, TEVENT_FD_READ,
+ nb_unexpected_server_listener, srv);
+ if (srv->listen_fde == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ status = NT_STATUS_OK;
+done:
+ if (NT_STATUS_IS_OK(status)) {
+ *psrv = srv;
+ } else {
+ TALLOC_FREE(srv);
+ }
+ return status;
+}
+
+static int nbtd_unexpected_client_destructor(struct nbtd_unexpected_client *c);
+static int nbtd_unexpected_client_next_vec(struct tstream_context *stream,
+ void *private_data,
+ TALLOC_CTX *mem_ctx,
+ struct iovec **_vector,
+ size_t *_count);
+static void nbtd_unexpected_client_got_query(struct tevent_req *req);
+static void nbtd_unexpected_client_ack_done(struct tevent_req *req);
+static int nbtd_unexpected_client_pkt_next_vec(struct tstream_context *stream,
+ void *private_data,
+ TALLOC_CTX *mem_ctx,
+ struct iovec **_vector,
+ size_t *_count);
+static void nbtd_unexpected_client_got_pkt(struct tevent_req *req);
+
+static void nb_unexpected_server_listener(
+ struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags,
+ void *private_data)
+{
+ struct nbtd_unexpected_server *srv = talloc_get_type_abort(
+ private_data, struct nbtd_unexpected_server);
+ struct nbtd_unexpected_client *client;
+ struct tevent_req *req;
+ int ret, sock;
+
+ sock = accept(srv->sock, NULL, NULL);
+ if (sock == -1) {
+ return;
+ }
+ smb_set_close_on_exec(sock);
+
+ client = talloc_zero(srv, struct nbtd_unexpected_client);
+ if (client == NULL) {
+ close(sock);
+ return;
+ }
+ ret = tstream_bsd_existing_socket(client, sock, &client->sock);
+ if (ret == -1) {
+ close(sock);
+ TALLOC_FREE(client);
+ return;
+ }
+ sock = -1;
+
+ client->server = srv;
+ DLIST_ADD(srv->clients, client);
+ talloc_set_destructor(client, nbtd_unexpected_client_destructor);
+
+ client->out_queue = tevent_queue_create(
+ client, "unexpected packet output");
+ if (client->out_queue == NULL) {
+ DEBUG(10, ("tevent_queue_create failed\n"));
+ TALLOC_FREE(client);
+ return;
+ }
+
+ req = tstream_readv_pdu_send(
+ client, client->server->nbtd->task->event_ctx, client->sock,
+ nbtd_unexpected_client_next_vec, client);
+ if (req == NULL) {
+ TALLOC_FREE(client);
+ return;
+ }
+ tevent_req_set_callback(req, nbtd_unexpected_client_got_query, client);
+}
+
+static int nbtd_unexpected_server_destructor(struct nbtd_unexpected_server *s)
+{
+ while (s->clients != NULL) {
+ TALLOC_FREE(s->clients);
+ }
+
+ TALLOC_FREE(s->listen_fde);
+
+ if (s->sock != -1) {
+ close(s->sock);
+ s->sock = -1;
+ }
+
+ return 0;
+}
+
+static int nbtd_unexpected_client_destructor(struct nbtd_unexpected_client *c)
+{
+ DLIST_REMOVE(c->server->clients, c);
+ return 0;
+}
+
+static int nbtd_unexpected_client_next_vec(struct tstream_context *stream,
+ void *private_data,
+ TALLOC_CTX *mem_ctx,
+ struct iovec **_vector,
+ size_t *_count)
+{
+ struct nbtd_unexpected_client *client = talloc_get_type_abort(
+ private_data, struct nbtd_unexpected_client);
+ struct iovec *vector;
+
+ if (client->nread == 0) {
+ vector = talloc_array(mem_ctx, struct iovec, 1);
+ if (vector == NULL) {
+ return -1;
+ }
+ vector[0] = (struct iovec) {
+ .iov_base = &client->query,
+ .iov_len = sizeof(client->query)
+ };
+ client->nread = sizeof(client->query);
+
+ *_vector = vector;
+ *_count = 1;
+ return 0;
+ }
+
+ if (client->nread == sizeof(client->query)) {
+ size_t mailslot_namelen = client->query.mailslot_namelen;
+
+ if (mailslot_namelen > 1024) {
+ return -1;
+ }
+ if (mailslot_namelen == 0) {
+ *_vector = NULL;
+ *_count = 0;
+ return 0;
+ }
+
+ client->mailslot = talloc_array(client, char,
+ mailslot_namelen+1);
+ if (client->mailslot == NULL) {
+ return -1;
+ }
+ client->mailslot[mailslot_namelen] = '\0';
+
+ vector = talloc_array(mem_ctx, struct iovec, 1);
+ if (vector == 0) {
+ return -1;
+ }
+ vector[0] = (struct iovec) {
+ .iov_base = client->mailslot,
+ .iov_len = mailslot_namelen
+ };
+ client->nread += mailslot_namelen;
+
+ *_vector = vector;
+ *_count = 1;
+ return 0;
+ }
+
+ *_vector = NULL;
+ *_count = 0;
+ return 0;
+}
+
+static void nbtd_unexpected_write_dgm(struct nbtd_unexpected_client *client,
+ struct in_addr from,
+ struct nbt_dgram_packet *packet);
+
+static void nbtd_unexpected_mailslot_handler(
+ struct dgram_mailslot_handler *handler,
+ struct nbt_dgram_packet *packet,
+ struct socket_address *from)
+{
+ struct nbtd_unexpected_client *client = talloc_get_type_abort(
+ handler->private_data, struct nbtd_unexpected_client);
+ struct sockaddr_in *from_in;
+
+ if ((from->sockaddr == NULL) ||
+ (from->sockaddrlen != sizeof(struct sockaddr_in))) {
+ DBG_DEBUG("Invalid from: %p/%zu\n", from->sockaddr,
+ (size_t)from->sockaddrlen);
+ return;
+ }
+ from_in = (struct sockaddr_in *)from->sockaddr;
+
+ nbtd_unexpected_write_dgm(client, from_in->sin_addr, packet);
+}
+
+struct nbtd_unexpected_write_dgm_state {
+ struct iovec iov[2];
+ struct nb_packet_client_header hdr;
+};
+
+static void nbtd_unexpected_write_dgm_written(struct tevent_req *req);
+
+static void nbtd_unexpected_write_dgm(struct nbtd_unexpected_client *client,
+ struct in_addr from,
+ struct nbt_dgram_packet *packet)
+{
+ struct nbtd_unexpected_write_dgm_state *state;
+ struct tevent_req *req;
+ enum ndr_err_code ndr_err;
+ DATA_BLOB blob;
+
+ {
+ char fromstr[INET_ADDRSTRLEN];
+ inet_ntop(AF_INET, &from, fromstr, sizeof(fromstr));
+ DBG_DEBUG("Sending DGM from %s to unexpected client\n",
+ fromstr);
+ }
+
+ state = talloc(client, struct nbtd_unexpected_write_dgm_state);
+ if (state == NULL) {
+ return;
+ }
+ state->hdr = (struct nb_packet_client_header) {
+ .type = DGRAM_PACKET, .timestamp = time(NULL), .ip = from
+ };
+
+ ndr_err = ndr_push_struct_blob(
+ &blob, state, packet,
+ (ndr_push_flags_fn_t)ndr_push_nbt_dgram_packet);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ talloc_free(state);
+ return;
+ }
+ state->hdr.len = blob.length;
+
+ state->iov[0] = (struct iovec) {
+ .iov_base = &state->hdr, .iov_len = sizeof(state->hdr)
+ };
+ state->iov[1] = (struct iovec) {
+ .iov_base = blob.data, .iov_len = blob.length
+ };
+
+ req = tstream_writev_queue_send(
+ state, client->server->nbtd->task->event_ctx,
+ client->sock, client->out_queue,
+ state->iov, ARRAY_SIZE(state->iov));
+ if (req == NULL) {
+ TALLOC_FREE(state);
+ return;
+ }
+ tevent_req_set_callback(req, nbtd_unexpected_write_dgm_written, state);
+}
+
+static void nbtd_unexpected_write_dgm_written(struct tevent_req *req)
+{
+ struct nbtd_unexpected_write_dgm_state *state =
+ tevent_req_callback_data(
+ req, struct nbtd_unexpected_write_dgm_state);
+ TALLOC_FREE(state);
+}
+
+static bool nbtd_unexpected_setup_mailslots(struct nbtd_unexpected_client *c,
+ const char *mailslot_name)
+{
+ struct nbtd_server *srv = c->server->nbtd;
+ struct nbtd_interface *interface;
+
+ for (interface = srv->interfaces; interface != NULL;
+ interface = interface->next) {
+ struct dgram_mailslot_handler *dgmslot;
+
+ if (interface->dgmsock == NULL) {
+ continue;
+ }
+
+ dgmslot = dgram_mailslot_listen(
+ interface->dgmsock, mailslot_name,
+ nbtd_unexpected_mailslot_handler, c);
+ if (dgmslot == NULL) {
+ DBG_DEBUG("dgram_mailslot_listen failed\n");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void nbtd_unexpected_client_got_query(struct tevent_req *req)
+{
+ struct nbtd_unexpected_client *client = tevent_req_callback_data(
+ req, struct nbtd_unexpected_client);
+ int ret, err;
+
+ ret = tstream_readv_pdu_recv(req, &err);
+ TALLOC_FREE(req);
+ if (ret == -1) {
+ TALLOC_FREE(client);
+ return;
+ }
+
+ if (client->mailslot != NULL) {
+ bool ok;
+
+ DBG_WARNING("Listening on mailslot %s\n", client->mailslot);
+
+ ok = nbtd_unexpected_setup_mailslots(client, client->mailslot);
+ if (!ok) {
+ TALLOC_FREE(client);
+ return;
+ }
+ }
+
+ client->nread = 0;
+
+ req = tstream_readv_pdu_send(
+ client, client->server->nbtd->task->event_ctx, client->sock,
+ nbtd_unexpected_client_pkt_next_vec, client);
+ if (req == NULL) {
+ TALLOC_FREE(client);
+ return;
+ }
+ tevent_req_set_callback(req, nbtd_unexpected_client_got_pkt, client);
+
+ client->ack_iov = (struct iovec) {
+ .iov_base = &client->nread, /* Just *any* byte that's there */
+ .iov_len = 1
+ };
+
+ req = tstream_writev_queue_send(
+ client, client->server->nbtd->task->event_ctx,
+ client->sock, client->out_queue, &client->ack_iov, 1);
+ if (req == NULL) {
+ TALLOC_FREE(client);
+ return;
+ }
+ tevent_req_set_callback(req, nbtd_unexpected_client_ack_done, client);
+}
+
+static void nbtd_unexpected_client_ack_done(struct tevent_req *req)
+{
+ struct nbtd_unexpected_client *client = tevent_req_callback_data(
+ req, struct nbtd_unexpected_client);
+ ssize_t nwritten;
+ int err;
+
+ nwritten = tstream_writev_queue_recv(req, &err);
+
+ TALLOC_FREE(req);
+
+ if (nwritten == -1) {
+ DEBUG(10, ("tstream_writev_queue_recv failed: %s\n",
+ strerror(err)));
+ TALLOC_FREE(client);
+ return;
+ }
+}
+
+static int nbtd_unexpected_client_pkt_next_vec(struct tstream_context *stream,
+ void *private_data,
+ TALLOC_CTX *mem_ctx,
+ struct iovec **_vector,
+ size_t *_count)
+{
+ struct nbtd_unexpected_client *client = talloc_get_type_abort(
+ private_data, struct nbtd_unexpected_client);
+ struct iovec *vector;
+
+ if (client->nread == 0) {
+ vector = talloc_array(mem_ctx, struct iovec, 1);
+ if (vector == NULL) {
+ return -1;
+ }
+ vector[0] = (struct iovec) {
+ .iov_base = &client->hdr,
+ .iov_len = sizeof(client->hdr)
+ };
+ client->nread = sizeof(client->hdr);
+
+ *_vector = vector;
+ *_count = 1;
+ return 0;
+ }
+
+ if (client->nread == sizeof(client->hdr)) {
+ size_t len = client->hdr.len;
+
+ if ((len == 0) || (len > sizeof(client->buf))) {
+ return -1;
+ }
+
+ vector = talloc_array(mem_ctx, struct iovec, 1);
+ if (vector == 0) {
+ return -1;
+ }
+ vector[0] = (struct iovec) {
+ .iov_base = client->buf, .iov_len = len
+ };
+ client->nread += len;
+
+ *_vector = vector;
+ *_count = 1;
+ return 0;
+ }
+
+ *_vector = NULL;
+ *_count = 0;
+ return 0;
+}
+
+static void nbtd_unexpected_handle_nmb(struct nbtd_server *srv,
+ struct nbtd_unexpected_client *client,
+ struct nb_packet_client_header *hdr,
+ struct nbt_name_packet *packet);
+static void nbtd_unexpected_handle_dgm(struct nbtd_server *srv,
+ struct nbtd_unexpected_client *client,
+ struct nb_packet_client_header *hdr,
+ struct nbt_dgram_packet *packet);
+
+static void nbtd_unexpected_client_got_pkt(struct tevent_req *req)
+{
+ struct nbtd_unexpected_client *client = tevent_req_callback_data(
+ req, struct nbtd_unexpected_client);
+ int ret, err;
+ enum ndr_err_code ndr_err;
+ DATA_BLOB blob = { .data = client->buf, .length = client->hdr.len };
+
+ ret = tstream_readv_pdu_recv(req, &err);
+ TALLOC_FREE(req);
+ if (ret == -1) {
+ TALLOC_FREE(client);
+ return;
+ }
+
+ if (client->hdr.type == NMB_PACKET) {
+ struct nbt_name_packet *packet;
+
+ packet = talloc(client, struct nbt_name_packet);
+ if (packet == NULL) {
+ goto next;
+ }
+
+ ndr_err = ndr_pull_struct_blob(
+ &blob, packet, packet,
+ (ndr_pull_flags_fn_t)ndr_pull_nbt_name_packet);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DBG_NOTICE("Failed to parse packet: %s, "
+ "dropping client\n",
+ ndr_errstr(ndr_err));
+ TALLOC_FREE(client);
+ return;
+ }
+
+ DBG_DEBUG("Got nmb packet: %s\n", ndr_errstr(ndr_err));
+
+ nbtd_unexpected_handle_nmb(client->server->nbtd, client,
+ &client->hdr, packet);
+
+ TALLOC_FREE(packet);
+ }
+
+ if (client->hdr.type == DGRAM_PACKET) {
+ struct nbt_dgram_packet *packet;
+
+ packet = talloc(client, struct nbt_dgram_packet);
+ if (packet == NULL) {
+ goto next;
+ }
+
+ ndr_err = ndr_pull_struct_blob(
+ &blob, packet, packet,
+ (ndr_pull_flags_fn_t)ndr_pull_nbt_dgram_packet);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DBG_NOTICE("Failed to parse packet: %s, "
+ "dropping client\n",
+ ndr_errstr(ndr_err));
+ TALLOC_FREE(client);
+ return;
+ }
+
+ DBG_DEBUG("Got dgm packet for %s\n", ndr_errstr(ndr_err));
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_DEBUG(nbt_dgram_packet, packet);
+ }
+
+ nbtd_unexpected_handle_dgm(client->server->nbtd, client,
+ &client->hdr, packet);
+
+ TALLOC_FREE(packet);
+ }
+
+next:
+ client->nread = 0;
+
+ req = tstream_readv_pdu_send(
+ client, client->server->nbtd->task->event_ctx, client->sock,
+ nbtd_unexpected_client_pkt_next_vec, client);
+ if (req == NULL) {
+ TALLOC_FREE(client);
+ return;
+ }
+ tevent_req_set_callback(req, nbtd_unexpected_client_got_pkt, client);
+}
+
+static void nbtd_unexpected_write_nmb(struct nbtd_unexpected_client *client,
+ struct in_addr from,
+ struct nbt_name_packet *packet);
+static void nbtd_unexpected_sent_nmb(struct nbt_name_request *req);
+
+static void nbtd_unexpected_handle_nmb(struct nbtd_server *srv,
+ struct nbtd_unexpected_client *client,
+ struct nb_packet_client_header *hdr,
+ struct nbt_name_packet *packet)
+{
+ if (((packet->operation & NBT_OPCODE) == NBT_OPCODE_QUERY) &&
+ (packet->qdcount == 1) &&
+ (packet->questions[0].question_type == NBT_QTYPE_NETBIOS) &&
+ (packet->questions[0].question_class == NBT_QCLASS_IP)) {
+
+ /*
+ * Try to answer name queries locally
+ */
+
+ struct nbt_name *qname = &packet->questions[0].name;
+ struct nbtd_interface *interface;
+ struct nbtd_iface_name *iname = NULL;
+
+ for (interface = srv->interfaces; interface != NULL;
+ interface = interface->next) {
+ if (interface->ip_address == NULL) {
+ /* Not sure this can happen */
+ continue;
+ }
+
+ iname = nbtd_find_iname(interface, qname, 0);
+
+ if (iname != NULL) {
+ break;
+ }
+ }
+
+ if (iname != NULL) {
+ struct nbt_name_packet *reply;
+ struct in_addr from;
+ int ret;
+
+ ret = inet_pton(AF_INET, interface->ip_address, &from);
+ if (ret != 1) {
+ return;
+ }
+
+ reply = nbtd_name_query_reply_packet(
+ packet, packet->name_trn_id, iname->ttl,
+ iname->nb_flags, qname,
+ &interface->ip_address, 1);
+ if (reply == NULL) {
+ return;
+ }
+
+ nbtd_unexpected_write_nmb(client, from, reply);
+
+ TALLOC_FREE(reply);
+ return;
+ }
+ }
+
+ if (((packet->operation & NBT_OPCODE) == NBT_OPCODE_QUERY) &&
+ (packet->qdcount == 1) &&
+ (packet->questions[0].question_type == NBT_QTYPE_STATUS) &&
+ (packet->questions[0].question_class == NBT_QCLASS_IP)) {
+
+ /*
+ * Do a node status request locally
+ */
+
+ struct nbt_name *qname = &packet->questions[0].name;
+ struct nbtd_interface *interface;
+ struct nbtd_iface_name *iname = NULL;
+
+ for (interface = srv->interfaces; interface != NULL;
+ interface = interface->next) {
+ iname = nbtd_find_iname(interface, qname, 0);
+ if (iname != NULL) {
+ break;
+ }
+ }
+
+ if (iname != NULL) {
+ struct nbt_name_packet *reply;
+ struct in_addr from;
+ int ret;
+
+ ret = inet_pton(AF_INET, interface->ip_address, &from);
+ if (ret != 1) {
+ return;
+ }
+
+ reply = nbtd_node_status_reply_packet(
+ packet, packet->name_trn_id, qname, interface);
+ if (reply == NULL) {
+ return;
+ }
+
+ nbtd_unexpected_write_nmb(client, from, reply);
+
+ TALLOC_FREE(reply);
+ return;
+ }
+ }
+
+ if (packet->operation & NBT_FLAG_BROADCAST) {
+
+ /*
+ * Broadcast to all interfaces
+ */
+
+ struct nbtd_interface *interface;
+
+ for (interface = srv->interfaces; interface != NULL;
+ interface = interface->next) {
+ struct socket_address *addr;
+ struct nbt_name_request *req;
+
+ addr = socket_address_from_strings(
+ packet, "ip", interface->bcast_address,
+ NBT_NAME_SERVICE_PORT);
+ if (addr == NULL) {
+ continue;
+ }
+
+ /*
+ * "false" here is wrong, but nmblookup4 does
+ * the same. Also, nbt_name_request_send/recv
+ * does not have the capability to intercept
+ * replies as they come in. For "make test"
+ * and winbind it should be good enough.
+ *
+ * When winbind on a AD DC needs to connect to
+ * NT4 domains, choosing between multiple
+ * group-registered DCs, this will become
+ * relevant. Then we need to enhance
+ * libcli/nbt.
+ */
+ req = nbt_name_request_send(
+ client, interface->nbtsock, addr,
+ packet, 1, 0, false);
+
+ /* nbt_name_request_send takes a reference */
+ talloc_unlink(packet, addr);
+
+ if (req != NULL) {
+ req->async.fn = nbtd_unexpected_sent_nmb;
+ req->async.private_data = client;
+ }
+ }
+
+ return;
+ }
+
+ /* TODO: Proxy WINS requests -- do we still need those? */
+}
+
+struct nbtd_unexpected_write_nmb_state {
+ struct iovec iov[2];
+ struct nb_packet_client_header hdr;
+};
+
+static void nbtd_unexpected_write_nmb_written(struct tevent_req *req);
+
+static void nbtd_unexpected_write_nmb(struct nbtd_unexpected_client *client,
+ struct in_addr from,
+ struct nbt_name_packet *packet)
+{
+ struct nbtd_unexpected_write_nmb_state *state;
+ struct tevent_req *req;
+ enum ndr_err_code ndr_err;
+ DATA_BLOB blob;
+
+ state = talloc(client, struct nbtd_unexpected_write_nmb_state);
+ if (state == NULL) {
+ return;
+ }
+ state->hdr = (struct nb_packet_client_header) {
+ .type = NMB_PACKET, .timestamp = time(NULL), .ip = from
+ };
+
+ ndr_err = ndr_push_struct_blob(
+ &blob, state, packet,
+ (ndr_push_flags_fn_t)ndr_push_nbt_name_packet);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ talloc_free(state);
+ return;
+ }
+ state->hdr.len = blob.length;
+
+ state->iov[0] = (struct iovec) {
+ .iov_base = &state->hdr, .iov_len = sizeof(state->hdr)
+ };
+ state->iov[1] = (struct iovec) {
+ .iov_base = blob.data, .iov_len = blob.length
+ };
+
+ req = tstream_writev_queue_send(
+ state, client->server->nbtd->task->event_ctx,
+ client->sock, client->out_queue,
+ state->iov, ARRAY_SIZE(state->iov));
+ if (req == NULL) {
+ TALLOC_FREE(state);
+ return;
+ }
+ tevent_req_set_callback(req, nbtd_unexpected_write_nmb_written, state);
+}
+
+static void nbtd_unexpected_write_nmb_written(struct tevent_req *req)
+{
+ struct nbtd_unexpected_write_nmb_state *state =
+ tevent_req_callback_data(
+ req, struct nbtd_unexpected_write_nmb_state);
+ TALLOC_FREE(state);
+}
+
+static void nbtd_unexpected_sent_nmb(struct nbt_name_request *req)
+{
+ struct nbtd_unexpected_client *client = talloc_get_type_abort(
+ req->async.private_data, struct nbtd_unexpected_client);
+ unsigned int i;
+
+ for (i=0; i<req->num_replies; i++) {
+ struct nbt_name_reply *reply = &req->replies[i];
+ struct socket_address *from = reply->dest;
+ struct sockaddr_in *from_in;
+
+ if ((from->sockaddr == NULL) ||
+ (from->sockaddrlen != sizeof(struct sockaddr_in))) {
+ continue;
+ }
+ from_in = (struct sockaddr_in *)from->sockaddr;
+
+ nbtd_unexpected_write_nmb(client, from_in->sin_addr,
+ reply->packet);
+ }
+
+ TALLOC_FREE(req);
+}
+
+static bool nbtd_unexpected_handle_local_dgm(
+ struct nbtd_server *srv,
+ struct nbtd_unexpected_client *client,
+ struct nbtd_interface *interface,
+ struct nb_packet_client_header *hdr,
+ struct nbt_dgram_packet *packet);
+
+static void nbtd_unexpected_handle_dgm(struct nbtd_server *srv,
+ struct nbtd_unexpected_client *client,
+ struct nb_packet_client_header *hdr,
+ struct nbt_dgram_packet *packet)
+{
+ struct nbtd_interface *interface;
+ char addr[INET_ADDRSTRLEN];
+ struct socket_address *dest;
+ NTSTATUS status;
+ bool ok;
+
+ inet_ntop(AF_INET, &client->hdr.ip, addr, sizeof(addr));
+
+ interface = nbtd_find_request_iface(client->server->nbtd,
+ addr, true);
+ if (interface == NULL) {
+ DBG_DEBUG("Failed to find iface for %s\n", addr);
+ return;
+ }
+
+ ok = nbtd_unexpected_handle_local_dgm(srv, client, interface, hdr,
+ packet);
+ if (ok) {
+ DBG_DEBUG("Packet for %s handled locally\n", addr);
+ return;
+ }
+
+ dest = socket_address_from_strings(
+ packet, "ip", addr, NBT_DGRAM_SERVICE_PORT);
+ if (dest == NULL) {
+ DBG_DEBUG("socket_address_from_strings for %s "
+ "failed\n", addr);
+ return;
+ }
+
+ status = nbt_dgram_send(interface->dgmsock, packet, dest);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("nbt_dgram_send to %s failed: %s\n", addr,
+ nt_errstr(status));
+ return;
+ }
+}
+
+static bool nbtd_unexpected_handle_local_dgm(
+ struct nbtd_server *srv,
+ struct nbtd_unexpected_client *client,
+ struct nbtd_interface *interface,
+ struct nb_packet_client_header *hdr,
+ struct nbt_dgram_packet *packet)
+{
+ struct dgram_message *msg;
+ struct nbtd_iface_name *iname;
+ struct socket_address *src;
+ struct nbt_netlogon_response *reply = NULL;
+ DATA_BLOB reply_blob;
+ struct nbt_dgram_packet *reply_packet;
+ char *reply_mailslot = NULL;
+ struct in_addr from;
+ NTSTATUS status;
+ int ret;
+
+ ret = inet_pton(AF_INET, interface->ip_address, &from);
+ if (ret != 1) {
+ DBG_DEBUG("inet_pton failed\n");
+ return false;
+ }
+
+ if (packet->msg_type != DGRAM_DIRECT_GROUP) {
+ DBG_DEBUG("packet->msg_type = %d\n", (int)packet->msg_type);
+ return false;
+ }
+
+ msg = &packet->data.msg;
+
+ iname = nbtd_find_iname(interface, &msg->dest_name, 0);
+ if (iname == NULL) {
+ DBG_DEBUG("Local name %s not found\n", msg->dest_name.name);
+ return false;
+ }
+
+ DBG_DEBUG("Found Interface address %s\n", interface->ip_address);
+
+ src = socket_address_from_strings(packet,
+ "ip",
+ interface->ip_address,
+ NBT_DGRAM_SERVICE_PORT);
+ if (src == NULL) {
+ DBG_DEBUG("socket_address_from_strings failed\n");
+ return false;
+ }
+
+ status = nbtd_mailslot_netlogon_reply(interface,
+ packet,
+ src,
+ packet,
+ &reply,
+ &reply_mailslot);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("nbtd_mailslot_netlogon_reply failed: %s\n",
+ nt_errstr(status));
+ return false;
+ }
+
+ DBG_DEBUG("Sending reply to mailslot %s\n", reply_mailslot);
+
+ status = push_nbt_netlogon_response(&reply_blob, packet, reply);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("push_nbt_netlogon_response failed: %s\n",
+ nt_errstr(status));
+ return false;
+ }
+
+ reply_packet = dgram_mailslot_init(packet,
+ DGRAM_DIRECT_UNIQUE,
+ &msg->dest_name,
+ interface->ip_address,
+ &msg->source_name,
+ reply_mailslot,
+ &reply_blob);
+ if (reply_packet == NULL) {
+ DBG_DEBUG("dgram_mailslot_init failed\n");
+ return false;
+ }
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_DEBUG(nbt_dgram_packet, reply_packet);
+ }
+
+ nbtd_unexpected_write_dgm(client, from, reply_packet);
+
+ return true;
+}
diff --git a/source4/nbt_server/wscript_build b/source4/nbt_server/wscript_build
index 632d5fbe41d..45e972c6bc0 100644
--- a/source4/nbt_server/wscript_build
+++ b/source4/nbt_server/wscript_build
@@ -43,6 +43,7 @@ bld.SAMBA_SUBSYSTEM('NBT_SERVER',
nodestatus.c
defense.c
packet.c
+ unexpected_pipe.c
irpc.c''',
autoproto='nbt_server_proto.h',
deps='cli-nbt NBTD_WINS NBTD_DGRAM service',
--
2.11.0
From afb54a7de4d359fd8b6c2fd98650e6a2534d8eae Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 23 Jan 2018 22:02:16 +0100
Subject: [PATCH 14/32] libsmb: Add nb_packet_write_send/recv
This is the client end of the packet proxy into nmbd
---
source3/libsmb/unexpected.c | 68 +++++++++++++++++++++++++++++++++++++++++++++
source3/libsmb/unexpected.h | 5 ++++
2 files changed, 73 insertions(+)
diff --git a/source3/libsmb/unexpected.c b/source3/libsmb/unexpected.c
index 6d7a8452073..3283a0b6e77 100644
--- a/source3/libsmb/unexpected.c
+++ b/source3/libsmb/unexpected.c
@@ -503,6 +503,7 @@ static void nb_packet_client_send_done(struct tevent_req *req)
struct nb_packet_reader {
struct tstream_context *sock;
+ struct tevent_queue *out_queue;
};
struct nb_packet_reader_state {
@@ -549,6 +550,12 @@ struct tevent_req *nb_packet_reader_send(TALLOC_CTX *mem_ctx,
return tevent_req_post(req, ev);
}
+ state->reader->out_queue = tevent_queue_create(
+ state->reader, "nb_packet_reader send queue");
+ if (tevent_req_nomem(state->reader->out_queue, req)) {
+ return tevent_req_post(req, ev);
+ }
+
ret = tsocket_address_unix_from_path(state, NULL, &laddr);
if (ret != 0) {
tevent_req_nterror(req, map_nt_error_from_unix(errno));
@@ -829,3 +836,64 @@ NTSTATUS nb_packet_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
*ppacket = talloc_move(mem_ctx, &state->pkt);
return NT_STATUS_OK;
}
+
+struct nb_packet_write_state {
+ struct iovec iov[2];
+ struct nb_packet_client_header hdr;
+ char buf[1024];
+};
+
+static void nb_packet_write_done(struct tevent_req *subreq);
+
+struct tevent_req *nb_packet_write_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct nb_packet_reader *reader,
+ struct packet_struct *packet)
+{
+ struct tevent_req *req, *subreq;
+ struct nb_packet_write_state *state;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct nb_packet_write_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->hdr.ip = packet->ip;
+ state->hdr.port = packet->port;
+ state->hdr.timestamp = packet->timestamp;
+ state->hdr.type = packet->packet_type;
+ state->hdr.len = build_packet(state->buf, sizeof(state->buf), packet);
+
+ state->iov[0].iov_base = (char *)&state->hdr;
+ state->iov[0].iov_len = sizeof(state->hdr);
+ state->iov[1].iov_base = state->buf;
+ state->iov[1].iov_len = state->hdr.len;
+
+ subreq = tstream_writev_queue_send(state, ev, reader->sock,
+ reader->out_queue, state->iov, 2);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(req, nb_packet_write_done, state);
+ return req;
+}
+
+static void nb_packet_write_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ int ret, err;
+
+ ret = tstream_writev_queue_recv(subreq, &err);
+ TALLOC_FREE(subreq);
+ if (ret == -1) {
+ tevent_req_nterror(req, map_nt_error_from_unix_common(err));
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS nb_packet_write_recv(struct tevent_req *req)
+{
+ return tevent_req_simple_recv_ntstatus(req);
+}
diff --git a/source3/libsmb/unexpected.h b/source3/libsmb/unexpected.h
index b06b8763549..cd0a1058cba 100644
--- a/source3/libsmb/unexpected.h
+++ b/source3/libsmb/unexpected.h
@@ -48,5 +48,10 @@ struct tevent_req *nb_packet_read_send(TALLOC_CTX *mem_ctx,
struct nb_packet_reader *reader);
NTSTATUS nb_packet_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
struct packet_struct **ppacket);
+struct tevent_req *nb_packet_write_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct nb_packet_reader *reader,
+ struct packet_struct *packet);
+NTSTATUS nb_packet_write_recv(struct tevent_req *req);
#endif
--
2.11.0
From 27754af0861c4895f8261dbd2a368620cbd9009c Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 20 Jan 2018 09:31:15 +0000
Subject: [PATCH 15/32] libsmb: Add nb_call_send/recv
This wraps connecting to the "unexpected" nmbd pipe, sending and re-sending a
packet and listening for replies.
The difference to nb_trans_send_recv is that we hand a packet_struct down, so
that we don't have to do the build_packet in the caller.
---
source3/libsmb/nb_call.c | 201 +++++++++++++++++++++++++++++++++++++++++++++++
source3/libsmb/nb_call.h | 39 +++++++++
source3/wscript_build | 1 +
3 files changed, 241 insertions(+)
create mode 100644 source3/libsmb/nb_call.c
create mode 100644 source3/libsmb/nb_call.h
diff --git a/source3/libsmb/nb_call.c b/source3/libsmb/nb_call.c
new file mode 100644
index 00000000000..ba229082ff5
--- /dev/null
+++ b/source3/libsmb/nb_call.c
@@ -0,0 +1,201 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Do a NetBIOS call via nmbd
+ * Copyright (C) Volker Lendecke 2018
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include <tevent.h>
+#include "libsmb/nb_call.h"
+#include "nameserv.h"
+#include "libsmb/unexpected.h"
+#include "lib/util/tevent_ntstatus.h"
+
+struct nb_call_state {
+ struct tevent_context *ev;
+ struct nb_packet_reader *reader;
+
+ struct packet_struct *pkt;
+ bool (*validator)(struct packet_struct *p, void *private_data);
+ void *private_data;
+
+ struct packet_struct *result;
+};
+
+static void nb_call_got_reader(struct tevent_req *subreq);
+static void nb_call_got_pkt(struct tevent_req *subreq);
+static void nb_call_written(struct tevent_req *subreq);
+static void nb_call_resend(struct tevent_req *subreq);
+
+struct tevent_req *nb_call_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct packet_struct *pkt,
+ int trn_id, const char *mailslot_name,
+ bool (*validator)(struct packet_struct *p,
+ void *private_data),
+ void *private_data)
+{
+ struct tevent_req *req, *subreq;
+ struct nb_call_state *state;
+
+ req = tevent_req_create(mem_ctx, &state, struct nb_call_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->ev = ev;
+ state->pkt = pkt;
+ state->validator = validator;
+ state->private_data = private_data;
+
+ subreq = nb_packet_reader_send(state, ev, pkt->packet_type,
+ trn_id, mailslot_name);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, nb_call_got_reader, req);
+ return req;
+}
+
+static void nb_call_got_reader(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct nb_call_state *state = tevent_req_data(
+ req, struct nb_call_state);
+ NTSTATUS status;
+
+ status = nb_packet_reader_recv(subreq, state, &state->reader);
+ TALLOC_FREE(subreq);
+
+ if (NT_STATUS_EQUAL(NT_STATUS_CONNECTION_REFUSED, status)) {
+ /*
+ * At a higher level this might be seen as a network
+ * error. Use a more specific error message for "nmbd
+ * not around".
+ */
+ status = NT_STATUS_PIPE_NOT_AVAILABLE;
+ }
+
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+
+ subreq = nb_packet_read_send(state, state->ev, state->reader);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, nb_call_got_pkt, req);
+
+ subreq = nb_packet_write_send(state, state->ev, state->reader,
+ state->pkt);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, nb_call_written, req);
+}
+
+static void nb_call_got_pkt(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct nb_call_state *state = tevent_req_data(
+ req, struct nb_call_state);
+ NTSTATUS status;
+ bool done = true;
+
+ status = nb_packet_read_recv(subreq, state, &state->result);
+ TALLOC_FREE(subreq);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+
+ if (state->validator != NULL) {
+ done = state->validator(state->result, state->private_data);
+ }
+
+ if (done) {
+ tevent_req_done(req);
+ return;
+ }
+
+ subreq = nb_packet_read_send(state, state->ev, state->reader);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, nb_call_got_pkt, req);
+}
+
+static void nb_call_written(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct nb_call_state *state = tevent_req_data(
+ req, struct nb_call_state);
+ NTSTATUS status;
+
+ status = nb_packet_write_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+
+ subreq = tevent_wakeup_send(state, state->ev,
+ timeval_current_ofs(1, 0));
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, nb_call_resend, req);
+}
+
+static void nb_call_resend(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct nb_call_state *state = tevent_req_data(
+ req, struct nb_call_state);
+ bool ret;
+
+ ret = tevent_wakeup_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (!ret) {
+ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+ return;
+ }
+
+ subreq = nb_packet_write_send(state, state->ev, state->reader,
+ state->pkt);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, nb_call_written, req);
+}
+
+NTSTATUS nb_call_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ struct packet_struct **ppacket)
+{
+ struct nb_call_state *state = tevent_req_data(
+ req, struct nb_call_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+ if (ppacket != NULL) {
+ *ppacket = talloc_move(mem_ctx, &state->result);
+ }
+ tevent_req_received(req);
+ return NT_STATUS_OK;
+}
diff --git a/source3/libsmb/nb_call.h b/source3/libsmb/nb_call.h
new file mode 100644
index 00000000000..e38451a1aa6
--- /dev/null
+++ b/source3/libsmb/nb_call.h
@@ -0,0 +1,39 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Do a NetBIOS call via nmbd
+ * Copyright (C) Volker Lendecke 2018
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LIBSMB_NB_CALL_H__
+#define __LIBSMB_NB_CALL_H__
+
+#include "replace.h"
+#include <tevent.h>
+#include "libcli/util/ntstatus.h"
+
+struct packet_struct;
+
+struct tevent_req *nb_call_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct packet_struct *pkt,
+ int trn_id, const char *mailslot_name,
+ bool (*validator)(struct packet_struct *p,
+ void *private_data),
+ void *private_data);
+NTSTATUS nb_call_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ struct packet_struct **ppacket);
+
+#endif
diff --git a/source3/wscript_build b/source3/wscript_build
index ed9ed24fae2..4debf7f845a 100644
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -875,6 +875,7 @@ bld.SAMBA3_SUBSYSTEM('LIBNMB',
libsmb/nmblib.c
libsmb/namequery.c
libsmb/conncache.c
+ libsmb/nb_call.c
libads/sitename_cache.c
''',
deps='''
--
2.11.0
From 7d29d1d9c1622f7aa17903b77f5f16d5e3569b2b Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 23 Jan 2018 22:11:00 +0100
Subject: [PATCH 16/32] libsmb: Use nb_call_send/recv in clidgram
This was the one user of the messaging_send proxy mechanism via
nmbd. This has to come from port 137, so it was required to go via the
daemon.
---
source3/libsmb/clidgram.c | 68 +++++++++++++----------------------------------
1 file changed, 19 insertions(+), 49 deletions(-)
diff --git a/source3/libsmb/clidgram.c b/source3/libsmb/clidgram.c
index 4ae57a30d33..34eb9720d86 100644
--- a/source3/libsmb/clidgram.c
+++ b/source3/libsmb/clidgram.c
@@ -24,7 +24,7 @@
#include "../lib/util/tevent_ntstatus.h"
#include "libsmb/clidgram.h"
#include "libsmb/nmblib.h"
-#include "libsmb/unexpected.h"
+#include "libsmb/nb_call.h"
#include "messages.h"
#include "librpc/gen_ndr/samr.h"
#include "../lib/util/pidfile.h"
@@ -294,8 +294,9 @@ struct nbt_getdc_state {
struct packet_struct p;
};
-static void nbt_getdc_got_reader(struct tevent_req *subreq);
-static void nbt_getdc_got_response(struct tevent_req *subreq);
+static void nbt_getdc_done(struct tevent_req *subreq);
+static bool nbt_getdc_validator(struct packet_struct *pkt,
+ void *private_data);
struct tevent_req *nbt_getdc_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
@@ -346,70 +347,39 @@ struct tevent_req *nbt_getdc_send(TALLOC_CTX *mem_ctx,
return tevent_req_post(req, ev);
}
- subreq = nb_packet_reader_send(state, ev, DGRAM_PACKET, -1,
- state->my_mailslot);
+ subreq = nb_call_send(state, ev, &state->p, 0, state->my_mailslot,
+ nbt_getdc_validator, state);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
- tevent_req_set_callback(subreq, nbt_getdc_got_reader, req);
+ tevent_req_set_callback(subreq, nbt_getdc_done, req);
return req;
}
-static void nbt_getdc_got_reader(struct tevent_req *subreq)
+static bool nbt_getdc_validator(struct packet_struct *pkt,
+ void *private_data)
{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct nbt_getdc_state *state = tevent_req_data(
- req, struct nbt_getdc_state);
- NTSTATUS status;
-
- status = nb_packet_reader_recv(subreq, state, &state->reader);
- TALLOC_FREE(subreq);
- if (tevent_req_nterror(req, status)) {
- DEBUG(10, ("nb_packet_reader_recv returned %s\n",
- nt_errstr(status)));
- return;
- }
-
- status = messaging_send_buf(
- state->msg_ctx, pid_to_procid(state->nmbd_pid),
- MSG_SEND_PACKET, (uint8_t *)&state->p, sizeof(state->p));
-
- if (tevent_req_nterror(req, status)) {
- DEBUG(10, ("messaging_send_buf returned %s\n",
- nt_errstr(status)));
- return;
- }
- subreq = nb_packet_read_send(state, state->ev, state->reader);
- if (tevent_req_nomem(subreq, req)) {
- return;
- }
- tevent_req_set_callback(subreq, nbt_getdc_got_response, req);
+ struct nbt_getdc_state *state = talloc_get_type_abort(
+ private_data, struct nbt_getdc_state);
+ bool ok;
+
+ ok = parse_getdc_response(pkt, state, state->domain_name,
+ &state->nt_version, &state->dc_name,
+ &state->samlogon_response);
+ return ok;
}
-static void nbt_getdc_got_response(struct tevent_req *subreq)
+static void nbt_getdc_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(
subreq, struct tevent_req);
- struct nbt_getdc_state *state = tevent_req_data(
- req, struct nbt_getdc_state);
- struct packet_struct *p;
NTSTATUS status;
- bool ret;
- status = nb_packet_read_recv(subreq, state, &p);
+ status = nb_call_recv(subreq, NULL, NULL);
TALLOC_FREE(subreq);
if (tevent_req_nterror(req, status)) {
return;
}
-
- ret = parse_getdc_response(p, state, state->domain_name,
- &state->nt_version, &state->dc_name,
- &state->samlogon_response);
- if (!ret) {
- tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
- return;
- }
tevent_req_done(req);
}
--
2.11.0
From d62ee7aef9ea549e783124d61a16a09b2059ecbc Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 23 Jan 2018 22:15:33 +0100
Subject: [PATCH 17/32] smbcontrol: Remove the "nodestatus" command
This was only a pure test command that did not fulfill any sensible
purpose. It did not wait for a reply at all. It wasn't documented in
smbcontrol.1 either.
---
source3/utils/smbcontrol.c | 50 ----------------------------------------------
1 file changed, 50 deletions(-)
diff --git a/source3/utils/smbcontrol.c b/source3/utils/smbcontrol.c
index bd89b9ebf0a..aacc5fadd6a 100644
--- a/source3/utils/smbcontrol.c
+++ b/source3/utils/smbcontrol.c
@@ -1310,55 +1310,6 @@ static bool do_reload_printers(struct tevent_context *ev_ctx,
return send_message(msg_ctx, pid, MSG_PRINTER_PCAP, NULL, 0);
}
-static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
-{
- fstring unix_name;
- memset( (char *)n, '\0', sizeof(struct nmb_name) );
- fstrcpy(unix_name, name);
- (void)strupper_m(unix_name);
- push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
- n->name_type = (unsigned int)type & 0xFF;
- push_ascii(n->scope, lp_netbios_scope(), 64, STR_TERMINATE);
-}
-
-static bool do_nodestatus(struct tevent_context *ev_ctx,
- struct messaging_context *msg_ctx,
- const struct server_id pid,
- const int argc, const char **argv)
-{
- struct packet_struct p;
-
- if (argc != 2) {
- fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
- return False;
- }
-
- ZERO_STRUCT(p);
-
- p.ip = interpret_addr2(argv[1]);
- p.port = 137;
- p.packet_type = NMB_PACKET;
-
- p.packet.nmb.header.name_trn_id = 10;
- p.packet.nmb.header.opcode = 0;
- p.packet.nmb.header.response = False;
- p.packet.nmb.header.nm_flags.bcast = False;
- p.packet.nmb.header.nm_flags.recursion_available = False;
- p.packet.nmb.header.nm_flags.recursion_desired = False;
- p.packet.nmb.header.nm_flags.trunc = False;
- p.packet.nmb.header.nm_flags.authoritative = False;
- p.packet.nmb.header.rcode = 0;
- p.packet.nmb.header.qdcount = 1;
- p.packet.nmb.header.ancount = 0;
- p.packet.nmb.header.nscount = 0;
- p.packet.nmb.header.arcount = 0;
- my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
- p.packet.nmb.question.question_type = 0x21;
- p.packet.nmb.question.question_class = 0x1;
-
- return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
-}
-
static bool do_notify_cleanup(struct tevent_context *ev_ctx,
struct messaging_context *msg_ctx,
const struct server_id pid,
@@ -1408,7 +1359,6 @@ static const struct {
{ "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
{ "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
{ "reload-printers", do_reload_printers, "Force smbd to reload printers"},
- { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
{ "online", do_winbind_online, "Ask winbind to go into online state"},
{ "offline", do_winbind_offline, "Ask winbind to go into offline state"},
{ "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
--
2.11.0
From ffacb55fa8ad868b20d1142bed08e21a283f36c8 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 23 Jan 2018 22:19:27 +0100
Subject: [PATCH 18/32] nmbd: Remove MSG_SEND_PACKET
---
librpc/idl/messaging.idl | 1 -
source3/nmbd/nmbd.c | 63 ------------------------------------------------
2 files changed, 64 deletions(-)
diff --git a/librpc/idl/messaging.idl b/librpc/idl/messaging.idl
index 14a6f92d583..4d029a9f9a3 100644
--- a/librpc/idl/messaging.idl
+++ b/librpc/idl/messaging.idl
@@ -51,7 +51,6 @@ interface messaging
/* nmbd messages */
MSG_FORCE_ELECTION = 0x0101,
MSG_WINS_NEW_ENTRY = 0x0102,
- MSG_SEND_PACKET = 0x0103,
/* printing messages */
/* MSG_PRINTER_NOTIFY = 0x2001, Obsoleted */
diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c
index 9be708a9c02..62f0c277db2 100644
--- a/source3/nmbd/nmbd.c
+++ b/source3/nmbd/nmbd.c
@@ -436,67 +436,6 @@ static void msg_reload_nmbd_services(struct messaging_context *msg,
reload_interfaces(0);
}
-static void msg_nmbd_send_packet(struct messaging_context *msg,
- void *private_data,
- uint32_t msg_type,
- struct server_id src,
- DATA_BLOB *data)
-{
- struct packet_struct *p = (struct packet_struct *)data->data;
- struct subnet_record *subrec;
- struct sockaddr_storage ss;
- const struct sockaddr_storage *pss;
- const struct in_addr *local_ip;
-
- DEBUG(10, ("Received send_packet from %u\n", (unsigned int)procid_to_pid(&src)));
-
- if (data->length != sizeof(struct packet_struct)) {
- DEBUG(2, ("Discarding invalid packet length from %u\n",
- (unsigned int)procid_to_pid(&src)));
- return;
- }
-
- if ((p->packet_type != NMB_PACKET) &&
- (p->packet_type != DGRAM_PACKET)) {
- DEBUG(2, ("Discarding invalid packet type from %u: %d\n",
- (unsigned int)procid_to_pid(&src), p->packet_type));
- return;
- }
-
- in_addr_to_sockaddr_storage(&ss, p->ip);
- pss = iface_ip((struct sockaddr *)(void *)&ss);
-
- if (pss == NULL) {
- DEBUG(2, ("Could not find ip for packet from %u\n",
- (unsigned int)procid_to_pid(&src)));
- return;
- }
-
- local_ip = &((const struct sockaddr_in *)pss)->sin_addr;
- subrec = FIRST_SUBNET;
-
- p->recv_fd = -1;
- p->send_fd = (p->packet_type == NMB_PACKET) ?
- subrec->nmb_sock : subrec->dgram_sock;
-
- for (subrec = FIRST_SUBNET; subrec != NULL;
- subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
- if (ip_equal_v4(*local_ip, subrec->myip)) {
- p->send_fd = (p->packet_type == NMB_PACKET) ?
- subrec->nmb_sock : subrec->dgram_sock;
- break;
- }
- }
-
- if (p->packet_type == DGRAM_PACKET) {
- p->port = 138;
- p->packet.dgram.header.source_ip.s_addr = local_ip->s_addr;
- p->packet.dgram.header.source_port = 138;
- }
-
- send_packet(p);
-}
-
/**************************************************************************** **
The main select loop.
**************************************************************************** */
@@ -1025,8 +964,6 @@ static bool open_sockets(bool isdaemon, int port)
nmbd_terminate);
messaging_register(msg, NULL, MSG_SMB_CONF_UPDATED,
msg_reload_nmbd_services);
- messaging_register(msg, NULL, MSG_SEND_PACKET,
- msg_nmbd_send_packet);
TimeInit();
--
2.11.0
From a511f99f4c4b45f7f5f2076a64658949336c0da9 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 24 Jan 2018 11:05:43 +0100
Subject: [PATCH 19/32] libsmb: Remove the "msg_ctx" from nbt_getdc
This was needed for injecting packets into nmbd for sending
---
source3/libsmb/clidgram.c | 9 ++-------
source3/libsmb/clidgram.h | 4 +---
source3/libsmb/dsgetdcname.c | 2 +-
source3/winbindd/winbindd_cm.c | 2 +-
4 files changed, 5 insertions(+), 12 deletions(-)
diff --git a/source3/libsmb/clidgram.c b/source3/libsmb/clidgram.c
index 34eb9720d86..8d33ee1719a 100644
--- a/source3/libsmb/clidgram.c
+++ b/source3/libsmb/clidgram.c
@@ -279,7 +279,6 @@ static bool parse_getdc_response(
struct nbt_getdc_state {
struct tevent_context *ev;
- struct messaging_context *msg_ctx;
struct nb_packet_reader *reader;
const char *my_mailslot;
pid_t nmbd_pid;
@@ -300,7 +299,6 @@ static bool nbt_getdc_validator(struct packet_struct *pkt,
struct tevent_req *nbt_getdc_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
- struct messaging_context *msg_ctx,
const struct sockaddr_storage *dc_addr,
const char *domain_name,
const struct dom_sid *sid,
@@ -315,7 +313,6 @@ struct tevent_req *nbt_getdc_send(TALLOC_CTX *mem_ctx,
return NULL;
}
state->ev = ev;
- state->msg_ctx = msg_ctx;
state->dc_addr = dc_addr;
state->domain_name = domain_name;
state->sid = sid;
@@ -407,8 +404,7 @@ NTSTATUS nbt_getdc_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
return NT_STATUS_OK;
}
-NTSTATUS nbt_getdc(struct messaging_context *msg_ctx,
- uint32_t timeout_in_seconds,
+NTSTATUS nbt_getdc(uint32_t timeout_in_seconds,
const struct sockaddr_storage *dc_addr,
const char *domain_name,
const struct dom_sid *sid,
@@ -427,8 +423,7 @@ NTSTATUS nbt_getdc(struct messaging_context *msg_ctx,
if (ev == NULL) {
goto fail;
}
- req = nbt_getdc_send(ev, ev, msg_ctx, dc_addr, domain_name,
- sid, nt_version);
+ req = nbt_getdc_send(ev, ev, dc_addr, domain_name, sid, nt_version);
if (req == NULL) {
goto fail;
}
diff --git a/source3/libsmb/clidgram.h b/source3/libsmb/clidgram.h
index 6cd6222df68..a80d5a5ad72 100644
--- a/source3/libsmb/clidgram.h
+++ b/source3/libsmb/clidgram.h
@@ -28,7 +28,6 @@
struct tevent_req *nbt_getdc_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
- struct messaging_context *msg_ctx,
const struct sockaddr_storage *dc_addr,
const char *domain_name,
const struct dom_sid *sid,
@@ -36,8 +35,7 @@ struct tevent_req *nbt_getdc_send(TALLOC_CTX *mem_ctx,
NTSTATUS nbt_getdc_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
uint32_t *nt_version, const char **dc_name,
struct netlogon_samlogon_response **samlogon_response);
-NTSTATUS nbt_getdc(struct messaging_context *msg_ctx,
- uint32_t timeout_in_seconds,
+NTSTATUS nbt_getdc(uint32_t timeout_in_seconds,
const struct sockaddr_storage *dc_addr,
const char *domain_name,
const struct dom_sid *sid,
diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c
index a7fe5a1e748..31326c9fe13 100644
--- a/source3/libsmb/dsgetdcname.c
+++ b/source3/libsmb/dsgetdcname.c
@@ -934,7 +934,7 @@ static NTSTATUS process_dc_netbios(TALLOC_CTX *mem_ctx,
return NT_STATUS_UNSUCCESSFUL;
}
- status = nbt_getdc(msg_ctx, 10, &dclist[i].ss, domain_name,
+ status = nbt_getdc(10, &dclist[i].ss, domain_name,
NULL, nt_version,
mem_ctx, &nt_version, &dc_name, &r);
if (NT_STATUS_IS_OK(status)) {
diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
index bf5a2b4d7b1..fdff8fe5baf 100644
--- a/source3/winbindd/winbindd_cm.c
+++ b/source3/winbindd/winbindd_cm.c
@@ -1465,7 +1465,7 @@ static bool dcip_check_name(TALLOC_CTX *mem_ctx,
}
#endif
- status = nbt_getdc(server_messaging_context(), 10, pss, domain->name,
+ status = nbt_getdc(10, pss, domain->name,
&domain->sid, nt_version, mem_ctx, &nt_version,
&dc_name, NULL);
if (NT_STATUS_IS_OK(status)) {
--
2.11.0
From 72fb21b29cda4c60f7196a359cd4811e60c19e47 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 24 Jan 2018 11:07:27 +0100
Subject: [PATCH 20/32] libsmb: "process_dc_netbios" doesn't need the msg_ctx
anymore
---
source3/libsmb/dsgetdcname.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c
index 31326c9fe13..6ea5957278d 100644
--- a/source3/libsmb/dsgetdcname.c
+++ b/source3/libsmb/dsgetdcname.c
@@ -890,7 +890,6 @@ static NTSTATUS process_dc_dns(TALLOC_CTX *mem_ctx,
****************************************************************/
static NTSTATUS process_dc_netbios(TALLOC_CTX *mem_ctx,
- struct messaging_context *msg_ctx,
const char *domain_name,
uint32_t flags,
struct ip_service_name *dclist,
@@ -910,10 +909,6 @@ static NTSTATUS process_dc_netbios(TALLOC_CTX *mem_ctx,
NETLOGON_NT_VERSION_5 |
NETLOGON_NT_VERSION_5EX_WITH_IP;
- if (msg_ctx == NULL) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
if (flags & DS_PDC_REQUIRED) {
name_type = NBT_NAME_PDC;
}
@@ -1015,7 +1010,7 @@ static NTSTATUS dsgetdcname_rediscover(TALLOC_CTX *mem_ctx,
&dclist, &num_dcs);
NT_STATUS_NOT_OK_RETURN(status);
- return process_dc_netbios(mem_ctx, msg_ctx, domain_name, flags,
+ return process_dc_netbios(mem_ctx, domain_name, flags,
dclist, num_dcs, info);
}
@@ -1049,7 +1044,7 @@ static NTSTATUS dsgetdcname_rediscover(TALLOC_CTX *mem_ctx,
&num_dcs);
NT_STATUS_NOT_OK_RETURN(status);
- return process_dc_netbios(mem_ctx, msg_ctx, domain_name, flags, dclist,
+ return process_dc_netbios(mem_ctx, domain_name, flags, dclist,
num_dcs, info);
}
--
2.11.0
From d924b30033d65b3e84d340118f24feb818a4f5cb Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 24 Jan 2018 11:08:56 +0100
Subject: [PATCH 21/32] libsmb: "dsgetdcname_rediscover" doesn't need "msg_ctx"
anymore
---
source3/libsmb/dsgetdcname.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c
index 6ea5957278d..855a9518e76 100644
--- a/source3/libsmb/dsgetdcname.c
+++ b/source3/libsmb/dsgetdcname.c
@@ -987,7 +987,6 @@ static NTSTATUS process_dc_netbios(TALLOC_CTX *mem_ctx,
****************************************************************/
static NTSTATUS dsgetdcname_rediscover(TALLOC_CTX *mem_ctx,
- struct messaging_context *msg_ctx,
const char *domain_name,
const struct GUID *domain_guid,
uint32_t flags,
@@ -1114,7 +1113,7 @@ static NTSTATUS dsgetdcname_internal(TALLOC_CTX *mem_ctx,
}
rediscover:
- status = dsgetdcname_rediscover(mem_ctx, msg_ctx, domain_name,
+ status = dsgetdcname_rediscover(mem_ctx, domain_name,
domain_guid, flags, site_name,
&myinfo);
--
2.11.0
From edd578cde6669fec63a3e25cc0bd9ead1737c6ac Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 24 Jan 2018 11:18:25 +0100
Subject: [PATCH 22/32] libsmb: "dsgetcname" doesn't need "msg_ctx" anymore
---
source3/include/proto.h | 1 -
source3/lib/netapi/getdc.c | 5 -----
source3/lib/netapi/joindomain.c | 18 +++---------------
source3/libnet/libnet_join.c | 2 --
source3/libsmb/dsgetdcname.c | 9 ++-------
source3/rpc_server/netlogon/srv_netlog_nt.c | 4 +---
source3/utils/net_lookup.c | 2 +-
source3/utils/net_rpc.c | 1 -
source3/winbindd/winbindd_dual_srv.c | 2 +-
9 files changed, 8 insertions(+), 36 deletions(-)
diff --git a/source3/include/proto.h b/source3/include/proto.h
index fa87407ff24..21225bf0104 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -681,7 +681,6 @@ void flush_negative_conn_cache_for_domain(const char *domain);
struct netr_DsRGetDCNameInfo;
NTSTATUS dsgetdcname(TALLOC_CTX *mem_ctx,
- struct messaging_context *msg_ctx,
const char *domain_name,
const struct GUID *domain_guid,
const char *site_name,
diff --git a/source3/lib/netapi/getdc.c b/source3/lib/netapi/getdc.c
index 2d47ee45840..ad95e60bbcd 100644
--- a/source3/lib/netapi/getdc.c
+++ b/source3/lib/netapi/getdc.c
@@ -141,13 +141,8 @@ WERROR DsGetDcName_l(struct libnetapi_ctx *ctx,
struct DsGetDcName *r)
{
NTSTATUS status;
- struct libnetapi_private_ctx *priv;
-
- priv = talloc_get_type_abort(ctx->private_data,
- struct libnetapi_private_ctx);
status = dsgetdcname(ctx,
- priv->msg_ctx,
r->in.domain_name,
r->in.domain_guid,
r->in.site_name,
diff --git a/source3/lib/netapi/joindomain.c b/source3/lib/netapi/joindomain.c
index 7d27bd9d0fe..a096e594a8b 100644
--- a/source3/lib/netapi/joindomain.c
+++ b/source3/lib/netapi/joindomain.c
@@ -37,12 +37,8 @@ WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx,
struct NetJoinDomain *r)
{
struct libnet_JoinCtx *j = NULL;
- struct libnetapi_private_ctx *priv;
WERROR werr;
- priv = talloc_get_type_abort(mem_ctx->private_data,
- struct libnetapi_private_ctx);
-
if (!r->in.domain) {
return WERR_INVALID_PARAMETER;
}
@@ -60,7 +56,7 @@ WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx,
uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
DS_WRITABLE_REQUIRED |
DS_RETURN_DNS_NAME;
- status = dsgetdcname(mem_ctx, priv->msg_ctx, r->in.domain,
+ status = dsgetdcname(mem_ctx, r->in.domain,
NULL, NULL, flags, &info);
if (!NT_STATUS_IS_OK(status)) {
libnetapi_set_error_string(mem_ctx,
@@ -174,12 +170,8 @@ WERROR NetUnjoinDomain_l(struct libnetapi_ctx *mem_ctx,
struct dom_sid domain_sid;
const char *domain = NULL;
WERROR werr;
- struct libnetapi_private_ctx *priv;
const char *realm = lp_realm();
- priv = talloc_get_type_abort(mem_ctx->private_data,
- struct libnetapi_private_ctx);
-
if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
return WERR_NERR_SETUPNOTJOINED;
}
@@ -203,7 +195,7 @@ WERROR NetUnjoinDomain_l(struct libnetapi_ctx *mem_ctx,
uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
DS_WRITABLE_REQUIRED |
DS_RETURN_DNS_NAME;
- status = dsgetdcname(mem_ctx, priv->msg_ctx, domain,
+ status = dsgetdcname(mem_ctx, domain,
NULL, NULL, flags, &info);
if (!NT_STATUS_IS_OK(status)) {
libnetapi_set_error_string(mem_ctx,
@@ -393,14 +385,10 @@ WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
const char *dc = NULL;
uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
DS_RETURN_DNS_NAME;
- struct libnetapi_private_ctx *priv;
char **p;
size_t s;
- priv = talloc_get_type_abort(ctx->private_data,
- struct libnetapi_private_ctx);
-
- status = dsgetdcname(ctx, priv->msg_ctx, r->in.domain,
+ status = dsgetdcname(ctx, r->in.domain,
NULL, NULL, flags, &info);
if (!NT_STATUS_IS_OK(status)) {
libnetapi_set_error_string(ctx, "%s",
diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c
index 5db2ca09ccc..587dc874f7e 100644
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -2540,7 +2540,6 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx,
name_type_flags = DS_IS_FLAT_NAME;
}
status = dsgetdcname(mem_ctx,
- r->in.msg_ctx,
r->in.domain_name,
NULL,
NULL,
@@ -2801,7 +2800,6 @@ static WERROR libnet_DomainUnjoin(TALLOC_CTX *mem_ctx,
struct netr_DsRGetDCNameInfo *info;
const char *dc;
status = dsgetdcname(mem_ctx,
- r->in.msg_ctx,
r->in.domain_name,
NULL,
NULL,
diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c
index 855a9518e76..e68b0c031ac 100644
--- a/source3/libsmb/dsgetdcname.c
+++ b/source3/libsmb/dsgetdcname.c
@@ -348,7 +348,6 @@ static NTSTATUS dsgetdcname_cache_fetch(TALLOC_CTX *mem_ctx,
****************************************************************/
static NTSTATUS dsgetdcname_cached(TALLOC_CTX *mem_ctx,
- struct messaging_context *msg_ctx,
const char *domain_name,
const struct GUID *domain_guid,
uint32_t flags,
@@ -373,7 +372,7 @@ static NTSTATUS dsgetdcname_cached(TALLOC_CTX *mem_ctx,
if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
struct netr_DsRGetDCNameInfo *dc_info;
- status = dsgetdcname(mem_ctx, msg_ctx, domain_name,
+ status = dsgetdcname(mem_ctx, domain_name,
domain_guid, site_name,
flags | DS_FORCE_REDISCOVERY,
&dc_info);
@@ -1073,7 +1072,6 @@ static bool is_closest_site(struct netr_DsRGetDCNameInfo *info)
********************************************************************/
static NTSTATUS dsgetdcname_internal(TALLOC_CTX *mem_ctx,
- struct messaging_context *msg_ctx,
const char *domain_name,
const struct GUID *domain_guid,
const char *site_name,
@@ -1102,7 +1100,7 @@ static NTSTATUS dsgetdcname_internal(TALLOC_CTX *mem_ctx,
goto rediscover;
}
- status = dsgetdcname_cached(mem_ctx, msg_ctx, domain_name, domain_guid,
+ status = dsgetdcname_cached(mem_ctx, domain_name, domain_guid,
flags, site_name, &myinfo);
if (NT_STATUS_IS_OK(status)) {
goto done;
@@ -1147,7 +1145,6 @@ static NTSTATUS dsgetdcname_internal(TALLOC_CTX *mem_ctx,
********************************************************************/
NTSTATUS dsgetdcname(TALLOC_CTX *mem_ctx,
- struct messaging_context *msg_ctx,
const char *domain_name,
const struct GUID *domain_guid,
const char *site_name,
@@ -1170,7 +1167,6 @@ NTSTATUS dsgetdcname(TALLOC_CTX *mem_ctx,
}
status = dsgetdcname_internal(mem_ctx,
- msg_ctx,
domain_name,
domain_guid,
query_site,
@@ -1186,7 +1182,6 @@ NTSTATUS dsgetdcname(TALLOC_CTX *mem_ctx,
/* Should we try again with site_name == NULL ? */
if (retry_query_with_null) {
status = dsgetdcname_internal(mem_ctx,
- msg_ctx,
domain_name,
domain_guid,
NULL,
diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index 83e68417c76..6227895b955 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -318,7 +318,7 @@ WERROR _netr_LogonControl2Ex(struct pipes_struct *p,
break;
}
- status = dsgetdcname(p->mem_ctx, p->msg_ctx, domain, NULL, NULL,
+ status = dsgetdcname(p->mem_ctx, domain, NULL, NULL,
DS_FORCE_REDISCOVERY | DS_RETURN_FLAT_NAME,
&dc_info);
if (!NT_STATUS_IS_OK(status)) {
@@ -2071,7 +2071,6 @@ WERROR _netr_GetDcName(struct pipes_struct *p,
flags = DS_PDC_REQUIRED | DS_IS_FLAT_NAME | DS_RETURN_FLAT_NAME;
status = dsgetdcname(p->mem_ctx,
- p->msg_ctx,
r->in.domainname,
NULL,
NULL,
@@ -2116,7 +2115,6 @@ WERROR _netr_GetAnyDCName(struct pipes_struct *p,
flags = DS_IS_FLAT_NAME | DS_RETURN_FLAT_NAME;
status = dsgetdcname(p->mem_ctx,
- p->msg_ctx,
r->in.domainname,
NULL,
NULL,
diff --git a/source3/utils/net_lookup.c b/source3/utils/net_lookup.c
index 597e098e2e1..f8a5ac61ee8 100644
--- a/source3/utils/net_lookup.c
+++ b/source3/utils/net_lookup.c
@@ -423,7 +423,7 @@ static int net_lookup_dsgetdcname(struct net_context *c, int argc, const char **
return -1;
}
- status = dsgetdcname(mem_ctx, c->msg_ctx, domain_name, NULL, site_name,
+ status = dsgetdcname(mem_ctx, domain_name, NULL, site_name,
flags, &info);
if (!NT_STATUS_IS_OK(status)) {
d_printf(_("failed with: %s\n"), nt_errstr(status));
diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c
index 8a989d790f2..11cc0c49849 100644
--- a/source3/utils/net_rpc.c
+++ b/source3/utils/net_rpc.c
@@ -497,7 +497,6 @@ int net_rpc_testjoin(struct net_context *c, int argc, const char **argv)
}
status = dsgetdcname(mem_ctx,
- c->msg_ctx,
domain,
NULL,
NULL,
diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c
index 4cea73feaf9..481b29262d8 100644
--- a/source3/winbindd/winbindd_dual_srv.c
+++ b/source3/winbindd/winbindd_dual_srv.c
@@ -551,7 +551,7 @@ NTSTATUS _wbint_DsGetDcName(struct pipes_struct *p, struct wbint_DsGetDcName *r)
bool try_dsrgetdcname = false;
if (domain == NULL) {
- return dsgetdcname(p->mem_ctx, server_messaging_context(),
+ return dsgetdcname(p->mem_ctx,
r->in.domain_name, r->in.domain_guid,
r->in.site_name ? r->in.site_name : "",
r->in.flags,
--
2.11.0
From 64e3676e48d22ac93b84c1fb11f6bf5f3ae0f0f8 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 5 Jan 2018 14:21:05 +0100
Subject: [PATCH 23/32] libsmb: Give dsgetdcname.c its own header
---
source3/include/proto.h | 11 ---------
source3/lib/netapi/getdc.c | 1 +
source3/lib/netapi/joindomain.c | 1 +
source3/lib/netapi/serverinfo.c | 1 +
source3/libnet/libnet_join.c | 1 +
source3/libsmb/dsgetdcname.c | 1 +
source3/libsmb/dsgetdcname.h | 36 +++++++++++++++++++++++++++++
source3/rpc_server/netlogon/srv_netlog_nt.c | 1 +
source3/utils/net_lookup.c | 1 +
source3/utils/net_rpc.c | 1 +
source3/winbindd/winbindd_dual_srv.c | 1 +
11 files changed, 45 insertions(+), 11 deletions(-)
create mode 100644 source3/libsmb/dsgetdcname.h
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 21225bf0104..abdfdcc4bdd 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -676,17 +676,6 @@ NTSTATUS check_negative_conn_cache( const char *domain, const char *server);
void add_failed_connection_entry(const char *domain, const char *server, NTSTATUS result) ;
void flush_negative_conn_cache_for_domain(const char *domain);
-/* The following definitions come from libsmb/dsgetdcname.c */
-
-struct netr_DsRGetDCNameInfo;
-
-NTSTATUS dsgetdcname(TALLOC_CTX *mem_ctx,
- const char *domain_name,
- const struct GUID *domain_guid,
- const char *site_name,
- uint32_t flags,
- struct netr_DsRGetDCNameInfo **info);
-
/* The following definitions come from libsmb/errormap.c */
NTSTATUS dos_to_ntstatus(uint8_t eclass, uint32_t ecode);
diff --git a/source3/lib/netapi/getdc.c b/source3/lib/netapi/getdc.c
index ad95e60bbcd..3b837e79c82 100644
--- a/source3/lib/netapi/getdc.c
+++ b/source3/lib/netapi/getdc.c
@@ -24,6 +24,7 @@
#include "lib/netapi/netapi.h"
#include "lib/netapi/netapi_private.h"
#include "lib/netapi/libnetapi.h"
+#include "libsmb/dsgetdcname.h"
/********************************************************************
********************************************************************/
diff --git a/source3/lib/netapi/joindomain.c b/source3/lib/netapi/joindomain.c
index a096e594a8b..e8ed19eef3e 100644
--- a/source3/lib/netapi/joindomain.c
+++ b/source3/lib/netapi/joindomain.c
@@ -29,6 +29,7 @@
#include "../librpc/gen_ndr/ndr_wkssvc_c.h"
#include "rpc_client/cli_pipe.h"
#include "secrets.h"
+#include "libsmb/dsgetdcname.h"
/****************************************************************
****************************************************************/
diff --git a/source3/lib/netapi/serverinfo.c b/source3/lib/netapi/serverinfo.c
index 2fd7668c682..7d9cc481c8c 100644
--- a/source3/lib/netapi/serverinfo.c
+++ b/source3/lib/netapi/serverinfo.c
@@ -26,6 +26,7 @@
#include "../librpc/gen_ndr/ndr_srvsvc_c.h"
#include "lib/smbconf/smbconf.h"
#include "lib/smbconf/smbconf_reg.h"
+#include "libsmb/dsgetdcname.h"
/****************************************************************
****************************************************************/
diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c
index 587dc874f7e..694a09db33d 100644
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -43,6 +43,7 @@
#include "libcli/auth/netlogon_creds_cli.h"
#include "auth/credentials/credentials.h"
#include "krb5_env.h"
+#include "libsmb/dsgetdcname.h"
/****************************************************************
****************************************************************/
diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c
index e68b0c031ac..179222de64c 100644
--- a/source3/libsmb/dsgetdcname.c
+++ b/source3/libsmb/dsgetdcname.c
@@ -21,6 +21,7 @@
*/
#include "includes.h"
+#include "libsmb/dsgetdcname.h"
#include "libads/sitename_cache.h"
#include "../librpc/gen_ndr/ndr_netlogon.h"
#include "libads/cldap.h"
diff --git a/source3/libsmb/dsgetdcname.h b/source3/libsmb/dsgetdcname.h
new file mode 100644
index 00000000000..36948c2cb1e
--- /dev/null
+++ b/source3/libsmb/dsgetdcname.h
@@ -0,0 +1,36 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Copyright (C) Volker Lendecke 2018
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LIBSMB_DSGETDCNAME_H__
+#define __LIBSMB_DSGETDCNAME_H__
+
+#include "replace.h"
+#include <talloc.h>
+#include "source3/include/messages.h"
+#include "librpc/gen_ndr/misc.h"
+
+struct netr_DsRGetDCNameInfo;
+
+NTSTATUS dsgetdcname(TALLOC_CTX *mem_ctx,
+ const char *domain_name,
+ const struct GUID *domain_guid,
+ const char *site_name,
+ uint32_t flags,
+ struct netr_DsRGetDCNameInfo **info);
+
+#endif
diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index 6227895b955..c377e529cd1 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -47,6 +47,7 @@
#include "messages.h"
#include "../lib/tsocket/tsocket.h"
#include "lib/param/param.h"
+#include "libsmb/dsgetdcname.h"
extern userdom_struct current_user_info;
diff --git a/source3/utils/net_lookup.c b/source3/utils/net_lookup.c
index f8a5ac61ee8..0f5fefe581c 100644
--- a/source3/utils/net_lookup.c
+++ b/source3/utils/net_lookup.c
@@ -24,6 +24,7 @@
#include "smb_krb5.h"
#include "../libcli/security/security.h"
#include "passdb/lookup_sid.h"
+#include "libsmb/dsgetdcname.h"
int net_lookup_usage(struct net_context *c, int argc, const char **argv)
{
diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c
index 11cc0c49849..6c69ffb9670 100644
--- a/source3/utils/net_rpc.c
+++ b/source3/utils/net_rpc.c
@@ -46,6 +46,7 @@
#include "nsswitch/libwbclient/wbclient.h"
#include "passdb.h"
#include "../libcli/smb/smbXcli_base.h"
+#include "libsmb/dsgetdcname.h"
static int net_mode_share;
static NTSTATUS sync_files(struct copy_clistate *cp_clistate, const char *mask);
diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c
index 481b29262d8..e18a1ce5a40 100644
--- a/source3/winbindd/winbindd_dual_srv.c
+++ b/source3/winbindd/winbindd_dual_srv.c
@@ -35,6 +35,7 @@
#include "../source4/dsdb/samdb/samdb.h"
#include "rpc_client/cli_netlogon.h"
#include "rpc_client/util_netlogon.h"
+#include "libsmb/dsgetdcname.h"
void _wbint_Ping(struct pipes_struct *p, struct wbint_Ping *r)
{
--
2.11.0
From 5c00ecb80f835e2e5ce032c21a8752b0e8df54e6 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 24 Jan 2018 21:59:30 +0100
Subject: [PATCH 24/32] Use nb_call in name_query_send
---
source3/libsmb/namequery.c | 38 ++++++++++++++++++--------------------
1 file changed, 18 insertions(+), 20 deletions(-)
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index b616a64b896..6f00985957b 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -27,6 +27,7 @@
#include "lib/tsocket/tsocket.h"
#include "libsmb/nmblib.h"
#include "libsmb/unexpected.h"
+#include "libsmb/nb_call.h"
#include "../libcli/nbt/libnbt.h"
#include "libads/kerberos_proto.h"
@@ -1220,9 +1221,7 @@ struct name_query_state {
struct sockaddr_storage addr;
bool bcast;
-
- uint8_t buf[1024];
- ssize_t buflen;
+ struct packet_struct pkt;
NTSTATUS validate_error;
uint8_t flags;
@@ -1242,8 +1241,7 @@ struct tevent_req *name_query_send(TALLOC_CTX *mem_ctx,
{
struct tevent_req *req, *subreq;
struct name_query_state *state;
- struct packet_struct p;
- struct nmb_packet *nmb = &p.packet.nmb;
+ struct nmb_packet *nmb;
struct sockaddr_in *in_addr;
req = tevent_req_create(mem_ctx, &state, struct name_query_state);
@@ -1271,7 +1269,17 @@ struct tevent_req *name_query_send(TALLOC_CTX *mem_ctx,
set_socket_addr_v4(&state->my_addr);
- ZERO_STRUCT(p);
+ state->addr = *addr;
+ in_addr = (struct sockaddr_in *)(void *)&state->addr;
+ in_addr->sin_port = htons(NMB_PORT);
+
+ set_socket_addr_v4(&state->my_addr);
+
+ state->pkt.ip = in_addr->sin_addr;
+ state->pkt.port = 137;
+
+ nmb = &state->pkt.packet.nmb;
+
nmb->header.name_trn_id = generate_trn_id();
nmb->header.opcode = 0;
nmb->header.response = false;
@@ -1291,18 +1299,9 @@ struct tevent_req *name_query_send(TALLOC_CTX *mem_ctx,
nmb->question.question_type = 0x20;
nmb->question.question_class = 0x1;
- state->buflen = build_packet((char *)state->buf, sizeof(state->buf),
- &p);
- if (state->buflen == 0) {
- tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
- DEBUG(10, ("build_packet failed\n"));
- return tevent_req_post(req, ev);
- }
-
- subreq = nb_trans_send(state, ev, &state->my_addr, &state->addr, bcast,
- state->buf, state->buflen,
- NMB_PACKET, nmb->header.name_trn_id,
- name_query_validator, state);
+ subreq = nb_call_send(state, ev, &state->pkt,
+ nmb->header.name_trn_id, NULL,
+ name_query_validator, state);
if (tevent_req_nomem(subreq, req)) {
DEBUG(10, ("nb_trans_send failed\n"));
return tevent_req_post(req, ev);
@@ -1460,9 +1459,8 @@ static void name_query_done(struct tevent_req *subreq)
struct name_query_state *state = tevent_req_data(
req, struct name_query_state);
NTSTATUS status;
- struct packet_struct *p = NULL;
- status = nb_trans_recv(subreq, state, &p);
+ status = nb_call_recv(subreq, NULL, NULL);
TALLOC_FREE(subreq);
if (tevent_req_nterror(req, status)) {
return;
--
2.11.0
From 2619a98876d63d54dbd4259474a64be69d745cca Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 24 Jan 2018 21:58:51 +0100
Subject: [PATCH 25/32] Use nb_call in node_status_query
---
source3/libsmb/namequery.c | 445 ++-------------------------------------------
1 file changed, 13 insertions(+), 432 deletions(-)
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index 6f00985957b..e18745bec1c 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -290,418 +290,6 @@ static struct node_status *parse_node_status(TALLOC_CTX *mem_ctx, char *p,
return ret;
}
-struct sock_packet_read_state {
- struct tevent_context *ev;
- enum packet_type type;
- int trn_id;
-
- struct nb_packet_reader *reader;
- struct tevent_req *reader_req;
-
- struct tdgram_context *sock;
- struct tevent_req *socket_req;
- uint8_t *buf;
- struct tsocket_address *addr;
-
- bool (*validator)(struct packet_struct *p,
- void *private_data);
- void *private_data;
-
- struct packet_struct *packet;
-};
-
-static void sock_packet_read_got_packet(struct tevent_req *subreq);
-static void sock_packet_read_got_socket(struct tevent_req *subreq);
-
-static struct tevent_req *sock_packet_read_send(
- TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct tdgram_context *sock,
- struct nb_packet_reader *reader,
- enum packet_type type,
- int trn_id,
- bool (*validator)(struct packet_struct *p, void *private_data),
- void *private_data)
-{
- struct tevent_req *req;
- struct sock_packet_read_state *state;
-
- req = tevent_req_create(mem_ctx, &state,
- struct sock_packet_read_state);
- if (req == NULL) {
- return NULL;
- }
- state->ev = ev;
- state->reader = reader;
- state->sock = sock;
- state->type = type;
- state->trn_id = trn_id;
- state->validator = validator;
- state->private_data = private_data;
-
- if (reader != NULL) {
- state->reader_req = nb_packet_read_send(state, ev, reader);
- if (tevent_req_nomem(state->reader_req, req)) {
- return tevent_req_post(req, ev);
- }
- tevent_req_set_callback(
- state->reader_req, sock_packet_read_got_packet, req);
- }
-
- state->socket_req = tdgram_recvfrom_send(state, ev, state->sock);
- if (tevent_req_nomem(state->socket_req, req)) {
- return tevent_req_post(req, ev);
- }
- tevent_req_set_callback(state->socket_req, sock_packet_read_got_socket,
- req);
-
- return req;
-}
-
-static void sock_packet_read_got_packet(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct sock_packet_read_state *state = tevent_req_data(
- req, struct sock_packet_read_state);
- NTSTATUS status;
-
- status = nb_packet_read_recv(subreq, state, &state->packet);
-
- TALLOC_FREE(state->reader_req);
-
- if (!NT_STATUS_IS_OK(status)) {
- if (state->socket_req != NULL) {
- /*
- * Still waiting for socket
- */
- return;
- }
- /*
- * Both socket and packet reader failed
- */
- tevent_req_nterror(req, status);
- return;
- }
-
- if ((state->validator != NULL) &&
- !state->validator(state->packet, state->private_data)) {
- DEBUG(10, ("validator failed\n"));
-
- TALLOC_FREE(state->packet);
-
- state->reader_req = nb_packet_read_send(state, state->ev,
- state->reader);
- if (tevent_req_nomem(state->reader_req, req)) {
- return;
- }
- tevent_req_set_callback(
- state->reader_req, sock_packet_read_got_packet, req);
- return;
- }
-
- TALLOC_FREE(state->socket_req);
- tevent_req_done(req);
-}
-
-static void sock_packet_read_got_socket(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct sock_packet_read_state *state = tevent_req_data(
- req, struct sock_packet_read_state);
- union {
- struct sockaddr sa;
- struct sockaddr_in sin;
- } addr;
- ssize_t ret;
- ssize_t received;
- int err;
- bool ok;
-
- received = tdgram_recvfrom_recv(subreq, &err, state,
- &state->buf, &state->addr);
-
- TALLOC_FREE(state->socket_req);
-
- if (received == -1) {
- if (state->reader_req != NULL) {
- /*
- * Still waiting for reader
- */
- return;
- }
- /*
- * Both socket and reader failed
- */
- tevent_req_nterror(req, map_nt_error_from_unix(err));
- return;
- }
- ok = tsocket_address_is_inet(state->addr, "ipv4");
- if (!ok) {
- goto retry;
- }
- ret = tsocket_address_bsd_sockaddr(state->addr,
- &addr.sa,
- sizeof(addr.sin));
- if (ret == -1) {
- tevent_req_nterror(req, map_nt_error_from_unix(errno));
- return;
- }
-
- state->packet = parse_packet_talloc(
- state, (char *)state->buf, received, state->type,
- addr.sin.sin_addr, addr.sin.sin_port);
- if (state->packet == NULL) {
- DEBUG(10, ("parse_packet failed\n"));
- goto retry;
- }
- if ((state->trn_id != -1) &&
- (state->trn_id != packet_trn_id(state->packet))) {
- DEBUG(10, ("Expected transaction id %d, got %d\n",
- state->trn_id, packet_trn_id(state->packet)));
- goto retry;
- }
-
- if ((state->validator != NULL) &&
- !state->validator(state->packet, state->private_data)) {
- DEBUG(10, ("validator failed\n"));
- goto retry;
- }
-
- tevent_req_done(req);
- return;
-
-retry:
- TALLOC_FREE(state->packet);
- TALLOC_FREE(state->buf);
- TALLOC_FREE(state->addr);
-
- state->socket_req = tdgram_recvfrom_send(state, state->ev, state->sock);
- if (tevent_req_nomem(state->socket_req, req)) {
- return;
- }
- tevent_req_set_callback(state->socket_req, sock_packet_read_got_socket,
- req);
-}
-
-static NTSTATUS sock_packet_read_recv(struct tevent_req *req,
- TALLOC_CTX *mem_ctx,
- struct packet_struct **ppacket)
-{
- struct sock_packet_read_state *state = tevent_req_data(
- req, struct sock_packet_read_state);
- NTSTATUS status;
-
- if (tevent_req_is_nterror(req, &status)) {
- return status;
- }
- *ppacket = talloc_move(mem_ctx, &state->packet);
- return NT_STATUS_OK;
-}
-
-struct nb_trans_state {
- struct tevent_context *ev;
- struct tdgram_context *sock;
- struct nb_packet_reader *reader;
-
- struct tsocket_address *src_addr;
- struct tsocket_address *dst_addr;
- uint8_t *buf;
- size_t buflen;
- enum packet_type type;
- int trn_id;
-
- bool (*validator)(struct packet_struct *p,
- void *private_data);
- void *private_data;
-
- struct packet_struct *packet;
-};
-
-static void nb_trans_got_reader(struct tevent_req *subreq);
-static void nb_trans_done(struct tevent_req *subreq);
-static void nb_trans_sent(struct tevent_req *subreq);
-static void nb_trans_send_next(struct tevent_req *subreq);
-
-static struct tevent_req *nb_trans_send(
- TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- const struct sockaddr_storage *_my_addr,
- const struct sockaddr_storage *_dst_addr,
- bool bcast,
- uint8_t *buf, size_t buflen,
- enum packet_type type, int trn_id,
- bool (*validator)(struct packet_struct *p,
- void *private_data),
- void *private_data)
-{
- const struct sockaddr *my_addr =
- discard_const_p(const struct sockaddr, _my_addr);
- size_t my_addr_len = sizeof(*_my_addr);
- const struct sockaddr *dst_addr =
- discard_const_p(const struct sockaddr, _dst_addr);
- size_t dst_addr_len = sizeof(*_dst_addr);
- struct tevent_req *req, *subreq;
- struct nb_trans_state *state;
- int ret;
-
- req = tevent_req_create(mem_ctx, &state, struct nb_trans_state);
- if (req == NULL) {
- return NULL;
- }
- state->ev = ev;
- state->buf = buf;
- state->buflen = buflen;
- state->type = type;
- state->trn_id = trn_id;
- state->validator = validator;
- state->private_data = private_data;
-
- ret = tsocket_address_bsd_from_sockaddr(state,
- my_addr, my_addr_len,
- &state->src_addr);
- if (ret == -1) {
- tevent_req_nterror(req, map_nt_error_from_unix(errno));
- return tevent_req_post(req, ev);
- }
-
- ret = tsocket_address_bsd_from_sockaddr(state,
- dst_addr, dst_addr_len,
- &state->dst_addr);
- if (ret == -1) {
- tevent_req_nterror(req, map_nt_error_from_unix(errno));
- return tevent_req_post(req, ev);
- }
-
- ret = tdgram_inet_udp_broadcast_socket(state->src_addr, state,
- &state->sock);
- if (ret == -1) {
- tevent_req_nterror(req, map_nt_error_from_unix(errno));
- return tevent_req_post(req, ev);
- }
-
- subreq = nb_packet_reader_send(state, ev, type, state->trn_id, NULL);
- if (tevent_req_nomem(subreq, req)) {
- return tevent_req_post(req, ev);
- }
- tevent_req_set_callback(subreq, nb_trans_got_reader, req);
- return req;
-}
-
-static void nb_trans_got_reader(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct nb_trans_state *state = tevent_req_data(
- req, struct nb_trans_state);
- NTSTATUS status;
-
- status = nb_packet_reader_recv(subreq, state, &state->reader);
- TALLOC_FREE(subreq);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("nmbd not around\n"));
- state->reader = NULL;
- }
-
- subreq = sock_packet_read_send(
- state, state->ev, state->sock,
- state->reader, state->type, state->trn_id,
- state->validator, state->private_data);
- if (tevent_req_nomem(subreq, req)) {
- return;
- }
- tevent_req_set_callback(subreq, nb_trans_done, req);
-
- subreq = tdgram_sendto_send(state, state->ev,
- state->sock,
- state->buf, state->buflen,
- state->dst_addr);
- if (tevent_req_nomem(subreq, req)) {
- return;
- }
- tevent_req_set_callback(subreq, nb_trans_sent, req);
-}
-
-static void nb_trans_sent(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct nb_trans_state *state = tevent_req_data(
- req, struct nb_trans_state);
- ssize_t sent;
- int err;
-
- sent = tdgram_sendto_recv(subreq, &err);
- TALLOC_FREE(subreq);
- if (sent == -1) {
- DEBUG(10, ("sendto failed: %s\n", strerror(err)));
- tevent_req_nterror(req, map_nt_error_from_unix(err));
- return;
- }
- subreq = tevent_wakeup_send(state, state->ev,
- timeval_current_ofs(1, 0));
- if (tevent_req_nomem(subreq, req)) {
- return;
- }
- tevent_req_set_callback(subreq, nb_trans_send_next, req);
-}
-
-static void nb_trans_send_next(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct nb_trans_state *state = tevent_req_data(
- req, struct nb_trans_state);
- bool ret;
-
- ret = tevent_wakeup_recv(subreq);
- TALLOC_FREE(subreq);
- if (!ret) {
- tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
- return;
- }
- subreq = tdgram_sendto_send(state, state->ev,
- state->sock,
- state->buf, state->buflen,
- state->dst_addr);
- if (tevent_req_nomem(subreq, req)) {
- return;
- }
- tevent_req_set_callback(subreq, nb_trans_sent, req);
-}
-
-static void nb_trans_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct nb_trans_state *state = tevent_req_data(
- req, struct nb_trans_state);
- NTSTATUS status;
-
- status = sock_packet_read_recv(subreq, state, &state->packet);
- TALLOC_FREE(subreq);
- if (tevent_req_nterror(req, status)) {
- return;
- }
- tevent_req_done(req);
-}
-
-static NTSTATUS nb_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
- struct packet_struct **ppacket)
-{
- struct nb_trans_state *state = tevent_req_data(
- req, struct nb_trans_state);
- NTSTATUS status;
-
- if (tevent_req_is_nterror(req, &status)) {
- return status;
- }
- *ppacket = talloc_move(mem_ctx, &state->packet);
- return NT_STATUS_OK;
-}
-
/****************************************************************************
Do a NBT node status query on an open socket and return an array of
structures holding the returned names or NULL if the query failed.
@@ -710,9 +298,8 @@ static NTSTATUS nb_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
struct node_status_query_state {
struct sockaddr_storage my_addr;
struct sockaddr_storage addr;
- uint8_t buf[1024];
- ssize_t buflen;
- struct packet_struct *packet;
+ struct packet_struct pkt;
+ struct packet_struct *result;
};
static bool node_status_query_validator(struct packet_struct *p,
@@ -726,8 +313,7 @@ struct tevent_req *node_status_query_send(TALLOC_CTX *mem_ctx,
{
struct tevent_req *req, *subreq;
struct node_status_query_state *state;
- struct packet_struct p;
- struct nmb_packet *nmb = &p.packet.nmb;
+ struct nmb_packet *nmb;
struct sockaddr_in *in_addr;
req = tevent_req_create(mem_ctx, &state,
@@ -748,7 +334,11 @@ struct tevent_req *node_status_query_send(TALLOC_CTX *mem_ctx,
set_socket_addr_v4(&state->my_addr);
- ZERO_STRUCT(p);
+ state->pkt.ip = in_addr->sin_addr;
+ state->pkt.port = 137;
+
+ nmb = &state->pkt.packet.nmb;
+
nmb->header.name_trn_id = generate_trn_id();
nmb->header.opcode = 0;
nmb->header.response = false;
@@ -766,18 +356,9 @@ struct tevent_req *node_status_query_send(TALLOC_CTX *mem_ctx,
nmb->question.question_type = 0x21;
nmb->question.question_class = 0x1;
- state->buflen = build_packet((char *)state->buf, sizeof(state->buf),
- &p);
- if (state->buflen == 0) {
- tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
- DEBUG(10, ("build_packet failed\n"));
- return tevent_req_post(req, ev);
- }
-
- subreq = nb_trans_send(state, ev, &state->my_addr, &state->addr, false,
- state->buf, state->buflen,
- NMB_PACKET, nmb->header.name_trn_id,
- node_status_query_validator, NULL);
+ subreq = nb_call_send(state, ev, &state->pkt,
+ nmb->header.name_trn_id, NULL,
+ node_status_query_validator, NULL);
if (tevent_req_nomem(subreq, req)) {
DEBUG(10, ("nb_trans_send failed\n"));
return tevent_req_post(req, ev);
@@ -817,7 +398,7 @@ static void node_status_query_done(struct tevent_req *subreq)
req, struct node_status_query_state);
NTSTATUS status;
- status = nb_trans_recv(subreq, state, &state->packet);
+ status = nb_call_recv(subreq, state, &state->result);
TALLOC_FREE(subreq);
if (tevent_req_nterror(req, status)) {
return;
@@ -840,7 +421,7 @@ NTSTATUS node_status_query_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
return status;
}
node_status = parse_node_status(
- mem_ctx, &state->packet->packet.nmb.answers->rdata[0],
+ mem_ctx, &state->result->packet.nmb.answers->rdata[0],
&num_names, extra);
if (node_status == NULL) {
return NT_STATUS_NO_MEMORY;
--
2.11.0
From 822ab8de8be7d19ceec337ab7f4b897557396da3 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 20 Jan 2018 14:49:45 +0000
Subject: [PATCH 26/32] Use nb_call in name_resolve_bcast
---
source3/libsmb/namequery.c | 350 ++++++++++++++++-----------------------------
1 file changed, 124 insertions(+), 226 deletions(-)
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index e18745bec1c..564d4d19be5 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -1175,286 +1175,184 @@ static bool convert_ss2service(struct ip_service **return_iplist,
return true;
}
-struct name_queries_state {
- struct tevent_context *ev;
- const char *name;
- int name_type;
- bool bcast;
- bool recurse;
- const struct sockaddr_storage *addrs;
- int num_addrs;
- int wait_msec;
- int timeout_msec;
+/********************************************************
+ Resolve via "bcast" method.
+*********************************************************/
- struct tevent_req **subreqs;
- int num_received;
- int num_sent;
+struct name_resolve_bcast_state {
+ struct packet_struct pkt;
- int received_index;
- struct sockaddr_storage *result_addrs;
- int num_result_addrs;
- uint8_t flags;
+ struct sockaddr_storage *addrs;
+ size_t num_addrs;
};
-static void name_queries_done(struct tevent_req *subreq);
-static void name_queries_next(struct tevent_req *subreq);
-
-/*
- * Send a name query to multiple destinations with a wait time in between
- */
+static bool name_resolve_bcast_validator(struct packet_struct *p,
+ void *private_data);
+static void name_resolve_bcast_waited(struct tevent_req *subreq);
+static void name_resolve_bcast_done(struct tevent_req *subreq);
-static struct tevent_req *name_queries_send(
- TALLOC_CTX *mem_ctx, struct tevent_context *ev,
- const char *name, int name_type,
- bool bcast, bool recurse,
- const struct sockaddr_storage *addrs,
- int num_addrs, int wait_msec, int timeout_msec)
+struct tevent_req *name_resolve_bcast_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const char *name,
+ int name_type)
{
struct tevent_req *req, *subreq;
- struct name_queries_state *state;
+ struct name_resolve_bcast_state *state;
+ struct nmb_packet *nmb;
+
+ /*
+ * "bcast" means do a broadcast lookup on all the local interfaces.
+ */
+
+ DEBUG(3, ("name_resolve_bcast: Attempting broadcast lookup "
+ "for name %s<0x%x>\n", name, name_type));
req = tevent_req_create(mem_ctx, &state,
- struct name_queries_state);
+ struct name_resolve_bcast_state);
if (req == NULL) {
return NULL;
}
- state->ev = ev;
- state->name = name;
- state->name_type = name_type;
- state->bcast = bcast;
- state->recurse = recurse;
- state->addrs = addrs;
- state->num_addrs = num_addrs;
- state->wait_msec = wait_msec;
- state->timeout_msec = timeout_msec;
-
- state->subreqs = talloc_zero_array(
- state, struct tevent_req *, num_addrs);
- if (tevent_req_nomem(state->subreqs, req)) {
- return tevent_req_post(req, ev);
- }
- state->num_sent = 0;
- subreq = name_query_send(
- state->subreqs, state->ev, name, name_type, bcast, recurse,
- &state->addrs[state->num_sent]);
+ nmb = &state->pkt.packet.nmb;
+
+ nmb->header.name_trn_id = generate_trn_id();
+ nmb->header.opcode = NMB_NAME_QUERY_OPCODE;
+ nmb->header.nm_flags.bcast = true;
+
+ make_nmb_name(&nmb->question.question_name,name,name_type);
+ nmb->question.question_type = RR_TYPE_NB;
+ nmb->question.question_class = RR_CLASS_IN;
+
+ nmb->header.qdcount = 1;
+
+ subreq = nb_call_send(state, ev, &state->pkt,
+ nmb->header.name_trn_id, NULL,
+ name_resolve_bcast_validator, state);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
- if (!tevent_req_set_endtime(
- subreq, state->ev,
- timeval_current_ofs(0, state->timeout_msec * 1000))) {
- tevent_req_oom(req);
+ tevent_req_set_callback(subreq, name_resolve_bcast_done, req);
+
+ /*
+ * Wait one second for group names
+ */
+ subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
+ if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
- tevent_req_set_callback(subreq, name_queries_done, req);
-
- state->subreqs[state->num_sent] = subreq;
- state->num_sent += 1;
+ tevent_req_set_callback(subreq, name_resolve_bcast_waited, req);
- if (state->num_sent < state->num_addrs) {
- subreq = tevent_wakeup_send(
- state, state->ev,
- timeval_current_ofs(0, state->wait_msec * 1000));
- if (tevent_req_nomem(subreq, req)) {
- return tevent_req_post(req, ev);
- }
- tevent_req_set_callback(subreq, name_queries_next, req);
- }
return req;
}
-static void name_queries_done(struct tevent_req *subreq)
+static bool name_resolve_bcast_validator(struct packet_struct *pkt,
+ void *private_data)
{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct name_queries_state *state = tevent_req_data(
- req, struct name_queries_state);
- int i;
- NTSTATUS status;
-
- status = name_query_recv(subreq, state, &state->result_addrs,
- &state->num_result_addrs, &state->flags);
-
- for (i=0; i<state->num_sent; i++) {
- if (state->subreqs[i] == subreq) {
- break;
- }
- }
- if (i == state->num_sent) {
- tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
- return;
- }
- TALLOC_FREE(state->subreqs[i]);
-
- state->num_received += 1;
-
- if (!NT_STATUS_IS_OK(status)) {
+ struct name_resolve_bcast_state *state = talloc_get_type_abort(
+ private_data, struct name_resolve_bcast_state);
+ struct nmb_packet *nmb;
+ struct res_rec *answer;
+ size_t i, num_addr_entries;
+ struct sockaddr_storage *tmp;
+ bool got_unique_netbios_name = false;
- if (state->num_received >= state->num_addrs) {
- tevent_req_nterror(req, status);
- return;
- }
- /*
- * Still outstanding requests, just wait
- */
- return;
+ if (pkt->packet_type != NMB_PACKET) {
+ return false;
}
- state->received_index = i;
- tevent_req_done(req);
-}
-
-static void name_queries_next(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct name_queries_state *state = tevent_req_data(
- req, struct name_queries_state);
+ nmb = &pkt->packet.nmb;
- if (!tevent_wakeup_recv(subreq)) {
- tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
- return;
+ if ((nmb->header.opcode != NMB_NAME_QUERY_OPCODE) ||
+ !nmb->header.response ||
+ nmb->header.nm_flags.bcast ||
+ (nmb->header.rcode != 0) ||
+ (nmb->header.ancount != 1)) {
+ return false;
}
- subreq = name_query_send(
- state->subreqs, state->ev,
- state->name, state->name_type, state->bcast, state->recurse,
- &state->addrs[state->num_sent]);
- if (tevent_req_nomem(subreq, req)) {
- return;
- }
- tevent_req_set_callback(subreq, name_queries_done, req);
- if (!tevent_req_set_endtime(
- subreq, state->ev,
- timeval_current_ofs(0, state->timeout_msec * 1000))) {
- tevent_req_oom(req);
- return;
- }
- state->subreqs[state->num_sent] = subreq;
- state->num_sent += 1;
+ /*
+ * NetBIOS only has one answer record
+ */
+ answer = nmb->answers;
- if (state->num_sent < state->num_addrs) {
- subreq = tevent_wakeup_send(
- state, state->ev,
- timeval_current_ofs(0, state->wait_msec * 1000));
- if (tevent_req_nomem(subreq, req)) {
- return;
- }
- tevent_req_set_callback(subreq, name_queries_next, req);
+ if ((answer->rdlength % 6) != 0) {
+ return false;
}
-}
-
-static NTSTATUS name_queries_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
- struct sockaddr_storage **result_addrs,
- int *num_result_addrs, uint8_t *flags,
- int *received_index)
-{
- struct name_queries_state *state = tevent_req_data(
- req, struct name_queries_state);
- NTSTATUS status;
- if (tevent_req_is_nterror(req, &status)) {
- return status;
- }
+ num_addr_entries = answer->rdlength / 6;
- if (result_addrs != NULL) {
- *result_addrs = talloc_move(mem_ctx, &state->result_addrs);
- }
- if (num_result_addrs != NULL) {
- *num_result_addrs = state->num_result_addrs;
- }
- if (flags != NULL) {
- *flags = state->flags;
- }
- if (received_index != NULL) {
- *received_index = state->received_index;
+ tmp = talloc_realloc(state, state->addrs, struct sockaddr_storage,
+ state->num_addrs + num_addr_entries);
+ if (tmp == NULL) {
+ /* Exit without addrs */
+ return true;
}
- return NT_STATUS_OK;
-}
+ state->addrs = tmp;
-/********************************************************
- Resolve via "bcast" method.
-*********************************************************/
+ for (i=0; i<num_addr_entries; i++) {
+ char *addr_entry = answer->rdata + (i*6);
+ uint16_t flags;
+ struct sockaddr_storage *addr =
+ &state->addrs[state->num_addrs];
+ struct in_addr ip;
+ size_t j;
-struct name_resolve_bcast_state {
- struct sockaddr_storage *addrs;
- int num_addrs;
-};
+ flags = RSVAL(addr_entry, 0);
+ got_unique_netbios_name |= ((flags & 0x8000) == 0);
-static void name_resolve_bcast_done(struct tevent_req *subreq);
+ putip((char *)&ip, addr_entry+2);
+ in_addr_to_sockaddr_storage(addr, ip);
-struct tevent_req *name_resolve_bcast_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- const char *name,
- int name_type)
-{
- struct tevent_req *req, *subreq;
- struct name_resolve_bcast_state *state;
- struct sockaddr_storage *bcast_addrs;
- int i, num_addrs, num_bcast_addrs;
+ if (is_zero_addr(addr)) {
+ continue;
+ }
+ for (j=0; j<state->num_addrs; j++) {
+ struct sockaddr_storage *cmp = &state->addrs[j];
- req = tevent_req_create(mem_ctx, &state,
- struct name_resolve_bcast_state);
- if (req == NULL) {
- return NULL;
- }
+ if (sockaddr_equal((struct sockaddr *)(void *)cmp,
+ (struct sockaddr *)(void *)addr)) {
+ break;
+ }
+ }
+ if (j < state->num_addrs) {
+ /* Already got it */
+ continue;
+ }
- if (lp_disable_netbios()) {
- DEBUG(5, ("name_resolve_bcast(%s#%02x): netbios is disabled\n",
- name, name_type));
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
+ state->num_addrs += 1;
}
- /*
- * "bcast" means do a broadcast lookup on all the local interfaces.
- */
-
- DEBUG(3, ("name_resolve_bcast: Attempting broadcast lookup "
- "for name %s<0x%x>\n", name, name_type));
-
- num_addrs = iface_count();
- bcast_addrs = talloc_array(state, struct sockaddr_storage, num_addrs);
- if (tevent_req_nomem(bcast_addrs, req)) {
- return tevent_req_post(req, ev);
+ if (got_unique_netbios_name) {
+ return true;
}
- /*
- * Lookup the name on all the interfaces, return on
- * the first successful match.
- */
- num_bcast_addrs = 0;
-
- for (i=0; i<num_addrs; i++) {
- const struct sockaddr_storage *pss = iface_n_bcast(i);
+ return false;
+}
- if (pss->ss_family != AF_INET) {
- continue;
- }
- bcast_addrs[num_bcast_addrs] = *pss;
- num_bcast_addrs += 1;
- }
+static void name_resolve_bcast_waited(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ bool ret;
- subreq = name_queries_send(state, ev, name, name_type, true, true,
- bcast_addrs, num_bcast_addrs, 0, 1000);
- if (tevent_req_nomem(subreq, req)) {
- return tevent_req_post(req, ev);
+ ret = tevent_wakeup_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (!ret) {
+ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+ return;
}
- tevent_req_set_callback(subreq, name_resolve_bcast_done, req);
- return req;
+ tevent_req_done(req);
}
static void name_resolve_bcast_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(
subreq, struct tevent_req);
- struct name_resolve_bcast_state *state = tevent_req_data(
- req, struct name_resolve_bcast_state);
NTSTATUS status;
- status = name_queries_recv(subreq, state,
- &state->addrs, &state->num_addrs,
- NULL, NULL);
+ /*
+ * We've collected the addresses in the validator
+ */
+ status = nb_call_recv(subreq, NULL, NULL);
TALLOC_FREE(subreq);
if (tevent_req_nterror(req, status)) {
return;
--
2.11.0
From ea1d85288eb1f674f0c9a48430e2c87c61b926b2 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 25 Jan 2018 12:48:54 +0100
Subject: [PATCH 27/32] libsmb: Remove unused #includes
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/libsmb/namequery.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index 564d4d19be5..59c7cf0c2e2 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -23,10 +23,7 @@
#include "libads/sitename_cache.h"
#include "../lib/addns/dnsquery.h"
#include "../libcli/netlogon/netlogon.h"
-#include "lib/async_req/async_sock.h"
-#include "lib/tsocket/tsocket.h"
#include "libsmb/nmblib.h"
-#include "libsmb/unexpected.h"
#include "libsmb/nb_call.h"
#include "../libcli/nbt/libnbt.h"
#include "libads/kerberos_proto.h"
--
2.11.0
From fcd559832887e41285629000ef6de21013075203 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 25 Jan 2018 13:02:20 +0100
Subject: [PATCH 28/32] nmblookup: We don't need receiving sockets anymore
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/utils/nmblookup.c | 37 -------------------------------------
1 file changed, 37 deletions(-)
diff --git a/source3/utils/nmblookup.c b/source3/utils/nmblookup.c
index dadd30fdb74..4435cc54412 100644
--- a/source3/utils/nmblookup.c
+++ b/source3/utils/nmblookup.c
@@ -29,41 +29,10 @@ static bool got_bcast = false;
static struct sockaddr_storage bcast_addr;
static bool recursion_desired = false;
static bool translate_addresses = false;
-static int ServerFD= -1;
static bool RootPort = false;
static bool find_status = false;
/****************************************************************************
- Open the socket communication.
-**************************************************************************/
-
-static bool open_sockets(void)
-{
- struct sockaddr_storage ss;
- const char *sock_addr = lp_nbt_client_socket_address();
-
- if (!interpret_string_addr(&ss, sock_addr,
- AI_NUMERICHOST|AI_PASSIVE)) {
- DEBUG(0,("open_sockets: unable to get socket address "
- "from string %s", sock_addr));
- return false;
- }
- ServerFD = open_socket_in( SOCK_DGRAM,
- (RootPort ? 137 : 0),
- (RootPort ? 0 : 3),
- &ss, true );
-
- if (ServerFD == -1) {
- return false;
- }
-
- set_socket_options( ServerFD, "SO_BROADCAST" );
-
- DEBUG(3, ("Socket opened.\n"));
- return true;
-}
-
-/****************************************************************************
turn a node status flags field into a string
****************************************************************************/
static char *node_status_flags(unsigned char flags)
@@ -311,12 +280,6 @@ int main(int argc, const char *argv[])
get_dyn_CONFIGFILE());
}
- load_interfaces();
- if (!open_sockets()) {
- rc = 1;
- goto out;
- }
-
while(poptPeekArg(pc)) {
char *p;
struct in_addr ip;
--
2.11.0
From 301b34d9d4d3cefb71c79ac1b47b14900049a1d3 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 25 Jan 2018 13:24:00 +0100
Subject: [PATCH 29/32] nmblookup: Remove unneeded option "-r"
---
docs-xml/manpages/nmblookup.1.xml | 14 --------------
source3/utils/nmblookup.c | 4 ----
2 files changed, 18 deletions(-)
diff --git a/docs-xml/manpages/nmblookup.1.xml b/docs-xml/manpages/nmblookup.1.xml
index c633e072146..4f1c0d93c8b 100644
--- a/docs-xml/manpages/nmblookup.1.xml
+++ b/docs-xml/manpages/nmblookup.1.xml
@@ -23,7 +23,6 @@
<arg choice="opt">-M|--master-browser</arg>
<arg choice="opt">-R|--recursion</arg>
<arg choice="opt">-S|--status</arg>
- <arg choice="opt">-r|--root-port</arg>
<arg choice="opt">-A|--lookup-by-ip</arg>
<arg choice="opt">-B|--broadcast <broadcast address></arg>
<arg choice="opt">-U|--unicast <unicast address></arg>
@@ -86,19 +85,6 @@
<varlistentry>
- <term>-r|--root-port</term>
- <listitem><para>Try and bind to UDP port 137 to send and receive UDP
- datagrams. The reason for this option is a bug in Windows 95
- where it ignores the source port of the requesting packet
- and only replies to UDP port 137. Unfortunately, on most UNIX
- systems root privilege is needed to bind to this port, and
- in addition, if the <citerefentry><refentrytitle>nmbd</refentrytitle>
- <manvolnum>8</manvolnum></citerefentry> daemon is running on this machine it also binds to this port.
- </para></listitem>
- </varlistentry>
-
-
- <varlistentry>
<term>-A|--lookup-by-ip</term>
<listitem><para>Interpret <replaceable>name</replaceable> as
an IP Address and do a node status query on this address.</para>
diff --git a/source3/utils/nmblookup.c b/source3/utils/nmblookup.c
index 4435cc54412..eb887f85349 100644
--- a/source3/utils/nmblookup.c
+++ b/source3/utils/nmblookup.c
@@ -29,7 +29,6 @@ static bool got_bcast = false;
static struct sockaddr_storage bcast_addr;
static bool recursion_desired = false;
static bool translate_addresses = false;
-static bool RootPort = false;
static bool find_status = false;
/****************************************************************************
@@ -239,9 +238,6 @@ int main(int argc, const char *argv[])
case 'S':
find_status = true;
break;
- case 'r':
- RootPort = true;
- break;
case 'A':
lookup_by_ip = true;
break;
--
2.11.0
From adc824236f1ede5669fc627f342399d16900b331 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sun, 28 Jan 2018 16:16:52 +0100
Subject: [PATCH 30/32] selftest: Start nmbd before net join in nt4_member
---
selftest/target/Samba3.pm | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 8914507c12e..d502f7fbf72 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -308,6 +308,10 @@ sub setup_nt4_member
$ret or return undef;
+ if (not $self->check_or_start($ret, "yes", "no", "no")) {
+ return undef;
+ }
+
my $nmblookup = Samba::bindir_path($self, "nmblookup");
do {
print "Waiting for the LOGON SERVER registration ...\n";
@@ -345,7 +349,7 @@ sub setup_nt4_member
return undef;
}
- if (not $self->check_or_start($ret, "yes", "yes", "yes")) {
+ if (not $self->check_or_start($ret, "no", "yes", "yes")) {
return undef;
}
--
2.11.0
From c88427eb906c54449aaa1a6343a3ecde16b4a19a Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 30 Jan 2018 13:46:52 +0100
Subject: [PATCH 31/32] direct nmbd socket dir in testenvs
---
selftest/target/Samba3.pm | 1 +
selftest/target/Samba4.pm | 1 +
2 files changed, 2 insertions(+)
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index d502f7fbf72..a8f92cbe140 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -1662,6 +1662,7 @@ sub provision($$$$$$$$$)
binddns dir = $binddnsdir
pid directory = $piddir
lock directory = $lockdir
+ nmbd:socket dir = $lockdir
log file = $logdir/log.\%m
log level = 1
debug pid = yes
diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index 842cd1e1bb6..15e12986bed 100755
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -612,6 +612,7 @@ sub provision_raw_step1($$)
state directory = $ctx->{statedir}
cache directory = $ctx->{cachedir}
winbindd socket directory = $ctx->{winbindd_socket_dir}
+ nmbd:socket dir = $ctx->{winbindd_socket_dir}
ntp signd socket directory = $ctx->{ntp_signd_socket_dir}
winbind separator = /
interfaces = $ctx->{interfaces}
--
2.11.0
From 2181e164d65719a1d29c1f4e82e37521661a24e3 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Mon, 5 Mar 2018 13:04:14 +0100
Subject: [PATCH 32/32] libdgram: We don't need the check for nmbd
Failing to connect to the "unexpected" pipe is sufficient here
---
source3/libsmb/clidgram.c | 7 -------
1 file changed, 7 deletions(-)
diff --git a/source3/libsmb/clidgram.c b/source3/libsmb/clidgram.c
index 8d33ee1719a..d3986de8d09 100644
--- a/source3/libsmb/clidgram.c
+++ b/source3/libsmb/clidgram.c
@@ -281,7 +281,6 @@ struct nbt_getdc_state {
struct tevent_context *ev;
struct nb_packet_reader *reader;
const char *my_mailslot;
- pid_t nmbd_pid;
const struct sockaddr_storage *dc_addr;
const char *domain_name;
@@ -327,12 +326,6 @@ struct tevent_req *nbt_getdc_send(TALLOC_CTX *mem_ctx,
if (tevent_req_nomem(state->my_mailslot, req)) {
return tevent_req_post(req, ev);
}
- state->nmbd_pid = pidfile_pid(lp_pid_directory(), "nmbd");
- if (state->nmbd_pid == 0) {
- DEBUG(3, ("No nmbd found\n"));
- tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
- return tevent_req_post(req, ev);
- }
generate_random_buffer((uint8_t *)(void *)&dgm_id, sizeof(dgm_id));
--
2.11.0
More information about the samba-technical
mailing list