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