r14464: Don't include ndr_BASENAME.h files unless strictly required, instead
[jelmer/samba4-debian.git] / source / nbt_server / register.c
index e033797164e9c879f644c88375c09e9efa603259..7d178991efb6b3b0869210790a56177bb06d127a 100644 (file)
 #include "dlinklist.h"
 #include "nbt_server/nbt_server.h"
 #include "smbd/service_task.h"
-#include "libcli/raw/libcliraw.h"
 #include "libcli/composite/composite.h"
+#include "librpc/gen_ndr/ndr_samr.h"
+#include "nbt_server/wins/winsserver.h"
+#include "librpc/gen_ndr/ndr_nbt.h"
 
 
-static void nbtd_start_refresh_timer(struct nbt_iface_name *iname);
+static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname);
 
 /*
   a name refresh request has completed
 */
 static void refresh_completion_handler(struct nbt_name_request *req)
 {
-       struct nbt_iface_name *iname = talloc_get_type(req->async.private, struct nbt_iface_name);
+       struct nbtd_iface_name *iname = talloc_get_type(req->async.private, 
+                                                       struct nbtd_iface_name);
        NTSTATUS status;
        struct nbt_name_refresh io;
        TALLOC_CTX *tmp_ctx = talloc_new(iname);
 
        status = nbt_name_refresh_recv(req, tmp_ctx, &io);
        if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
-               DEBUG(4,("Refreshed name %s<%02x> on %s\n", 
-                        iname->name.name, iname->name.type, iname->iface->ip_address));
+               DEBUG(4,("Refreshed name %s with %s on interface %s\n", 
+                        nbt_name_string(tmp_ctx, &iname->name),
+                        iname->iface->ip_address, iname->iface->bcast_address));
                iname->registration_time = timeval_current();
                nbtd_start_refresh_timer(iname);
                talloc_free(tmp_ctx);
@@ -55,12 +59,14 @@ static void refresh_completion_handler(struct nbt_name_request *req)
        iname->nb_flags &= ~NBT_NM_ACTIVE;
 
        if (NT_STATUS_IS_OK(status)) {
-               DEBUG(1,("Name conflict from %s refreshing name %s<%02x> on %s - rcode %d\n", 
-                        io.out.reply_addr, iname->name.name, iname->name.type, 
-                        iname->iface->ip_address, io.out.rcode));
+               DEBUG(1,("Name conflict from %s refreshing name %s with %s on interface %s - %s\n", 
+                        io.out.reply_addr, nbt_name_string(tmp_ctx, &iname->name),
+                        iname->iface->ip_address, iname->iface->bcast_address,
+                        nt_errstr(nbt_rcode_to_ntstatus(io.out.rcode))));
        } else {
-               DEBUG(1,("Error refreshing name %s<%02x> on %s - %s\n", 
-                        iname->name.name, iname->name.type, iname->iface->ip_address,
+               DEBUG(1,("Error refreshing name %s with %s on interface %s - %s\n", 
+                        nbt_name_string(tmp_ctx, &iname->name), 
+                        iname->iface->ip_address, iname->iface->bcast_address,
                         nt_errstr(status)));
        }
 
@@ -72,12 +78,13 @@ static void refresh_completion_handler(struct nbt_name_request *req)
   handle name refresh timer events
 */
 static void name_refresh_handler(struct event_context *ev, struct timed_event *te, 
-                                struct timeval t, void *private)
+                                struct timeval t, void *private_data)
 {
-       struct nbt_iface_name *iname = talloc_get_type(private, struct nbt_iface_name);
-       struct nbt_interface *iface = iname->iface;
+       struct nbtd_iface_name *iname = talloc_get_type(private_data, struct nbtd_iface_name);
+       struct nbtd_interface *iface = iname->iface;
        struct nbt_name_register io;
        struct nbt_name_request *req;
+       struct nbtd_server *nbtsrv = iface->nbtsrv;
 
        /* setup a single name register request. Notice that we don't
           use a name refresh request, as Windows and Samba3 do not
@@ -91,8 +98,11 @@ static void name_refresh_handler(struct event_context *ev, struct timed_event *t
        io.in.ttl             = iname->ttl;
        io.in.register_demand = False;
        io.in.broadcast       = True;
+       io.in.multi_homed     = False;
        io.in.timeout         = 3;
+       io.in.retries         = 0;
 
+       nbtsrv->stats.total_sent++;
        req = nbt_name_register_send(iface->nbtsock, &io);
        if (req == NULL) return;
 
@@ -104,7 +114,7 @@ static void name_refresh_handler(struct event_context *ev, struct timed_event *t
 /*
   start a timer to refresh this name
 */
-static void nbtd_start_refresh_timer(struct nbt_iface_name *iname)
+static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname)
 {
        uint32_t refresh_time;
        uint32_t max_refresh_time = lp_parm_int(-1, "nbtd", "max_refresh_time", 7200);
@@ -121,19 +131,22 @@ static void nbtd_start_refresh_timer(struct nbt_iface_name *iname)
 /*
   a name registration has completed
 */
-static void nbtd_register_handler(struct composite_context *req)
+static void nbtd_register_handler(struct composite_context *creq)
 {
-       struct nbt_iface_name *iname = talloc_get_type(req->async.private
-                                                      struct nbt_iface_name);
+       struct nbtd_iface_name *iname = talloc_get_type(creq->async.private_data
+                                                       struct nbtd_iface_name);
        NTSTATUS status;
+       TALLOC_CTX *tmp_ctx = talloc_new(iname);
 
-       status = nbt_name_register_bcast_recv(req);
+       status = nbt_name_register_bcast_recv(creq);
        if (NT_STATUS_IS_OK(status)) {
                /* good - nobody complained about our registration */
                iname->nb_flags |= NBT_NM_ACTIVE;
-               DEBUG(3,("Registered %s<%02x> on interface %s\n",
-                        iname->name.name, iname->name.type, iname->iface->bcast_address));
+               DEBUG(3,("Registered %s with %s on interface %s\n",
+                        nbt_name_string(tmp_ctx, &iname->name), 
+                        iname->iface->ip_address, iname->iface->bcast_address));
                iname->registration_time = timeval_current();
+               talloc_free(tmp_ctx);
                nbtd_start_refresh_timer(iname);
                return;
        }
@@ -141,40 +154,44 @@ static void nbtd_register_handler(struct composite_context *req)
        /* someone must have replied with an objection! */
        iname->nb_flags |= NBT_NM_CONFLICT;
 
-       DEBUG(1,("Error registering %s<%02x> on interface %s - %s\n",
-                iname->name.name, iname->name.type, iname->iface->bcast_address,
+       DEBUG(1,("Error registering %s with %s on interface %s - %s\n",
+                nbt_name_string(tmp_ctx, &iname->name),
+                iname->iface->ip_address, iname->iface->bcast_address,
                 nt_errstr(status)));
+       talloc_free(tmp_ctx);
 }
 
 
 /*
   register a name on a network interface
 */
-static void nbtd_register_name_iface(struct nbt_interface *iface,
+static void nbtd_register_name_iface(struct nbtd_interface *iface,
                                     const char *name, enum nbt_name_type type,
                                     uint16_t nb_flags)
 {
-       struct nbt_iface_name *iname;
+       struct nbtd_iface_name *iname;
        const char *scope = lp_netbios_scope();
        struct nbt_name_register_bcast io;
-       struct composite_context *req;
+       struct composite_context *creq;
+       struct nbtd_server *nbtsrv = iface->nbtsrv;
 
-       iname = talloc(iface, struct nbt_iface_name);
+       iname = talloc(iface, struct nbtd_iface_name);
        if (!iname) return;
 
        iname->iface     = iface;
        iname->name.name = strupper_talloc(iname, name);
        iname->name.type = type;
        if (scope && *scope) {
-               iname->name.scope = talloc_strdup(iname, scope);
+               iname->name.scope = strupper_talloc(iname, scope);
        } else {
                iname->name.scope = NULL;
        }
        iname->nb_flags          = nb_flags;
        iname->ttl               = lp_parm_int(-1, "nbtd", "bcast_ttl", 300000);
        iname->registration_time = timeval_zero();
+       iname->wins_server       = NULL;
 
-       DLIST_ADD_END(iface->names, iname, struct nbt_iface_name *);
+       DLIST_ADD_END(iface->names, iname, struct nbtd_iface_name *);
 
        if (nb_flags & NBT_NM_PERMANENT) {
                /* permanent names are not announced and are immediately active */
@@ -183,6 +200,13 @@ static void nbtd_register_name_iface(struct nbt_interface *iface,
                return;
        }
 
+       /* if this is the wins interface, then we need to do a special
+          wins name registration */
+       if (iface == iface->nbtsrv->wins_interface) {
+               nbtd_winsclient_register(iname);
+               return;
+       }
+
        /* setup a broadcast name registration request */
        io.in.name            = iname->name;
        io.in.dest_addr       = iface->bcast_address;
@@ -190,22 +214,23 @@ static void nbtd_register_name_iface(struct nbt_interface *iface,
        io.in.nb_flags        = nb_flags;
        io.in.ttl             = iname->ttl;
 
-       req = nbt_name_register_bcast_send(iface->nbtsock, &io);
-       if (req == NULL) return;
+       nbtsrv->stats.total_sent++;
+       creq = nbt_name_register_bcast_send(iface->nbtsock, &io);
+       if (creq == NULL) return;
 
-       req->async.fn = nbtd_register_handler;
-       req->async.private = iname;
+       creq->async.fn = nbtd_register_handler;
+       creq->async.private_data = iname;
 }
 
 
 /*
   register one name on all our interfaces
 */
-static void nbtd_register_name(struct nbt_server *nbtsrv, 
+static void nbtd_register_name(struct nbtd_server *nbtsrv, 
                               const char *name, enum nbt_name_type type,
                               uint16_t nb_flags)
 {
-       struct nbt_interface *iface;
+       struct nbtd_interface *iface;
        
        /* register with all the local interfaces */
        for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
@@ -218,14 +243,17 @@ static void nbtd_register_name(struct nbt_server *nbtsrv,
                                         nb_flags | NBT_NM_PERMANENT);
        }
 
-       /* TODO: register with our WINS servers */
+       /* register with our WINS servers */
+       if (nbtsrv->wins_interface) {
+               nbtd_register_name_iface(nbtsrv->wins_interface, name, type, nb_flags);
+       }
 }
 
 
 /*
   register our names on all interfaces
 */
-void nbtd_register_names(struct nbt_server *nbtsrv)
+void nbtd_register_names(struct nbtd_server *nbtsrv)
 {
        uint16_t nb_flags = NBT_NODE_M;
        const char **aliases;
@@ -243,6 +271,17 @@ void nbtd_register_names(struct nbt_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 | NBT_NM_GROUP);
+               break;
+       case ROLE_DOMAIN_BDC:
+               nbtd_register_name(nbtsrv, lp_workgroup(),    NBT_NAME_LOGON, nb_flags | NBT_NM_GROUP);
+       default:
+               break;
+       }
+
        nb_flags |= NBT_NM_GROUP;
        nbtd_register_name(nbtsrv, lp_workgroup(),    NBT_NAME_CLIENT, nb_flags);