LCOV - code coverage report
Current view: top level - source4/nbt_server/wins - winsclient.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 33 120 27.5 %
Date: 2024-04-13 12:30:31 Functions: 3 7 42.9 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    wins client name registration and refresh
       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 "nbt_server/nbt_server.h"
      24             : #include "nbt_server/wins/winsserver.h"
      25             : #include "libcli/composite/composite.h"
      26             : #include "lib/events/events.h"
      27             : #include "librpc/gen_ndr/ndr_nbt.h"
      28             : #include "samba/service_task.h"
      29             : #include "param/param.h"
      30             : 
      31             : /* we send WINS client requests using our primary network interface 
      32             : */
      33         389 : static struct nbt_name_socket *wins_socket(struct nbtd_interface *iface)
      34             : {
      35         389 :         struct nbtd_server *nbtsrv = iface->nbtsrv;
      36         389 :         return nbtsrv->interfaces->nbtsock;
      37             : }
      38             : 
      39             : 
      40             : static void nbtd_wins_refresh(struct tevent_context *ev, struct tevent_timer *te,
      41             :                               struct timeval t, void *private_data);
      42             : 
      43             : /*
      44             :   retry a WINS name registration
      45             : */
      46           0 : static void nbtd_wins_register_retry(struct tevent_context *ev, struct tevent_timer *te,
      47             :                                      struct timeval t, void *private_data)
      48             : {
      49           0 :         struct nbtd_iface_name *iname = talloc_get_type(private_data, struct nbtd_iface_name);
      50           0 :         nbtd_winsclient_register(iname);
      51           0 : }
      52             : 
      53             : /*
      54             :   start a timer to refresh this name
      55             : */
      56           0 : static void nbtd_wins_start_refresh_timer(struct nbtd_iface_name *iname)
      57             : {
      58           0 :         uint32_t refresh_time;
      59           0 :         uint32_t max_refresh_time = lpcfg_parm_int(iname->iface->nbtsrv->task->lp_ctx, NULL, "nbtd", "max_refresh_time", 7200);
      60             : 
      61           0 :         refresh_time = MIN(max_refresh_time, iname->ttl/2);
      62             :         
      63           0 :         tevent_add_timer(iname->iface->nbtsrv->task->event_ctx,
      64             :                         iname, 
      65             :                         timeval_add(&iname->registration_time, refresh_time, 0),
      66             :                         nbtd_wins_refresh, iname);
      67           0 : }
      68             : 
      69             : struct nbtd_wins_refresh_state {
      70             :         struct nbtd_iface_name *iname;
      71             :         struct nbt_name_refresh_wins io;
      72             : };
      73             : 
      74             : /*
      75             :   called when a wins name refresh has completed
      76             : */
      77           0 : static void nbtd_wins_refresh_handler(struct tevent_req *subreq)
      78             : {
      79           0 :         NTSTATUS status;
      80           0 :         struct nbtd_wins_refresh_state *state =
      81           0 :                 tevent_req_callback_data(subreq,
      82             :                 struct nbtd_wins_refresh_state);
      83           0 :         struct nbtd_iface_name *iname = state->iname;
      84             : 
      85           0 :         status = nbt_name_refresh_wins_recv(subreq, state, &state->io);
      86           0 :         TALLOC_FREE(subreq);
      87           0 :         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
      88             :                 /* our WINS server is dead - start registration over
      89             :                    from scratch */
      90           0 :                 DEBUG(2,("Failed to refresh %s with WINS server %s\n",
      91             :                          nbt_name_string(state, &iname->name), iname->wins_server));
      92           0 :                 talloc_free(state);
      93           0 :                 nbtd_winsclient_register(iname);
      94           0 :                 return;
      95             :         }
      96             : 
      97           0 :         if (!NT_STATUS_IS_OK(status)) {
      98           0 :                 DEBUG(1,("Name refresh failure with WINS for %s - %s\n", 
      99             :                          nbt_name_string(state, &iname->name), nt_errstr(status)));
     100           0 :                 talloc_free(state);
     101           0 :                 return;
     102             :         }
     103             : 
     104           0 :         if (state->io.out.rcode != 0) {
     105           0 :                 DEBUG(1,("WINS server %s rejected name refresh of %s - %s\n", 
     106             :                          state->io.out.wins_server,
     107             :                          nbt_name_string(state, &iname->name),
     108             :                          nt_errstr(nbt_rcode_to_ntstatus(state->io.out.rcode))));
     109           0 :                 iname->nb_flags |= NBT_NM_CONFLICT;
     110           0 :                 talloc_free(state);
     111           0 :                 return;
     112             :         }       
     113             : 
     114           0 :         DEBUG(4,("Refreshed name %s with WINS server %s\n",
     115             :                  nbt_name_string(state, &iname->name), iname->wins_server));
     116             :         /* success - start a periodic name refresh */
     117           0 :         iname->nb_flags |= NBT_NM_ACTIVE;
     118           0 :         if (iname->wins_server) {
     119             :                 /*
     120             :                  * talloc_free() would generate a warning,
     121             :                  * so steal it into the tmp context
     122             :                  */
     123           0 :                 talloc_steal(state, iname->wins_server);
     124             :         }
     125           0 :         iname->wins_server = talloc_move(iname, &state->io.out.wins_server);
     126           0 :         iname->registration_time = timeval_current();
     127             : 
     128           0 :         talloc_free(state);
     129             : 
     130           0 :         nbtd_wins_start_refresh_timer(iname);
     131             : }
     132             : 
     133             : 
     134             : /*
     135             :   refresh a WINS name registration
     136             : */
     137           0 : static void nbtd_wins_refresh(struct tevent_context *ev, struct tevent_timer *te,
     138             :                               struct timeval t, void *private_data)
     139             : {
     140           0 :         struct nbtd_iface_name *iname = talloc_get_type(private_data, struct nbtd_iface_name);
     141           0 :         struct nbtd_interface *iface = iname->iface;
     142           0 :         struct nbt_name_socket *nbtsock = wins_socket(iface);
     143           0 :         struct tevent_req *subreq;
     144           0 :         struct nbtd_wins_refresh_state *state;
     145           0 :         char **l;
     146             : 
     147           0 :         state = talloc_zero(iname, struct nbtd_wins_refresh_state);
     148           0 :         if (state == NULL) {
     149           0 :                 return;
     150             :         }
     151             : 
     152           0 :         state->iname = iname;
     153             : 
     154             :         /* setup a wins name refresh request */
     155           0 :         state->io.in.name            = iname->name;
     156           0 :         l = str_list_make_single(state, iname->wins_server);
     157           0 :         state->io.in.wins_servers    = discard_const_p(const char *, l);
     158           0 :         state->io.in.wins_port       = lpcfg_nbt_port(iface->nbtsrv->task->lp_ctx);
     159           0 :         state->io.in.addresses       = nbtd_address_list(iface, state);
     160           0 :         state->io.in.nb_flags        = iname->nb_flags;
     161           0 :         state->io.in.ttl             = iname->ttl;
     162             : 
     163           0 :         if (!state->io.in.addresses) {
     164           0 :                 talloc_free(state);
     165           0 :                 return;
     166             :         }
     167             : 
     168           0 :         subreq = nbt_name_refresh_wins_send(state, ev, nbtsock, &state->io);
     169           0 :         if (subreq == NULL) {
     170           0 :                 talloc_free(state);
     171           0 :                 return;
     172             :         }
     173             : 
     174           0 :         tevent_req_set_callback(subreq, nbtd_wins_refresh_handler, state);
     175             : }
     176             : 
     177             : struct nbtd_wins_register_state {
     178             :         struct nbtd_iface_name *iname;
     179             :         struct nbt_name_register_wins io;
     180             : };
     181             : 
     182             : /*
     183             :   called when a wins name register has completed
     184             : */
     185         389 : static void nbtd_wins_register_handler(struct tevent_req *subreq)
     186             : {
     187          12 :         NTSTATUS status;
     188          12 :         struct nbtd_wins_register_state *state =
     189         389 :                 tevent_req_callback_data(subreq,
     190             :                 struct nbtd_wins_register_state);
     191         389 :         struct nbtd_iface_name *iname = state->iname;
     192             : 
     193         389 :         status = nbt_name_register_wins_recv(subreq, state, &state->io);
     194         389 :         TALLOC_FREE(subreq);
     195         389 :         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
     196             :                 /* none of the WINS servers responded - try again 
     197             :                    periodically */
     198           0 :                 int wins_retry_time = lpcfg_parm_int(iname->iface->nbtsrv->task->lp_ctx, NULL, "nbtd", "wins_retry", 300);
     199           0 :                 tevent_add_timer(iname->iface->nbtsrv->task->event_ctx,
     200             :                                 iname,
     201             :                                 timeval_current_ofs(wins_retry_time, 0),
     202             :                                 nbtd_wins_register_retry,
     203             :                                 iname);
     204           0 :                 talloc_free(state);
     205           0 :                 return;
     206             :         }
     207             : 
     208         389 :         if (!NT_STATUS_IS_OK(status)) {
     209         389 :                 DEBUG(1,("Name register failure with WINS for %s - %s\n", 
     210             :                          nbt_name_string(state, &iname->name), nt_errstr(status)));
     211         389 :                 talloc_free(state);
     212         389 :                 return;
     213             :         }       
     214             : 
     215           0 :         if (state->io.out.rcode != 0) {
     216           0 :                 DEBUG(1,("WINS server %s rejected name register of %s - %s\n", 
     217             :                          state->io.out.wins_server,
     218             :                          nbt_name_string(state, &iname->name),
     219             :                          nt_errstr(nbt_rcode_to_ntstatus(state->io.out.rcode))));
     220           0 :                 iname->nb_flags |= NBT_NM_CONFLICT;
     221           0 :                 talloc_free(state);
     222           0 :                 return;
     223             :         }       
     224             : 
     225             :         /* success - start a periodic name refresh */
     226           0 :         iname->nb_flags |= NBT_NM_ACTIVE;
     227           0 :         if (iname->wins_server) {
     228             :                 /*
     229             :                  * talloc_free() would generate a warning,
     230             :                  * so steal it into the tmp context
     231             :                  */
     232           0 :                 talloc_steal(state, iname->wins_server);
     233             :         }
     234           0 :         iname->wins_server = talloc_move(iname, &state->io.out.wins_server);
     235             : 
     236           0 :         iname->registration_time = timeval_current();
     237             : 
     238           0 :         DEBUG(3,("Registered %s with WINS server %s\n",
     239             :                  nbt_name_string(state, &iname->name), iname->wins_server));
     240             : 
     241           0 :         talloc_free(state);
     242             : 
     243           0 :         nbtd_wins_start_refresh_timer(iname);
     244             : }
     245             : 
     246             : /*
     247             :   register a name with our WINS servers
     248             : */
     249         389 : void nbtd_winsclient_register(struct nbtd_iface_name *iname)
     250             : {
     251         389 :         struct nbtd_interface *iface = iname->iface;
     252         389 :         struct nbt_name_socket *nbtsock = wins_socket(iface);
     253          12 :         struct nbtd_wins_register_state *state;
     254          12 :         struct tevent_req *subreq;
     255             : 
     256         389 :         state = talloc_zero(iname, struct nbtd_wins_register_state);
     257         389 :         if (state == NULL) {
     258           0 :                 return;
     259             :         }
     260             : 
     261         389 :         state->iname = iname;
     262             : 
     263             :         /* setup a wins name register request */
     264         389 :         state->io.in.name         = iname->name;
     265         389 :         state->io.in.wins_port    = lpcfg_nbt_port(iface->nbtsrv->task->lp_ctx);
     266         389 :         state->io.in.wins_servers = lpcfg_wins_server_list(iface->nbtsrv->task->lp_ctx);
     267         389 :         state->io.in.addresses    = nbtd_address_list(iface, state);
     268         389 :         state->io.in.nb_flags     = iname->nb_flags;
     269         389 :         state->io.in.ttl          = iname->ttl;
     270             : 
     271         389 :         if (state->io.in.addresses == NULL) {
     272           0 :                 talloc_free(state);
     273           0 :                 return;
     274             :         }
     275             : 
     276         389 :         subreq = nbt_name_register_wins_send(state, iface->nbtsrv->task->event_ctx,
     277             :                                              nbtsock, &state->io);
     278         389 :         if (subreq == NULL) {
     279           0 :                 talloc_free(state);
     280           0 :                 return;
     281             :         }
     282             : 
     283         389 :         tevent_req_set_callback(subreq, nbtd_wins_register_handler, state);
     284             : }

Generated by: LCOV version 1.14