dnscrypto-proxy: Support files updated.
[tomato.git] / release / src / router / samba / source / nmbd / nmbd_incomingrequests.c
blob7c46204445c20487e1ce19c940764be0622b460d
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
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.
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.
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.
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.
29 #include "includes.h"
31 extern int DEBUGLEVEL;
32 extern fstring global_myworkgroup;
34 /****************************************************************************
35 Send a name release response.
36 **************************************************************************/
38 static void send_name_release_response(int rcode, struct packet_struct *p)
40 struct nmb_packet *nmb = &p->packet.nmb;
41 char rdata[6];
43 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
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. */
54 /****************************************************************************
55 Process a name release packet on a broadcast subnet.
56 Ignore it if it's not one of our names.
57 ****************************************************************************/
59 void process_name_release_request(struct subnet_record *subrec,
60 struct packet_struct *p)
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;
71 putip((char *)&owner_ip,&nmb->additional->rdata[2]);
73 if(!bcast)
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.
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));
86 send_name_release_response(FMT_ERR, p);
87 return;
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)));
95 /* If someone is releasing a broadcast group name, just ignore it. */
96 if( group && !ismyip(owner_ip) )
97 return;
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* !!!!!
105 if( !group && !ismyip(owner_ip) && strequal(question->name, global_myworkgroup) &&
106 ((question->name_type == 0x0) || (question->name_type == 0x1e)))
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;
114 namerec = find_name_on_subnet(subrec, &nmb->question.question_name, FIND_ANY_NAME);
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) ) )
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));
127 if(rcode == 0)
128 return;
130 /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
131 send_name_release_response(rcode, p);
134 /****************************************************************************
135 Send a name registration response.
136 **************************************************************************/
138 static void send_name_registration_response(int rcode, int ttl, struct packet_struct *p)
140 struct nmb_packet *nmb = &p->packet.nmb;
141 char rdata[6];
143 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
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. */
154 /****************************************************************************
155 Process a name refresh request on a broadcast subnet.
156 **************************************************************************/
158 void process_name_refresh_request(struct subnet_record *subrec,
159 struct packet_struct *p)
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;
167 putip((char *)&from_ip,&nmb->additional->rdata[2]);
169 if(!bcast)
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.
178 DEBUG(0,("process_name_refresh_request: unicast name registration request \
179 received for name %s from IP %s on subnet %s.\n",
180 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
181 DEBUG(0,("Error - should be sent to WINS server\n"));
183 send_name_registration_response(FMT_ERR, 0, p);
184 return;
187 /* Just log a message. We really don't care about broadcast name
188 refreshes. */
190 DEBUG(3,("process_name_refresh_request: Name refresh for name %s \
191 IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
195 /****************************************************************************
196 Process a name registration request on a broadcast subnet.
197 **************************************************************************/
199 void process_name_registration_request(struct subnet_record *subrec,
200 struct packet_struct *p)
202 struct nmb_packet *nmb = &p->packet.nmb;
203 struct nmb_name *question = &nmb->question.question_name;
204 BOOL bcast = nmb->header.nm_flags.bcast;
205 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
206 BOOL group = (nb_flags & NB_GROUP) ? True : False;
207 struct name_record *namerec = NULL;
208 int ttl = nmb->additional->ttl;
209 struct in_addr from_ip;
211 putip((char *)&from_ip,&nmb->additional->rdata[2]);
213 if(!bcast)
215 /* We should only get broadcast name registration packets here.
216 Anyone trying to register unicast should be going to a WINS
217 server. If the code gets here, then either we are not a wins
218 server and they sent it anyway, or we are a WINS server and
219 the request was malformed. Either way, log an error here.
220 and send an error reply back.
222 DEBUG(0,("process_name_registration_request: unicast name registration request \
223 received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
224 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
226 send_name_registration_response(FMT_ERR, 0, p);
227 return;
230 DEBUG(3,("process_name_registration_request: Name registration for name %s \
231 IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
233 /* See if the name already exists. */
234 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
237 * If the name being registered exists and is a WINS_PROXY_NAME
238 * then delete the WINS proxy name entry so we don't reply erroneously
239 * later to queries.
242 if((namerec != NULL) && (namerec->data.source == WINS_PROXY_NAME))
244 remove_name_from_namelist( subrec, namerec );
245 namerec = NULL;
248 if (!group)
250 /* Unique name. */
252 if( (namerec != NULL)
253 && ( (namerec->data.source == SELF_NAME)
254 || (namerec->data.source == PERMANENT_NAME)
255 || NAME_GROUP(namerec) ) )
257 /* No-one can register one of Samba's names, nor can they
258 register a name that's a group name as a unique name */
260 send_name_registration_response(ACT_ERR, 0, p);
261 return;
263 else if(namerec != NULL)
265 /* Update the namelist record with the new information. */
266 namerec->data.ip[0] = from_ip;
267 update_name_ttl(namerec, ttl);
269 DEBUG(3,("process_name_registration_request: Updated name record %s \
270 with IP %s on subnet %s\n",nmb_namestr(&namerec->name),inet_ntoa(from_ip), subrec->subnet_name));
271 return;
274 else
276 /* Group name. */
278 if( (namerec != NULL)
279 && !NAME_GROUP(namerec)
280 && ( (namerec->data.source == SELF_NAME)
281 || (namerec->data.source == PERMANENT_NAME) ) )
283 /* Disallow group names when we have a unique name. */
284 send_name_registration_response(ACT_ERR, 0, p);
285 return;
290 /****************************************************************************
291 This is used to sort names for a name status into a sensible order.
292 We put our own names first, then in alphabetical order.
293 **************************************************************************/
295 static int status_compare(char *n1,char *n2)
297 extern pstring global_myname;
298 int l1,l2,l3;
300 /* It's a bit tricky because the names are space padded */
301 for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++) ;
302 for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++) ;
303 l3 = strlen(global_myname);
305 if ((l1==l3) && strncmp(n1,global_myname,l3) == 0 &&
306 (l2!=l3 || strncmp(n2,global_myname,l3) != 0))
307 return -1;
309 if ((l2==l3) && strncmp(n2,global_myname,l3) == 0 &&
310 (l1!=l3 || strncmp(n1,global_myname,l3) != 0))
311 return 1;
313 return memcmp(n1,n2,18);
317 /****************************************************************************
318 Process a node status query
319 ****************************************************************************/
321 void process_node_status_request(struct subnet_record *subrec, struct packet_struct *p)
323 struct nmb_packet *nmb = &p->packet.nmb;
324 char *qname = nmb->question.question_name.name;
325 int ques_type = nmb->question.question_name.name_type;
326 char rdata[MAX_DGRAM_SIZE];
327 char *countptr, *buf, *bufend, *buf0;
328 int names_added,i;
329 struct name_record *namerec;
331 DEBUG(3,("process_node_status_request: status request for name %s from IP %s on \
332 subnet %s.\n", nmb_namestr(&nmb->question.question_name), inet_ntoa(p->ip),
333 subrec->subnet_name));
335 if((namerec = find_name_on_subnet(subrec, &nmb->question.question_name,
336 FIND_SELF_NAME)) == 0)
338 DEBUG(1,("process_node_status_request: status request for name %s from IP %s on \
339 subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
340 inet_ntoa(p->ip), subrec->subnet_name));
342 return;
345 /* this is not an exact calculation. the 46 is for the stats buffer
346 and the 60 is to leave room for the header etc */
347 bufend = &rdata[MAX_DGRAM_SIZE] - (18 + 46 + 60);
348 countptr = buf = rdata;
349 buf += 1;
350 buf0 = buf;
352 names_added = 0;
354 namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
356 while (buf < bufend)
358 if( (namerec->data.source == SELF_NAME)
359 || (namerec->data.source == PERMANENT_NAME) )
361 int name_type = namerec->name.name_type;
363 if (!strequal(namerec->name.name,"*") &&
364 !strequal(namerec->name.name,"__SAMBA__") &&
365 (name_type < 0x1b || name_type >= 0x20 ||
366 ques_type < 0x1b || ques_type >= 0x20 ||
367 strequal(qname, namerec->name.name)))
369 /* Start with the name. */
370 memset(buf,'\0',18);
371 slprintf(buf, 17, "%-15.15s",namerec->name.name);
372 strupper(buf);
374 /* Put the name type and netbios flags in the buffer. */
375 buf[15] = name_type;
376 set_nb_flags( &buf[16],namerec->data.nb_flags );
377 buf[16] |= NB_ACTIVE; /* all our names are active */
379 buf += 18;
381 names_added++;
385 /* Remove duplicate names. */
386 qsort( buf0, names_added, 18, QSORT_CAST status_compare );
388 for( i=1; i < names_added ; i++ )
390 if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0)
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--;
400 buf = buf0 + 18*names_added;
402 namerec = (struct name_record *)ubi_trNext( namerec );
404 if (!namerec)
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;
410 if (uni_subrec != subrec)
412 subrec = uni_subrec;
413 namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
416 if (!namerec)
417 break;
421 SCVAL(countptr,0,names_added);
423 /* We don't send any stats as they could be used to attack
424 the protocol. */
425 memset(buf,'\0',46);
427 buf += 46;
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. */
440 /***************************************************************************
441 Process a name query.
443 For broadcast name queries:
445 - Only reply if the query is for one of YOUR names.
446 - NEVER send a negative response to a broadcast query.
448 ****************************************************************************/
450 void process_name_query_request(struct subnet_record *subrec, struct packet_struct *p)
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;
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)));
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). */
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);
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) ) )
483 DEBUG(5,("process_name_query_request: expired name %s\n", nmb_namestr(&namerec->name)));
484 namerec = NULL;
487 if (namerec)
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.
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) )
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. */
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.
522 if( namerec->data.source == WINS_PROXY_NAME )
524 for( i = 0; i < namerec->data.num_ips; i++)
526 if(same_net( namerec->data.ip[i], subrec->myip, subrec->mask_ip ))
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;
536 ttl = (namerec->data.death_time != PERMANENT_TTL) ?
537 namerec->data.death_time - p->timestamp : lp_max_ttl();
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. */
543 if( namerec->data.num_ips == 1 )
544 prdata = rdata;
545 else
547 if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL)
549 DEBUG(0,("process_name_query_request: malloc fail !\n"));
550 return;
554 for( i = 0; i < namerec->data.num_ips; i++ )
556 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
557 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
560 sort_query_replies(prdata, i, p->ip);
562 reply_data_len = namerec->data.num_ips * 6;
563 success = True;
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.
573 if(!success && (namerec == NULL) && we_are_a_wins_client() && lp_wins_proxy() &&
574 bcast && (subrec != remote_broadcast_subnet))
576 make_wins_proxy_name_query_request( subrec, p, question );
577 return;
580 if (!success && bcast)
582 if((prdata != rdata) && (prdata != NULL))
583 free(prdata);
584 return; /* Never reply with a negative response to broadcasts. */
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.
593 if(!success && !bcast && nmb->header.nm_flags.recursion_desired)
595 if((prdata != rdata) && (prdata != NULL))
596 free(prdata);
597 return;
600 if (success)
602 rcode = 0;
603 DEBUG(3,("OK\n"));
605 else
607 rcode = NAM_ERR;
608 DEBUG(3,("UNKNOWN\n"));
611 /* See rfc1002.txt 4.2.13. */
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. */
621 if((prdata != rdata) && (prdata != NULL))
622 free(prdata);