Fix for possible crash bug from Sebastian Krahmer (SuSE).
[Samba/gebeck_regimport.git] / source3 / nmbd / nmbd_winsserver.c
blob369407242071c7b14f3c3ab1a12029b5cc8d6823
1 /*
2 Unix SMB/CIFS implementation.
3 NBT netbios routines and daemon - version 2
5 Copyright (C) Jeremy Allison 1994-2003
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
25 #define WINS_LIST "wins.dat"
26 #define WINS_VERSION 1
28 /****************************************************************************
29 Change the wins owner address in the record.
30 *****************************************************************************/
32 static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip)
34 if (namerec==NULL)
35 return;
36 namerec->data.wins_ip=wins_ip;
39 /****************************************************************************
40 Create the wins flags based on the nb flags and the input value.
41 *****************************************************************************/
43 static void update_wins_flag(struct name_record *namerec, int flags)
45 if (namerec==NULL)
46 return;
48 namerec->data.wins_flags=0x0;
50 /* if it's a group, it can be a normal or a special one */
51 if (namerec->data.nb_flags & NB_GROUP) {
52 if (namerec->name.name_type==0x1C)
53 namerec->data.wins_flags|=WINS_SGROUP;
54 else
55 if (namerec->data.num_ips>1)
56 namerec->data.wins_flags|=WINS_SGROUP;
57 else
58 namerec->data.wins_flags|=WINS_NGROUP;
59 } else {
60 /* can be unique or multi-homed */
61 if (namerec->data.num_ips>1)
62 namerec->data.wins_flags|=WINS_MHOMED;
63 else
64 namerec->data.wins_flags|=WINS_UNIQUE;
67 /* the node type are the same bits */
68 namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK;
70 /* the static bit is elsewhere */
71 if (namerec->data.death_time == PERMANENT_TTL)
72 namerec->data.wins_flags|=WINS_STATIC;
74 /* and add the given bits */
75 namerec->data.wins_flags|=flags;
77 DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n",
78 namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags));
81 /****************************************************************************
82 Return the general ID value and increase it if requested.
83 *****************************************************************************/
85 static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update)
88 * it's kept as a static here, to prevent people from messing
89 * with the value directly
92 static SMB_BIG_UINT general_id = 1;
94 DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id));
96 *current_id = general_id;
98 if (update)
99 general_id++;
102 /****************************************************************************
103 Possibly call the WINS hook external program when a WINS change is made.
104 *****************************************************************************/
106 static void wins_hook(const char *operation, struct name_record *namerec, int ttl)
108 pstring command;
109 char *cmd = lp_wins_hook();
110 char *p, *namestr;
111 int i;
113 if (!cmd || !*cmd) return;
115 for (p=namerec->name.name; *p; p++) {
116 if (!(isalnum((int)*p) || strchr_m("._-",*p))) {
117 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
118 return;
122 /* Use the name without the nametype (and scope) appended */
124 namestr = nmb_namestr(&namerec->name);
125 if ((p = strchr(namestr, '<')))
126 *p = 0;
128 p = command;
129 p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d",
130 cmd,
131 operation,
132 namestr,
133 namerec->name.name_type,
134 ttl);
136 for (i=0;i<namerec->data.num_ips;i++) {
137 p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.ip[i]));
140 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
141 smbrun(command, NULL);
145 /****************************************************************************
146 Determine if this packet should be allocated to the WINS server.
147 *****************************************************************************/
149 BOOL packet_is_for_wins_server(struct packet_struct *packet)
151 struct nmb_packet *nmb = &packet->packet.nmb;
153 /* Only unicast packets go to a WINS server. */
154 if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True)) {
155 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
156 return False;
159 /* Check for node status requests. */
160 if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY)
161 return False;
163 switch(nmb->header.opcode) {
165 * A WINS server issues WACKS, not receives them.
167 case NMB_WACK_OPCODE:
168 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
169 return False;
171 * A WINS server only processes registration and
172 * release requests, not responses.
174 case NMB_NAME_REG_OPCODE:
175 case NMB_NAME_MULTIHOMED_REG_OPCODE:
176 case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
177 case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
178 if(nmb->header.response) {
179 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
180 return False;
182 break;
184 case NMB_NAME_RELEASE_OPCODE:
185 if(nmb->header.response) {
186 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
187 return False;
189 break;
192 * Only process unicast name queries with rd = 1.
194 case NMB_NAME_QUERY_OPCODE:
195 if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired) {
196 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
197 return False;
199 break;
202 return True;
205 /****************************************************************************
206 Utility function to decide what ttl to give a register/refresh request.
207 *****************************************************************************/
209 static int get_ttl_from_packet(struct nmb_packet *nmb)
211 int ttl = nmb->additional->ttl;
213 if(ttl < lp_min_wins_ttl() )
214 ttl = lp_min_wins_ttl();
216 if(ttl > lp_max_wins_ttl() )
217 ttl = lp_max_wins_ttl();
219 return ttl;
222 /****************************************************************************
223 Load or create the WINS database.
224 *****************************************************************************/
226 BOOL initialise_wins(void)
228 time_t time_now = time(NULL);
229 XFILE *fp;
230 pstring line;
232 if(!lp_we_are_a_wins_server())
233 return True;
235 add_samba_names_to_subnet(wins_server_subnet);
237 if((fp = x_fopen(lock_path(WINS_LIST),O_RDONLY,0)) == NULL) {
238 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
239 WINS_LIST, strerror(errno) ));
240 return True;
243 while (!x_feof(fp)) {
244 pstring name_str, ip_str, ttl_str, nb_flags_str;
245 unsigned int num_ips;
246 pstring name;
247 struct in_addr *ip_list;
248 int type = 0;
249 int nb_flags;
250 int ttl;
251 const char *ptr;
252 char *p;
253 BOOL got_token;
254 BOOL was_ip;
255 int i;
256 unsigned int hash;
257 int version;
259 /* Read a line from the wins.dat file. Strips whitespace
260 from the beginning and end of the line. */
261 if (!fgets_slash(line,sizeof(pstring),fp))
262 continue;
264 if (*line == '#')
265 continue;
267 if (strncmp(line,"VERSION ", 8) == 0) {
268 if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||
269 version != WINS_VERSION) {
270 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line));
271 x_fclose(fp);
272 return True;
274 continue;
277 ptr = line;
280 * Now we handle multiple IP addresses per name we need
281 * to iterate over the line twice. The first time to
282 * determine how many IP addresses there are, the second
283 * time to actually parse them into the ip_list array.
286 if (!next_token(&ptr,name_str,NULL,sizeof(name_str))) {
287 DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));
288 continue;
291 if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str))) {
292 DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));
293 continue;
297 * Determine the number of IP addresses per line.
299 num_ips = 0;
300 do {
301 got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str));
302 was_ip = False;
304 if(got_token && strchr(ip_str, '.')) {
305 num_ips++;
306 was_ip = True;
308 } while( got_token && was_ip);
310 if(num_ips == 0) {
311 DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line ));
312 continue;
315 if(!got_token) {
316 DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line ));
317 continue;
320 /* Allocate the space for the ip_list. */
321 if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL) {
322 DEBUG(0,("initialise_wins: Malloc fail !\n"));
323 return False;
326 /* Reset and re-parse the line. */
327 ptr = line;
328 next_token(&ptr,name_str,NULL,sizeof(name_str));
329 next_token(&ptr,ttl_str,NULL,sizeof(ttl_str));
330 for(i = 0; i < num_ips; i++) {
331 next_token(&ptr, ip_str, NULL, sizeof(ip_str));
332 ip_list[i] = *interpret_addr2(ip_str);
334 next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str));
337 * Deal with SELF or REGISTER name encoding. Default is REGISTER
338 * for compatibility with old nmbds.
341 if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') {
342 DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line));
343 SAFE_FREE(ip_list);
344 continue;
347 if(nb_flags_str[strlen(nb_flags_str)-1] == 'R')
348 nb_flags_str[strlen(nb_flags_str)-1] = '\0';
350 /* Netbios name. # divides the name from the type (hex): netbios#xx */
351 pstrcpy(name,name_str);
353 if((p = strchr(name,'#')) != NULL) {
354 *p = 0;
355 sscanf(p+1,"%x",&type);
358 /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
359 sscanf(nb_flags_str,"%x",&nb_flags);
360 sscanf(ttl_str,"%d",&ttl);
362 /* add all entries that have 60 seconds or more to live */
363 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {
364 if(ttl != PERMANENT_TTL)
365 ttl -= time_now;
367 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
368 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
370 (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
371 ttl, REGISTER_NAME, num_ips, ip_list );
372 } else {
373 DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n",
374 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
377 SAFE_FREE(ip_list);
380 x_fclose(fp);
381 return True;
384 /****************************************************************************
385 Send a WINS WACK (Wait ACKnowledgement) response.
386 **************************************************************************/
388 static void send_wins_wack_response(int ttl, struct packet_struct *p)
390 struct nmb_packet *nmb = &p->packet.nmb;
391 unsigned char rdata[2];
393 rdata[0] = rdata[1] = 0;
395 /* Taken from nmblib.c - we need to send back almost
396 identical bytes from the requesting packet header. */
398 rdata[0] = (nmb->header.opcode & 0xF) << 3;
399 if (nmb->header.nm_flags.authoritative && nmb->header.response)
400 rdata[0] |= 0x4;
401 if (nmb->header.nm_flags.trunc)
402 rdata[0] |= 0x2;
403 if (nmb->header.nm_flags.recursion_desired)
404 rdata[0] |= 0x1;
405 if (nmb->header.nm_flags.recursion_available && nmb->header.response)
406 rdata[1] |= 0x80;
407 if (nmb->header.nm_flags.bcast)
408 rdata[1] |= 0x10;
410 reply_netbios_packet(p, /* Packet to reply to. */
411 0, /* Result code. */
412 NMB_WAIT_ACK, /* nmbd type code. */
413 NMB_WACK_OPCODE, /* opcode. */
414 ttl, /* ttl. */
415 (char *)rdata, /* data to send. */
416 2); /* data length. */
419 /****************************************************************************
420 Send a WINS name registration response.
421 **************************************************************************/
423 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
425 struct nmb_packet *nmb = &p->packet.nmb;
426 char rdata[6];
428 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
430 reply_netbios_packet(p, /* Packet to reply to. */
431 rcode, /* Result code. */
432 WINS_REG, /* nmbd type code. */
433 NMB_NAME_REG_OPCODE, /* opcode. */
434 ttl, /* ttl. */
435 rdata, /* data to send. */
436 6); /* data length. */
439 /***********************************************************************
440 Deal with a name refresh request to a WINS server.
441 ************************************************************************/
443 void wins_process_name_refresh_request(struct subnet_record *subrec,
444 struct packet_struct *p)
446 struct nmb_packet *nmb = &p->packet.nmb;
447 struct nmb_name *question = &nmb->question.question_name;
448 BOOL bcast = nmb->header.nm_flags.bcast;
449 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
450 BOOL group = (nb_flags & NB_GROUP) ? True : False;
451 struct name_record *namerec = NULL;
452 int ttl = get_ttl_from_packet(nmb);
453 struct in_addr from_ip;
454 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
456 putip((char *)&from_ip,&nmb->additional->rdata[2]);
458 if(bcast) {
460 * We should only get unicast name refresh packets here.
461 * Anyone trying to refresh broadcast should not be going to a WINS
462 * server. Log an error here.
465 DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh request \
466 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
467 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
468 return;
471 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \
472 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
475 * See if the name already exists.
478 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
481 * If this is a refresh request and the name doesn't exist then
482 * treat it like a registration request. This allows us to recover
483 * from errors (tridge)
486 if(namerec == NULL) {
487 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \
488 the name does not exist. Treating as registration.\n", nmb_namestr(question) ));
489 wins_process_name_registration_request(subrec,p);
490 return;
494 * if the name is present but not active,
495 * simply remove it and treat the request
496 * as a registration
498 if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) {
499 DEBUG(5,("wins_process_name_refresh_request: Name (%s) in WINS was \
500 not active - removing it.\n", nmb_namestr(question) ));
501 remove_name_from_namelist( subrec, namerec );
502 namerec = NULL;
503 wins_process_name_registration_request(subrec,p);
504 return;
508 * Check that the group bits for the refreshing name and the
509 * name in our database match.
512 if((namerec != NULL) && ((group && !NAME_GROUP(namerec)) || (!group && NAME_GROUP(namerec))) ) {
513 DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \
514 does not match group bit in WINS for this name.\n", nmb_namestr(question), group ? "True" : "False" ));
515 send_wins_name_registration_response(RFS_ERR, 0, p);
516 return;
520 * For a unique name check that the person refreshing the name is one of the registered IP
521 * addresses. If not - fail the refresh. Do the same for group names with a type of 0x1c.
522 * Just return success for unique 0x1d refreshes. For normal group names update the ttl
523 * and return success.
526 if((!group || (group && (question->name_type == 0x1c))) && find_ip_in_name_record(namerec, from_ip )) {
528 * Update the ttl.
530 update_name_ttl(namerec, ttl);
533 * if the record is a replica:
534 * we take ownership and update the version ID.
536 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
537 update_wins_owner(namerec, our_fake_ip);
538 get_global_id_and_update(&namerec->data.id, True);
541 send_wins_name_registration_response(0, ttl, p);
542 wins_hook("refresh", namerec, ttl);
543 return;
544 } else if(group) {
546 * Normal groups are all registered with an IP address of 255.255.255.255
547 * so we can't search for the IP address.
549 update_name_ttl(namerec, ttl);
550 send_wins_name_registration_response(0, ttl, p);
551 return;
552 } else if(!group && (question->name_type == 0x1d)) {
554 * Special name type - just pretend the refresh succeeded.
556 send_wins_name_registration_response(0, ttl, p);
557 return;
558 } else {
560 * Fail the refresh.
563 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \
564 is IP is not known to the name.\n", nmb_namestr(question), inet_ntoa(from_ip) ));
565 send_wins_name_registration_response(RFS_ERR, 0, p);
566 return;
570 /***********************************************************************
571 Deal with a name registration request query success to a client that
572 owned the name.
574 We have a locked pointer to the original packet stashed away in the
575 userdata pointer. The success here is actually a failure as it means
576 the client we queried wants to keep the name, so we must return
577 a registration failure to the original requestor.
578 ************************************************************************/
580 static void wins_register_query_success(struct subnet_record *subrec,
581 struct userdata_struct *userdata,
582 struct nmb_name *question_name,
583 struct in_addr ip,
584 struct res_rec *answers)
586 struct packet_struct *orig_reg_packet;
588 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
590 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
591 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
593 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
595 orig_reg_packet->locked = False;
596 free_packet(orig_reg_packet);
599 /***********************************************************************
600 Deal with a name registration request query failure to a client that
601 owned the name.
603 We have a locked pointer to the original packet stashed away in the
604 userdata pointer. The failure here is actually a success as it means
605 the client we queried didn't want to keep the name, so we can remove
606 the old name record and then successfully add the new name.
607 ************************************************************************/
609 static void wins_register_query_fail(struct subnet_record *subrec,
610 struct response_record *rrec,
611 struct nmb_name *question_name,
612 int rcode)
614 struct userdata_struct *userdata = rrec->userdata;
615 struct packet_struct *orig_reg_packet;
616 struct name_record *namerec = NULL;
618 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
621 * We want to just add the name, as we now know the original owner
622 * didn't want it. But we can't just do that as an arbitary
623 * amount of time may have taken place between the name query
624 * request and this timeout/error response. So we check that
625 * the name still exists and is in the same state - if so
626 * we remove it and call wins_process_name_registration_request()
627 * as we know it will do the right thing now.
630 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
632 if( (namerec != NULL) && (namerec->data.source == REGISTER_NAME) && ip_equal(rrec->packet->ip, *namerec->data.ip) ) {
633 remove_name_from_namelist( subrec, namerec);
634 namerec = NULL;
637 if(namerec == NULL)
638 wins_process_name_registration_request(subrec, orig_reg_packet);
639 else
640 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \
641 querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) ));
643 orig_reg_packet->locked = False;
644 free_packet(orig_reg_packet);
647 /***********************************************************************
648 Deal with a name registration request to a WINS server.
650 Use the following pseudocode :
652 registering_group
655 +--------name exists
658 | +--- existing name is group
659 | | |
660 | | |
661 | | +--- add name (return).
664 | +--- exiting name is unique
667 | +--- query existing owner (return).
670 +--------name doesn't exist
673 +--- add name (return).
675 registering_unique
678 +--------name exists
681 | +--- existing name is group
682 | | |
683 | | |
684 | | +--- fail add (return).
685 | |
687 | +--- exiting name is unique
690 | +--- query existing owner (return).
693 +--------name doesn't exist
696 +--- add name (return).
698 As can be seen from the above, the two cases may be collapsed onto each
699 other with the exception of the case where the name already exists and
700 is a group name. This case we handle with an if statement.
702 ************************************************************************/
704 void wins_process_name_registration_request(struct subnet_record *subrec,
705 struct packet_struct *p)
707 nstring name;
708 struct nmb_packet *nmb = &p->packet.nmb;
709 struct nmb_name *question = &nmb->question.question_name;
710 BOOL bcast = nmb->header.nm_flags.bcast;
711 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
712 int ttl = get_ttl_from_packet(nmb);
713 struct name_record *namerec = NULL;
714 struct in_addr from_ip;
715 BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;
716 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
718 putip((char *)&from_ip,&nmb->additional->rdata[2]);
720 if(bcast) {
722 * We should only get unicast name registration packets here.
723 * Anyone trying to register broadcast should not be going to a WINS
724 * server. Log an error here.
727 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
728 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
729 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
730 return;
733 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
734 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
737 * See if the name already exists.
740 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
743 * if the record exists but NOT in active state,
744 * consider it dead.
746 if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
747 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
748 not active - removing it.\n", nmb_namestr(question) ));
749 remove_name_from_namelist( subrec, namerec );
750 namerec = NULL;
754 * Deal with the case where the name found was a dns entry.
755 * Remove it as we now have a NetBIOS client registering the
756 * name.
759 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
760 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
761 a dns lookup - removing it.\n", nmb_namestr(question) ));
762 remove_name_from_namelist( subrec, namerec );
763 namerec = NULL;
767 * Reject if the name exists and is not a REGISTER_NAME.
768 * (ie. Don't allow any static names to be overwritten.
771 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) {
772 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
773 to register name %s. Name already exists in WINS with source type %d.\n",
774 nmb_namestr(question), namerec->data.source ));
775 send_wins_name_registration_response(RFS_ERR, 0, p);
776 return;
780 * Special policy decisions based on MS documentation.
781 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
782 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
786 * A group name is always added as the local broadcast address, except
787 * for group names ending in 0x1c.
788 * Group names with type 0x1c are registered with individual IP addresses.
791 if(registering_group_name && (question->name_type != 0x1c))
792 from_ip = *interpret_addr2("255.255.255.255");
795 * Ignore all attempts to register a unique 0x1d name, although return success.
798 if(!registering_group_name && (question->name_type == 0x1d)) {
799 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
800 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
801 send_wins_name_registration_response(0, ttl, p);
802 return;
806 * Next two cases are the 'if statement' mentioned above.
809 if((namerec != NULL) && NAME_GROUP(namerec)) {
810 if(registering_group_name) {
812 * If we are adding a group name, the name exists and is also a group entry just add this
813 * IP address to it and update the ttl.
816 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
817 inet_ntoa(from_ip), nmb_namestr(question) ));
820 * Check the ip address is not already in the group.
823 if(!find_ip_in_name_record(namerec, from_ip)) {
824 add_ip_to_name_record(namerec, from_ip);
825 /* we need to update the record for replication */
826 get_global_id_and_update(&namerec->data.id, True);
829 * if the record is a replica, we must change
830 * the wins owner to us to make the replication updates
831 * it on the other wins servers.
832 * And when the partner will receive this record,
833 * it will update its own record.
836 update_wins_owner(namerec, our_fake_ip);
838 update_name_ttl(namerec, ttl);
839 send_wins_name_registration_response(0, ttl, p);
840 return;
841 } else {
844 * If we are adding a unique name, the name exists in the WINS db
845 * and is a group name then reject the registration.
847 * explanation: groups have a higher priority than unique names.
850 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
851 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
852 send_wins_name_registration_response(RFS_ERR, 0, p);
853 return;
858 * From here on down we know that if the name exists in the WINS db it is
859 * a unique name, not a group name.
863 * If the name exists and is one of our names then check the
864 * registering IP address. If it's not one of ours then automatically
865 * reject without doing the query - we know we will reject it.
868 if ( namerec != NULL )
869 pull_ascii_nstring(name, namerec->name.name);
871 if( is_myname(name) ) {
872 if(!ismyip(from_ip)) {
873 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
874 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
875 send_wins_name_registration_response(RFS_ERR, 0, p);
876 return;
877 } else {
879 * It's one of our names and one of our IP's - update the ttl.
881 update_name_ttl(namerec, ttl);
882 send_wins_name_registration_response(0, ttl, p);
883 wins_hook("refresh", namerec, ttl);
884 return;
889 * If the name exists and it is a unique registration and the registering IP
890 * is the same as the (single) already registered IP then just update the ttl.
892 * But not if the record is an active replica. IF it's a replica, it means it can be
893 * the same client which has moved and not yet expired. So we don't update
894 * the ttl in this case and go beyond to do a WACK and query the old client
897 if( !registering_group_name
898 && (namerec != NULL)
899 && (namerec->data.num_ips == 1)
900 && ip_equal( namerec->data.ip[0], from_ip )
901 && ip_equal(namerec->data.wins_ip, our_fake_ip) ) {
902 update_name_ttl( namerec, ttl );
903 send_wins_name_registration_response( 0, ttl, p );
904 wins_hook("refresh", namerec, ttl);
905 return;
909 * Finally if the name exists do a query to the registering machine
910 * to see if they still claim to have the name.
913 if( namerec != NULL ) {
914 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
915 struct userdata_struct *userdata = (struct userdata_struct *)ud;
918 * First send a WACK to the registering machine.
921 send_wins_wack_response(60, p);
924 * When the reply comes back we need the original packet.
925 * Lock this so it won't be freed and then put it into
926 * the userdata structure.
929 p->locked = True;
931 userdata = (struct userdata_struct *)ud;
933 userdata->copy_fn = NULL;
934 userdata->free_fn = NULL;
935 userdata->userdata_len = sizeof(struct packet_struct *);
936 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
939 * Use the new call to send a query directly to an IP address.
940 * This sends the query directly to the IP address, and ensures
941 * the recursion desired flag is not set (you were right Luke :-).
942 * This function should *only* be called from the WINS server
943 * code. JRA.
946 pull_ascii_nstring(name, question->name);
947 query_name_from_wins_server( *namerec->data.ip,
948 name,
949 question->name_type,
950 wins_register_query_success,
951 wins_register_query_fail,
952 userdata );
953 return;
957 * Name did not exist - add it.
960 pull_ascii_nstring(name, question->name);
961 add_name_to_subnet( subrec, name, question->name_type,
962 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
964 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
965 get_global_id_and_update(&namerec->data.id, True);
966 update_wins_owner(namerec, our_fake_ip);
967 update_wins_flag(namerec, WINS_ACTIVE);
968 wins_hook("add", namerec, ttl);
971 send_wins_name_registration_response(0, ttl, p);
974 /***********************************************************************
975 Deal with a mutihomed name query success to the machine that
976 requested the multihomed name registration.
978 We have a locked pointer to the original packet stashed away in the
979 userdata pointer.
980 ************************************************************************/
982 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
983 struct userdata_struct *userdata,
984 struct nmb_name *question_name,
985 struct in_addr ip,
986 struct res_rec *answers)
988 struct packet_struct *orig_reg_packet;
989 struct nmb_packet *nmb;
990 struct name_record *namerec = NULL;
991 struct in_addr from_ip;
992 int ttl;
993 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
995 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
997 nmb = &orig_reg_packet->packet.nmb;
999 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1000 ttl = get_ttl_from_packet(nmb);
1003 * We want to just add the new IP, as we now know the requesting
1004 * machine claims to own it. But we can't just do that as an arbitary
1005 * amount of time may have taken place between the name query
1006 * request and this response. So we check that
1007 * the name still exists and is in the same state - if so
1008 * we just add the extra IP and update the ttl.
1011 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1013 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) {
1014 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
1015 a subsequent IP address.\n", nmb_namestr(question_name) ));
1016 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1018 orig_reg_packet->locked = False;
1019 free_packet(orig_reg_packet);
1021 return;
1024 if(!find_ip_in_name_record(namerec, from_ip))
1025 add_ip_to_name_record(namerec, from_ip);
1027 get_global_id_and_update(&namerec->data.id, True);
1028 update_wins_owner(namerec, our_fake_ip);
1029 update_wins_flag(namerec, WINS_ACTIVE);
1030 update_name_ttl(namerec, ttl);
1031 send_wins_name_registration_response(0, ttl, orig_reg_packet);
1032 wins_hook("add", namerec, ttl);
1034 orig_reg_packet->locked = False;
1035 free_packet(orig_reg_packet);
1038 /***********************************************************************
1039 Deal with a name registration request query failure to a client that
1040 owned the name.
1042 We have a locked pointer to the original packet stashed away in the
1043 userdata pointer.
1044 ************************************************************************/
1046 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
1047 struct response_record *rrec,
1048 struct nmb_name *question_name,
1049 int rcode)
1051 struct userdata_struct *userdata = rrec->userdata;
1052 struct packet_struct *orig_reg_packet;
1054 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1056 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1057 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
1058 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1060 orig_reg_packet->locked = False;
1061 free_packet(orig_reg_packet);
1062 return;
1065 /***********************************************************************
1066 Deal with a multihomed name registration request to a WINS server.
1067 These cannot be group name registrations.
1068 ***********************************************************************/
1070 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
1071 struct packet_struct *p)
1073 struct nmb_packet *nmb = &p->packet.nmb;
1074 struct nmb_name *question = &nmb->question.question_name;
1075 BOOL bcast = nmb->header.nm_flags.bcast;
1076 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1077 int ttl = get_ttl_from_packet(nmb);
1078 struct name_record *namerec = NULL;
1079 struct in_addr from_ip;
1080 BOOL group = (nb_flags & NB_GROUP) ? True : False;
1081 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1082 nstring qname;
1084 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1086 if(bcast) {
1088 * We should only get unicast name registration packets here.
1089 * Anyone trying to register broadcast should not be going to a WINS
1090 * server. Log an error here.
1093 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1094 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1095 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1096 return;
1100 * Only unique names should be registered multihomed.
1103 if(group) {
1104 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1105 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1106 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1107 return;
1110 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1111 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1114 * Deal with policy regarding 0x1d names.
1117 if(question->name_type == 0x1d) {
1118 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1119 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1120 send_wins_name_registration_response(0, ttl, p);
1121 return;
1125 * See if the name already exists.
1128 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1131 * if the record exists but NOT in active state,
1132 * consider it dead.
1135 if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1136 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question)));
1137 remove_name_from_namelist(subrec, namerec);
1138 namerec = NULL;
1142 * Deal with the case where the name found was a dns entry.
1143 * Remove it as we now have a NetBIOS client registering the
1144 * name.
1147 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1148 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1149 - removing it.\n", nmb_namestr(question) ));
1150 remove_name_from_namelist( subrec, namerec);
1151 namerec = NULL;
1155 * Reject if the name exists and is not a REGISTER_NAME.
1156 * (ie. Don't allow any static names to be overwritten.
1159 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) {
1160 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1161 to register name %s. Name already exists in WINS with source type %d.\n",
1162 nmb_namestr(question), namerec->data.source ));
1163 send_wins_name_registration_response(RFS_ERR, 0, p);
1164 return;
1168 * Reject if the name exists and is a GROUP name and is active.
1171 if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) {
1172 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1173 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1174 send_wins_name_registration_response(RFS_ERR, 0, p);
1175 return;
1179 * From here on down we know that if the name exists in the WINS db it is
1180 * a unique name, not a group name.
1184 * If the name exists and is one of our names then check the
1185 * registering IP address. If it's not one of ours then automatically
1186 * reject without doing the query - we know we will reject it.
1189 if((namerec != NULL) && (is_myname(namerec->name.name)) ) {
1190 if(!ismyip(from_ip)) {
1191 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1192 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1193 send_wins_name_registration_response(RFS_ERR, 0, p);
1194 return;
1195 } else {
1197 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1198 * update the ttl. Update the version ID to force replication.
1200 if(!find_ip_in_name_record(namerec, from_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);
1205 add_ip_to_name_record(namerec, from_ip);
1206 wins_hook("add", namerec, ttl);
1207 } else {
1208 wins_hook("refresh", namerec, ttl);
1211 update_name_ttl(namerec, ttl);
1212 send_wins_name_registration_response(0, ttl, p);
1213 return;
1218 * If the name exists and is active, check if the IP address is already registered
1219 * to that name. If so then update the ttl and reply success.
1222 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) {
1223 update_name_ttl(namerec, ttl);
1226 * If it's a replica, we need to become the wins owner
1227 * to force the replication
1229 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1230 get_global_id_and_update(&namerec->data.id, True);
1231 update_wins_owner(namerec, our_fake_ip);
1232 update_wins_flag(namerec, WINS_ACTIVE);
1235 send_wins_name_registration_response(0, ttl, p);
1236 wins_hook("refresh", namerec, ttl);
1237 return;
1241 * If the name exists do a query to the owner
1242 * to see if they still want the name.
1245 if(namerec != NULL) {
1246 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1247 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1250 * First send a WACK to the registering machine.
1253 send_wins_wack_response(60, p);
1256 * When the reply comes back we need the original packet.
1257 * Lock this so it won't be freed and then put it into
1258 * the userdata structure.
1261 p->locked = True;
1263 userdata = (struct userdata_struct *)ud;
1265 userdata->copy_fn = NULL;
1266 userdata->free_fn = NULL;
1267 userdata->userdata_len = sizeof(struct packet_struct *);
1268 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1271 * Use the new call to send a query directly to an IP address.
1272 * This sends the query directly to the IP address, and ensures
1273 * the recursion desired flag is not set (you were right Luke :-).
1274 * This function should *only* be called from the WINS server
1275 * code. JRA.
1277 * Note that this packet is sent to the current owner of the name,
1278 * not the person who sent the packet
1281 pull_ascii_nstring( qname, question->name);
1282 query_name_from_wins_server( namerec->data.ip[0],
1283 qname,
1284 question->name_type,
1285 wins_multihomed_register_query_success,
1286 wins_multihomed_register_query_fail,
1287 userdata );
1289 return;
1293 * Name did not exist - add it.
1296 pull_ascii_nstring( qname, question->name);
1297 add_name_to_subnet( subrec, qname, question->name_type,
1298 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1300 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1301 get_global_id_and_update(&namerec->data.id, True);
1302 update_wins_owner(namerec, our_fake_ip);
1303 update_wins_flag(namerec, WINS_ACTIVE);
1304 wins_hook("add", namerec, ttl);
1307 send_wins_name_registration_response(0, ttl, p);
1310 /***********************************************************************
1311 Deal with the special name query for *<1b>.
1312 ***********************************************************************/
1314 static void process_wins_dmb_query_request(struct subnet_record *subrec,
1315 struct packet_struct *p)
1317 struct name_record *namerec = NULL;
1318 char *prdata;
1319 int num_ips;
1322 * Go through all the ACTIVE names in the WINS db looking for those
1323 * ending in <1b>. Use this to calculate the number of IP
1324 * addresses we need to return.
1327 num_ips = 0;
1328 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1329 namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {
1330 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b )
1331 num_ips += namerec->data.num_ips;
1334 if(num_ips == 0) {
1336 * There are no 0x1b names registered. Return name query fail.
1338 send_wins_name_query_response(NAM_ERR, p, NULL);
1339 return;
1342 if((prdata = (char *)malloc( num_ips * 6 )) == NULL) {
1343 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1344 return;
1348 * Go through all the names again in the WINS db looking for those
1349 * ending in <1b>. Add their IP addresses into the list we will
1350 * return.
1353 num_ips = 0;
1354 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1355 namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {
1356 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1357 int i;
1358 for(i = 0; i < namerec->data.num_ips; i++) {
1359 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1360 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1361 num_ips++;
1367 * Send back the reply containing the IP list.
1370 reply_netbios_packet(p, /* Packet to reply to. */
1371 0, /* Result code. */
1372 WINS_QUERY, /* nmbd type code. */
1373 NMB_NAME_QUERY_OPCODE, /* opcode. */
1374 lp_min_wins_ttl(), /* ttl. */
1375 prdata, /* data to send. */
1376 num_ips*6); /* data length. */
1378 SAFE_FREE(prdata);
1381 /****************************************************************************
1382 Send a WINS name query response.
1383 **************************************************************************/
1385 void send_wins_name_query_response(int rcode, struct packet_struct *p,
1386 struct name_record *namerec)
1388 char rdata[6];
1389 char *prdata = rdata;
1390 int reply_data_len = 0;
1391 int ttl = 0;
1392 int i;
1394 memset(rdata,'\0',6);
1396 if(rcode == 0) {
1397 ttl = (namerec->data.death_time != PERMANENT_TTL) ? namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1399 /* Copy all known ip addresses into the return data. */
1400 /* Optimise for the common case of one IP address so we don't need a malloc. */
1402 if( namerec->data.num_ips == 1 ) {
1403 prdata = rdata;
1404 } else {
1405 if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL) {
1406 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1407 return;
1411 for(i = 0; i < namerec->data.num_ips; i++) {
1412 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
1413 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
1416 sort_query_replies(prdata, i, p->ip);
1417 reply_data_len = namerec->data.num_ips * 6;
1420 reply_netbios_packet(p, /* Packet to reply to. */
1421 rcode, /* Result code. */
1422 WINS_QUERY, /* nmbd type code. */
1423 NMB_NAME_QUERY_OPCODE, /* opcode. */
1424 ttl, /* ttl. */
1425 prdata, /* data to send. */
1426 reply_data_len); /* data length. */
1428 if(prdata != rdata)
1429 SAFE_FREE(prdata);
1432 /***********************************************************************
1433 Deal with a name query.
1434 ***********************************************************************/
1436 void wins_process_name_query_request(struct subnet_record *subrec,
1437 struct packet_struct *p)
1439 struct nmb_packet *nmb = &p->packet.nmb;
1440 struct nmb_name *question = &nmb->question.question_name;
1441 struct name_record *namerec = NULL;
1442 nstring qname;
1444 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
1445 nmb_namestr(question), inet_ntoa(p->ip) ));
1448 * Special name code. If the queried name is *<1b> then search
1449 * the entire WINS database and return a list of all the IP addresses
1450 * registered to any <1b> name. This is to allow domain master browsers
1451 * to discover other domains that may not have a presence on their subnet.
1454 pull_ascii_nstring(qname, question->name);
1455 if(strequal( qname, "*") && (question->name_type == 0x1b)) {
1456 process_wins_dmb_query_request( subrec, p);
1457 return;
1460 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1462 if(namerec != NULL) {
1464 * If the name is not anymore in active state then reply not found.
1465 * it's fair even if we keep it in the cache for days.
1467 if (!WINS_STATE_ACTIVE(namerec)) {
1468 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1469 nmb_namestr(question) ));
1470 send_wins_name_query_response(NAM_ERR, p, namerec);
1471 return;
1475 * If it's a DNSFAIL_NAME then reply name not found.
1478 if( namerec->data.source == DNSFAIL_NAME ) {
1479 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
1480 nmb_namestr(question) ));
1481 send_wins_name_query_response(NAM_ERR, p, namerec);
1482 return;
1486 * If the name has expired then reply name not found.
1489 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < p->timestamp) ) {
1490 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1491 nmb_namestr(question) ));
1492 send_wins_name_query_response(NAM_ERR, p, namerec);
1493 return;
1496 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
1497 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
1499 send_wins_name_query_response(0, p, namerec);
1500 return;
1504 * Name not found in WINS - try a dns query if it's a 0x20 name.
1507 if(lp_dns_proxy() && ((question->name_type == 0x20) || question->name_type == 0)) {
1508 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
1509 nmb_namestr(question) ));
1511 queue_dns_query(p, question, &namerec);
1512 return;
1516 * Name not found - return error.
1519 send_wins_name_query_response(NAM_ERR, p, NULL);
1522 /****************************************************************************
1523 Send a WINS name release response.
1524 **************************************************************************/
1526 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
1528 struct nmb_packet *nmb = &p->packet.nmb;
1529 char rdata[6];
1531 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
1533 reply_netbios_packet(p, /* Packet to reply to. */
1534 rcode, /* Result code. */
1535 NMB_REL, /* nmbd type code. */
1536 NMB_NAME_RELEASE_OPCODE, /* opcode. */
1537 0, /* ttl. */
1538 rdata, /* data to send. */
1539 6); /* data length. */
1542 /***********************************************************************
1543 Deal with a name release.
1544 ***********************************************************************/
1546 void wins_process_name_release_request(struct subnet_record *subrec,
1547 struct packet_struct *p)
1549 struct nmb_packet *nmb = &p->packet.nmb;
1550 struct nmb_name *question = &nmb->question.question_name;
1551 BOOL bcast = nmb->header.nm_flags.bcast;
1552 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1553 struct name_record *namerec = NULL;
1554 struct in_addr from_ip;
1555 BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
1557 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1559 if(bcast) {
1561 * We should only get unicast name registration packets here.
1562 * Anyone trying to register broadcast should not be going to a WINS
1563 * server. Log an error here.
1566 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
1567 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1568 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1569 return;
1572 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
1573 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1576 * Deal with policy regarding 0x1d names.
1579 if(!releasing_group_name && (question->name_type == 0x1d)) {
1580 DEBUG(3,("wins_process_name_release_request: Ignoring request \
1581 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1582 send_wins_name_release_response(0, p);
1583 return;
1587 * See if the name already exists.
1590 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1592 if( (namerec == NULL) || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) {
1593 send_wins_name_release_response(NAM_ERR, p);
1594 return;
1598 * Check that the sending machine has permission to release this name.
1599 * If it's a group name not ending in 0x1c then just say yes and let
1600 * the group time out.
1603 if(releasing_group_name && (question->name_type != 0x1c)) {
1604 send_wins_name_release_response(0, p);
1605 return;
1609 * Check that the releasing node is on the list of IP addresses
1610 * for this name. Disallow the release if not.
1613 if(!find_ip_in_name_record(namerec, from_ip)) {
1614 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1615 release name %s as IP %s is not one of the known IP's for this name.\n",
1616 nmb_namestr(question), inet_ntoa(from_ip) ));
1617 send_wins_name_release_response(NAM_ERR, p);
1618 return;
1622 * Check if the record is active. IF it's already released
1623 * or tombstoned, refuse the release.
1626 if (!WINS_STATE_ACTIVE(namerec)) {
1627 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1628 release name %s as this record is not active anymore.\n", nmb_namestr(question) ));
1629 send_wins_name_release_response(NAM_ERR, p);
1630 return;
1634 * Check if the record is a 0x1c group
1635 * and has more then one ip
1636 * remove only this address.
1639 if(releasing_group_name && (question->name_type == 0x1c) && (namerec->data.num_ips > 1)) {
1640 remove_ip_from_name_record(namerec, from_ip);
1641 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
1642 inet_ntoa(from_ip),nmb_namestr(question)));
1643 send_wins_name_release_response(0, p);
1644 return;
1648 * Send a release response.
1649 * Flag the name as released and update the ttl
1652 send_wins_name_release_response(0, p);
1654 namerec->data.wins_flags |= WINS_RELEASED;
1655 update_name_ttl(namerec, EXTINCTION_INTERVAL);
1657 wins_hook("delete", namerec, 0);
1660 /*******************************************************************
1661 WINS time dependent processing.
1662 ******************************************************************/
1664 void initiate_wins_processing(time_t t)
1666 static time_t lasttime = 0;
1667 struct name_record *namerec;
1668 struct name_record *next_namerec;
1669 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1671 if (!lasttime)
1672 lasttime = t;
1673 if (t - lasttime < 20)
1674 return;
1676 lasttime = t;
1678 if(!lp_we_are_a_wins_server())
1679 return;
1681 for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
1682 namerec;
1683 namerec = next_namerec ) {
1684 next_namerec = (struct name_record *)ubi_trNext( namerec );
1686 if( (namerec->data.death_time != PERMANENT_TTL)
1687 && (namerec->data.death_time < t) ) {
1689 if( namerec->data.source == SELF_NAME ) {
1690 DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF name %s\n",
1691 wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
1692 namerec->data.death_time += 300;
1693 namerec->subnet->namelist_changed = True;
1694 continue;
1697 /* handle records, samba is the wins owner */
1698 if (ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1699 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
1700 case WINS_ACTIVE:
1701 namerec->data.wins_flags&=~WINS_STATE_MASK;
1702 namerec->data.wins_flags|=WINS_RELEASED;
1703 namerec->data.death_time = t + EXTINCTION_INTERVAL;
1704 DEBUG(3,("initiate_wins_processing: expiring %s\n", nmb_namestr(&namerec->name)));
1705 break;
1706 case WINS_RELEASED:
1707 namerec->data.wins_flags&=~WINS_STATE_MASK;
1708 namerec->data.wins_flags|=WINS_TOMBSTONED;
1709 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
1710 get_global_id_and_update(&namerec->data.id, True);
1711 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
1712 break;
1713 case WINS_TOMBSTONED:
1714 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
1715 remove_name_from_namelist( wins_server_subnet, namerec );
1716 break;
1718 } else {
1719 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
1720 case WINS_ACTIVE:
1721 /* that's not as MS says it should be */
1722 namerec->data.wins_flags&=~WINS_STATE_MASK;
1723 namerec->data.wins_flags|=WINS_TOMBSTONED;
1724 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
1725 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
1726 case WINS_TOMBSTONED:
1727 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
1728 remove_name_from_namelist( wins_server_subnet, namerec );
1729 break;
1730 case WINS_RELEASED:
1731 DEBUG(0,("initiate_wins_processing: %s is in released state and\
1732 we are not the wins owner !\n", nmb_namestr(&namerec->name)));
1733 break;
1740 if(wins_server_subnet->namelist_changed)
1741 wins_write_database(True);
1743 wins_server_subnet->namelist_changed = False;
1746 /*******************************************************************
1747 Write out the current WINS database.
1748 ******************************************************************/
1750 void wins_write_database(BOOL background)
1752 struct name_record *namerec;
1753 pstring fname, fnamenew;
1755 XFILE *fp;
1757 if(!lp_we_are_a_wins_server())
1758 return;
1760 /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */
1761 if (background) {
1762 CatchChild();
1763 if (sys_fork()) {
1764 return;
1768 slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST);
1769 all_string_sub(fname,"//", "/", 0);
1770 slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid());
1772 if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) {
1773 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
1774 if (background) {
1775 _exit(0);
1777 return;
1780 DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
1782 x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0);
1784 for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {
1785 int i;
1786 struct tm *tm;
1788 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
1790 if( namerec->data.death_time != PERMANENT_TTL ) {
1791 char *ts, *nl;
1793 tm = LocalTime(&namerec->data.death_time);
1794 ts = asctime(tm);
1795 nl = strrchr( ts, '\n' );
1796 if( NULL != nl )
1797 *nl = '\0';
1798 DEBUGADD(4,("TTL = %s ", ts ));
1799 } else {
1800 DEBUGADD(4,("TTL = PERMANENT "));
1803 for (i = 0; i < namerec->data.num_ips; i++)
1804 DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
1805 DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
1807 if( namerec->data.source == REGISTER_NAME ) {
1808 nstring name;
1809 pull_ascii_nstring(name, namerec->name.name);
1810 x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */
1811 (int)namerec->data.death_time);
1813 for (i = 0; i < namerec->data.num_ips; i++)
1814 x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
1815 x_fprintf( fp, "%2xR\n", namerec->data.nb_flags );
1819 x_fclose(fp);
1820 chmod(fnamenew,0644);
1821 unlink(fname);
1822 rename(fnamenew,fname);
1823 if (background) {
1824 _exit(0);
1828 /****************************************************************************
1829 Process a internal Samba message receiving a wins record.
1830 ***************************************************************************/
1832 void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len)
1834 WINS_RECORD *record;
1835 struct name_record *namerec = NULL;
1836 struct name_record *new_namerec = NULL;
1837 struct nmb_name question;
1838 BOOL overwrite=False;
1839 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1840 int i;
1842 if (buf==NULL)
1843 return;
1845 /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */
1846 record=(WINS_RECORD *)buf;
1848 make_nmb_name(&question, record->name, record->type);
1850 namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
1852 /* record doesn't exist, add it */
1853 if (namerec == NULL) {
1854 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
1855 record->name, record->type, inet_ntoa(record->wins_ip)));
1857 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
1858 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
1859 if (new_namerec!=NULL) {
1860 update_wins_owner(new_namerec, record->wins_ip);
1861 update_wins_flag(new_namerec, record->wins_flags);
1862 new_namerec->data.id=record->id;
1864 wins_server_subnet->namelist_changed = True;
1868 /* check if we have a conflict */
1869 if (namerec != NULL) {
1870 /* both records are UNIQUE */
1871 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
1873 /* the database record is a replica */
1874 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1875 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
1876 if (ip_equal(namerec->data.wins_ip, record->wins_ip))
1877 overwrite=True;
1878 } else
1879 overwrite=True;
1880 } else {
1881 /* we are the wins owner of the database record */
1882 /* the 2 records have the same IP address */
1883 if (ip_equal(namerec->data.ip[0], record->ip[0])) {
1884 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
1885 get_global_id_and_update(&namerec->data.id, True);
1886 else
1887 overwrite=True;
1889 } else {
1890 /* the 2 records have different IP address */
1891 if (namerec->data.wins_flags&WINS_ACTIVE) {
1892 if (record->wins_flags&WINS_TOMBSTONED)
1893 get_global_id_and_update(&namerec->data.id, True);
1894 if (record->wins_flags&WINS_ACTIVE)
1895 /* send conflict challenge to the replica node */
1897 } else
1898 overwrite=True;
1904 /* the replica is a standard group */
1905 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {
1906 /* if the database record is unique and active force a name release */
1907 if (namerec->data.wins_flags&WINS_UNIQUE)
1908 /* send a release name to the unique node */
1910 overwrite=True;
1914 /* the replica is a special group */
1915 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
1916 if (namerec->data.wins_flags&WINS_ACTIVE) {
1917 for (i=0; i<record->num_ips; i++)
1918 if(!find_ip_in_name_record(namerec, record->ip[i]))
1919 add_ip_to_name_record(namerec, record->ip[i]);
1920 } else {
1921 overwrite=True;
1925 /* the replica is a multihomed host */
1927 /* I'm giving up on multi homed. Too much complex to understand */
1929 if (record->wins_flags&WINS_MHOMED) {
1930 if (! (namerec->data.wins_flags&WINS_ACTIVE)) {
1931 if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP))
1932 overwrite=True;
1934 else {
1935 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
1936 overwrite=True;
1938 if (ip_equal(namerec->data.wins_ip, our_fake_ip))
1939 if (namerec->data.wins_flags&WINS_UNIQUE)
1940 get_global_id_and_update(&namerec->data.id, True);
1944 if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
1945 if (namerec->data.wins_flags&WINS_UNIQUE ||
1946 namerec->data.wins_flags&WINS_MHOMED)
1947 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
1948 overwrite=True;
1952 if (overwrite == False)
1953 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
1954 record->name, record->type, inet_ntoa(record->wins_ip)));
1955 else {
1956 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
1957 record->name, record->type, inet_ntoa(record->wins_ip)));
1959 /* remove the old record and add a new one */
1960 remove_name_from_namelist( wins_server_subnet, namerec );
1961 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
1962 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
1963 if (new_namerec!=NULL) {
1964 update_wins_owner(new_namerec, record->wins_ip);
1965 update_wins_flag(new_namerec, record->wins_flags);
1966 new_namerec->data.id=record->id;
1968 wins_server_subnet->namelist_changed = True;
1971 wins_server_subnet->namelist_changed = True;