fix typo for callback bit
[Samba/nascimento.git] / source3 / nmbd / nmbd_incomingrequests.c
blobdd999fbdf774832e21da6741e497700aad753410
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
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file contains all the code to process NetBIOS requests coming
23 in on port 137. It does not deal with the code needed to service
24 WINS server requests, but only broadcast and unicast requests.
28 #include "includes.h"
30 /****************************************************************************
31 Send a name release response.
32 **************************************************************************/
34 static void send_name_release_response(int rcode, struct packet_struct *p)
36 struct nmb_packet *nmb = &p->packet.nmb;
37 char rdata[6];
39 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
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. */
50 /****************************************************************************
51 Process a name release packet on a broadcast subnet.
52 Ignore it if it's not one of our names.
53 ****************************************************************************/
55 void process_name_release_request(struct subnet_record *subrec,
56 struct packet_struct *p)
58 struct nmb_packet *nmb = &p->packet.nmb;
59 struct in_addr owner_ip;
60 struct nmb_name *question = &nmb->question.question_name;
61 nstring 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;
68 putip((char *)&owner_ip,&nmb->additional->rdata[2]);
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.
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));
82 send_name_release_response(FMT_ERR, p);
83 return;
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)));
91 /* If someone is releasing a broadcast group name, just ignore it. */
92 if( group && !ismyip(owner_ip) )
93 return;
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* !!!!!
101 pull_ascii_nstring(qname, question->name);
102 if( !group && !ismyip(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;
110 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
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));
121 if(rcode == 0)
122 return;
124 /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
125 send_name_release_response(rcode, p);
128 /****************************************************************************
129 Send a name registration response.
130 **************************************************************************/
132 static void send_name_registration_response(int rcode, int ttl, struct packet_struct *p)
134 struct nmb_packet *nmb = &p->packet.nmb;
135 char rdata[6];
137 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
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. */
148 /****************************************************************************
149 Process a name refresh request on a broadcast subnet.
150 **************************************************************************/
152 void process_name_refresh_request(struct subnet_record *subrec,
153 struct packet_struct *p)
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;
160 putip((char *)&from_ip,&nmb->additional->rdata[2]);
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.
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"));
175 send_name_registration_response(FMT_ERR, 0, p);
176 return;
179 /* Just log a message. We really don't care about broadcast name refreshes. */
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));
185 /****************************************************************************
186 Process a name registration request on a broadcast subnet.
187 **************************************************************************/
189 void process_name_registration_request(struct subnet_record *subrec,
190 struct packet_struct *p)
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;
201 putip((char *)&from_ip,&nmb->additional->rdata[2]);
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.
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));
215 send_name_registration_response(FMT_ERR, 0, p);
216 return;
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));
222 /* See if the name already exists. */
223 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
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.
231 if((namerec != NULL) && (namerec->data.source == WINS_PROXY_NAME)) {
232 remove_name_from_namelist( subrec, namerec );
233 namerec = NULL;
236 if (!group) {
237 /* Unique name. */
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 */
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);
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;
257 } else {
258 /* Group name. */
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;
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 **************************************************************************/
276 static int status_compare(char *n1,char *n2)
278 nstring name1, name2;
279 int l1,l2,l3;
281 pull_ascii_nstring(name1, n1);
282 pull_ascii_nstring(name2, n2);
283 n1 = name1;
284 n2 = name2;
286 /* It's a bit tricky because the names are space padded */
287 for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++)
289 for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++)
291 l3 = strlen(global_myname());
293 if ((l1==l3) && strncmp(n1,global_myname(),l3) == 0 &&
294 (l2!=l3 || strncmp(n2,global_myname(),l3) != 0))
295 return -1;
297 if ((l2==l3) && strncmp(n2,global_myname(),l3) == 0 &&
298 (l1!=l3 || strncmp(n1,global_myname(),l3) != 0))
299 return 1;
301 return memcmp(n1,n2,sizeof(nstring));
304 /****************************************************************************
305 Process a node status query
306 ****************************************************************************/
308 void process_node_status_request(struct subnet_record *subrec, struct packet_struct *p)
310 struct nmb_packet *nmb = &p->packet.nmb;
311 nstring qname;
312 int ques_type = nmb->question.question_name.name_type;
313 char rdata[MAX_DGRAM_SIZE];
314 char *countptr, *buf, *bufend, *buf0;
315 int names_added,i;
316 struct name_record *namerec;
318 pull_ascii_nstring(qname, nmb->question.question_name.name);
320 DEBUG(3,("process_node_status_request: status request for name %s from IP %s on \
321 subnet %s.\n", nmb_namestr(&nmb->question.question_name), inet_ntoa(p->ip), subrec->subnet_name));
323 if((namerec = find_name_on_subnet(subrec, &nmb->question.question_name, FIND_SELF_NAME)) == 0) {
324 DEBUG(1,("process_node_status_request: status request for name %s from IP %s on \
325 subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
326 inet_ntoa(p->ip), subrec->subnet_name));
328 return;
331 /* this is not an exact calculation. the 46 is for the stats buffer
332 and the 60 is to leave room for the header etc */
333 bufend = &rdata[MAX_DGRAM_SIZE] - (18 + 46 + 60);
334 countptr = buf = rdata;
335 buf += 1;
336 buf0 = buf;
338 names_added = 0;
340 namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
342 while (buf < bufend) {
343 if( (namerec->data.source == SELF_NAME) || (namerec->data.source == PERMANENT_NAME) ) {
344 int name_type = namerec->name.name_type;
345 nstring name;
347 pull_ascii_nstring(name, namerec->name.name);
348 strupper_m(name);
349 if (!strequal(name,"*") &&
350 !strequal(name,"__SAMBA__") &&
351 (name_type < 0x1b || name_type >= 0x20 ||
352 ques_type < 0x1b || ques_type >= 0x20 ||
353 strequal(qname, name))) {
354 /* Start with the name. */
355 nstring tmp_name;
356 memset(tmp_name,'\0',sizeof(tmp_name));
357 snprintf(tmp_name, sizeof(tmp_name), "%-15.15s",name);
358 push_ascii_nstring(buf, tmp_name);
360 /* Put the name type and netbios flags in the buffer. */
362 buf[15] = name_type;
363 set_nb_flags( &buf[16],namerec->data.nb_flags );
364 buf[16] |= NB_ACTIVE; /* all our names are active */
366 buf += 18;
368 names_added++;
372 /* Remove duplicate names. */
373 if (names_added > 1) {
374 qsort( buf0, names_added, 18, QSORT_CAST status_compare );
377 for( i=1; i < names_added ; i++ ) {
378 if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) {
379 names_added--;
380 if (names_added == i)
381 break;
382 memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i));
383 i--;
387 buf = buf0 + 18*names_added;
389 namerec = (struct name_record *)ubi_trNext( namerec );
391 if (!namerec) {
392 /* End of the subnet specific name list. Now
393 add the names on the unicast subnet . */
394 struct subnet_record *uni_subrec = unicast_subnet;
396 if (uni_subrec != subrec) {
397 subrec = uni_subrec;
398 namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
401 if (!namerec)
402 break;
406 SCVAL(countptr,0,names_added);
408 /* We don't send any stats as they could be used to attack
409 the protocol. */
410 memset(buf,'\0',46);
412 buf += 46;
414 /* Send a NODE STATUS RESPONSE */
415 reply_netbios_packet(p, /* Packet to reply to. */
416 0, /* Result code. */
417 NMB_STATUS, /* nmbd type code. */
418 NMB_NAME_QUERY_OPCODE, /* opcode. */
419 0, /* ttl. */
420 rdata, /* data to send. */
421 PTR_DIFF(buf,rdata)); /* data length. */
425 /***************************************************************************
426 Process a name query.
428 For broadcast name queries:
430 - Only reply if the query is for one of YOUR names.
431 - NEVER send a negative response to a broadcast query.
433 ****************************************************************************/
435 void process_name_query_request(struct subnet_record *subrec, struct packet_struct *p)
437 struct nmb_packet *nmb = &p->packet.nmb;
438 struct nmb_name *question = &nmb->question.question_name;
439 int name_type = question->name_type;
440 BOOL bcast = nmb->header.nm_flags.bcast;
441 int ttl=0;
442 int rcode = 0;
443 char *prdata = NULL;
444 char rdata[6];
445 BOOL success = False;
446 struct name_record *namerec = NULL;
447 int reply_data_len = 0;
448 int i;
450 DEBUG(3,("process_name_query_request: Name query from %s on subnet %s for name %s\n",
451 inet_ntoa(p->ip), subrec->subnet_name, nmb_namestr(question)));
453 /* Look up the name in the cache - if the request is a broadcast request that
454 came from a subnet we don't know about then search all the broadcast subnets
455 for a match (as we don't know what interface the request came in on). */
457 if(subrec == remote_broadcast_subnet)
458 namerec = find_name_for_remote_broadcast_subnet( question, FIND_ANY_NAME);
459 else
460 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
462 /* Check if it is a name that expired */
463 if (namerec &&
464 ((namerec->data.death_time != PERMANENT_TTL) &&
465 (namerec->data.death_time < p->timestamp))) {
466 DEBUG(5,("process_name_query_request: expired name %s\n", nmb_namestr(&namerec->name)));
467 namerec = NULL;
470 if (namerec) {
472 * Always respond to unicast queries.
473 * Don't respond to broadcast queries unless the query is for
474 * a name we own, a Primary Domain Controller name, or a WINS_PROXY
475 * name with type 0 or 0x20. WINS_PROXY names are only ever added
476 * into the namelist if we were configured as a WINS proxy.
479 if (!bcast ||
480 (bcast && ((name_type == 0x1b) ||
481 (namerec->data.source == SELF_NAME) ||
482 (namerec->data.source == PERMANENT_NAME) ||
483 ((namerec->data.source == WINS_PROXY_NAME) &&
484 ((name_type == 0) || (name_type == 0x20)))))) {
485 /* The requested name is a directed query, or it's SELF or PERMANENT or WINS_PROXY,
486 or it's a Domain Master type. */
489 * If this is a WINS_PROXY_NAME, then ceck that none of the IP
490 * addresses we are returning is on the same broadcast subnet
491 * as the requesting packet. If it is then don't reply as the
492 * actual machine will be replying also and we don't want two
493 * replies to a broadcast query.
496 if (namerec->data.source == WINS_PROXY_NAME) {
497 for( i = 0; i < namerec->data.num_ips; i++) {
498 if (same_net(namerec->data.ip[i], subrec->myip, subrec->mask_ip)) {
499 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",
500 nmb_namestr(&namerec->name), subrec->subnet_name ));
501 return;
506 ttl = (namerec->data.death_time != PERMANENT_TTL) ?
507 namerec->data.death_time - p->timestamp : lp_max_ttl();
509 /* Copy all known ip addresses into the return data. */
510 /* Optimise for the common case of one IP address so
511 we don't need a malloc. */
513 if (namerec->data.num_ips == 1) {
514 prdata = rdata;
515 } else {
516 if ((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL) {
517 DEBUG(0,("process_name_query_request: malloc fail !\n"));
518 return;
522 for (i = 0; i < namerec->data.num_ips; i++) {
523 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
524 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
527 sort_query_replies(prdata, i, p->ip);
529 reply_data_len = namerec->data.num_ips * 6;
530 success = True;
535 * If a machine is broadcasting a name lookup request and we have lp_wins_proxy()
536 * set we should initiate a WINS query here. On success we add the resolved name
537 * into our namelist with a type of WINS_PROXY_NAME and then reply to the query.
540 if(!success && (namerec == NULL) && we_are_a_wins_client() && lp_wins_proxy() &&
541 bcast && (subrec != remote_broadcast_subnet)) {
542 make_wins_proxy_name_query_request( subrec, p, question );
543 return;
546 if (!success && bcast) {
547 if(prdata != rdata)
548 SAFE_FREE(prdata);
549 return; /* Never reply with a negative response to broadcasts. */
553 * Final check. From observation, if a unicast packet is sent
554 * to a non-WINS server with the recursion desired bit set
555 * then never send a negative response.
558 if(!success && !bcast && nmb->header.nm_flags.recursion_desired) {
559 if(prdata != rdata)
560 SAFE_FREE(prdata);
561 return;
564 if (success) {
565 rcode = 0;
566 DEBUG(3,("OK\n"));
567 } else {
568 rcode = NAM_ERR;
569 DEBUG(3,("UNKNOWN\n"));
572 /* See rfc1002.txt 4.2.13. */
574 reply_netbios_packet(p, /* Packet to reply to. */
575 rcode, /* Result code. */
576 NMB_QUERY, /* nmbd type code. */
577 NMB_NAME_QUERY_OPCODE, /* opcode. */
578 ttl, /* ttl. */
579 prdata, /* data to send. */
580 reply_data_len); /* data length. */
582 if(prdata != rdata)
583 SAFE_FREE(prdata);