2 Unix SMB/Netbios implementation.
4 NBT netbios routines and daemon - version 2
6 Copyright (C) Jeremy Allison 1994-1998
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #define WINS_LIST "wins.tdb"
27 #define WINS_VERSION 1
29 /****************************************************************************
30 change the wins owner address in the record.
31 *****************************************************************************/
32 static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip)
36 namerec->data.wins_ip=wins_ip;
39 /****************************************************************************
40 create the wins flags based on the nb flags and the input value.
41 *****************************************************************************/
42 static void update_wins_flag(struct name_record *namerec, int flags)
47 namerec->data.wins_flags=0x0;
49 /* if it's a group, it can be a normal or a special one */
50 if (namerec->data.nb_flags & NB_GROUP) {
51 if (namerec->name.name_type==0x1C)
52 namerec->data.wins_flags|=WINS_SGROUP;
54 if (namerec->data.num_ips>1)
55 namerec->data.wins_flags|=WINS_SGROUP;
57 namerec->data.wins_flags|=WINS_NGROUP;
59 /* can be unique or multi-homed */
60 if (namerec->data.num_ips>1)
61 namerec->data.wins_flags|=WINS_MHOMED;
63 namerec->data.wins_flags|=WINS_UNIQUE;
66 /* the node type are the same bits */
67 namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK;
69 /* the static bit is elsewhere */
70 if (namerec->data.death_time == PERMANENT_TTL)
71 namerec->data.wins_flags|=WINS_STATIC;
73 /* and add the given bits */
74 namerec->data.wins_flags|=flags;
76 DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n",
77 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 *****************************************************************************/
84 static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update)
87 * it's kept as a static here, to prevent people from messing
88 * with the value directly
91 static SMB_BIG_UINT general_id = 1;
93 DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id));
95 *current_id = general_id;
101 /****************************************************************************
102 possibly call the WINS hook external program when a WINS change is made
103 *****************************************************************************/
104 static void wins_hook(char *operation, struct name_record *namerec, int ttl)
107 char *cmd = lp_wins_hook();
111 if (!cmd || !*cmd) return;
113 for (p=namerec->name.name; *p; p++) {
114 if (!(isalnum((int)*p) || strchr_m("._-",*p))) {
115 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
121 p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d",
125 namerec->name.name_type,
128 for (i=0;i<namerec->data.num_ips;i++) {
129 p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.ip[i]));
132 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
133 smbrun(command, NULL);
137 /****************************************************************************
138 hash our interfaces and netbios names settings
139 *****************************************************************************/
140 static unsigned wins_hash(void)
143 unsigned ret = iface_hash();
144 extern char **my_netbios_names;
146 for (i=0;my_netbios_names[i];i++)
147 ret ^= str_checksum(my_netbios_names[i]);
149 ret ^= str_checksum(lp_workgroup());
155 /****************************************************************************
156 Determine if this packet should be allocated to the WINS server.
157 *****************************************************************************/
159 BOOL packet_is_for_wins_server(struct packet_struct *packet)
161 struct nmb_packet *nmb = &packet->packet.nmb;
163 /* Only unicast packets go to a WINS server. */
164 if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True))
166 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
170 /* Check for node status requests. */
171 if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY)
174 switch(nmb->header.opcode)
177 * A WINS server issues WACKS, not receives them.
179 case NMB_WACK_OPCODE:
180 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
183 * A WINS server only processes registration and
184 * release requests, not responses.
186 case NMB_NAME_REG_OPCODE:
187 case NMB_NAME_MULTIHOMED_REG_OPCODE:
188 case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
189 case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
190 if(nmb->header.response)
192 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
197 case NMB_NAME_RELEASE_OPCODE:
198 if(nmb->header.response)
200 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
206 * Only process unicast name queries with rd = 1.
208 case NMB_NAME_QUERY_OPCODE:
209 if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired)
211 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
220 /****************************************************************************
221 Utility function to decide what ttl to give a register/refresh request.
222 *****************************************************************************/
224 static int get_ttl_from_packet(struct nmb_packet *nmb)
226 int ttl = nmb->additional->ttl;
228 if(ttl < lp_min_wins_ttl() )
229 ttl = lp_min_wins_ttl();
231 if(ttl > lp_max_wins_ttl() )
232 ttl = lp_max_wins_ttl();
237 /****************************************************************************
238 Load or create the WINS database.
239 *****************************************************************************/
241 BOOL initialise_wins(void)
243 time_t time_now = time(NULL);
245 TDB_DATA kbuf, dbuf, newkey;
246 struct name_record *namerec = NULL;
247 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
249 DEBUG(2,("initialise_wins: started\n"));
251 if(!lp_we_are_a_wins_server())
254 add_samba_names_to_subnet(wins_server_subnet);
256 tdb = tdb_open_log(lock_path(WINS_LIST), 0, TDB_DEFAULT, O_RDONLY, 0600);
258 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n", WINS_LIST, strerror(errno) ));
262 if (tdb_fetch_int(tdb, INFO_VERSION) != WINS_VERSION) {
263 DEBUG(0,("Discarding invalid wins.dat file\n"));
268 for (kbuf = tdb_firstkey(tdb);
270 newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
272 pstring name_type, name, ip_str;
277 unsigned int num_ips;
279 struct in_addr wins_ip;
280 struct in_addr *ip_list;
284 if (strncmp(kbuf.dptr, ENTRY_PREFIX, strlen(ENTRY_PREFIX)) != 0)
287 dbuf = tdb_fetch(tdb, kbuf);
288 if (!dbuf.dptr) continue;
290 fstrcpy(name_type, kbuf.dptr+strlen(ENTRY_PREFIX));
292 pstrcpy(name, name_type);
294 if((p = strchr(name,'#')) != NULL) {
296 sscanf(p+1,"%x",&type);
299 len = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddfddd",
300 &nb_flags, &high, &low,
301 ip_str, &ttl, &num_ips, &wins_flags);
303 wins_ip=*interpret_addr2(ip_str);
305 /* Don't reload replica records */
306 if (!ip_equal(wins_ip, our_fake_ip))
309 /* Don't reload released or tombstoned records */
310 if ((wins_flags&WINS_STATE_MASK) != WINS_ACTIVE)
313 /* Allocate the space for the ip_list. */
314 if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL) {
315 DEBUG(0,("initialise_wins: Malloc fail !\n"));
319 for (i = 0; i < num_ips; i++) {
320 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f", ip_str);
321 ip_list[i] = *interpret_addr2(ip_str);
324 /* add all entries that have 60 seconds or more to live */
325 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {
326 if(ttl != PERMANENT_TTL)
329 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
330 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
332 namerec=add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
333 ttl, REGISTER_NAME, num_ips, ip_list);
335 update_wins_owner(namerec, wins_ip);
336 update_wins_flag(namerec, wins_flags);
337 /* we don't reload the ID, on startup we restart at 1 */
338 get_global_id_and_update(&namerec->data.id, True);
342 DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n",
343 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
350 DEBUG(2,("initialise_wins: done\n"));
354 /****************************************************************************
355 Send a WINS WACK (Wait ACKnowledgement) response.
356 **************************************************************************/
358 static void send_wins_wack_response(int ttl, struct packet_struct *p)
360 struct nmb_packet *nmb = &p->packet.nmb;
361 unsigned char rdata[2];
363 rdata[0] = rdata[1] = 0;
365 /* Taken from nmblib.c - we need to send back almost
366 identical bytes from the requesting packet header. */
368 rdata[0] = (nmb->header.opcode & 0xF) << 3;
369 if (nmb->header.nm_flags.authoritative &&
370 nmb->header.response) rdata[0] |= 0x4;
371 if (nmb->header.nm_flags.trunc) rdata[0] |= 0x2;
372 if (nmb->header.nm_flags.recursion_desired) rdata[0] |= 0x1;
373 if (nmb->header.nm_flags.recursion_available &&
374 nmb->header.response) rdata[1] |= 0x80;
375 if (nmb->header.nm_flags.bcast) rdata[1] |= 0x10;
377 reply_netbios_packet(p, /* Packet to reply to. */
378 0, /* Result code. */
379 NMB_WAIT_ACK, /* nmbd type code. */
380 NMB_WACK_OPCODE, /* opcode. */
382 (char *)rdata, /* data to send. */
383 2); /* data length. */
386 /****************************************************************************
387 Send a WINS name registration response.
388 **************************************************************************/
390 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
392 struct nmb_packet *nmb = &p->packet.nmb;
395 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
397 reply_netbios_packet(p, /* Packet to reply to. */
398 rcode, /* Result code. */
399 WINS_REG, /* nmbd type code. */
400 NMB_NAME_REG_OPCODE, /* opcode. */
402 rdata, /* data to send. */
403 6); /* data length. */
406 /***********************************************************************
407 Deal with a name refresh request to a WINS server.
408 ************************************************************************/
410 void wins_process_name_refresh_request(struct subnet_record *subrec,
411 struct packet_struct *p)
413 struct nmb_packet *nmb = &p->packet.nmb;
414 struct nmb_name *question = &nmb->question.question_name;
415 BOOL bcast = nmb->header.nm_flags.bcast;
416 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
417 BOOL group = (nb_flags & NB_GROUP) ? True : False;
418 struct name_record *namerec = NULL;
419 int ttl = get_ttl_from_packet(nmb);
420 struct in_addr from_ip;
421 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
423 putip((char *)&from_ip,&nmb->additional->rdata[2]);
428 * We should only get unicast name refresh packets here.
429 * Anyone trying to refresh broadcast should not be going to a WINS
430 * server. Log an error here.
433 DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh request \
434 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
435 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
439 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \
440 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
443 * See if the name already exists.
446 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
449 * If this is a refresh request and the name doesn't exist then
450 * treat it like a registration request. This allows us to recover
451 * from errors (tridge)
456 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \
457 the name does not exist. Treating as registration.\n", nmb_namestr(question) ));
458 wins_process_name_registration_request(subrec,p);
463 * if the name is present but not active,
464 * simply remove it and treat the request
467 if (namerec != NULL && !WINS_STATE_ACTIVE(namerec))
469 DEBUG(5,("wins_process_name_refresh_request: Name (%s) in WINS was \
470 not active - removing it.\n", nmb_namestr(question) ));
471 remove_name_from_namelist( subrec, namerec );
473 wins_process_name_registration_request(subrec,p);
478 * Check that the group bits for the refreshing name and the
479 * name in our database match.
482 if((namerec != NULL) && ((group && !NAME_GROUP(namerec)) || (!group && NAME_GROUP(namerec))) )
484 DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \
485 does not match group bit in WINS for this name.\n", nmb_namestr(question), group ? "True" : "False" ));
486 send_wins_name_registration_response(RFS_ERR, 0, p);
491 * For a unique name check that the person refreshing the name is one of the registered IP
492 * addresses. If not - fail the refresh. Do the same for group names with a type of 0x1c.
493 * Just return success for unique 0x1d refreshes. For normal group names update the ttl
494 * and return success.
497 if((!group || (group && (question->name_type == 0x1c))) && find_ip_in_name_record(namerec, from_ip ))
502 update_name_ttl(namerec, ttl);
505 * if the record is a replica:
506 * we take ownership and update the version ID.
508 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
509 update_wins_owner(namerec, our_fake_ip);
510 get_global_id_and_update(&namerec->data.id, True);
513 send_wins_name_registration_response(0, ttl, p);
514 wins_hook("refresh", namerec, ttl);
520 * Normal groups are all registered with an IP address of 255.255.255.255
521 * so we can't search for the IP address.
523 update_name_ttl(namerec, ttl);
524 send_wins_name_registration_response(0, ttl, p);
527 else if(!group && (question->name_type == 0x1d))
530 * Special name type - just pretend the refresh succeeded.
532 send_wins_name_registration_response(0, ttl, p);
541 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \
542 is IP is not known to the name.\n", nmb_namestr(question), inet_ntoa(from_ip) ));
543 send_wins_name_registration_response(RFS_ERR, 0, p);
548 /***********************************************************************
549 Deal with a name registration request query success to a client that
552 We have a locked pointer to the original packet stashed away in the
553 userdata pointer. The success here is actually a failure as it means
554 the client we queried wants to keep the name, so we must return
555 a registration failure to the original requestor.
556 ************************************************************************/
558 static void wins_register_query_success(struct subnet_record *subrec,
559 struct userdata_struct *userdata,
560 struct nmb_name *question_name,
562 struct res_rec *answers)
564 struct packet_struct *orig_reg_packet;
566 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
568 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
569 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
571 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
573 orig_reg_packet->locked = False;
574 free_packet(orig_reg_packet);
577 /***********************************************************************
578 Deal with a name registration request query failure to a client that
581 We have a locked pointer to the original packet stashed away in the
582 userdata pointer. The failure here is actually a success as it means
583 the client we queried didn't want to keep the name, so we can remove
584 the old name record and then successfully add the new name.
585 ************************************************************************/
587 static void wins_register_query_fail(struct subnet_record *subrec,
588 struct response_record *rrec,
589 struct nmb_name *question_name,
592 struct userdata_struct *userdata = rrec->userdata;
593 struct packet_struct *orig_reg_packet;
594 struct name_record *namerec = NULL;
596 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
599 * We want to just add the name, as we now know the original owner
600 * didn't want it. But we can't just do that as an arbitary
601 * amount of time may have taken place between the name query
602 * request and this timeout/error response. So we check that
603 * the name still exists and is in the same state - if so
604 * we remove it and call wins_process_name_registration_request()
605 * as we know it will do the right thing now.
608 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
610 if( (namerec != NULL)
611 && (namerec->data.source == REGISTER_NAME)
612 && ip_equal(rrec->packet->ip, *namerec->data.ip) )
614 remove_name_from_namelist( subrec, namerec);
619 wins_process_name_registration_request(subrec, orig_reg_packet);
621 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \
622 querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) ));
624 orig_reg_packet->locked = False;
625 free_packet(orig_reg_packet);
628 /***********************************************************************
629 Deal with a name registration request to a WINS server.
631 Use the following pseudocode :
639 | +--- existing name is group
642 | | +--- add name (return).
645 | +--- exiting name is unique
648 | +--- query existing owner (return).
651 +--------name doesn't exist
654 +--- add name (return).
662 | +--- existing name is group
665 | | +--- fail add (return).
668 | +--- exiting name is unique
671 | +--- query existing owner (return).
674 +--------name doesn't exist
677 +--- add name (return).
679 As can be seen from the above, the two cases may be collapsed onto each
680 other with the exception of the case where the name already exists and
681 is a group name. This case we handle with an if statement.
683 ************************************************************************/
685 void wins_process_name_registration_request(struct subnet_record *subrec,
686 struct packet_struct *p)
688 struct nmb_packet *nmb = &p->packet.nmb;
689 struct nmb_name *question = &nmb->question.question_name;
690 BOOL bcast = nmb->header.nm_flags.bcast;
691 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
692 int ttl = get_ttl_from_packet(nmb);
693 struct name_record *namerec = NULL;
694 struct in_addr from_ip;
695 BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;
696 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
698 putip((char *)&from_ip,&nmb->additional->rdata[2]);
703 * We should only get unicast name registration packets here.
704 * Anyone trying to register broadcast should not be going to a WINS
705 * server. Log an error here.
708 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
709 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
710 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
714 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
715 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
718 * See if the name already exists.
721 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
724 * if the record exists but NOT in active state,
727 if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec))
729 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
730 not active - removing it.\n", nmb_namestr(question) ));
731 remove_name_from_namelist( subrec, namerec );
736 * Deal with the case where the name found was a dns entry.
737 * Remove it as we now have a NetBIOS client registering the
741 if( (namerec != NULL)
742 && ( (namerec->data.source == DNS_NAME)
743 || (namerec->data.source == DNSFAIL_NAME) ) )
745 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
746 a dns lookup - removing it.\n", nmb_namestr(question) ));
747 remove_name_from_namelist( subrec, namerec );
752 * Reject if the name exists and is not a REGISTER_NAME.
753 * (ie. Don't allow any static names to be overwritten.
756 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME))
758 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
759 to register name %s. Name already exists in WINS with source type %d.\n",
760 nmb_namestr(question), namerec->data.source ));
761 send_wins_name_registration_response(RFS_ERR, 0, p);
766 * Special policy decisions based on MS documentation.
767 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
768 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
772 * A group name is always added as the local broadcast address, except
773 * for group names ending in 0x1c.
774 * Group names with type 0x1c are registered with individual IP addresses.
777 if(registering_group_name && (question->name_type != 0x1c))
778 from_ip = *interpret_addr2("255.255.255.255");
781 * Ignore all attempts to register a unique 0x1d name, although return success.
784 if(!registering_group_name && (question->name_type == 0x1d))
786 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
787 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
788 send_wins_name_registration_response(0, ttl, p);
793 * Next two cases are the 'if statement' mentioned above.
796 if((namerec != NULL) && NAME_GROUP(namerec))
798 if(registering_group_name)
801 * If we are adding a group name, the name exists and is also a group entry just add this
802 * IP address to it and update the ttl.
805 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
806 inet_ntoa(from_ip), nmb_namestr(question) ));
808 * Check the ip address is not already in the group.
810 if(!find_ip_in_name_record(namerec, from_ip)) {
811 add_ip_to_name_record(namerec, from_ip);
812 /* we need to update the record for replication */
813 get_global_id_and_update(&namerec->data.id, True);
816 * if the record is a replica, we must change
817 * the wins owner to us to make the replication updates
818 * it on the other wins servers.
819 * And when the partner will receive this record,
820 * it will update its own record.
823 update_wins_owner(namerec, our_fake_ip);
826 update_name_ttl(namerec, ttl);
827 send_wins_name_registration_response(0, ttl, p);
833 * If we are adding a unique name, the name exists in the WINS db
834 * and is a group name then reject the registration.
836 * explanation: groups have a higher priority than unique names.
839 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
840 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
841 send_wins_name_registration_response(RFS_ERR, 0, p);
847 * From here on down we know that if the name exists in the WINS db it is
848 * a unique name, not a group name.
852 * If the name exists and is one of our names then check the
853 * registering IP address. If it's not one of ours then automatically
854 * reject without doing the query - we know we will reject it.
857 if((namerec != NULL) && (is_myname(namerec->name.name)) )
861 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
862 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
863 send_wins_name_registration_response(RFS_ERR, 0, p);
869 * It's one of our names and one of our IP's - update the ttl.
871 update_name_ttl(namerec, ttl);
872 send_wins_name_registration_response(0, ttl, p);
873 wins_hook("refresh", namerec, ttl);
879 * If the name exists and it is a unique registration and the registering IP
880 * is the same as the (single) already registered IP then just update the ttl.
882 * But not if the record is an active replica. IF it's a replica, it means it can be
883 * the same client which has moved and not yet expired. So we don't update
884 * the ttl in this case and go beyond to do a WACK and query the old client
887 if( !registering_group_name
889 && (namerec->data.num_ips == 1)
890 && ip_equal( namerec->data.ip[0], from_ip )
891 && ip_equal(namerec->data.wins_ip, our_fake_ip) )
893 update_name_ttl( namerec, ttl );
894 send_wins_name_registration_response( 0, ttl, p );
895 wins_hook("refresh", namerec, ttl);
900 * Finally if the name exists do a query to the registering machine
901 * to see if they still claim to have the name.
904 if( namerec != NULL )
906 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
907 struct userdata_struct *userdata = (struct userdata_struct *)ud;
910 * First send a WACK to the registering machine.
913 send_wins_wack_response(60, p);
916 * When the reply comes back we need the original packet.
917 * Lock this so it won't be freed and then put it into
918 * the userdata structure.
923 userdata = (struct userdata_struct *)ud;
925 userdata->copy_fn = NULL;
926 userdata->free_fn = NULL;
927 userdata->userdata_len = sizeof(struct packet_struct *);
928 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
931 * Use the new call to send a query directly to an IP address.
932 * This sends the query directly to the IP address, and ensures
933 * the recursion desired flag is not set (you were right Luke :-).
934 * This function should *only* be called from the WINS server
938 query_name_from_wins_server( *namerec->data.ip,
941 wins_register_query_success,
942 wins_register_query_fail,
948 * Name did not exist - add it.
951 (void)add_name_to_subnet( subrec, question->name, question->name_type,
952 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
953 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
954 get_global_id_and_update(&namerec->data.id, True);
955 update_wins_owner(namerec, our_fake_ip);
956 update_wins_flag(namerec, WINS_ACTIVE);
957 wins_hook("add", namerec, ttl);
960 send_wins_name_registration_response(0, ttl, p);
963 /***********************************************************************
964 Deal with a mutihomed name query success to the machine that
965 requested the multihomed name registration.
967 We have a locked pointer to the original packet stashed away in the
969 ************************************************************************/
971 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
972 struct userdata_struct *userdata,
973 struct nmb_name *question_name,
975 struct res_rec *answers)
977 struct packet_struct *orig_reg_packet;
978 struct nmb_packet *nmb;
979 struct name_record *namerec = NULL;
980 struct in_addr from_ip;
982 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
984 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
986 nmb = &orig_reg_packet->packet.nmb;
988 putip((char *)&from_ip,&nmb->additional->rdata[2]);
989 ttl = get_ttl_from_packet(nmb);
992 * We want to just add the new IP, as we now know the requesting
993 * machine claims to own it. But we can't just do that as an arbitary
994 * amount of time may have taken place between the name query
995 * request and this response. So we check that
996 * the name still exists and is in the same state - if so
997 * we just add the extra IP and update the ttl.
1000 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1002 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) )
1004 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
1005 a subsequent IP addess.\n", nmb_namestr(question_name) ));
1006 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1008 orig_reg_packet->locked = False;
1009 free_packet(orig_reg_packet);
1014 if(!find_ip_in_name_record(namerec, from_ip))
1015 add_ip_to_name_record(namerec, from_ip);
1017 get_global_id_and_update(&namerec->data.id, True);
1018 update_wins_owner(namerec, our_fake_ip);
1019 update_wins_flag(namerec, WINS_ACTIVE);
1020 update_name_ttl(namerec, ttl);
1021 send_wins_name_registration_response(0, ttl, orig_reg_packet);
1022 wins_hook("add", namerec, ttl);
1024 orig_reg_packet->locked = False;
1025 free_packet(orig_reg_packet);
1028 /***********************************************************************
1029 Deal with a name registration request query failure to a client that
1032 We have a locked pointer to the original packet stashed away in the
1034 ************************************************************************/
1036 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
1037 struct response_record *rrec,
1038 struct nmb_name *question_name,
1041 struct userdata_struct *userdata = rrec->userdata;
1042 struct packet_struct *orig_reg_packet;
1044 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1046 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1047 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
1048 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1050 orig_reg_packet->locked = False;
1051 free_packet(orig_reg_packet);
1055 /***********************************************************************
1056 Deal with a multihomed name registration request to a WINS server.
1057 These cannot be group name registrations.
1058 ***********************************************************************/
1060 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
1061 struct packet_struct *p)
1063 struct nmb_packet *nmb = &p->packet.nmb;
1064 struct nmb_name *question = &nmb->question.question_name;
1065 BOOL bcast = nmb->header.nm_flags.bcast;
1066 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1067 int ttl = get_ttl_from_packet(nmb);
1068 struct name_record *namerec = NULL;
1069 struct in_addr from_ip;
1070 BOOL group = (nb_flags & NB_GROUP) ? True : False;
1071 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1073 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1078 * We should only get unicast name registration packets here.
1079 * Anyone trying to register broadcast should not be going to a WINS
1080 * server. Log an error here.
1083 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1084 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1085 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1090 * Only unique names should be registered multihomed.
1095 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1096 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1097 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1101 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1102 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1105 * Deal with policy regarding 0x1d names.
1108 if(question->name_type == 0x1d)
1110 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1111 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1112 send_wins_name_registration_response(0, ttl, p);
1117 * See if the name already exists.
1120 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1123 * Deal with the case where the name found was a dns entry.
1124 * Remove it as we now have a NetBIOS client registering the
1128 if( (namerec != NULL)
1129 && ( (namerec->data.source == DNS_NAME)
1130 || (namerec->data.source == DNSFAIL_NAME) ) )
1132 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1133 - removing it.\n", nmb_namestr(question) ));
1134 remove_name_from_namelist( subrec, namerec);
1139 * Reject if the name exists and is not a REGISTER_NAME.
1140 * (ie. Don't allow any static names to be overwritten.
1143 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) )
1145 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1146 to register name %s. Name already exists in WINS with source type %d.\n",
1147 nmb_namestr(question), namerec->data.source ));
1148 send_wins_name_registration_response(RFS_ERR, 0, p);
1153 * Reject if the name exists and is a GROUP name and is active.
1156 if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec))
1158 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1159 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1160 send_wins_name_registration_response(RFS_ERR, 0, p);
1165 * From here on down we know that if the name exists in the WINS db it is
1166 * a unique name, not a group name.
1170 * If the name exists and is one of our names then check the
1171 * registering IP address. If it's not one of ours then automatically
1172 * reject without doing the query - we know we will reject it.
1175 if((namerec != NULL) && (is_myname(namerec->name.name)) )
1177 if(!ismyip(from_ip))
1179 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1180 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1181 send_wins_name_registration_response(RFS_ERR, 0, p);
1187 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1188 * update the ttl. Update the version ID to force replication.
1190 if(!find_ip_in_name_record(namerec, from_ip)) {
1191 get_global_id_and_update(&namerec->data.id, True);
1192 update_wins_owner(namerec, our_fake_ip);
1193 update_wins_flag(namerec, WINS_ACTIVE);
1195 add_ip_to_name_record(namerec, from_ip);
1196 wins_hook("add", namerec, ttl);
1198 wins_hook("refresh", namerec, ttl);
1201 update_name_ttl(namerec, ttl);
1202 send_wins_name_registration_response(0, ttl, p);
1208 * If the name exists and is active, check if the IP address is already registered
1209 * to that name. If so then update the ttl and reply success.
1212 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec))
1214 update_name_ttl(namerec, ttl);
1216 * If it's a replica, we need to become the wins owner
1217 * to force the replication
1219 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1220 get_global_id_and_update(&namerec->data.id, True);
1221 update_wins_owner(namerec, our_fake_ip);
1222 update_wins_flag(namerec, WINS_ACTIVE);
1225 send_wins_name_registration_response(0, ttl, p);
1226 wins_hook("refresh", namerec, ttl);
1231 * If the name exists do a query to the owner
1232 * to see if they still want the name.
1237 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1238 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1241 * First send a WACK to the registering machine.
1244 send_wins_wack_response(60, p);
1247 * When the reply comes back we need the original packet.
1248 * Lock this so it won't be freed and then put it into
1249 * the userdata structure.
1254 userdata = (struct userdata_struct *)ud;
1256 userdata->copy_fn = NULL;
1257 userdata->free_fn = NULL;
1258 userdata->userdata_len = sizeof(struct packet_struct *);
1259 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1262 * Use the new call to send a query directly to an IP address.
1263 * This sends the query directly to the IP address, and ensures
1264 * the recursion desired flag is not set (you were right Luke :-).
1265 * This function should *only* be called from the WINS server
1268 * Note that this packet is sent to the current owner of the name,
1269 * not the person who sent the packet
1272 query_name_from_wins_server( namerec->data.ip[0],
1274 question->name_type,
1275 wins_multihomed_register_query_success,
1276 wins_multihomed_register_query_fail,
1283 * Name did not exist - add it.
1286 (void)add_name_to_subnet( subrec, question->name, question->name_type,
1287 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1289 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1290 get_global_id_and_update(&namerec->data.id, True);
1291 update_wins_owner(namerec, our_fake_ip);
1292 update_wins_flag(namerec, WINS_ACTIVE);
1293 wins_hook("add", namerec, ttl);
1296 send_wins_name_registration_response(0, ttl, p);
1299 /***********************************************************************
1300 Deal with the special name query for *<1b>.
1301 ***********************************************************************/
1303 static void process_wins_dmb_query_request(struct subnet_record *subrec,
1304 struct packet_struct *p)
1306 struct name_record *namerec = NULL;
1311 * Go through all the ACTIVE names in the WINS db looking for those
1312 * ending in <1b>. Use this to calculate the number of IP
1313 * addresses we need to return.
1317 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1319 namerec = (struct name_record *)ubi_trNext( namerec ) )
1321 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b )
1322 num_ips += namerec->data.num_ips;
1328 * There are no 0x1b names registered. Return name query fail.
1330 send_wins_name_query_response(NAM_ERR, p, NULL);
1334 if((prdata = (char *)malloc( num_ips * 6 )) == NULL)
1336 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1341 * Go through all the names again in the WINS db looking for those
1342 * ending in <1b>. Add their IP addresses into the list we will
1347 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1349 namerec = (struct name_record *)ubi_trNext( namerec ) )
1351 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b)
1354 for(i = 0; i < namerec->data.num_ips; i++)
1356 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1357 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1364 * Send back the reply containing the IP list.
1367 reply_netbios_packet(p, /* Packet to reply to. */
1368 0, /* Result code. */
1369 WINS_QUERY, /* nmbd type code. */
1370 NMB_NAME_QUERY_OPCODE, /* opcode. */
1371 lp_min_wins_ttl(), /* ttl. */
1372 prdata, /* data to send. */
1373 num_ips*6); /* data length. */
1378 /****************************************************************************
1379 Send a WINS name query response.
1380 **************************************************************************/
1382 void send_wins_name_query_response(int rcode, struct packet_struct *p,
1383 struct name_record *namerec)
1386 char *prdata = rdata;
1387 int reply_data_len = 0;
1391 memset(rdata,'\0',6);
1395 ttl = (namerec->data.death_time != PERMANENT_TTL) ?
1396 namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1398 /* Copy all known ip addresses into the return data. */
1399 /* Optimise for the common case of one IP address so
1400 we don't need a malloc. */
1402 if( namerec->data.num_ips == 1 )
1406 if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL)
1408 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1413 for(i = 0; i < namerec->data.num_ips; i++)
1415 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
1416 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
1419 sort_query_replies(prdata, i, p->ip);
1421 reply_data_len = namerec->data.num_ips * 6;
1424 reply_netbios_packet(p, /* Packet to reply to. */
1425 rcode, /* Result code. */
1426 WINS_QUERY, /* nmbd type code. */
1427 NMB_NAME_QUERY_OPCODE, /* opcode. */
1429 prdata, /* data to send. */
1430 reply_data_len); /* data length. */
1436 /***********************************************************************
1437 Deal with a name query.
1438 ***********************************************************************/
1440 void wins_process_name_query_request(struct subnet_record *subrec,
1441 struct packet_struct *p)
1443 struct nmb_packet *nmb = &p->packet.nmb;
1444 struct nmb_name *question = &nmb->question.question_name;
1445 struct name_record *namerec = NULL;
1447 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
1448 nmb_namestr(question), inet_ntoa(p->ip) ));
1451 * Special name code. If the queried name is *<1b> then search
1452 * the entire WINS database and return a list of all the IP addresses
1453 * registered to any <1b> name. This is to allow domain master browsers
1454 * to discover other domains that may not have a presence on their subnet.
1457 if(strequal( question->name, "*") && (question->name_type == 0x1b))
1459 process_wins_dmb_query_request( subrec, p);
1463 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1468 * If the name is not anymore in active state then reply not found.
1469 * it's fair even if we keep it in the cache for days.
1471 if (!WINS_STATE_ACTIVE(namerec))
1473 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1474 nmb_namestr(question) ));
1475 send_wins_name_query_response(NAM_ERR, p, namerec);
1479 * If it's a DNSFAIL_NAME then reply name not found.
1482 if( namerec->data.source == DNSFAIL_NAME )
1484 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
1485 nmb_namestr(question) ));
1486 send_wins_name_query_response(NAM_ERR, p, namerec);
1491 * If the name has expired then reply name not found.
1494 if( (namerec->data.death_time != PERMANENT_TTL)
1495 && (namerec->data.death_time < p->timestamp) )
1497 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1498 nmb_namestr(question) ));
1499 send_wins_name_query_response(NAM_ERR, p, namerec);
1503 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
1504 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
1506 send_wins_name_query_response(0, p, namerec);
1511 * Name not found in WINS - try a dns query if it's a 0x20 name.
1514 if(lp_dns_proxy() &&
1515 ((question->name_type == 0x20) || question->name_type == 0))
1518 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
1519 nmb_namestr(question) ));
1521 queue_dns_query(p, question, &namerec);
1526 * Name not found - return error.
1529 send_wins_name_query_response(NAM_ERR, p, NULL);
1532 /****************************************************************************
1533 Send a WINS name release response.
1534 **************************************************************************/
1536 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
1538 struct nmb_packet *nmb = &p->packet.nmb;
1541 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
1543 reply_netbios_packet(p, /* Packet to reply to. */
1544 rcode, /* Result code. */
1545 NMB_REL, /* nmbd type code. */
1546 NMB_NAME_RELEASE_OPCODE, /* opcode. */
1548 rdata, /* data to send. */
1549 6); /* data length. */
1552 /***********************************************************************
1553 Deal with a name release.
1554 ***********************************************************************/
1556 void wins_process_name_release_request(struct subnet_record *subrec,
1557 struct packet_struct *p)
1559 struct nmb_packet *nmb = &p->packet.nmb;
1560 struct nmb_name *question = &nmb->question.question_name;
1561 BOOL bcast = nmb->header.nm_flags.bcast;
1562 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1563 struct name_record *namerec = NULL;
1564 struct in_addr from_ip;
1565 BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
1567 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1572 * We should only get unicast name registration packets here.
1573 * Anyone trying to register broadcast should not be going to a WINS
1574 * server. Log an error here.
1577 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
1578 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1579 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1583 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
1584 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1587 * Deal with policy regarding 0x1d names.
1590 if(!releasing_group_name && (question->name_type == 0x1d))
1592 DEBUG(3,("wins_process_name_release_request: Ignoring request \
1593 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1594 send_wins_name_release_response(0, p);
1599 * See if the name already exists.
1602 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1604 if( (namerec == NULL)
1605 || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) )
1607 send_wins_name_release_response(NAM_ERR, p);
1612 * Check that the sending machine has permission to release this name.
1613 * If it's a group name not ending in 0x1c then just say yes and let
1614 * the group time out.
1617 if(releasing_group_name && (question->name_type != 0x1c))
1619 send_wins_name_release_response(0, p);
1624 * Check that the releasing node is on the list of IP addresses
1625 * for this name. Disallow the release if not.
1628 if(!find_ip_in_name_record(namerec, from_ip))
1630 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1631 release name %s as IP %s is not one of the known IP's for this name.\n",
1632 nmb_namestr(question), inet_ntoa(from_ip) ));
1633 send_wins_name_release_response(NAM_ERR, p);
1638 * Check if the record is active. IF it's already released
1639 * or tombstoned, refuse the release.
1641 if (!WINS_STATE_ACTIVE(namerec)) {
1642 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1643 release name %s as this record is not anymore active.\n",
1644 nmb_namestr(question) ));
1645 send_wins_name_release_response(NAM_ERR, p);
1650 * Send a release response.
1651 * Flag the name as released and update the ttl
1654 send_wins_name_release_response(0, p);
1656 namerec->data.wins_flags |= WINS_RELEASED;
1657 update_name_ttl(namerec, EXTINCTION_INTERVAL);
1659 wins_hook("delete", namerec, 0);
1662 /*******************************************************************
1663 WINS time dependent processing.
1664 ******************************************************************/
1666 void initiate_wins_processing(time_t t)
1668 static time_t lasttime = 0;
1669 struct name_record *namerec;
1670 struct name_record *next_namerec;
1671 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1675 if (t - lasttime < 20)
1680 if(!lp_we_are_a_wins_server())
1683 for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
1685 namerec = next_namerec ) {
1686 next_namerec = (struct name_record *)ubi_trNext( namerec );
1688 if( (namerec->data.death_time != PERMANENT_TTL)
1689 && (namerec->data.death_time < t) ) {
1691 if( namerec->data.source == SELF_NAME ) {
1692 DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF name %s\n",
1693 wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
1694 namerec->data.death_time += 300;
1695 namerec->subnet->namelist_changed = True;
1699 /* handle records, samba is the wins owner */
1700 if (ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1701 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
1703 namerec->data.wins_flags&=~WINS_STATE_MASK;
1704 namerec->data.wins_flags|=WINS_RELEASED;
1705 namerec->data.death_time = t + EXTINCTION_INTERVAL;
1706 DEBUG(3,("initiate_wins_processing: expiring %s\n", nmb_namestr(&namerec->name)));
1709 namerec->data.wins_flags&=~WINS_STATE_MASK;
1710 namerec->data.wins_flags|=WINS_TOMBSTONED;
1711 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
1712 get_global_id_and_update(&namerec->data.id, True);
1713 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
1715 case WINS_TOMBSTONED:
1716 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
1717 remove_name_from_namelist( wins_server_subnet, namerec );
1721 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
1723 /* that's not as MS says it should be */
1724 namerec->data.wins_flags&=~WINS_STATE_MASK;
1725 namerec->data.wins_flags|=WINS_TOMBSTONED;
1726 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
1727 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
1728 case WINS_TOMBSTONED:
1729 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
1730 remove_name_from_namelist( wins_server_subnet, namerec );
1733 DEBUG(0,("initiate_wins_processing: %s is in released state and\
1734 we are not the wins owner !\n", nmb_namestr(&namerec->name)));
1742 if(wins_server_subnet->namelist_changed)
1743 wins_write_database(True);
1745 wins_server_subnet->namelist_changed = False;
1748 /*******************************************************************
1749 Write out the current WINS database.
1750 ******************************************************************/
1751 void wins_write_database(BOOL background)
1753 struct name_record *namerec;
1754 pstring fname, fnamenew;
1756 TDB_DATA kbuf, dbuf;
1762 if(!lp_we_are_a_wins_server())
1765 /* we will do the writing in a child process to ensure that the parent
1766 doesn't block while this is done */
1774 slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST);
1775 all_string_sub(fname,"//", "/", 0);
1776 slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid());
1778 tdb = tdb_open_log(fnamenew, 0, TDB_DEFAULT, O_RDWR|O_CREAT|O_TRUNC, 0644);
1780 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
1786 DEBUG(3,("wins_write_database: Dump of WINS name list.\n"));
1788 tdb_store_int(tdb, INFO_VERSION, WINS_VERSION);
1790 for (namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
1792 namerec = (struct name_record *)ubi_trNext( namerec ) ) {
1797 DEBUGADD(3,("%-19s ", nmb_namestr(&namerec->name) ));
1799 if( namerec->data.death_time != PERMANENT_TTL ) {
1802 tm = LocalTime(&namerec->data.death_time);
1804 nl = strrchr_m( ts, '\n' );
1808 DEBUGADD(3,("TTL = %s ", ts ));
1810 DEBUGADD(3,("TTL = PERMANENT "));
1812 for (i = 0; i < namerec->data.num_ips; i++)
1813 DEBUGADD(0,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
1815 DEBUGADD(3,("0x%2x 0x%2x %15s\n", namerec->data.nb_flags, namerec->data.wins_flags, inet_ntoa(namerec->data.wins_ip)));
1817 if( namerec->data.source == REGISTER_NAME ) {
1819 /* store the type in the key to make the name unique */
1820 slprintf(key, sizeof(key), "%s%s#%02x", ENTRY_PREFIX, namerec->name.name, namerec->name.name_type);
1822 len = tdb_pack(buf, sizeof(buf), "dddfddd",
1823 (int)namerec->data.nb_flags,
1824 (int)(namerec->data.id>>32),
1825 (int)(namerec->data.id&0xffffffff),
1826 inet_ntoa(namerec->data.wins_ip),
1827 (int)namerec->data.death_time,
1828 namerec->data.num_ips,
1829 namerec->data.wins_flags);
1831 for (i = 0; i < namerec->data.num_ips; i++)
1832 len += tdb_pack(buf+len, sizeof(buf)-len, "f", inet_ntoa(namerec->data.ip[i]));
1834 kbuf.dsize = strlen(key)+1;
1838 if (tdb_store(tdb, kbuf, dbuf, TDB_INSERT) != 0) return;
1844 /* store the number of records */
1845 tdb_store_int(tdb, INFO_COUNT, num_record);
1847 /* get and store the last used ID */
1848 get_global_id_and_update(&id, False);
1849 tdb_store_int(tdb, INFO_ID_HIGH, id>>32);
1850 tdb_store_int(tdb, INFO_ID_LOW, id&0xffffffff);
1854 chmod(fnamenew,0644);
1856 rename(fnamenew,fname);
1862 /****************************************************************************
1863 process a internal Samba message receiving a wins record
1864 ***************************************************************************/
1865 void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len)
1867 WINS_RECORD *record;
1868 struct name_record *namerec = NULL;
1869 struct name_record *new_namerec = NULL;
1870 struct nmb_name question;
1871 BOOL overwrite=False;
1872 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1878 record=(WINS_RECORD *)buf;
1880 ZERO_STRUCT(question);
1881 memcpy(question.name, record->name, 16);
1882 question.name_type=record->type;
1884 namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
1886 /* record doesn't exist, add it */
1887 if (namerec == NULL) {
1888 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
1889 record->name, record->type, inet_ntoa(record->wins_ip)));
1891 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
1892 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
1893 if (new_namerec!=NULL) {
1894 update_wins_owner(new_namerec, record->wins_ip);
1895 update_wins_flag(new_namerec, record->wins_flags);
1896 new_namerec->data.id=record->id;
1898 wins_server_subnet->namelist_changed = True;
1902 /* check if we have a conflict */
1903 if (namerec != NULL) {
1904 /* both records are UNIQUE */
1905 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
1907 /* the database record is a replica */
1908 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1909 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
1910 if (ip_equal(namerec->data.wins_ip, record->wins_ip))
1915 /* we are the wins owner of the database record */
1916 /* the 2 records have the same IP address */
1917 if (ip_equal(namerec->data.ip[0], record->ip[0])) {
1918 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
1919 get_global_id_and_update(&namerec->data.id, True);
1924 /* the 2 records have different IP address */
1925 if (namerec->data.wins_flags&WINS_ACTIVE) {
1926 if (record->wins_flags&WINS_TOMBSTONED)
1927 get_global_id_and_update(&namerec->data.id, True);
1928 if (record->wins_flags&WINS_ACTIVE)
1929 /* send conflict challenge to the replica node */
1938 /* the replica is a standard group */
1939 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {
1940 /* if the database record is unique and active force a name release */
1941 if (namerec->data.wins_flags&WINS_UNIQUE)
1942 /* send a release name to the unique node */
1948 /* the replica is a special group */
1949 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
1950 if (namerec->data.wins_flags&WINS_ACTIVE) {
1951 for (i=0; i<record->num_ips; i++)
1952 if(!find_ip_in_name_record(namerec, record->ip[i]))
1953 add_ip_to_name_record(namerec, record->ip[i]);
1959 /* the replica is a multihomed host */
1961 /* I'm giving up on multi homed. Too much complex to understand */
1963 if (record->wins_flags&WINS_MHOMED) {
1964 if (! namerec->data.wins_flags&WINS_ACTIVE) {
1965 if ( !namerec->data.wins_flags&WINS_RELEASED && !namerec->data.wins_flags&WINS_NGROUP)
1969 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
1972 if (ip_equal(namerec->data.wins_ip, our_fake_ip))
1973 if (namerec->data.wins_flags&WINS_UNIQUE)
1974 get_global_id_and_update(&namerec->data.id, True);
1978 if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
1979 if (namerec->data.wins_flags&WINS_UNIQUE ||
1980 namerec->data.wins_flags&WINS_MHOMED)
1981 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
1986 if (overwrite == False)
1987 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
1988 record->name, record->type, inet_ntoa(record->wins_ip)));
1990 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
1991 record->name, record->type, inet_ntoa(record->wins_ip)));
1993 /* remove the old record and add a new one */
1994 remove_name_from_namelist( wins_server_subnet, namerec );
1995 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
1996 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
1997 if (new_namerec!=NULL) {
1998 update_wins_owner(new_namerec, record->wins_ip);
1999 update_wins_flag(new_namerec, record->wins_flags);
2000 new_namerec->data.id=record->id;
2002 wins_server_subnet->namelist_changed = True;
2005 wins_server_subnet->namelist_changed = True;