2 Unix SMB/Netbios implementation.
4 NBT netbios routines and daemon - version 2
5 Copyright (C) Andrew Tridgell 1994-1997
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 Module name: nameservreply.c
25 14 jan 96: lkcl@pires.co.uk
26 added multiple workgroup domain master support
28 04 jul 96: lkcl@pires.co.uk
29 created module nameservreply containing NetBIOS reply functions
37 extern int DEBUGLEVEL;
39 extern struct in_addr wins_ip;
41 /****************************************************************************
42 send a registration / release response: pos/neg
43 **************************************************************************/
44 static void send_name_response(int fd, struct in_addr from_ip,
45 int name_trn_id, int opcode, BOOL success, BOOL recurse,
46 struct nmb_name *reply_name, int nb_flags, int ttl,
50 struct packet_struct p;
56 /* NEGATIVE RESPONSE */
59 else if (opcode == NMB_REG && recurse == False)
61 /* END-NODE CHALLENGE REGISTRATION RESPONSE */
67 putip(&rdata[2],(char *)&ip);
72 p.timestamp = time(NULL);
73 p.packet_type = NMB_PACKET;
75 reply_netbios_packet(&p,name_trn_id,
76 rcode,opcode,opcode,recurse,
77 reply_name, 0x20, 0x1,
82 /****************************************************************************
83 add a netbios entry. respond to the (possibly new) owner.
84 **************************************************************************/
85 void add_name_respond(struct subnet_record *d, int fd, struct in_addr from_ip,
87 struct nmb_name *name,
88 int nb_flags, int ttl, struct in_addr register_ip,
89 BOOL new_owner, struct in_addr reply_to_ip)
91 /* register the old or the new owners' ip */
92 add_netbios_entry(d,name->name,name->name_type,
93 nb_flags,ttl,REGISTER,register_ip,False,True);
95 /* reply yes or no to the host that requested the name */
96 send_name_response(fd,from_ip, response_id, NMB_REG,
98 name, nb_flags, ttl, reply_to_ip);
102 /****************************************************************************
103 reply to a name release
104 ****************************************************************************/
105 void reply_name_release(struct packet_struct *p)
107 struct nmb_packet *nmb = &p->packet.nmb;
109 int nb_flags = nmb->additional->rdata[0];
110 BOOL bcast = nmb->header.nm_flags.bcast;
111 struct name_record *n;
112 struct subnet_record *d = NULL;
114 BOOL success = False;
116 putip((char *)&ip,&nmb->additional->rdata[2]);
118 DEBUG(3,("Name release on name %s\n",
119 namestr(&nmb->question.question_name)));
121 if (!(d = find_req_subnet(p->ip, bcast)))
123 DEBUG(3,("response packet: bcast %s not known\n",
129 search |= FIND_LOCAL;
133 n = find_name_search(&d, &nmb->question.question_name,
136 /* XXXX under what conditions should we reject the removal?? */
137 /* For now - remove if the names match and the group bit matches. */
138 if (n && (NAME_GROUP(n->ip_flgs[0].nb_flags) == NAME_GROUP(nb_flags)))
142 DEBUG(5, ("reply_name_release: Removing name %s on subnet %s\n",
143 namestr(&nmb->question.question_name), inet_ntoa(d->bcast_ip)));
150 /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
151 send_name_response(p->fd,p->ip, nmb->header.name_trn_id, NMB_REL,
152 success, nmb->header.nm_flags.recursion_desired,
153 &nmb->question.question_name, nb_flags, 0, ip);
157 /****************************************************************************
158 reply to a reg request
159 **************************************************************************/
160 void reply_name_reg(struct packet_struct *p)
162 struct nmb_packet *nmb = &p->packet.nmb;
163 struct nmb_name *question = &nmb->question.question_name;
165 struct nmb_name *reply_name = question;
167 char *qname = question->name;
168 int qname_type = question->name_type;
170 BOOL bcast = nmb->header.nm_flags.bcast;
172 int ttl = GET_TTL(nmb->additional->ttl);
173 int nb_flags = nmb->additional->rdata[0];
174 BOOL group = NAME_GROUP(nb_flags);
176 struct subnet_record *d = NULL;
177 struct name_record *n = NULL;
180 BOOL secured_redirect = False;
182 struct in_addr ip, from_ip;
185 putip((char *)&from_ip,&nmb->additional->rdata[2]);
188 DEBUG(3,("Name registration for name %s at %s - ",
189 namestr(question),inet_ntoa(ip)));
193 /* apparently we should return 255.255.255.255 for group queries
195 ip = *interpret_addr2("255.255.255.255");
198 if (!(d = find_req_subnet(p->ip, bcast)))
200 DEBUG(3,("reply_name_reg: subnet %s not known\n",
206 search |= FIND_LOCAL;
210 /* see if the name already exists */
211 n = find_name_search(&d, question, search, from_ip);
215 DEBUG(3,("found\n"));
216 if (!group) /* unique names */
218 if (n->source == SELF || NAME_GROUP(n->ip_flgs[0].nb_flags))
220 /* no-one can register one of samba's names, nor can they
221 register a name that's a group name as a unique name */
225 else if(!ip_equal(ip, n->ip_flgs[0].ip))
227 /* XXXX rfc1001.txt says:
228 * if we are doing secured WINS, we must send a Wait-Acknowledge
229 * packet (WACK) to the person who wants the name, then do a
230 * name query on the person who currently owns the unique name.
231 * if the current owner still says they own it, the person who wants
232 * the name can't have it. if they do not, or are not alive, they can.
235 secured_redirect = True;
237 reply_name = &n->name;
241 n->ip_flgs[0].ip = ip;
242 n->death_time = ttl?p->timestamp+ttl*3:0;
243 DEBUG(3,("%s owner: %s\n",namestr(&n->name),inet_ntoa(n->ip_flgs[0].ip)));
248 /* refresh the name */
249 if (n->source != SELF)
251 n->death_time = ttl?p->timestamp + ttl*3:0;
255 /* XXXX bug reported by terryt@ren.pc.athabascau.ca */
256 /* names that people have checked for and not found get DNSFAILed.
257 we need to update the name record if someone then registers */
259 if (n->source == DNSFAIL)
260 n->source = REGISTER;
265 DEBUG(3,("not found\n"));
266 /* add the name to our name/subnet, or WINS, database */
267 n = add_netbios_entry(d,qname,qname_type,nb_flags,ttl,REGISTER,ip,
271 /* if samba owns a unique name on a subnet, then it must respond and
272 disallow the attempted registration. if the registration is
273 successful by broadcast, only then is there no need to respond
274 (implicit registration: see rfc1001.txt 15.2.1).
277 if (bcast && success) return;
279 if (secured_redirect)
283 /* XXXX i am confused. RSVAL or SSVAL? assume NMB byte ordering */
284 RSSVAL(rdata,0,(nmb->header.opcode&0xf) + ((nb_flags&0xff) << 4));
286 /* XXXX mistake in rfc1002.txt? 4.2.16: NULL is 0xa see 4.2.1.3
287 type = 0x0a; see rfc1002.txt 4.2.1.3
288 class = 0x01; see rfc1002.txt 4.2.16
291 /* send WAIT ACKNOWLEDGEMENT see rfc1002.txt 4.2.16 */
292 reply_netbios_packet(p,nmb->header.name_trn_id,
293 0,NMB_WAIT_ACK,NMB_WAIT_ACK,False,
294 reply_name, 0x0a, 0x01,
295 15*1000, /* 15 seconds long enough to wait? */
298 /* initiate some enquiries to the current owner. */
299 queue_netbios_packet(d,ClientNMB,NMB_QUERY,
300 NAME_REGISTER_CHALLENGE,
301 reply_name->name,reply_name->name_type,
302 nb_flags,0,0,NULL,NULL,
303 False, False, n->ip_flgs[0].ip, p->ip);
307 /* Send a NAME REGISTRATION RESPONSE (pos/neg) see rfc1002.txt 4.2.13-14
308 or an END-NODE CHALLENGE REGISTRATION RESPONSE see rfc1002.txt 4.2.7
311 send_name_response(p->fd,p->ip, nmb->header.name_trn_id, NMB_REG,
312 success, nmb->header.nm_flags.recursion_desired,
313 reply_name, nb_flags, ttl, ip);
317 /* this is used to sort names for a name status into a sensible order
318 we put our own names first, then in alphabetical order */
319 static int status_compare(char *n1,char *n2)
321 extern pstring myname;
324 /* its a bit tricky because the names are space padded */
325 for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++) ;
326 for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++) ;
329 if ((l1==l3) && strncmp(n1,myname,l3) == 0 &&
330 (l2!=l3 || strncmp(n2,myname,l3) != 0))
333 if ((l2==l3) && strncmp(n2,myname,l3) == 0 &&
334 (l1!=l3 || strncmp(n1,myname,l3) != 0))
337 return memcmp(n1,n2,18);
341 /****************************************************************************
342 reply to a name status query
344 combine the list of the local interface on which the query was made with
345 the names registered via wins.
346 ****************************************************************************/
347 void reply_name_status(struct packet_struct *p)
349 struct nmb_packet *nmb = &p->packet.nmb;
350 char *qname = nmb->question.question_name.name;
351 int ques_type = nmb->question.question_name.name_type;
352 char rdata[MAX_DGRAM_SIZE];
353 char *countptr, *buf, *bufend, *buf0;
355 struct name_record *n;
356 struct subnet_record *d = NULL;
357 int search = FIND_SELF | FIND_WINS | FIND_LOCAL;
359 /* NOTE: we always treat a name status lookup as a bcast */
360 if (!(d = find_req_subnet(p->ip, True)))
362 DEBUG(3,("Name status req: bcast %s not known\n",
367 DEBUG(3,("Name status for name %s %s\n",
368 namestr(&nmb->question.question_name),
371 n = find_name_search(&d, &nmb->question.question_name,
376 /* XXXX hack, we should calculate exactly how many will fit */
377 bufend = &rdata[MAX_DGRAM_SIZE] - 18;
378 countptr = buf = rdata;
388 if (n->source == SELF)
390 int name_type = n->name.name_type;
392 /* check if we want to exclude other workgroup names
393 from the response. if we don't exclude them, windows clients
394 get confused and will respond with an error for NET VIEW */
396 if (!strequal(n->name.name,"*") &&
397 !strequal(n->name.name,"__SAMBA__") &&
398 (name_type < 0x1b || name_type >= 0x20 ||
399 ques_type < 0x1b || ques_type >= 0x20 ||
400 strequal(qname, n->name.name)))
402 /* start with first bit of putting info in buffer: the name */
404 sprintf(buf,"%-15.15s",n->name.name);
407 /* put name type and netbios flags in buffer */
409 buf[16] = n->ip_flgs[0].nb_flags;
417 /* remove duplicate names */
418 qsort(buf0,names_added,18,QSORT_CAST status_compare);
420 for (i=1;i<names_added;i++) {
421 if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) {
423 if (names_added == i) break;
424 memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i));
429 buf = buf0 + 18*names_added;
435 /* end of this name list: add wins names too? */
436 struct subnet_record *w_d;
438 if (!(w_d = wins_subnet)) break;
443 n = d->namelist; /* start on the wins name list */
449 SCVAL(countptr,0,names_added);
451 /* XXXXXXX we should fill in more fields of the statistics structure */
454 extern int num_good_sends,num_good_receives;
455 SIVAL(buf,20,num_good_sends);
456 SIVAL(buf,24,num_good_receives);
461 /* Send a POSITIVE NAME STATUS RESPONSE */
462 reply_netbios_packet(p,nmb->header.name_trn_id,
464 &nmb->question.question_name,
466 0, rdata,PTR_DIFF(buf,rdata));
470 /***************************************************************************
471 reply to a name query.
473 with broadcast name queries:
475 - only reply if the query is for one of YOUR names. all other machines on
476 the network will be doing the same thing (that is, only replying to a
477 broadcast query if they own it)
478 NOTE: broadcast name queries should only be sent out by a machine
479 if they HAVEN'T been configured to use WINS. this is generally bad news
480 in a wide area tcp/ip network and should be rectified by the systems
481 administrator. USE WINS! :-)
482 - the exception to this is if the query is for a Primary Domain Controller
483 type name (0x1b), in which case, a reply is sent.
485 - NEVER send a negative response to a broadcast query. no-one else will!
487 with directed name queries:
489 - if you are the WINS server, you are expected to respond with either
490 a negative response, a positive response, or a wait-for-acknowledgement
491 packet, and then later on a pos/neg response.
493 ****************************************************************************/
494 void reply_name_query(struct packet_struct *p)
496 struct nmb_packet *nmb = &p->packet.nmb;
497 struct nmb_name *question = &nmb->question.question_name;
498 int name_type = question->name_type;
499 BOOL bcast = nmb->header.nm_flags.bcast;
503 struct in_addr retip;
505 struct subnet_record *d = NULL;
507 struct name_record *n = NULL;
509 /* directed queries are for WINS server: broadcasts are local SELF queries.
510 the exception is Domain Master names. */
512 int search = bcast ? FIND_LOCAL | FIND_WINS: FIND_WINS;
514 if (search & FIND_LOCAL)
516 if (!(d = find_req_subnet(p->ip, bcast)))
518 DEBUG(3,("name query: bcast %s not known\n",
525 if (!(d = wins_subnet))
527 DEBUG(3,("name query: wins search %s not known\n",
533 DEBUG(3,("Name query from %s for name %s<0x%x>\n",
534 inet_ntoa(p->ip), question->name, question->name_type));
538 /* eh? no criterion for searching database. help! */
542 if (!bcast && (name_type == 0x1d) && lp_wins_support())
544 /* see WINS manager HELP - 'How WINS Handles Special Names' */
545 /* a WINS query (unicasted) for a 0x1d name must always return False */
551 /* look up the name in the cache */
552 n = find_name_search(&d, question, search, p->ip);
554 /* it is a name that already failed DNS lookup or it's expired */
555 if (n && (n->source == DNSFAIL ||
556 (n->death_time && n->death_time < p->timestamp)))
561 /* do we want to do dns lookups? */
562 /* XXXX this DELAYS nmbd while it does a search. not a good idea
563 but there's no pleasant alternative. phil@hands.com suggested
564 making the name a full DNS name, which would succeed / fail
567 if (success && !n && (lp_wins_proxy() || !bcast))
569 n = dns_name_search(question, p->timestamp);
573 if (!n) success = False;
577 if (bcast && n->source != SELF && name_type != 0x1b)
579 /* don't respond to broadcast queries unless the query is for
580 a name we own or it is for a Primary Domain Controller name */
582 if (!lp_wins_proxy() ||
583 same_net(p->ip,n->ip_flgs[0].ip,*iface_nmask(p->ip)))
585 /* never reply with a negative response to broadcast queries */
590 /* name is directed query, or it's self, or it's a Domain Master type
591 name, or we're replying on behalf of a caller because they are on a
592 different subnet and cannot hear the broadcast. XXXX lp_wins_proxy
593 should be switched off in environments where broadcasts are forwarded
596 /* XXXX note: for proxy servers, we should forward the query on to
597 another WINS server if the name is not in our database, or we are
598 not a WINS server ourselves
600 ttl = n->death_time ? n->death_time - p->timestamp : GET_TTL(0);
601 retip = n->ip_flgs[0].ip;
602 nb_flags = n->ip_flgs[0].nb_flags;
605 if (!success && bcast) return; /* never reply negative response to bcasts */
607 /* if the IP is 0 then substitute my IP */
608 if (zero_ip(retip)) retip = *iface_ip(p->ip);
610 /* SPECIAL CASE... If we are a WINS server and the request is explicitly
611 *to* the WINS server and the name type is WORKGROUP<0x1e> we should
612 respond with the local broadcast address 255.255.255.255.
614 if(!bcast && (name_type == 0x1e) && lp_wins_support())
615 retip = *interpret_addr2("255.255.255.255");
620 DEBUG(3,("OK %s\n",inet_ntoa(retip)));
625 DEBUG(3,("UNKNOWN\n"));
632 putip(&rdata[2],(char *)&retip);
635 reply_netbios_packet(p,nmb->header.name_trn_id,
636 rcode,NMB_QUERY,0,True,
637 &nmb->question.question_name,
640 rdata, success ? 6 : 0);