source: trunk/samba/source/nmbd/nmbd_incomingdgrams.c @ 26

Last change on this file since 26 was 26, checked in by Paul Smedley, 14 years ago

Updated source to 3.0.25rc1

File size: 28.5 KB
Line 
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   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 2 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, write to the Free Software
20   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21   
22*/
23
24#include "includes.h"
25
26extern BOOL found_lm_clients;
27
28#if 0
29
30/* XXXX note: This function is currently unsuitable for use, as it
31   does not properly check that a server is in a fit state to become
32   a backup browser before asking it to be one.
33   The code is left here to be worked on at a later date.
34*/
35
36/****************************************************************************
37Tell a server to become a backup browser
38**************************************************************************/
39
40void tell_become_backup(void)
41{
42  struct subnet_record *subrec;
43  for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
44  {
45    struct work_record *work;
46    for (work = subrec->workgrouplist; work; work = work->next)
47    {
48      struct server_record *servrec;
49      int num_servers = 0;
50      int num_backups = 0;
51         
52      for (servrec = work->serverlist; servrec; servrec = servrec->next)
53      {
54        num_servers++;
55             
56        if (is_myname(servrec->serv.name))
57          continue;
58             
59        if (servrec->serv.type & SV_TYPE_BACKUP_BROWSER)
60        {
61          num_backups++;
62          continue;
63        }
64             
65        if (servrec->serv.type & SV_TYPE_MASTER_BROWSER)
66          continue;
67             
68        if (!(servrec->serv.type & SV_TYPE_POTENTIAL_BROWSER))
69          continue;
70             
71        DEBUG(3,("num servers: %d num backups: %d\n",
72              num_servers, num_backups));
73             
74        /* make first server a backup server. thereafter make every
75           tenth server a backup server */
76        if (num_backups != 0 && (num_servers+9) / num_backups > 10)
77          continue;
78             
79        DEBUG(2,("sending become backup to %s %s for %s\n",
80             servrec->serv.name, inet_ntoa(subrec->bcast_ip),
81             work->work_group));
82             
83        /* type 11 request from MYNAME(20) to WG(1e) for SERVER */
84        do_announce_request(servrec->serv.name, work->work_group,
85              ANN_BecomeBackup, 0x20, 0x1e, subrec->bcast_ip);
86      }
87    }
88  }
89}
90#endif
91
92/*******************************************************************
93  Process an incoming host announcement packet.
94*******************************************************************/
95
96void process_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
97{
98        struct dgram_packet *dgram = &p->packet.dgram;
99        int ttl = IVAL(buf,1)/1000;
100        unstring announce_name;
101        uint32 servertype = IVAL(buf,23);
102        fstring comment;
103        struct work_record *work;
104        struct server_record *servrec;
105        unstring work_name;
106        unstring source_name;
107
108        START_PROFILE(host_announce);
109
110        pull_ascii_fstring(comment, buf+31);
111 
112        pull_ascii_nstring(announce_name, sizeof(announce_name), buf+5);
113        pull_ascii_nstring(source_name, sizeof(source_name), dgram->source_name.name);
114
115        DEBUG(3,("process_host_announce: from %s<%02x> IP %s to \
116%s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
117                        nmb_namestr(&dgram->dest_name),announce_name));
118
119        DEBUG(5,("process_host_announce: ttl=%d server type=%08x comment=%s\n",
120                ttl, servertype,comment));
121
122        /* Filter servertype to remove impossible bits. */
123        servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);
124
125        /* A host announcement must be sent to the name WORKGROUP<1d>. */
126        if(dgram->dest_name.name_type != 0x1d) {
127                DEBUG(2,("process_host_announce: incorrect name type for destination from IP %s \
128(was %02x) should be 0x1d. Allowing packet anyway.\n",
129                        inet_ntoa(p->ip), dgram->dest_name.name_type));
130                /* Change it so it was. */
131                dgram->dest_name.name_type = 0x1d;
132        }
133
134        /* For a host announce the workgroup name is the destination name. */
135        pull_ascii_nstring(work_name, sizeof(work_name), dgram->dest_name.name);
136
137        /*
138         * Syntax servers version 5.1 send HostAnnounce packets to
139         * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00>
140         * instead of WORKGROUP<1d> name. So to fix this we check if
141         * the workgroup name is our own name, and if so change it
142         * to be our primary workgroup name.
143         */
144
145        if(strequal(work_name, global_myname()))
146                unstrcpy(work_name,lp_workgroup());
147
148        /*
149         * We are being very agressive here in adding a workgroup
150         * name on the basis of a host announcing itself as being
151         * in that workgroup. Maybe we should wait for the workgroup
152         * announce instead ? JRA.
153         */
154
155        work = find_workgroup_on_subnet(subrec, work_name);
156
157        if(servertype != 0) {
158                if (work ==NULL ) {
159                        /* We have no record of this workgroup. Add it. */
160                        if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
161                                goto done;
162                }
163 
164                if((servrec = find_server_in_workgroup( work, announce_name))==NULL) {
165                        /* If this server is not already in the workgroup, add it. */
166                        create_server_on_workgroup(work, announce_name, 
167                                servertype|SV_TYPE_LOCAL_LIST_ONLY, 
168                                ttl, comment);
169                } else {
170                        /* Update the record. */
171                        servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;
172                        update_server_ttl( servrec, ttl);
173                        fstrcpy(servrec->serv.comment,comment);
174                }
175        } else {
176                /*
177                 * This server is announcing it is going down. Remove it from the
178                 * workgroup.
179                 */
180                if(!is_myname(announce_name) && (work != NULL) &&
181                                ((servrec = find_server_in_workgroup( work, announce_name))!=NULL)) {
182                        remove_server_from_workgroup( work, servrec);
183                }
184        }
185
186        subrec->work_changed = True;
187done:
188
189        END_PROFILE(host_announce);
190}
191
192/*******************************************************************
193  Process an incoming WORKGROUP announcement packet.
194*******************************************************************/
195
196void process_workgroup_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
197{
198        struct dgram_packet *dgram = &p->packet.dgram;
199        int ttl = IVAL(buf,1)/1000;
200        unstring workgroup_announce_name;
201        unstring master_name;
202        uint32 servertype = IVAL(buf,23);
203        struct work_record *work;
204        unstring source_name;
205        unstring dest_name;
206
207        START_PROFILE(workgroup_announce);
208
209        pull_ascii_nstring(workgroup_announce_name,sizeof(workgroup_announce_name),buf+5);
210        pull_ascii_nstring(master_name,sizeof(master_name),buf+31);
211        pull_ascii_nstring(source_name,sizeof(source_name),dgram->source_name.name);
212        pull_ascii_nstring(dest_name,sizeof(dest_name),dgram->dest_name.name);
213
214        DEBUG(3,("process_workgroup_announce: from %s<%02x> IP %s to \
215%s for workgroup %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
216                        nmb_namestr(&dgram->dest_name),workgroup_announce_name));
217
218        DEBUG(5,("process_workgroup_announce: ttl=%d server type=%08x master browser=%s\n",
219                ttl, servertype, master_name));
220
221        /* Workgroup announcements must only go to the MSBROWSE name. */
222        if (!strequal(dest_name, MSBROWSE) || (dgram->dest_name.name_type != 0x1)) {
223                DEBUG(0,("process_workgroup_announce: from IP %s should be to __MSBROWSE__<0x01> not %s\n",
224                        inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name)));
225                goto done;
226        }
227
228        if ((work = find_workgroup_on_subnet(subrec, workgroup_announce_name))==NULL) {
229                /* We have no record of this workgroup. Add it. */
230                if((work = create_workgroup_on_subnet(subrec, workgroup_announce_name, ttl))==NULL)
231                        goto done;
232        } else {
233                /* Update the workgroup death_time. */
234                update_workgroup_ttl(work, ttl);
235        }
236
237        if(*work->local_master_browser_name == '\0') {
238                /* Set the master browser name. */
239                set_workgroup_local_master_browser_name( work, master_name );
240        }
241
242        subrec->work_changed = True;
243
244done:
245
246        END_PROFILE(workgroup_announce);
247}
248
249/*******************************************************************
250  Process an incoming local master browser announcement packet.
251*******************************************************************/
252
253void process_local_master_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
254{
255        struct dgram_packet *dgram = &p->packet.dgram;
256        int ttl = IVAL(buf,1)/1000;
257        unstring server_name;
258        uint32 servertype = IVAL(buf,23);
259        fstring comment;
260        unstring work_name;
261        struct work_record *work;
262        struct server_record *servrec;
263        unstring source_name;
264
265        START_PROFILE(local_master_announce);
266
267        pull_ascii_nstring(server_name,sizeof(server_name),buf+5);
268        pull_ascii_fstring(comment, buf+31);
269        pull_ascii_nstring(source_name, sizeof(source_name), dgram->source_name.name);
270        pull_ascii_nstring(work_name, sizeof(work_name), dgram->dest_name.name);
271
272        DEBUG(3,("process_local_master_announce: from %s<%02x> IP %s to \
273%s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
274                nmb_namestr(&dgram->dest_name),server_name));
275
276        DEBUG(5,("process_local_master_announce: ttl=%d server type=%08x comment=%s\n",
277                ttl, servertype, comment));
278
279        /* A local master announcement must be sent to the name WORKGROUP<1e>. */
280        if(dgram->dest_name.name_type != 0x1e) {
281                DEBUG(0,("process_local_master_announce: incorrect name type for destination from IP %s \
282(was %02x) should be 0x1e. Ignoring packet.\n",
283                        inet_ntoa(p->ip), dgram->dest_name.name_type));
284                goto done;
285        }
286
287        /* Filter servertype to remove impossible bits. */
288        servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);
289
290        /* For a local master announce the workgroup name is the destination name. */
291
292        if ((work = find_workgroup_on_subnet(subrec, work_name))==NULL) {
293                /* Don't bother adding if it's a local master release announce. */
294                if(servertype == 0)
295                        goto done;
296
297                /* We have no record of this workgroup. Add it. */
298                if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
299                        goto done;
300        }
301
302        /* If we think we're the local master browser for this workgroup,
303                we should never have got this packet. We don't see our own
304                packets.
305        */
306        if(AM_LOCAL_MASTER_BROWSER(work)) {
307                DEBUG(0,("process_local_master_announce: Server %s at IP %s is announcing itself as \
308a local master browser for workgroup %s and we think we are master. Forcing election.\n",
309                        server_name, inet_ntoa(p->ip), work_name));
310
311                /* Samba nmbd versions 1.9.17 to 1.9.17p4 have a bug in that when
312                 they have become a local master browser once, they will never
313                 stop sending local master announcements. To fix this we send
314                 them a reset browser packet, with level 0x2 on the __SAMBA__
315                 name that only they should be listening to. */
316   
317                send_browser_reset( 0x2, "__SAMBA__" , 0x20, p->ip);
318
319                /* We should demote ourself and force an election. */
320
321                unbecome_local_master_browser( subrec, work, True);
322
323                /* The actual election requests are handled in nmbd_election.c */
324                goto done;
325        } 
326
327        /* Find the server record on this workgroup. If it doesn't exist, add it. */
328
329        if(servertype != 0) {
330                if((servrec = find_server_in_workgroup( work, server_name))==NULL) {
331                        /* If this server is not already in the workgroup, add it. */
332                        create_server_on_workgroup(work, server_name, 
333                                servertype|SV_TYPE_LOCAL_LIST_ONLY, 
334                                ttl, comment);
335                } else {
336                        /* Update the record. */
337                        servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;
338                        update_server_ttl(servrec, ttl);
339                        fstrcpy(servrec->serv.comment,comment);
340                }
341       
342                set_workgroup_local_master_browser_name( work, server_name );
343        } else {
344                /*
345                 * This server is announcing it is going down. Remove it from the
346                 * workgroup.
347                 */
348                if(!is_myname(server_name) && (work != NULL) &&
349                                ((servrec = find_server_in_workgroup( work, server_name))!=NULL)) {
350                        remove_server_from_workgroup( work, servrec);
351                }
352        }
353
354        subrec->work_changed = True;
355done:
356
357        END_PROFILE(local_master_announce);
358}
359
360/*******************************************************************
361  Process a domain master announcement frame.
362  Domain master browsers receive these from local masters. The Domain
363  master should then issue a sync with the local master, asking for
364  that machines local server list.
365******************************************************************/
366
367void process_master_browser_announce(struct subnet_record *subrec, 
368                                     struct packet_struct *p,char *buf)
369{
370        unstring local_master_name;
371        struct work_record *work;
372        struct browse_cache_record *browrec;
373
374        START_PROFILE(master_browser_announce);
375
376        pull_ascii_nstring(local_master_name,sizeof(local_master_name),buf);
377 
378        DEBUG(3,("process_master_browser_announce: Local master announce from %s IP %s.\n",
379                local_master_name, inet_ntoa(p->ip)));
380 
381        if (!lp_domain_master()) {
382                DEBUG(0,("process_master_browser_announce: Not configured as domain \
383master - ignoring master announce.\n"));
384                goto done;
385        }
386 
387        if((work = find_workgroup_on_subnet(subrec, lp_workgroup())) == NULL) {
388                DEBUG(0,("process_master_browser_announce: Cannot find workgroup %s on subnet %s\n",
389                        lp_workgroup(), subrec->subnet_name));
390                goto done;
391        }
392
393        if(!AM_DOMAIN_MASTER_BROWSER(work)) {
394                DEBUG(0,("process_master_browser_announce: Local master announce made to us from \
395%s IP %s and we are not a domain master browser.\n", local_master_name, inet_ntoa(p->ip)));
396                goto done;
397        }
398
399        /* Add this host as a local master browser entry on the browse lists.
400                This causes a sync request to be made to it at a later date.
401        */
402
403        if((browrec = find_browser_in_lmb_cache( local_master_name )) == NULL) {
404                /* Add it. */
405                create_browser_in_lmb_cache( work->work_group, local_master_name, p->ip);
406        } else {
407                update_browser_death_time(browrec);
408        }
409
410done:
411
412        END_PROFILE(master_browser_announce);
413}
414
415/*******************************************************************
416  Process an incoming LanMan host announcement packet.
417*******************************************************************/
418
419void process_lm_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf, int len)
420{
421        struct dgram_packet *dgram = &p->packet.dgram;
422        uint32 servertype = IVAL(buf,1);
423        int osmajor=CVAL(buf,5);           /* major version of node software */
424        int osminor=CVAL(buf,6);           /* minor version of node software */
425        int ttl = SVAL(buf,7);
426        unstring announce_name;
427        struct work_record *work;
428        struct server_record *servrec;
429        unstring work_name;
430        unstring source_name;
431        fstring comment;
432        char *s = get_safe_str_ptr(buf,len,buf,9);
433
434        START_PROFILE(lm_host_announce);
435        if (!s) {
436                goto done;
437        }
438        s = skip_string(buf,len,s);
439        if (!s) {
440                goto done;
441        }
442        pull_ascii(comment, s, sizeof(fstring), 43, STR_TERMINATE);
443
444        pull_ascii_nstring(announce_name,sizeof(announce_name),buf+9);
445        pull_ascii_nstring(source_name,sizeof(source_name),dgram->source_name.name);
446        /* For a LanMan host announce the workgroup name is the destination name. */
447        pull_ascii_nstring(work_name,sizeof(work_name),dgram->dest_name.name);
448
449        DEBUG(3,("process_lm_host_announce: LM Announcement from %s IP %s to \
450%s for server %s.\n", nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),
451                nmb_namestr(&dgram->dest_name),announce_name));
452
453        DEBUG(5,("process_lm_host_announce: os=(%d,%d) ttl=%d server type=%08x comment=%s\n",
454                osmajor, osminor, ttl, servertype,comment));
455
456        if ((osmajor < 36) || (osmajor > 38) || (osminor !=0)) {
457                DEBUG(5,("process_lm_host_announce: LM Announcement packet does not \
458originate from OS/2 Warp client. Ignoring packet.\n"));
459                /* Could have been from a Windows machine (with its LM Announce enabled),
460                        or a Samba server. Then don't disrupt the current browse list. */
461                goto done;
462        }
463
464        /* Filter servertype to remove impossible bits. */
465        servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);
466
467        /* A LanMan host announcement must be sent to the name WORKGROUP<00>. */
468        if(dgram->dest_name.name_type != 0x00) {
469                DEBUG(2,("process_lm_host_announce: incorrect name type for destination from IP %s \
470(was %02x) should be 0x00. Allowing packet anyway.\n",
471                        inet_ntoa(p->ip), dgram->dest_name.name_type));
472                /* Change it so it was. */
473                dgram->dest_name.name_type = 0x00;
474        }
475
476        /*
477         * Syntax servers version 5.1 send HostAnnounce packets to
478         * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00>
479         * instead of WORKGROUP<1d> name. So to fix this we check if
480         * the workgroup name is our own name, and if so change it
481         * to be our primary workgroup name. This code is probably
482         * not needed in the LanMan announce code, but it won't hurt.
483         */
484
485        if(strequal(work_name, global_myname()))
486                unstrcpy(work_name,lp_workgroup());
487
488        /*
489         * We are being very agressive here in adding a workgroup
490         * name on the basis of a host announcing itself as being
491         * in that workgroup. Maybe we should wait for the workgroup
492         * announce instead ? JRA.
493         */
494
495        work = find_workgroup_on_subnet(subrec, work_name);
496
497        if(servertype != 0) {
498                if (work == NULL) {
499                        /* We have no record of this workgroup. Add it. */
500                        if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
501                                goto done;
502                }
503
504                if((servrec = find_server_in_workgroup( work, announce_name))==NULL) {
505                        /* If this server is not already in the workgroup, add it. */
506                        create_server_on_workgroup(work, announce_name,
507                                        servertype|SV_TYPE_LOCAL_LIST_ONLY,
508                                        ttl, comment);
509                } else {
510                        /* Update the record. */
511                        servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;
512                        update_server_ttl( servrec, ttl);
513                        fstrcpy(servrec->serv.comment,comment);
514                }
515        } else {
516                /*
517                 * This server is announcing it is going down. Remove it from the
518                 * workgroup.
519                 */
520                if(!is_myname(announce_name) && (work != NULL) &&
521                                ((servrec = find_server_in_workgroup( work, announce_name))!=NULL)) {
522                        remove_server_from_workgroup( work, servrec);
523                }
524        }
525
526        subrec->work_changed = True;
527        found_lm_clients = True;
528
529done:
530
531        END_PROFILE(lm_host_announce);
532}
533
534/****************************************************************************
535  Send a backup list response.
536*****************************************************************************/
537
538static void send_backup_list_response(struct subnet_record *subrec, 
539                                      struct work_record *work,
540                                      struct nmb_name *send_to_name,
541                                      unsigned char max_number_requested,
542                                      uint32 token, struct in_addr sendto_ip,
543                                      int port)
544{                     
545        char outbuf[1024];
546        char *p, *countptr;
547        unsigned int count = 0;
548        unstring send_to_namestr;
549#if 0
550  struct server_record *servrec;
551#endif
552        unstring myname;
553
554        memset(outbuf,'\0',sizeof(outbuf));
555
556        DEBUG(3,("send_backup_list_response: sending backup list for workgroup %s to %s IP %s\n",
557                work->work_group, nmb_namestr(send_to_name), inet_ntoa(sendto_ip)));
558 
559        p = outbuf;
560 
561        SCVAL(p,0,ANN_GetBackupListResp); /* Backup list response opcode. */
562        p++;
563
564        countptr = p;
565        p++;
566
567        SIVAL(p,0,token); /* The sender's unique info. */
568        p += 4;
569 
570        /* We always return at least one name - our own. */
571        count = 1;
572        unstrcpy(myname, global_myname());
573        strupper_m(myname);
574        myname[15]='\0';
575        push_pstring_base(p, myname, outbuf);
576
577        p = skip_string(outbuf,sizeof(outbuf),p);
578
579        /* Look for backup browsers in this workgroup. */
580
581#if 0
582  /* we don't currently send become_backup requests so we should never
583     send any other servers names out as backups for our
584     workgroup. That's why this is commented out (tridge) */
585
586  /*
587   * NB. Note that the struct work_record here is not neccessarily
588   * attached to the subnet *subrec.
589   */
590
591  for (servrec = work->serverlist; servrec; servrec = servrec->next)
592  {
593    int len = PTR_DIFF(p, outbuf);
594    if((sizeof(outbuf) - len) < 16)
595      break;
596
597    if(count >= (unsigned int)max_number_requested)
598      break;
599
600    if(strnequal(servrec->serv.name, global_myname(),15))
601      continue;
602
603    if(!(servrec->serv.type & SV_TYPE_BACKUP_BROWSER))
604      continue;
605
606    StrnCpy(p, servrec->serv.name, 15);
607    strupper_m(p);
608    count++;
609
610    DEBUG(5,("send_backup_list_response: Adding server %s number %d\n",
611              p, count));
612
613    p = skip_string(outbuf,sizeof(outbuf),p);
614  }
615#endif
616
617        SCVAL(countptr, 0, count);
618
619        pull_ascii_nstring(send_to_namestr, sizeof(send_to_namestr), send_to_name->name);
620
621        DEBUG(4,("send_backup_list_response: sending response to %s<00> IP %s with %d servers.\n",
622                send_to_namestr, inet_ntoa(sendto_ip), count));
623
624        send_mailslot(True, BROWSE_MAILSLOT,
625                outbuf,PTR_DIFF(p,outbuf),
626                global_myname(), 0, 
627                send_to_namestr,0,
628                sendto_ip, subrec->myip, port);
629}
630
631/*******************************************************************
632  Process a send backup list request packet.
633
634  A client sends a backup list request to ask for a list of servers on
635  the net that maintain server lists for a domain. A server is then
636  chosen from this list to send NetServerEnum commands to to list
637  available servers.
638
639********************************************************************/
640
641void process_get_backup_list_request(struct subnet_record *subrec,
642                                     struct packet_struct *p,char *buf)
643{
644        struct dgram_packet *dgram = &p->packet.dgram;
645        struct work_record *work;
646        unsigned char max_number_requested = CVAL(buf,0);
647        uint32 token = IVAL(buf,1); /* Sender's key index for the workgroup. */
648        int name_type = dgram->dest_name.name_type;
649        unstring workgroup_name;
650        struct subnet_record *search_subrec = subrec;
651
652        START_PROFILE(get_backup_list);
653        pull_ascii_nstring(workgroup_name, sizeof(workgroup_name), dgram->dest_name.name);
654
655        DEBUG(3,("process_get_backup_list_request: request from %s IP %s to %s.\n",
656                nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),
657                nmb_namestr(&dgram->dest_name)));
658 
659        /* We have to be a master browser, or a domain master browser
660                for the requested workgroup. That means it must be our
661                workgroup. */
662
663        if(strequal(workgroup_name, lp_workgroup()) == False) {
664                DEBUG(7,("process_get_backup_list_request: Ignoring announce request for workgroup %s.\n",
665                        workgroup_name));
666                goto done;
667        }
668
669        if((work = find_workgroup_on_subnet(search_subrec, workgroup_name)) == NULL) {
670                DEBUG(0,("process_get_backup_list_request: Cannot find workgroup %s on \
671subnet %s.\n", workgroup_name, search_subrec->subnet_name));
672                goto done;
673        }
674
675        /*
676         * If the packet was sent to WORKGROUP<1b> instead
677         * of WORKGROUP<1d> then it was unicast to us a domain master
678         * browser. Change search subrec to unicast.
679         */
680
681        if(name_type == 0x1b) {
682                /* We must be a domain master browser in order to
683                        process this packet. */
684
685                if(!AM_DOMAIN_MASTER_BROWSER(work)) {
686                        DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \
687and I am not a domain master browser.\n", workgroup_name));
688                        goto done;
689                }
690
691                search_subrec = unicast_subnet;
692        } else if (name_type == 0x1d) {
693                /* We must be a local master browser in order to process this packet. */
694
695                if(!AM_LOCAL_MASTER_BROWSER(work)) {
696                        DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \
697and I am not a local master browser.\n", workgroup_name));
698                        goto done;
699                }
700        } else {
701                DEBUG(0,("process_get_backup_list_request: Invalid name type %x - should be 0x1b or 0x1d.\n",
702                        name_type));
703                goto done;
704        }
705
706        send_backup_list_response(subrec, work, &dgram->source_name,
707                        max_number_requested, token, p->ip, p->port);
708
709done:
710
711        END_PROFILE(get_backup_list);
712}
713
714/*******************************************************************
715  Process a reset browser state packet.
716
717  Diagnostic packet:
718  0x1 - Stop being a master browser and become a backup browser.
719  0x2 - Discard browse lists, stop being a master browser, try again.
720  0x4 - Stop being a master browser forever.
721         
722******************************************************************/
723
724void process_reset_browser(struct subnet_record *subrec,
725                                  struct packet_struct *p,char *buf)
726{
727        struct dgram_packet *dgram = &p->packet.dgram;
728        int state = CVAL(buf,0);
729        struct subnet_record *sr;
730
731        START_PROFILE(reset_browser);
732
733        DEBUG(1,("process_reset_browser: received diagnostic browser reset \
734request from %s IP %s state=0x%X\n",
735                nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), state));
736
737        /* Stop being a local master browser on all our broadcast subnets. */
738        if (state & 0x1) {
739                for (sr = FIRST_SUBNET; sr; sr = NEXT_SUBNET_EXCLUDING_UNICAST(sr)) {
740                        struct work_record *work;
741                        for (work = sr->workgrouplist; work; work = work->next) {
742                                if (AM_LOCAL_MASTER_BROWSER(work))
743                                        unbecome_local_master_browser(sr, work, True);
744                        }
745                }
746        }
747 
748        /* Discard our browse lists. */
749        if (state & 0x2) {
750                /*
751                 * Calling expire_workgroups_and_servers with a -1
752                 * time causes all servers not marked with a PERMANENT_TTL
753                 * on the workgroup lists to be discarded, and all
754                 * workgroups with empty server lists to be discarded.
755                 * This means we keep our own server names and workgroup
756                 * as these have a PERMANENT_TTL.
757                 */
758
759                expire_workgroups_and_servers(-1);
760        }
761 
762        /* Request to stop browsing altogether. */
763        if (state & 0x4)
764                DEBUG(1,("process_reset_browser: ignoring request to stop being a browser.\n"));
765
766        END_PROFILE(reset_browser);
767}
768
769/*******************************************************************
770  Process an announcement request packet.
771  We don't respond immediately, we just check it's a request for
772  our workgroup and then set the flag telling the announce code
773  in nmbd_sendannounce.c:announce_my_server_names that an
774  announcement is needed soon.
775******************************************************************/
776
777void process_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf)
778{
779        struct dgram_packet *dgram = &p->packet.dgram;
780        struct work_record *work;
781        unstring workgroup_name;
782 
783        START_PROFILE(announce_request);
784
785        pull_ascii_nstring(workgroup_name, sizeof(workgroup_name), dgram->dest_name.name);
786        DEBUG(3,("process_announce_request: Announce request from %s IP %s to %s.\n",
787                nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),
788                nmb_namestr(&dgram->dest_name)));
789 
790        /* We only send announcement requests on our workgroup. */
791        if(strequal(workgroup_name, lp_workgroup()) == False) {
792                DEBUG(7,("process_announce_request: Ignoring announce request for workgroup %s.\n",
793                        workgroup_name));
794                goto done;
795        }
796
797        if((work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL) {
798                DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n",
799                        workgroup_name));
800                goto done;
801        }
802
803        work->needannounce = True;
804done:
805
806        END_PROFILE(announce_request);
807}
808
809/*******************************************************************
810  Process a LanMan announcement request packet.
811  We don't respond immediately, we just check it's a request for
812  our workgroup and then set the flag telling that we have found
813  a LanMan client (DOS or OS/2) and that we will have to start
814  sending LanMan announcements (unless specifically disabled
815  through the "lm announce" parameter in smb.conf)
816******************************************************************/
817
818void process_lm_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf, int len)
819{
820        struct dgram_packet *dgram = &p->packet.dgram;
821        unstring workgroup_name;
822
823        START_PROFILE(lm_announce_request);
824
825        pull_ascii_nstring(workgroup_name, sizeof(workgroup_name), dgram->dest_name.name);
826        DEBUG(3,("process_lm_announce_request: Announce request from %s IP %s to %s.\n",
827                nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),
828                nmb_namestr(&dgram->dest_name)));
829
830        /* We only send announcement requests on our workgroup. */
831        if(strequal(workgroup_name, lp_workgroup()) == False) {
832                DEBUG(7,("process_lm_announce_request: Ignoring announce request for workgroup %s.\n",
833                        workgroup_name));
834                goto done;
835        }
836
837        if(find_workgroup_on_subnet(subrec, workgroup_name) == NULL) {
838                DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n",
839                        workgroup_name));
840                goto done;
841        }
842
843        found_lm_clients = True;
844
845done:
846
847        END_PROFILE(lm_announce_request);
848}
Note: See TracBrowser for help on using the repository browser.