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