Removed version number from file header.
[kai/samba.git] / source3 / nmbd / nmbd_incomingrequests.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    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    This file contains all the code to process NetBIOS requests coming
23    in on port 137. It does not deal with the code needed to service
24    WINS server requests, but only broadcast and unicast requests.
25
26 */
27
28 #include "includes.h"
29
30 extern fstring global_myworkgroup;
31
32 /****************************************************************************
33 Send a name release response.
34 **************************************************************************/
35
36 static void send_name_release_response(int rcode, struct packet_struct *p)
37 {
38   struct nmb_packet *nmb = &p->packet.nmb;
39   char rdata[6];
40
41   memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
42   
43   reply_netbios_packet(p,                            /* Packet to reply to. */
44                        rcode,                        /* Result code. */
45                        NMB_REL,                      /* nmbd type code. */
46                        NMB_NAME_RELEASE_OPCODE,      /* opcode. */
47                        0,                            /* ttl. */
48                        rdata,                        /* data to send. */
49                        6);                           /* data length. */
50 }
51
52 /****************************************************************************
53 Process a name release packet on a broadcast subnet.
54 Ignore it if it's not one of our names.
55 ****************************************************************************/
56
57 void process_name_release_request(struct subnet_record *subrec, 
58                                   struct packet_struct *p)
59 {
60   struct nmb_packet *nmb = &p->packet.nmb;
61   struct in_addr owner_ip;
62   struct nmb_name *question = &nmb->question.question_name;
63   BOOL bcast = nmb->header.nm_flags.bcast;
64   uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
65   BOOL group = (nb_flags & NB_GROUP) ? True : False;
66   struct name_record *namerec;
67   int rcode = 0;
68   
69   putip((char *)&owner_ip,&nmb->additional->rdata[2]);  
70   
71   if(!bcast)
72   {
73     /* We should only get broadcast name release packets here.
74        Anyone trying to release unicast should be going to a WINS
75        server. If the code gets here, then either we are not a wins
76        server and they sent it anyway, or we are a WINS server and
77        the request was malformed. Either way, log an error here.
78        and send an error reply back.
79      */
80     DEBUG(0,("process_name_release_request: unicast name release request \
81 received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
82           nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name));      
83
84     send_name_release_response(FMT_ERR, p);
85     return;
86   }
87
88   DEBUG(3,("process_name_release_request: Name release on name %s, \
89 subnet %s from owner IP %s\n",
90            nmb_namestr(&nmb->question.question_name),
91            subrec->subnet_name, inet_ntoa(owner_ip)));
92   
93   /* If someone is releasing a broadcast group name, just ignore it. */
94   if( group && !ismyip(owner_ip) )
95     return;
96
97   /*
98    * Code to work around a bug in FTP OnNet software NBT implementation.
99    * They do a broadcast name release for WORKGROUP<0> and WORKGROUP<1e>
100    * names and *don't set the group bit* !!!!!
101    */
102
103   if( !group && !ismyip(owner_ip) && strequal(question->name, global_myworkgroup) && 
104       ((question->name_type == 0x0) || (question->name_type == 0x1e)))
105   {
106     DEBUG(6,("process_name_release_request: FTP OnNet bug workaround. Ignoring \
107 group release name %s from IP %s on subnet %s with no group bit set.\n",
108         nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name ));
109     return;
110   }
111
112   namerec = find_name_on_subnet(subrec, &nmb->question.question_name, FIND_ANY_NAME);
113
114   /* We only care about someone trying to release one of our names. */
115   if( namerec
116    && ( (namerec->data.source == SELF_NAME)
117      || (namerec->data.source == PERMANENT_NAME) ) )
118   {
119     rcode = ACT_ERR;
120     DEBUG(0, ("process_name_release_request: Attempt to release name %s from IP %s \
121 on subnet %s being rejected as it is one of our names.\n", 
122           nmb_namestr(&nmb->question.question_name), inet_ntoa(owner_ip), subrec->subnet_name));
123   }
124
125   if(rcode == 0)
126     return;
127
128   /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
129   send_name_release_response(rcode, p);
130 }
131
132 /****************************************************************************
133 Send a name registration response.
134 **************************************************************************/
135
136 static void send_name_registration_response(int rcode, int ttl, struct packet_struct *p)
137 {
138   struct nmb_packet *nmb = &p->packet.nmb;
139   char rdata[6];
140
141   memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
142   
143   reply_netbios_packet(p,                             /* Packet to reply to. */
144                        rcode,                         /* Result code. */
145                        NMB_REG,                       /* nmbd type code. */
146                        NMB_NAME_REG_OPCODE,           /* opcode. */
147                        ttl,                           /* ttl. */
148                        rdata,                         /* data to send. */
149                        6);                            /* data length. */
150 }
151
152 /****************************************************************************
153 Process a name refresh request on a broadcast subnet.
154 **************************************************************************/
155      
156 void process_name_refresh_request(struct subnet_record *subrec,
157                                   struct packet_struct *p)
158 {    
159      
160   struct nmb_packet *nmb = &p->packet.nmb;
161   struct nmb_name *question = &nmb->question.question_name;
162   BOOL bcast = nmb->header.nm_flags.bcast;
163   struct in_addr from_ip;
164   
165   putip((char *)&from_ip,&nmb->additional->rdata[2]);
166
167   if(!bcast)
168   { 
169     /* We should only get broadcast name refresh packets here.
170        Anyone trying to refresh unicast should be going to a WINS
171        server. If the code gets here, then either we are not a wins
172        server and they sent it anyway, or we are a WINS server and
173        the request was malformed. Either way, log an error here.
174        and send an error reply back.
175      */
176     DEBUG(0,("process_name_refresh_request: unicast name registration request \
177 received for name %s from IP %s on subnet %s.\n",
178           nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
179     DEBUG(0,("Error - should be sent to WINS server\n"));
180     
181     send_name_registration_response(FMT_ERR, 0, p);
182     return;
183   } 
184
185   /* Just log a message. We really don't care about broadcast name
186      refreshes. */
187      
188   DEBUG(3,("process_name_refresh_request: Name refresh for name %s \
189 IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
190      
191 }
192     
193 /****************************************************************************
194 Process a name registration request on a broadcast subnet.
195 **************************************************************************/
196
197 void process_name_registration_request(struct subnet_record *subrec, 
198                                        struct packet_struct *p)
199 {
200   struct nmb_packet *nmb = &p->packet.nmb;
201   struct nmb_name *question = &nmb->question.question_name;
202   BOOL bcast = nmb->header.nm_flags.bcast;
203   uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
204   BOOL group = (nb_flags & NB_GROUP) ? True : False;
205   struct name_record *namerec = NULL;
206   int ttl = nmb->additional->ttl;
207   struct in_addr from_ip;
208   
209   putip((char *)&from_ip,&nmb->additional->rdata[2]);
210   
211   if(!bcast)
212   {
213     /* We should only get broadcast name registration packets here.
214        Anyone trying to register unicast should be going to a WINS
215        server. If the code gets here, then either we are not a wins
216        server and they sent it anyway, or we are a WINS server and
217        the request was malformed. Either way, log an error here.
218        and send an error reply back.
219      */
220     DEBUG(0,("process_name_registration_request: unicast name registration request \
221 received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
222           nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));      
223
224     send_name_registration_response(FMT_ERR, 0, p);
225     return;
226   }
227
228   DEBUG(3,("process_name_registration_request: Name registration for name %s \
229 IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
230   
231   /* See if the name already exists. */
232   namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
233  
234   /* 
235    * If the name being registered exists and is a WINS_PROXY_NAME 
236    * then delete the WINS proxy name entry so we don't reply erroneously
237    * later to queries.
238    */
239
240   if((namerec != NULL) && (namerec->data.source == WINS_PROXY_NAME))
241   {
242     remove_name_from_namelist( subrec, namerec );
243     namerec = NULL;
244   }
245
246   if (!group)
247   {
248     /* Unique name. */
249
250     if( (namerec != NULL)
251      && ( (namerec->data.source == SELF_NAME)
252        || (namerec->data.source == PERMANENT_NAME)
253        || NAME_GROUP(namerec) ) )
254     {
255       /* No-one can register one of Samba's names, nor can they
256          register a name that's a group name as a unique name */
257
258       send_name_registration_response(ACT_ERR, 0, p);
259       return;
260     }
261     else if(namerec != NULL)
262     {
263       /* Update the namelist record with the new information. */
264       namerec->data.ip[0] = from_ip;
265       update_name_ttl(namerec, ttl);
266
267       DEBUG(3,("process_name_registration_request: Updated name record %s \
268 with IP %s on subnet %s\n",nmb_namestr(&namerec->name),inet_ntoa(from_ip), subrec->subnet_name));
269       return;
270     }
271   }
272   else
273   {
274     /* Group name. */
275
276     if( (namerec != NULL)
277      && !NAME_GROUP(namerec)
278      && ( (namerec->data.source == SELF_NAME)
279        || (namerec->data.source == PERMANENT_NAME) ) )
280     {
281       /* Disallow group names when we have a unique name. */
282       send_name_registration_response(ACT_ERR, 0, p);  
283       return;  
284     }  
285   }
286 }
287
288 /****************************************************************************
289 This is used to sort names for a name status into a sensible order.
290 We put our own names first, then in alphabetical order.
291 **************************************************************************/
292
293 static int status_compare(char *n1,char *n2)
294 {
295   extern pstring global_myname;
296   int l1,l2,l3;
297
298   /* It's a bit tricky because the names are space padded */
299   for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++) ;
300   for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++) ;
301   l3 = strlen(global_myname);
302
303   if ((l1==l3) && strncmp(n1,global_myname,l3) == 0 && 
304       (l2!=l3 || strncmp(n2,global_myname,l3) != 0))
305     return -1;
306
307   if ((l2==l3) && strncmp(n2,global_myname,l3) == 0 && 
308       (l1!=l3 || strncmp(n1,global_myname,l3) != 0))
309     return 1;
310
311   return memcmp(n1,n2,18);
312 }
313
314
315 /****************************************************************************
316   Process a node status query
317   ****************************************************************************/
318
319 void process_node_status_request(struct subnet_record *subrec, struct packet_struct *p)
320 {
321   struct nmb_packet *nmb = &p->packet.nmb;
322   char *qname   = nmb->question.question_name.name;
323   int ques_type = nmb->question.question_name.name_type;
324   char rdata[MAX_DGRAM_SIZE];
325   char *countptr, *buf, *bufend, *buf0;
326   int names_added,i;
327   struct name_record *namerec;
328
329   DEBUG(3,("process_node_status_request: status request for name %s from IP %s on \
330 subnet %s.\n", nmb_namestr(&nmb->question.question_name), inet_ntoa(p->ip),
331           subrec->subnet_name));
332
333   if((namerec = find_name_on_subnet(subrec, &nmb->question.question_name,
334                                     FIND_SELF_NAME)) == 0)
335   {
336     DEBUG(1,("process_node_status_request: status request for name %s from IP %s on \
337 subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
338           inet_ntoa(p->ip), subrec->subnet_name));
339
340     return;
341   }
342  
343   /* this is not an exact calculation. the 46 is for the stats buffer
344      and the 60 is to leave room for the header etc */
345   bufend = &rdata[MAX_DGRAM_SIZE] - (18 + 46 + 60);
346   countptr = buf = rdata;
347   buf += 1;
348   buf0 = buf;
349
350   names_added = 0;
351
352   namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
353
354   while (buf < bufend) 
355   {
356     if( (namerec->data.source == SELF_NAME)
357      || (namerec->data.source == PERMANENT_NAME) )
358     {
359       int name_type = namerec->name.name_type;
360       
361       if (!strequal(namerec->name.name,"*") &&
362           !strequal(namerec->name.name,"__SAMBA__") &&
363           (name_type < 0x1b || name_type >= 0x20 || 
364            ques_type < 0x1b || ques_type >= 0x20 ||
365            strequal(qname, namerec->name.name)))
366       {
367         /* Start with the name. */
368         memset(buf,'\0',18);
369         slprintf(buf, 17, "%-15.15s",namerec->name.name);
370         strupper(buf);
371         
372         /* Put the name type and netbios flags in the buffer. */
373         buf[15] = name_type;
374         set_nb_flags( &buf[16],namerec->data.nb_flags );
375         buf[16] |= NB_ACTIVE; /* all our names are active */
376
377         buf += 18;
378
379         names_added++;
380       }
381     }
382
383     /* Remove duplicate names. */
384     if (names_added > 1) {
385             qsort( buf0, names_added, 18, QSORT_CAST status_compare );
386     }
387
388     for( i=1; i < names_added ; i++ )
389     {
390       if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) 
391       {
392         names_added--;
393         if (names_added == i)
394           break;
395         memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i));
396         i--;
397       }
398     }
399
400     buf = buf0 + 18*names_added;
401
402     namerec = (struct name_record *)ubi_trNext( namerec );
403
404     if (!namerec)
405     {
406       /* End of the subnet specific name list. Now 
407          add the names on the unicast subnet . */
408       struct subnet_record *uni_subrec = unicast_subnet;
409
410       if (uni_subrec != subrec)
411       {
412         subrec = uni_subrec;
413         namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
414       }
415     }
416     if (!namerec)
417       break;
418
419   }
420   
421   SCVAL(countptr,0,names_added);
422   
423   /* We don't send any stats as they could be used to attack
424      the protocol. */
425   memset(buf,'\0',46);
426   
427   buf += 46;
428   
429   /* Send a NODE STATUS RESPONSE */
430   reply_netbios_packet(p,                            /* Packet to reply to. */
431                        0,                            /* Result code. */
432                        NMB_STATUS,                   /* nmbd type code. */
433                        NMB_NAME_QUERY_OPCODE,        /* opcode. */
434                        0,                            /* ttl. */
435                        rdata,                        /* data to send. */
436                        PTR_DIFF(buf,rdata));         /* data length. */
437 }
438
439
440 /***************************************************************************
441 Process a name query.
442
443 For broadcast name queries:
444
445   - Only reply if the query is for one of YOUR names.
446   - NEVER send a negative response to a broadcast query.
447
448 ****************************************************************************/
449
450 void process_name_query_request(struct subnet_record *subrec, struct packet_struct *p)
451 {
452   struct nmb_packet *nmb = &p->packet.nmb;
453   struct nmb_name *question = &nmb->question.question_name;
454   int name_type = question->name_type;
455   BOOL bcast = nmb->header.nm_flags.bcast;
456   int ttl=0;
457   int rcode = 0;
458   char *prdata = NULL;
459   char rdata[6];
460   BOOL success = False;
461   struct name_record *namerec = NULL;
462   int reply_data_len = 0;
463   int i;
464  
465   DEBUG(3,("process_name_query_request: Name query from %s on subnet %s for name %s\n", 
466             inet_ntoa(p->ip), subrec->subnet_name, nmb_namestr(question)));
467   
468   /* Look up the name in the cache - if the request is a broadcast request that
469      came from a subnet we don't know about then search all the broadcast subnets
470      for a match (as we don't know what interface the request came in on). */
471
472   if(subrec == remote_broadcast_subnet)
473     namerec = find_name_for_remote_broadcast_subnet( question, FIND_ANY_NAME);
474   else
475     namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
476
477
478   /* Check if it is a name that expired */
479   if( namerec
480    && ( (namerec->data.death_time != PERMANENT_TTL)
481      && (namerec->data.death_time < p->timestamp) ) )
482   {
483     DEBUG(5,("process_name_query_request: expired name %s\n", nmb_namestr(&namerec->name)));
484     namerec = NULL;
485   }
486
487   if (namerec)
488   {
489
490     /* 
491      * Always respond to unicast queries.
492      * Don't respond to broadcast queries unless the query is for
493      * a name we own, a Primary Domain Controller name, or a WINS_PROXY 
494      * name with type 0 or 0x20. WINS_PROXY names are only ever added
495      * into the namelist if we were configured as a WINS proxy.
496      */
497
498     if( !bcast
499      || ( bcast
500        && ( (name_type == 0x1b)
501          || (namerec->data.source == SELF_NAME)
502          || (namerec->data.source == PERMANENT_NAME)
503          || ( (namerec->data.source == WINS_PROXY_NAME)
504            && ( (name_type == 0) || (name_type == 0x20) ) 
505             )
506           )
507         )
508       )
509     {
510       
511       /* The requested name is a directed query, or it's SELF or PERMANENT or WINS_PROXY, 
512          or it's a Domain Master type. */
513
514       /*
515        * If this is a WINS_PROXY_NAME, then ceck that none of the IP 
516        * addresses we are returning is on the same broadcast subnet 
517        * as the requesting packet. If it is then don't reply as the 
518        * actual machine will be replying also and we don't want two 
519        * replies to a broadcast query.
520        */
521
522       if( namerec->data.source == WINS_PROXY_NAME )
523       {
524         for( i = 0; i < namerec->data.num_ips; i++)
525         {
526           if(same_net( namerec->data.ip[i], subrec->myip, subrec->mask_ip ))    
527           {
528             DEBUG(5,("process_name_query_request: name %s is a WINS proxy name and is also \
529 on the same subnet (%s) as the requestor. Not replying.\n", 
530                    nmb_namestr(&namerec->name), subrec->subnet_name ));
531             return;
532           }
533         }   
534       }     
535
536       ttl = (namerec->data.death_time != PERMANENT_TTL) ?
537                      namerec->data.death_time - p->timestamp : lp_max_ttl();
538
539       /* Copy all known ip addresses into the return data. */
540       /* Optimise for the common case of one IP address so 
541          we don't need a malloc. */
542
543       if( namerec->data.num_ips == 1 )
544         prdata = rdata;
545       else
546       {
547         if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL)
548         {
549           DEBUG(0,("process_name_query_request: malloc fail !\n"));
550           return;
551         }
552       }
553
554       for( i = 0; i < namerec->data.num_ips; i++ )
555       {
556         set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
557         putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
558       }
559
560       sort_query_replies(prdata, i, p->ip);
561       
562       reply_data_len = namerec->data.num_ips * 6;
563       success = True;
564     }
565   }
566
567   /*
568    * If a machine is broadcasting a name lookup request and we have lp_wins_proxy()
569    * set we should initiate a WINS query here. On success we add the resolved name 
570    * into our namelist with a type of WINS_PROXY_NAME and then reply to the query.
571    */
572
573   if(!success && (namerec == NULL) && we_are_a_wins_client() && lp_wins_proxy() && 
574      bcast && (subrec != remote_broadcast_subnet))
575   {
576     make_wins_proxy_name_query_request( subrec, p, question );
577     return;
578   }
579
580   if (!success && bcast)
581   {
582     if(prdata != rdata)
583       SAFE_FREE(prdata);
584     return; /* Never reply with a negative response to broadcasts. */
585   }
586
587   /* 
588    * Final check. From observation, if a unicast packet is sent
589    * to a non-WINS server with the recursion desired bit set
590    * then never send a negative response.
591    */
592
593   if(!success && !bcast && nmb->header.nm_flags.recursion_desired)
594   {
595     if(prdata != rdata)
596       SAFE_FREE(prdata);
597     return;
598   }
599
600   if (success)
601   {
602       rcode = 0;
603       DEBUG(3,("OK\n"));
604   }
605   else
606   {
607       rcode = NAM_ERR;
608       DEBUG(3,("UNKNOWN\n"));      
609   }
610
611   /* See rfc1002.txt 4.2.13. */
612
613   reply_netbios_packet(p,                              /* Packet to reply to. */
614                        rcode,                          /* Result code. */
615                        NMB_QUERY,                      /* nmbd type code. */
616                        NMB_NAME_QUERY_OPCODE,          /* opcode. */
617                        ttl,                            /* ttl. */
618                        prdata,                         /* data to send. */
619                        reply_data_len);                /* data length. */
620
621   if(prdata != rdata)
622     SAFE_FREE(prdata);
623 }