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 && (n->source != SELF) && (NAME_GROUP(n->ip_flgs[0].nb_flags) == NAME_GROUP(nb_flags)))
142 /* If it's a group name not ending in 1c (not an internet name)
143 then just allow it to fade out of existance by timing out. */
144 if(NAME_GROUP(nb_flags) && (n->name.name_type != 0x1c))
146 DEBUG(5, ("reply_name_release: Allow group name %s(%d) to fade out on \
147 subnet %s\n", namestr(&nmb->question.question_name), n->name.name_type,
148 inet_ntoa(d->bcast_ip)));
152 DEBUG(5, ("reply_name_release: Removing name %s on subnet %s\n",
153 namestr(&nmb->question.question_name), inet_ntoa(d->bcast_ip)));
161 /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
162 send_name_response(p->fd,p->ip, nmb->header.name_trn_id, NMB_REL,
163 success, nmb->header.nm_flags.recursion_desired,
164 &nmb->question.question_name, nb_flags, 0, ip);
168 /****************************************************************************
169 reply to a reg request
170 **************************************************************************/
171 void reply_name_reg(struct packet_struct *p)
173 struct nmb_packet *nmb = &p->packet.nmb;
174 struct nmb_name *question = &nmb->question.question_name;
176 struct nmb_name *reply_name = question;
178 char *qname = question->name;
179 int qname_type = question->name_type;
181 BOOL bcast = nmb->header.nm_flags.bcast;
183 int ttl = GET_TTL(nmb->additional->ttl);
184 int nb_flags = nmb->additional->rdata[0];
185 BOOL group = NAME_GROUP(nb_flags);
187 struct subnet_record *d = NULL;
188 struct name_record *n = NULL;
191 BOOL secured_redirect = False;
193 struct in_addr ip, from_ip;
196 putip((char *)&from_ip,&nmb->additional->rdata[2]);
199 DEBUG(3,("Name registration for name %s at %s - ",
200 namestr(question),inet_ntoa(ip)));
204 /* apparently we should return 255.255.255.255 for group queries
206 ip = *interpret_addr2("255.255.255.255");
209 if (!(d = find_req_subnet(p->ip, bcast)))
211 DEBUG(3,("reply_name_reg: subnet %s not known\n",
217 search |= FIND_LOCAL;
221 /* see if the name already exists */
222 n = find_name_search(&d, question, search, from_ip);
226 DEBUG(3,("found\n"));
227 if (!group) /* unique names */
229 if (n->source == SELF || NAME_GROUP(n->ip_flgs[0].nb_flags))
231 /* no-one can register one of samba's names, nor can they
232 register a name that's a group name as a unique name */
236 else if(!ip_equal(ip, n->ip_flgs[0].ip))
238 /* XXXX rfc1001.txt says:
239 * if we are doing secured WINS, we must send a Wait-Acknowledge
240 * packet (WACK) to the person who wants the name, then do a
241 * name query on the person who currently owns the unique name.
242 * if the current owner still says they own it, the person who wants
243 * the name can't have it. if they do not, or are not alive, they can.
246 secured_redirect = True;
248 reply_name = &n->name;
252 n->ip_flgs[0].ip = ip;
253 n->death_time = ttl?p->timestamp+ttl*3:0;
254 DEBUG(3,("%s owner: %s\n",namestr(&n->name),inet_ntoa(n->ip_flgs[0].ip)));
259 /* refresh the name */
260 if (n->source != SELF)
262 n->death_time = ttl?p->timestamp + ttl*3:0;
266 /* XXXX bug reported by terryt@ren.pc.athabascau.ca */
267 /* names that people have checked for and not found get DNSFAILed.
268 we need to update the name record if someone then registers */
270 if (n->source == DNSFAIL)
271 n->source = REGISTER;
276 DEBUG(3,("not found\n"));
277 /* add the name to our name/subnet, or WINS, database */
278 n = add_netbios_entry(d,qname,qname_type,nb_flags,ttl,REGISTER,ip,
282 /* if samba owns a unique name on a subnet, then it must respond and
283 disallow the attempted registration. if the registration is
284 successful by broadcast, only then is there no need to respond
285 (implicit registration: see rfc1001.txt 15.2.1).
288 if (bcast && success) return;
290 if (secured_redirect)
294 /* XXXX i am confused. RSVAL or SSVAL? assume NMB byte ordering */
295 RSSVAL(rdata,0,(nmb->header.opcode&0xf) + ((nb_flags&0xff) << 4));
297 /* XXXX mistake in rfc1002.txt? 4.2.16: NULL is 0xa see 4.2.1.3
298 type = 0x0a; see rfc1002.txt 4.2.1.3
299 class = 0x01; see rfc1002.txt 4.2.16
302 /* send WAIT ACKNOWLEDGEMENT see rfc1002.txt 4.2.16 */
303 reply_netbios_packet(p,nmb->header.name_trn_id,
304 0,NMB_WAIT_ACK,NMB_WAIT_ACK,False,
305 reply_name, 0x0a, 0x01,
306 15*1000, /* 15 seconds long enough to wait? */
309 /* initiate some enquiries to the current owner. */
310 queue_netbios_packet(d,ClientNMB,NMB_QUERY,
311 NAME_REGISTER_CHALLENGE,
312 reply_name->name,reply_name->name_type,
313 nb_flags,0,0,NULL,NULL,
314 False, False, n->ip_flgs[0].ip, p->ip);
318 /* Send a NAME REGISTRATION RESPONSE (pos/neg) see rfc1002.txt 4.2.13-14
319 or an END-NODE CHALLENGE REGISTRATION RESPONSE see rfc1002.txt 4.2.7
322 send_name_response(p->fd,p->ip, nmb->header.name_trn_id, NMB_REG,
323 success, nmb->header.nm_flags.recursion_desired,
324 reply_name, nb_flags, ttl, ip);
328 /* this is used to sort names for a name status into a sensible order
329 we put our own names first, then in alphabetical order */
330 static int status_compare(char *n1,char *n2)
332 extern pstring myname;
335 /* its a bit tricky because the names are space padded */
336 for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++) ;
337 for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++) ;
340 if ((l1==l3) && strncmp(n1,myname,l3) == 0 &&
341 (l2!=l3 || strncmp(n2,myname,l3) != 0))
344 if ((l2==l3) && strncmp(n2,myname,l3) == 0 &&
345 (l1!=l3 || strncmp(n1,myname,l3) != 0))
348 return memcmp(n1,n2,18);
352 /****************************************************************************
353 reply to a name status query
355 combine the list of the local interface on which the query was made with
356 the names registered via wins.
357 ****************************************************************************/
358 void reply_name_status(struct packet_struct *p)
360 struct nmb_packet *nmb = &p->packet.nmb;
361 char *qname = nmb->question.question_name.name;
362 int ques_type = nmb->question.question_name.name_type;
363 char rdata[MAX_DGRAM_SIZE];
364 char *countptr, *buf, *bufend, *buf0;
366 struct name_record *n;
367 struct subnet_record *d = NULL;
368 int search = FIND_SELF | FIND_WINS | FIND_LOCAL;
370 /* NOTE: we always treat a name status lookup as a bcast */
371 if (!(d = find_req_subnet(p->ip, True)))
373 DEBUG(3,("Name status req: bcast %s not known\n",
378 DEBUG(3,("Name status for name %s %s\n",
379 namestr(&nmb->question.question_name),
382 n = find_name_search(&d, &nmb->question.question_name,
387 /* XXXX hack, we should calculate exactly how many will fit */
388 bufend = &rdata[MAX_DGRAM_SIZE] - 18;
389 countptr = buf = rdata;
399 if (n->source == SELF)
401 int name_type = n->name.name_type;
403 /* check if we want to exclude other workgroup names
404 from the response. if we don't exclude them, windows clients
405 get confused and will respond with an error for NET VIEW */
407 if (!strequal(n->name.name,"*") &&
408 !strequal(n->name.name,"__SAMBA__") &&
409 (name_type < 0x1b || name_type >= 0x20 ||
410 ques_type < 0x1b || ques_type >= 0x20 ||
411 strequal(qname, n->name.name)))
413 /* start with first bit of putting info in buffer: the name */
415 sprintf(buf,"%-15.15s",n->name.name);
418 /* put name type and netbios flags in buffer */
420 buf[16] = n->ip_flgs[0].nb_flags;
428 /* remove duplicate names */
429 qsort(buf0,names_added,18,QSORT_CAST status_compare);
431 for (i=1;i<names_added;i++) {
432 if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) {
434 if (names_added == i) break;
435 memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i));
440 buf = buf0 + 18*names_added;
446 /* end of this name list: add wins names too? */
447 struct subnet_record *w_d;
449 if (!(w_d = wins_subnet)) break;
454 n = d->namelist; /* start on the wins name list */
460 SCVAL(countptr,0,names_added);
462 /* XXXXXXX we should fill in more fields of the statistics structure */
465 extern int num_good_sends,num_good_receives;
466 SIVAL(buf,20,num_good_sends);
467 SIVAL(buf,24,num_good_receives);
472 /* Send a POSITIVE NAME STATUS RESPONSE */
473 reply_netbios_packet(p,nmb->header.name_trn_id,
475 &nmb->question.question_name,
477 0, rdata,PTR_DIFF(buf,rdata));
481 /***************************************************************************
482 reply to a name query.
484 with broadcast name queries:
486 - only reply if the query is for one of YOUR names. all other machines on
487 the network will be doing the same thing (that is, only replying to a
488 broadcast query if they own it)
489 NOTE: broadcast name queries should only be sent out by a machine
490 if they HAVEN'T been configured to use WINS. this is generally bad news
491 in a wide area tcp/ip network and should be rectified by the systems
492 administrator. USE WINS! :-)
493 - the exception to this is if the query is for a Primary Domain Controller
494 type name (0x1b), in which case, a reply is sent.
496 - NEVER send a negative response to a broadcast query. no-one else will!
498 with directed name queries:
500 - if you are the WINS server, you are expected to respond with either
501 a negative response, a positive response, or a wait-for-acknowledgement
502 packet, and then later on a pos/neg response.
504 ****************************************************************************/
505 void reply_name_query(struct packet_struct *p)
507 struct nmb_packet *nmb = &p->packet.nmb;
508 struct nmb_name *question = &nmb->question.question_name;
509 int name_type = question->name_type;
510 BOOL bcast = nmb->header.nm_flags.bcast;
514 struct in_addr retip;
516 struct subnet_record *d = NULL;
518 struct name_record *n = NULL;
520 /* directed queries are for WINS server: broadcasts are local SELF queries.
521 the exception is Domain Master names. */
523 int search = bcast ? FIND_LOCAL | FIND_WINS: FIND_WINS;
525 if (search & FIND_LOCAL)
527 if (!(d = find_req_subnet(p->ip, bcast)))
529 DEBUG(3,("name query: bcast %s not known\n",
536 if (!(d = wins_subnet))
538 DEBUG(3,("name query: wins search %s not known\n",
544 DEBUG(3,("Name query from %s for name %s<0x%x>\n",
545 inet_ntoa(p->ip), question->name, question->name_type));
549 /* eh? no criterion for searching database. help! */
553 if (!bcast && (name_type == 0x1d) && lp_wins_support())
555 /* see WINS manager HELP - 'How WINS Handles Special Names' */
556 /* a WINS query (unicasted) for a 0x1d name must always return False */
562 /* look up the name in the cache */
563 n = find_name_search(&d, question, search, p->ip);
565 /* it is a name that already failed DNS lookup or it's expired */
566 if (n && (n->source == DNSFAIL ||
567 (n->death_time && n->death_time < p->timestamp)))
572 /* do we want to do dns lookups? */
573 /* XXXX this DELAYS nmbd while it does a search. lp_dns_proxy()
574 can be switched off, to ensure that the blocking doesn't occur.
575 a better solution would be to fork, but this will require a
576 mechanism to carry on processing after the query is resolved
577 (similar to the netbios queue).
579 if (success && !n && (lp_dns_proxy() || !bcast))
581 n = dns_name_search(question, p->timestamp);
585 if (!n) success = False;
589 if (bcast && n->source != SELF && name_type != 0x1b)
591 /* don't respond to broadcast queries unless the query is for
592 a name we own or it is for a Primary Domain Controller name */
594 if (!lp_wins_proxy() ||
595 same_net(p->ip,n->ip_flgs[0].ip,*iface_nmask(p->ip)))
597 /* never reply with a negative response to broadcast queries */
602 /* name is directed query, or it's self, or it's a Domain Master type
603 name, or we're replying on behalf of a caller because they are on a
604 different subnet and cannot hear the broadcast. XXXX lp_wins_proxy
605 should be switched off in environments where broadcasts are forwarded
608 /* XXXX note: for proxy servers, we should forward the query on to
609 another WINS server if the name is not in our database, or we are
610 not a WINS server ourselves
612 ttl = n->death_time ? n->death_time - p->timestamp : GET_TTL(0);
613 retip = n->ip_flgs[0].ip;
614 nb_flags = n->ip_flgs[0].nb_flags;
617 if (!success && bcast) return; /* never reply negative response to bcasts */
619 /* if the IP is 0 then substitute my IP */
620 if (zero_ip(retip)) retip = *iface_ip(p->ip);
622 /* SPECIAL CASE... If we are a WINS server and the request is explicitly
623 *to* the WINS server and the name type is WORKGROUP<0x1e> we should
624 respond with the local broadcast address 255.255.255.255.
626 if(!bcast && (name_type == 0x1e) && lp_wins_support())
627 retip = *interpret_addr2("255.255.255.255");
632 DEBUG(3,("OK %s\n",inet_ntoa(retip)));
637 DEBUG(3,("UNKNOWN\n"));
644 putip(&rdata[2],(char *)&retip);
647 reply_netbios_packet(p,nmb->header.name_trn_id,
648 rcode,NMB_QUERY,0,True,
649 &nmb->question.question_name,
652 rdata, success ? 6 : 0);