LCOV - code coverage report
Current view: top level - source3/nmbd - nmbd_sendannounce.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 127 224 56.7 %
Date: 2024-02-28 12:06:22 Functions: 13 16 81.2 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    NBT netbios routines and daemon - version 2
       4             :    Copyright (C) Andrew Tridgell 1994-1998
       5             :    Copyright (C) Luke Kenneth Casson Leighton 1994-1998
       6             :    Copyright (C) Jeremy Allison 1994-1998
       7             : 
       8             :    SMB Version handling
       9             :    Copyright (C) John H Terpstra 1995-1998
      10             :    
      11             :    This program is free software; you can redistribute it and/or modify
      12             :    it under the terms of the GNU General Public License as published by
      13             :    the Free Software Foundation; either version 3 of the License, or
      14             :    (at your option) any later version.
      15             :    
      16             :    This program is distributed in the hope that it will be useful,
      17             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19             :    GNU General Public License for more details.
      20             :    
      21             :    You should have received a copy of the GNU General Public License
      22             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      23             :    
      24             : */
      25             : 
      26             : #include "includes.h"
      27             : #include "../librpc/gen_ndr/svcctl.h"
      28             : #include "nmbd/nmbd.h"
      29             : #include "lib/util/string_wrappers.h"
      30             : 
      31             : extern int  updatecount;
      32             : extern bool found_lm_clients;
      33             : 
      34             : /****************************************************************************
      35             :  Send a browser reset packet.
      36             : **************************************************************************/
      37             : 
      38           0 : void send_browser_reset(int reset_type, const char *to_name, int to_type, struct in_addr to_ip)
      39             : {
      40             :         char outbuf[1024];
      41             :         char *p;
      42             : 
      43           0 :         DBG_NOTICE("send_browser_reset: sending reset request type %d to %s<%02x> IP %s.\n",
      44             :                 reset_type, to_name, to_type, inet_ntoa(to_ip) );
      45             : 
      46           0 :         memset(outbuf,'\0',sizeof(outbuf));
      47           0 :         p = outbuf;
      48           0 :         SCVAL(p,0,ANN_ResetBrowserState);
      49           0 :         p++;
      50           0 :         SCVAL(p,0,reset_type);
      51           0 :         p++;
      52             : 
      53           0 :         send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
      54             :                 lp_netbios_name(), 0x0, to_name, to_type, to_ip,
      55           0 :                 FIRST_SUBNET->myip, DGRAM_PORT);
      56           0 : }
      57             : 
      58             : /****************************************************************************
      59             :   Broadcast a packet to the local net requesting that all servers in this
      60             :   workgroup announce themselves to us.
      61             :   **************************************************************************/
      62             : 
      63          30 : void broadcast_announce_request(struct subnet_record *subrec, struct work_record *work)
      64             : {
      65             :         char outbuf[1024];
      66             :         char *p;
      67             : 
      68          30 :         work->needannounce = True;
      69             : 
      70          30 :         DBG_NOTICE("broadcast_announce_request: sending announce request for workgroup %s \
      71             : to subnet %s\n", work->work_group, subrec->subnet_name);
      72             : 
      73          30 :         memset(outbuf,'\0',sizeof(outbuf));
      74          30 :         p = outbuf;
      75          30 :         SCVAL(p,0,ANN_AnnouncementRequest);
      76          30 :         p++;
      77             : 
      78          30 :         SCVAL(p,0,work->token); /* (local) Unique workgroup token id. */
      79          30 :         p++;
      80          30 :         p +=  push_string_check(p+1, lp_netbios_name(), 15, STR_ASCII|STR_UPPER|STR_TERMINATE);
      81             :   
      82          30 :         send_mailslot(False, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
      83          30 :                 lp_netbios_name(), 0x0, work->work_group,0x1e, subrec->bcast_ip,
      84             :                 subrec->myip, DGRAM_PORT);
      85          30 : }
      86             : 
      87             : /****************************************************************************
      88             :   Broadcast an announcement.
      89             :   **************************************************************************/
      90             : 
      91         416 : static void send_announcement(struct subnet_record *subrec, int announce_type,
      92             :                               const char *from_name, const char *to_name, int to_type, struct in_addr to_ip,
      93             :                               time_t announce_interval,
      94             :                               const char *server_name, int server_type, const char *server_comment)
      95             : {
      96             :         char outbuf[1024];
      97             :         unstring upper_server_name;
      98             :         char *p;
      99             : 
     100         416 :         memset(outbuf,'\0',sizeof(outbuf));
     101         416 :         p = outbuf+1;
     102             : 
     103         416 :         SCVAL(outbuf,0,announce_type);
     104             : 
     105             :         /* Announcement parameters. */
     106         416 :         SCVAL(p,0,updatecount);
     107         416 :         SIVAL(p,1,announce_interval*1000); /* Milliseconds - despite the spec. */
     108             : 
     109         416 :         strlcpy(upper_server_name, server_name ? server_name : "", sizeof(upper_server_name));
     110         416 :         if (!strupper_m(upper_server_name)) {
     111           0 :                 DBG_WARNING("strupper_m %s failed\n", upper_server_name);
     112           0 :                 return;
     113             :         }
     114         416 :         push_string_check(p+5, upper_server_name, 16, STR_ASCII|STR_TERMINATE);
     115             : 
     116         416 :         SCVAL(p,21,SAMBA_MAJOR_NBT_ANNOUNCE_VERSION); /* Major version. */
     117         416 :         SCVAL(p,22,SAMBA_MINOR_NBT_ANNOUNCE_VERSION); /* Minor version. */
     118             : 
     119         416 :         SIVAL(p,23,server_type & ~SV_TYPE_LOCAL_LIST_ONLY);
     120             :         /* Browse version: got from NT/AS 4.00  - Value defined in smb.h (JHT). */
     121         416 :         SSVAL(p,27,BROWSER_ELECTION_VERSION);
     122         416 :         SSVAL(p,29,BROWSER_CONSTANT); /* Browse signature. */
     123             : 
     124         416 :         p += 31 + push_string_check(p+31, server_comment, sizeof(outbuf) - (p + 31 - outbuf), STR_ASCII|STR_TERMINATE);
     125             : 
     126         416 :         send_mailslot(False,BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
     127             :                         from_name, 0x0, to_name, to_type, to_ip, subrec->myip,
     128             :                         DGRAM_PORT);
     129             : }
     130             : 
     131             : /****************************************************************************
     132             :   Broadcast a LanMan announcement.
     133             : **************************************************************************/
     134             : 
     135           0 : static void send_lm_announcement(struct subnet_record *subrec, int announce_type,
     136             :                               char *from_name, char *to_name, int to_type, struct in_addr to_ip,
     137             :                               time_t announce_interval,
     138             :                               char *server_name, int server_type, char *server_comment)
     139             : {
     140             :         char outbuf[1024];
     141           0 :         char *p=outbuf;
     142             : 
     143           0 :         memset(outbuf,'\0',sizeof(outbuf));
     144             : 
     145           0 :         SSVAL(p,0,announce_type);
     146           0 :         SIVAL(p,2,server_type & ~SV_TYPE_LOCAL_LIST_ONLY);
     147           0 :         SCVAL(p,6,SAMBA_MAJOR_NBT_ANNOUNCE_VERSION); /* Major version. */
     148           0 :         SCVAL(p,7,SAMBA_MINOR_NBT_ANNOUNCE_VERSION); /* Minor version. */
     149           0 :         SSVAL(p,8,announce_interval);            /* In seconds - according to spec. */
     150             : 
     151           0 :         p += 10;
     152           0 :         p += push_string_check(p, server_name, 15, STR_ASCII|STR_UPPER|STR_TERMINATE);
     153           0 :         p += push_string_check(p, server_comment, sizeof(outbuf)- (p - outbuf), STR_ASCII|STR_UPPER|STR_TERMINATE);
     154             : 
     155           0 :         send_mailslot(False,LANMAN_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
     156             :                 from_name, 0x0, to_name, to_type, to_ip, subrec->myip,
     157             :                 DGRAM_PORT);
     158           0 : }
     159             : 
     160             : /****************************************************************************
     161             :  We are a local master browser. Announce this to WORKGROUP<1e>.
     162             : ****************************************************************************/
     163             : 
     164         149 : static void send_local_master_announcement(struct subnet_record *subrec, struct work_record *work,
     165             :                                            struct server_record *servrec)
     166             : {
     167             :         /* Ensure we don't have the prohibited bit set. */
     168         149 :         uint32_t type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY;
     169             : 
     170         149 :         DBG_NOTICE("send_local_master_announcement: type %x for name %s on subnet %s for workgroup %s\n",
     171             :                 type, lp_netbios_name(), subrec->subnet_name, work->work_group);
     172             : 
     173         149 :         send_announcement(subrec, ANN_LocalMasterAnnouncement,
     174             :                         lp_netbios_name(),                 /* From nbt name. */
     175         149 :                         work->work_group, 0x1e,          /* To nbt name. */
     176             :                         subrec->bcast_ip,                /* To ip. */
     177         149 :                         work->announce_interval,         /* Time until next announce. */
     178             :                         lp_netbios_name(),                 /* Name to announce. */
     179             :                         type,                            /* Type field. */
     180         149 :                         servrec->serv.comment);
     181         149 : }
     182             : 
     183             : /****************************************************************************
     184             :  Announce the workgroup WORKGROUP to MSBROWSE<01>.
     185             : ****************************************************************************/
     186             : 
     187         117 : static void send_workgroup_announcement(struct subnet_record *subrec, struct work_record *work)
     188             : {
     189         117 :         DBG_NOTICE("send_workgroup_announcement: on subnet %s for workgroup %s\n",
     190             :                 subrec->subnet_name, work->work_group);
     191             : 
     192         234 :         send_announcement(subrec, ANN_DomainAnnouncement,
     193             :                         lp_netbios_name(),                 /* From nbt name. */
     194             :                         MSBROWSE, 0x1,                   /* To nbt name. */
     195             :                         subrec->bcast_ip,                /* To ip. */
     196         117 :                         work->announce_interval,         /* Time until next announce. */
     197         117 :                         work->work_group,                /* Name to announce. */
     198             :                         SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT,  /* workgroup announce flags. */
     199             :                         lp_netbios_name());                /* From name as comment. */
     200         117 : }
     201             : 
     202             : /****************************************************************************
     203             :  Announce the given host to WORKGROUP<1d>.
     204             : ****************************************************************************/
     205             : 
     206         150 : static void send_host_announcement(struct subnet_record *subrec, struct work_record *work,
     207             :                                    struct server_record *servrec)
     208             : {
     209             :         /* Ensure we don't have the prohibited bits set. */
     210         150 :         uint32_t type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY;
     211             : 
     212         150 :         DBG_NOTICE("send_host_announcement: type %x for host %s on subnet %s for workgroup %s\n",
     213             :                 type, servrec->serv.name, subrec->subnet_name, work->work_group);
     214             : 
     215         150 :         send_announcement(subrec, ANN_HostAnnouncement,
     216         150 :                         servrec->serv.name,              /* From nbt name. */
     217         150 :                         work->work_group, 0x1d,          /* To nbt name. */
     218             :                         subrec->bcast_ip,                /* To ip. */
     219         150 :                         work->announce_interval,         /* Time until next announce. */
     220         150 :                         servrec->serv.name,              /* Name to announce. */
     221             :                         type,                            /* Type field. */
     222         150 :                         servrec->serv.comment);
     223         150 : }
     224             : 
     225             : /****************************************************************************
     226             :  Announce the given LanMan host
     227             : ****************************************************************************/
     228             : 
     229           0 : static void send_lm_host_announcement(struct subnet_record *subrec, struct work_record *work,
     230             :                                    struct server_record *servrec, int lm_interval)
     231             : {
     232             :         /* Ensure we don't have the prohibited bits set. */
     233           0 :         uint32_t type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY;
     234             : 
     235           0 :         DBG_NOTICE("send_lm_host_announcement: type %x for host %s on subnet %s for workgroup %s, ttl: %d\n",
     236             :                 type, servrec->serv.name, subrec->subnet_name, work->work_group, lm_interval);
     237             : 
     238           0 :         send_lm_announcement(subrec, ANN_HostAnnouncement,
     239           0 :                         servrec->serv.name,              /* From nbt name. */
     240           0 :                         work->work_group, 0x00,          /* To nbt name. */
     241             :                         subrec->bcast_ip,                /* To ip. */
     242             :                         lm_interval,                     /* Time until next announce. */
     243           0 :                         servrec->serv.name,              /* Name to announce (fstring not netbios name struct). */
     244             :                         type,                            /* Type field. */
     245           0 :                         servrec->serv.comment);
     246           0 : }
     247             : 
     248             : /****************************************************************************
     249             :   Announce a server record.
     250             :   ****************************************************************************/
     251             : 
     252         219 : static void announce_server(struct subnet_record *subrec, struct work_record *work,
     253             :                      struct server_record *servrec)
     254             : {
     255             :         /* Only do domain announcements if we are a master and it's
     256             :                 our primary name we're being asked to announce. */
     257             : 
     258         219 :         if (AM_LOCAL_MASTER_BROWSER(work) && strequal(lp_netbios_name(),servrec->serv.name)) {
     259         117 :                 send_local_master_announcement(subrec, work, servrec);
     260         117 :                 send_workgroup_announcement(subrec, work);
     261             :         } else {
     262         102 :                 send_host_announcement(subrec, work, servrec);
     263             :         }
     264         219 : }
     265             : 
     266             : /****************************************************************************
     267             :   Go through all my registered names on all broadcast subnets and announce
     268             :   them if the timeout requires it.
     269             :   **************************************************************************/
     270             : 
     271       17496 : void announce_my_server_names(time_t t)
     272             : {
     273             :         struct subnet_record *subrec;
     274             : 
     275       34992 :         for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
     276       17496 :                 struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup());
     277             : 
     278       17496 :                 if(work) {
     279             :                         struct server_record *servrec;
     280             : 
     281       17496 :                         if (work->needannounce) {
     282             :                                 /* Drop back to a max 3 minute announce. This is to prevent a
     283             :                                         single lost packet from breaking things for too long. */
     284             : 
     285          81 :                                 work->announce_interval = MIN(work->announce_interval,
     286             :                                                         CHECK_TIME_MIN_HOST_ANNCE*60);
     287          81 :                                 work->lastannounce_time = t - (work->announce_interval+1);
     288          81 :                                 work->needannounce = False;
     289             :                         }
     290             : 
     291             :                         /* Announce every minute at first then progress to every 12 mins */
     292       17496 :                         if (t >= work->lastannounce_time &&
     293       17496 :                             (t - work->lastannounce_time) < work->announce_interval) {
     294       17293 :                                 continue;
     295             :                         }
     296             : 
     297         203 :                         if (work->announce_interval < (CHECK_TIME_MAX_HOST_ANNCE * 60))
     298         203 :                                 work->announce_interval += 60;
     299             : 
     300         203 :                         work->lastannounce_time = t;
     301             : 
     302         494 :                         for (servrec = work->serverlist; servrec; servrec = servrec->next) {
     303         291 :                                 if (is_myname(servrec->serv.name))
     304         219 :                                         announce_server(subrec, work, servrec);
     305             :                         }
     306             :                 } /* if work */
     307             :         } /* for subrec */
     308       17496 : }
     309             : 
     310             : /****************************************************************************
     311             :   Go through all my registered names on all broadcast subnets and announce
     312             :   them as a LanMan server if the timeout requires it.
     313             : **************************************************************************/
     314             : 
     315       17496 : void announce_my_lm_server_names(time_t t)
     316             : {
     317             :         struct subnet_record *subrec;
     318             :         static time_t last_lm_announce_time=0;
     319       17496 :         int announce_interval = lp_lm_interval();
     320       17496 :         int lm_announce = lp_lm_announce();
     321             : 
     322       17496 :         if ((announce_interval <= 0) || (lm_announce <= 0)) {
     323             :                 /* user absolutely does not want LM announcements to be sent. */
     324           0 :                 return;
     325             :         }
     326             : 
     327       17496 :         if ((lm_announce >= 2) && (!found_lm_clients)) {
     328             :                 /* has been set to 2 (Auto) but no LM clients detected (yet). */
     329       17496 :                 return;
     330             :         }
     331             : 
     332             :         /* Otherwise: must have been set to 1 (Yes), or LM clients *have*
     333             :                 been detected. */
     334             : 
     335           0 :         for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
     336           0 :                 struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup());
     337             : 
     338           0 :                 if(work) {
     339             :                         struct server_record *servrec;
     340             : 
     341           0 :                         if (last_lm_announce_time && ((t - last_lm_announce_time) < announce_interval ))
     342           0 :                                 continue;
     343             : 
     344           0 :                         last_lm_announce_time = t;
     345             : 
     346           0 :                         for (servrec = work->serverlist; servrec; servrec = servrec->next) {
     347           0 :                                 if (is_myname(servrec->serv.name))
     348             :                                         /* skipping equivalent of announce_server() */
     349           0 :                                         send_lm_host_announcement(subrec, work, servrec, announce_interval);
     350             :                         }
     351             :                 } /* if work */
     352             :         } /* for subrec */
     353             : }
     354             : 
     355             : /* Announce timer. Moved into global static so it can be reset
     356             :    when a machine becomes a local master browser. */
     357             : static time_t announce_timer_last=0;
     358             : 
     359             : /****************************************************************************
     360             :  Reset the announce_timer so that a local master browser announce will be done
     361             :  immediately.
     362             :  ****************************************************************************/
     363             : 
     364          30 : void reset_announce_timer(void)
     365             : {
     366          30 :         announce_timer_last = time(NULL) - (CHECK_TIME_MST_ANNOUNCE * 60);
     367          30 : }
     368             : 
     369             : /****************************************************************************
     370             :   Announce myself as a local master browser to a domain master browser.
     371             :   **************************************************************************/
     372             : 
     373       17496 : void announce_myself_to_domain_master_browser(time_t t)
     374             : {
     375             :         struct subnet_record *subrec;
     376             :         struct work_record *work;
     377             : 
     378       17496 :         if(!we_are_a_wins_client()) {
     379       17496 :                 DBG_DEBUG("announce_myself_to_domain_master_browser: no unicast subnet, ignoring.\n");
     380       17496 :                 return;
     381             :         }
     382             : 
     383           0 :         if (!announce_timer_last)
     384           0 :                 announce_timer_last = t;
     385             : 
     386           0 :         if ((t-announce_timer_last) < (CHECK_TIME_MST_ANNOUNCE * 60)) {
     387           0 :                 DBG_DEBUG("announce_myself_to_domain_master_browser: t (%d) - last(%d) < %d\n",
     388             :                         (int)t, (int)announce_timer_last, 
     389             :                         CHECK_TIME_MST_ANNOUNCE * 60 );
     390           0 :                 return;
     391             :         }
     392             : 
     393           0 :         announce_timer_last = t;
     394             : 
     395             :         /* Look over all our broadcast subnets to see if any of them
     396             :                 has the state set as local master browser. */
     397             : 
     398           0 :         for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
     399           0 :                 for (work = subrec->workgrouplist; work; work = work->next) {
     400           0 :                         if (AM_LOCAL_MASTER_BROWSER(work)) {
     401           0 :                                 DBG_NOTICE( "announce_myself_to_domain_master_browser: I am a local master browser for \
     402             : workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name);
     403             : 
     404             :                                 /* Look in nmbd_browsersync.c for the rest of this code. */
     405           0 :                                 announce_and_sync_with_domain_master_browser(subrec, work);
     406             :                         }
     407             :                 }
     408             :         }
     409             : }
     410             : 
     411             : /****************************************************************************
     412             : Announce all samba's server entries as 'gone'.
     413             : This must *only* be called on shutdown.
     414             : ****************************************************************************/
     415             : 
     416          44 : void announce_my_servers_removed(void)
     417             : {
     418          44 :         int announce_interval = lp_lm_interval();
     419          44 :         int lm_announce = lp_lm_announce();
     420             :         struct subnet_record *subrec; 
     421             : 
     422          88 :         for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
     423             :                 struct work_record *work;
     424         139 :                 for (work = subrec->workgrouplist; work; work = work->next) {
     425             :                         struct server_record *servrec;
     426             : 
     427          95 :                         work->announce_interval = 0;
     428         159 :                         for (servrec = work->serverlist; servrec; servrec = servrec->next) {
     429          64 :                                 if (!is_myname(servrec->serv.name))
     430          16 :                                         continue;
     431          48 :                                 servrec->serv.type = 0;
     432          48 :                                 if(AM_LOCAL_MASTER_BROWSER(work))
     433          32 :                                         send_local_master_announcement(subrec, work, servrec);
     434          48 :                                 send_host_announcement(subrec, work, servrec);
     435             : 
     436          48 :                                 if ((announce_interval <= 0) || (lm_announce <= 0)) {
     437             :                                         /* user absolutely does not want LM announcements to be sent. */
     438           0 :                                         continue;
     439             :                                 }
     440             : 
     441          48 :                                 if ((lm_announce >= 2) && (!found_lm_clients)) {
     442             :                                         /* has been set to 2 (Auto) but no LM clients detected (yet). */
     443          48 :                                         continue;
     444             :                                 }
     445             : 
     446             :                                 /* 
     447             :                                  * lm announce was set or we have seen lm announcements, so do
     448             :                                  * a lm announcement of host removed.
     449             :                                  */
     450             : 
     451           0 :                                 send_lm_host_announcement(subrec, work, servrec, 0);
     452             :                         }
     453             :                 }
     454             :         }
     455          44 : }
     456             : 
     457             : /****************************************************************************
     458             :   Do all the "remote" announcements. These are used to put ourselves
     459             :   on a remote browse list. They are done blind, no checking is done to
     460             :   see if there is actually a local master browser at the other end.
     461             :   **************************************************************************/
     462             : 
     463       17496 : void announce_remote(time_t t)
     464             : {
     465       17496 :         char *s = NULL;
     466             :         const char *ptr;
     467             :         static time_t last_time = 0;
     468             :         char *s2;
     469             :         struct in_addr addr;
     470             :         char *comment;
     471       17496 :         int stype = lp_default_server_announce();
     472       17496 :         TALLOC_CTX *frame = NULL;
     473             :         const struct loadparm_substitution *lp_sub =
     474       17496 :                 loadparm_s3_global_substitution();
     475             : 
     476       17496 :         if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL)))
     477       17496 :                 return;
     478             : 
     479         212 :         last_time = t;
     480             : 
     481         212 :         s = lp_remote_announce(talloc_tos(), lp_sub);
     482         212 :         if (!*s)
     483         212 :                 return;
     484             : 
     485           0 :         comment = string_truncate(lp_server_string(talloc_tos(), lp_sub),
     486             :                                   MAX_SERVER_STRING_LENGTH);
     487             : 
     488           0 :         frame = talloc_stackframe();
     489           0 :         for (ptr=s; next_token_talloc(frame,&ptr,&s2,NULL); ) {
     490             :                 /* The entries are of the form a.b.c.d/WORKGROUP with
     491             :                                 WORKGROUP being optional */
     492             :                 const char *wgroup;
     493             :                 char *pwgroup;
     494             :                 int i;
     495             : 
     496           0 :                 pwgroup = strchr_m(s2,'/');
     497           0 :                 if (pwgroup)
     498           0 :                         *pwgroup++ = 0;
     499           0 :                 if (!pwgroup || !*pwgroup)
     500           0 :                         wgroup = lp_workgroup();
     501             :                 else
     502           0 :                         wgroup = pwgroup;
     503             : 
     504           0 :                 addr = interpret_addr2(s2);
     505             : 
     506             :                 /* Announce all our names including aliases */
     507             :                 /* Give the ip address as the address of our first
     508             :                                 broadcast subnet. */
     509             : 
     510           0 :                 for(i=0; my_netbios_names(i); i++) {
     511           0 :                         const char *name = my_netbios_names(i);
     512             : 
     513           0 :                         DBG_INFO("announce_remote: Doing remote announce for server %s to IP %s.\n",
     514             :                                 name, inet_ntoa(addr) );
     515             : 
     516           0 :                         send_announcement(FIRST_SUBNET, ANN_HostAnnouncement,
     517             :                                                 name,                      /* From nbt name. */
     518             :                                                 wgroup, 0x1d,              /* To nbt name. */
     519             :                                                 addr,                      /* To ip. */
     520             :                                                 REMOTE_ANNOUNCE_INTERVAL,  /* Time until next announce. */
     521             :                                                 name,                      /* Name to announce. */
     522             :                                                 stype,                     /* Type field. */
     523             :                                                 comment);
     524             :                 }
     525             :         }
     526           0 :         TALLOC_FREE(frame);
     527             : }
     528             : 
     529             : /****************************************************************************
     530             :   Implement the 'remote browse sync' feature Andrew added.
     531             :   These are used to put our browse lists into remote browse lists.
     532             : **************************************************************************/
     533             : 
     534       17496 : void browse_sync_remote(time_t t)
     535             : {
     536             :         char *s;
     537             :         const char *ptr;
     538             :         static time_t last_time = 0;
     539             :         char *s2;
     540             :         struct in_addr addr;
     541             :         struct work_record *work;
     542             :         char outbuf[1024];
     543             :         char *p;
     544             :         unstring myname;
     545       17496 :         TALLOC_CTX *frame = NULL;
     546             :         const struct loadparm_substitution *lp_sub =
     547       17496 :                 loadparm_s3_global_substitution();
     548             : 
     549       17496 :         if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL)))
     550       17496 :                 return;
     551             : 
     552         212 :         last_time = t;
     553             : 
     554         212 :         s = lp_remote_browse_sync(talloc_tos(), lp_sub);
     555         212 :         if (!*s)
     556         212 :                 return;
     557             : 
     558             :         /*
     559             :          * We only do this if we are the local master browser
     560             :          * for our workgroup on the firsst subnet.
     561             :          */
     562             : 
     563           0 :         if((work = find_workgroup_on_subnet(FIRST_SUBNET, lp_workgroup())) == NULL) {   
     564           0 :                 DBG_WARNING("browse_sync_remote: Cannot find workgroup %s on subnet %s\n",
     565             :                         lp_workgroup(), FIRST_SUBNET->subnet_name );
     566           0 :                 return;
     567             :         }
     568             : 
     569           0 :         if(!AM_LOCAL_MASTER_BROWSER(work)) {
     570           0 :                 DBG_NOTICE("browse_sync_remote: We can only do this if we are a local master browser \
     571             : for workgroup %s on subnet %s.\n", lp_workgroup(), FIRST_SUBNET->subnet_name );
     572           0 :                 return;
     573             :         }
     574             : 
     575           0 :         memset(outbuf,'\0',sizeof(outbuf));
     576           0 :         p = outbuf;
     577           0 :         SCVAL(p,0,ANN_MasterAnnouncement);
     578           0 :         p++;
     579             : 
     580           0 :         unstrcpy(myname, lp_netbios_name());
     581           0 :         if (!strupper_m(myname)) {
     582           0 :                 DBG_WARNING("strupper_m %s failed\n", myname);
     583           0 :                 return;
     584             :         }
     585           0 :         myname[15]='\0';
     586           0 :         push_ascii(p, myname, sizeof(outbuf)-PTR_DIFF(p,outbuf)-1, STR_TERMINATE);
     587             : 
     588           0 :         p = skip_string(outbuf,sizeof(outbuf),p);
     589             : 
     590           0 :         frame = talloc_stackframe();
     591           0 :         for (ptr=s; next_token_talloc(frame,&ptr,&s2,NULL); ) {
     592             :                 /* The entries are of the form a.b.c.d */
     593           0 :                 addr = interpret_addr2(s2);
     594             : 
     595           0 :                 DBG_INFO("announce_remote: Doing remote browse sync announce for server %s to IP %s.\n",
     596             :                         lp_netbios_name(), inet_ntoa(addr) );
     597             : 
     598           0 :                 send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
     599           0 :                         lp_netbios_name(), 0x0, "*", 0x0, addr, FIRST_SUBNET->myip, DGRAM_PORT);
     600             :         }
     601           0 :         TALLOC_FREE(frame);
     602             : }

Generated by: LCOV version 1.14