lots of changes to nmbd
[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-1996
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 ipgrp;
40
41
42 /****************************************************************************
43   add a netbios entry. respond to the (possibly new) owner.
44   **************************************************************************/
45 void add_name_respond(struct subnet_record *d, int fd, struct in_addr from_ip,
46                                 uint16 response_id,
47                                 struct nmb_name *name,
48                                 int nb_flags, int ttl, struct in_addr register_ip,
49                                 BOOL new_owner, struct in_addr reply_to_ip)
50 {
51         /* register the old or the new owners' ip */
52         add_netbios_entry(d,name->name,name->name_type,
53                                                 nb_flags,ttl,REGISTER,register_ip,False,True);
54
55         /* reply yes or no to the host that requested the name */
56         send_name_response(fd,from_ip, response_id, NMB_REG,
57                                 new_owner, True,
58                                 name, nb_flags, ttl, reply_to_ip);
59 }
60
61 /****************************************************************************
62 send a registration / release response: pos/neg
63 **************************************************************************/
64 void send_name_response(int fd, struct in_addr from_ip,
65                                 int name_trn_id, int opcode, BOOL success, BOOL recurse,
66                                 struct nmb_name *reply_name, int nb_flags, int ttl,
67                                 struct in_addr ip)
68 {
69   char rdata[6];
70   struct packet_struct p;
71
72   int rcode = 0;  
73
74   if (success == False)
75   {
76     /* NEGATIVE RESPONSE */
77     rcode = 6;
78   }
79   else if (opcode == NMB_REG && recurse == False)
80   {
81     /* END-NODE CHALLENGE REGISTRATION RESPONSE */
82         rcode = 0;
83   }
84   
85   rdata[0] = nb_flags;
86   rdata[1] = 0;
87   putip(&rdata[2],(char *)&ip);
88   
89   p.ip = from_ip;
90   p.port = NMB_PORT;
91   p.fd = fd;
92   p.timestamp = time(NULL);
93   p.packet_type = NMB_PACKET;
94
95   reply_netbios_packet(&p,name_trn_id,
96                        rcode,opcode,opcode,recurse,
97                        reply_name, 0x20, 0x1,
98                        ttl, 
99                        rdata, 6);
100 }
101
102
103 /****************************************************************************
104 reply to a name release
105 ****************************************************************************/
106 void reply_name_release(struct packet_struct *p)
107 {
108   struct nmb_packet *nmb = &p->packet.nmb;
109   struct in_addr ip;
110   int nb_flags = nmb->additional->rdata[0];
111   BOOL bcast = nmb->header.nm_flags.bcast;
112   struct name_record *n;
113   struct subnet_record *d = NULL;
114   int search = 0;
115   BOOL success = False;
116   
117   putip((char *)&ip,&nmb->additional->rdata[2]);  
118   
119   DEBUG(3,("Name release on name %s\n",
120            namestr(&nmb->question.question_name)));
121   
122   if (!(d = find_req_subnet(p->ip, bcast)))
123   {
124     DEBUG(3,("response packet: bcast %s not known\n",
125                         inet_ntoa(p->ip)));
126     return;
127   }
128
129   if (bcast)
130         search &= FIND_LOCAL;
131   else
132         search &= FIND_WINS;
133
134   n = find_name_search(&d, &nmb->question.question_name, 
135                                         search, ip);
136   
137   /* XXXX under what conditions should we reject the removal?? */
138   if (n && n->nb_flags == nb_flags)
139   {
140       success = True;
141       
142       remove_name(d,n);
143       n = NULL;
144   }
145   
146   if (bcast) return;
147   
148   /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
149   send_name_response(p->fd,p->ip, nmb->header.name_trn_id, NMB_REL,
150                                                 success, False,
151                                                 &nmb->question.question_name, nb_flags, 0, ip);
152 }
153
154
155 /****************************************************************************
156 reply to a reg request
157 **************************************************************************/
158 void reply_name_reg(struct packet_struct *p)
159 {
160   struct nmb_packet *nmb = &p->packet.nmb;
161   struct nmb_name *question = &nmb->question.question_name;
162   
163   struct nmb_name *reply_name = question;
164
165   char *qname      = question->name;
166   int   qname_type = question->name_type;
167  
168   BOOL bcast = nmb->header.nm_flags.bcast;
169   
170   int ttl = GET_TTL(nmb->additional->ttl);
171   int nb_flags = nmb->additional->rdata[0];
172   BOOL group = NAME_GROUP(nb_flags);
173
174   struct subnet_record *d = NULL;
175   struct name_record *n = NULL;
176
177   BOOL success = True;
178   BOOL secured_redirect = False;
179
180   struct in_addr ip, from_ip;
181   int search = 0;
182   
183   putip((char *)&from_ip,&nmb->additional->rdata[2]);
184   ip = from_ip;
185   
186   DEBUG(3,("Name registration for name %s at %s\n",
187                    namestr(question),inet_ntoa(ip)));
188   
189   if (group)
190     {
191       /* apparently we should return 255.255.255.255 for group queries
192          (email from MS) */
193       ip = ipgrp;
194     }
195   
196   if (!(d = find_req_subnet(p->ip, bcast)))
197   {
198     DEBUG(3,("response packet: bcast %s not known\n",
199                                 inet_ntoa(p->ip)));
200     return;
201   }
202
203   if (bcast)
204         search &= FIND_LOCAL;
205   else
206         search &= FIND_WINS;
207
208   /* see if the name already exists */
209   n = find_name_search(&d, question, search, from_ip);
210   
211   if (n)
212   {
213     if (!group) /* unique names */
214         {
215           if (n->source == SELF || NAME_GROUP(n->nb_flags))
216           {
217               /* no-one can register one of samba's names, nor can they
218                  register a name that's a group name as a unique name */
219               
220               success = False;
221           }
222           else if(!ip_equal(ip, n->ip))
223           {
224               /* XXXX rfc1001.txt says:
225                * if we are doing secured WINS, we must send a Wait-Acknowledge
226                * packet (WACK) to the person who wants the name, then do a
227                * name query on the person who currently owns the unique name.
228                * if the current owner still says they own it, the person who wants
229                    * the name can't have it. if they do not, or are not alive, they can.
230                */
231
232           secured_redirect = True;
233
234               reply_name = &n->name;
235           }
236           else
237           {
238               n->ip = ip;
239               n->death_time = ttl?p->timestamp+ttl*3:0;
240               DEBUG(3,("%s owner: %s\n",namestr(&n->name),inet_ntoa(n->ip)));
241           }
242         }
243     else
244         {
245           /* refresh the name */
246           if (n->source != SELF)
247           {
248               n->death_time = ttl?p->timestamp + ttl*3:0;
249           }
250         }
251
252     /* XXXX bug reported by terryt@ren.pc.athabascau.ca */
253     /* names that people have checked for and not found get DNSFAILed. 
254        we need to update the name record if someone then registers */
255
256     if (n->source == DNSFAIL)
257       n->source = REGISTER;
258
259   }
260   else
261   {
262       /* add the name to our name/subnet, or WINS, database */
263       n = add_netbios_entry(d,qname,qname_type,nb_flags,ttl,REGISTER,ip,
264                                 True,!bcast);
265   }
266   
267   /* if samba owns a unique name on a subnet, then it must respond and
268      disallow the attempted registration. if the registration is
269      successful by broadcast, only then is there no need to respond
270      (implicit registration: see rfc1001.txt 15.2.1).
271    */
272
273   if (bcast && success) return;
274   
275   if (secured_redirect)
276   {
277     char rdata[2];
278
279     /* XXXX luke is confused. RSVAL or SSVAL? assume NMB byte ordering */
280     RSSVAL(rdata,0,(nmb->header.opcode&0xf) + ((nb_flags&0xff) << 4));
281   
282     /* XXXX mistake in rfc1002.txt? 4.2.16: NULL is 0xa see 4.2.1.3 
283        type  = 0x0a; see rfc1002.txt 4.2.1.3 
284        class = 0x01; see rfc1002.txt 4.2.16
285      */
286
287     /* send WAIT ACKNOWLEDGEMENT see rfc1002.txt 4.2.16 */
288     reply_netbios_packet(p,nmb->header.name_trn_id,
289                        0,NMB_WAIT_ACK,NMB_WAIT_ACK,False,
290                        reply_name, 0x0a, 0x01,
291                        15*1000, /* 15 seconds long enough to wait? */
292                        rdata, 2);
293
294     /* initiate some enquiries to the current owner. */
295         queue_netbios_packet(d,ClientNMB,NMB_QUERY,
296                                                  NAME_REGISTER_CHALLENGE,
297                                                  reply_name->name,reply_name->name_type,nb_flags,0,
298                                                  False, False, n->ip, p->ip);
299   }
300   else
301   {
302     /* Send a NAME REGISTRATION RESPONSE (pos/neg) see rfc1002.txt 4.2.13-14
303        or an END-NODE CHALLENGE REGISTRATION RESPONSE see rfc1002.txt 4.2.7
304      */
305
306         send_name_response(p->fd,p->ip, nmb->header.name_trn_id, NMB_REG,
307                                                 success, True,
308                                                 reply_name, nb_flags, ttl, ip);
309   }
310 }
311
312
313 /****************************************************************************
314 reply to a name status query
315 ****************************************************************************/
316 void reply_name_status(struct packet_struct *p)
317 {
318   struct nmb_packet *nmb = &p->packet.nmb;
319   char *qname   = nmb->question.question_name.name;
320   int ques_type = nmb->question.question_name.name_type;
321   char rdata[MAX_DGRAM_SIZE];
322   char *countptr, *buf, *bufend;
323   int names_added;
324   struct name_record *n;
325   struct subnet_record *d = NULL;
326   int search = FIND_SELF;
327
328   BOOL bcast = nmb->header.nm_flags.bcast;
329   
330   if (!(d = find_req_subnet(p->ip, bcast)))
331   {
332     DEBUG(3,("Name status req: bcast %s not known\n",
333                         inet_ntoa(p->ip)));
334     return;
335   }
336
337   DEBUG(3,("Name status for name %s %s\n",
338            namestr(&nmb->question.question_name), inet_ntoa(p->ip)));
339   
340   if (bcast)
341     search |= FIND_WINS;
342   else
343     search |= FIND_LOCAL;
344
345   n = find_name_search(&d, &nmb->question.question_name,
346                                 search, p->ip);
347   
348   if (!n) return;
349   
350   /* XXXX hack, we should calculate exactly how many will fit */
351   bufend = &rdata[MAX_DGRAM_SIZE] - 18;
352   countptr = buf = rdata;
353   buf += 1;
354   
355   names_added = 0;
356   
357   for (n = d->namelist ; n && buf < bufend; n = n->next) 
358     {
359       int name_type = n->name.name_type;
360       
361       if (n->source != SELF) continue;
362       
363       /* start with first bit of putting info in buffer: the name */
364       
365       bzero(buf,18);
366           sprintf(buf,"%-15.15s",n->name.name);
367       strupper(buf);
368       
369       /* now check if we want to exclude other workgroup names
370          from the response. if we don't exclude them, windows clients
371          get confused and will respond with an error for NET VIEW */
372       
373       if (name_type >= 0x1b && name_type <= 0x20 && 
374           ques_type >= 0x1b && ques_type <= 0x20)
375         {
376           if (!strequal(qname, n->name.name)) continue;
377         }
378       
379       /* carry on putting name info in buffer */
380       
381       buf[15] = name_type;
382       buf[16]  = n->nb_flags;
383       
384       buf += 18;
385       
386       names_added++;
387     }
388   
389   SCVAL(countptr,0,names_added);
390   
391   /* XXXXXXX we should fill in more fields of the statistics structure */
392   bzero(buf,64);
393   {
394     extern int num_good_sends,num_good_receives;
395     SIVAL(buf,20,num_good_sends);
396     SIVAL(buf,24,num_good_receives);
397   }
398   
399   SIVAL(buf,46,0xFFB8E5); /* undocumented - used by NT */
400   
401   buf += 64;
402   
403   /* Send a POSITIVE NAME STATUS RESPONSE */
404   reply_netbios_packet(p,nmb->header.name_trn_id,
405                            0,NMB_STATUS,0,True,
406                        &nmb->question.question_name,
407                        nmb->question.question_type,
408                        nmb->question.question_class,
409                        0,
410                        rdata,PTR_DIFF(buf,rdata));
411 }
412
413
414 /***************************************************************************
415 reply to a name query.
416
417 with broadcast name queries:
418
419         - only reply if the query is for one of YOUR names. all other machines on
420           the network will be doing the same thing (that is, only replying to a
421           broadcast query if they own it)
422           NOTE: broadcast name queries should only be sent out by a machine
423           if they HAVEN'T been configured to use WINS. this is generally bad news
424           in a wide area tcp/ip network and should be rectified by the systems
425           administrator. USE WINS! :-)
426         - the exception to this is if the query is for a Primary Domain Controller
427           type name (0x1b), in which case, a reply is sent.
428
429         - NEVER send a negative response to a broadcast query. no-one else will!
430
431 with directed name queries:
432
433         - if you are the WINS server, you are expected to respond with either
434       a negative response, a positive response, or a wait-for-acknowledgement
435       packet, and then later on a pos/neg response.
436
437 ****************************************************************************/
438 void reply_name_query(struct packet_struct *p)
439 {
440   struct nmb_packet *nmb = &p->packet.nmb;
441   struct nmb_name *question = &nmb->question.question_name;
442   int name_type = question->name_type;
443   BOOL bcast = nmb->header.nm_flags.bcast;
444   int ttl=0;
445   int rcode = 0;
446   int nb_flags = 0;
447   struct in_addr retip;
448   char rdata[6];
449   struct subnet_record *d = NULL;
450   BOOL success = True;
451   struct name_record *n;
452
453   /* directed queries are for WINS server: broadcasts are local SELF queries.
454      the exception is PDC names.  */
455
456   int search = bcast ? FIND_LOCAL | FIND_SELF : FIND_WINS;
457   
458   if (name_type == 0x1b)
459   {
460     /* even if it's a broadcast, we don't ignore queries for PDC names */
461     search = FIND_WINS;
462   }
463
464   if (search | FIND_LOCAL)
465   {
466     if (!(d = find_req_subnet(p->ip, bcast)))
467     {
468       DEBUG(3,("name query: bcast %s not known\n",
469                                     inet_ntoa(p->ip)));
470       success = False;
471     }
472   }
473   else
474   {
475     if (!(d = find_subnet(ipgrp)))
476     {
477       DEBUG(3,("name query: wins search %s not known\n",
478                                     inet_ntoa(p->ip)));
479       success = False;
480     }
481   }
482
483   DEBUG(3,("Name query "));
484   
485   if (search == 0)
486   {
487     /* eh? no criterion for searching database. help! */
488     success = False;
489   }
490
491   if (success && (n = search_for_name(&d,question,p->ip,p->timestamp, search)))
492   {
493       /* don't respond to broadcast queries unless the query is for
494          a name we own or it is for a Primary Domain Controller name */
495
496       if (bcast && n->source != SELF && name_type != 0x1b) {
497             if (!lp_wins_proxy() || same_net(p->ip,n->ip,*iface_nmask(p->ip))) {
498               /* never reply with a negative response to broadcast queries */
499               return;
500             }
501           }
502       
503       /* name is directed query, or it's self, or it's a PDC type name, or
504              we're replying on behalf of a caller because they are on a different
505          subnet and cannot hear the broadcast. XXXX lp_wins_proxy should be
506                  switched off in environments where broadcasts are forwarded */
507
508       /* XXXX note: for proxy servers, we should forward the query on to
509          another WINS server if the name is not in our database, or we are
510          not a WINS server ourselves
511        */
512       ttl = n->death_time ? n->death_time - p->timestamp : GET_TTL(0);
513       retip = n->ip;
514       nb_flags = n->nb_flags;
515   }
516   else
517   {
518       if (bcast) return; /* never reply negative response to bcasts */
519       success = False;
520   }
521   
522   /* if the IP is 0 then substitute my IP */
523   if (zero_ip(retip)) retip = *iface_ip(p->ip);
524
525   if (success)
526   {
527       rcode = 0;
528       DEBUG(3,("OK %s\n",inet_ntoa(retip)));      
529   }
530   else
531   {
532       rcode = 3;
533       DEBUG(3,("UNKNOWN\n"));      
534   }
535   
536   if (success)
537   {
538       rdata[0] = nb_flags;
539       rdata[1] = 0;
540       putip(&rdata[2],(char *)&retip);
541   }
542   
543   reply_netbios_packet(p,nmb->header.name_trn_id,
544                            rcode,NMB_QUERY,0,True,
545                        &nmb->question.question_name,
546                        nmb->question.question_type,
547                        nmb->question.question_class,
548                        ttl,
549                        rdata, success ? 6 : 0);
550 }
551
552