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