2 more consultants.
[kai/samba.git] / source3 / nameservreply.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    NBT netbios routines and daemon - version 2
5    Copyright (C) Andrew Tridgell 1994-1997
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20    
21    Module name: nameservreply.c
22
23    Revision History:
24
25    14 jan 96: lkcl@pires.co.uk
26    added multiple workgroup domain master support
27
28    04 jul 96: lkcl@pires.co.uk
29    created module nameservreply containing NetBIOS reply functions
30
31 */
32
33 #include "includes.h"
34
35 extern int ClientNMB;
36
37 extern int DEBUGLEVEL;
38
39 extern struct in_addr wins_ip;
40
41 /****************************************************************************
42 send a registration / release response: pos/neg
43 **************************************************************************/
44 static void send_name_response(int fd, struct in_addr from_ip,
45                                 int name_trn_id, int opcode, BOOL success,
46                 BOOL recursion_available, BOOL recursion_desired,
47                                 struct nmb_name *reply_name, int nb_flags, int ttl,
48                                 struct in_addr ip)
49 {
50   char rdata[6];
51   struct packet_struct p;
52
53   int rcode = 0;  
54
55   if (success == False)
56   {
57     /* NEGATIVE RESPONSE */
58     rcode = 6;
59   }
60   else if (opcode == NMB_REG && !recursion_available)
61   {
62     /* END-NODE CHALLENGE REGISTRATION RESPONSE */
63         rcode = 0;
64   }
65   
66   rdata[0] = nb_flags;
67   rdata[1] = 0;
68   putip(&rdata[2],(char *)&ip);
69   
70   p.ip = from_ip;
71   p.port = NMB_PORT;
72   p.fd = fd;
73   p.timestamp = time(NULL);
74   p.packet_type = NMB_PACKET;
75
76   reply_netbios_packet(&p,name_trn_id,
77                        rcode,opcode,opcode,
78                recursion_available, recursion_desired,
79                        reply_name, 0x20, 0x1,
80                        ttl, 
81                        rdata, 6);
82 }
83
84 /****************************************************************************
85   add a netbios entry. respond to the (possibly new) owner.
86   **************************************************************************/
87 void add_name_respond(struct subnet_record *d, int fd, struct in_addr from_ip,
88                                 uint16 response_id,
89                                 struct nmb_name *name,
90                                 int nb_flags, int ttl, struct in_addr register_ip,
91                                 BOOL new_owner, struct in_addr reply_to_ip)
92 {
93   /* register the old or the new owners' ip */
94   add_netbios_entry(d,name->name,name->name_type,
95                     nb_flags,ttl,REGISTER,register_ip,False,True);
96
97   /* reply yes or no to the host that requested the name */
98   /* see rfc1002.txt - 4.2.10 and 4.2.11 */
99   send_name_response(fd,from_ip, response_id, NMB_REG,
100                      new_owner,
101                      True, True,
102                      name, nb_flags, ttl, reply_to_ip);
103 }
104
105
106 /****************************************************************************
107 reply to a name release
108 ****************************************************************************/
109 void reply_name_release(struct packet_struct *p)
110 {
111   struct nmb_packet *nmb = &p->packet.nmb;
112   struct in_addr ip;
113   int nb_flags = nmb->additional->rdata[0];
114   BOOL bcast = nmb->header.nm_flags.bcast;
115   struct name_record *n;
116   struct subnet_record *d = NULL;
117   int search = 0;
118   BOOL success = False;
119   
120   putip((char *)&ip,&nmb->additional->rdata[2]);  
121   
122   DEBUG(3,("Name release on name %s\n",
123            namestr(&nmb->question.question_name)));
124   
125   if (!(d = find_req_subnet(p->ip, bcast)))
126     {
127       DEBUG(3,("response packet: bcast %s not known\n",
128                inet_ntoa(p->ip)));
129       return;
130     }
131
132   if (bcast)
133     search |= FIND_LOCAL;
134   else
135     search |= FIND_WINS;
136
137   n = find_name_search(&d, &nmb->question.question_name, 
138                        search, ip);
139   
140   /* XXXX under what conditions should we reject the removal?? */
141   /* For now - remove if the names match and the group bit matches. */
142   if (n && (n->source != SELF) && (NAME_GROUP(n->ip_flgs[0].nb_flags) == NAME_GROUP(nb_flags)))
143     {
144       success = True;
145   
146       /* If it's a group name not ending in 1c (not an internet name)
147          then just allow it to fade out of existance by timing out. */  
148       if(NAME_GROUP(nb_flags) && (n->name.name_type != 0x1c))
149       {
150         DEBUG(5, ("reply_name_release: Allow group name %s(%d) to fade out on \
151 subnet %s\n", namestr(&nmb->question.question_name), n->name.name_type,
152             inet_ntoa(d->bcast_ip)));
153       }
154       else
155       {
156         DEBUG(5, ("reply_name_release: Removing name %s on subnet %s\n",
157                 namestr(&nmb->question.question_name), inet_ntoa(d->bcast_ip)));
158         remove_name(d,n);
159         n = NULL;
160       }
161     }
162   
163   if (bcast) return;
164   
165   /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
166   send_name_response(p->fd,p->ip, nmb->header.name_trn_id, NMB_REL,
167                      success, False, False,
168                      &nmb->question.question_name, nb_flags, 0, ip);
169 }
170
171
172 /****************************************************************************
173 reply to a reg request
174 **************************************************************************/
175 void reply_name_reg(struct packet_struct *p)
176 {
177   struct nmb_packet *nmb = &p->packet.nmb;
178   struct nmb_name *question = &nmb->question.question_name;
179   
180   struct nmb_name *reply_name = question;
181
182   char *qname      = question->name;
183   int   qname_type = question->name_type;
184  
185   BOOL bcast = nmb->header.nm_flags.bcast;
186   
187   int ttl = GET_TTL(nmb->additional->ttl);
188   int nb_flags = nmb->additional->rdata[0];
189   BOOL group = NAME_GROUP(nb_flags);
190
191   struct subnet_record *d = NULL;
192   struct name_record *n = NULL;
193
194   BOOL success = True;
195   BOOL secured_redirect = False;
196
197   struct in_addr ip, from_ip;
198   int search = 0;
199   
200   putip((char *)&from_ip,&nmb->additional->rdata[2]);
201   ip = from_ip;
202   
203   DEBUG(3,("Name registration for name %s at %s - ",
204                    namestr(question),inet_ntoa(ip)));
205   
206   if (group)
207     {
208       /* apparently we should return 255.255.255.255 for group queries
209          (email from MS) */
210       ip = *interpret_addr2("255.255.255.255");
211     }
212   
213   if (!(d = find_req_subnet(p->ip, bcast)))
214   {
215     DEBUG(3,("reply_name_reg: subnet %s not known\n",
216                                 inet_ntoa(p->ip)));
217     return;
218   }
219
220   if (bcast)
221         search |= FIND_LOCAL;
222   else
223         search |= FIND_WINS;
224
225   /* see if the name already exists */
226   n = find_name_search(&d, question, search, from_ip);
227   
228   if (n)
229   {
230     DEBUG(3,("found\n"));
231     if (!group) /* unique names */
232         {
233           if (n->source == SELF || NAME_GROUP(n->ip_flgs[0].nb_flags))
234           {
235               /* no-one can register one of samba's names, nor can they
236                  register a name that's a group name as a unique name */
237               
238               success = False;
239           }
240           else if(!ip_equal(ip, n->ip_flgs[0].ip))
241           {
242               /* XXXX rfc1001.txt says:
243                * if we are doing secured WINS, we must send a Wait-Acknowledge
244                * packet (WACK) to the person who wants the name, then do a
245                * name query on the person who currently owns the unique name.
246                * if the current owner still says they own it, the person who wants
247                    * the name can't have it. if they do not, or are not alive, they can.
248                */
249
250           secured_redirect = True;
251
252               reply_name = &n->name;
253           }
254           else
255           {
256               n->ip_flgs[0].ip = ip;
257               n->death_time = ttl?p->timestamp+ttl*3:0;
258               DEBUG(3,("%s owner: %s\n",namestr(&n->name),inet_ntoa(n->ip_flgs[0].ip)));
259           }
260         }
261     else
262         {
263           /* refresh the name */
264           if (n->source != SELF)
265           {
266               n->death_time = ttl?p->timestamp + ttl*3:0;
267           }
268         }
269
270     /* XXXX bug reported by terryt@ren.pc.athabascau.ca */
271     /* names that people have checked for and not found get DNSFAILed. 
272        we need to update the name record if someone then registers */
273
274     if (n->source == DNSFAIL)
275       n->source = REGISTER;
276
277   }
278   else
279   {
280       DEBUG(3,("not found\n"));
281       /* add the name to our name/subnet, or WINS, database */
282       n = add_netbios_entry(d,qname,qname_type,nb_flags,ttl,REGISTER,ip,
283                                 True,!bcast);
284   }
285   
286   /* if samba owns a unique name on a subnet, then it must respond and
287      disallow the attempted registration. if the registration is
288      successful by broadcast, only then is there no need to respond
289      (implicit registration: see rfc1001.txt 15.2.1).
290    */
291
292   if (bcast && success) return;
293   
294   if (secured_redirect)
295   {
296     char rdata[2];
297
298     /* XXXX i am confused. RSVAL or SSVAL? assume NMB byte ordering */
299     RSSVAL(rdata,0,(nmb->header.opcode&0xf) + ((nb_flags&0xff) << 4));
300   
301     /* XXXX mistake in rfc1002.txt? 4.2.16: NULL is 0xa see 4.2.1.3 
302        type  = 0x0a; see rfc1002.txt 4.2.1.3 
303        class = 0x01; see rfc1002.txt 4.2.16
304      */
305
306     /* send WAIT ACKNOWLEDGEMENT see rfc1002.txt 4.2.16 */
307     reply_netbios_packet(p,nmb->header.name_trn_id,
308                        0,NMB_WAIT_ACK,NMB_WAIT_ACK,
309                False,False,
310                        reply_name, 0x0a, 0x01,
311                        15*1000, /* 15 seconds long enough to wait? */
312                        rdata, 2);
313
314     /* initiate some enquiries to the current owner. */
315         queue_netbios_packet(d,ClientNMB,NMB_QUERY,
316              NAME_REGISTER_CHALLENGE,
317              reply_name->name,reply_name->name_type,
318              nb_flags,0,0,NULL,NULL,
319                          False, False,
320              n->ip_flgs[0].ip, p->ip);
321   }
322   else
323   {
324     /* Send a NAME REGISTRATION RESPONSE (pos/neg) see rfc1002.txt 4.2.5-6
325        or an END-NODE CHALLENGE REGISTRATION RESPONSE see rfc1002.txt 4.2.7
326      */
327
328         send_name_response(p->fd,p->ip, nmb->header.name_trn_id, NMB_REG,
329                         success,
330             True, True,
331                         reply_name, nb_flags, ttl, ip);
332   }
333 }
334
335 /* this is used to sort names for a name status into a sensible order
336    we put our own names first, then in alphabetical order */
337 static int status_compare(char *n1,char *n2)
338 {
339   extern pstring myname;
340   int l1,l2,l3;
341
342   /* its a bit tricky because the names are space padded */
343   for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++) ;
344   for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++) ;
345   l3 = strlen(myname);
346
347   if ((l1==l3) && strncmp(n1,myname,l3) == 0 && 
348       (l2!=l3 || strncmp(n2,myname,l3) != 0))
349     return -1;
350
351   if ((l2==l3) && strncmp(n2,myname,l3) == 0 && 
352       (l1!=l3 || strncmp(n1,myname,l3) != 0))
353     return 1;
354
355   return memcmp(n1,n2,18);
356 }
357
358
359 /****************************************************************************
360   reply to a name status query
361
362   combine the list of the local interface on which the query was made with
363   the names registered via wins.
364   ****************************************************************************/
365 void reply_name_status(struct packet_struct *p)
366 {
367   struct nmb_packet *nmb = &p->packet.nmb;
368   char *qname   = nmb->question.question_name.name;
369   int ques_type = nmb->question.question_name.name_type;
370   char rdata[MAX_DGRAM_SIZE];
371   char *countptr, *buf, *bufend, *buf0;
372   int names_added,i;
373   struct name_record *n;
374   struct subnet_record *d = NULL;
375   int search = FIND_SELF | FIND_WINS | FIND_LOCAL;
376
377   /* NOTE: we always treat a name status lookup as a bcast */ 
378   if (!(d = find_req_subnet(p->ip, True)))
379   {
380     DEBUG(3,("Name status req: bcast %s not known\n",
381                         inet_ntoa(p->ip)));
382     return;
383   }
384
385   DEBUG(3,("Name status for name %s %s\n",
386            namestr(&nmb->question.question_name), 
387            inet_ntoa(p->ip)));
388
389   n = find_name_search(&d, &nmb->question.question_name,
390                                 search, p->ip);
391   
392   if (!n) return;
393   
394   /* XXXX hack, we should calculate exactly how many will fit */
395   bufend = &rdata[MAX_DGRAM_SIZE] - 18;
396   countptr = buf = rdata;
397   buf += 1;
398   buf0 = buf;
399
400   names_added = 0;
401
402   n = d->namelist;
403
404   while (buf < bufend) 
405   {
406     if (n->source == SELF)
407     {
408       int name_type = n->name.name_type;
409       
410       /* check if we want to exclude other workgroup names
411              from the response. if we don't exclude them, windows clients
412              get confused and will respond with an error for NET VIEW */
413       
414       if (!strequal(n->name.name,"*") &&
415           !strequal(n->name.name,"__SAMBA__") &&
416           (name_type < 0x1b || name_type >= 0x20 || 
417            ques_type < 0x1b || ques_type >= 0x20 ||
418            strequal(qname, n->name.name)))
419       {
420         /* start with first bit of putting info in buffer: the name */
421         bzero(buf,18);
422             sprintf(buf,"%-15.15s",n->name.name);
423         strupper(buf);
424         
425         /* put name type and netbios flags in buffer */
426         buf[15] = name_type;
427         buf[16]  = n->ip_flgs[0].nb_flags;
428         
429         buf += 18;
430       
431         names_added++;
432       }
433     }
434
435     /* remove duplicate names */
436     qsort(buf0,names_added,18,QSORT_CAST status_compare);
437
438     for (i=1;i<names_added;i++) {
439       if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) {
440         names_added--;
441         if (names_added == i) break;
442         memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i));
443         i--;
444       }
445     }
446
447     buf = buf0 + 18*names_added;
448
449     n = n->next;
450
451     if (!n)
452     {
453       /* end of this name list: add wins names too? */
454       struct subnet_record *w_d;
455
456       if (!(w_d = wins_subnet)) break;
457
458       if (w_d != d)
459       {
460         d = w_d;
461         n = d->namelist; /* start on the wins name list */
462       }
463         }
464         if (!n) break;
465   }
466   
467   SCVAL(countptr,0,names_added);
468   
469   /* XXXXXXX we should fill in more fields of the statistics structure */
470   bzero(buf,64);
471   {
472     extern int num_good_sends,num_good_receives;
473     SIVAL(buf,20,num_good_sends);
474     SIVAL(buf,24,num_good_receives);
475   }
476   
477   buf += 46;
478   
479   /* Send a POSITIVE NAME STATUS RESPONSE */
480   reply_netbios_packet(p,nmb->header.name_trn_id,
481                            0,NMB_STATUS,0,False, False,
482                        &nmb->question.question_name,
483                        0x21, 0x01,
484                        0, rdata,PTR_DIFF(buf,rdata));
485 }
486
487
488 /***************************************************************************
489 reply to a name query.
490
491 with broadcast name queries:
492
493         - only reply if the query is for one of YOUR names. all other machines on
494           the network will be doing the same thing (that is, only replying to a
495           broadcast query if they own it)
496           NOTE: broadcast name queries should only be sent out by a machine
497           if they HAVEN'T been configured to use WINS. this is generally bad news
498           in a wide area tcp/ip network and should be rectified by the systems
499           administrator. USE WINS! :-)
500         - the exception to this is if the query is for a Primary Domain Controller
501           type name (0x1b), in which case, a reply is sent.
502
503         - NEVER send a negative response to a broadcast query. no-one else will!
504
505 with directed name queries:
506
507         - if you are the WINS server, you are expected to respond with either
508       a negative response, a positive response, or a wait-for-acknowledgement
509       packet, and then later on a pos/neg response.
510
511 ****************************************************************************/
512 void reply_name_query(struct packet_struct *p)
513 {
514   struct nmb_packet *nmb = &p->packet.nmb;
515   struct nmb_name *question = &nmb->question.question_name;
516   int name_type = question->name_type;
517
518   BOOL bcast = nmb->header.nm_flags.bcast;
519   BOOL query_is_to_wins_server = (!bcast && 
520              nmb->header.nm_flags.recursion_desired);
521   int ttl=0;
522   int rcode = 0;
523   int nb_flags = 0;
524   struct in_addr retip;
525   char rdata[6];
526   struct subnet_record *d = NULL;
527   BOOL success = True;
528   struct name_record *n = NULL;
529   BOOL acting_as_wins_server = lp_wins_support();
530
531   /* directed queries are for WINS server: broadcasts are local SELF queries.
532      the exception is Domain Master names.  */
533
534   if (query_is_to_wins_server)
535   {
536     /* queries to the WINS server involve the WINS server subnet */
537     if (!(d = wins_subnet))
538     {
539       DEBUG(3,("name query: wins search %s not known\n",
540                                     inet_ntoa(p->ip)));
541       success = False;
542     }
543   }
544   else
545   {
546     /* queries to the WINS client involve, unfortunately, the WINS subnet
547        because it contains WINS client (SELF) entries, as _well_ as WINS
548        server entries.  not good.
549      */
550
551     if (!(d = find_subnet(*iface_bcast(p->ip))))
552     {
553       DEBUG(3,("name query: interface for %s not known\n",
554                                     inet_ntoa(p->ip)));
555       success = False;
556     }
557   }
558
559   DEBUG(3,("Name query from %s for name %s<0x%x>\n", 
560                   inet_ntoa(p->ip), question->name, question->name_type));
561   
562   if (!bcast && (name_type == 0x1d) && lp_wins_support())
563   {
564     /* see WINS manager HELP - 'How WINS Handles Special Names' */
565     /* a WINS query (unicasted) for a 0x1d name must always return False */
566     success = False;
567   }
568
569   if (success)
570   {
571     /* look up the name in the cache */
572     n = find_name_search(&d, question, FIND_LOCAL, p->ip);
573
574     /* it is a name that already failed DNS lookup or it's expired */
575     if (n && (n->source == DNSFAIL ||
576               (n->death_time && n->death_time < p->timestamp)))
577     {
578       success = False;
579     }
580    
581     /* do we want to do dns lookups? */
582     /* XXXX this DELAYS nmbd while it does a search.  lp_dns_proxy()
583        can be switched off, to ensure that the blocking doesn't occur.
584        a better solution would be to fork, but this will require a
585        mechanism to carry on processing after the query is resolved
586        (similar to the netbios queue).
587      */
588     if (success && !n && (lp_dns_proxy() || !bcast))
589     {
590       n = dns_name_search(question, p->timestamp);
591     }
592   }
593
594   if (!n) success = False;
595   
596   if (success)
597   {
598       if (bcast && n->source != SELF && name_type != 0x1b)
599       {
600         /* don't respond to broadcast queries unless the query is for
601            a name we own or it is for a Primary Domain Controller name */
602
603             if (!lp_wins_proxy() || 
604             same_net(p->ip,n->ip_flgs[0].ip,*iface_nmask(p->ip)))
605         {
606               /* never reply with a negative response to broadcast queries */
607               return;
608         }
609       }
610       
611       /* name is directed query, or it's self, or it's a Domain Master type
612          name, or we're replying on behalf of a caller because they are on a
613          different subnet and cannot hear the broadcast. XXXX lp_wins_proxy
614          should be switched off in environments where broadcasts are forwarded
615        */
616
617       /* XXXX note: for proxy servers, we should forward the query on to
618          another WINS server if the name is not in our database, or we are
619          not a WINS server ourselves
620        */
621       ttl = n->death_time ? n->death_time - p->timestamp : GET_TTL(0);
622       retip = n->ip_flgs[0].ip;
623       nb_flags = n->ip_flgs[0].nb_flags;
624   }
625
626   if (!success && bcast) return; /* never reply negative response to bcasts */
627
628   /* if the IP is 0 then substitute my IP */
629   if (zero_ip(retip)) retip = *iface_ip(p->ip);
630
631   /* SPECIAL CASE... If we are a WINS server and the request is explicitly
632      *to* the WINS server and the name type is WORKGROUP<0x1e> we should 
633      respond with the local broadcast address 255.255.255.255.
634    */
635   if(!bcast && (name_type == 0x1e) && lp_wins_support())
636     retip = *interpret_addr2("255.255.255.255");
637
638   if (success)
639   {
640       rcode = 0;
641       DEBUG(3,("OK %s\n",inet_ntoa(retip)));      
642   }
643   else
644   {
645       rcode = 3;
646       DEBUG(3,("UNKNOWN\n"));      
647   }
648   
649   if (success)
650   {
651       rdata[0] = nb_flags;
652       rdata[1] = 0;
653       putip(&rdata[2],(char *)&retip);
654   }
655   
656   /* see rfc1002.txt 4.2.13 */
657
658   reply_netbios_packet(p,nmb->header.name_trn_id,
659      rcode,NMB_QUERY,0,
660      (query_is_to_wins_server && acting_as_wins_server ? 
661               True : False), /* recursion_available flag */
662      True, /* recursion_desired_flag */ 
663      &nmb->question.question_name,
664      0x20, 0x01,
665      ttl,
666      rdata, success ? 6 : 0);
667 }