I've replaced the linked list used to manage the subnet namelists with a
[kai/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           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            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         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           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           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", 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           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", 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",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", 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", namestr(&nmb->question.question_name),
339           inet_ntoa(p->ip), subrec->subnet_name));
340
341     return;
342   }
343  
344   /* XXXX hack, we should calculate exactly how many will fit. */
345   bufend = &rdata[MAX_DGRAM_SIZE] - 18;
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         bzero(buf,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     qsort( buf0, names_added, 18, QSORT_CAST status_compare );
385
386     for( i=1; i < names_added ; i++ )
387     {
388       if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) 
389       {
390         names_added--;
391         if (names_added == i)
392           break;
393         memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i));
394         i--;
395       }
396     }
397
398     buf = buf0 + 18*names_added;
399
400     namerec = (struct name_record *)ubi_trNext( namerec );
401
402     if (!namerec)
403     {
404       /* End of the subnet specific name list. Now 
405          add the names on the unicast subnet . */
406       struct subnet_record *uni_subrec = unicast_subnet;
407
408       if (uni_subrec != subrec)
409       {
410         subrec = uni_subrec;
411         namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
412       }
413     }
414     if (!namerec)
415       break;
416
417   }
418   
419   SCVAL(countptr,0,names_added);
420   
421   /* We don't send any stats as they could be used to attack
422      the protocol. */
423   bzero(buf,64);
424   
425   buf += 46;
426   
427   /* Send a NODE STATUS RESPONSE */
428   reply_netbios_packet(p,                            /* Packet to reply to. */
429                        0,                            /* Result code. */
430                        NMB_STATUS,                   /* nmbd type code. */
431                        NMB_NAME_QUERY_OPCODE,        /* opcode. */
432                        0,                            /* ttl. */
433                        rdata,                        /* data to send. */
434                        PTR_DIFF(buf,rdata));         /* data length. */
435 }
436
437
438 /***************************************************************************
439 Process a name query.
440
441 For broadcast name queries:
442
443   - Only reply if the query is for one of YOUR names.
444   - NEVER send a negative response to a broadcast query.
445
446 ****************************************************************************/
447
448 void process_name_query_request(struct subnet_record *subrec, struct packet_struct *p)
449 {
450   struct nmb_packet *nmb = &p->packet.nmb;
451   struct nmb_name *question = &nmb->question.question_name;
452   int name_type = question->name_type;
453   BOOL bcast = nmb->header.nm_flags.bcast;
454   int ttl=0;
455   int rcode = 0;
456   char *prdata = NULL;
457   char rdata[6];
458   BOOL success = False;
459   struct name_record *namerec = NULL;
460   int reply_data_len = 0;
461   int i;
462  
463   DEBUG(3,("process_name_query_request: Name query from %s on subnet %s for name %s\n", 
464             inet_ntoa(p->ip), subrec->subnet_name, namestr(question)));
465   
466   /* Look up the name in the cache - if the request is a broadcast request that
467      came from a subnet we don't know about then search all the broadcast subnets
468      for a match (as we don't know what interface the request came in on). */
469
470   if(subrec == remote_broadcast_subnet)
471     namerec = find_name_for_remote_broadcast_subnet( question, FIND_ANY_NAME);
472   else
473     namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
474
475
476   /* Check if it is a name that expired */
477   if( namerec
478    && ( (namerec->data.death_time != PERMANENT_TTL)
479      && (namerec->data.death_time < p->timestamp) ) )
480   {
481     DEBUG(5,("process_name_query_request: expired name %s\n", namestr(&namerec->name)));
482     namerec = NULL;
483   }
484
485   if (namerec)
486   {
487
488     /* 
489      * Always respond to unicast queries.
490      * Don't respond to broadcast queries unless the query is for
491      * a name we own, a Primary Domain Controller name, or a WINS_PROXY 
492      * name with type 0 or 0x20. WINS_PROXY names are only ever added
493      * into the namelist if we were configured as a WINS proxy.
494      */
495
496     if( !bcast
497      || ( bcast
498        && ( (name_type == 0x1b)
499          || (namerec->data.source == SELF_NAME)
500          || (namerec->data.source == PERMANENT_NAME)
501          || ( (namerec->data.source == WINS_PROXY_NAME)
502            && ( (name_type == 0) || (name_type == 0x20) ) 
503             )
504           )
505         )
506       )
507     {
508       
509       /* The requested name is a directed query, or it's SELF or PERMANENT or WINS_PROXY, 
510          or it's a Domain Master type. */
511
512       /*
513        * If this is a WINS_PROXY_NAME, then ceck that none of the IP 
514        * addresses we are returning is on the same broadcast subnet 
515        * as the requesting packet. If it is then don't reply as the 
516        * actual machine will be replying also and we don't want two 
517        * replies to a broadcast query.
518        */
519
520       if( namerec->data.source == WINS_PROXY_NAME )
521       {
522         for( i = 0; i < namerec->data.num_ips; i++)
523         {
524           if(same_net( namerec->data.ip[i], subrec->myip, subrec->mask_ip ))    
525           {
526             DEBUG(5,("process_name_query_request: name %s is a WINS proxy name and is also \
527 on the same subnet (%s) as the requestor. Not replying.\n", 
528                    namestr(&namerec->name), subrec->subnet_name ));
529             return;
530           }
531         }   
532       }     
533
534       ttl = (namerec->data.death_time != PERMANENT_TTL) ?
535                      namerec->data.death_time - p->timestamp : lp_max_ttl();
536
537       /* Copy all known ip addresses into the return data. */
538       /* Optimise for the common case of one IP address so 
539          we don't need a malloc. */
540
541       if( namerec->data.num_ips == 1 )
542         prdata = rdata;
543       else
544       {
545         if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL)
546         {
547           DEBUG(0,("process_name_query_request: malloc fail !\n"));
548           return;
549         }
550       }
551
552       for( i = 0; i < namerec->data.num_ips; i++ )
553       {
554         set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
555         putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
556       }
557       reply_data_len = namerec->data.num_ips * 6;
558       success = True;
559     }
560   }
561
562   /*
563    * If a machine is broadcasting a name lookup request and we have lp_wins_proxy()
564    * set we should initiate a WINS query here. On success we add the resolved name 
565    * into our namelist with a type of WINS_PROXY_NAME and then reply to the query.
566    */
567
568   if(!success && (namerec == NULL) && we_are_a_wins_client() && lp_wins_proxy() && 
569      bcast && (subrec != remote_broadcast_subnet))
570   {
571     make_wins_proxy_name_query_request( subrec, p, question );
572     return;
573   }
574
575   if (!success && bcast)
576   {
577     if((prdata != rdata) && (prdata != NULL))
578       free(rdata);
579     return; /* Never reply with a negative response to broadcasts. */
580   }
581
582   /* 
583    * Final check. From observation, if a unicast packet is sent
584    * to a non-WINS server with the recursion desired bit set
585    * then never send a negative response.
586    */
587
588   if(!success && !bcast && nmb->header.nm_flags.recursion_desired)
589   {
590     if((prdata != rdata) && (prdata != NULL))
591       free(rdata);
592     return;
593   }
594
595   if (success)
596   {
597       rcode = 0;
598       DEBUG(3,("OK\n"));
599   }
600   else
601   {
602       rcode = NAM_ERR;
603       DEBUG(3,("UNKNOWN\n"));      
604   }
605
606   /* See rfc1002.txt 4.2.13. */
607
608   reply_netbios_packet(p,                              /* Packet to reply to. */
609                        rcode,                          /* Result code. */
610                        NMB_QUERY,                      /* nmbd type code. */
611                        NMB_NAME_QUERY_OPCODE,          /* opcode. */
612                        ttl,                            /* ttl. */
613                        prdata,                         /* data to send. */
614                        reply_data_len);                /* data length. */
615
616   if((prdata != rdata) && (prdata != NULL))
617     free(prdata);
618 }