2 Unix SMB/CIFS implementation.
3 NBT netbios routines and daemon - version 2
5 Copyright (C) Jeremy Allison 1994-1998
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.
25 #define WINS_LIST "wins.tdb"
26 #define WINS_VERSION 1
28 /****************************************************************************
29 change the wins owner address in the record.
30 *****************************************************************************/
31 static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip)
35 namerec->data.wins_ip=wins_ip;
38 /****************************************************************************
39 create the wins flags based on the nb flags and the input value.
40 *****************************************************************************/
41 static void update_wins_flag(struct name_record *namerec, int flags)
46 namerec->data.wins_flags=0x0;
48 /* if it's a group, it can be a normal or a special one */
49 if (namerec->data.nb_flags & NB_GROUP) {
50 if (namerec->name.name_type==0x1C)
51 namerec->data.wins_flags|=WINS_SGROUP;
53 if (namerec->data.num_ips>1)
54 namerec->data.wins_flags|=WINS_SGROUP;
56 namerec->data.wins_flags|=WINS_NGROUP;
58 /* can be unique or multi-homed */
59 if (namerec->data.num_ips>1)
60 namerec->data.wins_flags|=WINS_MHOMED;
62 namerec->data.wins_flags|=WINS_UNIQUE;
65 /* the node type are the same bits */
66 namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK;
68 /* the static bit is elsewhere */
69 if (namerec->data.death_time == PERMANENT_TTL)
70 namerec->data.wins_flags|=WINS_STATIC;
72 /* and add the given bits */
73 namerec->data.wins_flags|=flags;
75 DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n",
76 namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags));
80 /****************************************************************************
81 return the general ID value and increase it if requested
82 *****************************************************************************/
83 static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update)
86 * it's kept as a static here, to prevent people from messing
87 * with the value directly
90 static SMB_BIG_UINT general_id = 1;
92 DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id));
94 *current_id = general_id;
100 /****************************************************************************
101 possibly call the WINS hook external program when a WINS change is made
102 *****************************************************************************/
103 static void wins_hook(char *operation, struct name_record *namerec, int ttl)
106 char *cmd = lp_wins_hook();
110 if (!cmd || !*cmd) return;
112 for (p=namerec->name.name; *p; p++) {
113 if (!(isalnum((int)*p) || strchr_m("._-",*p))) {
114 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
120 p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d",
124 namerec->name.name_type,
127 for (i=0;i<namerec->data.num_ips;i++) {
128 p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.ip[i]));
131 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
132 smbrun(command, NULL);
136 /****************************************************************************
137 Determine if this packet should be allocated to the WINS server.
138 *****************************************************************************/
140 BOOL packet_is_for_wins_server(struct packet_struct *packet)
142 struct nmb_packet *nmb = &packet->packet.nmb;
144 /* Only unicast packets go to a WINS server. */
145 if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True))
147 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
151 /* Check for node status requests. */
152 if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY)
155 switch(nmb->header.opcode)
158 * A WINS server issues WACKS, not receives them.
160 case NMB_WACK_OPCODE:
161 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
164 * A WINS server only processes registration and
165 * release requests, not responses.
167 case NMB_NAME_REG_OPCODE:
168 case NMB_NAME_MULTIHOMED_REG_OPCODE:
169 case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
170 case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
171 if(nmb->header.response)
173 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
178 case NMB_NAME_RELEASE_OPCODE:
179 if(nmb->header.response)
181 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
187 * Only process unicast name queries with rd = 1.
189 case NMB_NAME_QUERY_OPCODE:
190 if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired)
192 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
201 /****************************************************************************
202 Utility function to decide what ttl to give a register/refresh request.
203 *****************************************************************************/
205 static int get_ttl_from_packet(struct nmb_packet *nmb)
207 int ttl = nmb->additional->ttl;
209 if(ttl < lp_min_wins_ttl() )
210 ttl = lp_min_wins_ttl();
212 if(ttl > lp_max_wins_ttl() )
213 ttl = lp_max_wins_ttl();
218 /****************************************************************************
219 Load or create the WINS database.
220 *****************************************************************************/
222 BOOL initialise_wins(void)
224 time_t time_now = time(NULL);
226 TDB_DATA kbuf, dbuf, newkey;
227 struct name_record *namerec = NULL;
228 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
230 DEBUG(2,("initialise_wins: started\n"));
232 if(!lp_we_are_a_wins_server())
235 add_samba_names_to_subnet(wins_server_subnet);
237 tdb = tdb_open_log(lock_path(WINS_LIST), 0, TDB_DEFAULT, O_RDONLY, 0600);
239 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n", WINS_LIST, strerror(errno) ));
243 if (tdb_fetch_int32(tdb, INFO_VERSION) != WINS_VERSION) {
244 DEBUG(0,("Discarding invalid wins.dat file\n"));
249 for (kbuf = tdb_firstkey(tdb);
251 newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
253 pstring name_type, name, ip_str;
258 unsigned int num_ips;
260 struct in_addr wins_ip;
261 struct in_addr *ip_list;
265 if (strncmp(kbuf.dptr, ENTRY_PREFIX, strlen(ENTRY_PREFIX)) != 0)
268 dbuf = tdb_fetch(tdb, kbuf);
272 fstrcpy(name_type, kbuf.dptr+strlen(ENTRY_PREFIX));
274 pstrcpy(name, name_type);
276 if((p = strchr(name,'#')) != NULL) {
278 sscanf(p+1,"%x",&type);
281 len = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddfddd",
282 &nb_flags, &high, &low,
283 ip_str, &ttl, &num_ips, &wins_flags);
285 wins_ip=*interpret_addr2(ip_str);
287 /* Don't reload replica records */
288 if (!ip_equal(wins_ip, our_fake_ip)) {
289 SAFE_FREE(dbuf.dptr);
293 /* Don't reload released or tombstoned records */
294 if ((wins_flags&WINS_STATE_MASK) != WINS_ACTIVE) {
295 SAFE_FREE(dbuf.dptr);
299 /* Allocate the space for the ip_list. */
300 if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL) {
301 SAFE_FREE(dbuf.dptr);
302 DEBUG(0,("initialise_wins: Malloc fail !\n"));
306 for (i = 0; i < num_ips; i++) {
307 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f", ip_str);
308 ip_list[i] = *interpret_addr2(ip_str);
311 /* add all entries that have 60 seconds or more to live */
312 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {
313 if(ttl != PERMANENT_TTL)
316 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
317 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
319 namerec=add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
320 ttl, REGISTER_NAME, num_ips, ip_list);
322 update_wins_owner(namerec, wins_ip);
323 update_wins_flag(namerec, wins_flags);
324 /* we don't reload the ID, on startup we restart at 1 */
325 get_global_id_and_update(&namerec->data.id, True);
329 DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n",
330 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
333 SAFE_FREE(dbuf.dptr);
338 DEBUG(2,("initialise_wins: done\n"));
342 /****************************************************************************
343 Send a WINS WACK (Wait ACKnowledgement) response.
344 **************************************************************************/
346 static void send_wins_wack_response(int ttl, struct packet_struct *p)
348 struct nmb_packet *nmb = &p->packet.nmb;
349 unsigned char rdata[2];
351 rdata[0] = rdata[1] = 0;
353 /* Taken from nmblib.c - we need to send back almost
354 identical bytes from the requesting packet header. */
356 rdata[0] = (nmb->header.opcode & 0xF) << 3;
357 if (nmb->header.nm_flags.authoritative &&
358 nmb->header.response) rdata[0] |= 0x4;
359 if (nmb->header.nm_flags.trunc) rdata[0] |= 0x2;
360 if (nmb->header.nm_flags.recursion_desired) rdata[0] |= 0x1;
361 if (nmb->header.nm_flags.recursion_available &&
362 nmb->header.response) rdata[1] |= 0x80;
363 if (nmb->header.nm_flags.bcast) rdata[1] |= 0x10;
365 reply_netbios_packet(p, /* Packet to reply to. */
366 0, /* Result code. */
367 NMB_WAIT_ACK, /* nmbd type code. */
368 NMB_WACK_OPCODE, /* opcode. */
370 (char *)rdata, /* data to send. */
371 2); /* data length. */
374 /****************************************************************************
375 Send a WINS name registration response.
376 **************************************************************************/
378 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
380 struct nmb_packet *nmb = &p->packet.nmb;
383 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
385 reply_netbios_packet(p, /* Packet to reply to. */
386 rcode, /* Result code. */
387 WINS_REG, /* nmbd type code. */
388 NMB_NAME_REG_OPCODE, /* opcode. */
390 rdata, /* data to send. */
391 6); /* data length. */
394 /***********************************************************************
395 Deal with a name refresh request to a WINS server.
396 ************************************************************************/
398 void wins_process_name_refresh_request(struct subnet_record *subrec,
399 struct packet_struct *p)
401 struct nmb_packet *nmb = &p->packet.nmb;
402 struct nmb_name *question = &nmb->question.question_name;
403 BOOL bcast = nmb->header.nm_flags.bcast;
404 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
405 BOOL group = (nb_flags & NB_GROUP) ? True : False;
406 struct name_record *namerec = NULL;
407 int ttl = get_ttl_from_packet(nmb);
408 struct in_addr from_ip;
409 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
411 putip((char *)&from_ip,&nmb->additional->rdata[2]);
416 * We should only get unicast name refresh packets here.
417 * Anyone trying to refresh broadcast should not be going to a WINS
418 * server. Log an error here.
421 DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh request \
422 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
423 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
427 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \
428 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
431 * See if the name already exists.
434 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
437 * If this is a refresh request and the name doesn't exist then
438 * treat it like a registration request. This allows us to recover
439 * from errors (tridge)
444 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \
445 the name does not exist. Treating as registration.\n", nmb_namestr(question) ));
446 wins_process_name_registration_request(subrec,p);
451 * if the name is present but not active,
452 * simply remove it and treat the request
455 if (namerec != NULL && !WINS_STATE_ACTIVE(namerec))
457 DEBUG(5,("wins_process_name_refresh_request: Name (%s) in WINS was \
458 not active - removing it.\n", nmb_namestr(question) ));
459 remove_name_from_namelist( subrec, namerec );
461 wins_process_name_registration_request(subrec,p);
466 * Check that the group bits for the refreshing name and the
467 * name in our database match.
470 if((namerec != NULL) && ((group && !NAME_GROUP(namerec)) || (!group && NAME_GROUP(namerec))) )
472 DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \
473 does not match group bit in WINS for this name.\n", nmb_namestr(question), group ? "True" : "False" ));
474 send_wins_name_registration_response(RFS_ERR, 0, p);
479 * For a unique name check that the person refreshing the name is one of the registered IP
480 * addresses. If not - fail the refresh. Do the same for group names with a type of 0x1c.
481 * Just return success for unique 0x1d refreshes. For normal group names update the ttl
482 * and return success.
485 if((!group || (group && (question->name_type == 0x1c))) && find_ip_in_name_record(namerec, from_ip ))
490 update_name_ttl(namerec, ttl);
493 * if the record is a replica:
494 * we take ownership and update the version ID.
496 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
497 update_wins_owner(namerec, our_fake_ip);
498 get_global_id_and_update(&namerec->data.id, True);
501 send_wins_name_registration_response(0, ttl, p);
502 wins_hook("refresh", namerec, ttl);
508 * Normal groups are all registered with an IP address of 255.255.255.255
509 * so we can't search for the IP address.
511 update_name_ttl(namerec, ttl);
512 send_wins_name_registration_response(0, ttl, p);
515 else if(!group && (question->name_type == 0x1d))
518 * Special name type - just pretend the refresh succeeded.
520 send_wins_name_registration_response(0, ttl, p);
529 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \
530 is IP is not known to the name.\n", nmb_namestr(question), inet_ntoa(from_ip) ));
531 send_wins_name_registration_response(RFS_ERR, 0, p);
536 /***********************************************************************
537 Deal with a name registration request query success to a client that
540 We have a locked pointer to the original packet stashed away in the
541 userdata pointer. The success here is actually a failure as it means
542 the client we queried wants to keep the name, so we must return
543 a registration failure to the original requestor.
544 ************************************************************************/
546 static void wins_register_query_success(struct subnet_record *subrec,
547 struct userdata_struct *userdata,
548 struct nmb_name *question_name,
550 struct res_rec *answers)
552 struct packet_struct *orig_reg_packet;
554 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
556 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
557 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
559 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
561 orig_reg_packet->locked = False;
562 free_packet(orig_reg_packet);
565 /***********************************************************************
566 Deal with a name registration request query failure to a client that
569 We have a locked pointer to the original packet stashed away in the
570 userdata pointer. The failure here is actually a success as it means
571 the client we queried didn't want to keep the name, so we can remove
572 the old name record and then successfully add the new name.
573 ************************************************************************/
575 static void wins_register_query_fail(struct subnet_record *subrec,
576 struct response_record *rrec,
577 struct nmb_name *question_name,
580 struct userdata_struct *userdata = rrec->userdata;
581 struct packet_struct *orig_reg_packet;
582 struct name_record *namerec = NULL;
584 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
587 * We want to just add the name, as we now know the original owner
588 * didn't want it. But we can't just do that as an arbitary
589 * amount of time may have taken place between the name query
590 * request and this timeout/error response. So we check that
591 * the name still exists and is in the same state - if so
592 * we remove it and call wins_process_name_registration_request()
593 * as we know it will do the right thing now.
596 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
598 if( (namerec != NULL)
599 && (namerec->data.source == REGISTER_NAME)
600 && ip_equal(rrec->packet->ip, *namerec->data.ip) )
602 remove_name_from_namelist( subrec, namerec);
607 wins_process_name_registration_request(subrec, orig_reg_packet);
609 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \
610 querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) ));
612 orig_reg_packet->locked = False;
613 free_packet(orig_reg_packet);
616 /***********************************************************************
617 Deal with a name registration request to a WINS server.
619 Use the following pseudocode :
627 | +--- existing name is group
630 | | +--- add name (return).
633 | +--- exiting name is unique
636 | +--- query existing owner (return).
639 +--------name doesn't exist
642 +--- add name (return).
650 | +--- existing name is group
653 | | +--- fail add (return).
656 | +--- exiting name is unique
659 | +--- query existing owner (return).
662 +--------name doesn't exist
665 +--- add name (return).
667 As can be seen from the above, the two cases may be collapsed onto each
668 other with the exception of the case where the name already exists and
669 is a group name. This case we handle with an if statement.
671 ************************************************************************/
673 void wins_process_name_registration_request(struct subnet_record *subrec,
674 struct packet_struct *p)
676 struct nmb_packet *nmb = &p->packet.nmb;
677 struct nmb_name *question = &nmb->question.question_name;
678 BOOL bcast = nmb->header.nm_flags.bcast;
679 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
680 int ttl = get_ttl_from_packet(nmb);
681 struct name_record *namerec = NULL;
682 struct in_addr from_ip;
683 BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;
684 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
686 putip((char *)&from_ip,&nmb->additional->rdata[2]);
691 * We should only get unicast name registration packets here.
692 * Anyone trying to register broadcast should not be going to a WINS
693 * server. Log an error here.
696 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
697 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
698 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
702 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
703 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
706 * See if the name already exists.
709 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
712 * if the record exists but NOT in active state,
715 if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec))
717 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
718 not active - removing it.\n", nmb_namestr(question) ));
719 remove_name_from_namelist( subrec, namerec );
724 * Deal with the case where the name found was a dns entry.
725 * Remove it as we now have a NetBIOS client registering the
729 if( (namerec != NULL)
730 && ( (namerec->data.source == DNS_NAME)
731 || (namerec->data.source == DNSFAIL_NAME) ) )
733 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
734 a dns lookup - removing it.\n", nmb_namestr(question) ));
735 remove_name_from_namelist( subrec, namerec );
740 * Reject if the name exists and is not a REGISTER_NAME.
741 * (ie. Don't allow any static names to be overwritten.
744 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME))
746 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
747 to register name %s. Name already exists in WINS with source type %d.\n",
748 nmb_namestr(question), namerec->data.source ));
749 send_wins_name_registration_response(RFS_ERR, 0, p);
754 * Special policy decisions based on MS documentation.
755 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
756 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
760 * A group name is always added as the local broadcast address, except
761 * for group names ending in 0x1c.
762 * Group names with type 0x1c are registered with individual IP addresses.
765 if(registering_group_name && (question->name_type != 0x1c))
766 from_ip = *interpret_addr2("255.255.255.255");
769 * Ignore all attempts to register a unique 0x1d name, although return success.
772 if(!registering_group_name && (question->name_type == 0x1d))
774 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
775 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
776 send_wins_name_registration_response(0, ttl, p);
781 * Next two cases are the 'if statement' mentioned above.
784 if((namerec != NULL) && NAME_GROUP(namerec))
786 if(registering_group_name)
789 * If we are adding a group name, the name exists and is also a group entry just add this
790 * IP address to it and update the ttl.
793 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
794 inet_ntoa(from_ip), nmb_namestr(question) ));
796 * Check the ip address is not already in the group.
798 if(!find_ip_in_name_record(namerec, from_ip)) {
799 add_ip_to_name_record(namerec, from_ip);
800 /* we need to update the record for replication */
801 get_global_id_and_update(&namerec->data.id, True);
804 * if the record is a replica, we must change
805 * the wins owner to us to make the replication updates
806 * it on the other wins servers.
807 * And when the partner will receive this record,
808 * it will update its own record.
811 update_wins_owner(namerec, our_fake_ip);
814 update_name_ttl(namerec, ttl);
815 send_wins_name_registration_response(0, ttl, p);
821 * If we are adding a unique name, the name exists in the WINS db
822 * and is a group name then reject the registration.
824 * explanation: groups have a higher priority than unique names.
827 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
828 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
829 send_wins_name_registration_response(RFS_ERR, 0, p);
835 * From here on down we know that if the name exists in the WINS db it is
836 * a unique name, not a group name.
840 * If the name exists and is one of our names then check the
841 * registering IP address. If it's not one of ours then automatically
842 * reject without doing the query - we know we will reject it.
845 if((namerec != NULL) && (is_myname(namerec->name.name)) )
849 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
850 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
851 send_wins_name_registration_response(RFS_ERR, 0, p);
857 * It's one of our names and one of our IP's - update the ttl.
859 update_name_ttl(namerec, ttl);
860 send_wins_name_registration_response(0, ttl, p);
861 wins_hook("refresh", namerec, ttl);
867 * If the name exists and it is a unique registration and the registering IP
868 * is the same as the (single) already registered IP then just update the ttl.
870 * But not if the record is an active replica. IF it's a replica, it means it can be
871 * the same client which has moved and not yet expired. So we don't update
872 * the ttl in this case and go beyond to do a WACK and query the old client
875 if( !registering_group_name
877 && (namerec->data.num_ips == 1)
878 && ip_equal( namerec->data.ip[0], from_ip )
879 && ip_equal(namerec->data.wins_ip, our_fake_ip) )
881 update_name_ttl( namerec, ttl );
882 send_wins_name_registration_response( 0, ttl, p );
883 wins_hook("refresh", namerec, ttl);
888 * Finally if the name exists do a query to the registering machine
889 * to see if they still claim to have the name.
892 if( namerec != NULL )
894 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
895 struct userdata_struct *userdata = (struct userdata_struct *)ud;
898 * First send a WACK to the registering machine.
901 send_wins_wack_response(60, p);
904 * When the reply comes back we need the original packet.
905 * Lock this so it won't be freed and then put it into
906 * the userdata structure.
911 userdata = (struct userdata_struct *)ud;
913 userdata->copy_fn = NULL;
914 userdata->free_fn = NULL;
915 userdata->userdata_len = sizeof(struct packet_struct *);
916 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
919 * Use the new call to send a query directly to an IP address.
920 * This sends the query directly to the IP address, and ensures
921 * the recursion desired flag is not set (you were right Luke :-).
922 * This function should *only* be called from the WINS server
926 query_name_from_wins_server( *namerec->data.ip,
929 wins_register_query_success,
930 wins_register_query_fail,
936 * Name did not exist - add it.
939 (void)add_name_to_subnet( subrec, question->name, question->name_type,
940 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
941 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
942 get_global_id_and_update(&namerec->data.id, True);
943 update_wins_owner(namerec, our_fake_ip);
944 update_wins_flag(namerec, WINS_ACTIVE);
945 wins_hook("add", namerec, ttl);
948 send_wins_name_registration_response(0, ttl, p);
951 /***********************************************************************
952 Deal with a mutihomed name query success to the machine that
953 requested the multihomed name registration.
955 We have a locked pointer to the original packet stashed away in the
957 ************************************************************************/
959 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
960 struct userdata_struct *userdata,
961 struct nmb_name *question_name,
963 struct res_rec *answers)
965 struct packet_struct *orig_reg_packet;
966 struct nmb_packet *nmb;
967 struct name_record *namerec = NULL;
968 struct in_addr from_ip;
970 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
972 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
974 nmb = &orig_reg_packet->packet.nmb;
976 putip((char *)&from_ip,&nmb->additional->rdata[2]);
977 ttl = get_ttl_from_packet(nmb);
980 * We want to just add the new IP, as we now know the requesting
981 * machine claims to own it. But we can't just do that as an arbitary
982 * amount of time may have taken place between the name query
983 * request and this response. So we check that
984 * the name still exists and is in the same state - if so
985 * we just add the extra IP and update the ttl.
988 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
990 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) )
992 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
993 a subsequent IP address.\n", nmb_namestr(question_name) ));
994 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
996 orig_reg_packet->locked = False;
997 free_packet(orig_reg_packet);
1002 if(!find_ip_in_name_record(namerec, from_ip))
1003 add_ip_to_name_record(namerec, from_ip);
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 update_name_ttl(namerec, ttl);
1009 send_wins_name_registration_response(0, ttl, orig_reg_packet);
1010 wins_hook("add", namerec, ttl);
1012 orig_reg_packet->locked = False;
1013 free_packet(orig_reg_packet);
1016 /***********************************************************************
1017 Deal with a name registration request query failure to a client that
1020 We have a locked pointer to the original packet stashed away in the
1022 ************************************************************************/
1024 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
1025 struct response_record *rrec,
1026 struct nmb_name *question_name,
1029 struct userdata_struct *userdata = rrec->userdata;
1030 struct packet_struct *orig_reg_packet;
1032 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1034 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1035 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
1036 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1038 orig_reg_packet->locked = False;
1039 free_packet(orig_reg_packet);
1043 /***********************************************************************
1044 Deal with a multihomed name registration request to a WINS server.
1045 These cannot be group name registrations.
1046 ***********************************************************************/
1048 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
1049 struct packet_struct *p)
1051 struct nmb_packet *nmb = &p->packet.nmb;
1052 struct nmb_name *question = &nmb->question.question_name;
1053 BOOL bcast = nmb->header.nm_flags.bcast;
1054 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1055 int ttl = get_ttl_from_packet(nmb);
1056 struct name_record *namerec = NULL;
1057 struct in_addr from_ip;
1058 BOOL group = (nb_flags & NB_GROUP) ? True : False;
1059 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1061 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1066 * We should only get unicast name registration packets here.
1067 * Anyone trying to register broadcast should not be going to a WINS
1068 * server. Log an error here.
1071 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1072 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1073 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1078 * Only unique names should be registered multihomed.
1083 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1084 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1085 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1089 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1090 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1093 * Deal with policy regarding 0x1d names.
1096 if(question->name_type == 0x1d)
1098 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1099 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1100 send_wins_name_registration_response(0, ttl, p);
1105 * See if the name already exists.
1108 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1111 * if the record exists but NOT in active state,
1114 if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1115 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question)));
1116 remove_name_from_namelist(subrec, namerec);
1121 * Deal with the case where the name found was a dns entry.
1122 * Remove it as we now have a NetBIOS client registering the
1126 if( (namerec != NULL)
1127 && ( (namerec->data.source == DNS_NAME)
1128 || (namerec->data.source == DNSFAIL_NAME) ) )
1130 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1131 - removing it.\n", nmb_namestr(question) ));
1132 remove_name_from_namelist( subrec, namerec);
1137 * Reject if the name exists and is not a REGISTER_NAME.
1138 * (ie. Don't allow any static names to be overwritten.
1141 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) )
1143 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1144 to register name %s. Name already exists in WINS with source type %d.\n",
1145 nmb_namestr(question), namerec->data.source ));
1146 send_wins_name_registration_response(RFS_ERR, 0, p);
1151 * Reject if the name exists and is a GROUP name and is active.
1154 if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec))
1156 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1157 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1158 send_wins_name_registration_response(RFS_ERR, 0, p);
1163 * From here on down we know that if the name exists in the WINS db it is
1164 * a unique name, not a group name.
1168 * If the name exists and is one of our names then check the
1169 * registering IP address. If it's not one of ours then automatically
1170 * reject without doing the query - we know we will reject it.
1173 if((namerec != NULL) && (is_myname(namerec->name.name)) )
1175 if(!ismyip(from_ip))
1177 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1178 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1179 send_wins_name_registration_response(RFS_ERR, 0, p);
1185 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1186 * update the ttl. Update the version ID to force replication.
1188 if(!find_ip_in_name_record(namerec, from_ip)) {
1189 get_global_id_and_update(&namerec->data.id, True);
1190 update_wins_owner(namerec, our_fake_ip);
1191 update_wins_flag(namerec, WINS_ACTIVE);
1193 add_ip_to_name_record(namerec, from_ip);
1194 wins_hook("add", namerec, ttl);
1196 wins_hook("refresh", namerec, ttl);
1199 update_name_ttl(namerec, ttl);
1200 send_wins_name_registration_response(0, ttl, p);
1206 * If the name exists and is active, check if the IP address is already registered
1207 * to that name. If so then update the ttl and reply success.
1210 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec))
1212 update_name_ttl(namerec, ttl);
1214 * If it's a replica, we need to become the wins owner
1215 * to force the replication
1217 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1218 get_global_id_and_update(&namerec->data.id, True);
1219 update_wins_owner(namerec, our_fake_ip);
1220 update_wins_flag(namerec, WINS_ACTIVE);
1223 send_wins_name_registration_response(0, ttl, p);
1224 wins_hook("refresh", namerec, ttl);
1229 * If the name exists do a query to the owner
1230 * to see if they still want the name.
1235 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1236 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1239 * First send a WACK to the registering machine.
1242 send_wins_wack_response(60, p);
1245 * When the reply comes back we need the original packet.
1246 * Lock this so it won't be freed and then put it into
1247 * the userdata structure.
1252 userdata = (struct userdata_struct *)ud;
1254 userdata->copy_fn = NULL;
1255 userdata->free_fn = NULL;
1256 userdata->userdata_len = sizeof(struct packet_struct *);
1257 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1260 * Use the new call to send a query directly to an IP address.
1261 * This sends the query directly to the IP address, and ensures
1262 * the recursion desired flag is not set (you were right Luke :-).
1263 * This function should *only* be called from the WINS server
1266 * Note that this packet is sent to the current owner of the name,
1267 * not the person who sent the packet
1270 query_name_from_wins_server( namerec->data.ip[0],
1272 question->name_type,
1273 wins_multihomed_register_query_success,
1274 wins_multihomed_register_query_fail,
1281 * Name did not exist - add it.
1284 (void)add_name_to_subnet( subrec, question->name, question->name_type,
1285 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1287 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1288 get_global_id_and_update(&namerec->data.id, True);
1289 update_wins_owner(namerec, our_fake_ip);
1290 update_wins_flag(namerec, WINS_ACTIVE);
1291 wins_hook("add", namerec, ttl);
1294 send_wins_name_registration_response(0, ttl, p);
1297 /***********************************************************************
1298 Deal with the special name query for *<1b>.
1299 ***********************************************************************/
1301 static void process_wins_dmb_query_request(struct subnet_record *subrec,
1302 struct packet_struct *p)
1304 struct name_record *namerec = NULL;
1309 * Go through all the ACTIVE names in the WINS db looking for those
1310 * ending in <1b>. Use this to calculate the number of IP
1311 * addresses we need to return.
1315 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1317 namerec = (struct name_record *)ubi_trNext( namerec ) )
1319 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b )
1320 num_ips += namerec->data.num_ips;
1326 * There are no 0x1b names registered. Return name query fail.
1328 send_wins_name_query_response(NAM_ERR, p, NULL);
1332 if((prdata = (char *)malloc( num_ips * 6 )) == NULL)
1334 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1339 * Go through all the names again in the WINS db looking for those
1340 * ending in <1b>. Add their IP addresses into the list we will
1345 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1347 namerec = (struct name_record *)ubi_trNext( namerec ) )
1349 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b)
1352 for(i = 0; i < namerec->data.num_ips; i++)
1354 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1355 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1362 * Send back the reply containing the IP list.
1365 reply_netbios_packet(p, /* Packet to reply to. */
1366 0, /* Result code. */
1367 WINS_QUERY, /* nmbd type code. */
1368 NMB_NAME_QUERY_OPCODE, /* opcode. */
1369 lp_min_wins_ttl(), /* ttl. */
1370 prdata, /* data to send. */
1371 num_ips*6); /* data length. */
1376 /****************************************************************************
1377 Send a WINS name query response.
1378 **************************************************************************/
1380 void send_wins_name_query_response(int rcode, struct packet_struct *p,
1381 struct name_record *namerec)
1384 char *prdata = rdata;
1385 int reply_data_len = 0;
1389 memset(rdata,'\0',6);
1393 ttl = (namerec->data.death_time != PERMANENT_TTL) ?
1394 namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1396 /* Copy all known ip addresses into the return data. */
1397 /* Optimise for the common case of one IP address so
1398 we don't need a malloc. */
1400 if( namerec->data.num_ips == 1 )
1404 if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL)
1406 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1411 for(i = 0; i < namerec->data.num_ips; i++)
1413 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
1414 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
1417 sort_query_replies(prdata, i, p->ip);
1419 reply_data_len = namerec->data.num_ips * 6;
1422 reply_netbios_packet(p, /* Packet to reply to. */
1423 rcode, /* Result code. */
1424 WINS_QUERY, /* nmbd type code. */
1425 NMB_NAME_QUERY_OPCODE, /* opcode. */
1427 prdata, /* data to send. */
1428 reply_data_len); /* data length. */
1434 /***********************************************************************
1435 Deal with a name query.
1436 ***********************************************************************/
1438 void wins_process_name_query_request(struct subnet_record *subrec,
1439 struct packet_struct *p)
1441 struct nmb_packet *nmb = &p->packet.nmb;
1442 struct nmb_name *question = &nmb->question.question_name;
1443 struct name_record *namerec = NULL;
1445 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
1446 nmb_namestr(question), inet_ntoa(p->ip) ));
1449 * Special name code. If the queried name is *<1b> then search
1450 * the entire WINS database and return a list of all the IP addresses
1451 * registered to any <1b> name. This is to allow domain master browsers
1452 * to discover other domains that may not have a presence on their subnet.
1455 if(strequal( question->name, "*") && (question->name_type == 0x1b))
1457 process_wins_dmb_query_request( subrec, p);
1461 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1466 * If the name is not anymore in active state then reply not found.
1467 * it's fair even if we keep it in the cache for days.
1469 if (!WINS_STATE_ACTIVE(namerec))
1471 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1472 nmb_namestr(question) ));
1473 send_wins_name_query_response(NAM_ERR, p, namerec);
1477 * If it's a DNSFAIL_NAME then reply name not found.
1480 if( namerec->data.source == DNSFAIL_NAME )
1482 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
1483 nmb_namestr(question) ));
1484 send_wins_name_query_response(NAM_ERR, p, namerec);
1489 * If the name has expired then reply name not found.
1492 if( (namerec->data.death_time != PERMANENT_TTL)
1493 && (namerec->data.death_time < p->timestamp) )
1495 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1496 nmb_namestr(question) ));
1497 send_wins_name_query_response(NAM_ERR, p, namerec);
1501 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
1502 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
1504 send_wins_name_query_response(0, p, namerec);
1509 * Name not found in WINS - try a dns query if it's a 0x20 name.
1512 if(lp_dns_proxy() &&
1513 ((question->name_type == 0x20) || question->name_type == 0))
1516 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
1517 nmb_namestr(question) ));
1519 queue_dns_query(p, question, &namerec);
1524 * Name not found - return error.
1527 send_wins_name_query_response(NAM_ERR, p, NULL);
1530 /****************************************************************************
1531 Send a WINS name release response.
1532 **************************************************************************/
1534 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
1536 struct nmb_packet *nmb = &p->packet.nmb;
1539 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
1541 reply_netbios_packet(p, /* Packet to reply to. */
1542 rcode, /* Result code. */
1543 NMB_REL, /* nmbd type code. */
1544 NMB_NAME_RELEASE_OPCODE, /* opcode. */
1546 rdata, /* data to send. */
1547 6); /* data length. */
1550 /***********************************************************************
1551 Deal with a name release.
1552 ***********************************************************************/
1554 void wins_process_name_release_request(struct subnet_record *subrec,
1555 struct packet_struct *p)
1557 struct nmb_packet *nmb = &p->packet.nmb;
1558 struct nmb_name *question = &nmb->question.question_name;
1559 BOOL bcast = nmb->header.nm_flags.bcast;
1560 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1561 struct name_record *namerec = NULL;
1562 struct in_addr from_ip;
1563 BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
1565 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1570 * We should only get unicast name registration packets here.
1571 * Anyone trying to register broadcast should not be going to a WINS
1572 * server. Log an error here.
1575 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
1576 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1577 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1581 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
1582 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1585 * Deal with policy regarding 0x1d names.
1588 if(!releasing_group_name && (question->name_type == 0x1d))
1590 DEBUG(3,("wins_process_name_release_request: Ignoring request \
1591 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1592 send_wins_name_release_response(0, p);
1597 * See if the name already exists.
1600 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1602 if( (namerec == NULL)
1603 || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) )
1605 send_wins_name_release_response(NAM_ERR, p);
1610 * Check that the sending machine has permission to release this name.
1611 * If it's a group name not ending in 0x1c then just say yes and let
1612 * the group time out.
1615 if(releasing_group_name && (question->name_type != 0x1c))
1617 send_wins_name_release_response(0, p);
1622 * Check that the releasing node is on the list of IP addresses
1623 * for this name. Disallow the release if not.
1626 if(!find_ip_in_name_record(namerec, from_ip))
1628 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1629 release name %s as IP %s is not one of the known IP's for this name.\n",
1630 nmb_namestr(question), inet_ntoa(from_ip) ));
1631 send_wins_name_release_response(NAM_ERR, p);
1636 * Check if the record is active. IF it's already released
1637 * or tombstoned, refuse the release.
1639 if (!WINS_STATE_ACTIVE(namerec)) {
1640 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1641 release name %s as this record is not anymore active.\n",
1642 nmb_namestr(question) ));
1643 send_wins_name_release_response(NAM_ERR, p);
1648 * Check if the record is a 0x1c group
1649 * and has more then one ip
1650 * remove only this address.
1653 if(releasing_group_name &&
1654 (question->name_type == 0x1c) &&
1655 (namerec->data.num_ips > 1)) {
1656 remove_ip_from_name_record(namerec, from_ip);
1657 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
1658 inet_ntoa(from_ip),nmb_namestr(question)));
1659 send_wins_name_release_response(0, p);
1664 * Send a release response.
1665 * Flag the name as released and update the ttl
1668 send_wins_name_release_response(0, p);
1670 namerec->data.wins_flags |= WINS_RELEASED;
1671 update_name_ttl(namerec, EXTINCTION_INTERVAL);
1673 wins_hook("delete", namerec, 0);
1676 /*******************************************************************
1677 WINS time dependent processing.
1678 ******************************************************************/
1680 void initiate_wins_processing(time_t t)
1682 static time_t lasttime = 0;
1683 struct name_record *namerec;
1684 struct name_record *next_namerec;
1685 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1689 if (t - lasttime < 20)
1694 if(!lp_we_are_a_wins_server())
1697 for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
1699 namerec = next_namerec ) {
1700 next_namerec = (struct name_record *)ubi_trNext( namerec );
1702 if( (namerec->data.death_time != PERMANENT_TTL)
1703 && (namerec->data.death_time < t) ) {
1705 if( namerec->data.source == SELF_NAME ) {
1706 DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF name %s\n",
1707 wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
1708 namerec->data.death_time += 300;
1709 namerec->subnet->namelist_changed = True;
1713 /* handle records, samba is the wins owner */
1714 if (ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1715 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
1717 namerec->data.wins_flags&=~WINS_STATE_MASK;
1718 namerec->data.wins_flags|=WINS_RELEASED;
1719 namerec->data.death_time = t + EXTINCTION_INTERVAL;
1720 DEBUG(3,("initiate_wins_processing: expiring %s\n", nmb_namestr(&namerec->name)));
1723 namerec->data.wins_flags&=~WINS_STATE_MASK;
1724 namerec->data.wins_flags|=WINS_TOMBSTONED;
1725 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
1726 get_global_id_and_update(&namerec->data.id, True);
1727 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
1729 case WINS_TOMBSTONED:
1730 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
1731 remove_name_from_namelist( wins_server_subnet, namerec );
1735 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
1737 /* that's not as MS says it should be */
1738 namerec->data.wins_flags&=~WINS_STATE_MASK;
1739 namerec->data.wins_flags|=WINS_TOMBSTONED;
1740 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
1741 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
1742 case WINS_TOMBSTONED:
1743 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
1744 remove_name_from_namelist( wins_server_subnet, namerec );
1747 DEBUG(0,("initiate_wins_processing: %s is in released state and\
1748 we are not the wins owner !\n", nmb_namestr(&namerec->name)));
1756 if(wins_server_subnet->namelist_changed)
1757 wins_write_database(True);
1759 wins_server_subnet->namelist_changed = False;
1762 /*******************************************************************
1763 Write out the current WINS database.
1764 ******************************************************************/
1765 void wins_write_database(BOOL background)
1767 struct name_record *namerec;
1768 pstring fname, fnamenew;
1770 TDB_DATA kbuf, dbuf;
1776 if(!lp_we_are_a_wins_server())
1779 /* we will do the writing in a child process to ensure that the parent
1780 doesn't block while this is done */
1788 slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST);
1789 all_string_sub(fname,"//", "/", 0);
1790 slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid());
1792 tdb = tdb_open_log(fnamenew, 0, TDB_DEFAULT, O_RDWR|O_CREAT|O_TRUNC, 0644);
1794 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
1800 DEBUG(3,("wins_write_database: Dump of WINS name list.\n"));
1802 tdb_store_int32(tdb, INFO_VERSION, WINS_VERSION);
1804 for (namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
1806 namerec = (struct name_record *)ubi_trNext( namerec ) ) {
1811 DEBUGADD(3,("%-19s ", nmb_namestr(&namerec->name) ));
1813 if( namerec->data.death_time != PERMANENT_TTL ) {
1816 tm = LocalTime(&namerec->data.death_time);
1818 nl = strrchr_m( ts, '\n' );
1822 DEBUGADD(3,("TTL = %s ", ts ));
1824 DEBUGADD(3,("TTL = PERMANENT "));
1826 for (i = 0; i < namerec->data.num_ips; i++)
1827 DEBUGADD(0,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
1829 DEBUGADD(3,("0x%2x 0x%2x %15s\n", namerec->data.nb_flags, namerec->data.wins_flags, inet_ntoa(namerec->data.wins_ip)));
1831 if( namerec->data.source == REGISTER_NAME ) {
1833 /* store the type in the key to make the name unique */
1834 slprintf(key, sizeof(key), "%s%s#%02x", ENTRY_PREFIX, namerec->name.name, namerec->name.name_type);
1836 len = tdb_pack(buf, sizeof(buf), "dddfddd",
1837 (int)namerec->data.nb_flags,
1838 (int)(namerec->data.id>>32),
1839 (int)(namerec->data.id&0xffffffff),
1840 inet_ntoa(namerec->data.wins_ip),
1841 (int)namerec->data.death_time,
1842 namerec->data.num_ips,
1843 namerec->data.wins_flags);
1845 for (i = 0; i < namerec->data.num_ips; i++)
1846 len += tdb_pack(buf+len, sizeof(buf)-len, "f", inet_ntoa(namerec->data.ip[i]));
1848 kbuf.dsize = strlen(key)+1;
1852 if (tdb_store(tdb, kbuf, dbuf, TDB_INSERT) != 0) return;
1858 /* store the number of records */
1859 tdb_store_int32(tdb, INFO_COUNT, num_record);
1861 /* get and store the last used ID */
1862 get_global_id_and_update(&id, False);
1863 tdb_store_int32(tdb, INFO_ID_HIGH, id>>32);
1864 tdb_store_int32(tdb, INFO_ID_LOW, id&0xffffffff);
1868 chmod(fnamenew,0644);
1870 rename(fnamenew,fname);
1876 /****************************************************************************
1877 process a internal Samba message receiving a wins record
1878 ***************************************************************************/
1879 void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len)
1881 WINS_RECORD *record;
1882 struct name_record *namerec = NULL;
1883 struct name_record *new_namerec = NULL;
1884 struct nmb_name question;
1885 BOOL overwrite=False;
1886 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1892 record=(WINS_RECORD *)buf;
1894 ZERO_STRUCT(question);
1895 memcpy(question.name, record->name, 16);
1896 question.name_type=record->type;
1898 namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
1900 /* record doesn't exist, add it */
1901 if (namerec == NULL) {
1902 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
1903 record->name, record->type, inet_ntoa(record->wins_ip)));
1905 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
1906 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
1907 if (new_namerec!=NULL) {
1908 update_wins_owner(new_namerec, record->wins_ip);
1909 update_wins_flag(new_namerec, record->wins_flags);
1910 new_namerec->data.id=record->id;
1912 wins_server_subnet->namelist_changed = True;
1916 /* check if we have a conflict */
1917 if (namerec != NULL) {
1918 /* both records are UNIQUE */
1919 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
1921 /* the database record is a replica */
1922 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1923 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
1924 if (ip_equal(namerec->data.wins_ip, record->wins_ip))
1929 /* we are the wins owner of the database record */
1930 /* the 2 records have the same IP address */
1931 if (ip_equal(namerec->data.ip[0], record->ip[0])) {
1932 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
1933 get_global_id_and_update(&namerec->data.id, True);
1938 /* the 2 records have different IP address */
1939 if (namerec->data.wins_flags&WINS_ACTIVE) {
1940 if (record->wins_flags&WINS_TOMBSTONED)
1941 get_global_id_and_update(&namerec->data.id, True);
1942 if (record->wins_flags&WINS_ACTIVE)
1943 /* send conflict challenge to the replica node */
1952 /* the replica is a standard group */
1953 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {
1954 /* if the database record is unique and active force a name release */
1955 if (namerec->data.wins_flags&WINS_UNIQUE)
1956 /* send a release name to the unique node */
1962 /* the replica is a special group */
1963 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
1964 if (namerec->data.wins_flags&WINS_ACTIVE) {
1965 for (i=0; i<record->num_ips; i++)
1966 if(!find_ip_in_name_record(namerec, record->ip[i]))
1967 add_ip_to_name_record(namerec, record->ip[i]);
1973 /* the replica is a multihomed host */
1975 /* I'm giving up on multi homed. Too much complex to understand */
1977 if (record->wins_flags&WINS_MHOMED) {
1978 if (! (namerec->data.wins_flags&WINS_ACTIVE)) {
1979 if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP))
1983 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
1986 if (ip_equal(namerec->data.wins_ip, our_fake_ip))
1987 if (namerec->data.wins_flags&WINS_UNIQUE)
1988 get_global_id_and_update(&namerec->data.id, True);
1992 if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
1993 if (namerec->data.wins_flags&WINS_UNIQUE ||
1994 namerec->data.wins_flags&WINS_MHOMED)
1995 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
2000 if (overwrite == False)
2001 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
2002 record->name, record->type, inet_ntoa(record->wins_ip)));
2004 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
2005 record->name, record->type, inet_ntoa(record->wins_ip)));
2007 /* remove the old record and add a new one */
2008 remove_name_from_namelist( wins_server_subnet, namerec );
2009 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
2010 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
2011 if (new_namerec!=NULL) {
2012 update_wins_owner(new_namerec, record->wins_ip);
2013 update_wins_flag(new_namerec, record->wins_flags);
2014 new_namerec->data.id=record->id;
2016 wins_server_subnet->namelist_changed = True;
2019 wins_server_subnet->namelist_changed = True;