skel_ -> cap_
[Samba/gebeck_regimport.git] / source3 / nmbd / nmbd_winsserver.c
blob484588c6626be24364af9a0fcfd3e9f828f71255
1 /*
2 Unix SMB/CIFS implementation.
3 NBT netbios routines and daemon - version 2
5 Copyright (C) Jeremy Allison 1994-2003
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
25 #define WINS_LIST "wins.dat"
26 #define WINS_VERSION 1
28 /****************************************************************************
29 Change the wins owner address in the record.
30 *****************************************************************************/
32 static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip)
34 if (namerec==NULL)
35 return;
36 namerec->data.wins_ip=wins_ip;
39 /****************************************************************************
40 Create the wins flags based on the nb flags and the input value.
41 *****************************************************************************/
43 static void update_wins_flag(struct name_record *namerec, int flags)
45 if (namerec==NULL)
46 return;
48 namerec->data.wins_flags=0x0;
50 /* if it's a group, it can be a normal or a special one */
51 if (namerec->data.nb_flags & NB_GROUP) {
52 if (namerec->name.name_type==0x1C)
53 namerec->data.wins_flags|=WINS_SGROUP;
54 else
55 if (namerec->data.num_ips>1)
56 namerec->data.wins_flags|=WINS_SGROUP;
57 else
58 namerec->data.wins_flags|=WINS_NGROUP;
59 } else {
60 /* can be unique or multi-homed */
61 if (namerec->data.num_ips>1)
62 namerec->data.wins_flags|=WINS_MHOMED;
63 else
64 namerec->data.wins_flags|=WINS_UNIQUE;
67 /* the node type are the same bits */
68 namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK;
70 /* the static bit is elsewhere */
71 if (namerec->data.death_time == PERMANENT_TTL)
72 namerec->data.wins_flags|=WINS_STATIC;
74 /* and add the given bits */
75 namerec->data.wins_flags|=flags;
77 DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n",
78 namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags));
81 /****************************************************************************
82 Return the general ID value and increase it if requested.
83 *****************************************************************************/
85 static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update)
88 * it's kept as a static here, to prevent people from messing
89 * with the value directly
92 static SMB_BIG_UINT general_id = 1;
94 DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id));
96 *current_id = general_id;
98 if (update)
99 general_id++;
102 /****************************************************************************
103 Possibly call the WINS hook external program when a WINS change is made.
104 *****************************************************************************/
106 static void wins_hook(const char *operation, struct name_record *namerec, int ttl)
108 pstring command;
109 char *cmd = lp_wins_hook();
110 char *p;
111 int i;
113 if (!cmd || !*cmd) return;
115 for (p=namerec->name.name; *p; p++) {
116 if (!(isalnum((int)*p) || strchr_m("._-",*p))) {
117 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
118 return;
122 p = command;
123 p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d",
124 cmd,
125 operation,
126 nmb_namestr(&namerec->name),
127 namerec->name.name_type,
128 ttl);
130 for (i=0;i<namerec->data.num_ips;i++) {
131 p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.ip[i]));
134 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
135 smbrun(command, NULL);
139 /****************************************************************************
140 Determine if this packet should be allocated to the WINS server.
141 *****************************************************************************/
143 BOOL packet_is_for_wins_server(struct packet_struct *packet)
145 struct nmb_packet *nmb = &packet->packet.nmb;
147 /* Only unicast packets go to a WINS server. */
148 if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True)) {
149 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
150 return False;
153 /* Check for node status requests. */
154 if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY)
155 return False;
157 switch(nmb->header.opcode) {
159 * A WINS server issues WACKS, not receives them.
161 case NMB_WACK_OPCODE:
162 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
163 return False;
165 * A WINS server only processes registration and
166 * release requests, not responses.
168 case NMB_NAME_REG_OPCODE:
169 case NMB_NAME_MULTIHOMED_REG_OPCODE:
170 case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
171 case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
172 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) {
180 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
181 return False;
183 break;
186 * Only process unicast name queries with rd = 1.
188 case NMB_NAME_QUERY_OPCODE:
189 if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired) {
190 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
191 return False;
193 break;
196 return True;
199 /****************************************************************************
200 Utility function to decide what ttl to give a register/refresh request.
201 *****************************************************************************/
203 static int get_ttl_from_packet(struct nmb_packet *nmb)
205 int ttl = nmb->additional->ttl;
207 if(ttl < lp_min_wins_ttl() )
208 ttl = lp_min_wins_ttl();
210 if(ttl > lp_max_wins_ttl() )
211 ttl = lp_max_wins_ttl();
213 return ttl;
216 /****************************************************************************
217 Load or create the WINS database.
218 *****************************************************************************/
220 BOOL initialise_wins(void)
222 time_t time_now = time(NULL);
223 XFILE *fp;
224 pstring line;
226 if(!lp_we_are_a_wins_server())
227 return True;
229 add_samba_names_to_subnet(wins_server_subnet);
231 if((fp = x_fopen(lock_path(WINS_LIST),O_RDONLY,0)) == NULL) {
232 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
233 WINS_LIST, strerror(errno) ));
234 return True;
237 while (!x_feof(fp)) {
238 pstring name_str, ip_str, ttl_str, nb_flags_str;
239 unsigned int num_ips;
240 pstring name;
241 struct in_addr *ip_list;
242 int type = 0;
243 int nb_flags;
244 int ttl;
245 const char *ptr;
246 char *p;
247 BOOL got_token;
248 BOOL was_ip;
249 int i;
250 unsigned int hash;
251 int version;
253 /* Read a line from the wins.dat file. Strips whitespace
254 from the beginning and end of the line. */
255 if (!fgets_slash(line,sizeof(pstring),fp))
256 continue;
258 if (*line == '#')
259 continue;
261 if (strncmp(line,"VERSION ", 8) == 0) {
262 if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||
263 version != WINS_VERSION) {
264 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line));
265 x_fclose(fp);
266 return True;
268 continue;
271 ptr = line;
274 * Now we handle multiple IP addresses per name we need
275 * to iterate over the line twice. The first time to
276 * determine how many IP addresses there are, the second
277 * time to actually parse them into the ip_list array.
280 if (!next_token(&ptr,name_str,NULL,sizeof(name_str))) {
281 DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));
282 continue;
285 if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str))) {
286 DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));
287 continue;
291 * Determine the number of IP addresses per line.
293 num_ips = 0;
294 do {
295 got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str));
296 was_ip = False;
298 if(got_token && strchr(ip_str, '.')) {
299 num_ips++;
300 was_ip = True;
302 } while( got_token && was_ip);
304 if(num_ips == 0) {
305 DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line ));
306 continue;
309 if(!got_token) {
310 DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line ));
311 continue;
314 /* Allocate the space for the ip_list. */
315 if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL) {
316 DEBUG(0,("initialise_wins: Malloc fail !\n"));
317 return False;
320 /* Reset and re-parse the line. */
321 ptr = line;
322 next_token(&ptr,name_str,NULL,sizeof(name_str));
323 next_token(&ptr,ttl_str,NULL,sizeof(ttl_str));
324 for(i = 0; i < num_ips; i++) {
325 next_token(&ptr, ip_str, NULL, sizeof(ip_str));
326 ip_list[i] = *interpret_addr2(ip_str);
328 next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str));
331 * Deal with SELF or REGISTER name encoding. Default is REGISTER
332 * for compatibility with old nmbds.
335 if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') {
336 DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line));
337 SAFE_FREE(ip_list);
338 continue;
341 if(nb_flags_str[strlen(nb_flags_str)-1] == 'R')
342 nb_flags_str[strlen(nb_flags_str)-1] = '\0';
344 /* Netbios name. # divides the name from the type (hex): netbios#xx */
345 pstrcpy(name,name_str);
347 if((p = strchr(name,'#')) != NULL) {
348 *p = 0;
349 sscanf(p+1,"%x",&type);
352 /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
353 sscanf(nb_flags_str,"%x",&nb_flags);
354 sscanf(ttl_str,"%d",&ttl);
356 /* add all entries that have 60 seconds or more to live */
357 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {
358 if(ttl != PERMANENT_TTL)
359 ttl -= time_now;
361 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
362 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
364 (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
365 ttl, REGISTER_NAME, num_ips, ip_list );
366 } else {
367 DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n",
368 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
371 SAFE_FREE(ip_list);
374 x_fclose(fp);
375 return True;
378 /****************************************************************************
379 Send a WINS WACK (Wait ACKnowledgement) response.
380 **************************************************************************/
382 static void send_wins_wack_response(int ttl, struct packet_struct *p)
384 struct nmb_packet *nmb = &p->packet.nmb;
385 unsigned char rdata[2];
387 rdata[0] = rdata[1] = 0;
389 /* Taken from nmblib.c - we need to send back almost
390 identical bytes from the requesting packet header. */
392 rdata[0] = (nmb->header.opcode & 0xF) << 3;
393 if (nmb->header.nm_flags.authoritative && nmb->header.response)
394 rdata[0] |= 0x4;
395 if (nmb->header.nm_flags.trunc)
396 rdata[0] |= 0x2;
397 if (nmb->header.nm_flags.recursion_desired)
398 rdata[0] |= 0x1;
399 if (nmb->header.nm_flags.recursion_available && nmb->header.response)
400 rdata[1] |= 0x80;
401 if (nmb->header.nm_flags.bcast)
402 rdata[1] |= 0x10;
404 reply_netbios_packet(p, /* Packet to reply to. */
405 0, /* Result code. */
406 NMB_WAIT_ACK, /* nmbd type code. */
407 NMB_WACK_OPCODE, /* opcode. */
408 ttl, /* ttl. */
409 (char *)rdata, /* data to send. */
410 2); /* data length. */
413 /****************************************************************************
414 Send a WINS name registration response.
415 **************************************************************************/
417 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
419 struct nmb_packet *nmb = &p->packet.nmb;
420 char rdata[6];
422 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
424 reply_netbios_packet(p, /* Packet to reply to. */
425 rcode, /* Result code. */
426 WINS_REG, /* nmbd type code. */
427 NMB_NAME_REG_OPCODE, /* opcode. */
428 ttl, /* ttl. */
429 rdata, /* data to send. */
430 6); /* data length. */
433 /***********************************************************************
434 Deal with a name refresh request to a WINS server.
435 ************************************************************************/
437 void wins_process_name_refresh_request(struct subnet_record *subrec,
438 struct packet_struct *p)
440 struct nmb_packet *nmb = &p->packet.nmb;
441 struct nmb_name *question = &nmb->question.question_name;
442 BOOL bcast = nmb->header.nm_flags.bcast;
443 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
444 BOOL group = (nb_flags & NB_GROUP) ? True : False;
445 struct name_record *namerec = NULL;
446 int ttl = get_ttl_from_packet(nmb);
447 struct in_addr from_ip;
448 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
450 putip((char *)&from_ip,&nmb->additional->rdata[2]);
452 if(bcast) {
454 * We should only get unicast name refresh packets here.
455 * Anyone trying to refresh broadcast should not be going to a WINS
456 * server. Log an error here.
459 DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh request \
460 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
461 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
462 return;
465 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \
466 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
469 * See if the name already exists.
472 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
475 * If this is a refresh request and the name doesn't exist then
476 * treat it like a registration request. This allows us to recover
477 * from errors (tridge)
480 if(namerec == NULL) {
481 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \
482 the name does not exist. Treating as registration.\n", nmb_namestr(question) ));
483 wins_process_name_registration_request(subrec,p);
484 return;
488 * if the name is present but not active,
489 * simply remove it and treat the request
490 * as a registration
492 if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) {
493 DEBUG(5,("wins_process_name_refresh_request: Name (%s) in WINS was \
494 not active - removing it.\n", nmb_namestr(question) ));
495 remove_name_from_namelist( subrec, namerec );
496 namerec = NULL;
497 wins_process_name_registration_request(subrec,p);
498 return;
502 * Check that the group bits for the refreshing name and the
503 * name in our database match.
506 if((namerec != NULL) && ((group && !NAME_GROUP(namerec)) || (!group && NAME_GROUP(namerec))) ) {
507 DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \
508 does not match group bit in WINS for this name.\n", nmb_namestr(question), group ? "True" : "False" ));
509 send_wins_name_registration_response(RFS_ERR, 0, p);
510 return;
514 * For a unique name check that the person refreshing the name is one of the registered IP
515 * addresses. If not - fail the refresh. Do the same for group names with a type of 0x1c.
516 * Just return success for unique 0x1d refreshes. For normal group names update the ttl
517 * and return success.
520 if((!group || (group && (question->name_type == 0x1c))) && find_ip_in_name_record(namerec, from_ip )) {
522 * Update the ttl.
524 update_name_ttl(namerec, ttl);
527 * if the record is a replica:
528 * we take ownership and update the version ID.
530 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
531 update_wins_owner(namerec, our_fake_ip);
532 get_global_id_and_update(&namerec->data.id, True);
535 send_wins_name_registration_response(0, ttl, p);
536 wins_hook("refresh", namerec, ttl);
537 return;
538 } else if(group) {
540 * Normal groups are all registered with an IP address of 255.255.255.255
541 * so we can't search for the IP address.
543 update_name_ttl(namerec, ttl);
544 send_wins_name_registration_response(0, ttl, p);
545 return;
546 } else if(!group && (question->name_type == 0x1d)) {
548 * Special name type - just pretend the refresh succeeded.
550 send_wins_name_registration_response(0, ttl, p);
551 return;
552 } else {
554 * Fail the refresh.
557 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \
558 is IP is not known to the name.\n", nmb_namestr(question), inet_ntoa(from_ip) ));
559 send_wins_name_registration_response(RFS_ERR, 0, p);
560 return;
564 /***********************************************************************
565 Deal with a name registration request query success to a client that
566 owned the name.
568 We have a locked pointer to the original packet stashed away in the
569 userdata pointer. The success here is actually a failure as it means
570 the client we queried wants to keep the name, so we must return
571 a registration failure to the original requestor.
572 ************************************************************************/
574 static void wins_register_query_success(struct subnet_record *subrec,
575 struct userdata_struct *userdata,
576 struct nmb_name *question_name,
577 struct in_addr ip,
578 struct res_rec *answers)
580 struct packet_struct *orig_reg_packet;
582 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
584 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
585 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
587 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
589 orig_reg_packet->locked = False;
590 free_packet(orig_reg_packet);
593 /***********************************************************************
594 Deal with a name registration request query failure to a client that
595 owned the name.
597 We have a locked pointer to the original packet stashed away in the
598 userdata pointer. The failure here is actually a success as it means
599 the client we queried didn't want to keep the name, so we can remove
600 the old name record and then successfully add the new name.
601 ************************************************************************/
603 static void wins_register_query_fail(struct subnet_record *subrec,
604 struct response_record *rrec,
605 struct nmb_name *question_name,
606 int rcode)
608 struct userdata_struct *userdata = rrec->userdata;
609 struct packet_struct *orig_reg_packet;
610 struct name_record *namerec = NULL;
612 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
615 * We want to just add the name, as we now know the original owner
616 * didn't want it. But we can't just do that as an arbitary
617 * amount of time may have taken place between the name query
618 * request and this timeout/error response. So we check that
619 * the name still exists and is in the same state - if so
620 * we remove it and call wins_process_name_registration_request()
621 * as we know it will do the right thing now.
624 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
626 if( (namerec != NULL) && (namerec->data.source == REGISTER_NAME) && ip_equal(rrec->packet->ip, *namerec->data.ip) ) {
627 remove_name_from_namelist( subrec, namerec);
628 namerec = NULL;
631 if(namerec == NULL)
632 wins_process_name_registration_request(subrec, orig_reg_packet);
633 else
634 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \
635 querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) ));
637 orig_reg_packet->locked = False;
638 free_packet(orig_reg_packet);
641 /***********************************************************************
642 Deal with a name registration request to a WINS server.
644 Use the following pseudocode :
646 registering_group
649 +--------name exists
652 | +--- existing name is group
653 | | |
654 | | |
655 | | +--- add name (return).
658 | +--- exiting name is unique
661 | +--- query existing owner (return).
664 +--------name doesn't exist
667 +--- add name (return).
669 registering_unique
672 +--------name exists
675 | +--- existing name is group
676 | | |
677 | | |
678 | | +--- fail add (return).
679 | |
681 | +--- exiting name is unique
684 | +--- query existing owner (return).
687 +--------name doesn't exist
690 +--- add name (return).
692 As can be seen from the above, the two cases may be collapsed onto each
693 other with the exception of the case where the name already exists and
694 is a group name. This case we handle with an if statement.
696 ************************************************************************/
698 void wins_process_name_registration_request(struct subnet_record *subrec,
699 struct packet_struct *p)
701 nstring name;
702 struct nmb_packet *nmb = &p->packet.nmb;
703 struct nmb_name *question = &nmb->question.question_name;
704 BOOL bcast = nmb->header.nm_flags.bcast;
705 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
706 int ttl = get_ttl_from_packet(nmb);
707 struct name_record *namerec = NULL;
708 struct in_addr from_ip;
709 BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;
710 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
712 putip((char *)&from_ip,&nmb->additional->rdata[2]);
714 if(bcast) {
716 * We should only get unicast name registration packets here.
717 * Anyone trying to register broadcast should not be going to a WINS
718 * server. Log an error here.
721 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
722 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
723 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
724 return;
727 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
728 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
731 * See if the name already exists.
734 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
737 * if the record exists but NOT in active state,
738 * consider it dead.
740 if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
741 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
742 not active - removing it.\n", nmb_namestr(question) ));
743 remove_name_from_namelist( subrec, namerec );
744 namerec = NULL;
748 * Deal with the case where the name found was a dns entry.
749 * Remove it as we now have a NetBIOS client registering the
750 * name.
753 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
754 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
755 a dns lookup - removing it.\n", nmb_namestr(question) ));
756 remove_name_from_namelist( subrec, namerec );
757 namerec = NULL;
761 * Reject if the name exists and is not a REGISTER_NAME.
762 * (ie. Don't allow any static names to be overwritten.
765 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) {
766 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
767 to register name %s. Name already exists in WINS with source type %d.\n",
768 nmb_namestr(question), namerec->data.source ));
769 send_wins_name_registration_response(RFS_ERR, 0, p);
770 return;
774 * Special policy decisions based on MS documentation.
775 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
776 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
780 * A group name is always added as the local broadcast address, except
781 * for group names ending in 0x1c.
782 * Group names with type 0x1c are registered with individual IP addresses.
785 if(registering_group_name && (question->name_type != 0x1c))
786 from_ip = *interpret_addr2("255.255.255.255");
789 * Ignore all attempts to register a unique 0x1d name, although return success.
792 if(!registering_group_name && (question->name_type == 0x1d)) {
793 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
794 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
795 send_wins_name_registration_response(0, ttl, p);
796 return;
800 * Next two cases are the 'if statement' mentioned above.
803 if((namerec != NULL) && NAME_GROUP(namerec)) {
804 if(registering_group_name) {
806 * If we are adding a group name, the name exists and is also a group entry just add this
807 * IP address to it and update the ttl.
810 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
811 inet_ntoa(from_ip), nmb_namestr(question) ));
814 * Check the ip address is not already in the group.
817 if(!find_ip_in_name_record(namerec, from_ip)) {
818 add_ip_to_name_record(namerec, from_ip);
819 /* we need to update the record for replication */
820 get_global_id_and_update(&namerec->data.id, True);
823 * if the record is a replica, we must change
824 * the wins owner to us to make the replication updates
825 * it on the other wins servers.
826 * And when the partner will receive this record,
827 * it will update its own record.
830 update_wins_owner(namerec, our_fake_ip);
832 update_name_ttl(namerec, ttl);
833 send_wins_name_registration_response(0, ttl, p);
834 return;
835 } else {
838 * If we are adding a unique name, the name exists in the WINS db
839 * and is a group name then reject the registration.
841 * explanation: groups have a higher priority than unique names.
844 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
845 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
846 send_wins_name_registration_response(RFS_ERR, 0, p);
847 return;
852 * From here on down we know that if the name exists in the WINS db it is
853 * a unique name, not a group name.
857 * If the name exists and is one of our names then check the
858 * registering IP address. If it's not one of ours then automatically
859 * reject without doing the query - we know we will reject it.
862 if ( namerec != NULL )
863 pull_ascii_nstring(name, namerec->name.name);
865 if( is_myname(name) ) {
866 if(!ismyip(from_ip)) {
867 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
868 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
869 send_wins_name_registration_response(RFS_ERR, 0, p);
870 return;
871 } else {
873 * It's one of our names and one of our IP's - update the ttl.
875 update_name_ttl(namerec, ttl);
876 send_wins_name_registration_response(0, ttl, p);
877 wins_hook("refresh", namerec, ttl);
878 return;
883 * If the name exists and it is a unique registration and the registering IP
884 * is the same as the (single) already registered IP then just update the ttl.
886 * But not if the record is an active replica. IF it's a replica, it means it can be
887 * the same client which has moved and not yet expired. So we don't update
888 * the ttl in this case and go beyond to do a WACK and query the old client
891 if( !registering_group_name
892 && (namerec != NULL)
893 && (namerec->data.num_ips == 1)
894 && ip_equal( namerec->data.ip[0], from_ip )
895 && ip_equal(namerec->data.wins_ip, our_fake_ip) ) {
896 update_name_ttl( namerec, ttl );
897 send_wins_name_registration_response( 0, ttl, p );
898 wins_hook("refresh", namerec, ttl);
899 return;
903 * Finally if the name exists do a query to the registering machine
904 * to see if they still claim to have the name.
907 if( namerec != NULL ) {
908 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
909 struct userdata_struct *userdata = (struct userdata_struct *)ud;
912 * First send a WACK to the registering machine.
915 send_wins_wack_response(60, p);
918 * When the reply comes back we need the original packet.
919 * Lock this so it won't be freed and then put it into
920 * the userdata structure.
923 p->locked = True;
925 userdata = (struct userdata_struct *)ud;
927 userdata->copy_fn = NULL;
928 userdata->free_fn = NULL;
929 userdata->userdata_len = sizeof(struct packet_struct *);
930 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
933 * Use the new call to send a query directly to an IP address.
934 * This sends the query directly to the IP address, and ensures
935 * the recursion desired flag is not set (you were right Luke :-).
936 * This function should *only* be called from the WINS server
937 * code. JRA.
940 pull_ascii_nstring(name, question->name);
941 query_name_from_wins_server( *namerec->data.ip,
942 name,
943 question->name_type,
944 wins_register_query_success,
945 wins_register_query_fail,
946 userdata );
947 return;
951 * Name did not exist - add it.
954 pull_ascii_nstring(name, question->name);
955 add_name_to_subnet( subrec, name, question->name_type,
956 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
958 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
959 get_global_id_and_update(&namerec->data.id, True);
960 update_wins_owner(namerec, our_fake_ip);
961 update_wins_flag(namerec, WINS_ACTIVE);
962 wins_hook("add", namerec, ttl);
965 send_wins_name_registration_response(0, ttl, p);
968 /***********************************************************************
969 Deal with a mutihomed name query success to the machine that
970 requested the multihomed name registration.
972 We have a locked pointer to the original packet stashed away in the
973 userdata pointer.
974 ************************************************************************/
976 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
977 struct userdata_struct *userdata,
978 struct nmb_name *question_name,
979 struct in_addr ip,
980 struct res_rec *answers)
982 struct packet_struct *orig_reg_packet;
983 struct nmb_packet *nmb;
984 struct name_record *namerec = NULL;
985 struct in_addr from_ip;
986 int ttl;
987 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
989 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
991 nmb = &orig_reg_packet->packet.nmb;
993 putip((char *)&from_ip,&nmb->additional->rdata[2]);
994 ttl = get_ttl_from_packet(nmb);
997 * We want to just add the new IP, as we now know the requesting
998 * machine claims to own it. But we can't just do that as an arbitary
999 * amount of time may have taken place between the name query
1000 * request and this response. So we check that
1001 * the name still exists and is in the same state - if so
1002 * we just add the extra IP and update the ttl.
1005 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1007 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) {
1008 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
1009 a subsequent IP address.\n", nmb_namestr(question_name) ));
1010 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1012 orig_reg_packet->locked = False;
1013 free_packet(orig_reg_packet);
1015 return;
1018 if(!find_ip_in_name_record(namerec, from_ip))
1019 add_ip_to_name_record(namerec, from_ip);
1021 get_global_id_and_update(&namerec->data.id, True);
1022 update_wins_owner(namerec, our_fake_ip);
1023 update_wins_flag(namerec, WINS_ACTIVE);
1024 update_name_ttl(namerec, ttl);
1025 send_wins_name_registration_response(0, ttl, orig_reg_packet);
1026 wins_hook("add", namerec, ttl);
1028 orig_reg_packet->locked = False;
1029 free_packet(orig_reg_packet);
1032 /***********************************************************************
1033 Deal with a name registration request query failure to a client that
1034 owned the name.
1036 We have a locked pointer to the original packet stashed away in the
1037 userdata pointer.
1038 ************************************************************************/
1040 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
1041 struct response_record *rrec,
1042 struct nmb_name *question_name,
1043 int rcode)
1045 struct userdata_struct *userdata = rrec->userdata;
1046 struct packet_struct *orig_reg_packet;
1048 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1050 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1051 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
1052 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1054 orig_reg_packet->locked = False;
1055 free_packet(orig_reg_packet);
1056 return;
1059 /***********************************************************************
1060 Deal with a multihomed name registration request to a WINS server.
1061 These cannot be group name registrations.
1062 ***********************************************************************/
1064 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
1065 struct packet_struct *p)
1067 struct nmb_packet *nmb = &p->packet.nmb;
1068 struct nmb_name *question = &nmb->question.question_name;
1069 BOOL bcast = nmb->header.nm_flags.bcast;
1070 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1071 int ttl = get_ttl_from_packet(nmb);
1072 struct name_record *namerec = NULL;
1073 struct in_addr from_ip;
1074 BOOL group = (nb_flags & NB_GROUP) ? True : False;
1075 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1076 nstring qname;
1078 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1080 if(bcast) {
1082 * We should only get unicast name registration packets here.
1083 * Anyone trying to register broadcast should not be going to a WINS
1084 * server. Log an error here.
1087 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1088 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1089 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1090 return;
1094 * Only unique names should be registered multihomed.
1097 if(group) {
1098 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1099 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1100 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1101 return;
1104 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1105 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1108 * Deal with policy regarding 0x1d names.
1111 if(question->name_type == 0x1d) {
1112 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1113 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1114 send_wins_name_registration_response(0, ttl, p);
1115 return;
1119 * See if the name already exists.
1122 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1125 * if the record exists but NOT in active state,
1126 * consider it dead.
1129 if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1130 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question)));
1131 remove_name_from_namelist(subrec, namerec);
1132 namerec = NULL;
1136 * Deal with the case where the name found was a dns entry.
1137 * Remove it as we now have a NetBIOS client registering the
1138 * name.
1141 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1142 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1143 - removing it.\n", nmb_namestr(question) ));
1144 remove_name_from_namelist( subrec, namerec);
1145 namerec = NULL;
1149 * Reject if the name exists and is not a REGISTER_NAME.
1150 * (ie. Don't allow any static names to be overwritten.
1153 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) {
1154 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1155 to register name %s. Name already exists in WINS with source type %d.\n",
1156 nmb_namestr(question), namerec->data.source ));
1157 send_wins_name_registration_response(RFS_ERR, 0, p);
1158 return;
1162 * Reject if the name exists and is a GROUP name and is active.
1165 if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) {
1166 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1167 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1168 send_wins_name_registration_response(RFS_ERR, 0, p);
1169 return;
1173 * From here on down we know that if the name exists in the WINS db it is
1174 * a unique name, not a group name.
1178 * If the name exists and is one of our names then check the
1179 * registering IP address. If it's not one of ours then automatically
1180 * reject without doing the query - we know we will reject it.
1183 if((namerec != NULL) && (is_myname(namerec->name.name)) ) {
1184 if(!ismyip(from_ip)) {
1185 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1186 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1187 send_wins_name_registration_response(RFS_ERR, 0, p);
1188 return;
1189 } else {
1191 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1192 * update the ttl. Update the version ID to force replication.
1194 if(!find_ip_in_name_record(namerec, from_ip)) {
1195 get_global_id_and_update(&namerec->data.id, True);
1196 update_wins_owner(namerec, our_fake_ip);
1197 update_wins_flag(namerec, WINS_ACTIVE);
1199 add_ip_to_name_record(namerec, from_ip);
1200 wins_hook("add", namerec, ttl);
1201 } else {
1202 wins_hook("refresh", namerec, ttl);
1205 update_name_ttl(namerec, ttl);
1206 send_wins_name_registration_response(0, ttl, p);
1207 return;
1212 * If the name exists and is active, check if the IP address is already registered
1213 * to that name. If so then update the ttl and reply success.
1216 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) {
1217 update_name_ttl(namerec, ttl);
1220 * If it's a replica, we need to become the wins owner
1221 * to force the replication
1223 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1224 get_global_id_and_update(&namerec->data.id, True);
1225 update_wins_owner(namerec, our_fake_ip);
1226 update_wins_flag(namerec, WINS_ACTIVE);
1229 send_wins_name_registration_response(0, ttl, p);
1230 wins_hook("refresh", namerec, ttl);
1231 return;
1235 * If the name exists do a query to the owner
1236 * to see if they still want the name.
1239 if(namerec != NULL) {
1240 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1241 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1244 * First send a WACK to the registering machine.
1247 send_wins_wack_response(60, p);
1250 * When the reply comes back we need the original packet.
1251 * Lock this so it won't be freed and then put it into
1252 * the userdata structure.
1255 p->locked = True;
1257 userdata = (struct userdata_struct *)ud;
1259 userdata->copy_fn = NULL;
1260 userdata->free_fn = NULL;
1261 userdata->userdata_len = sizeof(struct packet_struct *);
1262 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1265 * Use the new call to send a query directly to an IP address.
1266 * This sends the query directly to the IP address, and ensures
1267 * the recursion desired flag is not set (you were right Luke :-).
1268 * This function should *only* be called from the WINS server
1269 * code. JRA.
1271 * Note that this packet is sent to the current owner of the name,
1272 * not the person who sent the packet
1275 pull_ascii_nstring( qname, question->name);
1276 query_name_from_wins_server( namerec->data.ip[0],
1277 qname,
1278 question->name_type,
1279 wins_multihomed_register_query_success,
1280 wins_multihomed_register_query_fail,
1281 userdata );
1283 return;
1287 * Name did not exist - add it.
1290 pull_ascii_nstring( qname, question->name);
1291 add_name_to_subnet( subrec, qname, question->name_type,
1292 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1294 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1295 get_global_id_and_update(&namerec->data.id, True);
1296 update_wins_owner(namerec, our_fake_ip);
1297 update_wins_flag(namerec, WINS_ACTIVE);
1298 wins_hook("add", namerec, ttl);
1301 send_wins_name_registration_response(0, ttl, p);
1304 /***********************************************************************
1305 Deal with the special name query for *<1b>.
1306 ***********************************************************************/
1308 static void process_wins_dmb_query_request(struct subnet_record *subrec,
1309 struct packet_struct *p)
1311 struct name_record *namerec = NULL;
1312 char *prdata;
1313 int num_ips;
1316 * Go through all the ACTIVE names in the WINS db looking for those
1317 * ending in <1b>. Use this to calculate the number of IP
1318 * addresses we need to return.
1321 num_ips = 0;
1322 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1323 namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {
1324 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b )
1325 num_ips += namerec->data.num_ips;
1328 if(num_ips == 0) {
1330 * There are no 0x1b names registered. Return name query fail.
1332 send_wins_name_query_response(NAM_ERR, p, NULL);
1333 return;
1336 if((prdata = (char *)malloc( num_ips * 6 )) == NULL) {
1337 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1338 return;
1342 * Go through all the names again in the WINS db looking for those
1343 * ending in <1b>. Add their IP addresses into the list we will
1344 * return.
1347 num_ips = 0;
1348 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1349 namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {
1350 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1351 int i;
1352 for(i = 0; i < namerec->data.num_ips; i++) {
1353 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1354 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1355 num_ips++;
1361 * Send back the reply containing the IP list.
1364 reply_netbios_packet(p, /* Packet to reply to. */
1365 0, /* Result code. */
1366 WINS_QUERY, /* nmbd type code. */
1367 NMB_NAME_QUERY_OPCODE, /* opcode. */
1368 lp_min_wins_ttl(), /* ttl. */
1369 prdata, /* data to send. */
1370 num_ips*6); /* data length. */
1372 SAFE_FREE(prdata);
1375 /****************************************************************************
1376 Send a WINS name query response.
1377 **************************************************************************/
1379 void send_wins_name_query_response(int rcode, struct packet_struct *p,
1380 struct name_record *namerec)
1382 char rdata[6];
1383 char *prdata = rdata;
1384 int reply_data_len = 0;
1385 int ttl = 0;
1386 int i;
1388 memset(rdata,'\0',6);
1390 if(rcode == 0) {
1391 ttl = (namerec->data.death_time != PERMANENT_TTL) ? namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1393 /* Copy all known ip addresses into the return data. */
1394 /* Optimise for the common case of one IP address so we don't need a malloc. */
1396 if( namerec->data.num_ips == 1 ) {
1397 prdata = rdata;
1398 } else {
1399 if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL) {
1400 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1401 return;
1405 for(i = 0; i < namerec->data.num_ips; i++) {
1406 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
1407 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
1410 sort_query_replies(prdata, i, p->ip);
1411 reply_data_len = namerec->data.num_ips * 6;
1414 reply_netbios_packet(p, /* Packet to reply to. */
1415 rcode, /* Result code. */
1416 WINS_QUERY, /* nmbd type code. */
1417 NMB_NAME_QUERY_OPCODE, /* opcode. */
1418 ttl, /* ttl. */
1419 prdata, /* data to send. */
1420 reply_data_len); /* data length. */
1422 if(prdata != rdata)
1423 SAFE_FREE(prdata);
1426 /***********************************************************************
1427 Deal with a name query.
1428 ***********************************************************************/
1430 void wins_process_name_query_request(struct subnet_record *subrec,
1431 struct packet_struct *p)
1433 struct nmb_packet *nmb = &p->packet.nmb;
1434 struct nmb_name *question = &nmb->question.question_name;
1435 struct name_record *namerec = NULL;
1436 nstring qname;
1438 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
1439 nmb_namestr(question), inet_ntoa(p->ip) ));
1442 * Special name code. If the queried name is *<1b> then search
1443 * the entire WINS database and return a list of all the IP addresses
1444 * registered to any <1b> name. This is to allow domain master browsers
1445 * to discover other domains that may not have a presence on their subnet.
1448 pull_ascii_nstring(qname, question->name);
1449 if(strequal( qname, "*") && (question->name_type == 0x1b)) {
1450 process_wins_dmb_query_request( subrec, p);
1451 return;
1454 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1456 if(namerec != NULL) {
1458 * If the name is not anymore in active state then reply not found.
1459 * it's fair even if we keep it in the cache for days.
1461 if (!WINS_STATE_ACTIVE(namerec)) {
1462 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1463 nmb_namestr(question) ));
1464 send_wins_name_query_response(NAM_ERR, p, namerec);
1465 return;
1469 * If it's a DNSFAIL_NAME then reply name not found.
1472 if( namerec->data.source == DNSFAIL_NAME ) {
1473 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
1474 nmb_namestr(question) ));
1475 send_wins_name_query_response(NAM_ERR, p, namerec);
1476 return;
1480 * If the name has expired then reply name not found.
1483 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < p->timestamp) ) {
1484 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1485 nmb_namestr(question) ));
1486 send_wins_name_query_response(NAM_ERR, p, namerec);
1487 return;
1490 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
1491 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
1493 send_wins_name_query_response(0, p, namerec);
1494 return;
1498 * Name not found in WINS - try a dns query if it's a 0x20 name.
1501 if(lp_dns_proxy() && ((question->name_type == 0x20) || question->name_type == 0)) {
1502 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
1503 nmb_namestr(question) ));
1505 queue_dns_query(p, question, &namerec);
1506 return;
1510 * Name not found - return error.
1513 send_wins_name_query_response(NAM_ERR, p, NULL);
1516 /****************************************************************************
1517 Send a WINS name release response.
1518 **************************************************************************/
1520 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
1522 struct nmb_packet *nmb = &p->packet.nmb;
1523 char rdata[6];
1525 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
1527 reply_netbios_packet(p, /* Packet to reply to. */
1528 rcode, /* Result code. */
1529 NMB_REL, /* nmbd type code. */
1530 NMB_NAME_RELEASE_OPCODE, /* opcode. */
1531 0, /* ttl. */
1532 rdata, /* data to send. */
1533 6); /* data length. */
1536 /***********************************************************************
1537 Deal with a name release.
1538 ***********************************************************************/
1540 void wins_process_name_release_request(struct subnet_record *subrec,
1541 struct packet_struct *p)
1543 struct nmb_packet *nmb = &p->packet.nmb;
1544 struct nmb_name *question = &nmb->question.question_name;
1545 BOOL bcast = nmb->header.nm_flags.bcast;
1546 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1547 struct name_record *namerec = NULL;
1548 struct in_addr from_ip;
1549 BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
1551 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1553 if(bcast) {
1555 * We should only get unicast name registration packets here.
1556 * Anyone trying to register broadcast should not be going to a WINS
1557 * server. Log an error here.
1560 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
1561 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1562 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1563 return;
1566 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
1567 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1570 * Deal with policy regarding 0x1d names.
1573 if(!releasing_group_name && (question->name_type == 0x1d)) {
1574 DEBUG(3,("wins_process_name_release_request: Ignoring request \
1575 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1576 send_wins_name_release_response(0, p);
1577 return;
1581 * See if the name already exists.
1584 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1586 if( (namerec == NULL) || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) {
1587 send_wins_name_release_response(NAM_ERR, p);
1588 return;
1592 * Check that the sending machine has permission to release this name.
1593 * If it's a group name not ending in 0x1c then just say yes and let
1594 * the group time out.
1597 if(releasing_group_name && (question->name_type != 0x1c)) {
1598 send_wins_name_release_response(0, p);
1599 return;
1603 * Check that the releasing node is on the list of IP addresses
1604 * for this name. Disallow the release if not.
1607 if(!find_ip_in_name_record(namerec, from_ip)) {
1608 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1609 release name %s as IP %s is not one of the known IP's for this name.\n",
1610 nmb_namestr(question), inet_ntoa(from_ip) ));
1611 send_wins_name_release_response(NAM_ERR, p);
1612 return;
1616 * Check if the record is active. IF it's already released
1617 * or tombstoned, refuse the release.
1620 if (!WINS_STATE_ACTIVE(namerec)) {
1621 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1622 release name %s as this record is not active anymore.\n", nmb_namestr(question) ));
1623 send_wins_name_release_response(NAM_ERR, p);
1624 return;
1628 * Check if the record is a 0x1c group
1629 * and has more then one ip
1630 * remove only this address.
1633 if(releasing_group_name && (question->name_type == 0x1c) && (namerec->data.num_ips > 1)) {
1634 remove_ip_from_name_record(namerec, from_ip);
1635 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
1636 inet_ntoa(from_ip),nmb_namestr(question)));
1637 send_wins_name_release_response(0, p);
1638 return;
1642 * Send a release response.
1643 * Flag the name as released and update the ttl
1646 send_wins_name_release_response(0, p);
1648 namerec->data.wins_flags |= WINS_RELEASED;
1649 update_name_ttl(namerec, EXTINCTION_INTERVAL);
1651 wins_hook("delete", namerec, 0);
1654 /*******************************************************************
1655 WINS time dependent processing.
1656 ******************************************************************/
1658 void initiate_wins_processing(time_t t)
1660 static time_t lasttime = 0;
1661 struct name_record *namerec;
1662 struct name_record *next_namerec;
1663 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1665 if (!lasttime)
1666 lasttime = t;
1667 if (t - lasttime < 20)
1668 return;
1670 lasttime = t;
1672 if(!lp_we_are_a_wins_server())
1673 return;
1675 for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
1676 namerec;
1677 namerec = next_namerec ) {
1678 next_namerec = (struct name_record *)ubi_trNext( namerec );
1680 if( (namerec->data.death_time != PERMANENT_TTL)
1681 && (namerec->data.death_time < t) ) {
1683 if( namerec->data.source == SELF_NAME ) {
1684 DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF name %s\n",
1685 wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
1686 namerec->data.death_time += 300;
1687 namerec->subnet->namelist_changed = True;
1688 continue;
1691 /* handle records, samba is the wins owner */
1692 if (ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1693 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
1694 case WINS_ACTIVE:
1695 namerec->data.wins_flags&=~WINS_STATE_MASK;
1696 namerec->data.wins_flags|=WINS_RELEASED;
1697 namerec->data.death_time = t + EXTINCTION_INTERVAL;
1698 DEBUG(3,("initiate_wins_processing: expiring %s\n", nmb_namestr(&namerec->name)));
1699 break;
1700 case WINS_RELEASED:
1701 namerec->data.wins_flags&=~WINS_STATE_MASK;
1702 namerec->data.wins_flags|=WINS_TOMBSTONED;
1703 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
1704 get_global_id_and_update(&namerec->data.id, True);
1705 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
1706 break;
1707 case WINS_TOMBSTONED:
1708 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
1709 remove_name_from_namelist( wins_server_subnet, namerec );
1710 break;
1712 } else {
1713 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
1714 case WINS_ACTIVE:
1715 /* that's not as MS says it should be */
1716 namerec->data.wins_flags&=~WINS_STATE_MASK;
1717 namerec->data.wins_flags|=WINS_TOMBSTONED;
1718 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
1719 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
1720 case WINS_TOMBSTONED:
1721 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
1722 remove_name_from_namelist( wins_server_subnet, namerec );
1723 break;
1724 case WINS_RELEASED:
1725 DEBUG(0,("initiate_wins_processing: %s is in released state and\
1726 we are not the wins owner !\n", nmb_namestr(&namerec->name)));
1727 break;
1734 if(wins_server_subnet->namelist_changed)
1735 wins_write_database(True);
1737 wins_server_subnet->namelist_changed = False;
1740 /*******************************************************************
1741 Write out the current WINS database.
1742 ******************************************************************/
1744 void wins_write_database(BOOL background)
1746 struct name_record *namerec;
1747 pstring fname, fnamenew;
1749 XFILE *fp;
1751 if(!lp_we_are_a_wins_server())
1752 return;
1754 /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */
1755 if (background) {
1756 CatchChild();
1757 if (sys_fork()) {
1758 return;
1762 slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST);
1763 all_string_sub(fname,"//", "/", 0);
1764 slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid());
1766 if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) {
1767 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
1768 if (background) {
1769 _exit(0);
1771 return;
1774 DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
1776 x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0);
1778 for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {
1779 int i;
1780 struct tm *tm;
1782 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
1784 if( namerec->data.death_time != PERMANENT_TTL ) {
1785 char *ts, *nl;
1787 tm = LocalTime(&namerec->data.death_time);
1788 ts = asctime(tm);
1789 nl = strrchr( ts, '\n' );
1790 if( NULL != nl )
1791 *nl = '\0';
1792 DEBUGADD(4,("TTL = %s ", ts ));
1793 } else {
1794 DEBUGADD(4,("TTL = PERMANENT "));
1797 for (i = 0; i < namerec->data.num_ips; i++)
1798 DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
1799 DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
1801 if( namerec->data.source == REGISTER_NAME ) {
1802 nstring name;
1803 pull_ascii_nstring(name, namerec->name.name);
1804 x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */
1805 (int)namerec->data.death_time);
1807 for (i = 0; i < namerec->data.num_ips; i++)
1808 x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
1809 x_fprintf( fp, "%2xR\n", namerec->data.nb_flags );
1813 x_fclose(fp);
1814 chmod(fnamenew,0644);
1815 unlink(fname);
1816 rename(fnamenew,fname);
1817 if (background) {
1818 _exit(0);
1822 /****************************************************************************
1823 Process a internal Samba message receiving a wins record.
1824 ***************************************************************************/
1826 void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len)
1828 WINS_RECORD *record;
1829 struct name_record *namerec = NULL;
1830 struct name_record *new_namerec = NULL;
1831 struct nmb_name question;
1832 BOOL overwrite=False;
1833 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1834 int i;
1836 if (buf==NULL)
1837 return;
1839 /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */
1840 record=(WINS_RECORD *)buf;
1842 make_nmb_name(&question, record->name, record->type);
1844 namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
1846 /* record doesn't exist, add it */
1847 if (namerec == NULL) {
1848 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
1849 record->name, record->type, inet_ntoa(record->wins_ip)));
1851 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
1852 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
1853 if (new_namerec!=NULL) {
1854 update_wins_owner(new_namerec, record->wins_ip);
1855 update_wins_flag(new_namerec, record->wins_flags);
1856 new_namerec->data.id=record->id;
1858 wins_server_subnet->namelist_changed = True;
1862 /* check if we have a conflict */
1863 if (namerec != NULL) {
1864 /* both records are UNIQUE */
1865 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
1867 /* the database record is a replica */
1868 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1869 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
1870 if (ip_equal(namerec->data.wins_ip, record->wins_ip))
1871 overwrite=True;
1872 } else
1873 overwrite=True;
1874 } else {
1875 /* we are the wins owner of the database record */
1876 /* the 2 records have the same IP address */
1877 if (ip_equal(namerec->data.ip[0], record->ip[0])) {
1878 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
1879 get_global_id_and_update(&namerec->data.id, True);
1880 else
1881 overwrite=True;
1883 } else {
1884 /* the 2 records have different IP address */
1885 if (namerec->data.wins_flags&WINS_ACTIVE) {
1886 if (record->wins_flags&WINS_TOMBSTONED)
1887 get_global_id_and_update(&namerec->data.id, True);
1888 if (record->wins_flags&WINS_ACTIVE)
1889 /* send conflict challenge to the replica node */
1891 } else
1892 overwrite=True;
1898 /* the replica is a standard group */
1899 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {
1900 /* if the database record is unique and active force a name release */
1901 if (namerec->data.wins_flags&WINS_UNIQUE)
1902 /* send a release name to the unique node */
1904 overwrite=True;
1908 /* the replica is a special group */
1909 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
1910 if (namerec->data.wins_flags&WINS_ACTIVE) {
1911 for (i=0; i<record->num_ips; i++)
1912 if(!find_ip_in_name_record(namerec, record->ip[i]))
1913 add_ip_to_name_record(namerec, record->ip[i]);
1914 } else {
1915 overwrite=True;
1919 /* the replica is a multihomed host */
1921 /* I'm giving up on multi homed. Too much complex to understand */
1923 if (record->wins_flags&WINS_MHOMED) {
1924 if (! (namerec->data.wins_flags&WINS_ACTIVE)) {
1925 if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP))
1926 overwrite=True;
1928 else {
1929 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
1930 overwrite=True;
1932 if (ip_equal(namerec->data.wins_ip, our_fake_ip))
1933 if (namerec->data.wins_flags&WINS_UNIQUE)
1934 get_global_id_and_update(&namerec->data.id, True);
1938 if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
1939 if (namerec->data.wins_flags&WINS_UNIQUE ||
1940 namerec->data.wins_flags&WINS_MHOMED)
1941 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
1942 overwrite=True;
1946 if (overwrite == False)
1947 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
1948 record->name, record->type, inet_ntoa(record->wins_ip)));
1949 else {
1950 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
1951 record->name, record->type, inet_ntoa(record->wins_ip)));
1953 /* remove the old record and add a new one */
1954 remove_name_from_namelist( wins_server_subnet, namerec );
1955 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
1956 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
1957 if (new_namerec!=NULL) {
1958 update_wins_owner(new_namerec, record->wins_ip);
1959 update_wins_flag(new_namerec, record->wins_flags);
1960 new_namerec->data.id=record->id;
1962 wins_server_subnet->namelist_changed = True;
1965 wins_server_subnet->namelist_changed = True;