r395: BUG 1232: patch from landonf@opendarwin.org (Landon Fuller) to fix
[Samba/gebeck_regimport.git] / source / nmbd / nmbd_winsserver.c
blob582338d710a97871188d55a5b2df18249a886747
1 /*
2 Unix SMB/CIFS implementation.
3 NBT netbios routines and daemon - version 2
5 Copyright (C) Jeremy Allison 1994-2003
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.
23 #include "includes.h"
25 #define WINS_LIST "wins.dat"
26 #define WINS_VERSION 1
28 /****************************************************************************
29 Change the wins owner address in the record.
30 *****************************************************************************/
32 static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip)
34 if (namerec==NULL)
35 return;
36 namerec->data.wins_ip=wins_ip;
39 /****************************************************************************
40 Create the wins flags based on the nb flags and the input value.
41 *****************************************************************************/
43 static void update_wins_flag(struct name_record *namerec, int flags)
45 if (namerec==NULL)
46 return;
48 namerec->data.wins_flags=0x0;
50 /* if it's a group, it can be a normal or a special one */
51 if (namerec->data.nb_flags & NB_GROUP) {
52 if (namerec->name.name_type==0x1C)
53 namerec->data.wins_flags|=WINS_SGROUP;
54 else
55 if (namerec->data.num_ips>1)
56 namerec->data.wins_flags|=WINS_SGROUP;
57 else
58 namerec->data.wins_flags|=WINS_NGROUP;
59 } else {
60 /* can be unique or multi-homed */
61 if (namerec->data.num_ips>1)
62 namerec->data.wins_flags|=WINS_MHOMED;
63 else
64 namerec->data.wins_flags|=WINS_UNIQUE;
67 /* the node type are the same bits */
68 namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK;
70 /* the static bit is elsewhere */
71 if (namerec->data.death_time == PERMANENT_TTL)
72 namerec->data.wins_flags|=WINS_STATIC;
74 /* and add the given bits */
75 namerec->data.wins_flags|=flags;
77 DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n",
78 namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags));
81 /****************************************************************************
82 Return the general ID value and increase it if requested.
83 *****************************************************************************/
85 static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update)
88 * it's kept as a static here, to prevent people from messing
89 * with the value directly
92 static SMB_BIG_UINT general_id = 1;
94 DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id));
96 *current_id = general_id;
98 if (update)
99 general_id++;
102 /****************************************************************************
103 Possibly call the WINS hook external program when a WINS change is made.
104 *****************************************************************************/
106 static void wins_hook(const char *operation, struct name_record *namerec, int ttl)
108 pstring command;
109 char *cmd = lp_wins_hook();
110 char *p, *namestr;
111 int i;
113 if (!cmd || !*cmd) return;
115 for (p=namerec->name.name; *p; p++) {
116 if (!(isalnum((int)*p) || strchr_m("._-",*p))) {
117 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
118 return;
122 /* Use the name without the nametype (and scope) appended */
124 namestr = nmb_namestr(&namerec->name);
125 if ((p = strchr(namestr, '<')))
126 *p = 0;
128 p = command;
129 p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d",
130 cmd,
131 operation,
132 namestr,
133 namerec->name.name_type,
134 ttl);
136 for (i=0;i<namerec->data.num_ips;i++) {
137 p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.ip[i]));
140 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
141 smbrun(command, NULL);
145 /****************************************************************************
146 Determine if this packet should be allocated to the WINS server.
147 *****************************************************************************/
149 BOOL packet_is_for_wins_server(struct packet_struct *packet)
151 struct nmb_packet *nmb = &packet->packet.nmb;
153 /* Only unicast packets go to a WINS server. */
154 if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True)) {
155 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
156 return False;
159 /* Check for node status requests. */
160 if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY)
161 return False;
163 switch(nmb->header.opcode) {
165 * A WINS server issues WACKS, not receives them.
167 case NMB_WACK_OPCODE:
168 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
169 return False;
171 * A WINS server only processes registration and
172 * release requests, not responses.
174 case NMB_NAME_REG_OPCODE:
175 case NMB_NAME_MULTIHOMED_REG_OPCODE:
176 case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
177 case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
178 if(nmb->header.response) {
179 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
180 return False;
182 break;
184 case NMB_NAME_RELEASE_OPCODE:
185 if(nmb->header.response) {
186 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
187 return False;
189 break;
192 * Only process unicast name queries with rd = 1.
194 case NMB_NAME_QUERY_OPCODE:
195 if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired) {
196 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
197 return False;
199 break;
202 return True;
205 /****************************************************************************
206 Utility function to decide what ttl to give a register/refresh request.
207 *****************************************************************************/
209 static int get_ttl_from_packet(struct nmb_packet *nmb)
211 int ttl = nmb->additional->ttl;
213 if(ttl < lp_min_wins_ttl() )
214 ttl = lp_min_wins_ttl();
216 if(ttl > lp_max_wins_ttl() )
217 ttl = lp_max_wins_ttl();
219 return ttl;
222 /****************************************************************************
223 Load or create the WINS database.
224 *****************************************************************************/
226 BOOL initialise_wins(void)
228 time_t time_now = time(NULL);
229 XFILE *fp;
230 pstring line;
232 if(!lp_we_are_a_wins_server())
233 return True;
235 add_samba_names_to_subnet(wins_server_subnet);
237 if((fp = x_fopen(lock_path(WINS_LIST),O_RDONLY,0)) == NULL) {
238 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
239 WINS_LIST, strerror(errno) ));
240 return True;
243 while (!x_feof(fp)) {
244 pstring name_str, ip_str, ttl_str, nb_flags_str;
245 unsigned int num_ips;
246 pstring name;
247 struct in_addr *ip_list;
248 int type = 0;
249 int nb_flags;
250 int ttl;
251 const char *ptr;
252 char *p;
253 BOOL got_token;
254 BOOL was_ip;
255 int i;
256 unsigned int hash;
257 int version;
259 /* Read a line from the wins.dat file. Strips whitespace
260 from the beginning and end of the line. */
261 if (!fgets_slash(line,sizeof(pstring),fp))
262 continue;
264 if (*line == '#')
265 continue;
267 if (strncmp(line,"VERSION ", 8) == 0) {
268 if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||
269 version != WINS_VERSION) {
270 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line));
271 x_fclose(fp);
272 return True;
274 continue;
277 ptr = line;
280 * Now we handle multiple IP addresses per name we need
281 * to iterate over the line twice. The first time to
282 * determine how many IP addresses there are, the second
283 * time to actually parse them into the ip_list array.
286 if (!next_token(&ptr,name_str,NULL,sizeof(name_str))) {
287 DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));
288 continue;
291 if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str))) {
292 DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));
293 continue;
297 * Determine the number of IP addresses per line.
299 num_ips = 0;
300 do {
301 got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str));
302 was_ip = False;
304 if(got_token && strchr(ip_str, '.')) {
305 num_ips++;
306 was_ip = True;
308 } while( got_token && was_ip);
310 if(num_ips == 0) {
311 DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line ));
312 continue;
315 if(!got_token) {
316 DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line ));
317 continue;
320 /* Allocate the space for the ip_list. */
321 if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL) {
322 DEBUG(0,("initialise_wins: Malloc fail !\n"));
323 return False;
326 /* Reset and re-parse the line. */
327 ptr = line;
328 next_token(&ptr,name_str,NULL,sizeof(name_str));
329 next_token(&ptr,ttl_str,NULL,sizeof(ttl_str));
330 for(i = 0; i < num_ips; i++) {
331 next_token(&ptr, ip_str, NULL, sizeof(ip_str));
332 ip_list[i] = *interpret_addr2(ip_str);
334 next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str));
337 * Deal with SELF or REGISTER name encoding. Default is REGISTER
338 * for compatibility with old nmbds.
341 if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') {
342 DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line));
343 SAFE_FREE(ip_list);
344 continue;
347 if(nb_flags_str[strlen(nb_flags_str)-1] == 'R')
348 nb_flags_str[strlen(nb_flags_str)-1] = '\0';
350 /* Netbios name. # divides the name from the type (hex): netbios#xx */
351 pstrcpy(name,name_str);
353 if((p = strchr(name,'#')) != NULL) {
354 *p = 0;
355 sscanf(p+1,"%x",&type);
358 /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
359 sscanf(nb_flags_str,"%x",&nb_flags);
360 sscanf(ttl_str,"%d",&ttl);
362 /* add all entries that have 60 seconds or more to live */
363 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {
364 if(ttl != PERMANENT_TTL)
365 ttl -= time_now;
367 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
368 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
370 (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
371 ttl, REGISTER_NAME, num_ips, ip_list );
372 } else {
373 DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n",
374 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
377 SAFE_FREE(ip_list);
380 x_fclose(fp);
381 return True;
384 /****************************************************************************
385 Send a WINS WACK (Wait ACKnowledgement) response.
386 **************************************************************************/
388 static void send_wins_wack_response(int ttl, struct packet_struct *p)
390 struct nmb_packet *nmb = &p->packet.nmb;
391 unsigned char rdata[2];
393 rdata[0] = rdata[1] = 0;
395 /* Taken from nmblib.c - we need to send back almost
396 identical bytes from the requesting packet header. */
398 rdata[0] = (nmb->header.opcode & 0xF) << 3;
399 if (nmb->header.nm_flags.authoritative && nmb->header.response)
400 rdata[0] |= 0x4;
401 if (nmb->header.nm_flags.trunc)
402 rdata[0] |= 0x2;
403 if (nmb->header.nm_flags.recursion_desired)
404 rdata[0] |= 0x1;
405 if (nmb->header.nm_flags.recursion_available && nmb->header.response)
406 rdata[1] |= 0x80;
407 if (nmb->header.nm_flags.bcast)
408 rdata[1] |= 0x10;
410 reply_netbios_packet(p, /* Packet to reply to. */
411 0, /* Result code. */
412 NMB_WAIT_ACK, /* nmbd type code. */
413 NMB_WACK_OPCODE, /* opcode. */
414 ttl, /* ttl. */
415 (char *)rdata, /* data to send. */
416 2); /* data length. */
419 /****************************************************************************
420 Send a WINS name registration response.
421 **************************************************************************/
423 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
425 struct nmb_packet *nmb = &p->packet.nmb;
426 char rdata[6];
428 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
430 reply_netbios_packet(p, /* Packet to reply to. */
431 rcode, /* Result code. */
432 WINS_REG, /* nmbd type code. */
433 NMB_NAME_REG_OPCODE, /* opcode. */
434 ttl, /* ttl. */
435 rdata, /* data to send. */
436 6); /* data length. */
439 /***********************************************************************
440 Deal with a name refresh request to a WINS server.
441 ************************************************************************/
443 void wins_process_name_refresh_request( struct subnet_record *subrec,
444 struct packet_struct *p )
446 struct nmb_packet *nmb = &p->packet.nmb;
447 struct nmb_name *question = &nmb->question.question_name;
448 BOOL bcast = nmb->header.nm_flags.bcast;
449 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
450 BOOL group = (nb_flags & NB_GROUP) ? True : False;
451 struct name_record *namerec = NULL;
452 int ttl = get_ttl_from_packet(nmb);
453 struct in_addr from_ip;
454 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
456 putip( (char *)&from_ip, &nmb->additional->rdata[2] );
458 if(bcast) {
460 * We should only get unicast name refresh packets here.
461 * Anyone trying to refresh broadcast should not be going
462 * to a WINS server. Log an error here.
464 if( DEBUGLVL( 0 ) ) {
465 dbgtext( "wins_process_name_refresh_request: " );
466 dbgtext( "Broadcast name refresh request received " );
467 dbgtext( "for name %s ", nmb_namestr(question) );
468 dbgtext( "from IP %s ", inet_ntoa(from_ip) );
469 dbgtext( "on subnet %s. ", subrec->subnet_name );
470 dbgtext( "Error - Broadcasts should not be sent " );
471 dbgtext( "to a WINS server\n" );
473 return;
476 if( DEBUGLVL( 3 ) ) {
477 dbgtext( "wins_process_name_refresh_request: " );
478 dbgtext( "Name refresh for name %s IP %s\n",
479 nmb_namestr(question), inet_ntoa(from_ip) );
483 * See if the name already exists.
484 * If not, handle it as a name registration and return.
486 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
489 * If this is a refresh request and the name doesn't exist then
490 * treat it like a registration request. This allows us to recover
491 * from errors (tridge)
493 if(namerec == NULL) {
494 if( DEBUGLVL( 3 ) ) {
495 dbgtext( "wins_process_name_refresh_request: " );
496 dbgtext( "Name refresh for name %s ",
497 nmb_namestr( question ) );
498 dbgtext( "and the name does not exist. Treating " );
499 dbgtext( "as registration.\n" );
501 wins_process_name_registration_request(subrec,p);
502 return;
506 * if the name is present but not active, simply remove it
507 * and treat the refresh request as a registration & return.
509 if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) {
510 if( DEBUGLVL( 5 ) ) {
511 dbgtext( "wins_process_name_refresh_request: " );
512 dbgtext( "Name (%s) in WINS ", nmb_namestr(question) );
513 dbgtext( "was not active - removing it.\n" );
515 remove_name_from_namelist( subrec, namerec );
516 namerec = NULL;
517 wins_process_name_registration_request( subrec, p );
518 return;
522 * Check that the group bits for the refreshing name and the
523 * name in our database match. If not, refuse the refresh.
524 * [crh: Why RFS_ERR instead of ACT_ERR? Is this what MS does?]
526 if( (namerec != NULL) &&
527 ( (group && !NAME_GROUP(namerec))
528 || (!group && NAME_GROUP(namerec)) ) ) {
529 if( DEBUGLVL( 3 ) ) {
530 dbgtext( "wins_process_name_refresh_request: " );
531 dbgtext( "Name %s ", nmb_namestr(question) );
532 dbgtext( "group bit = %s does not match ",
533 group ? "True" : "False" );
534 dbgtext( "group bit in WINS for this name.\n" );
536 send_wins_name_registration_response(RFS_ERR, 0, p);
537 return;
541 * For a unique name check that the person refreshing the name is
542 * one of the registered IP addresses. If not - fail the refresh.
543 * Do the same for group names with a type of 0x1c.
544 * Just return success for unique 0x1d refreshes. For normal group
545 * names update the ttl and return success.
547 if( (!group || (group && (question->name_type == 0x1c)))
548 && find_ip_in_name_record(namerec, from_ip) ) {
550 * Update the ttl.
552 update_name_ttl(namerec, ttl);
555 * if the record is a replica:
556 * we take ownership and update the version ID.
558 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
559 update_wins_owner(namerec, our_fake_ip);
560 get_global_id_and_update(&namerec->data.id, True);
563 send_wins_name_registration_response(0, ttl, p);
564 wins_hook("refresh", namerec, ttl);
565 return;
566 } else if((group && (question->name_type == 0x1c))) {
568 * Added by crh for bug #1079.
569 * Fix from Bert Driehuis
571 if( DEBUGLVL( 3 ) ) {
572 dbgtext( "wins_process_name_refresh_request: " );
573 dbgtext( "Name refresh for name %s, ",
574 nmb_namestr(question) );
575 dbgtext( "but IP address %s ", inet_ntoa(from_ip) );
576 dbgtext( "is not yet associated with " );
577 dbgtext( "that name. Treating as registration.\n" );
579 wins_process_name_registration_request(subrec,p);
580 return;
581 } else if(group) {
583 * Normal groups are all registered with an IP address of
584 * 255.255.255.255 so we can't search for the IP address.
586 update_name_ttl(namerec, ttl);
587 send_wins_name_registration_response(0, ttl, p);
588 return;
589 } else if(!group && (question->name_type == 0x1d)) {
591 * Special name type - just pretend the refresh succeeded.
593 send_wins_name_registration_response(0, ttl, p);
594 return;
595 } else {
597 * Fail the refresh.
599 if( DEBUGLVL( 3 ) ) {
600 dbgtext( "wins_process_name_refresh_request: " );
601 dbgtext( "Name refresh for name %s with IP %s ",
602 nmb_namestr(question), inet_ntoa(from_ip) );
603 dbgtext( "and is IP is not known to the name.\n" );
605 send_wins_name_registration_response(RFS_ERR, 0, p);
606 return;
610 /***********************************************************************
611 Deal with a name registration request query success to a client that
612 owned the name.
614 We have a locked pointer to the original packet stashed away in the
615 userdata pointer. The success here is actually a failure as it means
616 the client we queried wants to keep the name, so we must return
617 a registration failure to the original requestor.
618 ************************************************************************/
620 static void wins_register_query_success(struct subnet_record *subrec,
621 struct userdata_struct *userdata,
622 struct nmb_name *question_name,
623 struct in_addr ip,
624 struct res_rec *answers)
626 struct packet_struct *orig_reg_packet;
628 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
630 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
631 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
633 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
635 orig_reg_packet->locked = False;
636 free_packet(orig_reg_packet);
639 /***********************************************************************
640 Deal with a name registration request query failure to a client that
641 owned the name.
643 We have a locked pointer to the original packet stashed away in the
644 userdata pointer. The failure here is actually a success as it means
645 the client we queried didn't want to keep the name, so we can remove
646 the old name record and then successfully add the new name.
647 ************************************************************************/
649 static void wins_register_query_fail(struct subnet_record *subrec,
650 struct response_record *rrec,
651 struct nmb_name *question_name,
652 int rcode)
654 struct userdata_struct *userdata = rrec->userdata;
655 struct packet_struct *orig_reg_packet;
656 struct name_record *namerec = NULL;
658 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
661 * We want to just add the name, as we now know the original owner
662 * didn't want it. But we can't just do that as an arbitary
663 * amount of time may have taken place between the name query
664 * request and this timeout/error response. So we check that
665 * the name still exists and is in the same state - if so
666 * we remove it and call wins_process_name_registration_request()
667 * as we know it will do the right thing now.
670 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
672 if( (namerec != NULL) && (namerec->data.source == REGISTER_NAME) && ip_equal(rrec->packet->ip, *namerec->data.ip) ) {
673 remove_name_from_namelist( subrec, namerec);
674 namerec = NULL;
677 if(namerec == NULL)
678 wins_process_name_registration_request(subrec, orig_reg_packet);
679 else
680 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \
681 querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) ));
683 orig_reg_packet->locked = False;
684 free_packet(orig_reg_packet);
687 /***********************************************************************
688 Deal with a name registration request to a WINS server.
690 Use the following pseudocode :
692 registering_group
695 +--------name exists
698 | +--- existing name is group
699 | | |
700 | | |
701 | | +--- add name (return).
704 | +--- exiting name is unique
707 | +--- query existing owner (return).
710 +--------name doesn't exist
713 +--- add name (return).
715 registering_unique
718 +--------name exists
721 | +--- existing name is group
722 | | |
723 | | |
724 | | +--- fail add (return).
725 | |
727 | +--- exiting name is unique
730 | +--- query existing owner (return).
733 +--------name doesn't exist
736 +--- add name (return).
738 As can be seen from the above, the two cases may be collapsed onto each
739 other with the exception of the case where the name already exists and
740 is a group name. This case we handle with an if statement.
742 ************************************************************************/
744 void wins_process_name_registration_request(struct subnet_record *subrec,
745 struct packet_struct *p)
747 unstring name;
748 struct nmb_packet *nmb = &p->packet.nmb;
749 struct nmb_name *question = &nmb->question.question_name;
750 BOOL bcast = nmb->header.nm_flags.bcast;
751 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
752 int ttl = get_ttl_from_packet(nmb);
753 struct name_record *namerec = NULL;
754 struct in_addr from_ip;
755 BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;
756 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
758 putip((char *)&from_ip,&nmb->additional->rdata[2]);
760 if(bcast) {
762 * We should only get unicast name registration packets here.
763 * Anyone trying to register broadcast should not be going to a WINS
764 * server. Log an error here.
767 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
768 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
769 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
770 return;
773 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
774 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
777 * See if the name already exists.
780 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
783 * if the record exists but NOT in active state,
784 * consider it dead.
786 if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
787 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
788 not active - removing it.\n", nmb_namestr(question) ));
789 remove_name_from_namelist( subrec, namerec );
790 namerec = NULL;
794 * Deal with the case where the name found was a dns entry.
795 * Remove it as we now have a NetBIOS client registering the
796 * name.
799 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
800 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
801 a dns lookup - removing it.\n", nmb_namestr(question) ));
802 remove_name_from_namelist( subrec, namerec );
803 namerec = NULL;
807 * Reject if the name exists and is not a REGISTER_NAME.
808 * (ie. Don't allow any static names to be overwritten.
811 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) {
812 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
813 to register name %s. Name already exists in WINS with source type %d.\n",
814 nmb_namestr(question), namerec->data.source ));
815 send_wins_name_registration_response(RFS_ERR, 0, p);
816 return;
820 * Special policy decisions based on MS documentation.
821 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
822 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
826 * A group name is always added as the local broadcast address, except
827 * for group names ending in 0x1c.
828 * Group names with type 0x1c are registered with individual IP addresses.
831 if(registering_group_name && (question->name_type != 0x1c))
832 from_ip = *interpret_addr2("255.255.255.255");
835 * Ignore all attempts to register a unique 0x1d name, although return success.
838 if(!registering_group_name && (question->name_type == 0x1d)) {
839 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
840 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
841 send_wins_name_registration_response(0, ttl, p);
842 return;
846 * Next two cases are the 'if statement' mentioned above.
849 if((namerec != NULL) && NAME_GROUP(namerec)) {
850 if(registering_group_name) {
852 * If we are adding a group name, the name exists and is also a group entry just add this
853 * IP address to it and update the ttl.
856 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
857 inet_ntoa(from_ip), nmb_namestr(question) ));
860 * Check the ip address is not already in the group.
863 if(!find_ip_in_name_record(namerec, from_ip)) {
864 add_ip_to_name_record(namerec, from_ip);
865 /* we need to update the record for replication */
866 get_global_id_and_update(&namerec->data.id, True);
869 * if the record is a replica, we must change
870 * the wins owner to us to make the replication updates
871 * it on the other wins servers.
872 * And when the partner will receive this record,
873 * it will update its own record.
876 update_wins_owner(namerec, our_fake_ip);
878 update_name_ttl(namerec, ttl);
879 send_wins_name_registration_response(0, ttl, p);
880 return;
881 } else {
884 * If we are adding a unique name, the name exists in the WINS db
885 * and is a group name then reject the registration.
887 * explanation: groups have a higher priority than unique names.
890 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
891 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
892 send_wins_name_registration_response(RFS_ERR, 0, p);
893 return;
898 * From here on down we know that if the name exists in the WINS db it is
899 * a unique name, not a group name.
903 * If the name exists and is one of our names then check the
904 * registering IP address. If it's not one of ours then automatically
905 * reject without doing the query - we know we will reject it.
908 if ( namerec != NULL )
909 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
911 if( is_myname(name) ) {
912 if(!ismyip(from_ip)) {
913 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
914 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
915 send_wins_name_registration_response(RFS_ERR, 0, p);
916 return;
917 } else {
919 * It's one of our names and one of our IP's - update the ttl.
921 update_name_ttl(namerec, ttl);
922 send_wins_name_registration_response(0, ttl, p);
923 wins_hook("refresh", namerec, ttl);
924 return;
929 * If the name exists and it is a unique registration and the registering IP
930 * is the same as the (single) already registered IP then just update the ttl.
932 * But not if the record is an active replica. IF it's a replica, it means it can be
933 * the same client which has moved and not yet expired. So we don't update
934 * the ttl in this case and go beyond to do a WACK and query the old client
937 if( !registering_group_name
938 && (namerec != NULL)
939 && (namerec->data.num_ips == 1)
940 && ip_equal( namerec->data.ip[0], from_ip )
941 && ip_equal(namerec->data.wins_ip, our_fake_ip) ) {
942 update_name_ttl( namerec, ttl );
943 send_wins_name_registration_response( 0, ttl, p );
944 wins_hook("refresh", namerec, ttl);
945 return;
949 * Finally if the name exists do a query to the registering machine
950 * to see if they still claim to have the name.
953 if( namerec != NULL ) {
954 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
955 struct userdata_struct *userdata = (struct userdata_struct *)ud;
958 * First send a WACK to the registering machine.
961 send_wins_wack_response(60, p);
964 * When the reply comes back we need the original packet.
965 * Lock this so it won't be freed and then put it into
966 * the userdata structure.
969 p->locked = True;
971 userdata = (struct userdata_struct *)ud;
973 userdata->copy_fn = NULL;
974 userdata->free_fn = NULL;
975 userdata->userdata_len = sizeof(struct packet_struct *);
976 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
979 * Use the new call to send a query directly to an IP address.
980 * This sends the query directly to the IP address, and ensures
981 * the recursion desired flag is not set (you were right Luke :-).
982 * This function should *only* be called from the WINS server
983 * code. JRA.
986 pull_ascii_nstring(name, sizeof(name), question->name);
987 query_name_from_wins_server( *namerec->data.ip,
988 name,
989 question->name_type,
990 wins_register_query_success,
991 wins_register_query_fail,
992 userdata );
993 return;
997 * Name did not exist - add it.
1000 pull_ascii_nstring(name, sizeof(name), question->name);
1001 add_name_to_subnet( subrec, name, question->name_type,
1002 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1004 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1005 get_global_id_and_update(&namerec->data.id, True);
1006 update_wins_owner(namerec, our_fake_ip);
1007 update_wins_flag(namerec, WINS_ACTIVE);
1008 wins_hook("add", namerec, ttl);
1011 send_wins_name_registration_response(0, ttl, p);
1014 /***********************************************************************
1015 Deal with a mutihomed name query success to the machine that
1016 requested the multihomed name registration.
1018 We have a locked pointer to the original packet stashed away in the
1019 userdata pointer.
1020 ************************************************************************/
1022 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
1023 struct userdata_struct *userdata,
1024 struct nmb_name *question_name,
1025 struct in_addr ip,
1026 struct res_rec *answers)
1028 struct packet_struct *orig_reg_packet;
1029 struct nmb_packet *nmb;
1030 struct name_record *namerec = NULL;
1031 struct in_addr from_ip;
1032 int ttl;
1033 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1035 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1037 nmb = &orig_reg_packet->packet.nmb;
1039 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1040 ttl = get_ttl_from_packet(nmb);
1043 * We want to just add the new IP, as we now know the requesting
1044 * machine claims to own it. But we can't just do that as an arbitary
1045 * amount of time may have taken place between the name query
1046 * request and this response. So we check that
1047 * the name still exists and is in the same state - if so
1048 * we just add the extra IP and update the ttl.
1051 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1053 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) {
1054 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
1055 a subsequent IP address.\n", nmb_namestr(question_name) ));
1056 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1058 orig_reg_packet->locked = False;
1059 free_packet(orig_reg_packet);
1061 return;
1064 if(!find_ip_in_name_record(namerec, from_ip))
1065 add_ip_to_name_record(namerec, from_ip);
1067 get_global_id_and_update(&namerec->data.id, True);
1068 update_wins_owner(namerec, our_fake_ip);
1069 update_wins_flag(namerec, WINS_ACTIVE);
1070 update_name_ttl(namerec, ttl);
1071 send_wins_name_registration_response(0, ttl, orig_reg_packet);
1072 wins_hook("add", namerec, ttl);
1074 orig_reg_packet->locked = False;
1075 free_packet(orig_reg_packet);
1078 /***********************************************************************
1079 Deal with a name registration request query failure to a client that
1080 owned the name.
1082 We have a locked pointer to the original packet stashed away in the
1083 userdata pointer.
1084 ************************************************************************/
1086 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
1087 struct response_record *rrec,
1088 struct nmb_name *question_name,
1089 int rcode)
1091 struct userdata_struct *userdata = rrec->userdata;
1092 struct packet_struct *orig_reg_packet;
1094 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1096 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1097 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
1098 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1100 orig_reg_packet->locked = False;
1101 free_packet(orig_reg_packet);
1102 return;
1105 /***********************************************************************
1106 Deal with a multihomed name registration request to a WINS server.
1107 These cannot be group name registrations.
1108 ***********************************************************************/
1110 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
1111 struct packet_struct *p)
1113 struct nmb_packet *nmb = &p->packet.nmb;
1114 struct nmb_name *question = &nmb->question.question_name;
1115 BOOL bcast = nmb->header.nm_flags.bcast;
1116 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1117 int ttl = get_ttl_from_packet(nmb);
1118 struct name_record *namerec = NULL;
1119 struct in_addr from_ip;
1120 BOOL group = (nb_flags & NB_GROUP) ? True : False;
1121 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1122 unstring qname;
1124 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1126 if(bcast) {
1128 * We should only get unicast name registration packets here.
1129 * Anyone trying to register broadcast should not be going to a WINS
1130 * server. Log an error here.
1133 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1134 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1135 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1136 return;
1140 * Only unique names should be registered multihomed.
1143 if(group) {
1144 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1145 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1146 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1147 return;
1150 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1151 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1154 * Deal with policy regarding 0x1d names.
1157 if(question->name_type == 0x1d) {
1158 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1159 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1160 send_wins_name_registration_response(0, ttl, p);
1161 return;
1165 * See if the name already exists.
1168 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1171 * if the record exists but NOT in active state,
1172 * consider it dead.
1175 if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1176 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question)));
1177 remove_name_from_namelist(subrec, namerec);
1178 namerec = NULL;
1182 * Deal with the case where the name found was a dns entry.
1183 * Remove it as we now have a NetBIOS client registering the
1184 * name.
1187 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1188 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1189 - removing it.\n", nmb_namestr(question) ));
1190 remove_name_from_namelist( subrec, namerec);
1191 namerec = NULL;
1195 * Reject if the name exists and is not a REGISTER_NAME.
1196 * (ie. Don't allow any static names to be overwritten.
1199 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) {
1200 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1201 to register name %s. Name already exists in WINS with source type %d.\n",
1202 nmb_namestr(question), namerec->data.source ));
1203 send_wins_name_registration_response(RFS_ERR, 0, p);
1204 return;
1208 * Reject if the name exists and is a GROUP name and is active.
1211 if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) {
1212 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1213 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1214 send_wins_name_registration_response(RFS_ERR, 0, p);
1215 return;
1219 * From here on down we know that if the name exists in the WINS db it is
1220 * a unique name, not a group name.
1224 * If the name exists and is one of our names then check the
1225 * registering IP address. If it's not one of ours then automatically
1226 * reject without doing the query - we know we will reject it.
1229 if((namerec != NULL) && (is_myname(namerec->name.name)) ) {
1230 if(!ismyip(from_ip)) {
1231 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1232 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1233 send_wins_name_registration_response(RFS_ERR, 0, p);
1234 return;
1235 } else {
1237 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1238 * update the ttl. Update the version ID to force replication.
1240 if(!find_ip_in_name_record(namerec, from_ip)) {
1241 get_global_id_and_update(&namerec->data.id, True);
1242 update_wins_owner(namerec, our_fake_ip);
1243 update_wins_flag(namerec, WINS_ACTIVE);
1245 add_ip_to_name_record(namerec, from_ip);
1246 wins_hook("add", namerec, ttl);
1247 } else {
1248 wins_hook("refresh", namerec, ttl);
1251 update_name_ttl(namerec, ttl);
1252 send_wins_name_registration_response(0, ttl, p);
1253 return;
1258 * If the name exists and is active, check if the IP address is already registered
1259 * to that name. If so then update the ttl and reply success.
1262 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) {
1263 update_name_ttl(namerec, ttl);
1266 * If it's a replica, we need to become the wins owner
1267 * to force the replication
1269 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1270 get_global_id_and_update(&namerec->data.id, True);
1271 update_wins_owner(namerec, our_fake_ip);
1272 update_wins_flag(namerec, WINS_ACTIVE);
1275 send_wins_name_registration_response(0, ttl, p);
1276 wins_hook("refresh", namerec, ttl);
1277 return;
1281 * If the name exists do a query to the owner
1282 * to see if they still want the name.
1285 if(namerec != NULL) {
1286 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1287 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1290 * First send a WACK to the registering machine.
1293 send_wins_wack_response(60, p);
1296 * When the reply comes back we need the original packet.
1297 * Lock this so it won't be freed and then put it into
1298 * the userdata structure.
1301 p->locked = True;
1303 userdata = (struct userdata_struct *)ud;
1305 userdata->copy_fn = NULL;
1306 userdata->free_fn = NULL;
1307 userdata->userdata_len = sizeof(struct packet_struct *);
1308 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1311 * Use the new call to send a query directly to an IP address.
1312 * This sends the query directly to the IP address, and ensures
1313 * the recursion desired flag is not set (you were right Luke :-).
1314 * This function should *only* be called from the WINS server
1315 * code. JRA.
1317 * Note that this packet is sent to the current owner of the name,
1318 * not the person who sent the packet
1321 pull_ascii_nstring( qname, sizeof(qname), question->name);
1322 query_name_from_wins_server( namerec->data.ip[0],
1323 qname,
1324 question->name_type,
1325 wins_multihomed_register_query_success,
1326 wins_multihomed_register_query_fail,
1327 userdata );
1329 return;
1333 * Name did not exist - add it.
1336 pull_ascii_nstring( qname, sizeof(qname), question->name);
1337 add_name_to_subnet( subrec, qname, question->name_type,
1338 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1340 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1341 get_global_id_and_update(&namerec->data.id, True);
1342 update_wins_owner(namerec, our_fake_ip);
1343 update_wins_flag(namerec, WINS_ACTIVE);
1344 wins_hook("add", namerec, ttl);
1347 send_wins_name_registration_response(0, ttl, p);
1350 /***********************************************************************
1351 Deal with the special name query for *<1b>.
1352 ***********************************************************************/
1354 static void process_wins_dmb_query_request(struct subnet_record *subrec,
1355 struct packet_struct *p)
1357 struct name_record *namerec = NULL;
1358 char *prdata;
1359 int num_ips;
1362 * Go through all the ACTIVE names in the WINS db looking for those
1363 * ending in <1b>. Use this to calculate the number of IP
1364 * addresses we need to return.
1367 num_ips = 0;
1368 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1369 namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {
1370 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b )
1371 num_ips += namerec->data.num_ips;
1374 if(num_ips == 0) {
1376 * There are no 0x1b names registered. Return name query fail.
1378 send_wins_name_query_response(NAM_ERR, p, NULL);
1379 return;
1382 if((prdata = (char *)malloc( num_ips * 6 )) == NULL) {
1383 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1384 return;
1388 * Go through all the names again in the WINS db looking for those
1389 * ending in <1b>. Add their IP addresses into the list we will
1390 * return.
1393 num_ips = 0;
1394 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1395 namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {
1396 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1397 int i;
1398 for(i = 0; i < namerec->data.num_ips; i++) {
1399 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1400 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1401 num_ips++;
1407 * Send back the reply containing the IP list.
1410 reply_netbios_packet(p, /* Packet to reply to. */
1411 0, /* Result code. */
1412 WINS_QUERY, /* nmbd type code. */
1413 NMB_NAME_QUERY_OPCODE, /* opcode. */
1414 lp_min_wins_ttl(), /* ttl. */
1415 prdata, /* data to send. */
1416 num_ips*6); /* data length. */
1418 SAFE_FREE(prdata);
1421 /****************************************************************************
1422 Send a WINS name query response.
1423 **************************************************************************/
1425 void send_wins_name_query_response(int rcode, struct packet_struct *p,
1426 struct name_record *namerec)
1428 char rdata[6];
1429 char *prdata = rdata;
1430 int reply_data_len = 0;
1431 int ttl = 0;
1432 int i;
1434 memset(rdata,'\0',6);
1436 if(rcode == 0) {
1437 ttl = (namerec->data.death_time != PERMANENT_TTL) ? namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1439 /* Copy all known ip addresses into the return data. */
1440 /* Optimise for the common case of one IP address so we don't need a malloc. */
1442 if( namerec->data.num_ips == 1 ) {
1443 prdata = rdata;
1444 } else {
1445 if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL) {
1446 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1447 return;
1451 for(i = 0; i < namerec->data.num_ips; i++) {
1452 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
1453 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
1456 sort_query_replies(prdata, i, p->ip);
1457 reply_data_len = namerec->data.num_ips * 6;
1460 reply_netbios_packet(p, /* Packet to reply to. */
1461 rcode, /* Result code. */
1462 WINS_QUERY, /* nmbd type code. */
1463 NMB_NAME_QUERY_OPCODE, /* opcode. */
1464 ttl, /* ttl. */
1465 prdata, /* data to send. */
1466 reply_data_len); /* data length. */
1468 if(prdata != rdata)
1469 SAFE_FREE(prdata);
1472 /***********************************************************************
1473 Deal with a name query.
1474 ***********************************************************************/
1476 void wins_process_name_query_request(struct subnet_record *subrec,
1477 struct packet_struct *p)
1479 struct nmb_packet *nmb = &p->packet.nmb;
1480 struct nmb_name *question = &nmb->question.question_name;
1481 struct name_record *namerec = NULL;
1482 unstring qname;
1484 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
1485 nmb_namestr(question), inet_ntoa(p->ip) ));
1488 * Special name code. If the queried name is *<1b> then search
1489 * the entire WINS database and return a list of all the IP addresses
1490 * registered to any <1b> name. This is to allow domain master browsers
1491 * to discover other domains that may not have a presence on their subnet.
1494 pull_ascii_nstring(qname, sizeof(qname), question->name);
1495 if(strequal( qname, "*") && (question->name_type == 0x1b)) {
1496 process_wins_dmb_query_request( subrec, p);
1497 return;
1500 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1502 if(namerec != NULL) {
1504 * If the name is not anymore in active state then reply not found.
1505 * it's fair even if we keep it in the cache for days.
1507 if (!WINS_STATE_ACTIVE(namerec)) {
1508 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1509 nmb_namestr(question) ));
1510 send_wins_name_query_response(NAM_ERR, p, namerec);
1511 return;
1515 * If it's a DNSFAIL_NAME then reply name not found.
1518 if( namerec->data.source == DNSFAIL_NAME ) {
1519 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
1520 nmb_namestr(question) ));
1521 send_wins_name_query_response(NAM_ERR, p, namerec);
1522 return;
1526 * If the name has expired then reply name not found.
1529 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < p->timestamp) ) {
1530 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1531 nmb_namestr(question) ));
1532 send_wins_name_query_response(NAM_ERR, p, namerec);
1533 return;
1536 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
1537 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
1539 send_wins_name_query_response(0, p, namerec);
1540 return;
1544 * Name not found in WINS - try a dns query if it's a 0x20 name.
1547 if(lp_dns_proxy() && ((question->name_type == 0x20) || question->name_type == 0)) {
1548 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
1549 nmb_namestr(question) ));
1551 queue_dns_query(p, question, &namerec);
1552 return;
1556 * Name not found - return error.
1559 send_wins_name_query_response(NAM_ERR, p, NULL);
1562 /****************************************************************************
1563 Send a WINS name release response.
1564 **************************************************************************/
1566 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
1568 struct nmb_packet *nmb = &p->packet.nmb;
1569 char rdata[6];
1571 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
1573 reply_netbios_packet(p, /* Packet to reply to. */
1574 rcode, /* Result code. */
1575 NMB_REL, /* nmbd type code. */
1576 NMB_NAME_RELEASE_OPCODE, /* opcode. */
1577 0, /* ttl. */
1578 rdata, /* data to send. */
1579 6); /* data length. */
1582 /***********************************************************************
1583 Deal with a name release.
1584 ***********************************************************************/
1586 void wins_process_name_release_request(struct subnet_record *subrec,
1587 struct packet_struct *p)
1589 struct nmb_packet *nmb = &p->packet.nmb;
1590 struct nmb_name *question = &nmb->question.question_name;
1591 BOOL bcast = nmb->header.nm_flags.bcast;
1592 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1593 struct name_record *namerec = NULL;
1594 struct in_addr from_ip;
1595 BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
1597 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1599 if(bcast) {
1601 * We should only get unicast name registration packets here.
1602 * Anyone trying to register broadcast should not be going to a WINS
1603 * server. Log an error here.
1606 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
1607 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1608 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1609 return;
1612 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
1613 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1616 * Deal with policy regarding 0x1d names.
1619 if(!releasing_group_name && (question->name_type == 0x1d)) {
1620 DEBUG(3,("wins_process_name_release_request: Ignoring request \
1621 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1622 send_wins_name_release_response(0, p);
1623 return;
1627 * See if the name already exists.
1630 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1632 if( (namerec == NULL) || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) {
1633 send_wins_name_release_response(NAM_ERR, p);
1634 return;
1638 * Check that the sending machine has permission to release this name.
1639 * If it's a group name not ending in 0x1c then just say yes and let
1640 * the group time out.
1643 if(releasing_group_name && (question->name_type != 0x1c)) {
1644 send_wins_name_release_response(0, p);
1645 return;
1649 * Check that the releasing node is on the list of IP addresses
1650 * for this name. Disallow the release if not.
1653 if(!find_ip_in_name_record(namerec, from_ip)) {
1654 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1655 release name %s as IP %s is not one of the known IP's for this name.\n",
1656 nmb_namestr(question), inet_ntoa(from_ip) ));
1657 send_wins_name_release_response(NAM_ERR, p);
1658 return;
1662 * Check if the record is active. IF it's already released
1663 * or tombstoned, refuse the release.
1666 if (!WINS_STATE_ACTIVE(namerec)) {
1667 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1668 release name %s as this record is not active anymore.\n", nmb_namestr(question) ));
1669 send_wins_name_release_response(NAM_ERR, p);
1670 return;
1674 * Check if the record is a 0x1c group
1675 * and has more then one ip
1676 * remove only this address.
1679 if(releasing_group_name && (question->name_type == 0x1c) && (namerec->data.num_ips > 1)) {
1680 remove_ip_from_name_record(namerec, from_ip);
1681 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
1682 inet_ntoa(from_ip),nmb_namestr(question)));
1683 send_wins_name_release_response(0, p);
1684 return;
1688 * Send a release response.
1689 * Flag the name as released and update the ttl
1692 send_wins_name_release_response(0, p);
1694 namerec->data.wins_flags |= WINS_RELEASED;
1695 update_name_ttl(namerec, EXTINCTION_INTERVAL);
1697 wins_hook("delete", namerec, 0);
1700 /*******************************************************************
1701 WINS time dependent processing.
1702 ******************************************************************/
1704 void initiate_wins_processing(time_t t)
1706 static time_t lasttime = 0;
1707 struct name_record *namerec;
1708 struct name_record *next_namerec;
1709 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1711 if (!lasttime)
1712 lasttime = t;
1713 if (t - lasttime < 20)
1714 return;
1716 lasttime = t;
1718 if(!lp_we_are_a_wins_server())
1719 return;
1721 for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
1722 namerec;
1723 namerec = next_namerec ) {
1724 next_namerec = (struct name_record *)ubi_trNext( namerec );
1726 if( (namerec->data.death_time != PERMANENT_TTL)
1727 && (namerec->data.death_time < t) ) {
1729 if( namerec->data.source == SELF_NAME ) {
1730 DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF name %s\n",
1731 wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
1732 namerec->data.death_time += 300;
1733 namerec->subnet->namelist_changed = True;
1734 continue;
1737 /* handle records, samba is the wins owner */
1738 if (ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1739 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
1740 case WINS_ACTIVE:
1741 namerec->data.wins_flags&=~WINS_STATE_MASK;
1742 namerec->data.wins_flags|=WINS_RELEASED;
1743 namerec->data.death_time = t + EXTINCTION_INTERVAL;
1744 DEBUG(3,("initiate_wins_processing: expiring %s\n", nmb_namestr(&namerec->name)));
1745 break;
1746 case WINS_RELEASED:
1747 namerec->data.wins_flags&=~WINS_STATE_MASK;
1748 namerec->data.wins_flags|=WINS_TOMBSTONED;
1749 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
1750 get_global_id_and_update(&namerec->data.id, True);
1751 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
1752 break;
1753 case WINS_TOMBSTONED:
1754 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
1755 remove_name_from_namelist( wins_server_subnet, namerec );
1756 break;
1758 } else {
1759 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
1760 case WINS_ACTIVE:
1761 /* that's not as MS says it should be */
1762 namerec->data.wins_flags&=~WINS_STATE_MASK;
1763 namerec->data.wins_flags|=WINS_TOMBSTONED;
1764 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
1765 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
1766 case WINS_TOMBSTONED:
1767 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
1768 remove_name_from_namelist( wins_server_subnet, namerec );
1769 break;
1770 case WINS_RELEASED:
1771 DEBUG(0,("initiate_wins_processing: %s is in released state and\
1772 we are not the wins owner !\n", nmb_namestr(&namerec->name)));
1773 break;
1780 if(wins_server_subnet->namelist_changed)
1781 wins_write_database(True);
1783 wins_server_subnet->namelist_changed = False;
1786 /*******************************************************************
1787 Write out the current WINS database.
1788 ******************************************************************/
1790 void wins_write_database(BOOL background)
1792 struct name_record *namerec;
1793 pstring fname, fnamenew;
1795 XFILE *fp;
1797 if(!lp_we_are_a_wins_server())
1798 return;
1800 /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */
1801 if (background) {
1802 CatchChild();
1803 if (sys_fork()) {
1804 return;
1808 slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST);
1809 all_string_sub(fname,"//", "/", 0);
1810 slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid());
1812 if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) {
1813 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
1814 if (background) {
1815 _exit(0);
1817 return;
1820 DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
1822 x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0);
1824 for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {
1825 int i;
1826 struct tm *tm;
1828 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
1830 if( namerec->data.death_time != PERMANENT_TTL ) {
1831 char *ts, *nl;
1833 tm = LocalTime(&namerec->data.death_time);
1834 ts = asctime(tm);
1835 nl = strrchr( ts, '\n' );
1836 if( NULL != nl )
1837 *nl = '\0';
1838 DEBUGADD(4,("TTL = %s ", ts ));
1839 } else {
1840 DEBUGADD(4,("TTL = PERMANENT "));
1843 for (i = 0; i < namerec->data.num_ips; i++)
1844 DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
1845 DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
1847 if( namerec->data.source == REGISTER_NAME ) {
1848 unstring name;
1849 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
1850 x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */
1851 (int)namerec->data.death_time);
1853 for (i = 0; i < namerec->data.num_ips; i++)
1854 x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
1855 x_fprintf( fp, "%2xR\n", namerec->data.nb_flags );
1859 x_fclose(fp);
1860 chmod(fnamenew,0644);
1861 unlink(fname);
1862 rename(fnamenew,fname);
1863 if (background) {
1864 _exit(0);
1868 /****************************************************************************
1869 Process a internal Samba message receiving a wins record.
1870 ***************************************************************************/
1872 void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len)
1874 WINS_RECORD *record;
1875 struct name_record *namerec = NULL;
1876 struct name_record *new_namerec = NULL;
1877 struct nmb_name question;
1878 BOOL overwrite=False;
1879 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1880 int i;
1882 if (buf==NULL)
1883 return;
1885 /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */
1886 record=(WINS_RECORD *)buf;
1888 make_nmb_name(&question, record->name, record->type);
1890 namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
1892 /* record doesn't exist, add it */
1893 if (namerec == NULL) {
1894 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
1895 record->name, record->type, inet_ntoa(record->wins_ip)));
1897 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
1898 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
1899 if (new_namerec!=NULL) {
1900 update_wins_owner(new_namerec, record->wins_ip);
1901 update_wins_flag(new_namerec, record->wins_flags);
1902 new_namerec->data.id=record->id;
1904 wins_server_subnet->namelist_changed = True;
1908 /* check if we have a conflict */
1909 if (namerec != NULL) {
1910 /* both records are UNIQUE */
1911 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
1913 /* the database record is a replica */
1914 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1915 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
1916 if (ip_equal(namerec->data.wins_ip, record->wins_ip))
1917 overwrite=True;
1918 } else
1919 overwrite=True;
1920 } else {
1921 /* we are the wins owner of the database record */
1922 /* the 2 records have the same IP address */
1923 if (ip_equal(namerec->data.ip[0], record->ip[0])) {
1924 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
1925 get_global_id_and_update(&namerec->data.id, True);
1926 else
1927 overwrite=True;
1929 } else {
1930 /* the 2 records have different IP address */
1931 if (namerec->data.wins_flags&WINS_ACTIVE) {
1932 if (record->wins_flags&WINS_TOMBSTONED)
1933 get_global_id_and_update(&namerec->data.id, True);
1934 if (record->wins_flags&WINS_ACTIVE)
1935 /* send conflict challenge to the replica node */
1937 } else
1938 overwrite=True;
1944 /* the replica is a standard group */
1945 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {
1946 /* if the database record is unique and active force a name release */
1947 if (namerec->data.wins_flags&WINS_UNIQUE)
1948 /* send a release name to the unique node */
1950 overwrite=True;
1954 /* the replica is a special group */
1955 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
1956 if (namerec->data.wins_flags&WINS_ACTIVE) {
1957 for (i=0; i<record->num_ips; i++)
1958 if(!find_ip_in_name_record(namerec, record->ip[i]))
1959 add_ip_to_name_record(namerec, record->ip[i]);
1960 } else {
1961 overwrite=True;
1965 /* the replica is a multihomed host */
1967 /* I'm giving up on multi homed. Too much complex to understand */
1969 if (record->wins_flags&WINS_MHOMED) {
1970 if (! (namerec->data.wins_flags&WINS_ACTIVE)) {
1971 if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP))
1972 overwrite=True;
1974 else {
1975 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
1976 overwrite=True;
1978 if (ip_equal(namerec->data.wins_ip, our_fake_ip))
1979 if (namerec->data.wins_flags&WINS_UNIQUE)
1980 get_global_id_and_update(&namerec->data.id, True);
1984 if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
1985 if (namerec->data.wins_flags&WINS_UNIQUE ||
1986 namerec->data.wins_flags&WINS_MHOMED)
1987 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
1988 overwrite=True;
1992 if (overwrite == False)
1993 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
1994 record->name, record->type, inet_ntoa(record->wins_ip)));
1995 else {
1996 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
1997 record->name, record->type, inet_ntoa(record->wins_ip)));
1999 /* remove the old record and add a new one */
2000 remove_name_from_namelist( wins_server_subnet, namerec );
2001 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
2002 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
2003 if (new_namerec!=NULL) {
2004 update_wins_owner(new_namerec, record->wins_ip);
2005 update_wins_flag(new_namerec, record->wins_flags);
2006 new_namerec->data.id=record->id;
2008 wins_server_subnet->namelist_changed = True;
2011 wins_server_subnet->namelist_changed = True;