dnscrypto-proxy: Support files updated.
[tomato.git] / release / src / router / samba / source / nmbd / nmbd_winsserver.c
blob0a21adb1ec8937cf245b6cfbe50e182348cc1b5c
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 extern int DEBUGLEVEL;
30 extern struct in_addr ipzero;
33 /****************************************************************************
34 possibly call the WINS hook external program when a WINS change is made
35 *****************************************************************************/
36 static void wins_hook(char *operation, struct name_record *namerec, int ttl)
38 pstring command;
39 char *cmd = lp_wins_hook();
40 char *p;
41 int i;
43 if (!cmd || !*cmd) return;
45 for (p=namerec->name.name; *p; p++) {
46 if (!(isalnum((int)*p) || strchr("._-",*p))) {
47 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
48 return;
52 p = command;
53 p += slprintf(p, sizeof(command), "%s %s %s %02x %d",
54 cmd,
55 operation,
56 namerec->name.name,
57 namerec->name.name_type,
58 ttl);
60 for (i=0;i<namerec->data.num_ips;i++) {
61 p += slprintf(p, sizeof(command) - (p-command), " %s", inet_ntoa(namerec->data.ip[i]));
64 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
65 smbrun(command, NULL, False);
69 /****************************************************************************
70 hash our interfaces and netbios names settings
71 *****************************************************************************/
72 static unsigned wins_hash(void)
74 int i;
75 unsigned ret = iface_hash();
76 extern char **my_netbios_names;
78 for (i=0;my_netbios_names[i];i++)
79 ret ^= str_checksum(my_netbios_names[i]);
81 ret ^= str_checksum(lp_workgroup());
83 return ret;
87 /****************************************************************************
88 Determine if this packet should be allocated to the WINS server.
89 *****************************************************************************/
91 BOOL packet_is_for_wins_server(struct packet_struct *packet)
93 struct nmb_packet *nmb = &packet->packet.nmb;
95 /* Only unicast packets go to a WINS server. */
96 if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True))
98 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
99 return False;
102 /* Check for node status requests. */
103 if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY)
104 return False;
106 switch(nmb->header.opcode)
109 * A WINS server issues WACKS, not receives them.
111 case NMB_WACK_OPCODE:
112 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
113 return False;
115 * A WINS server only processes registration and
116 * release requests, not responses.
118 case NMB_NAME_REG_OPCODE:
119 case NMB_NAME_MULTIHOMED_REG_OPCODE:
120 case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
121 case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
122 if(nmb->header.response)
124 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
125 return False;
127 break;
129 case NMB_NAME_RELEASE_OPCODE:
130 if(nmb->header.response)
132 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
133 return False;
135 break;
138 * Only process unicast name queries with rd = 1.
140 case NMB_NAME_QUERY_OPCODE:
141 if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired)
143 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
144 return False;
146 break;
149 return True;
152 /****************************************************************************
153 Utility function to decide what ttl to give a register/refresh request.
154 *****************************************************************************/
156 static int get_ttl_from_packet(struct nmb_packet *nmb)
158 int ttl = nmb->additional->ttl;
160 if(ttl < lp_min_wins_ttl() )
161 ttl = lp_min_wins_ttl();
163 if(ttl > lp_max_wins_ttl() )
164 ttl = lp_max_wins_ttl();
166 return ttl;
169 /****************************************************************************
170 Load or create the WINS database.
171 *****************************************************************************/
173 BOOL initialise_wins(void)
175 pstring fname;
176 time_t time_now = time(NULL);
177 FILE *fp;
178 pstring line;
180 if(!lp_we_are_a_wins_server())
181 return True;
183 add_samba_names_to_subnet(wins_server_subnet);
185 pstrcpy(fname,lp_lockdir());
186 trim_string(fname,NULL,"/");
187 pstrcat(fname,"/");
188 pstrcat(fname,WINS_LIST);
190 if((fp = sys_fopen(fname,"r")) == NULL)
192 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
193 fname, strerror(errno) ));
194 return True;
197 while (!feof(fp))
199 pstring name_str, ip_str, ttl_str, nb_flags_str;
200 unsigned int num_ips;
201 pstring name;
202 struct in_addr *ip_list;
203 int type = 0;
204 int nb_flags;
205 int ttl;
206 char *ptr;
207 char *p;
208 BOOL got_token;
209 BOOL was_ip;
210 int i;
211 unsigned hash;
212 int version;
214 /* Read a line from the wins.dat file. Strips whitespace
215 from the beginning and end of the line.
217 if (!fgets_slash(line,sizeof(pstring),fp))
218 continue;
220 if (*line == '#')
221 continue;
223 if (strncmp(line,"VERSION ", 8) == 0) {
224 if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||
225 version != WINS_VERSION ||
226 hash != wins_hash()) {
227 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line));
228 fclose(fp);
229 return True;
231 continue;
234 ptr = line;
237 * Now we handle multiple IP addresses per name we need
238 * to iterate over the line twice. The first time to
239 * determine how many IP addresses there are, the second
240 * time to actually parse them into the ip_list array.
243 if (!next_token(&ptr,name_str,NULL,sizeof(name_str)))
245 DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));
246 continue;
249 if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str)))
251 DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));
252 continue;
256 * Determine the number of IP addresses per line.
258 num_ips = 0;
261 got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str));
262 was_ip = False;
264 if(got_token && strchr(ip_str, '.'))
266 num_ips++;
267 was_ip = True;
269 } while( got_token && was_ip);
271 if(num_ips == 0)
273 DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line ));
274 continue;
277 if(!got_token)
279 DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line ));
280 continue;
283 /* Allocate the space for the ip_list. */
284 if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL)
286 DEBUG(0,("initialise_wins: Malloc fail !\n"));
287 return False;
290 /* Reset and re-parse the line. */
291 ptr = line;
292 next_token(&ptr,name_str,NULL,sizeof(name_str));
293 next_token(&ptr,ttl_str,NULL,sizeof(ttl_str));
294 for(i = 0; i < num_ips; i++)
296 next_token(&ptr, ip_str, NULL, sizeof(ip_str));
297 ip_list[i] = *interpret_addr2(ip_str);
299 next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str));
302 * Deal with SELF or REGISTER name encoding. Default is REGISTER
303 * for compatibility with old nmbds.
306 if(nb_flags_str[strlen(nb_flags_str)-1] == 'S')
308 DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line));
309 free((char *)ip_list);
310 continue;
313 if(nb_flags_str[strlen(nb_flags_str)-1] == 'R')
314 nb_flags_str[strlen(nb_flags_str)-1] = '\0';
316 /* Netbios name. # divides the name from the type (hex): netbios#xx */
317 pstrcpy(name,name_str);
319 if((p = strchr(name,'#')) != NULL)
321 *p = 0;
322 sscanf(p+1,"%x",&type);
325 /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
326 sscanf(nb_flags_str,"%x",&nb_flags);
327 sscanf(ttl_str,"%d",&ttl);
329 /* add all entries that have 60 seconds or more to live */
330 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL)
332 if(ttl != PERMANENT_TTL)
333 ttl -= time_now;
335 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
336 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
338 (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
339 ttl, REGISTER_NAME, num_ips, ip_list );
342 else
344 DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n",
345 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
348 free((char *)ip_list);
351 fclose(fp);
352 return True;
355 /****************************************************************************
356 Send a WINS WACK (Wait ACKnowledgement) response.
357 **************************************************************************/
359 static void send_wins_wack_response(int ttl, struct packet_struct *p)
361 struct nmb_packet *nmb = &p->packet.nmb;
362 unsigned char rdata[2];
364 rdata[0] = rdata[1] = 0;
366 /* Taken from nmblib.c - we need to send back almost
367 identical bytes from the requesting packet header. */
369 rdata[0] = (nmb->header.opcode & 0xF) << 3;
370 if (nmb->header.nm_flags.authoritative &&
371 nmb->header.response) rdata[0] |= 0x4;
372 if (nmb->header.nm_flags.trunc) rdata[0] |= 0x2;
373 if (nmb->header.nm_flags.recursion_desired) rdata[0] |= 0x1;
374 if (nmb->header.nm_flags.recursion_available &&
375 nmb->header.response) rdata[1] |= 0x80;
376 if (nmb->header.nm_flags.bcast) rdata[1] |= 0x10;
378 reply_netbios_packet(p, /* Packet to reply to. */
379 0, /* Result code. */
380 NMB_WAIT_ACK, /* nmbd type code. */
381 NMB_WACK_OPCODE, /* opcode. */
382 ttl, /* ttl. */
383 (char *)rdata, /* data to send. */
384 2); /* data length. */
387 /****************************************************************************
388 Send a WINS name registration response.
389 **************************************************************************/
391 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
393 struct nmb_packet *nmb = &p->packet.nmb;
394 char rdata[6];
396 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
398 reply_netbios_packet(p, /* Packet to reply to. */
399 rcode, /* Result code. */
400 WINS_REG, /* nmbd type code. */
401 NMB_NAME_REG_OPCODE, /* opcode. */
402 ttl, /* ttl. */
403 rdata, /* data to send. */
404 6); /* data length. */
407 /***********************************************************************
408 Deal with a name refresh request to a WINS server.
409 ************************************************************************/
411 void wins_process_name_refresh_request(struct subnet_record *subrec,
412 struct packet_struct *p)
414 struct nmb_packet *nmb = &p->packet.nmb;
415 struct nmb_name *question = &nmb->question.question_name;
416 BOOL bcast = nmb->header.nm_flags.bcast;
417 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
418 BOOL group = (nb_flags & NB_GROUP) ? True : False;
419 struct name_record *namerec = NULL;
420 int ttl = get_ttl_from_packet(nmb);
421 struct in_addr from_ip;
423 putip((char *)&from_ip,&nmb->additional->rdata[2]);
425 if(bcast)
428 * We should only get unicast name refresh packets here.
429 * Anyone trying to refresh broadcast should not be going to a WINS
430 * server. Log an error here.
433 DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh request \
434 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
435 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
436 return;
439 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \
440 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
443 * See if the name already exists.
446 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
449 * If this is a refresh request and the name doesn't exist then
450 * treat it like a registration request. This allows us to recover
451 * from errors (tridge)
454 if(namerec == NULL)
456 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \
457 the name does not exist. Treating as registration.\n", nmb_namestr(question) ));
458 wins_process_name_registration_request(subrec,p);
459 return;
463 * Check that the group bits for the refreshing name and the
464 * name in our database match.
467 if((namerec != NULL) && ((group && !NAME_GROUP(namerec)) || (!group && NAME_GROUP(namerec))) )
469 DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \
470 does not match group bit in WINS for this name.\n", nmb_namestr(question), group ? "True" : "False" ));
471 send_wins_name_registration_response(RFS_ERR, 0, p);
472 return;
476 * For a unique name check that the person refreshing the name is one of the registered IP
477 * addresses. If not - fail the refresh. Do the same for group names with a type of 0x1c.
478 * Just return success for unique 0x1d refreshes. For normal group names update the ttl
479 * and return success.
482 if((!group || (group && (question->name_type == 0x1c))) && find_ip_in_name_record(namerec, from_ip ))
485 * Update the ttl.
487 update_name_ttl(namerec, ttl);
488 send_wins_name_registration_response(0, ttl, p);
489 wins_hook("refresh", namerec, ttl);
490 return;
492 else if(group)
495 * Normal groups are all registered with an IP address of 255.255.255.255
496 * so we can't search for the IP address.
498 update_name_ttl(namerec, ttl);
499 send_wins_name_registration_response(0, ttl, p);
500 return;
502 else if(!group && (question->name_type == 0x1d))
505 * Special name type - just pretend the refresh succeeded.
507 send_wins_name_registration_response(0, ttl, p);
508 return;
510 else
513 * Fail the refresh.
516 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \
517 is IP is not known to the name.\n", nmb_namestr(question), inet_ntoa(from_ip) ));
518 send_wins_name_registration_response(RFS_ERR, 0, p);
519 return;
523 /***********************************************************************
524 Deal with a name registration request query success to a client that
525 owned the name.
527 We have a locked pointer to the original packet stashed away in the
528 userdata pointer. The success here is actually a failure as it means
529 the client we queried wants to keep the name, so we must return
530 a registration failure to the original requestor.
531 ************************************************************************/
533 static void wins_register_query_success(struct subnet_record *subrec,
534 struct userdata_struct *userdata,
535 struct nmb_name *question_name,
536 struct in_addr ip,
537 struct res_rec *answers)
539 struct packet_struct *orig_reg_packet;
541 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
543 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
544 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
546 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
548 orig_reg_packet->locked = False;
549 free_packet(orig_reg_packet);
552 /***********************************************************************
553 Deal with a name registration request query failure to a client that
554 owned the name.
556 We have a locked pointer to the original packet stashed away in the
557 userdata pointer. The failure here is actually a success as it means
558 the client we queried didn't want to keep the name, so we can remove
559 the old name record and then successfully add the new name.
560 ************************************************************************/
562 static void wins_register_query_fail(struct subnet_record *subrec,
563 struct response_record *rrec,
564 struct nmb_name *question_name,
565 int rcode)
567 struct userdata_struct *userdata = rrec->userdata;
568 struct packet_struct *orig_reg_packet;
569 struct name_record *namerec = NULL;
571 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
574 * We want to just add the name, as we now know the original owner
575 * didn't want it. But we can't just do that as an arbitary
576 * amount of time may have taken place between the name query
577 * request and this timeout/error response. So we check that
578 * the name still exists and is in the same state - if so
579 * we remove it and call wins_process_name_registration_request()
580 * as we know it will do the right thing now.
583 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
585 if( (namerec != NULL)
586 && (namerec->data.source == REGISTER_NAME)
587 && ip_equal(rrec->packet->ip, *namerec->data.ip) )
589 remove_name_from_namelist( subrec, namerec);
590 namerec = NULL;
593 if(namerec == NULL)
594 wins_process_name_registration_request(subrec, orig_reg_packet);
595 else
596 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \
597 querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) ));
599 orig_reg_packet->locked = False;
600 free_packet(orig_reg_packet);
603 /***********************************************************************
604 Deal with a name registration request to a WINS server.
606 Use the following pseudocode :
608 registering_group
611 +--------name exists
614 | +--- existing name is group
615 | | |
616 | | |
617 | | +--- add name (return).
620 | +--- exiting name is unique
623 | +--- query existing owner (return).
626 +--------name doesn't exist
629 +--- add name (return).
631 registering_unique
634 +--------name exists
637 | +--- existing name is group
638 | | |
639 | | |
640 | | +--- fail add (return).
641 | |
643 | +--- exiting name is unique
646 | +--- query existing owner (return).
649 +--------name doesn't exist
652 +--- add name (return).
654 As can be seen from the above, the two cases may be collapsed onto each
655 other with the exception of the case where the name already exists and
656 is a group name. This case we handle with an if statement.
658 ************************************************************************/
660 void wins_process_name_registration_request(struct subnet_record *subrec,
661 struct packet_struct *p)
663 struct nmb_packet *nmb = &p->packet.nmb;
664 struct nmb_name *question = &nmb->question.question_name;
665 BOOL bcast = nmb->header.nm_flags.bcast;
666 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
667 int ttl = get_ttl_from_packet(nmb);
668 struct name_record *namerec = NULL;
669 struct in_addr from_ip;
670 BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;
672 putip((char *)&from_ip,&nmb->additional->rdata[2]);
674 if(bcast)
677 * We should only get unicast name registration packets here.
678 * Anyone trying to register broadcast should not be going to a WINS
679 * server. Log an error here.
682 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
683 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
684 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
685 return;
688 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
689 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
692 * See if the name already exists.
695 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
698 * Deal with the case where the name found was a dns entry.
699 * Remove it as we now have a NetBIOS client registering the
700 * name.
703 if( (namerec != NULL)
704 && ( (namerec->data.source == DNS_NAME)
705 || (namerec->data.source == DNSFAIL_NAME) ) )
707 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
708 a dns lookup - removing it.\n", nmb_namestr(question) ));
709 remove_name_from_namelist( subrec, namerec );
710 namerec = NULL;
714 * Reject if the name exists and is not a REGISTER_NAME.
715 * (ie. Don't allow any static names to be overwritten.
718 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME))
720 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
721 to register name %s. Name already exists in WINS with source type %d.\n",
722 nmb_namestr(question), namerec->data.source ));
723 send_wins_name_registration_response(RFS_ERR, 0, p);
724 return;
728 * Special policy decisions based on MS documentation.
729 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
730 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
734 * A group name is always added as the local broadcast address, except
735 * for group names ending in 0x1c.
736 * Group names with type 0x1c are registered with individual IP addresses.
739 if(registering_group_name && (question->name_type != 0x1c))
740 from_ip = *interpret_addr2("255.255.255.255");
743 * Ignore all attempts to register a unique 0x1d name, although return success.
746 if(!registering_group_name && (question->name_type == 0x1d))
748 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
749 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
750 send_wins_name_registration_response(0, ttl, p);
751 return;
755 * Next two cases are the 'if statement' mentioned above.
758 if((namerec != NULL) && NAME_GROUP(namerec))
760 if(registering_group_name)
763 * If we are adding a group name, the name exists and is also a group entry just add this
764 * IP address to it and update the ttl.
767 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
768 inet_ntoa(from_ip), nmb_namestr(question) ));
770 * Check the ip address is not already in the group.
772 if(!find_ip_in_name_record(namerec, from_ip))
773 add_ip_to_name_record(namerec, from_ip);
774 update_name_ttl(namerec, ttl);
775 send_wins_name_registration_response(0, ttl, p);
776 return;
778 else
781 * If we are adding a unique name, the name exists in the WINS db
782 * and is a group name then reject the registration.
785 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
786 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
787 send_wins_name_registration_response(RFS_ERR, 0, p);
788 return;
793 * From here on down we know that if the name exists in the WINS db it is
794 * a unique name, not a group name.
798 * If the name exists and is one of our names then check the
799 * registering IP address. If it's not one of ours then automatically
800 * reject without doing the query - we know we will reject it.
803 if((namerec != NULL) && (is_myname(namerec->name.name)) )
805 if(!ismyip(from_ip))
807 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
808 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
809 send_wins_name_registration_response(RFS_ERR, 0, p);
810 return;
812 else
815 * It's one of our names and one of our IP's - update the ttl.
817 update_name_ttl(namerec, ttl);
818 send_wins_name_registration_response(0, ttl, p);
819 wins_hook("refresh", namerec, ttl);
820 return;
825 * If the name exists and it is a unique registration and the registering IP
826 * is the same as the the (single) already registered IP then just update the ttl.
829 if( !registering_group_name
830 && (namerec != NULL)
831 && (namerec->data.num_ips == 1)
832 && ip_equal( namerec->data.ip[0], from_ip ) )
834 update_name_ttl( namerec, ttl );
835 send_wins_name_registration_response( 0, ttl, p );
836 wins_hook("refresh", namerec, ttl);
837 return;
841 * Finally if the name exists do a query to the registering machine
842 * to see if they still claim to have the name.
845 if( namerec != NULL )
847 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
848 struct userdata_struct *userdata = (struct userdata_struct *)ud;
851 * First send a WACK to the registering machine.
854 send_wins_wack_response(60, p);
857 * When the reply comes back we need the original packet.
858 * Lock this so it won't be freed and then put it into
859 * the userdata structure.
862 p->locked = True;
864 userdata = (struct userdata_struct *)ud;
866 userdata->copy_fn = NULL;
867 userdata->free_fn = NULL;
868 userdata->userdata_len = sizeof(struct packet_struct *);
869 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
872 * Use the new call to send a query directly to an IP address.
873 * This sends the query directly to the IP address, and ensures
874 * the recursion desired flag is not set (you were right Luke :-).
875 * This function should *only* be called from the WINS server
876 * code. JRA.
879 query_name_from_wins_server( *namerec->data.ip,
880 question->name,
881 question->name_type,
882 wins_register_query_success,
883 wins_register_query_fail,
884 userdata );
885 return;
889 * Name did not exist - add it.
892 (void)add_name_to_subnet( subrec, question->name, question->name_type,
893 nb_flags, ttl, REGISTER_NAME, 1, &from_ip );
894 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
895 wins_hook("add", namerec, ttl);
898 send_wins_name_registration_response(0, ttl, p);
901 /***********************************************************************
902 Deal with a mutihomed name query success to the machine that
903 requested the multihomed name registration.
905 We have a locked pointer to the original packet stashed away in the
906 userdata pointer.
907 ************************************************************************/
909 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
910 struct userdata_struct *userdata,
911 struct nmb_name *question_name,
912 struct in_addr ip,
913 struct res_rec *answers)
915 struct packet_struct *orig_reg_packet;
916 struct nmb_packet *nmb;
917 struct name_record *namerec = NULL;
918 struct in_addr from_ip;
919 int ttl;
921 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
923 nmb = &orig_reg_packet->packet.nmb;
925 putip((char *)&from_ip,&nmb->additional->rdata[2]);
926 ttl = get_ttl_from_packet(nmb);
929 * We want to just add the new IP, as we now know the requesting
930 * machine claims to own it. But we can't just do that as an arbitary
931 * amount of time may have taken place between the name query
932 * request and this response. So we check that
933 * the name still exists and is in the same state - if so
934 * we just add the extra IP and update the ttl.
937 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
939 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) )
941 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
942 a subsequent IP addess.\n", nmb_namestr(question_name) ));
943 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
945 orig_reg_packet->locked = False;
946 free_packet(orig_reg_packet);
948 return;
951 if(!find_ip_in_name_record(namerec, from_ip))
952 add_ip_to_name_record(namerec, from_ip);
953 update_name_ttl(namerec, ttl);
954 send_wins_name_registration_response(0, ttl, orig_reg_packet);
955 wins_hook("add", namerec, ttl);
957 orig_reg_packet->locked = False;
958 free_packet(orig_reg_packet);
961 /***********************************************************************
962 Deal with a name registration request query failure to a client that
963 owned the name.
965 We have a locked pointer to the original packet stashed away in the
966 userdata pointer.
967 ************************************************************************/
969 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
970 struct response_record *rrec,
971 struct nmb_name *question_name,
972 int rcode)
974 struct userdata_struct *userdata = rrec->userdata;
975 struct packet_struct *orig_reg_packet;
977 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
979 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
980 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
981 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
983 orig_reg_packet->locked = False;
984 free_packet(orig_reg_packet);
985 return;
988 /***********************************************************************
989 Deal with a multihomed name registration request to a WINS server.
990 These cannot be group name registrations.
991 ***********************************************************************/
993 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
994 struct packet_struct *p)
996 struct nmb_packet *nmb = &p->packet.nmb;
997 struct nmb_name *question = &nmb->question.question_name;
998 BOOL bcast = nmb->header.nm_flags.bcast;
999 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1000 int ttl = get_ttl_from_packet(nmb);
1001 struct name_record *namerec = NULL;
1002 struct in_addr from_ip;
1003 BOOL group = (nb_flags & NB_GROUP) ? True : False;;
1005 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1007 if(bcast)
1010 * We should only get unicast name registration packets here.
1011 * Anyone trying to register broadcast should not be going to a WINS
1012 * server. Log an error here.
1015 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1016 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1017 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1018 return;
1022 * Only unique names should be registered multihomed.
1025 if(group)
1027 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1028 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1029 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1030 return;
1033 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1034 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1037 * Deal with policy regarding 0x1d names.
1040 if(question->name_type == 0x1d)
1042 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1043 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1044 send_wins_name_registration_response(0, ttl, p);
1045 return;
1049 * See if the name already exists.
1052 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1055 * Deal with the case where the name found was a dns entry.
1056 * Remove it as we now have a NetBIOS client registering the
1057 * name.
1060 if( (namerec != NULL)
1061 && ( (namerec->data.source == DNS_NAME)
1062 || (namerec->data.source == DNSFAIL_NAME) ) )
1064 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1065 - removing it.\n", nmb_namestr(question) ));
1066 remove_name_from_namelist( subrec, namerec);
1067 namerec = NULL;
1071 * Reject if the name exists and is not a REGISTER_NAME.
1072 * (ie. Don't allow any static names to be overwritten.
1075 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) )
1077 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1078 to register name %s. Name already exists in WINS with source type %d.\n",
1079 nmb_namestr(question), namerec->data.source ));
1080 send_wins_name_registration_response(RFS_ERR, 0, p);
1081 return;
1085 * Reject if the name exists and is a GROUP name.
1088 if((namerec != NULL) && NAME_GROUP(namerec))
1090 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1091 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1092 send_wins_name_registration_response(RFS_ERR, 0, p);
1093 return;
1097 * From here on down we know that if the name exists in the WINS db it is
1098 * a unique name, not a group name.
1102 * If the name exists and is one of our names then check the
1103 * registering IP address. If it's not one of ours then automatically
1104 * reject without doing the query - we know we will reject it.
1107 if((namerec != NULL) && (is_myname(namerec->name.name)) )
1109 if(!ismyip(from_ip))
1111 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1112 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1113 send_wins_name_registration_response(RFS_ERR, 0, p);
1114 return;
1116 else
1119 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1120 * update the ttl.
1122 if(!find_ip_in_name_record(namerec, from_ip)) {
1123 add_ip_to_name_record(namerec, from_ip);
1124 wins_hook("add", namerec, ttl);
1125 } else {
1126 wins_hook("refresh", namerec, ttl);
1129 update_name_ttl(namerec, ttl);
1130 send_wins_name_registration_response(0, ttl, p);
1131 return;
1136 * If the name exists check if the IP address is already registered
1137 * to that name. If so then update the ttl and reply success.
1140 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip))
1142 update_name_ttl(namerec, ttl);
1143 send_wins_name_registration_response(0, ttl, p);
1144 wins_hook("refresh", namerec, ttl);
1145 return;
1149 * If the name exists do a query to the owner
1150 * to see if they still want the name.
1153 if(namerec != NULL)
1155 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1156 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1159 * First send a WACK to the registering machine.
1162 send_wins_wack_response(60, p);
1165 * When the reply comes back we need the original packet.
1166 * Lock this so it won't be freed and then put it into
1167 * the userdata structure.
1170 p->locked = True;
1172 userdata = (struct userdata_struct *)ud;
1174 userdata->copy_fn = NULL;
1175 userdata->free_fn = NULL;
1176 userdata->userdata_len = sizeof(struct packet_struct *);
1177 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1180 * Use the new call to send a query directly to an IP address.
1181 * This sends the query directly to the IP address, and ensures
1182 * the recursion desired flag is not set (you were right Luke :-).
1183 * This function should *only* be called from the WINS server
1184 * code. JRA.
1185 * Note that this packet is sent to the current owner of the name,
1186 * not the person who sent the packet.
1189 query_name_from_wins_server( namerec->data.ip[0],
1190 question->name,
1191 question->name_type,
1192 wins_multihomed_register_query_success,
1193 wins_multihomed_register_query_fail,
1194 userdata );
1196 return;
1200 * Name did not exist - add it.
1203 (void)add_name_to_subnet( subrec, question->name, question->name_type,
1204 nb_flags, ttl, REGISTER_NAME, 1, &from_ip );
1206 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1207 wins_hook("add", namerec, ttl);
1210 send_wins_name_registration_response(0, ttl, p);
1213 /***********************************************************************
1214 Deal with the special name query for *<1b>.
1215 ***********************************************************************/
1217 static void process_wins_dmb_query_request(struct subnet_record *subrec,
1218 struct packet_struct *p)
1220 struct name_record *namerec = NULL;
1221 char *prdata;
1222 int num_ips;
1225 * Go through all the names in the WINS db looking for those
1226 * ending in <1b>. Use this to calculate the number of IP
1227 * addresses we need to return.
1230 num_ips = 0;
1231 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1232 namerec;
1233 namerec = (struct name_record *)ubi_trNext( namerec ) )
1235 if( namerec->name.name_type == 0x1b )
1236 num_ips += namerec->data.num_ips;
1239 if(num_ips == 0)
1242 * There are no 0x1b names registered. Return name query fail.
1244 send_wins_name_query_response(NAM_ERR, p, NULL);
1245 return;
1248 if((prdata = (char *)malloc( num_ips * 6 )) == NULL)
1250 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1251 return;
1255 * Go through all the names again in the WINS db looking for those
1256 * ending in <1b>. Add their IP addresses into the list we will
1257 * return.
1260 num_ips = 0;
1261 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1262 namerec;
1263 namerec = (struct name_record *)ubi_trNext( namerec ) )
1265 if(namerec->name.name_type == 0x1b)
1267 int i;
1268 for(i = 0; i < namerec->data.num_ips; i++)
1270 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1271 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1272 num_ips++;
1278 * Send back the reply containing the IP list.
1281 reply_netbios_packet(p, /* Packet to reply to. */
1282 0, /* Result code. */
1283 WINS_QUERY, /* nmbd type code. */
1284 NMB_NAME_QUERY_OPCODE, /* opcode. */
1285 lp_min_wins_ttl(), /* ttl. */
1286 prdata, /* data to send. */
1287 num_ips*6); /* data length. */
1289 free(prdata);
1292 /****************************************************************************
1293 Send a WINS name query response.
1294 **************************************************************************/
1296 void send_wins_name_query_response(int rcode, struct packet_struct *p,
1297 struct name_record *namerec)
1299 char rdata[6];
1300 char *prdata = rdata;
1301 int reply_data_len = 0;
1302 int ttl = 0;
1303 int i;
1305 memset(rdata,'\0',6);
1307 if(rcode == 0)
1309 ttl = (namerec->data.death_time != PERMANENT_TTL) ?
1310 namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1312 /* Copy all known ip addresses into the return data. */
1313 /* Optimise for the common case of one IP address so
1314 we don't need a malloc. */
1316 if( namerec->data.num_ips == 1 )
1317 prdata = rdata;
1318 else
1320 if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL)
1322 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1323 return;
1327 for(i = 0; i < namerec->data.num_ips; i++)
1329 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
1330 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
1333 sort_query_replies(prdata, i, p->ip);
1335 reply_data_len = namerec->data.num_ips * 6;
1338 reply_netbios_packet(p, /* Packet to reply to. */
1339 rcode, /* Result code. */
1340 WINS_QUERY, /* nmbd type code. */
1341 NMB_NAME_QUERY_OPCODE, /* opcode. */
1342 ttl, /* ttl. */
1343 prdata, /* data to send. */
1344 reply_data_len); /* data length. */
1346 if((prdata != rdata) && (prdata != NULL))
1347 free(prdata);
1350 /***********************************************************************
1351 Deal with a name query.
1352 ***********************************************************************/
1354 void wins_process_name_query_request(struct subnet_record *subrec,
1355 struct packet_struct *p)
1357 struct nmb_packet *nmb = &p->packet.nmb;
1358 struct nmb_name *question = &nmb->question.question_name;
1359 struct name_record *namerec = NULL;
1361 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
1362 nmb_namestr(question), inet_ntoa(p->ip) ));
1365 * Special name code. If the queried name is *<1b> then search
1366 * the entire WINS database and return a list of all the IP addresses
1367 * registered to any <1b> name. This is to allow domain master browsers
1368 * to discover other domains that may not have a presence on their subnet.
1371 if(strequal( question->name, "*") && (question->name_type == 0x1b))
1373 process_wins_dmb_query_request( subrec, p);
1374 return;
1377 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1379 if(namerec != NULL)
1382 * If it's a DNSFAIL_NAME then reply name not found.
1385 if( namerec->data.source == DNSFAIL_NAME )
1387 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
1388 nmb_namestr(question) ));
1389 send_wins_name_query_response(NAM_ERR, p, namerec);
1390 return;
1394 * If the name has expired then reply name not found.
1397 if( (namerec->data.death_time != PERMANENT_TTL)
1398 && (namerec->data.death_time < p->timestamp) )
1400 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1401 nmb_namestr(question) ));
1402 send_wins_name_query_response(NAM_ERR, p, namerec);
1403 return;
1406 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
1407 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
1409 send_wins_name_query_response(0, p, namerec);
1410 return;
1414 * Name not found in WINS - try a dns query if it's a 0x20 name.
1417 if(lp_dns_proxy() &&
1418 ((question->name_type == 0x20) || question->name_type == 0))
1421 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
1422 nmb_namestr(question) ));
1424 queue_dns_query(p, question, &namerec);
1425 return;
1429 * Name not found - return error.
1432 send_wins_name_query_response(NAM_ERR, p, NULL);
1435 /****************************************************************************
1436 Send a WINS name release response.
1437 **************************************************************************/
1439 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
1441 struct nmb_packet *nmb = &p->packet.nmb;
1442 char rdata[6];
1444 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
1446 reply_netbios_packet(p, /* Packet to reply to. */
1447 rcode, /* Result code. */
1448 NMB_REL, /* nmbd type code. */
1449 NMB_NAME_RELEASE_OPCODE, /* opcode. */
1450 0, /* ttl. */
1451 rdata, /* data to send. */
1452 6); /* data length. */
1455 /***********************************************************************
1456 Deal with a name release.
1457 ***********************************************************************/
1459 void wins_process_name_release_request(struct subnet_record *subrec,
1460 struct packet_struct *p)
1462 struct nmb_packet *nmb = &p->packet.nmb;
1463 struct nmb_name *question = &nmb->question.question_name;
1464 BOOL bcast = nmb->header.nm_flags.bcast;
1465 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1466 struct name_record *namerec = NULL;
1467 struct in_addr from_ip;
1468 BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
1470 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1472 if(bcast)
1475 * We should only get unicast name registration packets here.
1476 * Anyone trying to register broadcast should not be going to a WINS
1477 * server. Log an error here.
1480 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
1481 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1482 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1483 return;
1486 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
1487 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1490 * Deal with policy regarding 0x1d names.
1493 if(!releasing_group_name && (question->name_type == 0x1d))
1495 DEBUG(3,("wins_process_name_release_request: Ignoring request \
1496 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1497 send_wins_name_release_response(0, p);
1498 return;
1502 * See if the name already exists.
1505 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1507 if( (namerec == NULL)
1508 || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) )
1510 send_wins_name_release_response(NAM_ERR, p);
1511 return;
1515 * Check that the sending machine has permission to release this name.
1516 * If it's a group name not ending in 0x1c then just say yes and let
1517 * the group time out.
1520 if(releasing_group_name && (question->name_type != 0x1c))
1522 send_wins_name_release_response(0, p);
1523 return;
1527 * Check that the releasing node is on the list of IP addresses
1528 * for this name. Disallow the release if not.
1531 if(!find_ip_in_name_record(namerec, from_ip))
1533 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1534 release name %s as IP %s is not one of the known IP's for this name.\n",
1535 nmb_namestr(question), inet_ntoa(from_ip) ));
1536 send_wins_name_release_response(NAM_ERR, p);
1537 return;
1541 * Release the name and then remove the IP from the known list.
1544 send_wins_name_release_response(0, p);
1545 remove_ip_from_name_record(namerec, from_ip);
1547 wins_hook("delete", namerec, 0);
1550 * Remove the name entirely if no IP addresses left.
1552 if (namerec->data.num_ips == 0)
1553 remove_name_from_namelist(subrec, namerec);
1557 /*******************************************************************
1558 WINS time dependent processing.
1559 ******************************************************************/
1561 void initiate_wins_processing(time_t t)
1563 static time_t lasttime = 0;
1565 if (!lasttime)
1566 lasttime = t;
1567 if (t - lasttime < 20)
1568 return;
1570 lasttime = t;
1572 if(!lp_we_are_a_wins_server())
1573 return;
1575 expire_names_on_subnet(wins_server_subnet, t);
1577 if(wins_server_subnet->namelist_changed)
1578 wins_write_database(True);
1580 wins_server_subnet->namelist_changed = False;
1583 /*******************************************************************
1584 Write out the current WINS database.
1585 ******************************************************************/
1586 void wins_write_database(BOOL background)
1588 struct name_record *namerec;
1589 pstring fname, fnamenew;
1591 FILE *fp;
1593 if(!lp_we_are_a_wins_server())
1594 return;
1596 /* we will do the writing in a child process to ensure that the parent
1597 doesn't block while this is done */
1598 if (background) {
1599 CatchChild();
1600 if (fork()) {
1601 return;
1605 slprintf(fname,sizeof(fname),"%s/%s", lp_lockdir(), WINS_LIST);
1606 all_string_sub(fname,"//", "/", 0);
1607 slprintf(fnamenew,sizeof(fnamenew),"%s.%u", fname, (unsigned int)getpid());
1609 if((fp = sys_fopen(fnamenew,"w")) == NULL)
1611 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
1612 if (background) {
1613 _exit(0);
1615 return;
1618 DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
1620 fprintf(fp,"VERSION %d %u\n", WINS_VERSION, wins_hash());
1622 for( namerec
1623 = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
1624 namerec;
1625 namerec = (struct name_record *)ubi_trNext( namerec ) )
1627 int i;
1628 struct tm *tm;
1630 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
1632 if( namerec->data.death_time != PERMANENT_TTL )
1634 char *ts, *nl;
1636 tm = LocalTime(&namerec->data.death_time);
1637 ts = asctime(tm);
1638 nl = strrchr( ts, '\n' );
1639 if( NULL != nl )
1640 *nl = '\0';
1641 DEBUGADD(4,("TTL = %s ", ts ));
1643 else
1644 DEBUGADD(4,("TTL = PERMANENT "));
1646 for (i = 0; i < namerec->data.num_ips; i++)
1647 DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
1648 DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
1650 if( namerec->data.source == REGISTER_NAME )
1652 fprintf(fp, "\"%s#%02x\" %d ",
1653 namerec->name.name,namerec->name.name_type, /* Ignore scope. */
1654 (int)namerec->data.death_time);
1656 for (i = 0; i < namerec->data.num_ips; i++)
1657 fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
1658 fprintf( fp, "%2xR\n", namerec->data.nb_flags );
1662 fclose(fp);
1663 chmod(fnamenew,0644);
1664 unlink(fname);
1665 rename(fnamenew,fname);
1666 if (background) {
1667 _exit(0);