compile fix
[Samba.git] / source / nmbd / nmbd_winsserver.c
blob3332e99e9d5c5a0a2393c66d64981a162922f533
1 /*
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.
23 #include "includes.h"
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)
33 if (namerec==NULL)
34 return;
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)
43 if (namerec==NULL)
44 return;
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;
52 else
53 if (namerec->data.num_ips>1)
54 namerec->data.wins_flags|=WINS_SGROUP;
55 else
56 namerec->data.wins_flags|=WINS_NGROUP;
57 } else {
58 /* can be unique or multi-homed */
59 if (namerec->data.num_ips>1)
60 namerec->data.wins_flags|=WINS_MHOMED;
61 else
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;
96 if (update)
97 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)
105 pstring command;
106 char *cmd = lp_wins_hook();
107 char *p;
108 int i;
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)));
115 return;
119 p = command;
120 p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d",
121 cmd,
122 operation,
123 namerec->name.name,
124 namerec->name.name_type,
125 ttl);
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"));
148 return False;
151 /* Check for node status requests. */
152 if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY)
153 return False;
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"));
162 return False;
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"));
174 return False;
176 break;
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"));
182 return False;
184 break;
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"));
193 return False;
195 break;
198 return True;
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();
215 return ttl;
218 /****************************************************************************
219 Load or create the WINS database.
220 *****************************************************************************/
222 BOOL initialise_wins(void)
224 time_t time_now = time(NULL);
225 TDB_CONTEXT *tdb;
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())
233 return True;
235 add_samba_names_to_subnet(wins_server_subnet);
237 tdb = tdb_open_log(lock_path(WINS_LIST), 0, TDB_DEFAULT, O_RDONLY, 0600);
238 if (!tdb) {
239 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n", WINS_LIST, strerror(errno) ));
240 return True;
243 if (tdb_fetch_int32(tdb, INFO_VERSION) != WINS_VERSION) {
244 DEBUG(0,("Discarding invalid wins.dat file\n"));
245 tdb_close(tdb);
246 return True;
249 for (kbuf = tdb_firstkey(tdb);
250 kbuf.dptr;
251 newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
253 pstring name_type, name, ip_str;
254 char *p;
255 int type = 0;
256 int nb_flags;
257 int ttl;
258 unsigned int num_ips;
259 int high, low;
260 struct in_addr wins_ip;
261 struct in_addr *ip_list;
262 int wins_flags;
263 int len,i;
265 if (strncmp(kbuf.dptr, ENTRY_PREFIX, strlen(ENTRY_PREFIX)) != 0)
266 continue;
268 dbuf = tdb_fetch(tdb, kbuf);
269 if (!dbuf.dptr) continue;
271 fstrcpy(name_type, kbuf.dptr+strlen(ENTRY_PREFIX));
273 pstrcpy(name, name_type);
275 if((p = strchr(name,'#')) != NULL) {
276 *p = 0;
277 sscanf(p+1,"%x",&type);
280 len = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddfddd",
281 &nb_flags, &high, &low,
282 ip_str, &ttl, &num_ips, &wins_flags);
284 wins_ip=*interpret_addr2(ip_str);
286 /* Don't reload replica records */
287 if (!ip_equal(wins_ip, our_fake_ip))
288 continue;
290 /* Don't reload released or tombstoned records */
291 if ((wins_flags&WINS_STATE_MASK) != WINS_ACTIVE)
292 continue;
294 /* Allocate the space for the ip_list. */
295 if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL) {
296 DEBUG(0,("initialise_wins: Malloc fail !\n"));
297 return False;
300 for (i = 0; i < num_ips; i++) {
301 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f", ip_str);
302 ip_list[i] = *interpret_addr2(ip_str);
305 /* add all entries that have 60 seconds or more to live */
306 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {
307 if(ttl != PERMANENT_TTL)
308 ttl -= time_now;
310 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
311 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
313 namerec=add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
314 ttl, REGISTER_NAME, num_ips, ip_list);
315 if (namerec!=NULL) {
316 update_wins_owner(namerec, wins_ip);
317 update_wins_flag(namerec, wins_flags);
318 /* we don't reload the ID, on startup we restart at 1 */
319 get_global_id_and_update(&namerec->data.id, True);
322 } else {
323 DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n",
324 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
327 SAFE_FREE(ip_list);
330 tdb_close(tdb);
331 DEBUG(2,("initialise_wins: done\n"));
332 return True;
335 /****************************************************************************
336 Send a WINS WACK (Wait ACKnowledgement) response.
337 **************************************************************************/
339 static void send_wins_wack_response(int ttl, struct packet_struct *p)
341 struct nmb_packet *nmb = &p->packet.nmb;
342 unsigned char rdata[2];
344 rdata[0] = rdata[1] = 0;
346 /* Taken from nmblib.c - we need to send back almost
347 identical bytes from the requesting packet header. */
349 rdata[0] = (nmb->header.opcode & 0xF) << 3;
350 if (nmb->header.nm_flags.authoritative &&
351 nmb->header.response) rdata[0] |= 0x4;
352 if (nmb->header.nm_flags.trunc) rdata[0] |= 0x2;
353 if (nmb->header.nm_flags.recursion_desired) rdata[0] |= 0x1;
354 if (nmb->header.nm_flags.recursion_available &&
355 nmb->header.response) rdata[1] |= 0x80;
356 if (nmb->header.nm_flags.bcast) rdata[1] |= 0x10;
358 reply_netbios_packet(p, /* Packet to reply to. */
359 0, /* Result code. */
360 NMB_WAIT_ACK, /* nmbd type code. */
361 NMB_WACK_OPCODE, /* opcode. */
362 ttl, /* ttl. */
363 (char *)rdata, /* data to send. */
364 2); /* data length. */
367 /****************************************************************************
368 Send a WINS name registration response.
369 **************************************************************************/
371 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
373 struct nmb_packet *nmb = &p->packet.nmb;
374 char rdata[6];
376 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
378 reply_netbios_packet(p, /* Packet to reply to. */
379 rcode, /* Result code. */
380 WINS_REG, /* nmbd type code. */
381 NMB_NAME_REG_OPCODE, /* opcode. */
382 ttl, /* ttl. */
383 rdata, /* data to send. */
384 6); /* data length. */
387 /***********************************************************************
388 Deal with a name refresh request to a WINS server.
389 ************************************************************************/
391 void wins_process_name_refresh_request(struct subnet_record *subrec,
392 struct packet_struct *p)
394 struct nmb_packet *nmb = &p->packet.nmb;
395 struct nmb_name *question = &nmb->question.question_name;
396 BOOL bcast = nmb->header.nm_flags.bcast;
397 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
398 BOOL group = (nb_flags & NB_GROUP) ? True : False;
399 struct name_record *namerec = NULL;
400 int ttl = get_ttl_from_packet(nmb);
401 struct in_addr from_ip;
402 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
404 putip((char *)&from_ip,&nmb->additional->rdata[2]);
406 if(bcast)
409 * We should only get unicast name refresh packets here.
410 * Anyone trying to refresh broadcast should not be going to a WINS
411 * server. Log an error here.
414 DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh request \
415 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
416 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
417 return;
420 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \
421 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
424 * See if the name already exists.
427 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
430 * If this is a refresh request and the name doesn't exist then
431 * treat it like a registration request. This allows us to recover
432 * from errors (tridge)
435 if(namerec == NULL)
437 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \
438 the name does not exist. Treating as registration.\n", nmb_namestr(question) ));
439 wins_process_name_registration_request(subrec,p);
440 return;
444 * if the name is present but not active,
445 * simply remove it and treat the request
446 * as a registration
448 if (namerec != NULL && !WINS_STATE_ACTIVE(namerec))
450 DEBUG(5,("wins_process_name_refresh_request: Name (%s) in WINS was \
451 not active - removing it.\n", nmb_namestr(question) ));
452 remove_name_from_namelist( subrec, namerec );
453 namerec = NULL;
454 wins_process_name_registration_request(subrec,p);
455 return;
459 * Check that the group bits for the refreshing name and the
460 * name in our database match.
463 if((namerec != NULL) && ((group && !NAME_GROUP(namerec)) || (!group && NAME_GROUP(namerec))) )
465 DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \
466 does not match group bit in WINS for this name.\n", nmb_namestr(question), group ? "True" : "False" ));
467 send_wins_name_registration_response(RFS_ERR, 0, p);
468 return;
472 * For a unique name check that the person refreshing the name is one of the registered IP
473 * addresses. If not - fail the refresh. Do the same for group names with a type of 0x1c.
474 * Just return success for unique 0x1d refreshes. For normal group names update the ttl
475 * and return success.
478 if((!group || (group && (question->name_type == 0x1c))) && find_ip_in_name_record(namerec, from_ip ))
481 * Update the ttl.
483 update_name_ttl(namerec, ttl);
486 * if the record is a replica:
487 * we take ownership and update the version ID.
489 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
490 update_wins_owner(namerec, our_fake_ip);
491 get_global_id_and_update(&namerec->data.id, True);
494 send_wins_name_registration_response(0, ttl, p);
495 wins_hook("refresh", namerec, ttl);
496 return;
498 else if(group)
501 * Normal groups are all registered with an IP address of 255.255.255.255
502 * so we can't search for the IP address.
504 update_name_ttl(namerec, ttl);
505 send_wins_name_registration_response(0, ttl, p);
506 return;
508 else if(!group && (question->name_type == 0x1d))
511 * Special name type - just pretend the refresh succeeded.
513 send_wins_name_registration_response(0, ttl, p);
514 return;
516 else
519 * Fail the refresh.
522 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \
523 is IP is not known to the name.\n", nmb_namestr(question), inet_ntoa(from_ip) ));
524 send_wins_name_registration_response(RFS_ERR, 0, p);
525 return;
529 /***********************************************************************
530 Deal with a name registration request query success to a client that
531 owned the name.
533 We have a locked pointer to the original packet stashed away in the
534 userdata pointer. The success here is actually a failure as it means
535 the client we queried wants to keep the name, so we must return
536 a registration failure to the original requestor.
537 ************************************************************************/
539 static void wins_register_query_success(struct subnet_record *subrec,
540 struct userdata_struct *userdata,
541 struct nmb_name *question_name,
542 struct in_addr ip,
543 struct res_rec *answers)
545 struct packet_struct *orig_reg_packet;
547 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
549 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
550 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
552 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
554 orig_reg_packet->locked = False;
555 free_packet(orig_reg_packet);
558 /***********************************************************************
559 Deal with a name registration request query failure to a client that
560 owned the name.
562 We have a locked pointer to the original packet stashed away in the
563 userdata pointer. The failure here is actually a success as it means
564 the client we queried didn't want to keep the name, so we can remove
565 the old name record and then successfully add the new name.
566 ************************************************************************/
568 static void wins_register_query_fail(struct subnet_record *subrec,
569 struct response_record *rrec,
570 struct nmb_name *question_name,
571 int rcode)
573 struct userdata_struct *userdata = rrec->userdata;
574 struct packet_struct *orig_reg_packet;
575 struct name_record *namerec = NULL;
577 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
580 * We want to just add the name, as we now know the original owner
581 * didn't want it. But we can't just do that as an arbitary
582 * amount of time may have taken place between the name query
583 * request and this timeout/error response. So we check that
584 * the name still exists and is in the same state - if so
585 * we remove it and call wins_process_name_registration_request()
586 * as we know it will do the right thing now.
589 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
591 if( (namerec != NULL)
592 && (namerec->data.source == REGISTER_NAME)
593 && ip_equal(rrec->packet->ip, *namerec->data.ip) )
595 remove_name_from_namelist( subrec, namerec);
596 namerec = NULL;
599 if(namerec == NULL)
600 wins_process_name_registration_request(subrec, orig_reg_packet);
601 else
602 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \
603 querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) ));
605 orig_reg_packet->locked = False;
606 free_packet(orig_reg_packet);
609 /***********************************************************************
610 Deal with a name registration request to a WINS server.
612 Use the following pseudocode :
614 registering_group
617 +--------name exists
620 | +--- existing name is group
621 | | |
622 | | |
623 | | +--- add name (return).
626 | +--- exiting name is unique
629 | +--- query existing owner (return).
632 +--------name doesn't exist
635 +--- add name (return).
637 registering_unique
640 +--------name exists
643 | +--- existing name is group
644 | | |
645 | | |
646 | | +--- fail add (return).
647 | |
649 | +--- exiting name is unique
652 | +--- query existing owner (return).
655 +--------name doesn't exist
658 +--- add name (return).
660 As can be seen from the above, the two cases may be collapsed onto each
661 other with the exception of the case where the name already exists and
662 is a group name. This case we handle with an if statement.
664 ************************************************************************/
666 void wins_process_name_registration_request(struct subnet_record *subrec,
667 struct packet_struct *p)
669 struct nmb_packet *nmb = &p->packet.nmb;
670 struct nmb_name *question = &nmb->question.question_name;
671 BOOL bcast = nmb->header.nm_flags.bcast;
672 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
673 int ttl = get_ttl_from_packet(nmb);
674 struct name_record *namerec = NULL;
675 struct in_addr from_ip;
676 BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;
677 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
679 putip((char *)&from_ip,&nmb->additional->rdata[2]);
681 if(bcast)
684 * We should only get unicast name registration packets here.
685 * Anyone trying to register broadcast should not be going to a WINS
686 * server. Log an error here.
689 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
690 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
691 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
692 return;
695 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
696 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
699 * See if the name already exists.
702 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
705 * if the record exists but NOT in active state,
706 * consider it dead.
708 if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec))
710 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
711 not active - removing it.\n", nmb_namestr(question) ));
712 remove_name_from_namelist( subrec, namerec );
713 namerec = NULL;
717 * Deal with the case where the name found was a dns entry.
718 * Remove it as we now have a NetBIOS client registering the
719 * name.
722 if( (namerec != NULL)
723 && ( (namerec->data.source == DNS_NAME)
724 || (namerec->data.source == DNSFAIL_NAME) ) )
726 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
727 a dns lookup - removing it.\n", nmb_namestr(question) ));
728 remove_name_from_namelist( subrec, namerec );
729 namerec = NULL;
733 * Reject if the name exists and is not a REGISTER_NAME.
734 * (ie. Don't allow any static names to be overwritten.
737 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME))
739 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
740 to register name %s. Name already exists in WINS with source type %d.\n",
741 nmb_namestr(question), namerec->data.source ));
742 send_wins_name_registration_response(RFS_ERR, 0, p);
743 return;
747 * Special policy decisions based on MS documentation.
748 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
749 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
753 * A group name is always added as the local broadcast address, except
754 * for group names ending in 0x1c.
755 * Group names with type 0x1c are registered with individual IP addresses.
758 if(registering_group_name && (question->name_type != 0x1c))
759 from_ip = *interpret_addr2("255.255.255.255");
762 * Ignore all attempts to register a unique 0x1d name, although return success.
765 if(!registering_group_name && (question->name_type == 0x1d))
767 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
768 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
769 send_wins_name_registration_response(0, ttl, p);
770 return;
774 * Next two cases are the 'if statement' mentioned above.
777 if((namerec != NULL) && NAME_GROUP(namerec))
779 if(registering_group_name)
782 * If we are adding a group name, the name exists and is also a group entry just add this
783 * IP address to it and update the ttl.
786 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
787 inet_ntoa(from_ip), nmb_namestr(question) ));
789 * Check the ip address is not already in the group.
791 if(!find_ip_in_name_record(namerec, from_ip)) {
792 add_ip_to_name_record(namerec, from_ip);
793 /* we need to update the record for replication */
794 get_global_id_and_update(&namerec->data.id, True);
797 * if the record is a replica, we must change
798 * the wins owner to us to make the replication updates
799 * it on the other wins servers.
800 * And when the partner will receive this record,
801 * it will update its own record.
804 update_wins_owner(namerec, our_fake_ip);
807 update_name_ttl(namerec, ttl);
808 send_wins_name_registration_response(0, ttl, p);
809 return;
811 else
814 * If we are adding a unique name, the name exists in the WINS db
815 * and is a group name then reject the registration.
817 * explanation: groups have a higher priority than unique names.
820 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
821 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
822 send_wins_name_registration_response(RFS_ERR, 0, p);
823 return;
828 * From here on down we know that if the name exists in the WINS db it is
829 * a unique name, not a group name.
833 * If the name exists and is one of our names then check the
834 * registering IP address. If it's not one of ours then automatically
835 * reject without doing the query - we know we will reject it.
838 if((namerec != NULL) && (is_myname(namerec->name.name)) )
840 if(!ismyip(from_ip))
842 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
843 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
844 send_wins_name_registration_response(RFS_ERR, 0, p);
845 return;
847 else
850 * It's one of our names and one of our IP's - update the ttl.
852 update_name_ttl(namerec, ttl);
853 send_wins_name_registration_response(0, ttl, p);
854 wins_hook("refresh", namerec, ttl);
855 return;
860 * If the name exists and it is a unique registration and the registering IP
861 * is the same as the (single) already registered IP then just update the ttl.
863 * But not if the record is an active replica. IF it's a replica, it means it can be
864 * the same client which has moved and not yet expired. So we don't update
865 * the ttl in this case and go beyond to do a WACK and query the old client
868 if( !registering_group_name
869 && (namerec != NULL)
870 && (namerec->data.num_ips == 1)
871 && ip_equal( namerec->data.ip[0], from_ip )
872 && ip_equal(namerec->data.wins_ip, our_fake_ip) )
874 update_name_ttl( namerec, ttl );
875 send_wins_name_registration_response( 0, ttl, p );
876 wins_hook("refresh", namerec, ttl);
877 return;
881 * Finally if the name exists do a query to the registering machine
882 * to see if they still claim to have the name.
885 if( namerec != NULL )
887 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
888 struct userdata_struct *userdata = (struct userdata_struct *)ud;
891 * First send a WACK to the registering machine.
894 send_wins_wack_response(60, p);
897 * When the reply comes back we need the original packet.
898 * Lock this so it won't be freed and then put it into
899 * the userdata structure.
902 p->locked = True;
904 userdata = (struct userdata_struct *)ud;
906 userdata->copy_fn = NULL;
907 userdata->free_fn = NULL;
908 userdata->userdata_len = sizeof(struct packet_struct *);
909 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
912 * Use the new call to send a query directly to an IP address.
913 * This sends the query directly to the IP address, and ensures
914 * the recursion desired flag is not set (you were right Luke :-).
915 * This function should *only* be called from the WINS server
916 * code. JRA.
919 query_name_from_wins_server( *namerec->data.ip,
920 question->name,
921 question->name_type,
922 wins_register_query_success,
923 wins_register_query_fail,
924 userdata );
925 return;
929 * Name did not exist - add it.
932 (void)add_name_to_subnet( subrec, question->name, question->name_type,
933 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
934 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
935 get_global_id_and_update(&namerec->data.id, True);
936 update_wins_owner(namerec, our_fake_ip);
937 update_wins_flag(namerec, WINS_ACTIVE);
938 wins_hook("add", namerec, ttl);
941 send_wins_name_registration_response(0, ttl, p);
944 /***********************************************************************
945 Deal with a mutihomed name query success to the machine that
946 requested the multihomed name registration.
948 We have a locked pointer to the original packet stashed away in the
949 userdata pointer.
950 ************************************************************************/
952 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
953 struct userdata_struct *userdata,
954 struct nmb_name *question_name,
955 struct in_addr ip,
956 struct res_rec *answers)
958 struct packet_struct *orig_reg_packet;
959 struct nmb_packet *nmb;
960 struct name_record *namerec = NULL;
961 struct in_addr from_ip;
962 int ttl;
963 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
965 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
967 nmb = &orig_reg_packet->packet.nmb;
969 putip((char *)&from_ip,&nmb->additional->rdata[2]);
970 ttl = get_ttl_from_packet(nmb);
973 * We want to just add the new IP, as we now know the requesting
974 * machine claims to own it. But we can't just do that as an arbitary
975 * amount of time may have taken place between the name query
976 * request and this response. So we check that
977 * the name still exists and is in the same state - if so
978 * we just add the extra IP and update the ttl.
981 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
983 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) )
985 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
986 a subsequent IP addess.\n", nmb_namestr(question_name) ));
987 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
989 orig_reg_packet->locked = False;
990 free_packet(orig_reg_packet);
992 return;
995 if(!find_ip_in_name_record(namerec, from_ip))
996 add_ip_to_name_record(namerec, from_ip);
998 get_global_id_and_update(&namerec->data.id, True);
999 update_wins_owner(namerec, our_fake_ip);
1000 update_wins_flag(namerec, WINS_ACTIVE);
1001 update_name_ttl(namerec, ttl);
1002 send_wins_name_registration_response(0, ttl, orig_reg_packet);
1003 wins_hook("add", namerec, ttl);
1005 orig_reg_packet->locked = False;
1006 free_packet(orig_reg_packet);
1009 /***********************************************************************
1010 Deal with a name registration request query failure to a client that
1011 owned the name.
1013 We have a locked pointer to the original packet stashed away in the
1014 userdata pointer.
1015 ************************************************************************/
1017 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
1018 struct response_record *rrec,
1019 struct nmb_name *question_name,
1020 int rcode)
1022 struct userdata_struct *userdata = rrec->userdata;
1023 struct packet_struct *orig_reg_packet;
1025 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1027 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1028 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
1029 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1031 orig_reg_packet->locked = False;
1032 free_packet(orig_reg_packet);
1033 return;
1036 /***********************************************************************
1037 Deal with a multihomed name registration request to a WINS server.
1038 These cannot be group name registrations.
1039 ***********************************************************************/
1041 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
1042 struct packet_struct *p)
1044 struct nmb_packet *nmb = &p->packet.nmb;
1045 struct nmb_name *question = &nmb->question.question_name;
1046 BOOL bcast = nmb->header.nm_flags.bcast;
1047 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1048 int ttl = get_ttl_from_packet(nmb);
1049 struct name_record *namerec = NULL;
1050 struct in_addr from_ip;
1051 BOOL group = (nb_flags & NB_GROUP) ? True : False;
1052 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1054 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1056 if(bcast)
1059 * We should only get unicast name registration packets here.
1060 * Anyone trying to register broadcast should not be going to a WINS
1061 * server. Log an error here.
1064 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1065 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1066 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1067 return;
1071 * Only unique names should be registered multihomed.
1074 if(group)
1076 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1077 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1078 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1079 return;
1082 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1083 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1086 * Deal with policy regarding 0x1d names.
1089 if(question->name_type == 0x1d)
1091 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1092 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1093 send_wins_name_registration_response(0, ttl, p);
1094 return;
1098 * See if the name already exists.
1101 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1104 * Deal with the case where the name found was a dns entry.
1105 * Remove it as we now have a NetBIOS client registering the
1106 * name.
1109 if( (namerec != NULL)
1110 && ( (namerec->data.source == DNS_NAME)
1111 || (namerec->data.source == DNSFAIL_NAME) ) )
1113 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1114 - removing it.\n", nmb_namestr(question) ));
1115 remove_name_from_namelist( subrec, namerec);
1116 namerec = NULL;
1120 * Reject if the name exists and is not a REGISTER_NAME.
1121 * (ie. Don't allow any static names to be overwritten.
1124 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) )
1126 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1127 to register name %s. Name already exists in WINS with source type %d.\n",
1128 nmb_namestr(question), namerec->data.source ));
1129 send_wins_name_registration_response(RFS_ERR, 0, p);
1130 return;
1134 * Reject if the name exists and is a GROUP name and is active.
1137 if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec))
1139 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1140 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1141 send_wins_name_registration_response(RFS_ERR, 0, p);
1142 return;
1146 * From here on down we know that if the name exists in the WINS db it is
1147 * a unique name, not a group name.
1151 * If the name exists and is one of our names then check the
1152 * registering IP address. If it's not one of ours then automatically
1153 * reject without doing the query - we know we will reject it.
1156 if((namerec != NULL) && (is_myname(namerec->name.name)) )
1158 if(!ismyip(from_ip))
1160 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1161 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1162 send_wins_name_registration_response(RFS_ERR, 0, p);
1163 return;
1165 else
1168 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1169 * update the ttl. Update the version ID to force replication.
1171 if(!find_ip_in_name_record(namerec, from_ip)) {
1172 get_global_id_and_update(&namerec->data.id, True);
1173 update_wins_owner(namerec, our_fake_ip);
1174 update_wins_flag(namerec, WINS_ACTIVE);
1176 add_ip_to_name_record(namerec, from_ip);
1177 wins_hook("add", namerec, ttl);
1178 } else {
1179 wins_hook("refresh", namerec, ttl);
1182 update_name_ttl(namerec, ttl);
1183 send_wins_name_registration_response(0, ttl, p);
1184 return;
1189 * If the name exists and is active, check if the IP address is already registered
1190 * to that name. If so then update the ttl and reply success.
1193 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec))
1195 update_name_ttl(namerec, ttl);
1197 * If it's a replica, we need to become the wins owner
1198 * to force the replication
1200 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1201 get_global_id_and_update(&namerec->data.id, True);
1202 update_wins_owner(namerec, our_fake_ip);
1203 update_wins_flag(namerec, WINS_ACTIVE);
1206 send_wins_name_registration_response(0, ttl, p);
1207 wins_hook("refresh", namerec, ttl);
1208 return;
1212 * If the name exists do a query to the owner
1213 * to see if they still want the name.
1216 if(namerec != NULL)
1218 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1219 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1222 * First send a WACK to the registering machine.
1225 send_wins_wack_response(60, p);
1228 * When the reply comes back we need the original packet.
1229 * Lock this so it won't be freed and then put it into
1230 * the userdata structure.
1233 p->locked = True;
1235 userdata = (struct userdata_struct *)ud;
1237 userdata->copy_fn = NULL;
1238 userdata->free_fn = NULL;
1239 userdata->userdata_len = sizeof(struct packet_struct *);
1240 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1243 * Use the new call to send a query directly to an IP address.
1244 * This sends the query directly to the IP address, and ensures
1245 * the recursion desired flag is not set (you were right Luke :-).
1246 * This function should *only* be called from the WINS server
1247 * code. JRA.
1249 * Note that this packet is sent to the current owner of the name,
1250 * not the person who sent the packet
1253 query_name_from_wins_server( namerec->data.ip[0],
1254 question->name,
1255 question->name_type,
1256 wins_multihomed_register_query_success,
1257 wins_multihomed_register_query_fail,
1258 userdata );
1260 return;
1264 * Name did not exist - add it.
1267 (void)add_name_to_subnet( subrec, question->name, question->name_type,
1268 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1270 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1271 get_global_id_and_update(&namerec->data.id, True);
1272 update_wins_owner(namerec, our_fake_ip);
1273 update_wins_flag(namerec, WINS_ACTIVE);
1274 wins_hook("add", namerec, ttl);
1277 send_wins_name_registration_response(0, ttl, p);
1280 /***********************************************************************
1281 Deal with the special name query for *<1b>.
1282 ***********************************************************************/
1284 static void process_wins_dmb_query_request(struct subnet_record *subrec,
1285 struct packet_struct *p)
1287 struct name_record *namerec = NULL;
1288 char *prdata;
1289 int num_ips;
1292 * Go through all the ACTIVE names in the WINS db looking for those
1293 * ending in <1b>. Use this to calculate the number of IP
1294 * addresses we need to return.
1297 num_ips = 0;
1298 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1299 namerec;
1300 namerec = (struct name_record *)ubi_trNext( namerec ) )
1302 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b )
1303 num_ips += namerec->data.num_ips;
1306 if(num_ips == 0)
1309 * There are no 0x1b names registered. Return name query fail.
1311 send_wins_name_query_response(NAM_ERR, p, NULL);
1312 return;
1315 if((prdata = (char *)malloc( num_ips * 6 )) == NULL)
1317 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1318 return;
1322 * Go through all the names again in the WINS db looking for those
1323 * ending in <1b>. Add their IP addresses into the list we will
1324 * return.
1327 num_ips = 0;
1328 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1329 namerec;
1330 namerec = (struct name_record *)ubi_trNext( namerec ) )
1332 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b)
1334 int i;
1335 for(i = 0; i < namerec->data.num_ips; i++)
1337 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1338 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1339 num_ips++;
1345 * Send back the reply containing the IP list.
1348 reply_netbios_packet(p, /* Packet to reply to. */
1349 0, /* Result code. */
1350 WINS_QUERY, /* nmbd type code. */
1351 NMB_NAME_QUERY_OPCODE, /* opcode. */
1352 lp_min_wins_ttl(), /* ttl. */
1353 prdata, /* data to send. */
1354 num_ips*6); /* data length. */
1356 SAFE_FREE(prdata);
1359 /****************************************************************************
1360 Send a WINS name query response.
1361 **************************************************************************/
1363 void send_wins_name_query_response(int rcode, struct packet_struct *p,
1364 struct name_record *namerec)
1366 char rdata[6];
1367 char *prdata = rdata;
1368 int reply_data_len = 0;
1369 int ttl = 0;
1370 int i;
1372 memset(rdata,'\0',6);
1374 if(rcode == 0)
1376 ttl = (namerec->data.death_time != PERMANENT_TTL) ?
1377 namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1379 /* Copy all known ip addresses into the return data. */
1380 /* Optimise for the common case of one IP address so
1381 we don't need a malloc. */
1383 if( namerec->data.num_ips == 1 )
1384 prdata = rdata;
1385 else
1387 if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL)
1389 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1390 return;
1394 for(i = 0; i < namerec->data.num_ips; i++)
1396 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
1397 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
1400 sort_query_replies(prdata, i, p->ip);
1402 reply_data_len = namerec->data.num_ips * 6;
1405 reply_netbios_packet(p, /* Packet to reply to. */
1406 rcode, /* Result code. */
1407 WINS_QUERY, /* nmbd type code. */
1408 NMB_NAME_QUERY_OPCODE, /* opcode. */
1409 ttl, /* ttl. */
1410 prdata, /* data to send. */
1411 reply_data_len); /* data length. */
1413 if(prdata != rdata)
1414 SAFE_FREE(prdata);
1417 /***********************************************************************
1418 Deal with a name query.
1419 ***********************************************************************/
1421 void wins_process_name_query_request(struct subnet_record *subrec,
1422 struct packet_struct *p)
1424 struct nmb_packet *nmb = &p->packet.nmb;
1425 struct nmb_name *question = &nmb->question.question_name;
1426 struct name_record *namerec = NULL;
1428 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
1429 nmb_namestr(question), inet_ntoa(p->ip) ));
1432 * Special name code. If the queried name is *<1b> then search
1433 * the entire WINS database and return a list of all the IP addresses
1434 * registered to any <1b> name. This is to allow domain master browsers
1435 * to discover other domains that may not have a presence on their subnet.
1438 if(strequal( question->name, "*") && (question->name_type == 0x1b))
1440 process_wins_dmb_query_request( subrec, p);
1441 return;
1444 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1446 if(namerec != NULL)
1449 * If the name is not anymore in active state then reply not found.
1450 * it's fair even if we keep it in the cache for days.
1452 if (!WINS_STATE_ACTIVE(namerec))
1454 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1455 nmb_namestr(question) ));
1456 send_wins_name_query_response(NAM_ERR, p, namerec);
1457 return;
1460 * If it's a DNSFAIL_NAME then reply name not found.
1463 if( namerec->data.source == DNSFAIL_NAME )
1465 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
1466 nmb_namestr(question) ));
1467 send_wins_name_query_response(NAM_ERR, p, namerec);
1468 return;
1472 * If the name has expired then reply name not found.
1475 if( (namerec->data.death_time != PERMANENT_TTL)
1476 && (namerec->data.death_time < p->timestamp) )
1478 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1479 nmb_namestr(question) ));
1480 send_wins_name_query_response(NAM_ERR, p, namerec);
1481 return;
1484 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
1485 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
1487 send_wins_name_query_response(0, p, namerec);
1488 return;
1492 * Name not found in WINS - try a dns query if it's a 0x20 name.
1495 if(lp_dns_proxy() &&
1496 ((question->name_type == 0x20) || question->name_type == 0))
1499 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
1500 nmb_namestr(question) ));
1502 queue_dns_query(p, question, &namerec);
1503 return;
1507 * Name not found - return error.
1510 send_wins_name_query_response(NAM_ERR, p, NULL);
1513 /****************************************************************************
1514 Send a WINS name release response.
1515 **************************************************************************/
1517 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
1519 struct nmb_packet *nmb = &p->packet.nmb;
1520 char rdata[6];
1522 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
1524 reply_netbios_packet(p, /* Packet to reply to. */
1525 rcode, /* Result code. */
1526 NMB_REL, /* nmbd type code. */
1527 NMB_NAME_RELEASE_OPCODE, /* opcode. */
1528 0, /* ttl. */
1529 rdata, /* data to send. */
1530 6); /* data length. */
1533 /***********************************************************************
1534 Deal with a name release.
1535 ***********************************************************************/
1537 void wins_process_name_release_request(struct subnet_record *subrec,
1538 struct packet_struct *p)
1540 struct nmb_packet *nmb = &p->packet.nmb;
1541 struct nmb_name *question = &nmb->question.question_name;
1542 BOOL bcast = nmb->header.nm_flags.bcast;
1543 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1544 struct name_record *namerec = NULL;
1545 struct in_addr from_ip;
1546 BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
1548 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1550 if(bcast)
1553 * We should only get unicast name registration packets here.
1554 * Anyone trying to register broadcast should not be going to a WINS
1555 * server. Log an error here.
1558 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
1559 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1560 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1561 return;
1564 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
1565 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1568 * Deal with policy regarding 0x1d names.
1571 if(!releasing_group_name && (question->name_type == 0x1d))
1573 DEBUG(3,("wins_process_name_release_request: Ignoring request \
1574 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1575 send_wins_name_release_response(0, p);
1576 return;
1580 * See if the name already exists.
1583 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1585 if( (namerec == NULL)
1586 || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) )
1588 send_wins_name_release_response(NAM_ERR, p);
1589 return;
1593 * Check that the sending machine has permission to release this name.
1594 * If it's a group name not ending in 0x1c then just say yes and let
1595 * the group time out.
1598 if(releasing_group_name && (question->name_type != 0x1c))
1600 send_wins_name_release_response(0, p);
1601 return;
1605 * Check that the releasing node is on the list of IP addresses
1606 * for this name. Disallow the release if not.
1609 if(!find_ip_in_name_record(namerec, from_ip))
1611 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1612 release name %s as IP %s is not one of the known IP's for this name.\n",
1613 nmb_namestr(question), inet_ntoa(from_ip) ));
1614 send_wins_name_release_response(NAM_ERR, p);
1615 return;
1619 * Check if the record is active. IF it's already released
1620 * or tombstoned, refuse the release.
1622 if (!WINS_STATE_ACTIVE(namerec)) {
1623 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1624 release name %s as this record is not anymore active.\n",
1625 nmb_namestr(question) ));
1626 send_wins_name_release_response(NAM_ERR, p);
1627 return;
1631 * Send a release response.
1632 * Flag the name as released and update the ttl
1635 send_wins_name_release_response(0, p);
1637 namerec->data.wins_flags |= WINS_RELEASED;
1638 update_name_ttl(namerec, EXTINCTION_INTERVAL);
1640 wins_hook("delete", namerec, 0);
1643 /*******************************************************************
1644 WINS time dependent processing.
1645 ******************************************************************/
1647 void initiate_wins_processing(time_t t)
1649 static time_t lasttime = 0;
1650 struct name_record *namerec;
1651 struct name_record *next_namerec;
1652 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1654 if (!lasttime)
1655 lasttime = t;
1656 if (t - lasttime < 20)
1657 return;
1659 lasttime = t;
1661 if(!lp_we_are_a_wins_server())
1662 return;
1664 for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
1665 namerec;
1666 namerec = next_namerec ) {
1667 next_namerec = (struct name_record *)ubi_trNext( namerec );
1669 if( (namerec->data.death_time != PERMANENT_TTL)
1670 && (namerec->data.death_time < t) ) {
1672 if( namerec->data.source == SELF_NAME ) {
1673 DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF name %s\n",
1674 wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
1675 namerec->data.death_time += 300;
1676 namerec->subnet->namelist_changed = True;
1677 continue;
1680 /* handle records, samba is the wins owner */
1681 if (ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1682 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
1683 case WINS_ACTIVE:
1684 namerec->data.wins_flags&=~WINS_STATE_MASK;
1685 namerec->data.wins_flags|=WINS_RELEASED;
1686 namerec->data.death_time = t + EXTINCTION_INTERVAL;
1687 DEBUG(3,("initiate_wins_processing: expiring %s\n", nmb_namestr(&namerec->name)));
1688 break;
1689 case WINS_RELEASED:
1690 namerec->data.wins_flags&=~WINS_STATE_MASK;
1691 namerec->data.wins_flags|=WINS_TOMBSTONED;
1692 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
1693 get_global_id_and_update(&namerec->data.id, True);
1694 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
1695 break;
1696 case WINS_TOMBSTONED:
1697 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
1698 remove_name_from_namelist( wins_server_subnet, namerec );
1699 break;
1701 } else {
1702 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
1703 case WINS_ACTIVE:
1704 /* that's not as MS says it should be */
1705 namerec->data.wins_flags&=~WINS_STATE_MASK;
1706 namerec->data.wins_flags|=WINS_TOMBSTONED;
1707 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
1708 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
1709 case WINS_TOMBSTONED:
1710 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
1711 remove_name_from_namelist( wins_server_subnet, namerec );
1712 break;
1713 case WINS_RELEASED:
1714 DEBUG(0,("initiate_wins_processing: %s is in released state and\
1715 we are not the wins owner !\n", nmb_namestr(&namerec->name)));
1716 break;
1723 if(wins_server_subnet->namelist_changed)
1724 wins_write_database(True);
1726 wins_server_subnet->namelist_changed = False;
1729 /*******************************************************************
1730 Write out the current WINS database.
1731 ******************************************************************/
1732 void wins_write_database(BOOL background)
1734 struct name_record *namerec;
1735 pstring fname, fnamenew;
1736 TDB_CONTEXT *tdb;
1737 TDB_DATA kbuf, dbuf;
1738 pstring key, buf;
1739 int len;
1740 int num_record=0;
1741 SMB_BIG_UINT id;
1743 if(!lp_we_are_a_wins_server())
1744 return;
1746 /* we will do the writing in a child process to ensure that the parent
1747 doesn't block while this is done */
1748 if (background) {
1749 CatchChild();
1750 if (sys_fork()) {
1751 return;
1755 slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST);
1756 all_string_sub(fname,"//", "/", 0);
1757 slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid());
1759 tdb = tdb_open_log(fnamenew, 0, TDB_DEFAULT, O_RDWR|O_CREAT|O_TRUNC, 0644);
1760 if (!tdb) {
1761 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
1762 if (background)
1763 _exit(0);
1764 return;
1767 DEBUG(3,("wins_write_database: Dump of WINS name list.\n"));
1769 tdb_store_int32(tdb, INFO_VERSION, WINS_VERSION);
1771 for (namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
1772 namerec;
1773 namerec = (struct name_record *)ubi_trNext( namerec ) ) {
1775 int i;
1776 struct tm *tm;
1778 DEBUGADD(3,("%-19s ", nmb_namestr(&namerec->name) ));
1780 if( namerec->data.death_time != PERMANENT_TTL ) {
1781 char *ts, *nl;
1783 tm = LocalTime(&namerec->data.death_time);
1784 ts = asctime(tm);
1785 nl = strrchr_m( ts, '\n' );
1786 if( NULL != nl )
1787 *nl = '\0';
1789 DEBUGADD(3,("TTL = %s ", ts ));
1790 } else
1791 DEBUGADD(3,("TTL = PERMANENT "));
1793 for (i = 0; i < namerec->data.num_ips; i++)
1794 DEBUGADD(0,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
1796 DEBUGADD(3,("0x%2x 0x%2x %15s\n", namerec->data.nb_flags, namerec->data.wins_flags, inet_ntoa(namerec->data.wins_ip)));
1798 if( namerec->data.source == REGISTER_NAME ) {
1800 /* store the type in the key to make the name unique */
1801 slprintf(key, sizeof(key), "%s%s#%02x", ENTRY_PREFIX, namerec->name.name, namerec->name.name_type);
1803 len = tdb_pack(buf, sizeof(buf), "dddfddd",
1804 (int)namerec->data.nb_flags,
1805 (int)(namerec->data.id>>32),
1806 (int)(namerec->data.id&0xffffffff),
1807 inet_ntoa(namerec->data.wins_ip),
1808 (int)namerec->data.death_time,
1809 namerec->data.num_ips,
1810 namerec->data.wins_flags);
1812 for (i = 0; i < namerec->data.num_ips; i++)
1813 len += tdb_pack(buf+len, sizeof(buf)-len, "f", inet_ntoa(namerec->data.ip[i]));
1815 kbuf.dsize = strlen(key)+1;
1816 kbuf.dptr = key;
1817 dbuf.dsize = len;
1818 dbuf.dptr = buf;
1819 if (tdb_store(tdb, kbuf, dbuf, TDB_INSERT) != 0) return;
1821 num_record++;
1825 /* store the number of records */
1826 tdb_store_int32(tdb, INFO_COUNT, num_record);
1828 /* get and store the last used ID */
1829 get_global_id_and_update(&id, False);
1830 tdb_store_int32(tdb, INFO_ID_HIGH, id>>32);
1831 tdb_store_int32(tdb, INFO_ID_LOW, id&0xffffffff);
1833 tdb_close(tdb);
1835 chmod(fnamenew,0644);
1836 unlink(fname);
1837 rename(fnamenew,fname);
1839 if (background)
1840 _exit(0);
1843 /****************************************************************************
1844 process a internal Samba message receiving a wins record
1845 ***************************************************************************/
1846 void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len)
1848 WINS_RECORD *record;
1849 struct name_record *namerec = NULL;
1850 struct name_record *new_namerec = NULL;
1851 struct nmb_name question;
1852 BOOL overwrite=False;
1853 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1854 int i;
1856 if (buf==NULL)
1857 return;
1859 record=(WINS_RECORD *)buf;
1861 ZERO_STRUCT(question);
1862 memcpy(question.name, record->name, 16);
1863 question.name_type=record->type;
1865 namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
1867 /* record doesn't exist, add it */
1868 if (namerec == NULL) {
1869 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
1870 record->name, record->type, inet_ntoa(record->wins_ip)));
1872 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
1873 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
1874 if (new_namerec!=NULL) {
1875 update_wins_owner(new_namerec, record->wins_ip);
1876 update_wins_flag(new_namerec, record->wins_flags);
1877 new_namerec->data.id=record->id;
1879 wins_server_subnet->namelist_changed = True;
1883 /* check if we have a conflict */
1884 if (namerec != NULL) {
1885 /* both records are UNIQUE */
1886 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
1888 /* the database record is a replica */
1889 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1890 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
1891 if (ip_equal(namerec->data.wins_ip, record->wins_ip))
1892 overwrite=True;
1893 } else
1894 overwrite=True;
1895 } else {
1896 /* we are the wins owner of the database record */
1897 /* the 2 records have the same IP address */
1898 if (ip_equal(namerec->data.ip[0], record->ip[0])) {
1899 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
1900 get_global_id_and_update(&namerec->data.id, True);
1901 else
1902 overwrite=True;
1904 } else {
1905 /* the 2 records have different IP address */
1906 if (namerec->data.wins_flags&WINS_ACTIVE) {
1907 if (record->wins_flags&WINS_TOMBSTONED)
1908 get_global_id_and_update(&namerec->data.id, True);
1909 if (record->wins_flags&WINS_ACTIVE)
1910 /* send conflict challenge to the replica node */
1912 } else
1913 overwrite=True;
1919 /* the replica is a standard group */
1920 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {
1921 /* if the database record is unique and active force a name release */
1922 if (namerec->data.wins_flags&WINS_UNIQUE)
1923 /* send a release name to the unique node */
1925 overwrite=True;
1929 /* the replica is a special group */
1930 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
1931 if (namerec->data.wins_flags&WINS_ACTIVE) {
1932 for (i=0; i<record->num_ips; i++)
1933 if(!find_ip_in_name_record(namerec, record->ip[i]))
1934 add_ip_to_name_record(namerec, record->ip[i]);
1936 else
1937 overwrite=True;
1940 /* the replica is a multihomed host */
1942 /* I'm giving up on multi homed. Too much complex to understand */
1944 if (record->wins_flags&WINS_MHOMED) {
1945 if (! namerec->data.wins_flags&WINS_ACTIVE) {
1946 if ( !namerec->data.wins_flags&WINS_RELEASED && !namerec->data.wins_flags&WINS_NGROUP)
1947 overwrite=True;
1949 else {
1950 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
1951 overwrite=True;
1953 if (ip_equal(namerec->data.wins_ip, our_fake_ip))
1954 if (namerec->data.wins_flags&WINS_UNIQUE)
1955 get_global_id_and_update(&namerec->data.id, True);
1959 if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
1960 if (namerec->data.wins_flags&WINS_UNIQUE ||
1961 namerec->data.wins_flags&WINS_MHOMED)
1962 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
1963 overwrite=True;
1967 if (overwrite == False)
1968 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
1969 record->name, record->type, inet_ntoa(record->wins_ip)));
1970 else {
1971 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
1972 record->name, record->type, inet_ntoa(record->wins_ip)));
1974 /* remove the old record and add a new one */
1975 remove_name_from_namelist( wins_server_subnet, namerec );
1976 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
1977 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
1978 if (new_namerec!=NULL) {
1979 update_wins_owner(new_namerec, record->wins_ip);
1980 update_wins_flag(new_namerec, record->wins_flags);
1981 new_namerec->data.id=record->id;
1983 wins_server_subnet->namelist_changed = True;
1986 wins_server_subnet->namelist_changed = True;