removed two unneeded files after Richard backed out these changes.
[Samba.git] / source / nmbd / nmbd_winsserver.c
blob45385fc4e004421c46c83f05944decd388d7e10d
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 NBT netbios routines and daemon - version 2
6 Copyright (C) Jeremy Allison 1994-1998
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 #define WINS_LIST "wins.dat"
27 #define WINS_VERSION 1
29 /****************************************************************************
30 possibly call the WINS hook external program when a WINS change is made
31 *****************************************************************************/
33 static void wins_hook(char *operation, struct name_record *namerec, int ttl)
35 pstring command;
36 char *cmd = lp_wins_hook();
37 char *p;
38 int i;
40 if (!cmd || !*cmd) return;
42 for (p=namerec->name.name; *p; p++) {
43 if (!(isalnum((int)*p) || strchr("._-",*p))) {
44 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
45 return;
49 p = command;
50 p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d",
51 cmd,
52 operation,
53 namerec->name.name,
54 namerec->name.name_type,
55 ttl);
57 for (i=0;i<namerec->data.num_ips;i++) {
58 p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.ip[i]));
61 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
62 smbrun(command, NULL);
66 /****************************************************************************
67 hash our interfaces and netbios names settings
68 *****************************************************************************/
69 static unsigned wins_hash(void)
71 int i;
72 unsigned ret = iface_hash();
73 extern char **my_netbios_names;
75 for (i=0;my_netbios_names[i];i++)
76 ret ^= str_checksum(my_netbios_names[i]);
78 ret ^= str_checksum(lp_workgroup());
80 return ret;
84 /****************************************************************************
85 Determine if this packet should be allocated to the WINS server.
86 *****************************************************************************/
88 BOOL packet_is_for_wins_server(struct packet_struct *packet)
90 struct nmb_packet *nmb = &packet->packet.nmb;
92 /* Only unicast packets go to a WINS server. */
93 if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True))
95 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
96 return False;
99 /* Check for node status requests. */
100 if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY)
101 return False;
103 switch(nmb->header.opcode)
106 * A WINS server issues WACKS, not receives them.
108 case NMB_WACK_OPCODE:
109 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
110 return False;
112 * A WINS server only processes registration and
113 * release requests, not responses.
115 case NMB_NAME_REG_OPCODE:
116 case NMB_NAME_MULTIHOMED_REG_OPCODE:
117 case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
118 case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
119 if(nmb->header.response)
121 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
122 return False;
124 break;
126 case NMB_NAME_RELEASE_OPCODE:
127 if(nmb->header.response)
129 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
130 return False;
132 break;
135 * Only process unicast name queries with rd = 1.
137 case NMB_NAME_QUERY_OPCODE:
138 if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired)
140 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
141 return False;
143 break;
146 return True;
149 /****************************************************************************
150 Utility function to decide what ttl to give a register/refresh request.
151 *****************************************************************************/
153 static int get_ttl_from_packet(struct nmb_packet *nmb)
155 int ttl = nmb->additional->ttl;
157 if(ttl < lp_min_wins_ttl() )
158 ttl = lp_min_wins_ttl();
160 if(ttl > lp_max_wins_ttl() )
161 ttl = lp_max_wins_ttl();
163 return ttl;
166 /****************************************************************************
167 Load or create the WINS database.
168 *****************************************************************************/
170 BOOL initialise_wins(void)
172 time_t time_now = time(NULL);
173 FILE *fp;
174 pstring line;
176 if(!lp_we_are_a_wins_server())
177 return True;
179 add_samba_names_to_subnet(wins_server_subnet);
181 if((fp = sys_fopen(lock_path(WINS_LIST),"r")) == NULL)
183 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
184 WINS_LIST, strerror(errno) ));
185 return True;
188 while (!feof(fp))
190 pstring name_str, ip_str, ttl_str, nb_flags_str;
191 unsigned int num_ips;
192 pstring name;
193 struct in_addr *ip_list;
194 int type = 0;
195 int nb_flags;
196 int ttl;
197 char *ptr;
198 char *p;
199 BOOL got_token;
200 BOOL was_ip;
201 int i;
202 unsigned hash;
203 int version;
205 /* Read a line from the wins.dat file. Strips whitespace
206 from the beginning and end of the line.
208 if (!fgets_slash(line,sizeof(pstring),fp))
209 continue;
211 if (*line == '#')
212 continue;
214 if (strncmp(line,"VERSION ", 8) == 0) {
215 if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||
216 version != WINS_VERSION ||
217 hash != wins_hash()) {
218 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line));
219 fclose(fp);
220 return True;
222 continue;
225 ptr = line;
228 * Now we handle multiple IP addresses per name we need
229 * to iterate over the line twice. The first time to
230 * determine how many IP addresses there are, the second
231 * time to actually parse them into the ip_list array.
234 if (!next_token(&ptr,name_str,NULL,sizeof(name_str)))
236 DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));
237 continue;
240 if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str)))
242 DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));
243 continue;
247 * Determine the number of IP addresses per line.
249 num_ips = 0;
252 got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str));
253 was_ip = False;
255 if(got_token && strchr(ip_str, '.'))
257 num_ips++;
258 was_ip = True;
260 } while( got_token && was_ip);
262 if(num_ips == 0)
264 DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line ));
265 continue;
268 if(!got_token)
270 DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line ));
271 continue;
274 /* Allocate the space for the ip_list. */
275 if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL)
277 DEBUG(0,("initialise_wins: Malloc fail !\n"));
278 return False;
281 /* Reset and re-parse the line. */
282 ptr = line;
283 next_token(&ptr,name_str,NULL,sizeof(name_str));
284 next_token(&ptr,ttl_str,NULL,sizeof(ttl_str));
285 for(i = 0; i < num_ips; i++)
287 next_token(&ptr, ip_str, NULL, sizeof(ip_str));
288 ip_list[i] = *interpret_addr2(ip_str);
290 next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str));
293 * Deal with SELF or REGISTER name encoding. Default is REGISTER
294 * for compatibility with old nmbds.
297 if(nb_flags_str[strlen(nb_flags_str)-1] == 'S')
299 DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line));
300 SAFE_FREE(ip_list);
301 continue;
304 if(nb_flags_str[strlen(nb_flags_str)-1] == 'R')
305 nb_flags_str[strlen(nb_flags_str)-1] = '\0';
307 /* Netbios name. # divides the name from the type (hex): netbios#xx */
308 pstrcpy(name,name_str);
310 if((p = strchr(name,'#')) != NULL)
312 *p = 0;
313 sscanf(p+1,"%x",&type);
316 /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
317 sscanf(nb_flags_str,"%x",&nb_flags);
318 sscanf(ttl_str,"%d",&ttl);
320 /* add all entries that have 60 seconds or more to live */
321 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL)
323 if(ttl != PERMANENT_TTL)
324 ttl -= time_now;
326 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
327 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
329 (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
330 ttl, REGISTER_NAME, num_ips, ip_list );
333 else
335 DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n",
336 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
339 SAFE_FREE(ip_list);
342 fclose(fp);
343 return True;
346 /****************************************************************************
347 Send a WINS WACK (Wait ACKnowledgement) response.
348 **************************************************************************/
350 static void send_wins_wack_response(int ttl, struct packet_struct *p)
352 struct nmb_packet *nmb = &p->packet.nmb;
353 unsigned char rdata[2];
355 rdata[0] = rdata[1] = 0;
357 /* Taken from nmblib.c - we need to send back almost
358 identical bytes from the requesting packet header. */
360 rdata[0] = (nmb->header.opcode & 0xF) << 3;
361 if (nmb->header.nm_flags.authoritative &&
362 nmb->header.response) rdata[0] |= 0x4;
363 if (nmb->header.nm_flags.trunc) rdata[0] |= 0x2;
364 if (nmb->header.nm_flags.recursion_desired) rdata[0] |= 0x1;
365 if (nmb->header.nm_flags.recursion_available &&
366 nmb->header.response) rdata[1] |= 0x80;
367 if (nmb->header.nm_flags.bcast) rdata[1] |= 0x10;
369 reply_netbios_packet(p, /* Packet to reply to. */
370 0, /* Result code. */
371 NMB_WAIT_ACK, /* nmbd type code. */
372 NMB_WACK_OPCODE, /* opcode. */
373 ttl, /* ttl. */
374 (char *)rdata, /* data to send. */
375 2); /* data length. */
378 /****************************************************************************
379 Send a WINS name registration response.
380 **************************************************************************/
382 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
384 struct nmb_packet *nmb = &p->packet.nmb;
385 char rdata[6];
387 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
389 reply_netbios_packet(p, /* Packet to reply to. */
390 rcode, /* Result code. */
391 WINS_REG, /* nmbd type code. */
392 NMB_NAME_REG_OPCODE, /* opcode. */
393 ttl, /* ttl. */
394 rdata, /* data to send. */
395 6); /* data length. */
398 /***********************************************************************
399 Deal with a name refresh request to a WINS server.
400 ************************************************************************/
402 void wins_process_name_refresh_request(struct subnet_record *subrec,
403 struct packet_struct *p)
405 struct nmb_packet *nmb = &p->packet.nmb;
406 struct nmb_name *question = &nmb->question.question_name;
407 BOOL bcast = nmb->header.nm_flags.bcast;
408 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
409 BOOL group = (nb_flags & NB_GROUP) ? True : False;
410 struct name_record *namerec = NULL;
411 int ttl = get_ttl_from_packet(nmb);
412 struct in_addr from_ip;
414 putip((char *)&from_ip,&nmb->additional->rdata[2]);
416 if(bcast)
419 * We should only get unicast name refresh packets here.
420 * Anyone trying to refresh broadcast should not be going to a WINS
421 * server. Log an error here.
424 DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh request \
425 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
426 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
427 return;
430 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \
431 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
434 * See if the name already exists.
437 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
440 * If this is a refresh request and the name doesn't exist then
441 * treat it like a registration request. This allows us to recover
442 * from errors (tridge)
445 if(namerec == NULL)
447 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \
448 the name does not exist. Treating as registration.\n", nmb_namestr(question) ));
449 wins_process_name_registration_request(subrec,p);
450 return;
454 * Check that the group bits for the refreshing name and the
455 * name in our database match.
458 if((namerec != NULL) && ((group && !NAME_GROUP(namerec)) || (!group && NAME_GROUP(namerec))) )
460 DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \
461 does not match group bit in WINS for this name.\n", nmb_namestr(question), group ? "True" : "False" ));
462 send_wins_name_registration_response(RFS_ERR, 0, p);
463 return;
467 * For a unique name check that the person refreshing the name is one of the registered IP
468 * addresses. If not - fail the refresh. Do the same for group names with a type of 0x1c.
469 * Just return success for unique 0x1d refreshes. For normal group names update the ttl
470 * and return success.
473 if((!group || (group && (question->name_type == 0x1c))) && find_ip_in_name_record(namerec, from_ip ))
476 * Update the ttl.
478 update_name_ttl(namerec, ttl);
479 send_wins_name_registration_response(0, ttl, p);
480 wins_hook("refresh", namerec, ttl);
481 return;
483 else if(group)
486 * Normal groups are all registered with an IP address of 255.255.255.255
487 * so we can't search for the IP address.
489 update_name_ttl(namerec, ttl);
490 send_wins_name_registration_response(0, ttl, p);
491 return;
493 else if(!group && (question->name_type == 0x1d))
496 * Special name type - just pretend the refresh succeeded.
498 send_wins_name_registration_response(0, ttl, p);
499 return;
501 else
504 * Fail the refresh.
507 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \
508 is IP is not known to the name.\n", nmb_namestr(question), inet_ntoa(from_ip) ));
509 send_wins_name_registration_response(RFS_ERR, 0, p);
510 return;
514 /***********************************************************************
515 Deal with a name registration request query success to a client that
516 owned the name.
518 We have a locked pointer to the original packet stashed away in the
519 userdata pointer. The success here is actually a failure as it means
520 the client we queried wants to keep the name, so we must return
521 a registration failure to the original requestor.
522 ************************************************************************/
524 static void wins_register_query_success(struct subnet_record *subrec,
525 struct userdata_struct *userdata,
526 struct nmb_name *question_name,
527 struct in_addr ip,
528 struct res_rec *answers)
530 struct packet_struct *orig_reg_packet;
532 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
534 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
535 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
537 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
539 orig_reg_packet->locked = False;
540 free_packet(orig_reg_packet);
543 /***********************************************************************
544 Deal with a name registration request query failure to a client that
545 owned the name.
547 We have a locked pointer to the original packet stashed away in the
548 userdata pointer. The failure here is actually a success as it means
549 the client we queried didn't want to keep the name, so we can remove
550 the old name record and then successfully add the new name.
551 ************************************************************************/
553 static void wins_register_query_fail(struct subnet_record *subrec,
554 struct response_record *rrec,
555 struct nmb_name *question_name,
556 int rcode)
558 struct userdata_struct *userdata = rrec->userdata;
559 struct packet_struct *orig_reg_packet;
560 struct name_record *namerec = NULL;
562 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
565 * We want to just add the name, as we now know the original owner
566 * didn't want it. But we can't just do that as an arbitary
567 * amount of time may have taken place between the name query
568 * request and this timeout/error response. So we check that
569 * the name still exists and is in the same state - if so
570 * we remove it and call wins_process_name_registration_request()
571 * as we know it will do the right thing now.
574 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
576 if( (namerec != NULL)
577 && (namerec->data.source == REGISTER_NAME)
578 && ip_equal(rrec->packet->ip, *namerec->data.ip) )
580 remove_name_from_namelist( subrec, namerec);
581 namerec = NULL;
584 if(namerec == NULL)
585 wins_process_name_registration_request(subrec, orig_reg_packet);
586 else
587 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \
588 querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) ));
590 orig_reg_packet->locked = False;
591 free_packet(orig_reg_packet);
594 /***********************************************************************
595 Deal with a name registration request to a WINS server.
597 Use the following pseudocode :
599 registering_group
602 +--------name exists
605 | +--- existing name is group
606 | | |
607 | | |
608 | | +--- add name (return).
611 | +--- exiting name is unique
614 | +--- query existing owner (return).
617 +--------name doesn't exist
620 +--- add name (return).
622 registering_unique
625 +--------name exists
628 | +--- existing name is group
629 | | |
630 | | |
631 | | +--- fail add (return).
632 | |
634 | +--- exiting name is unique
637 | +--- query existing owner (return).
640 +--------name doesn't exist
643 +--- add name (return).
645 As can be seen from the above, the two cases may be collapsed onto each
646 other with the exception of the case where the name already exists and
647 is a group name. This case we handle with an if statement.
649 ************************************************************************/
651 void wins_process_name_registration_request(struct subnet_record *subrec,
652 struct packet_struct *p)
654 struct nmb_packet *nmb = &p->packet.nmb;
655 struct nmb_name *question = &nmb->question.question_name;
656 BOOL bcast = nmb->header.nm_flags.bcast;
657 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
658 int ttl = get_ttl_from_packet(nmb);
659 struct name_record *namerec = NULL;
660 struct in_addr from_ip;
661 BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;
663 putip((char *)&from_ip,&nmb->additional->rdata[2]);
665 if(bcast)
668 * We should only get unicast name registration packets here.
669 * Anyone trying to register broadcast should not be going to a WINS
670 * server. Log an error here.
673 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
674 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
675 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
676 return;
679 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
680 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
683 * See if the name already exists.
686 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
689 * Deal with the case where the name found was a dns entry.
690 * Remove it as we now have a NetBIOS client registering the
691 * name.
694 if( (namerec != NULL)
695 && ( (namerec->data.source == DNS_NAME)
696 || (namerec->data.source == DNSFAIL_NAME) ) )
698 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
699 a dns lookup - removing it.\n", nmb_namestr(question) ));
700 remove_name_from_namelist( subrec, namerec );
701 namerec = NULL;
705 * Reject if the name exists and is not a REGISTER_NAME.
706 * (ie. Don't allow any static names to be overwritten.
709 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME))
711 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
712 to register name %s. Name already exists in WINS with source type %d.\n",
713 nmb_namestr(question), namerec->data.source ));
714 send_wins_name_registration_response(RFS_ERR, 0, p);
715 return;
719 * Special policy decisions based on MS documentation.
720 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
721 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
725 * A group name is always added as the local broadcast address, except
726 * for group names ending in 0x1c.
727 * Group names with type 0x1c are registered with individual IP addresses.
730 if(registering_group_name && (question->name_type != 0x1c))
731 from_ip = *interpret_addr2("255.255.255.255");
734 * Ignore all attempts to register a unique 0x1d name, although return success.
737 if(!registering_group_name && (question->name_type == 0x1d))
739 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
740 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
741 send_wins_name_registration_response(0, ttl, p);
742 return;
746 * Next two cases are the 'if statement' mentioned above.
749 if((namerec != NULL) && NAME_GROUP(namerec))
751 if(registering_group_name)
754 * If we are adding a group name, the name exists and is also a group entry just add this
755 * IP address to it and update the ttl.
758 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
759 inet_ntoa(from_ip), nmb_namestr(question) ));
761 * Check the ip address is not already in the group.
763 if(!find_ip_in_name_record(namerec, from_ip))
764 add_ip_to_name_record(namerec, from_ip);
765 update_name_ttl(namerec, ttl);
766 send_wins_name_registration_response(0, ttl, p);
767 return;
769 else
772 * If we are adding a unique name, the name exists in the WINS db
773 * and is a group name then reject the registration.
776 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
777 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
778 send_wins_name_registration_response(RFS_ERR, 0, p);
779 return;
784 * From here on down we know that if the name exists in the WINS db it is
785 * a unique name, not a group name.
789 * If the name exists and is one of our names then check the
790 * registering IP address. If it's not one of ours then automatically
791 * reject without doing the query - we know we will reject it.
794 if((namerec != NULL) && (is_myname(namerec->name.name)) )
796 if(!ismyip(from_ip))
798 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
799 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
800 send_wins_name_registration_response(RFS_ERR, 0, p);
801 return;
803 else
806 * It's one of our names and one of our IP's - update the ttl.
808 update_name_ttl(namerec, ttl);
809 send_wins_name_registration_response(0, ttl, p);
810 wins_hook("refresh", namerec, ttl);
811 return;
816 * If the name exists and it is a unique registration and the registering IP
817 * is the same as the the (single) already registered IP then just update the ttl.
820 if( !registering_group_name
821 && (namerec != NULL)
822 && (namerec->data.num_ips == 1)
823 && ip_equal( namerec->data.ip[0], from_ip ) )
825 update_name_ttl( namerec, ttl );
826 send_wins_name_registration_response( 0, ttl, p );
827 wins_hook("refresh", namerec, ttl);
828 return;
832 * Finally if the name exists do a query to the registering machine
833 * to see if they still claim to have the name.
836 if( namerec != NULL )
838 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
839 struct userdata_struct *userdata = (struct userdata_struct *)ud;
842 * First send a WACK to the registering machine.
845 send_wins_wack_response(60, p);
848 * When the reply comes back we need the original packet.
849 * Lock this so it won't be freed and then put it into
850 * the userdata structure.
853 p->locked = True;
855 userdata = (struct userdata_struct *)ud;
857 userdata->copy_fn = NULL;
858 userdata->free_fn = NULL;
859 userdata->userdata_len = sizeof(struct packet_struct *);
860 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
863 * Use the new call to send a query directly to an IP address.
864 * This sends the query directly to the IP address, and ensures
865 * the recursion desired flag is not set (you were right Luke :-).
866 * This function should *only* be called from the WINS server
867 * code. JRA.
870 query_name_from_wins_server( *namerec->data.ip,
871 question->name,
872 question->name_type,
873 wins_register_query_success,
874 wins_register_query_fail,
875 userdata );
876 return;
880 * Name did not exist - add it.
883 (void)add_name_to_subnet( subrec, question->name, question->name_type,
884 nb_flags, ttl, REGISTER_NAME, 1, &from_ip );
885 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
886 wins_hook("add", namerec, ttl);
889 send_wins_name_registration_response(0, ttl, p);
892 /***********************************************************************
893 Deal with a mutihomed name query success to the machine that
894 requested the multihomed name registration.
896 We have a locked pointer to the original packet stashed away in the
897 userdata pointer.
898 ************************************************************************/
900 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
901 struct userdata_struct *userdata,
902 struct nmb_name *question_name,
903 struct in_addr ip,
904 struct res_rec *answers)
906 struct packet_struct *orig_reg_packet;
907 struct nmb_packet *nmb;
908 struct name_record *namerec = NULL;
909 struct in_addr from_ip;
910 int ttl;
912 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
914 nmb = &orig_reg_packet->packet.nmb;
916 putip((char *)&from_ip,&nmb->additional->rdata[2]);
917 ttl = get_ttl_from_packet(nmb);
920 * We want to just add the new IP, as we now know the requesting
921 * machine claims to own it. But we can't just do that as an arbitary
922 * amount of time may have taken place between the name query
923 * request and this response. So we check that
924 * the name still exists and is in the same state - if so
925 * we just add the extra IP and update the ttl.
928 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
930 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) )
932 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
933 a subsequent IP addess.\n", nmb_namestr(question_name) ));
934 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
936 orig_reg_packet->locked = False;
937 free_packet(orig_reg_packet);
939 return;
942 if(!find_ip_in_name_record(namerec, from_ip))
943 add_ip_to_name_record(namerec, from_ip);
944 update_name_ttl(namerec, ttl);
945 send_wins_name_registration_response(0, ttl, orig_reg_packet);
946 wins_hook("add", namerec, ttl);
948 orig_reg_packet->locked = False;
949 free_packet(orig_reg_packet);
952 /***********************************************************************
953 Deal with a name registration request query failure to a client that
954 owned the name.
956 We have a locked pointer to the original packet stashed away in the
957 userdata pointer.
958 ************************************************************************/
960 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
961 struct response_record *rrec,
962 struct nmb_name *question_name,
963 int rcode)
965 struct userdata_struct *userdata = rrec->userdata;
966 struct packet_struct *orig_reg_packet;
968 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
970 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
971 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
972 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
974 orig_reg_packet->locked = False;
975 free_packet(orig_reg_packet);
976 return;
979 /***********************************************************************
980 Deal with a multihomed name registration request to a WINS server.
981 These cannot be group name registrations.
982 ***********************************************************************/
984 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
985 struct packet_struct *p)
987 struct nmb_packet *nmb = &p->packet.nmb;
988 struct nmb_name *question = &nmb->question.question_name;
989 BOOL bcast = nmb->header.nm_flags.bcast;
990 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
991 int ttl = get_ttl_from_packet(nmb);
992 struct name_record *namerec = NULL;
993 struct in_addr from_ip;
994 BOOL group = (nb_flags & NB_GROUP) ? True : False;;
996 putip((char *)&from_ip,&nmb->additional->rdata[2]);
998 if(bcast)
1001 * We should only get unicast name registration packets here.
1002 * Anyone trying to register broadcast should not be going to a WINS
1003 * server. Log an error here.
1006 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1007 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1008 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1009 return;
1013 * Only unique names should be registered multihomed.
1016 if(group)
1018 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1019 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1020 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1021 return;
1024 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1025 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1028 * Deal with policy regarding 0x1d names.
1031 if(question->name_type == 0x1d)
1033 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1034 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1035 send_wins_name_registration_response(0, ttl, p);
1036 return;
1040 * See if the name already exists.
1043 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1046 * Deal with the case where the name found was a dns entry.
1047 * Remove it as we now have a NetBIOS client registering the
1048 * name.
1051 if( (namerec != NULL)
1052 && ( (namerec->data.source == DNS_NAME)
1053 || (namerec->data.source == DNSFAIL_NAME) ) )
1055 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1056 - removing it.\n", nmb_namestr(question) ));
1057 remove_name_from_namelist( subrec, namerec);
1058 namerec = NULL;
1062 * Reject if the name exists and is not a REGISTER_NAME.
1063 * (ie. Don't allow any static names to be overwritten.
1066 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) )
1068 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1069 to register name %s. Name already exists in WINS with source type %d.\n",
1070 nmb_namestr(question), namerec->data.source ));
1071 send_wins_name_registration_response(RFS_ERR, 0, p);
1072 return;
1076 * Reject if the name exists and is a GROUP name.
1079 if((namerec != NULL) && NAME_GROUP(namerec))
1081 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1082 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1083 send_wins_name_registration_response(RFS_ERR, 0, p);
1084 return;
1088 * From here on down we know that if the name exists in the WINS db it is
1089 * a unique name, not a group name.
1093 * If the name exists and is one of our names then check the
1094 * registering IP address. If it's not one of ours then automatically
1095 * reject without doing the query - we know we will reject it.
1098 if((namerec != NULL) && (is_myname(namerec->name.name)) )
1100 if(!ismyip(from_ip))
1102 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1103 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1104 send_wins_name_registration_response(RFS_ERR, 0, p);
1105 return;
1107 else
1110 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1111 * update the ttl.
1113 if(!find_ip_in_name_record(namerec, from_ip)) {
1114 add_ip_to_name_record(namerec, from_ip);
1115 wins_hook("add", namerec, ttl);
1116 } else {
1117 wins_hook("refresh", namerec, ttl);
1120 update_name_ttl(namerec, ttl);
1121 send_wins_name_registration_response(0, ttl, p);
1122 return;
1127 * If the name exists check if the IP address is already registered
1128 * to that name. If so then update the ttl and reply success.
1131 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip))
1133 update_name_ttl(namerec, ttl);
1134 send_wins_name_registration_response(0, ttl, p);
1135 wins_hook("refresh", namerec, ttl);
1136 return;
1140 * If the name exists do a query to the owner
1141 * to see if they still want the name.
1144 if(namerec != NULL)
1146 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1147 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1150 * First send a WACK to the registering machine.
1153 send_wins_wack_response(60, p);
1156 * When the reply comes back we need the original packet.
1157 * Lock this so it won't be freed and then put it into
1158 * the userdata structure.
1161 p->locked = True;
1163 userdata = (struct userdata_struct *)ud;
1165 userdata->copy_fn = NULL;
1166 userdata->free_fn = NULL;
1167 userdata->userdata_len = sizeof(struct packet_struct *);
1168 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1171 * Use the new call to send a query directly to an IP address.
1172 * This sends the query directly to the IP address, and ensures
1173 * the recursion desired flag is not set (you were right Luke :-).
1174 * This function should *only* be called from the WINS server
1175 * code. JRA.
1177 * Note that this packet is sent to the current owner of the name,
1178 * not the person who sent the packet
1181 query_name_from_wins_server( namerec->data.ip[0],
1182 question->name,
1183 question->name_type,
1184 wins_multihomed_register_query_success,
1185 wins_multihomed_register_query_fail,
1186 userdata );
1188 return;
1192 * Name did not exist - add it.
1195 (void)add_name_to_subnet( subrec, question->name, question->name_type,
1196 nb_flags, ttl, REGISTER_NAME, 1, &from_ip );
1198 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1199 wins_hook("add", namerec, ttl);
1202 send_wins_name_registration_response(0, ttl, p);
1205 /***********************************************************************
1206 Deal with the special name query for *<1b>.
1207 ***********************************************************************/
1209 static void process_wins_dmb_query_request(struct subnet_record *subrec,
1210 struct packet_struct *p)
1212 struct name_record *namerec = NULL;
1213 char *prdata;
1214 int num_ips;
1217 * Go through all the names in the WINS db looking for those
1218 * ending in <1b>. Use this to calculate the number of IP
1219 * addresses we need to return.
1222 num_ips = 0;
1223 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1224 namerec;
1225 namerec = (struct name_record *)ubi_trNext( namerec ) )
1227 if( namerec->name.name_type == 0x1b )
1228 num_ips += namerec->data.num_ips;
1231 if(num_ips == 0)
1234 * There are no 0x1b names registered. Return name query fail.
1236 send_wins_name_query_response(NAM_ERR, p, NULL);
1237 return;
1240 if((prdata = (char *)malloc( num_ips * 6 )) == NULL)
1242 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1243 return;
1247 * Go through all the names again in the WINS db looking for those
1248 * ending in <1b>. Add their IP addresses into the list we will
1249 * return.
1252 num_ips = 0;
1253 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1254 namerec;
1255 namerec = (struct name_record *)ubi_trNext( namerec ) )
1257 if(namerec->name.name_type == 0x1b)
1259 int i;
1260 for(i = 0; i < namerec->data.num_ips; i++)
1262 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1263 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1264 num_ips++;
1270 * Send back the reply containing the IP list.
1273 reply_netbios_packet(p, /* Packet to reply to. */
1274 0, /* Result code. */
1275 WINS_QUERY, /* nmbd type code. */
1276 NMB_NAME_QUERY_OPCODE, /* opcode. */
1277 lp_min_wins_ttl(), /* ttl. */
1278 prdata, /* data to send. */
1279 num_ips*6); /* data length. */
1281 SAFE_FREE(prdata);
1284 /****************************************************************************
1285 Send a WINS name query response.
1286 **************************************************************************/
1288 void send_wins_name_query_response(int rcode, struct packet_struct *p,
1289 struct name_record *namerec)
1291 char rdata[6];
1292 char *prdata = rdata;
1293 int reply_data_len = 0;
1294 int ttl = 0;
1295 int i;
1297 memset(rdata,'\0',6);
1299 if(rcode == 0)
1301 ttl = (namerec->data.death_time != PERMANENT_TTL) ?
1302 namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1304 /* Copy all known ip addresses into the return data. */
1305 /* Optimise for the common case of one IP address so
1306 we don't need a malloc. */
1308 if( namerec->data.num_ips == 1 )
1309 prdata = rdata;
1310 else
1312 if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL)
1314 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1315 return;
1319 for(i = 0; i < namerec->data.num_ips; i++)
1321 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
1322 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
1325 sort_query_replies(prdata, i, p->ip);
1327 reply_data_len = namerec->data.num_ips * 6;
1330 reply_netbios_packet(p, /* Packet to reply to. */
1331 rcode, /* Result code. */
1332 WINS_QUERY, /* nmbd type code. */
1333 NMB_NAME_QUERY_OPCODE, /* opcode. */
1334 ttl, /* ttl. */
1335 prdata, /* data to send. */
1336 reply_data_len); /* data length. */
1338 if((prdata != rdata) && (prdata != NULL))
1339 SAFE_FREE(prdata);
1342 /***********************************************************************
1343 Deal with a name query.
1344 ***********************************************************************/
1346 void wins_process_name_query_request(struct subnet_record *subrec,
1347 struct packet_struct *p)
1349 struct nmb_packet *nmb = &p->packet.nmb;
1350 struct nmb_name *question = &nmb->question.question_name;
1351 struct name_record *namerec = NULL;
1353 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
1354 nmb_namestr(question), inet_ntoa(p->ip) ));
1357 * Special name code. If the queried name is *<1b> then search
1358 * the entire WINS database and return a list of all the IP addresses
1359 * registered to any <1b> name. This is to allow domain master browsers
1360 * to discover other domains that may not have a presence on their subnet.
1363 if(strequal( question->name, "*") && (question->name_type == 0x1b))
1365 process_wins_dmb_query_request( subrec, p);
1366 return;
1369 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1371 if(namerec != NULL)
1374 * If it's a DNSFAIL_NAME then reply name not found.
1377 if( namerec->data.source == DNSFAIL_NAME )
1379 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
1380 nmb_namestr(question) ));
1381 send_wins_name_query_response(NAM_ERR, p, namerec);
1382 return;
1386 * If the name has expired then reply name not found.
1389 if( (namerec->data.death_time != PERMANENT_TTL)
1390 && (namerec->data.death_time < p->timestamp) )
1392 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1393 nmb_namestr(question) ));
1394 send_wins_name_query_response(NAM_ERR, p, namerec);
1395 return;
1398 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
1399 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
1401 send_wins_name_query_response(0, p, namerec);
1402 return;
1406 * Name not found in WINS - try a dns query if it's a 0x20 name.
1409 if(lp_dns_proxy() &&
1410 ((question->name_type == 0x20) || question->name_type == 0))
1413 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
1414 nmb_namestr(question) ));
1416 queue_dns_query(p, question, &namerec);
1417 return;
1421 * Name not found - return error.
1424 send_wins_name_query_response(NAM_ERR, p, NULL);
1427 /****************************************************************************
1428 Send a WINS name release response.
1429 **************************************************************************/
1431 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
1433 struct nmb_packet *nmb = &p->packet.nmb;
1434 char rdata[6];
1436 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
1438 reply_netbios_packet(p, /* Packet to reply to. */
1439 rcode, /* Result code. */
1440 NMB_REL, /* nmbd type code. */
1441 NMB_NAME_RELEASE_OPCODE, /* opcode. */
1442 0, /* ttl. */
1443 rdata, /* data to send. */
1444 6); /* data length. */
1447 /***********************************************************************
1448 Deal with a name release.
1449 ***********************************************************************/
1451 void wins_process_name_release_request(struct subnet_record *subrec,
1452 struct packet_struct *p)
1454 struct nmb_packet *nmb = &p->packet.nmb;
1455 struct nmb_name *question = &nmb->question.question_name;
1456 BOOL bcast = nmb->header.nm_flags.bcast;
1457 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1458 struct name_record *namerec = NULL;
1459 struct in_addr from_ip;
1460 BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
1462 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1464 if(bcast)
1467 * We should only get unicast name registration packets here.
1468 * Anyone trying to register broadcast should not be going to a WINS
1469 * server. Log an error here.
1472 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
1473 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1474 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1475 return;
1478 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
1479 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1482 * Deal with policy regarding 0x1d names.
1485 if(!releasing_group_name && (question->name_type == 0x1d))
1487 DEBUG(3,("wins_process_name_release_request: Ignoring request \
1488 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1489 send_wins_name_release_response(0, p);
1490 return;
1494 * See if the name already exists.
1497 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1499 if( (namerec == NULL)
1500 || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) )
1502 send_wins_name_release_response(NAM_ERR, p);
1503 return;
1507 * Check that the sending machine has permission to release this name.
1508 * If it's a group name not ending in 0x1c then just say yes and let
1509 * the group time out.
1512 if(releasing_group_name && (question->name_type != 0x1c))
1514 send_wins_name_release_response(0, p);
1515 return;
1519 * Check that the releasing node is on the list of IP addresses
1520 * for this name. Disallow the release if not.
1523 if(!find_ip_in_name_record(namerec, from_ip))
1525 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1526 release name %s as IP %s is not one of the known IP's for this name.\n",
1527 nmb_namestr(question), inet_ntoa(from_ip) ));
1528 send_wins_name_release_response(NAM_ERR, p);
1529 return;
1533 * Release the name and then remove the IP from the known list.
1536 send_wins_name_release_response(0, p);
1537 remove_ip_from_name_record(namerec, from_ip);
1539 wins_hook("delete", namerec, 0);
1542 * Remove the name entirely if no IP addresses left.
1544 if (namerec->data.num_ips == 0)
1545 remove_name_from_namelist(subrec, namerec);
1549 /*******************************************************************
1550 WINS time dependent processing.
1551 ******************************************************************/
1553 void initiate_wins_processing(time_t t)
1555 static time_t lasttime = 0;
1557 if (!lasttime)
1558 lasttime = t;
1559 if (t - lasttime < 20)
1560 return;
1562 lasttime = t;
1564 if(!lp_we_are_a_wins_server())
1565 return;
1567 expire_names_on_subnet(wins_server_subnet, t);
1569 if(wins_server_subnet->namelist_changed)
1570 wins_write_database(True);
1572 wins_server_subnet->namelist_changed = False;
1575 /*******************************************************************
1576 Write out the current WINS database.
1577 ******************************************************************/
1578 void wins_write_database(BOOL background)
1580 struct name_record *namerec;
1581 pstring fname, fnamenew;
1583 FILE *fp;
1585 if(!lp_we_are_a_wins_server())
1586 return;
1588 /* we will do the writing in a child process to ensure that the parent
1589 doesn't block while this is done */
1590 if (background) {
1591 CatchChild();
1592 if (sys_fork()) {
1593 return;
1597 slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST);
1598 all_string_sub(fname,"//", "/", 0);
1599 slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid());
1601 if((fp = sys_fopen(fnamenew,"w")) == NULL)
1603 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
1604 if (background) {
1605 _exit(0);
1607 return;
1610 DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
1612 fprintf(fp,"VERSION %d %u\n", WINS_VERSION, wins_hash());
1614 for( namerec
1615 = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
1616 namerec;
1617 namerec = (struct name_record *)ubi_trNext( namerec ) )
1619 int i;
1620 struct tm *tm;
1622 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
1624 if( namerec->data.death_time != PERMANENT_TTL )
1626 char *ts, *nl;
1628 tm = LocalTime(&namerec->data.death_time);
1629 ts = asctime(tm);
1630 nl = strrchr( ts, '\n' );
1631 if( NULL != nl )
1632 *nl = '\0';
1633 DEBUGADD(4,("TTL = %s ", ts ));
1635 else
1636 DEBUGADD(4,("TTL = PERMANENT "));
1638 for (i = 0; i < namerec->data.num_ips; i++)
1639 DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
1640 DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
1642 if( namerec->data.source == REGISTER_NAME )
1644 fprintf(fp, "\"%s#%02x\" %d ",
1645 namerec->name.name,namerec->name.name_type, /* Ignore scope. */
1646 (int)namerec->data.death_time);
1648 for (i = 0; i < namerec->data.num_ips; i++)
1649 fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
1650 fprintf( fp, "%2xR\n", namerec->data.nb_flags );
1654 fclose(fp);
1655 chmod(fnamenew,0644);
1656 unlink(fname);
1657 rename(fnamenew,fname);
1658 if (background) {
1659 _exit(0);