r6184: the beginnings of the libcli/dgram/ library, and the dgram
authorAndrew Tridgell <tridge@samba.org>
Sun, 3 Apr 2005 04:32:37 +0000 (04:32 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:11:24 +0000 (13:11 -0500)
server. Currently just listens on port 138 and parses the packets
(using IDL like the rest of NBT). This allows me to develop the
structures and test with real packets
(This used to be commit 10d64a525349ff96695ad961a3cfeb5bc7c8844f)

source4/libcli/dgram/dgramsocket.c [new file with mode: 0644]
source4/libcli/dgram/libdgram.h [new file with mode: 0644]
source4/librpc/idl/nbt.idl
source4/nbt_server/interfaces.c
source4/nbt_server/nbt_server.h
source4/nbt_server/register.c
source4/param/loadparm.c

diff --git a/source4/libcli/dgram/dgramsocket.c b/source4/libcli/dgram/dgramsocket.c
new file mode 100644 (file)
index 0000000..7f179bc
--- /dev/null
@@ -0,0 +1,153 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   low level socket handling for nbt dgram requests (UDP138)
+
+   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 "lib/events/events.h"
+#include "dlinklist.h"
+#include "libcli/nbt/libnbt.h"
+#include "libcli/dgram/libdgram.h"
+#include "lib/socket/socket.h"
+
+#define DGRAM_MAX_PACKET_SIZE 2048
+
+
+/*
+  handle recv events on a nbt dgram socket
+*/
+static void dgm_socket_recv(struct nbt_dgram_socket *nbtsock)
+{
+       TALLOC_CTX *tmp_ctx = talloc_new(nbtsock);
+       NTSTATUS status;
+       const char *src_addr;
+       int src_port;
+       DATA_BLOB blob;
+       size_t nread;
+       struct nbt_dgram_packet *packet;
+
+       blob = data_blob_talloc(tmp_ctx, NULL, DGRAM_MAX_PACKET_SIZE);
+       if (blob.data == NULL) {
+               talloc_free(tmp_ctx);
+               return;
+       }
+
+       status = socket_recvfrom(nbtsock->sock, blob.data, blob.length, &nread, 0,
+                                &src_addr, &src_port);
+       if (!NT_STATUS_IS_OK(status)) {
+               talloc_free(tmp_ctx);
+               return;
+       }
+       talloc_steal(tmp_ctx, src_addr);
+       blob.length = nread;
+
+       DEBUG(0,("Received dgram packet of length %d from %s:%d\n", 
+                blob.length, src_addr, src_port));
+
+       packet = talloc(tmp_ctx, struct nbt_dgram_packet);
+       if (packet == NULL) {
+               talloc_free(tmp_ctx);
+               return;
+       }
+
+       /* parse the request */
+       status = ndr_pull_struct_blob(&blob, packet, packet, 
+                                     (ndr_pull_flags_fn_t)ndr_pull_nbt_dgram_packet);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(2,("Failed to parse incoming NBT DGRAM packet - %s\n",
+                        nt_errstr(status)));
+               talloc_free(tmp_ctx);
+               return;
+       }
+
+       NDR_PRINT_DEBUG(nbt_dgram_packet, packet);
+
+       talloc_free(tmp_ctx);
+}
+
+
+/*
+  handle fd events on a nbt_dgram_socket
+*/
+static void dgm_socket_handler(struct event_context *ev, struct fd_event *fde,
+                              uint16_t flags, void *private)
+{
+       struct nbt_dgram_socket *dgmsock = talloc_get_type(private, 
+                                                          struct nbt_dgram_socket);
+       if (flags & EVENT_FD_WRITE) {
+               /* nothing at the moment */
+       } else if (flags & EVENT_FD_READ) {
+               dgm_socket_recv(dgmsock);
+       }
+}
+
+/*
+  initialise a nbt_dgram_socket. The event_ctx is optional, if provided
+  then operations will use that event context
+*/
+struct nbt_dgram_socket *nbt_dgram_socket_init(TALLOC_CTX *mem_ctx, 
+                                             struct event_context *event_ctx)
+{
+       struct nbt_dgram_socket *dgmsock;
+       NTSTATUS status;
+
+       dgmsock = talloc(mem_ctx, struct nbt_dgram_socket);
+       if (dgmsock == NULL) goto failed;
+
+       if (event_ctx == NULL) {
+               dgmsock->event_ctx = event_context_init(dgmsock);
+       } else {
+               dgmsock->event_ctx = talloc_reference(dgmsock, event_ctx);
+       }
+       if (dgmsock->event_ctx == NULL) goto failed;
+
+       status = socket_create("ip", SOCKET_TYPE_DGRAM, &dgmsock->sock, 0);
+       if (!NT_STATUS_IS_OK(status)) goto failed;
+
+       socket_set_option(dgmsock->sock, "SO_BROADCAST", "1");
+
+       talloc_steal(dgmsock, dgmsock->sock);
+
+       dgmsock->fde = event_add_fd(dgmsock->event_ctx, dgmsock, 
+                                   socket_get_fd(dgmsock->sock), 0,
+                                   dgm_socket_handler, dgmsock);
+       
+       return dgmsock;
+
+failed:
+       talloc_free(dgmsock);
+       return NULL;
+}
+
+
+/*
+  setup a handler for incoming requests
+*/
+NTSTATUS dgram_set_incoming_handler(struct nbt_dgram_socket *dgmsock,
+                                   void (*handler)(struct nbt_dgram_socket *, 
+                                                   struct nbt_dgram_packet *, 
+                                                   const char *, int ),
+                                   void *private)
+{
+       dgmsock->incoming.handler = handler;
+       dgmsock->incoming.private = private;
+       EVENT_FD_READABLE(dgmsock->fde);
+       return NT_STATUS_OK;
+}
diff --git a/source4/libcli/dgram/libdgram.h b/source4/libcli/dgram/libdgram.h
new file mode 100644 (file)
index 0000000..6ead6dc
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   a raw async NBT DGRAM library
+
+   Copyright (C) Andrew Tridgell 2005
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 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 "librpc/gen_ndr/ndr_nbt.h"
+
+/*
+  context structure for operations on dgram packets
+*/
+struct nbt_dgram_socket {
+       struct socket_context *sock;
+       struct event_context *event_ctx;
+
+       /* the fd event */
+       struct fd_event *fde;
+
+       /* what to do with incoming request packets */
+       struct {
+               void (*handler)(struct nbt_dgram_socket *, struct nbt_dgram_packet *, 
+                               const char *, int );
+               void *private;
+       } incoming;
+};
index 04fe0c4f90507e207ed86d14f5d37f4722e403b4..4d12dd02d09e9741d939e01078c197d9b80a7f0c 100644 (file)
@@ -183,4 +183,66 @@ interface nbt
                nbt_res_rec       additional[arcount];
                [flag(NDR_REMAINING)] DATA_BLOB padding;
        } nbt_name_packet;
+
+
+       /*
+         NBT DGRAM packets (UDP/138)
+       */
+
+       typedef [enum8bit] enum {
+               DGRAM_DIRECT_UNIQUE  = 0x10,
+               DGRAM_DIRECT_GROUP   = 0x11,
+               DGRAM_BCAST          = 0x12,
+               DGRAM_ERROR          = 0x13,
+               DGRAM_QUERY          = 0x14,
+               DGRAM_QUERY_POSITIVE = 0x15,
+               DGRAM_QUERY_NEGATIVE = 0x16
+       } dgram_msg_type;
+
+       typedef [bitmap8bit] bitmap {
+               DGRAM_FLAG_MORE         = 0x80,
+               DGRAM_FLAG_FIRST        = 0x40,
+               DGRAM_FLAG_NODE_TYPE    = 0x30
+       } dgram_flags;
+
+       typedef [enum8bit] enum {
+               DGRAM_NODE_B    = 0x00,
+               DGRAM_NODE_P    = 0x10,
+               DGRAM_NODE_M    = 0x20,
+               DGRAM_NODE_NBDD = 0x30
+       } dgram_node_type;
+
+       /* a dgram_message is the main dgram body in general use */
+       typedef struct {
+               uint16         length;
+               uint16         offset;
+               nbt_name       source_name;
+               nbt_name       dest_name;
+               [flag(NDR_REMAINING)] DATA_BLOB data;
+       } dgram_message;
+
+       typedef [enum8bit] enum {
+               DGRAM_ERROR_NAME_NOT_PRESENT = 0x82,
+               DGRAM_ERROR_INVALID_SOURCE   = 0x83,
+               DGRAM_ERROR_INVALID_DEST     = 0x84
+       } dgram_err_code;
+
+       typedef [nodiscriminant] union {
+               [case(DGRAM_DIRECT_UNIQUE)]   dgram_message msg;
+               [case(DGRAM_DIRECT_GROUP)]    dgram_message msg;
+               [case(DGRAM_BCAST)]           dgram_message msg;
+               [case(DGRAM_ERROR)]           dgram_err_code error;
+               [case(DGRAM_QUERY)]           nbt_name       dest_name;
+               [case(DGRAM_QUERY_POSITIVE)]  nbt_name       dest_name;
+               [case(DGRAM_QUERY_NEGATIVE)]  nbt_name       dest_name;
+       } dgram_data;
+
+       typedef [flag(NDR_NOALIGN|NDR_BIG_ENDIAN|NDR_PAHEX),public] struct {
+               dgram_msg_type msg_type;
+               dgram_flags    flags;
+               uint16         dgram_id;
+               ipv4address    source;
+               uint16         src_port;
+               [switch_is(msg_type)] dgram_data data;
+       } nbt_dgram_packet;
 }
index bc01ac6d99909afdfd30725da63e1ec88c866600..dfd453832122e04fda2d43929d53f278f9338264 100644 (file)
@@ -63,6 +63,16 @@ static void nbtd_request_handler(struct nbt_name_socket *nbtsock,
 }
 
 
+/*
+  receive an incoming dgram request
+*/
+static void dgram_request_handler(struct nbt_dgram_socket *dgmsock, 
+                                 struct nbt_dgram_packet *packet, 
+                                 const char *src_address, int src_port)
+{
+}
+
+
 
 /*
   find a registered name on an interface
@@ -93,7 +103,6 @@ static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv,
 {
        struct nbtd_interface *iface;
        NTSTATUS status;
-       struct nbt_name_socket *bcast_nbtsock;
 
        /*
          we actually create two sockets. One listens on the broadcast address
@@ -113,6 +122,10 @@ static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv,
        iface->names         = NULL;
 
        if (strcmp(netmask, "0.0.0.0") != 0) {
+               struct nbt_name_socket *bcast_nbtsock;
+               struct nbt_dgram_socket *bcast_dgmsock;
+
+               /* listen for broadcasts on port 137 */
                bcast_nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
                NT_STATUS_HAVE_NO_MEMORY(bcast_nbtsock);
 
@@ -125,10 +138,26 @@ static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv,
                }
 
                nbt_set_incoming_handler(bcast_nbtsock, nbtd_request_handler, iface);
+
+
+               /* listen for broadcasts on port 138 */
+               bcast_dgmsock = nbt_dgram_socket_init(iface, nbtsrv->task->event_ctx);
+               NT_STATUS_HAVE_NO_MEMORY(bcast_dgmsock);
+
+               status = socket_listen(bcast_dgmsock->sock, bcast, lp_dgram_port(), 0, 0);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(0,("Failed to bind to %s:%d - %s\n", 
+                                bcast, lp_dgram_port(), nt_errstr(status)));
+                       talloc_free(iface);
+                       return status;
+               }
+
+               dgram_set_incoming_handler(bcast_dgmsock, dgram_request_handler, iface);
        }
 
+       /* listen for unicasts on port 137 */
        iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
-       NT_STATUS_HAVE_NO_MEMORY(iface->ip_address);
+       NT_STATUS_HAVE_NO_MEMORY(iface->nbtsock);
 
        status = socket_listen(iface->nbtsock->sock, bind_address, lp_nbt_port(), 0, 0);
        if (!NT_STATUS_IS_OK(status)) {
@@ -137,9 +166,22 @@ static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv,
                talloc_free(iface);
                return status;
        }
-
        nbt_set_incoming_handler(iface->nbtsock, nbtd_request_handler, iface);
 
+
+       /* listen for unicasts on port 138 */
+       iface->dgmsock = nbt_dgram_socket_init(iface, nbtsrv->task->event_ctx);
+       NT_STATUS_HAVE_NO_MEMORY(iface->dgmsock);
+
+       status = socket_listen(iface->dgmsock->sock, bind_address, lp_dgram_port(), 0, 0);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("Failed to bind to %s:%d - %s\n", 
+                        address, lp_dgram_port(), nt_errstr(status)));
+               talloc_free(iface);
+               return status;
+       }
+       dgram_set_incoming_handler(iface->dgmsock, dgram_request_handler, iface);
+
        if (strcmp(netmask, "0.0.0.0") == 0) {
                DLIST_ADD(nbtsrv->bcast_interface, iface);
        } else {
index 6a7b14a5463b1c1b2fe5d31b94373d249837f8db..e2b8584f5a8bc60ae842a309fe0ab387a053cc4f 100644 (file)
@@ -21,6 +21,7 @@
 */
 
 #include "libcli/nbt/libnbt.h"
+#include "libcli/dgram/libdgram.h"
 
 /* 
    a list of our registered names on each interface
@@ -47,6 +48,7 @@ struct nbtd_interface {
        const char *bcast_address;
        const char *netmask;
        struct nbt_name_socket *nbtsock;
+       struct nbt_dgram_socket *dgmsock;
        struct nbtd_iface_name *names;
 };
 
index bec316cdea3b8d813492b9882e732cef9c79a1cb..cd39ef47691110d83e82bde289722080d6f5681e 100644 (file)
@@ -27,6 +27,7 @@
 #include "smbd/service_task.h"
 #include "libcli/raw/libcliraw.h"
 #include "libcli/composite/composite.h"
+#include "librpc/gen_ndr/ndr_samr.h"
 
 
 static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname);
@@ -264,6 +265,17 @@ void nbtd_register_names(struct nbtd_server *nbtsrv)
                aliases++;
        }
 
+       switch (lp_server_role()) {
+       case ROLE_DOMAIN_PDC:
+               nbtd_register_name(nbtsrv, lp_workgroup(),    NBT_NAME_PDC, nb_flags);
+               nbtd_register_name(nbtsrv, lp_workgroup(),    NBT_NAME_LOGON, nb_flags);
+               break;
+       case ROLE_DOMAIN_BDC:
+               nbtd_register_name(nbtsrv, lp_workgroup(),    NBT_NAME_LOGON, nb_flags);
+       default:
+               break;
+       }
+
        nb_flags |= NBT_NM_GROUP;
        nbtd_register_name(nbtsrv, lp_workgroup(),    NBT_NAME_CLIENT, nb_flags);
 
index 33026dd9e07d8cb1069d85c9db84a40bef007606..29da770d47d64f9c588d11f83b4208b6d9d98d78 100644 (file)
@@ -236,6 +236,7 @@ typedef struct
        int iLockSpinCount;
        int iLockSpinTime;
        int nbt_port;
+       int dgram_port;
        char *socket_options;
        BOOL bDNSproxy;
        BOOL bWINSsupport;
@@ -617,6 +618,7 @@ static struct parm_struct parm_table[] = {
        
        {"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},
+       {"dgram port", P_INTEGER, P_GLOBAL, &Globals.dgram_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},
@@ -1051,6 +1053,7 @@ static void init_globals(void)
 
        do_parameter("smb ports", SMB_PORTS);
        do_parameter("nbt port", "137");
+       do_parameter("dgram port", "138");
 
        do_parameter("nt status support", "True");
 
@@ -1152,6 +1155,7 @@ static const char *lp_string(const char *s)
 
 FN_GLOBAL_LIST(lp_smb_ports, &Globals.smb_ports)
 FN_GLOBAL_INTEGER(lp_nbt_port, &Globals.nbt_port)
+FN_GLOBAL_INTEGER(lp_dgram_port, &Globals.dgram_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)