use a precompiled grammer in pidl. This speeds up pidl by about a
[Samba/gebeck_regimport.git] / source / nmbd / nmbd_winsserver.c
blob4ef476f81416a15afc2b47a5e092db1878c0ae04
1 /*
2 Unix SMB/CIFS implementation.
3 NBT netbios routines and daemon - version 2
5 Copyright (C) Jeremy Allison 1994-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
25 #define WINS_LIST "wins.tdb"
26 #define WINS_VERSION 1
28 /****************************************************************************
29 change the wins owner address in the record.
30 *****************************************************************************/
31 static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip)
33 if (namerec==NULL)
34 return;
35 namerec->data.wins_ip=wins_ip;
38 /****************************************************************************
39 create the wins flags based on the nb flags and the input value.
40 *****************************************************************************/
41 static void update_wins_flag(struct name_record *namerec, int flags)
43 if (namerec==NULL)
44 return;
46 namerec->data.wins_flags=0x0;
48 /* if it's a group, it can be a normal or a special one */
49 if (namerec->data.nb_flags & NB_GROUP) {
50 if (namerec->name.name_type==0x1C)
51 namerec->data.wins_flags|=WINS_SGROUP;
52 else
53 if (namerec->data.num_ips>1)
54 namerec->data.wins_flags|=WINS_SGROUP;
55 else
56 namerec->data.wins_flags|=WINS_NGROUP;
57 } else {
58 /* can be unique or multi-homed */
59 if (namerec->data.num_ips>1)
60 namerec->data.wins_flags|=WINS_MHOMED;
61 else
62 namerec->data.wins_flags|=WINS_UNIQUE;
65 /* the node type are the same bits */
66 namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK;
68 /* the static bit is elsewhere */
69 if (namerec->data.death_time == PERMANENT_TTL)
70 namerec->data.wins_flags|=WINS_STATIC;
72 /* and add the given bits */
73 namerec->data.wins_flags|=flags;
75 DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n",
76 namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags));
80 /****************************************************************************
81 return the general ID value and increase it if requested
82 *****************************************************************************/
83 static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update)
86 * it's kept as a static here, to prevent people from messing
87 * with the value directly
90 static SMB_BIG_UINT general_id = 1;
92 DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id));
94 *current_id = general_id;
96 if (update)
97 general_id++;
100 /****************************************************************************
101 possibly call the WINS hook external program when a WINS change is made
102 *****************************************************************************/
103 static void wins_hook(const char *operation, struct name_record *namerec, int ttl)
105 pstring command;
106 char *cmd = lp_wins_hook();
107 char *p;
108 int i;
110 if (!cmd || !*cmd) return;
112 for (p=namerec->name.name; *p; p++) {
113 if (!(isalnum((int)*p) || strchr_m("._-",*p))) {
114 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
115 return;
119 p = command;
120 p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d",
121 cmd,
122 operation,
123 namerec->name.name,
124 namerec->name.name_type,
125 ttl);
127 for (i=0;i<namerec->data.num_ips;i++) {
128 p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.ip[i]));
131 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
132 smbrun(command, NULL);
136 /****************************************************************************
137 Determine if this packet should be allocated to the WINS server.
138 *****************************************************************************/
140 BOOL packet_is_for_wins_server(struct packet_struct *packet)
142 struct nmb_packet *nmb = &packet->packet.nmb;
144 /* Only unicast packets go to a WINS server. */
145 if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True))
147 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
148 return False;
151 /* Check for node status requests. */
152 if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY)
153 return False;
155 switch(nmb->header.opcode)
158 * A WINS server issues WACKS, not receives them.
160 case NMB_WACK_OPCODE:
161 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
162 return False;
164 * A WINS server only processes registration and
165 * release requests, not responses.
167 case NMB_NAME_REG_OPCODE:
168 case NMB_NAME_MULTIHOMED_REG_OPCODE:
169 case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
170 case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
171 if(nmb->header.response)
173 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
174 return False;
176 break;
178 case NMB_NAME_RELEASE_OPCODE:
179 if(nmb->header.response)
181 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
182 return False;
184 break;
187 * Only process unicast name queries with rd = 1.
189 case NMB_NAME_QUERY_OPCODE:
190 if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired)
192 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
193 return False;
195 break;
198 return True;
201 /****************************************************************************
202 Utility function to decide what ttl to give a register/refresh request.
203 *****************************************************************************/
205 static int get_ttl_from_packet(struct nmb_packet *nmb)
207 int ttl = nmb->additional->ttl;
209 if(ttl < lp_min_wins_ttl() )
210 ttl = lp_min_wins_ttl();
212 if(ttl > lp_max_wins_ttl() )
213 ttl = lp_max_wins_ttl();
215 return ttl;
218 /****************************************************************************
219 Load or create the WINS database.
220 *****************************************************************************/
222 BOOL initialise_wins(void)
224 time_t time_now = time(NULL);
225 TDB_CONTEXT *tdb;
226 TDB_DATA kbuf, dbuf, newkey;
227 struct name_record *namerec = NULL;
228 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
230 DEBUG(2,("initialise_wins: started\n"));
232 if(!lp_we_are_a_wins_server())
233 return True;
235 add_samba_names_to_subnet(wins_server_subnet);
237 tdb = tdb_open_log(lock_path(WINS_LIST), 0, TDB_DEFAULT, O_RDONLY, 0600);
238 if (!tdb) {
239 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n", WINS_LIST, strerror(errno) ));
240 return True;
243 if (tdb_fetch_int32(tdb, INFO_VERSION) != WINS_VERSION) {
244 DEBUG(0,("Discarding invalid wins.dat file\n"));
245 tdb_close(tdb);
246 return True;
249 for (kbuf = tdb_firstkey(tdb);
250 kbuf.dptr;
251 newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
253 fstring name_type;
254 pstring name, ip_str;
255 char *p;
256 int type = 0;
257 int nb_flags;
258 int ttl;
259 unsigned int num_ips;
260 int high, low;
261 struct in_addr wins_ip;
262 struct in_addr *ip_list;
263 int wins_flags;
264 int len,i;
266 if (strncmp(kbuf.dptr, ENTRY_PREFIX, strlen(ENTRY_PREFIX)) != 0)
267 continue;
269 dbuf = tdb_fetch(tdb, kbuf);
270 if (!dbuf.dptr)
271 continue;
273 fstrcpy(name_type, kbuf.dptr+strlen(ENTRY_PREFIX));
275 pstrcpy(name, name_type);
277 if((p = strchr(name,'#')) != NULL) {
278 *p = 0;
279 sscanf(p+1,"%x",&type);
282 len = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddfddd",
283 &nb_flags, &high, &low,
284 ip_str, &ttl, &num_ips, &wins_flags);
286 wins_ip=*interpret_addr2(ip_str);
288 /* Don't reload replica records */
289 if (!ip_equal(wins_ip, our_fake_ip)) {
290 SAFE_FREE(dbuf.dptr);
291 continue;
294 /* Don't reload released or tombstoned records */
295 if ((wins_flags&WINS_STATE_MASK) != WINS_ACTIVE) {
296 SAFE_FREE(dbuf.dptr);
297 continue;
300 /* Allocate the space for the ip_list. */
301 if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL) {
302 SAFE_FREE(dbuf.dptr);
303 DEBUG(0,("initialise_wins: Malloc fail !\n"));
304 return False;
307 for (i = 0; i < num_ips; i++) {
308 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f", ip_str);
309 ip_list[i] = *interpret_addr2(ip_str);
312 /* add all entries that have 60 seconds or more to live */
313 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {
314 if(ttl != PERMANENT_TTL)
315 ttl -= time_now;
317 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
318 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
320 namerec=add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
321 ttl, REGISTER_NAME, num_ips, ip_list);
322 if (namerec!=NULL) {
323 update_wins_owner(namerec, wins_ip);
324 update_wins_flag(namerec, wins_flags);
325 /* we don't reload the ID, on startup we restart at 1 */
326 get_global_id_and_update(&namerec->data.id, True);
329 } else {
330 DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n",
331 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
334 SAFE_FREE(dbuf.dptr);
335 SAFE_FREE(ip_list);
338 tdb_close(tdb);
339 DEBUG(2,("initialise_wins: done\n"));
340 return True;
343 /****************************************************************************
344 Send a WINS WACK (Wait ACKnowledgement) response.
345 **************************************************************************/
347 static void send_wins_wack_response(int ttl, struct packet_struct *p)
349 struct nmb_packet *nmb = &p->packet.nmb;
350 unsigned char rdata[2];
352 rdata[0] = rdata[1] = 0;
354 /* Taken from nmblib.c - we need to send back almost
355 identical bytes from the requesting packet header. */
357 rdata[0] = (nmb->header.opcode & 0xF) << 3;
358 if (nmb->header.nm_flags.authoritative &&
359 nmb->header.response) rdata[0] |= 0x4;
360 if (nmb->header.nm_flags.trunc) rdata[0] |= 0x2;
361 if (nmb->header.nm_flags.recursion_desired) rdata[0] |= 0x1;
362 if (nmb->header.nm_flags.recursion_available &&
363 nmb->header.response) rdata[1] |= 0x80;
364 if (nmb->header.nm_flags.bcast) rdata[1] |= 0x10;
366 reply_netbios_packet(p, /* Packet to reply to. */
367 0, /* Result code. */
368 NMB_WAIT_ACK, /* nmbd type code. */
369 NMB_WACK_OPCODE, /* opcode. */
370 ttl, /* ttl. */
371 (char *)rdata, /* data to send. */
372 2); /* data length. */
375 /****************************************************************************
376 Send a WINS name registration response.
377 **************************************************************************/
379 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
381 struct nmb_packet *nmb = &p->packet.nmb;
382 char rdata[6];
384 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
386 reply_netbios_packet(p, /* Packet to reply to. */
387 rcode, /* Result code. */
388 WINS_REG, /* nmbd type code. */
389 NMB_NAME_REG_OPCODE, /* opcode. */
390 ttl, /* ttl. */
391 rdata, /* data to send. */
392 6); /* data length. */
395 /***********************************************************************
396 Deal with a name refresh request to a WINS server.
397 ************************************************************************/
399 void wins_process_name_refresh_request(struct subnet_record *subrec,
400 struct packet_struct *p)
402 struct nmb_packet *nmb = &p->packet.nmb;
403 struct nmb_name *question = &nmb->question.question_name;
404 BOOL bcast = nmb->header.nm_flags.bcast;
405 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
406 BOOL group = (nb_flags & NB_GROUP) ? True : False;
407 struct name_record *namerec = NULL;
408 int ttl = get_ttl_from_packet(nmb);
409 struct in_addr from_ip;
410 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
412 putip((char *)&from_ip,&nmb->additional->rdata[2]);
414 if(bcast)
417 * We should only get unicast name refresh packets here.
418 * Anyone trying to refresh broadcast should not be going to a WINS
419 * server. Log an error here.
422 DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh request \
423 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
424 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
425 return;
428 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \
429 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
432 * See if the name already exists.
435 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
438 * If this is a refresh request and the name doesn't exist then
439 * treat it like a registration request. This allows us to recover
440 * from errors (tridge)
443 if(namerec == NULL)
445 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \
446 the name does not exist. Treating as registration.\n", nmb_namestr(question) ));
447 wins_process_name_registration_request(subrec,p);
448 return;
452 * if the name is present but not active,
453 * simply remove it and treat the request
454 * as a registration
456 if (namerec != NULL && !WINS_STATE_ACTIVE(namerec))
458 DEBUG(5,("wins_process_name_refresh_request: Name (%s) in WINS was \
459 not active - removing it.\n", nmb_namestr(question) ));
460 remove_name_from_namelist( subrec, namerec );
461 namerec = NULL;
462 wins_process_name_registration_request(subrec,p);
463 return;
467 * Check that the group bits for the refreshing name and the
468 * name in our database match.
471 if((namerec != NULL) && ((group && !NAME_GROUP(namerec)) || (!group && NAME_GROUP(namerec))) )
473 DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \
474 does not match group bit in WINS for this name.\n", nmb_namestr(question), group ? "True" : "False" ));
475 send_wins_name_registration_response(RFS_ERR, 0, p);
476 return;
480 * For a unique name check that the person refreshing the name is one of the registered IP
481 * addresses. If not - fail the refresh. Do the same for group names with a type of 0x1c.
482 * Just return success for unique 0x1d refreshes. For normal group names update the ttl
483 * and return success.
486 if((!group || (group && (question->name_type == 0x1c))) && find_ip_in_name_record(namerec, from_ip ))
489 * Update the ttl.
491 update_name_ttl(namerec, ttl);
494 * if the record is a replica:
495 * we take ownership and update the version ID.
497 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
498 update_wins_owner(namerec, our_fake_ip);
499 get_global_id_and_update(&namerec->data.id, True);
502 send_wins_name_registration_response(0, ttl, p);
503 wins_hook("refresh", namerec, ttl);
504 return;
506 else if(group)
509 * Normal groups are all registered with an IP address of 255.255.255.255
510 * so we can't search for the IP address.
512 update_name_ttl(namerec, ttl);
513 send_wins_name_registration_response(0, ttl, p);
514 return;
516 else if(!group && (question->name_type == 0x1d))
519 * Special name type - just pretend the refresh succeeded.
521 send_wins_name_registration_response(0, ttl, p);
522 return;
524 else
527 * Fail the refresh.
530 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \
531 is IP is not known to the name.\n", nmb_namestr(question), inet_ntoa(from_ip) ));
532 send_wins_name_registration_response(RFS_ERR, 0, p);
533 return;
537 /***********************************************************************
538 Deal with a name registration request query success to a client that
539 owned the name.
541 We have a locked pointer to the original packet stashed away in the
542 userdata pointer. The success here is actually a failure as it means
543 the client we queried wants to keep the name, so we must return
544 a registration failure to the original requestor.
545 ************************************************************************/
547 static void wins_register_query_success(struct subnet_record *subrec,
548 struct userdata_struct *userdata,
549 struct nmb_name *question_name,
550 struct in_addr ip,
551 struct res_rec *answers)
553 struct packet_struct *orig_reg_packet;
555 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
557 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
558 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
560 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
562 orig_reg_packet->locked = False;
563 free_packet(orig_reg_packet);
566 /***********************************************************************
567 Deal with a name registration request query failure to a client that
568 owned the name.
570 We have a locked pointer to the original packet stashed away in the
571 userdata pointer. The failure here is actually a success as it means
572 the client we queried didn't want to keep the name, so we can remove
573 the old name record and then successfully add the new name.
574 ************************************************************************/
576 static void wins_register_query_fail(struct subnet_record *subrec,
577 struct response_record *rrec,
578 struct nmb_name *question_name,
579 int rcode)
581 struct userdata_struct *userdata = rrec->userdata;
582 struct packet_struct *orig_reg_packet;
583 struct name_record *namerec = NULL;
585 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
588 * We want to just add the name, as we now know the original owner
589 * didn't want it. But we can't just do that as an arbitary
590 * amount of time may have taken place between the name query
591 * request and this timeout/error response. So we check that
592 * the name still exists and is in the same state - if so
593 * we remove it and call wins_process_name_registration_request()
594 * as we know it will do the right thing now.
597 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
599 if( (namerec != NULL)
600 && (namerec->data.source == REGISTER_NAME)
601 && ip_equal(rrec->packet->ip, *namerec->data.ip) )
603 remove_name_from_namelist( subrec, namerec);
604 namerec = NULL;
607 if(namerec == NULL)
608 wins_process_name_registration_request(subrec, orig_reg_packet);
609 else
610 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \
611 querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) ));
613 orig_reg_packet->locked = False;
614 free_packet(orig_reg_packet);
617 /***********************************************************************
618 Deal with a name registration request to a WINS server.
620 Use the following pseudocode :
622 registering_group
625 +--------name exists
628 | +--- existing name is group
629 | | |
630 | | |
631 | | +--- add name (return).
634 | +--- exiting name is unique
637 | +--- query existing owner (return).
640 +--------name doesn't exist
643 +--- add name (return).
645 registering_unique
648 +--------name exists
651 | +--- existing name is group
652 | | |
653 | | |
654 | | +--- fail add (return).
655 | |
657 | +--- exiting name is unique
660 | +--- query existing owner (return).
663 +--------name doesn't exist
666 +--- add name (return).
668 As can be seen from the above, the two cases may be collapsed onto each
669 other with the exception of the case where the name already exists and
670 is a group name. This case we handle with an if statement.
672 ************************************************************************/
674 void wins_process_name_registration_request(struct subnet_record *subrec,
675 struct packet_struct *p)
677 struct nmb_packet *nmb = &p->packet.nmb;
678 struct nmb_name *question = &nmb->question.question_name;
679 BOOL bcast = nmb->header.nm_flags.bcast;
680 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
681 int ttl = get_ttl_from_packet(nmb);
682 struct name_record *namerec = NULL;
683 struct in_addr from_ip;
684 BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;
685 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
687 putip((char *)&from_ip,&nmb->additional->rdata[2]);
689 if(bcast)
692 * We should only get unicast name registration packets here.
693 * Anyone trying to register broadcast should not be going to a WINS
694 * server. Log an error here.
697 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
698 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
699 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
700 return;
703 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
704 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
707 * See if the name already exists.
710 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
713 * if the record exists but NOT in active state,
714 * consider it dead.
716 if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec))
718 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
719 not active - removing it.\n", nmb_namestr(question) ));
720 remove_name_from_namelist( subrec, namerec );
721 namerec = NULL;
725 * Deal with the case where the name found was a dns entry.
726 * Remove it as we now have a NetBIOS client registering the
727 * name.
730 if( (namerec != NULL)
731 && ( (namerec->data.source == DNS_NAME)
732 || (namerec->data.source == DNSFAIL_NAME) ) )
734 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
735 a dns lookup - removing it.\n", nmb_namestr(question) ));
736 remove_name_from_namelist( subrec, namerec );
737 namerec = NULL;
741 * Reject if the name exists and is not a REGISTER_NAME.
742 * (ie. Don't allow any static names to be overwritten.
745 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME))
747 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
748 to register name %s. Name already exists in WINS with source type %d.\n",
749 nmb_namestr(question), namerec->data.source ));
750 send_wins_name_registration_response(RFS_ERR, 0, p);
751 return;
755 * Special policy decisions based on MS documentation.
756 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
757 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
761 * A group name is always added as the local broadcast address, except
762 * for group names ending in 0x1c.
763 * Group names with type 0x1c are registered with individual IP addresses.
766 if(registering_group_name && (question->name_type != 0x1c))
767 from_ip = *interpret_addr2("255.255.255.255");
770 * Ignore all attempts to register a unique 0x1d name, although return success.
773 if(!registering_group_name && (question->name_type == 0x1d))
775 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
776 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
777 send_wins_name_registration_response(0, ttl, p);
778 return;
782 * Next two cases are the 'if statement' mentioned above.
785 if((namerec != NULL) && NAME_GROUP(namerec))
787 if(registering_group_name)
790 * If we are adding a group name, the name exists and is also a group entry just add this
791 * IP address to it and update the ttl.
794 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
795 inet_ntoa(from_ip), nmb_namestr(question) ));
797 * Check the ip address is not already in the group.
799 if(!find_ip_in_name_record(namerec, from_ip)) {
800 add_ip_to_name_record(namerec, from_ip);
801 /* we need to update the record for replication */
802 get_global_id_and_update(&namerec->data.id, True);
805 * if the record is a replica, we must change
806 * the wins owner to us to make the replication updates
807 * it on the other wins servers.
808 * And when the partner will receive this record,
809 * it will update its own record.
812 update_wins_owner(namerec, our_fake_ip);
815 update_name_ttl(namerec, ttl);
816 send_wins_name_registration_response(0, ttl, p);
817 return;
819 else
822 * If we are adding a unique name, the name exists in the WINS db
823 * and is a group name then reject the registration.
825 * explanation: groups have a higher priority than unique names.
828 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
829 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
830 send_wins_name_registration_response(RFS_ERR, 0, p);
831 return;
836 * From here on down we know that if the name exists in the WINS db it is
837 * a unique name, not a group name.
841 * If the name exists and is one of our names then check the
842 * registering IP address. If it's not one of ours then automatically
843 * reject without doing the query - we know we will reject it.
846 if((namerec != NULL) && (is_myname(namerec->name.name)) )
848 if(!ismyip(from_ip))
850 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
851 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
852 send_wins_name_registration_response(RFS_ERR, 0, p);
853 return;
855 else
858 * It's one of our names and one of our IP's - update the ttl.
860 update_name_ttl(namerec, ttl);
861 send_wins_name_registration_response(0, ttl, p);
862 wins_hook("refresh", namerec, ttl);
863 return;
868 * If the name exists and it is a unique registration and the registering IP
869 * is the same as the (single) already registered IP then just update the ttl.
871 * But not if the record is an active replica. IF it's a replica, it means it can be
872 * the same client which has moved and not yet expired. So we don't update
873 * the ttl in this case and go beyond to do a WACK and query the old client
876 if( !registering_group_name
877 && (namerec != NULL)
878 && (namerec->data.num_ips == 1)
879 && ip_equal( namerec->data.ip[0], from_ip )
880 && ip_equal(namerec->data.wins_ip, our_fake_ip) )
882 update_name_ttl( namerec, ttl );
883 send_wins_name_registration_response( 0, ttl, p );
884 wins_hook("refresh", namerec, ttl);
885 return;
889 * Finally if the name exists do a query to the registering machine
890 * to see if they still claim to have the name.
893 if( namerec != NULL )
895 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
896 struct userdata_struct *userdata = (struct userdata_struct *)ud;
899 * First send a WACK to the registering machine.
902 send_wins_wack_response(60, p);
905 * When the reply comes back we need the original packet.
906 * Lock this so it won't be freed and then put it into
907 * the userdata structure.
910 p->locked = True;
912 userdata = (struct userdata_struct *)ud;
914 userdata->copy_fn = NULL;
915 userdata->free_fn = NULL;
916 userdata->userdata_len = sizeof(struct packet_struct *);
917 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
920 * Use the new call to send a query directly to an IP address.
921 * This sends the query directly to the IP address, and ensures
922 * the recursion desired flag is not set (you were right Luke :-).
923 * This function should *only* be called from the WINS server
924 * code. JRA.
927 query_name_from_wins_server( *namerec->data.ip,
928 question->name,
929 question->name_type,
930 wins_register_query_success,
931 wins_register_query_fail,
932 userdata );
933 return;
937 * Name did not exist - add it.
940 (void)add_name_to_subnet( subrec, question->name, question->name_type,
941 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
942 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
943 get_global_id_and_update(&namerec->data.id, True);
944 update_wins_owner(namerec, our_fake_ip);
945 update_wins_flag(namerec, WINS_ACTIVE);
946 wins_hook("add", namerec, ttl);
949 send_wins_name_registration_response(0, ttl, p);
952 /***********************************************************************
953 Deal with a mutihomed name query success to the machine that
954 requested the multihomed name registration.
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_success(struct subnet_record *subrec,
961 struct userdata_struct *userdata,
962 struct nmb_name *question_name,
963 struct in_addr ip,
964 struct res_rec *answers)
966 struct packet_struct *orig_reg_packet;
967 struct nmb_packet *nmb;
968 struct name_record *namerec = NULL;
969 struct in_addr from_ip;
970 int ttl;
971 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
973 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
975 nmb = &orig_reg_packet->packet.nmb;
977 putip((char *)&from_ip,&nmb->additional->rdata[2]);
978 ttl = get_ttl_from_packet(nmb);
981 * We want to just add the new IP, as we now know the requesting
982 * machine claims to own it. But we can't just do that as an arbitary
983 * amount of time may have taken place between the name query
984 * request and this response. So we check that
985 * the name still exists and is in the same state - if so
986 * we just add the extra IP and update the ttl.
989 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
991 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) )
993 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
994 a subsequent IP address.\n", nmb_namestr(question_name) ));
995 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
997 orig_reg_packet->locked = False;
998 free_packet(orig_reg_packet);
1000 return;
1003 if(!find_ip_in_name_record(namerec, from_ip))
1004 add_ip_to_name_record(namerec, from_ip);
1006 get_global_id_and_update(&namerec->data.id, True);
1007 update_wins_owner(namerec, our_fake_ip);
1008 update_wins_flag(namerec, WINS_ACTIVE);
1009 update_name_ttl(namerec, ttl);
1010 send_wins_name_registration_response(0, ttl, orig_reg_packet);
1011 wins_hook("add", namerec, ttl);
1013 orig_reg_packet->locked = False;
1014 free_packet(orig_reg_packet);
1017 /***********************************************************************
1018 Deal with a name registration request query failure to a client that
1019 owned the name.
1021 We have a locked pointer to the original packet stashed away in the
1022 userdata pointer.
1023 ************************************************************************/
1025 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
1026 struct response_record *rrec,
1027 struct nmb_name *question_name,
1028 int rcode)
1030 struct userdata_struct *userdata = rrec->userdata;
1031 struct packet_struct *orig_reg_packet;
1033 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1035 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1036 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
1037 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1039 orig_reg_packet->locked = False;
1040 free_packet(orig_reg_packet);
1041 return;
1044 /***********************************************************************
1045 Deal with a multihomed name registration request to a WINS server.
1046 These cannot be group name registrations.
1047 ***********************************************************************/
1049 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
1050 struct packet_struct *p)
1052 struct nmb_packet *nmb = &p->packet.nmb;
1053 struct nmb_name *question = &nmb->question.question_name;
1054 BOOL bcast = nmb->header.nm_flags.bcast;
1055 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1056 int ttl = get_ttl_from_packet(nmb);
1057 struct name_record *namerec = NULL;
1058 struct in_addr from_ip;
1059 BOOL group = (nb_flags & NB_GROUP) ? True : False;
1060 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1062 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1064 if(bcast)
1067 * We should only get unicast name registration packets here.
1068 * Anyone trying to register broadcast should not be going to a WINS
1069 * server. Log an error here.
1072 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1073 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1074 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1075 return;
1079 * Only unique names should be registered multihomed.
1082 if(group)
1084 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1085 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1086 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1087 return;
1090 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1091 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1094 * Deal with policy regarding 0x1d names.
1097 if(question->name_type == 0x1d)
1099 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1100 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1101 send_wins_name_registration_response(0, ttl, p);
1102 return;
1106 * See if the name already exists.
1109 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1112 * if the record exists but NOT in active state,
1113 * consider it dead.
1115 if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1116 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question)));
1117 remove_name_from_namelist(subrec, namerec);
1118 namerec = NULL;
1122 * Deal with the case where the name found was a dns entry.
1123 * Remove it as we now have a NetBIOS client registering the
1124 * name.
1127 if( (namerec != NULL)
1128 && ( (namerec->data.source == DNS_NAME)
1129 || (namerec->data.source == DNSFAIL_NAME) ) )
1131 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1132 - removing it.\n", nmb_namestr(question) ));
1133 remove_name_from_namelist( subrec, namerec);
1134 namerec = NULL;
1138 * Reject if the name exists and is not a REGISTER_NAME.
1139 * (ie. Don't allow any static names to be overwritten.
1142 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) )
1144 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1145 to register name %s. Name already exists in WINS with source type %d.\n",
1146 nmb_namestr(question), namerec->data.source ));
1147 send_wins_name_registration_response(RFS_ERR, 0, p);
1148 return;
1152 * Reject if the name exists and is a GROUP name and is active.
1155 if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec))
1157 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1158 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1159 send_wins_name_registration_response(RFS_ERR, 0, p);
1160 return;
1164 * From here on down we know that if the name exists in the WINS db it is
1165 * a unique name, not a group name.
1169 * If the name exists and is one of our names then check the
1170 * registering IP address. If it's not one of ours then automatically
1171 * reject without doing the query - we know we will reject it.
1174 if((namerec != NULL) && (is_myname(namerec->name.name)) )
1176 if(!ismyip(from_ip))
1178 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1179 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1180 send_wins_name_registration_response(RFS_ERR, 0, p);
1181 return;
1183 else
1186 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1187 * update the ttl. Update the version ID to force replication.
1189 if(!find_ip_in_name_record(namerec, from_ip)) {
1190 get_global_id_and_update(&namerec->data.id, True);
1191 update_wins_owner(namerec, our_fake_ip);
1192 update_wins_flag(namerec, WINS_ACTIVE);
1194 add_ip_to_name_record(namerec, from_ip);
1195 wins_hook("add", namerec, ttl);
1196 } else {
1197 wins_hook("refresh", namerec, ttl);
1200 update_name_ttl(namerec, ttl);
1201 send_wins_name_registration_response(0, ttl, p);
1202 return;
1207 * If the name exists and is active, check if the IP address is already registered
1208 * to that name. If so then update the ttl and reply success.
1211 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec))
1213 update_name_ttl(namerec, ttl);
1215 * If it's a replica, we need to become the wins owner
1216 * to force the replication
1218 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1219 get_global_id_and_update(&namerec->data.id, True);
1220 update_wins_owner(namerec, our_fake_ip);
1221 update_wins_flag(namerec, WINS_ACTIVE);
1224 send_wins_name_registration_response(0, ttl, p);
1225 wins_hook("refresh", namerec, ttl);
1226 return;
1230 * If the name exists do a query to the owner
1231 * to see if they still want the name.
1234 if(namerec != NULL)
1236 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1237 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1240 * First send a WACK to the registering machine.
1243 send_wins_wack_response(60, p);
1246 * When the reply comes back we need the original packet.
1247 * Lock this so it won't be freed and then put it into
1248 * the userdata structure.
1251 p->locked = True;
1253 userdata = (struct userdata_struct *)ud;
1255 userdata->copy_fn = NULL;
1256 userdata->free_fn = NULL;
1257 userdata->userdata_len = sizeof(struct packet_struct *);
1258 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1261 * Use the new call to send a query directly to an IP address.
1262 * This sends the query directly to the IP address, and ensures
1263 * the recursion desired flag is not set (you were right Luke :-).
1264 * This function should *only* be called from the WINS server
1265 * code. JRA.
1267 * Note that this packet is sent to the current owner of the name,
1268 * not the person who sent the packet
1271 query_name_from_wins_server( namerec->data.ip[0],
1272 question->name,
1273 question->name_type,
1274 wins_multihomed_register_query_success,
1275 wins_multihomed_register_query_fail,
1276 userdata );
1278 return;
1282 * Name did not exist - add it.
1285 (void)add_name_to_subnet( subrec, question->name, question->name_type,
1286 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1288 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1289 get_global_id_and_update(&namerec->data.id, True);
1290 update_wins_owner(namerec, our_fake_ip);
1291 update_wins_flag(namerec, WINS_ACTIVE);
1292 wins_hook("add", namerec, ttl);
1295 send_wins_name_registration_response(0, ttl, p);
1298 /***********************************************************************
1299 Deal with the special name query for *<1b>.
1300 ***********************************************************************/
1302 static void process_wins_dmb_query_request(struct subnet_record *subrec,
1303 struct packet_struct *p)
1305 struct name_record *namerec = NULL;
1306 char *prdata;
1307 int num_ips;
1310 * Go through all the ACTIVE names in the WINS db looking for those
1311 * ending in <1b>. Use this to calculate the number of IP
1312 * addresses we need to return.
1315 num_ips = 0;
1316 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1317 namerec;
1318 namerec = (struct name_record *)ubi_trNext( namerec ) )
1320 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b )
1321 num_ips += namerec->data.num_ips;
1324 if(num_ips == 0)
1327 * There are no 0x1b names registered. Return name query fail.
1329 send_wins_name_query_response(NAM_ERR, p, NULL);
1330 return;
1333 if((prdata = (char *)malloc( num_ips * 6 )) == NULL)
1335 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1336 return;
1340 * Go through all the names again in the WINS db looking for those
1341 * ending in <1b>. Add their IP addresses into the list we will
1342 * return.
1345 num_ips = 0;
1346 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1347 namerec;
1348 namerec = (struct name_record *)ubi_trNext( namerec ) )
1350 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b)
1352 int i;
1353 for(i = 0; i < namerec->data.num_ips; i++)
1355 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1356 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1357 num_ips++;
1363 * Send back the reply containing the IP list.
1366 reply_netbios_packet(p, /* Packet to reply to. */
1367 0, /* Result code. */
1368 WINS_QUERY, /* nmbd type code. */
1369 NMB_NAME_QUERY_OPCODE, /* opcode. */
1370 lp_min_wins_ttl(), /* ttl. */
1371 prdata, /* data to send. */
1372 num_ips*6); /* data length. */
1374 SAFE_FREE(prdata);
1377 /****************************************************************************
1378 Send a WINS name query response.
1379 **************************************************************************/
1381 void send_wins_name_query_response(int rcode, struct packet_struct *p,
1382 struct name_record *namerec)
1384 char rdata[6];
1385 char *prdata = rdata;
1386 int reply_data_len = 0;
1387 int ttl = 0;
1388 int i;
1390 memset(rdata,'\0',6);
1392 if(rcode == 0)
1394 ttl = (namerec->data.death_time != PERMANENT_TTL) ?
1395 namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1397 /* Copy all known ip addresses into the return data. */
1398 /* Optimise for the common case of one IP address so
1399 we don't need a malloc. */
1401 if( namerec->data.num_ips == 1 )
1402 prdata = rdata;
1403 else
1405 if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL)
1407 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1408 return;
1412 for(i = 0; i < namerec->data.num_ips; i++)
1414 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
1415 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
1418 sort_query_replies(prdata, i, p->ip);
1420 reply_data_len = namerec->data.num_ips * 6;
1423 reply_netbios_packet(p, /* Packet to reply to. */
1424 rcode, /* Result code. */
1425 WINS_QUERY, /* nmbd type code. */
1426 NMB_NAME_QUERY_OPCODE, /* opcode. */
1427 ttl, /* ttl. */
1428 prdata, /* data to send. */
1429 reply_data_len); /* data length. */
1431 if(prdata != rdata)
1432 SAFE_FREE(prdata);
1435 /***********************************************************************
1436 Deal with a name query.
1437 ***********************************************************************/
1439 void wins_process_name_query_request(struct subnet_record *subrec,
1440 struct packet_struct *p)
1442 struct nmb_packet *nmb = &p->packet.nmb;
1443 struct nmb_name *question = &nmb->question.question_name;
1444 struct name_record *namerec = NULL;
1446 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
1447 nmb_namestr(question), inet_ntoa(p->ip) ));
1450 * Special name code. If the queried name is *<1b> then search
1451 * the entire WINS database and return a list of all the IP addresses
1452 * registered to any <1b> name. This is to allow domain master browsers
1453 * to discover other domains that may not have a presence on their subnet.
1456 if(strequal( question->name, "*") && (question->name_type == 0x1b))
1458 process_wins_dmb_query_request( subrec, p);
1459 return;
1462 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1464 if(namerec != NULL)
1467 * If the name is not anymore in active state then reply not found.
1468 * it's fair even if we keep it in the cache for days.
1470 if (!WINS_STATE_ACTIVE(namerec))
1472 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1473 nmb_namestr(question) ));
1474 send_wins_name_query_response(NAM_ERR, p, namerec);
1475 return;
1478 * If it's a DNSFAIL_NAME then reply name not found.
1481 if( namerec->data.source == DNSFAIL_NAME )
1483 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
1484 nmb_namestr(question) ));
1485 send_wins_name_query_response(NAM_ERR, p, namerec);
1486 return;
1490 * If the name has expired then reply name not found.
1493 if( (namerec->data.death_time != PERMANENT_TTL)
1494 && (namerec->data.death_time < p->timestamp) )
1496 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1497 nmb_namestr(question) ));
1498 send_wins_name_query_response(NAM_ERR, p, namerec);
1499 return;
1502 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
1503 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
1505 send_wins_name_query_response(0, p, namerec);
1506 return;
1510 * Name not found in WINS - try a dns query if it's a 0x20 name.
1513 if(lp_dns_proxy() &&
1514 ((question->name_type == 0x20) || question->name_type == 0))
1517 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
1518 nmb_namestr(question) ));
1520 queue_dns_query(p, question, &namerec);
1521 return;
1525 * Name not found - return error.
1528 send_wins_name_query_response(NAM_ERR, p, NULL);
1531 /****************************************************************************
1532 Send a WINS name release response.
1533 **************************************************************************/
1535 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
1537 struct nmb_packet *nmb = &p->packet.nmb;
1538 char rdata[6];
1540 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
1542 reply_netbios_packet(p, /* Packet to reply to. */
1543 rcode, /* Result code. */
1544 NMB_REL, /* nmbd type code. */
1545 NMB_NAME_RELEASE_OPCODE, /* opcode. */
1546 0, /* ttl. */
1547 rdata, /* data to send. */
1548 6); /* data length. */
1551 /***********************************************************************
1552 Deal with a name release.
1553 ***********************************************************************/
1555 void wins_process_name_release_request(struct subnet_record *subrec,
1556 struct packet_struct *p)
1558 struct nmb_packet *nmb = &p->packet.nmb;
1559 struct nmb_name *question = &nmb->question.question_name;
1560 BOOL bcast = nmb->header.nm_flags.bcast;
1561 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1562 struct name_record *namerec = NULL;
1563 struct in_addr from_ip;
1564 BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
1566 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1568 if(bcast)
1571 * We should only get unicast name registration packets here.
1572 * Anyone trying to register broadcast should not be going to a WINS
1573 * server. Log an error here.
1576 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
1577 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1578 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1579 return;
1582 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
1583 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1586 * Deal with policy regarding 0x1d names.
1589 if(!releasing_group_name && (question->name_type == 0x1d))
1591 DEBUG(3,("wins_process_name_release_request: Ignoring request \
1592 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1593 send_wins_name_release_response(0, p);
1594 return;
1598 * See if the name already exists.
1601 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1603 if( (namerec == NULL)
1604 || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) )
1606 send_wins_name_release_response(NAM_ERR, p);
1607 return;
1611 * Check that the sending machine has permission to release this name.
1612 * If it's a group name not ending in 0x1c then just say yes and let
1613 * the group time out.
1616 if(releasing_group_name && (question->name_type != 0x1c))
1618 send_wins_name_release_response(0, p);
1619 return;
1623 * Check that the releasing node is on the list of IP addresses
1624 * for this name. Disallow the release if not.
1627 if(!find_ip_in_name_record(namerec, from_ip))
1629 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1630 release name %s as IP %s is not one of the known IP's for this name.\n",
1631 nmb_namestr(question), inet_ntoa(from_ip) ));
1632 send_wins_name_release_response(NAM_ERR, p);
1633 return;
1637 * Check if the record is active. IF it's already released
1638 * or tombstoned, refuse the release.
1640 if (!WINS_STATE_ACTIVE(namerec)) {
1641 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1642 release name %s as this record is not anymore active.\n",
1643 nmb_namestr(question) ));
1644 send_wins_name_release_response(NAM_ERR, p);
1645 return;
1649 * Check if the record is a 0x1c group
1650 * and has more then one ip
1651 * remove only this address.
1654 if(releasing_group_name &&
1655 (question->name_type == 0x1c) &&
1656 (namerec->data.num_ips > 1)) {
1657 remove_ip_from_name_record(namerec, from_ip);
1658 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
1659 inet_ntoa(from_ip),nmb_namestr(question)));
1660 send_wins_name_release_response(0, p);
1661 return;
1665 * Send a release response.
1666 * Flag the name as released and update the ttl
1669 send_wins_name_release_response(0, p);
1671 namerec->data.wins_flags |= WINS_RELEASED;
1672 update_name_ttl(namerec, EXTINCTION_INTERVAL);
1674 wins_hook("delete", namerec, 0);
1677 /*******************************************************************
1678 WINS time dependent processing.
1679 ******************************************************************/
1681 void initiate_wins_processing(time_t t)
1683 static time_t lasttime = 0;
1684 struct name_record *namerec;
1685 struct name_record *next_namerec;
1686 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1688 if (!lasttime)
1689 lasttime = t;
1690 if (t - lasttime < 20)
1691 return;
1693 lasttime = t;
1695 if(!lp_we_are_a_wins_server())
1696 return;
1698 for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
1699 namerec;
1700 namerec = next_namerec ) {
1701 next_namerec = (struct name_record *)ubi_trNext( namerec );
1703 if( (namerec->data.death_time != PERMANENT_TTL)
1704 && (namerec->data.death_time < t) ) {
1706 if( namerec->data.source == SELF_NAME ) {
1707 DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF name %s\n",
1708 wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
1709 namerec->data.death_time += 300;
1710 namerec->subnet->namelist_changed = True;
1711 continue;
1714 /* handle records, samba is the wins owner */
1715 if (ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1716 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
1717 case WINS_ACTIVE:
1718 namerec->data.wins_flags&=~WINS_STATE_MASK;
1719 namerec->data.wins_flags|=WINS_RELEASED;
1720 namerec->data.death_time = t + EXTINCTION_INTERVAL;
1721 DEBUG(3,("initiate_wins_processing: expiring %s\n", nmb_namestr(&namerec->name)));
1722 break;
1723 case WINS_RELEASED:
1724 namerec->data.wins_flags&=~WINS_STATE_MASK;
1725 namerec->data.wins_flags|=WINS_TOMBSTONED;
1726 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
1727 get_global_id_and_update(&namerec->data.id, True);
1728 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
1729 break;
1730 case WINS_TOMBSTONED:
1731 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
1732 remove_name_from_namelist( wins_server_subnet, namerec );
1733 break;
1735 } else {
1736 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
1737 case WINS_ACTIVE:
1738 /* that's not as MS says it should be */
1739 namerec->data.wins_flags&=~WINS_STATE_MASK;
1740 namerec->data.wins_flags|=WINS_TOMBSTONED;
1741 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
1742 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
1743 case WINS_TOMBSTONED:
1744 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
1745 remove_name_from_namelist( wins_server_subnet, namerec );
1746 break;
1747 case WINS_RELEASED:
1748 DEBUG(0,("initiate_wins_processing: %s is in released state and\
1749 we are not the wins owner !\n", nmb_namestr(&namerec->name)));
1750 break;
1757 if(wins_server_subnet->namelist_changed)
1758 wins_write_database(True);
1760 wins_server_subnet->namelist_changed = False;
1763 /*******************************************************************
1764 Write out the current WINS database.
1765 ******************************************************************/
1766 void wins_write_database(BOOL background)
1768 struct name_record *namerec;
1769 pstring fname, fnamenew;
1770 TDB_CONTEXT *tdb;
1771 TDB_DATA kbuf, dbuf;
1772 pstring key, buf;
1773 int len;
1774 int num_record=0;
1775 SMB_BIG_UINT id;
1777 if(!lp_we_are_a_wins_server())
1778 return;
1780 /* we will do the writing in a child process to ensure that the parent
1781 doesn't block while this is done */
1782 if (background) {
1783 CatchChild();
1784 if (sys_fork()) {
1785 return;
1789 slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST);
1790 all_string_sub(fname,"//", "/", 0);
1791 slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid());
1793 tdb = tdb_open_log(fnamenew, 0, TDB_DEFAULT, O_RDWR|O_CREAT|O_TRUNC, 0644);
1794 if (!tdb) {
1795 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
1796 if (background)
1797 _exit(0);
1798 return;
1801 DEBUG(3,("wins_write_database: Dump of WINS name list.\n"));
1803 tdb_store_int32(tdb, INFO_VERSION, WINS_VERSION);
1805 for (namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
1806 namerec;
1807 namerec = (struct name_record *)ubi_trNext( namerec ) ) {
1809 int i;
1810 struct tm *tm;
1812 DEBUGADD(3,("%-19s ", nmb_namestr(&namerec->name) ));
1814 if( namerec->data.death_time != PERMANENT_TTL ) {
1815 char *ts, *nl;
1817 tm = LocalTime(&namerec->data.death_time);
1818 ts = asctime(tm);
1819 nl = strrchr_m( ts, '\n' );
1820 if( NULL != nl )
1821 *nl = '\0';
1823 DEBUGADD(3,("TTL = %s ", ts ));
1824 } else
1825 DEBUGADD(3,("TTL = PERMANENT "));
1827 for (i = 0; i < namerec->data.num_ips; i++)
1828 DEBUGADD(0,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
1830 DEBUGADD(3,("0x%2x 0x%2x %15s\n", namerec->data.nb_flags, namerec->data.wins_flags, inet_ntoa(namerec->data.wins_ip)));
1832 if( namerec->data.source == REGISTER_NAME ) {
1834 /* store the type in the key to make the name unique */
1835 slprintf(key, sizeof(key), "%s%s#%02x", ENTRY_PREFIX, namerec->name.name, namerec->name.name_type);
1837 len = tdb_pack(buf, sizeof(buf), "dddfddd",
1838 (int)namerec->data.nb_flags,
1839 (int)(namerec->data.id>>32),
1840 (int)(namerec->data.id&0xffffffff),
1841 inet_ntoa(namerec->data.wins_ip),
1842 (int)namerec->data.death_time,
1843 namerec->data.num_ips,
1844 namerec->data.wins_flags);
1846 for (i = 0; i < namerec->data.num_ips; i++)
1847 len += tdb_pack(buf+len, sizeof(buf)-len, "f", inet_ntoa(namerec->data.ip[i]));
1849 kbuf.dsize = strlen(key)+1;
1850 kbuf.dptr = key;
1851 dbuf.dsize = len;
1852 dbuf.dptr = buf;
1853 if (tdb_store(tdb, kbuf, dbuf, TDB_INSERT) != 0) return;
1855 num_record++;
1859 /* store the number of records */
1860 tdb_store_int32(tdb, INFO_COUNT, num_record);
1862 /* get and store the last used ID */
1863 get_global_id_and_update(&id, False);
1864 tdb_store_int32(tdb, INFO_ID_HIGH, id>>32);
1865 tdb_store_int32(tdb, INFO_ID_LOW, id&0xffffffff);
1867 tdb_close(tdb);
1869 chmod(fnamenew,0644);
1870 unlink(fname);
1871 rename(fnamenew,fname);
1873 if (background)
1874 _exit(0);
1877 /****************************************************************************
1878 process a internal Samba message receiving a wins record
1879 ***************************************************************************/
1880 void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len)
1882 WINS_RECORD *record;
1883 struct name_record *namerec = NULL;
1884 struct name_record *new_namerec = NULL;
1885 struct nmb_name question;
1886 BOOL overwrite=False;
1887 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1888 int i;
1890 if (buf==NULL)
1891 return;
1893 record=(WINS_RECORD *)buf;
1895 ZERO_STRUCT(question);
1896 memcpy(question.name, record->name, 16);
1897 question.name_type=record->type;
1899 namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
1901 /* record doesn't exist, add it */
1902 if (namerec == NULL) {
1903 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
1904 record->name, record->type, inet_ntoa(record->wins_ip)));
1906 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
1907 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
1908 if (new_namerec!=NULL) {
1909 update_wins_owner(new_namerec, record->wins_ip);
1910 update_wins_flag(new_namerec, record->wins_flags);
1911 new_namerec->data.id=record->id;
1913 wins_server_subnet->namelist_changed = True;
1917 /* check if we have a conflict */
1918 if (namerec != NULL) {
1919 /* both records are UNIQUE */
1920 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
1922 /* the database record is a replica */
1923 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1924 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
1925 if (ip_equal(namerec->data.wins_ip, record->wins_ip))
1926 overwrite=True;
1927 } else
1928 overwrite=True;
1929 } else {
1930 /* we are the wins owner of the database record */
1931 /* the 2 records have the same IP address */
1932 if (ip_equal(namerec->data.ip[0], record->ip[0])) {
1933 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
1934 get_global_id_and_update(&namerec->data.id, True);
1935 else
1936 overwrite=True;
1938 } else {
1939 /* the 2 records have different IP address */
1940 if (namerec->data.wins_flags&WINS_ACTIVE) {
1941 if (record->wins_flags&WINS_TOMBSTONED)
1942 get_global_id_and_update(&namerec->data.id, True);
1943 if (record->wins_flags&WINS_ACTIVE)
1944 /* send conflict challenge to the replica node */
1946 } else
1947 overwrite=True;
1953 /* the replica is a standard group */
1954 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {
1955 /* if the database record is unique and active force a name release */
1956 if (namerec->data.wins_flags&WINS_UNIQUE)
1957 /* send a release name to the unique node */
1959 overwrite=True;
1963 /* the replica is a special group */
1964 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
1965 if (namerec->data.wins_flags&WINS_ACTIVE) {
1966 for (i=0; i<record->num_ips; i++)
1967 if(!find_ip_in_name_record(namerec, record->ip[i]))
1968 add_ip_to_name_record(namerec, record->ip[i]);
1970 else
1971 overwrite=True;
1974 /* the replica is a multihomed host */
1976 /* I'm giving up on multi homed. Too much complex to understand */
1978 if (record->wins_flags&WINS_MHOMED) {
1979 if (! (namerec->data.wins_flags&WINS_ACTIVE)) {
1980 if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP))
1981 overwrite=True;
1983 else {
1984 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
1985 overwrite=True;
1987 if (ip_equal(namerec->data.wins_ip, our_fake_ip))
1988 if (namerec->data.wins_flags&WINS_UNIQUE)
1989 get_global_id_and_update(&namerec->data.id, True);
1993 if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
1994 if (namerec->data.wins_flags&WINS_UNIQUE ||
1995 namerec->data.wins_flags&WINS_MHOMED)
1996 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
1997 overwrite=True;
2001 if (overwrite == False)
2002 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
2003 record->name, record->type, inet_ntoa(record->wins_ip)));
2004 else {
2005 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
2006 record->name, record->type, inet_ntoa(record->wins_ip)));
2008 /* remove the old record and add a new one */
2009 remove_name_from_namelist( wins_server_subnet, namerec );
2010 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
2011 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
2012 if (new_namerec!=NULL) {
2013 update_wins_owner(new_namerec, record->wins_ip);
2014 update_wins_flag(new_namerec, record->wins_flags);
2015 new_namerec->data.id=record->id;
2017 wins_server_subnet->namelist_changed = True;
2020 wins_server_subnet->namelist_changed = True;