LCOV - code coverage report
Current view: top level - source4/nbt_server - register.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 93 136 68.4 %
Date: 2024-02-28 12:06:22 Functions: 5 7 71.4 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    register our names
       5             : 
       6             :    Copyright (C) Andrew Tridgell        2005
       7             :    
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             :    
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             :    
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "lib/events/events.h"
      24             : #include "../lib/util/dlinklist.h"
      25             : #include "nbt_server/nbt_server.h"
      26             : #include "samba/service_task.h"
      27             : #include "libcli/composite/composite.h"
      28             : #include "librpc/gen_ndr/ndr_samr.h"
      29             : #include "nbt_server/wins/winsserver.h"
      30             : #include "librpc/gen_ndr/ndr_nbt.h"
      31             : #include "dsdb/samdb/samdb.h"
      32             : #include "param/param.h"
      33             : #include "libds/common/roles.h"
      34             : 
      35             : static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname);
      36             : 
      37             : /*
      38             :   a name refresh request has completed
      39             : */
      40           0 : static void refresh_completion_handler(struct nbt_name_request *req)
      41             : {
      42           0 :         struct nbtd_iface_name *iname = talloc_get_type(req->async.private_data,
      43             :                                                         struct nbtd_iface_name);
      44           0 :         NTSTATUS status;
      45           0 :         struct nbt_name_refresh io;
      46           0 :         TALLOC_CTX *tmp_ctx = talloc_new(iname);
      47             : 
      48           0 :         status = nbt_name_refresh_recv(req, tmp_ctx, &io);
      49           0 :         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
      50           0 :                 DEBUG(4,("Refreshed name %s with %s on interface %s\n", 
      51             :                          nbt_name_string(tmp_ctx, &iname->name),
      52             :                          iname->iface->ip_address, iname->iface->bcast_address));
      53           0 :                 iname->registration_time = timeval_current();
      54           0 :                 nbtd_start_refresh_timer(iname);
      55           0 :                 talloc_free(tmp_ctx);
      56           0 :                 return;
      57             :         }
      58             : 
      59           0 :         iname->nb_flags |= NBT_NM_CONFLICT;
      60           0 :         iname->nb_flags &= ~NBT_NM_ACTIVE;
      61             : 
      62           0 :         if (NT_STATUS_IS_OK(status)) {
      63           0 :                 DEBUG(1,("Name conflict from %s refreshing name %s with %s on interface %s - %s\n", 
      64             :                          io.out.reply_addr, nbt_name_string(tmp_ctx, &iname->name),
      65             :                          iname->iface->ip_address, iname->iface->bcast_address,
      66             :                          nt_errstr(nbt_rcode_to_ntstatus(io.out.rcode))));
      67             :         } else {
      68           0 :                 DEBUG(1,("Error refreshing name %s with %s on interface %s - %s\n", 
      69             :                          nbt_name_string(tmp_ctx, &iname->name), 
      70             :                          iname->iface->ip_address, iname->iface->bcast_address,
      71             :                          nt_errstr(status)));
      72             :         }
      73             : 
      74           0 :         talloc_free(tmp_ctx);
      75             : }
      76             : 
      77             : 
      78             : /*
      79             :   handle name refresh timer events
      80             : */
      81           0 : static void name_refresh_handler(struct tevent_context *ev, struct tevent_timer *te, 
      82             :                                  struct timeval t, void *private_data)
      83             : {
      84           0 :         struct nbtd_iface_name *iname = talloc_get_type(private_data, struct nbtd_iface_name);
      85           0 :         struct nbtd_interface *iface = iname->iface;
      86           0 :         struct nbt_name_register io;
      87           0 :         struct nbt_name_request *req;
      88           0 :         struct nbtd_server *nbtsrv = iface->nbtsrv;
      89             : 
      90             :         /* setup a single name register request. Notice that we don't
      91             :            use a name refresh request, as Windows and Samba3 do not
      92             :            defend against broadcast name refresh packets. So for this
      93             :            to be of any use at all, we need to refresh using name
      94             :            registration packets */
      95           0 :         io.in.name            = iname->name;
      96           0 :         io.in.dest_addr       = iface->bcast_address;
      97           0 :         io.in.dest_port       = lpcfg_nbt_port(iface->nbtsrv->task->lp_ctx);
      98           0 :         io.in.address         = iface->ip_address;
      99           0 :         io.in.nb_flags        = iname->nb_flags;
     100           0 :         io.in.ttl             = iname->ttl;
     101           0 :         io.in.register_demand = false;
     102           0 :         io.in.broadcast       = true;
     103           0 :         io.in.multi_homed     = false;
     104           0 :         io.in.timeout         = 3;
     105           0 :         io.in.retries         = 0;
     106             : 
     107           0 :         nbtsrv->stats.total_sent++;
     108           0 :         req = nbt_name_register_send(iface->nbtsock, &io);
     109           0 :         if (req == NULL) return;
     110             : 
     111           0 :         req->async.fn = refresh_completion_handler;
     112           0 :         req->async.private_data = iname;
     113             : }
     114             : 
     115             : 
     116             : /*
     117             :   start a timer to refresh this name
     118             : */
     119         383 : static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname)
     120             : {
     121          11 :         uint32_t refresh_time;
     122         383 :         uint32_t max_refresh_time = lpcfg_parm_int(iname->iface->nbtsrv->task->lp_ctx, NULL, "nbtd", "max_refresh_time", 7200);
     123             : 
     124         383 :         refresh_time = MIN(max_refresh_time, iname->ttl/2);
     125             :         
     126         383 :         tevent_add_timer(iname->iface->nbtsrv->task->event_ctx,
     127             :                         iname, 
     128             :                         timeval_add(&iname->registration_time, refresh_time, 0),
     129             :                         name_refresh_handler, iname);
     130         383 : }
     131             : 
     132             : struct nbtd_register_name_state {
     133             :         struct nbtd_iface_name *iname;
     134             :         struct nbt_name_register_bcast io;
     135             : };
     136             : 
     137             : /*
     138             :   a name registration has completed
     139             : */
     140         389 : static void nbtd_register_name_handler(struct tevent_req *subreq)
     141             : {
     142          12 :         struct nbtd_register_name_state *state =
     143         389 :                 tevent_req_callback_data(subreq,
     144             :                 struct nbtd_register_name_state);
     145         389 :         struct nbtd_iface_name *iname = state->iname;
     146          12 :         NTSTATUS status;
     147             : 
     148         389 :         status = nbt_name_register_bcast_recv(subreq);
     149         389 :         TALLOC_FREE(subreq);
     150         389 :         if (NT_STATUS_IS_OK(status)) {
     151             :                 /* good - nobody complained about our registration */
     152         383 :                 iname->nb_flags |= NBT_NM_ACTIVE;
     153         383 :                 DEBUG(3,("Registered %s with %s on interface %s\n",
     154             :                          nbt_name_string(state, &iname->name),
     155             :                          iname->iface->ip_address, iname->iface->bcast_address));
     156         383 :                 iname->registration_time = timeval_current();
     157         383 :                 talloc_free(state);
     158         383 :                 nbtd_start_refresh_timer(iname);
     159         383 :                 return;
     160             :         }
     161             : 
     162             :         /* someone must have replied with an objection! */
     163           6 :         iname->nb_flags |= NBT_NM_CONFLICT;
     164             : 
     165           6 :         DEBUG(1,("Error registering %s with %s on interface %s - %s\n",
     166             :                  nbt_name_string(state, &iname->name),
     167             :                  iname->iface->ip_address, iname->iface->bcast_address,
     168             :                  nt_errstr(status)));
     169           6 :         talloc_free(state);
     170             : }
     171             : 
     172             : 
     173             : /*
     174             :   register a name on a network interface
     175             : */
     176        1752 : static void nbtd_register_name_iface(struct nbtd_interface *iface,
     177             :                                      const char *name, enum nbt_name_type type,
     178             :                                      uint16_t nb_flags)
     179             : {
     180          54 :         struct nbtd_iface_name *iname;
     181        1752 :         const char *scope = lpcfg_netbios_scope(iface->nbtsrv->task->lp_ctx);
     182          54 :         struct nbtd_register_name_state *state;
     183          54 :         struct tevent_req *subreq;
     184        1752 :         struct nbtd_server *nbtsrv = iface->nbtsrv;
     185             : 
     186        1752 :         iname = talloc(iface, struct nbtd_iface_name);
     187        1752 :         if (!iname) return;
     188             : 
     189        1752 :         iname->iface     = iface;
     190        1752 :         iname->name.name = strupper_talloc(iname, name);
     191        1752 :         iname->name.type = type;
     192        1752 :         if (scope && *scope) {
     193           0 :                 iname->name.scope = strupper_talloc(iname, scope);
     194             :         } else {
     195        1752 :                 iname->name.scope = NULL;
     196             :         }
     197        1752 :         iname->nb_flags          = nb_flags;
     198        1752 :         iname->ttl               = lpcfg_parm_int(iface->nbtsrv->task->lp_ctx, NULL, "nbtd", "bcast_ttl", 300000);
     199        1752 :         iname->registration_time = timeval_zero();
     200        1752 :         iname->wins_server       = NULL;
     201             : 
     202        1752 :         DLIST_ADD_END(iface->names, iname);
     203             : 
     204        1752 :         if (nb_flags & NBT_NM_PERMANENT) {
     205             :                 /* permanent names are not announced and are immediately active */
     206         974 :                 iname->nb_flags |= NBT_NM_ACTIVE;
     207         974 :                 iname->ttl       = 0;
     208         974 :                 return;
     209             :         }
     210             : 
     211             :         /* if this is the wins interface, then we need to do a special
     212             :            wins name registration */
     213         778 :         if (iface == iface->nbtsrv->wins_interface) {
     214         389 :                 nbtd_winsclient_register(iname);
     215         389 :                 return;
     216             :         }
     217             : 
     218         389 :         state = talloc_zero(iname, struct nbtd_register_name_state);
     219         389 :         if (state == NULL) {
     220           0 :                 return;
     221             :         }
     222             : 
     223         389 :         state->iname = iname;
     224             : 
     225             :         /* setup a broadcast name registration request */
     226         389 :         state->io.in.name      = iname->name;
     227         389 :         state->io.in.dest_addr = iface->bcast_address;
     228         389 :         state->io.in.dest_port = lpcfg_nbt_port(iface->nbtsrv->task->lp_ctx);
     229         389 :         state->io.in.address   = iface->ip_address;
     230         389 :         state->io.in.nb_flags  = nb_flags;
     231         389 :         state->io.in.ttl       = iname->ttl;
     232             : 
     233         389 :         nbtsrv->stats.total_sent++;
     234             : 
     235         389 :         subreq = nbt_name_register_bcast_send(state, nbtsrv->task->event_ctx,
     236             :                                               iface->nbtsock, &state->io);
     237         389 :         if (subreq == NULL) {
     238           0 :                 return;
     239             :         }
     240             : 
     241         389 :         tevent_req_set_callback(subreq, nbtd_register_name_handler, state);
     242             : }
     243             : 
     244             : 
     245             : /*
     246             :   register one name on all our interfaces
     247             : */
     248         584 : void nbtd_register_name(struct nbtd_server *nbtsrv, 
     249             :                         const char *name, enum nbt_name_type type,
     250             :                         uint16_t nb_flags)
     251             : {
     252          18 :         struct nbtd_interface *iface;
     253             :         
     254             :         /* register with all the local interfaces */
     255        1168 :         for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
     256         584 :                 nbtd_register_name_iface(iface, name, type, nb_flags);
     257             :         }
     258             : 
     259             :         /* register on our general broadcast interface as a permanent name */
     260         584 :         if (nbtsrv->bcast_interface) {
     261         584 :                 nbtd_register_name_iface(nbtsrv->bcast_interface, name, type, 
     262             :                                          nb_flags | NBT_NM_PERMANENT);
     263             :         }
     264             : 
     265             :         /* register with our WINS servers */
     266         584 :         if (nbtsrv->wins_interface) {
     267         584 :                 nbtd_register_name_iface(nbtsrv->wins_interface, name, type, nb_flags);
     268             :         }
     269         584 : }
     270             : 
     271             : 
     272             : /*
     273             :   register our names on all interfaces
     274             : */
     275          65 : void nbtd_register_names(struct nbtd_server *nbtsrv)
     276             : {
     277          65 :         uint16_t nb_flags = NBT_NODE_M;
     278           2 :         const char **aliases;
     279             : 
     280             :         /* note that we don't initially mark the names "ACTIVE". They are 
     281             :            marked active once registration is successful */
     282          65 :         nbtd_register_name(nbtsrv, lpcfg_netbios_name(nbtsrv->task->lp_ctx), NBT_NAME_CLIENT, nb_flags);
     283          65 :         nbtd_register_name(nbtsrv, lpcfg_netbios_name(nbtsrv->task->lp_ctx), NBT_NAME_USER,   nb_flags);
     284          65 :         nbtd_register_name(nbtsrv, lpcfg_netbios_name(nbtsrv->task->lp_ctx), NBT_NAME_SERVER, nb_flags);
     285             : 
     286          65 :         aliases = lpcfg_netbios_aliases(nbtsrv->task->lp_ctx);
     287          74 :         while (aliases && aliases[0]) {
     288           9 :                 nbtd_register_name(nbtsrv, aliases[0], NBT_NAME_CLIENT, nb_flags);
     289           9 :                 nbtd_register_name(nbtsrv, aliases[0], NBT_NAME_SERVER, nb_flags);
     290           9 :                 aliases++;
     291             :         }
     292             : 
     293          65 :         if (lpcfg_server_role(nbtsrv->task->lp_ctx) == ROLE_ACTIVE_DIRECTORY_DC)  {
     294          59 :                 bool is_pdc = samdb_is_pdc(nbtsrv->sam_ctx);
     295          59 :                 if (is_pdc) {
     296          52 :                         nbtd_register_name(nbtsrv, lpcfg_workgroup(nbtsrv->task->lp_ctx),
     297             :                                            NBT_NAME_PDC, nb_flags);
     298             :                 }
     299          59 :                 nbtd_register_name(nbtsrv, lpcfg_workgroup(nbtsrv->task->lp_ctx),
     300             :                                    NBT_NAME_LOGON, nb_flags | NBT_NM_GROUP);
     301             :         }
     302             : 
     303          65 :         nb_flags |= NBT_NM_GROUP;
     304          65 :         nbtd_register_name(nbtsrv, lpcfg_workgroup(nbtsrv->task->lp_ctx), NBT_NAME_CLIENT, nb_flags);
     305             : 
     306          65 :         nb_flags |= NBT_NM_PERMANENT;
     307          65 :         nbtd_register_name(nbtsrv, "__SAMBA__",       NBT_NAME_CLIENT, nb_flags);
     308          65 :         nbtd_register_name(nbtsrv, "__SAMBA__",       NBT_NAME_SERVER, nb_flags);
     309          65 :         nbtd_register_name(nbtsrv, "*",               NBT_NAME_CLIENT, nb_flags);
     310          65 : }

Generated by: LCOV version 1.14