r5108: the beginnings of a nbtd server for Samba4. Currently just displays
authorAndrew Tridgell <tridge@samba.org>
Sun, 30 Jan 2005 10:24:36 +0000 (10:24 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:09:23 +0000 (13:09 -0500)
the packets it receives, but it at least shows how the server
structure will work.

To implement it I extended the libcli/nbt/ library to allow for an
incoming packet handler to be registered. That allows the nbt client
library to be used for low level processing of the nbtd server packets.

Other changes:

 - made the socket library always set SO_REUSEADDR when binding to an
   interface, to ensure that restarts of a server don't have to wait
   for a couple of minutes.

 - made the nbt port configurable. Defaults to 137, but other ports
   will be useful for testing.
(This used to be commit 2fedca6adfd4df9e85cc86896dfa79630777a917)

14 files changed:
source4/build/smb_build/main.pm
source4/include/structs.h
source4/lib/socket/socket_ipv4.c
source4/lib/socket/socket_ipv6.c
source4/libcli/nbt/libnbt.h
source4/libcli/nbt/namequery.c
source4/libcli/nbt/nbtsocket.c
source4/nbt_server/config.mk [new file with mode: 0644]
source4/nbt_server/interfaces.c [new file with mode: 0644]
source4/nbt_server/nbt_server.c [new file with mode: 0644]
source4/nbt_server/nbt_server.h [new file with mode: 0644]
source4/param/loadparm.c
source4/smbd/config.mk
source4/smbd/service_stream.c

index af4220ec7ba4774700759b0cb18bf0bde623adcb..cd776b54b93feedd84506cebf86a0cf4070cfea8 100644 (file)
@@ -41,6 +41,7 @@ sub smb_build_main($)
                "rpc_server/config.mk",
                "ldap_server/config.mk",
                "winbind/config.mk",
+               "nbt_server/config.mk",
                "libcli/auth/gensec.mk",
                "libcli/auth/config.mk",
                "libcli/ldap/config.mk",
index 2fe069e949e62ebc0b1c7e3ddc4ee1135144a3ef..0de876ca7c20d1b018b095a05ac9fb6d1fd9e2eb 100644 (file)
@@ -157,3 +157,5 @@ struct stream_connection;
 struct task_server;
 struct model_ops;
 struct stream_server_ops;
+
+struct nbt_server;
index aaa5ce0fa24e54f667d39b39b3bb98e1cbe48fb1..09a4b4a73a87b16e267a363cc49d2b964dc3571a 100644 (file)
@@ -139,6 +139,8 @@ static NTSTATUS ipv4_listen(struct socket_context *sock,
        struct ipv4_addr ip_addr;
        int ret;
 
+       socket_set_option(sock, "SO_REUSEADDR=1", NULL);
+
        ip_addr = interpret_addr2(my_address);
 
        ZERO_STRUCT(my_addr);
index 1dd7fe8e9da60d0686238bb3eae4a28bc2c5da1c..f5cd756259a0783224d82b8ae387d0ade14b087d 100644 (file)
@@ -125,6 +125,8 @@ static NTSTATUS ipv6_tcp_listen(struct socket_context *sock,
        struct in6_addr ip_addr;
        int ret;
 
+       socket_set_option(sock, "SO_REUSEADDR=1", NULL);
+
        ip_addr = interpret_addr6(my_address);
 
        ZERO_STRUCT(my_addr);
index a7788f791bf593de1b7ea8c7e18e6d4afba1ee5e..82069f039030d47290c227147c017ad64363ae7f 100644 (file)
@@ -90,6 +90,14 @@ struct nbt_name_socket {
 
        /* how many requests are waiting for a reply */
        uint16_t num_pending;
+
+       /* what to do with incoming request packets */
+       struct {
+               void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *, 
+                               const char *, int );
+               void *private;
+       } incoming;
+          
 };
 
 
index 05d5e554911e22464fca38c4e59debff55b69ce0..6f549e6241a8872d4af0b3f07c4c29a31ec6734b 100644 (file)
@@ -52,7 +52,7 @@ struct nbt_name_request *nbt_name_query_send(struct nbt_name_socket *nbtsock,
        packet->questions[0].question_type = NBT_QTYPE_NETBIOS;
        packet->questions[0].question_class = NBT_QCLASS_IP;
        
-       req = nbt_name_request_send(nbtsock, io->in.dest_addr, NBT_NAME_SERVICE_PORT, packet,
+       req = nbt_name_request_send(nbtsock, io->in.dest_addr, lp_nbt_port(), packet,
                                    timeval_current_ofs(io->in.timeout, 0), False);
        if (req == NULL) goto failed;
 
@@ -142,7 +142,7 @@ struct nbt_name_request *nbt_name_status_send(struct nbt_name_socket *nbtsock,
        packet->questions[0].question_type = NBT_QTYPE_STATUS;
        packet->questions[0].question_class = NBT_QCLASS_IP;
        
-       req = nbt_name_request_send(nbtsock, io->in.dest_addr, NBT_NAME_SERVICE_PORT, packet,
+       req = nbt_name_request_send(nbtsock, io->in.dest_addr, lp_nbt_port(), packet,
                                    timeval_current_ofs(io->in.timeout, 0), False);
        if (req == NULL) goto failed;
 
index 1eea77d356b697aa05f87504152228ec5063dd8a..f1964b71587fc98bfb918011eeef4d9c326f3438 100644 (file)
@@ -51,7 +51,8 @@ static int nbt_name_request_destructor(void *ptr)
        if (req->nbtsock->send_queue == NULL) {
                req->nbtsock->fde->flags &= ~EVENT_FD_WRITE;
        }
-       if (req->nbtsock->num_pending == 0) {
+       if (req->nbtsock->num_pending == 0 && 
+           req->nbtsock->incoming.handler == NULL) {
                req->nbtsock->fde->flags &= ~EVENT_FD_READ;
        }
        return 0;
@@ -170,6 +171,9 @@ static void nbt_name_socket_recv(struct nbt_name_socket *nbtsock)
        }
 
        if (!(packet->operation & NBT_FLAG_REPLY)) {
+               if (nbtsock->incoming.handler) {
+                       nbtsock->incoming.handler(nbtsock, packet, src_addr, src_port);
+               }
                talloc_free(tmp_ctx);
                return;
        }
@@ -375,3 +379,20 @@ NTSTATUS nbt_name_request_recv(struct nbt_name_request *req)
        }
        return req->status;
 }
+
+
+/*
+  setup a handler for incoming requests
+*/
+NTSTATUS nbt_set_incoming_handler(struct nbt_name_socket *nbtsock,
+                                 void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *, 
+                                                 const char *, int ),
+                                 void *private)
+{
+       nbtsock->incoming.handler = handler;
+       nbtsock->incoming.private = private;
+       nbtsock->fde->flags |= EVENT_FD_READ;
+       socket_set_option(nbtsock->sock, "SO_BROADCAST", "1");
+       return NT_STATUS_OK;
+}
+
diff --git a/source4/nbt_server/config.mk b/source4/nbt_server/config.mk
new file mode 100644 (file)
index 0000000..093cb61
--- /dev/null
@@ -0,0 +1,13 @@
+# NBTD server subsystem
+
+#######################
+# Start SUBSYSTEM NBTD
+[SUBSYSTEM::NBTD]
+INIT_OBJ_FILES = \
+               nbt_server/nbt_server.o
+ADD_OBJ_FILES = \
+               nbt_server/interfaces.o
+REQUIRED_SUBSYSTEMS = \
+               LIBCLI_NBT
+# End SUBSYSTEM SMB
+#######################
diff --git a/source4/nbt_server/interfaces.c b/source4/nbt_server/interfaces.c
new file mode 100644 (file)
index 0000000..18893e1
--- /dev/null
@@ -0,0 +1,88 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   NBT interface handling
+
+   Copyright (C) Andrew Tridgell       2005
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "dlinklist.h"
+#include "nbt_server/nbt_server.h"
+#include "smbd/service_task.h"
+#include "libcli/nbt/libnbt.h"
+
+/*
+  start listening on the given address
+*/
+static NTSTATUS nbt_add_socket(struct nbt_server *nbtsrv, 
+                              const char *address, const char *bcast)
+{
+       struct nbt_interface *iface;
+       NTSTATUS status;
+
+       iface = talloc(nbtsrv, struct nbt_interface);
+       NT_STATUS_HAVE_NO_MEMORY(iface);
+
+       iface->nbtsrv = nbtsrv;
+       iface->bcast_address = talloc_steal(iface, bcast);
+       iface->ip_address = talloc_steal(iface, address);
+
+       iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
+       NT_STATUS_HAVE_NO_MEMORY(iface->ip_address);
+
+       status = socket_listen(iface->nbtsock->sock, address, lp_nbt_port(), 0, 0);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("Failed to bind to %s:%d - %s\n", 
+                        address, lp_nbt_port(), nt_errstr(status)));
+               talloc_free(iface);
+               return status;
+       }
+
+       DLIST_ADD(nbtsrv->interfaces, iface);
+
+       return NT_STATUS_OK;
+}
+
+
+/*
+  setup our listening sockets on the configured network interfaces
+*/
+NTSTATUS nbt_startup_interfaces(struct nbt_server *nbtsrv)
+{
+       int num_interfaces = iface_count();
+       int i;
+       TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv);
+       NTSTATUS status;
+
+       status = nbt_add_socket(nbtsrv, 
+                               talloc_strdup(tmp_ctx, "0.0.0.0"), 
+                               talloc_strdup(tmp_ctx, "255.255.255.255"));
+       NT_STATUS_NOT_OK_RETURN(status);
+
+       for (i=0; i<num_interfaces; i++) {
+               const char *address = talloc_strdup(tmp_ctx, sys_inet_ntoa(*iface_n_ip(i)));
+               const char *bcast   = talloc_strdup(tmp_ctx, sys_inet_ntoa(*iface_n_bcast(i)));
+
+               status = nbt_add_socket(nbtsrv, address, bcast);
+               NT_STATUS_NOT_OK_RETURN(status);
+       }
+
+       talloc_free(tmp_ctx);
+
+       return NT_STATUS_OK;
+}
diff --git a/source4/nbt_server/nbt_server.c b/source4/nbt_server/nbt_server.c
new file mode 100644 (file)
index 0000000..19dabdf
--- /dev/null
@@ -0,0 +1,85 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   NBT server task
+
+   Copyright (C) Andrew Tridgell       2005
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "events.h"
+#include "libcli/nbt/libnbt.h"
+#include "smbd/service_task.h"
+#include "nbt_server/nbt_server.h"
+
+
+/*
+  receive an incoming request
+*/
+static void nbt_request_handler(struct nbt_name_socket *nbtsock, 
+                               struct nbt_name_packet *packet, 
+                               const char *src_address, int src_port)
+{
+       struct nbt_interface *iface = talloc_get_type(nbtsock->incoming.private, 
+                                                     struct nbt_interface);
+       DEBUG(0,("nbtd request from %s:%d\n", src_address, src_port));
+
+       NDR_PRINT_DEBUG(nbt_name_packet, packet);
+}
+
+
+/*
+  startup the nbtd task
+*/
+static void nbtd_task_init(struct task_server *task)
+{
+       struct nbt_server *nbtsrv;
+       struct nbt_interface *iface;
+
+       nbtsrv = talloc(task, struct nbt_server);
+       if (nbtsrv == NULL) {
+               task_terminate(task, "nbtd: out of memory");
+               return;
+       }
+
+       nbtsrv->task = task;
+       nbtsrv->interfaces = NULL;
+
+       nbt_startup_interfaces(nbtsrv);
+
+       for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
+               nbt_set_incoming_handler(iface->nbtsock, nbt_request_handler, iface);
+       }
+}
+
+
+/*
+  initialise the nbt server
+ */
+static NTSTATUS nbtd_init(struct event_context *event_ctx, const struct model_ops *model_ops)
+{
+       return task_server_startup(event_ctx, model_ops, nbtd_task_init);
+}
+
+
+/*
+  register ourselves as a available server
+*/
+NTSTATUS server_service_nbtd_init(void)
+{
+       return register_server_service("nbt", nbtd_init);
+}
diff --git a/source4/nbt_server/nbt_server.h b/source4/nbt_server/nbt_server.h
new file mode 100644 (file)
index 0000000..9ef510f
--- /dev/null
@@ -0,0 +1,44 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   NBT server structures
+
+   Copyright (C) Andrew Tridgell       2005
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+/* a list of network interfaces we are listening on */
+struct nbt_interface {
+       struct nbt_interface *next, *prev;
+       const char *ip_address;
+       const char *bcast_address;
+       struct nbt_name_socket *nbtsock;
+       struct nbt_server *nbtsrv;
+};
+
+
+/*
+  top level context structure for the nbt server
+*/
+struct nbt_server {
+       struct task_server *task;
+
+       struct nbt_interface *interfaces;
+};
+
+
+
index 8380fccaf73a2f432b4e49784b18b6ff6de94b60..d5a8928c3d74faccd05c555a3e336a4713b46b37 100644 (file)
@@ -61,6 +61,7 @@
 #include "system/printing.h"
 #include "librpc/gen_ndr/ndr_svcctl.h"
 #include "librpc/gen_ndr/ndr_samr.h"
+#include "librpc/gen_ndr/ndr_nbt.h"
 #include "dlinklist.h"
 
 BOOL in_client = False;                /* Not in the client by default */
@@ -233,6 +234,7 @@ typedef struct
        int winbind_cache_time;
        int iLockSpinCount;
        int iLockSpinTime;
+       int nbt_port;
        char *socket_options;
        BOOL bDNSproxy;
        BOOL bWINSsupport;
@@ -612,6 +614,7 @@ static struct parm_struct parm_table[] = {
        {"Protocol Options", P_SEP, P_SEPARATOR},
        
        {"smb ports", P_LIST, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"nbt port", P_INTEGER, P_GLOBAL, &Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
        {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
        {"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
@@ -1044,6 +1047,7 @@ static void init_globals(void)
        do_parameter("use spnego", "True");
 
        do_parameter("smb ports", SMB_PORTS);
+       do_parameter("nbt port", "137");
 
        do_parameter("nt status support", "True");
 }
@@ -1141,6 +1145,7 @@ static const char *lp_string(const char *s)
  int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
 
 FN_GLOBAL_LIST(lp_smb_ports, &Globals.smb_ports)
+FN_GLOBAL_INTEGER(lp_nbt_port, &Globals.nbt_port)
 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
 FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
index 4d5e929c795da5d624255ef917e593cd9e2d3b91..39697205f6bfdd252b6feabb6c04347ae4292335 100644 (file)
@@ -40,6 +40,16 @@ REQUIRED_SUBSYSTEMS = \
 # End MODULE server_ldap
 ################################################
 
+################################################
+# Start MODULE server_service_nbtd
+[MODULE::server_service_nbtd]
+INIT_FUNCTION = server_service_nbtd_init
+SUBSYSTEM = SERVER_SERVICE
+REQUIRED_SUBSYSTEMS = \
+               NBTD
+# End MODULE server_service_nbtd
+################################################
+
 #######################
 # Start SUBSYSTEM SERVICE
 [SUBSYSTEM::SERVER_SERVICE]
index 0d29c9fcb877acb0dd0ecb55bdd251482a3d8905..1662e9005fa6289d64f20622a365bc0a673f09f9 100644 (file)
@@ -170,7 +170,7 @@ NTSTATUS stream_setup_socket(struct event_context *event_context,
        talloc_steal(stream_socket, stream_socket->sock);
 
        /* ready to listen */
-       status = socket_set_option(stream_socket->sock, "SO_KEEPALIVE SO_REUSEADDR=1", NULL);
+       status = socket_set_option(stream_socket->sock, "SO_KEEPALIVE", NULL);
        NT_STATUS_NOT_OK_RETURN(status);
 
        status = socket_set_option(stream_socket->sock, lp_socket_options(), NULL);