From 7fb1be73734915e027f86aca9ba62b86c56ca787 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 24 May 2004 17:41:47 +0000 Subject: r853: remove a real big bunch of unused code I really think that this is needed to get a better overview of what is currently used Also this stuff is really out of date so if we really ever need some of this stuff back, a 'svn copy' from the SAMBA_3_0 branch should be no big problem... metze (This used to be commit 972598d511c64f29bdc849fe58c9c82fbcf6a4a2) --- source4/nmbd/nmbd_winsserver.c | 2032 ---------------------------------------- 1 file changed, 2032 deletions(-) delete mode 100644 source4/nmbd/nmbd_winsserver.c (limited to 'source4/nmbd/nmbd_winsserver.c') diff --git a/source4/nmbd/nmbd_winsserver.c b/source4/nmbd/nmbd_winsserver.c deleted file mode 100644 index 6d1f654e84..0000000000 --- a/source4/nmbd/nmbd_winsserver.c +++ /dev/null @@ -1,2032 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - - Copyright (C) Jeremy Allison 1994-1998 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "includes.h" - -#define WINS_LIST "wins.tdb" -#define WINS_VERSION 1 - -/**************************************************************************** -change the wins owner address in the record. -*****************************************************************************/ -static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip) -{ - if (namerec==NULL) - return; - namerec->data.wins_ip=wins_ip; -} - -/**************************************************************************** -create the wins flags based on the nb flags and the input value. -*****************************************************************************/ -static void update_wins_flag(struct name_record *namerec, int flags) -{ - if (namerec==NULL) - return; - - namerec->data.wins_flags=0x0; - - /* if it's a group, it can be a normal or a special one */ - if (namerec->data.nb_flags & NB_GROUP) { - if (namerec->name.name_type==0x1C) - namerec->data.wins_flags|=WINS_SGROUP; - else - if (namerec->data.num_ips>1) - namerec->data.wins_flags|=WINS_SGROUP; - else - namerec->data.wins_flags|=WINS_NGROUP; - } else { - /* can be unique or multi-homed */ - if (namerec->data.num_ips>1) - namerec->data.wins_flags|=WINS_MHOMED; - else - namerec->data.wins_flags|=WINS_UNIQUE; - } - - /* the node type are the same bits */ - namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK; - - /* the static bit is elsewhere */ - if (namerec->data.death_time == PERMANENT_TTL) - namerec->data.wins_flags|=WINS_STATIC; - - /* and add the given bits */ - namerec->data.wins_flags|=flags; - - DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n", - namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags)); - -} - -/**************************************************************************** -return the general ID value and increase it if requested -*****************************************************************************/ -static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update) -{ - /* - * it's kept as a static here, to prevent people from messing - * with the value directly - */ - - static SMB_BIG_UINT general_id = 1; - - DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id)); - - *current_id = general_id; - - if (update) - general_id++; -} - -/**************************************************************************** -possibly call the WINS hook external program when a WINS change is made -*****************************************************************************/ -static void wins_hook(const char *operation, struct name_record *namerec, int ttl) -{ - pstring command; - char *cmd = lp_wins_hook(); - char *p; - int i; - - if (!cmd || !*cmd) return; - - for (p=namerec->name.name; *p; p++) { - if (!(isalnum((int)*p) || strchr_m("._-",*p))) { - DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name))); - return; - } - } - - p = command; - p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d", - cmd, - operation, - namerec->name.name, - namerec->name.name_type, - ttl); - - for (i=0;idata.num_ips;i++) { - p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.ip[i])); - } - - DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name))); - smbrun(command, NULL); -} - - -/**************************************************************************** -Determine if this packet should be allocated to the WINS server. -*****************************************************************************/ - -BOOL packet_is_for_wins_server(struct packet_struct *packet) -{ - struct nmb_packet *nmb = &packet->packet.nmb; - - /* Only unicast packets go to a WINS server. */ - if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True)) - { - DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n")); - return False; - } - - /* Check for node status requests. */ - if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY) - return False; - - switch(nmb->header.opcode) - { - /* - * A WINS server issues WACKS, not receives them. - */ - case NMB_WACK_OPCODE: - DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n")); - return False; - /* - * A WINS server only processes registration and - * release requests, not responses. - */ - case NMB_NAME_REG_OPCODE: - case NMB_NAME_MULTIHOMED_REG_OPCODE: - case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */ - case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */ - if(nmb->header.response) - { - DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n")); - return False; - } - break; - - case NMB_NAME_RELEASE_OPCODE: - if(nmb->header.response) - { - DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n")); - return False; - } - break; - - /* - * Only process unicast name queries with rd = 1. - */ - case NMB_NAME_QUERY_OPCODE: - if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired) - { - DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n")); - return False; - } - break; - } - - return True; -} - -/**************************************************************************** -Utility function to decide what ttl to give a register/refresh request. -*****************************************************************************/ - -static int get_ttl_from_packet(struct nmb_packet *nmb) -{ - int ttl = nmb->additional->ttl; - - if(ttl < lp_min_wins_ttl() ) - ttl = lp_min_wins_ttl(); - - if(ttl > lp_max_wins_ttl() ) - ttl = lp_max_wins_ttl(); - - return ttl; -} - -/**************************************************************************** -Load or create the WINS database. -*****************************************************************************/ - -BOOL initialise_wins(void) -{ - time_t time_now = time(NULL); - TDB_CONTEXT *tdb; - TDB_DATA kbuf, dbuf, newkey; - struct name_record *namerec = NULL; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - - DEBUG(2,("initialise_wins: started\n")); - - if(!lp_we_are_a_wins_server()) - return True; - - add_samba_names_to_subnet(wins_server_subnet); - - tdb = tdb_open_log(lock_path(WINS_LIST), 0, TDB_DEFAULT, O_RDONLY, 0600); - if (!tdb) { - DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n", WINS_LIST, strerror(errno) )); - return True; - } - - if (tdb_fetch_int32(tdb, INFO_VERSION) != WINS_VERSION) { - DEBUG(0,("Discarding invalid wins.dat file\n")); - tdb_close(tdb); - return True; - } - - for (kbuf = tdb_firstkey(tdb); - kbuf.dptr; - newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) { - - fstring name_type; - pstring name, ip_str; - char *p; - int type = 0; - int nb_flags; - int ttl; - unsigned int num_ips; - int high, low; - struct in_addr wins_ip; - struct in_addr *ip_list; - int wins_flags; - int len,i; - - if (strncmp(kbuf.dptr, ENTRY_PREFIX, strlen(ENTRY_PREFIX)) != 0) - continue; - - dbuf = tdb_fetch(tdb, kbuf); - if (!dbuf.dptr) - continue; - - fstrcpy(name_type, kbuf.dptr+strlen(ENTRY_PREFIX)); - - pstrcpy(name, name_type); - - if((p = strchr(name,'#')) != NULL) { - *p = 0; - sscanf(p+1,"%x",&type); - } - - len = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddfddd", - &nb_flags, &high, &low, - ip_str, &ttl, &num_ips, &wins_flags); - - wins_ip=*interpret_addr2(ip_str); - - /* Don't reload replica records */ - if (!ip_equal(wins_ip, our_fake_ip)) { - SAFE_FREE(dbuf.dptr); - continue; - } - - /* Don't reload released or tombstoned records */ - if ((wins_flags&WINS_STATE_MASK) != WINS_ACTIVE) { - SAFE_FREE(dbuf.dptr); - continue; - } - - /* Allocate the space for the ip_list. */ - if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL) { - SAFE_FREE(dbuf.dptr); - DEBUG(0,("initialise_wins: Malloc fail !\n")); - return False; - } - - for (i = 0; i < num_ips; i++) { - len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f", ip_str); - ip_list[i] = *interpret_addr2(ip_str); - } - - /* add all entries that have 60 seconds or more to live */ - if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) { - if(ttl != PERMANENT_TTL) - ttl -= time_now; - - DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n", - name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); - - namerec=add_name_to_subnet( wins_server_subnet, name, type, nb_flags, - ttl, REGISTER_NAME, num_ips, ip_list); - if (namerec!=NULL) { - update_wins_owner(namerec, wins_ip); - update_wins_flag(namerec, wins_flags); - /* we don't reload the ID, on startup we restart at 1 */ - get_global_id_and_update(&namerec->data.id, True); - } - - } else { - DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n", - name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); - } - - SAFE_FREE(dbuf.dptr); - SAFE_FREE(ip_list); - } - - tdb_close(tdb); - DEBUG(2,("initialise_wins: done\n")); - return True; -} - -/**************************************************************************** -Send a WINS WACK (Wait ACKnowledgement) response. -**************************************************************************/ - -static void send_wins_wack_response(int ttl, struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - unsigned char rdata[2]; - - rdata[0] = rdata[1] = 0; - - /* Taken from nmblib.c - we need to send back almost - identical bytes from the requesting packet header. */ - - rdata[0] = (nmb->header.opcode & 0xF) << 3; - if (nmb->header.nm_flags.authoritative && - nmb->header.response) rdata[0] |= 0x4; - if (nmb->header.nm_flags.trunc) rdata[0] |= 0x2; - if (nmb->header.nm_flags.recursion_desired) rdata[0] |= 0x1; - if (nmb->header.nm_flags.recursion_available && - nmb->header.response) rdata[1] |= 0x80; - if (nmb->header.nm_flags.bcast) rdata[1] |= 0x10; - - reply_netbios_packet(p, /* Packet to reply to. */ - 0, /* Result code. */ - NMB_WAIT_ACK, /* nmbd type code. */ - NMB_WACK_OPCODE, /* opcode. */ - ttl, /* ttl. */ - (char *)rdata, /* data to send. */ - 2); /* data length. */ -} - -/**************************************************************************** -Send a WINS name registration response. -**************************************************************************/ - -static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - char rdata[6]; - - memcpy(&rdata[0], &nmb->additional->rdata[0], 6); - - reply_netbios_packet(p, /* Packet to reply to. */ - rcode, /* Result code. */ - WINS_REG, /* nmbd type code. */ - NMB_NAME_REG_OPCODE, /* opcode. */ - ttl, /* ttl. */ - rdata, /* data to send. */ - 6); /* data length. */ -} - -/*********************************************************************** - Deal with a name refresh request to a WINS server. -************************************************************************/ - -void wins_process_name_refresh_request(struct subnet_record *subrec, - struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - BOOL bcast = nmb->header.nm_flags.bcast; - uint16 nb_flags = get_nb_flags(nmb->additional->rdata); - BOOL group = (nb_flags & NB_GROUP) ? True : False; - struct name_record *namerec = NULL; - int ttl = get_ttl_from_packet(nmb); - struct in_addr from_ip; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - - putip((char *)&from_ip,&nmb->additional->rdata[2]); - - if(bcast) - { - /* - * We should only get unicast name refresh packets here. - * Anyone trying to refresh broadcast should not be going to a WINS - * server. Log an error here. - */ - - DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh request \ -received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n", - nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - return; - } - - DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \ -IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) )); - - /* - * See if the name already exists. - */ - - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); - - /* - * If this is a refresh request and the name doesn't exist then - * treat it like a registration request. This allows us to recover - * from errors (tridge) - */ - - if(namerec == NULL) - { - DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \ -the name does not exist. Treating as registration.\n", nmb_namestr(question) )); - wins_process_name_registration_request(subrec,p); - return; - } - - /* - * if the name is present but not active, - * simply remove it and treat the request - * as a registration - */ - if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) - { - DEBUG(5,("wins_process_name_refresh_request: Name (%s) in WINS was \ -not active - removing it.\n", nmb_namestr(question) )); - remove_name_from_namelist( subrec, namerec ); - namerec = NULL; - wins_process_name_registration_request(subrec,p); - return; - } - - /* - * Check that the group bits for the refreshing name and the - * name in our database match. - */ - - if((namerec != NULL) && ((group && !NAME_GROUP(namerec)) || (!group && NAME_GROUP(namerec))) ) - { - DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \ -does not match group bit in WINS for this name.\n", nmb_namestr(question), group ? "True" : "False" )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - - /* - * For a unique name check that the person refreshing the name is one of the registered IP - * addresses. If not - fail the refresh. Do the same for group names with a type of 0x1c. - * Just return success for unique 0x1d refreshes. For normal group names update the ttl - * and return success. - */ - - if((!group || (group && (question->name_type == 0x1c))) && find_ip_in_name_record(namerec, from_ip )) - { - /* - * Update the ttl. - */ - update_name_ttl(namerec, ttl); - - /* - * if the record is a replica: - * we take ownership and update the version ID. - */ - if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) { - update_wins_owner(namerec, our_fake_ip); - get_global_id_and_update(&namerec->data.id, True); - } - - send_wins_name_registration_response(0, ttl, p); - wins_hook("refresh", namerec, ttl); - return; - } - else if(group) - { - /* - * Normal groups are all registered with an IP address of 255.255.255.255 - * so we can't search for the IP address. - */ - update_name_ttl(namerec, ttl); - send_wins_name_registration_response(0, ttl, p); - return; - } - else if(!group && (question->name_type == 0x1d)) - { - /* - * Special name type - just pretend the refresh succeeded. - */ - send_wins_name_registration_response(0, ttl, p); - return; - } - else - { - /* - * Fail the refresh. - */ - - DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \ -is IP is not known to the name.\n", nmb_namestr(question), inet_ntoa(from_ip) )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } -} - -/*********************************************************************** - Deal with a name registration request query success to a client that - owned the name. - - We have a locked pointer to the original packet stashed away in the - userdata pointer. The success here is actually a failure as it means - the client we queried wants to keep the name, so we must return - a registration failure to the original requestor. -************************************************************************/ - -static void wins_register_query_success(struct subnet_record *subrec, - struct userdata_struct *userdata, - struct nmb_name *question_name, - struct in_addr ip, - struct res_rec *answers) -{ - struct packet_struct *orig_reg_packet; - - memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); - - DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \ -name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) )); - - send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); - - orig_reg_packet->locked = False; - free_packet(orig_reg_packet); -} - -/*********************************************************************** - Deal with a name registration request query failure to a client that - owned the name. - - We have a locked pointer to the original packet stashed away in the - userdata pointer. The failure here is actually a success as it means - the client we queried didn't want to keep the name, so we can remove - the old name record and then successfully add the new name. -************************************************************************/ - -static void wins_register_query_fail(struct subnet_record *subrec, - struct response_record *rrec, - struct nmb_name *question_name, - int rcode) -{ - struct userdata_struct *userdata = rrec->userdata; - struct packet_struct *orig_reg_packet; - struct name_record *namerec = NULL; - - memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); - - /* - * We want to just add the name, as we now know the original owner - * didn't want it. But we can't just do that as an arbitary - * amount of time may have taken place between the name query - * request and this timeout/error response. So we check that - * the name still exists and is in the same state - if so - * we remove it and call wins_process_name_registration_request() - * as we know it will do the right thing now. - */ - - namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME); - - if( (namerec != NULL) - && (namerec->data.source == REGISTER_NAME) - && ip_equal(rrec->packet->ip, *namerec->data.ip) ) - { - remove_name_from_namelist( subrec, namerec); - namerec = NULL; - } - - if(namerec == NULL) - wins_process_name_registration_request(subrec, orig_reg_packet); - else - DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \ -querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) )); - - orig_reg_packet->locked = False; - free_packet(orig_reg_packet); -} - -/*********************************************************************** - Deal with a name registration request to a WINS server. - - Use the following pseudocode : - - registering_group - | - | - +--------name exists - | | - | | - | +--- existing name is group - | | | - | | | - | | +--- add name (return). - | | - | | - | +--- exiting name is unique - | | - | | - | +--- query existing owner (return). - | - | - +--------name doesn't exist - | - | - +--- add name (return). - - registering_unique - | - | - +--------name exists - | | - | | - | +--- existing name is group - | | | - | | | - | | +--- fail add (return). - | | - | | - | +--- exiting name is unique - | | - | | - | +--- query existing owner (return). - | - | - +--------name doesn't exist - | - | - +--- add name (return). - - As can be seen from the above, the two cases may be collapsed onto each - other with the exception of the case where the name already exists and - is a group name. This case we handle with an if statement. - -************************************************************************/ - -void wins_process_name_registration_request(struct subnet_record *subrec, - struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - BOOL bcast = nmb->header.nm_flags.bcast; - uint16 nb_flags = get_nb_flags(nmb->additional->rdata); - int ttl = get_ttl_from_packet(nmb); - struct name_record *namerec = NULL; - struct in_addr from_ip; - BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - - putip((char *)&from_ip,&nmb->additional->rdata[2]); - - if(bcast) - { - /* - * We should only get unicast name registration packets here. - * Anyone trying to register broadcast should not be going to a WINS - * server. Log an error here. - */ - - DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \ -received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n", - nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - return; - } - - DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \ -IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) )); - - /* - * See if the name already exists. - */ - - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); - - /* - * if the record exists but NOT in active state, - * consider it dead. - */ - if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) - { - DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \ -not active - removing it.\n", nmb_namestr(question) )); - remove_name_from_namelist( subrec, namerec ); - namerec = NULL; - } - - /* - * Deal with the case where the name found was a dns entry. - * Remove it as we now have a NetBIOS client registering the - * name. - */ - - if( (namerec != NULL) - && ( (namerec->data.source == DNS_NAME) - || (namerec->data.source == DNSFAIL_NAME) ) ) - { - DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \ -a dns lookup - removing it.\n", nmb_namestr(question) )); - remove_name_from_namelist( subrec, namerec ); - namerec = NULL; - } - - /* - * Reject if the name exists and is not a REGISTER_NAME. - * (ie. Don't allow any static names to be overwritten. - */ - - if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) - { - DEBUG( 3, ( "wins_process_name_registration_request: Attempt \ -to register name %s. Name already exists in WINS with source type %d.\n", - nmb_namestr(question), namerec->data.source )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - - /* - * Special policy decisions based on MS documentation. - * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255. - * 2). All unique names ending in 0x1d are ignored, although a positive response is sent. - */ - - /* - * A group name is always added as the local broadcast address, except - * for group names ending in 0x1c. - * Group names with type 0x1c are registered with individual IP addresses. - */ - - if(registering_group_name && (question->name_type != 0x1c)) - from_ip = *interpret_addr2("255.255.255.255"); - - /* - * Ignore all attempts to register a unique 0x1d name, although return success. - */ - - if(!registering_group_name && (question->name_type == 0x1d)) - { - DEBUG(3,("wins_process_name_registration_request: Ignoring request \ -to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) )); - send_wins_name_registration_response(0, ttl, p); - return; - } - - /* - * Next two cases are the 'if statement' mentioned above. - */ - - if((namerec != NULL) && NAME_GROUP(namerec)) - { - if(registering_group_name) - { - /* - * If we are adding a group name, the name exists and is also a group entry just add this - * IP address to it and update the ttl. - */ - - DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n", - inet_ntoa(from_ip), nmb_namestr(question) )); - /* - * Check the ip address is not already in the group. - */ - if(!find_ip_in_name_record(namerec, from_ip)) { - add_ip_to_name_record(namerec, from_ip); - /* we need to update the record for replication */ - get_global_id_and_update(&namerec->data.id, True); - - /* - * if the record is a replica, we must change - * the wins owner to us to make the replication updates - * it on the other wins servers. - * And when the partner will receive this record, - * it will update its own record. - */ - - update_wins_owner(namerec, our_fake_ip); - - } - update_name_ttl(namerec, ttl); - send_wins_name_registration_response(0, ttl, p); - return; - } - else - { - /* - * If we are adding a unique name, the name exists in the WINS db - * and is a group name then reject the registration. - * - * explanation: groups have a higher priority than unique names. - */ - - DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \ -already exists in WINS as a GROUP name.\n", nmb_namestr(question) )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - } - - /* - * From here on down we know that if the name exists in the WINS db it is - * a unique name, not a group name. - */ - - /* - * If the name exists and is one of our names then check the - * registering IP address. If it's not one of ours then automatically - * reject without doing the query - we know we will reject it. - */ - - if((namerec != NULL) && (is_myname(namerec->name.name)) ) - { - if(!ismyip(from_ip)) - { - DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \ -is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - else - { - /* - * It's one of our names and one of our IP's - update the ttl. - */ - update_name_ttl(namerec, ttl); - send_wins_name_registration_response(0, ttl, p); - wins_hook("refresh", namerec, ttl); - return; - } - } - - /* - * If the name exists and it is a unique registration and the registering IP - * is the same as the (single) already registered IP then just update the ttl. - * - * But not if the record is an active replica. IF it's a replica, it means it can be - * the same client which has moved and not yet expired. So we don't update - * the ttl in this case and go beyond to do a WACK and query the old client - */ - - if( !registering_group_name - && (namerec != NULL) - && (namerec->data.num_ips == 1) - && ip_equal( namerec->data.ip[0], from_ip ) - && ip_equal(namerec->data.wins_ip, our_fake_ip) ) - { - update_name_ttl( namerec, ttl ); - send_wins_name_registration_response( 0, ttl, p ); - wins_hook("refresh", namerec, ttl); - return; - } - - /* - * Finally if the name exists do a query to the registering machine - * to see if they still claim to have the name. - */ - - if( namerec != NULL ) - { - long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1]; - struct userdata_struct *userdata = (struct userdata_struct *)ud; - - /* - * First send a WACK to the registering machine. - */ - - send_wins_wack_response(60, p); - - /* - * When the reply comes back we need the original packet. - * Lock this so it won't be freed and then put it into - * the userdata structure. - */ - - p->locked = True; - - userdata = (struct userdata_struct *)ud; - - userdata->copy_fn = NULL; - userdata->free_fn = NULL; - userdata->userdata_len = sizeof(struct packet_struct *); - memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) ); - - /* - * Use the new call to send a query directly to an IP address. - * This sends the query directly to the IP address, and ensures - * the recursion desired flag is not set (you were right Luke :-). - * This function should *only* be called from the WINS server - * code. JRA. - */ - - query_name_from_wins_server( *namerec->data.ip, - question->name, - question->name_type, - wins_register_query_success, - wins_register_query_fail, - userdata ); - return; - } - - /* - * Name did not exist - add it. - */ - - (void)add_name_to_subnet( subrec, question->name, question->name_type, - nb_flags, ttl, REGISTER_NAME, 1, &from_ip); - if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) { - get_global_id_and_update(&namerec->data.id, True); - update_wins_owner(namerec, our_fake_ip); - update_wins_flag(namerec, WINS_ACTIVE); - wins_hook("add", namerec, ttl); - } - - send_wins_name_registration_response(0, ttl, p); -} - -/*********************************************************************** - Deal with a mutihomed name query success to the machine that - requested the multihomed name registration. - - We have a locked pointer to the original packet stashed away in the - userdata pointer. -************************************************************************/ - -static void wins_multihomed_register_query_success(struct subnet_record *subrec, - struct userdata_struct *userdata, - struct nmb_name *question_name, - struct in_addr ip, - struct res_rec *answers) -{ - struct packet_struct *orig_reg_packet; - struct nmb_packet *nmb; - struct name_record *namerec = NULL; - struct in_addr from_ip; - int ttl; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - - memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); - - nmb = &orig_reg_packet->packet.nmb; - - putip((char *)&from_ip,&nmb->additional->rdata[2]); - ttl = get_ttl_from_packet(nmb); - - /* - * We want to just add the new IP, as we now know the requesting - * machine claims to own it. But we can't just do that as an arbitary - * amount of time may have taken place between the name query - * request and this response. So we check that - * the name still exists and is in the same state - if so - * we just add the extra IP and update the ttl. - */ - - namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME); - - if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) - { - DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \ -a subsequent IP address.\n", nmb_namestr(question_name) )); - send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); - - orig_reg_packet->locked = False; - free_packet(orig_reg_packet); - - return; - } - - if(!find_ip_in_name_record(namerec, from_ip)) - add_ip_to_name_record(namerec, from_ip); - - get_global_id_and_update(&namerec->data.id, True); - update_wins_owner(namerec, our_fake_ip); - update_wins_flag(namerec, WINS_ACTIVE); - update_name_ttl(namerec, ttl); - send_wins_name_registration_response(0, ttl, orig_reg_packet); - wins_hook("add", namerec, ttl); - - orig_reg_packet->locked = False; - free_packet(orig_reg_packet); -} - -/*********************************************************************** - Deal with a name registration request query failure to a client that - owned the name. - - We have a locked pointer to the original packet stashed away in the - userdata pointer. -************************************************************************/ - -static void wins_multihomed_register_query_fail(struct subnet_record *subrec, - struct response_record *rrec, - struct nmb_name *question_name, - int rcode) -{ - struct userdata_struct *userdata = rrec->userdata; - struct packet_struct *orig_reg_packet; - - memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); - - DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \ -query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) )); - send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); - - orig_reg_packet->locked = False; - free_packet(orig_reg_packet); - return; -} - -/*********************************************************************** - Deal with a multihomed name registration request to a WINS server. - These cannot be group name registrations. -***********************************************************************/ - -void wins_process_multihomed_name_registration_request( struct subnet_record *subrec, - struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - BOOL bcast = nmb->header.nm_flags.bcast; - uint16 nb_flags = get_nb_flags(nmb->additional->rdata); - int ttl = get_ttl_from_packet(nmb); - struct name_record *namerec = NULL; - struct in_addr from_ip; - BOOL group = (nb_flags & NB_GROUP) ? True : False; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - - putip((char *)&from_ip,&nmb->additional->rdata[2]); - - if(bcast) - { - /* - * We should only get unicast name registration packets here. - * Anyone trying to register broadcast should not be going to a WINS - * server. Log an error here. - */ - - DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \ -received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n", - nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - return; - } - - /* - * Only unique names should be registered multihomed. - */ - - if(group) - { - DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \ -received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n", - nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - return; - } - - DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \ -IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) )); - - /* - * Deal with policy regarding 0x1d names. - */ - - if(question->name_type == 0x1d) - { - DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \ -to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) )); - send_wins_name_registration_response(0, ttl, p); - return; - } - - /* - * See if the name already exists. - */ - - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); - - /* - * if the record exists but NOT in active state, - * consider it dead. - */ - if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) { - DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question))); - remove_name_from_namelist(subrec, namerec); - namerec = NULL; - } - - /* - * Deal with the case where the name found was a dns entry. - * Remove it as we now have a NetBIOS client registering the - * name. - */ - - if( (namerec != NULL) - && ( (namerec->data.source == DNS_NAME) - || (namerec->data.source == DNSFAIL_NAME) ) ) - { - DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \ -- removing it.\n", nmb_namestr(question) )); - remove_name_from_namelist( subrec, namerec); - namerec = NULL; - } - - /* - * Reject if the name exists and is not a REGISTER_NAME. - * (ie. Don't allow any static names to be overwritten. - */ - - if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) - { - DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \ -to register name %s. Name already exists in WINS with source type %d.\n", - nmb_namestr(question), namerec->data.source )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - - /* - * Reject if the name exists and is a GROUP name and is active. - */ - - if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) - { - DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \ -already exists in WINS as a GROUP name.\n", nmb_namestr(question) )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - - /* - * From here on down we know that if the name exists in the WINS db it is - * a unique name, not a group name. - */ - - /* - * If the name exists and is one of our names then check the - * registering IP address. If it's not one of ours then automatically - * reject without doing the query - we know we will reject it. - */ - - if((namerec != NULL) && (is_myname(namerec->name.name)) ) - { - if(!ismyip(from_ip)) - { - DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \ -is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - else - { - /* - * It's one of our names and one of our IP's. Ensure the IP is in the record and - * update the ttl. Update the version ID to force replication. - */ - if(!find_ip_in_name_record(namerec, from_ip)) { - get_global_id_and_update(&namerec->data.id, True); - update_wins_owner(namerec, our_fake_ip); - update_wins_flag(namerec, WINS_ACTIVE); - - add_ip_to_name_record(namerec, from_ip); - wins_hook("add", namerec, ttl); - } else { - wins_hook("refresh", namerec, ttl); - } - - update_name_ttl(namerec, ttl); - send_wins_name_registration_response(0, ttl, p); - return; - } - } - - /* - * If the name exists and is active, check if the IP address is already registered - * to that name. If so then update the ttl and reply success. - */ - - if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) - { - update_name_ttl(namerec, ttl); - /* - * If it's a replica, we need to become the wins owner - * to force the replication - */ - if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) { - get_global_id_and_update(&namerec->data.id, True); - update_wins_owner(namerec, our_fake_ip); - update_wins_flag(namerec, WINS_ACTIVE); - } - - send_wins_name_registration_response(0, ttl, p); - wins_hook("refresh", namerec, ttl); - return; - } - - /* - * If the name exists do a query to the owner - * to see if they still want the name. - */ - - if(namerec != NULL) - { - long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1]; - struct userdata_struct *userdata = (struct userdata_struct *)ud; - - /* - * First send a WACK to the registering machine. - */ - - send_wins_wack_response(60, p); - - /* - * When the reply comes back we need the original packet. - * Lock this so it won't be freed and then put it into - * the userdata structure. - */ - - p->locked = True; - - userdata = (struct userdata_struct *)ud; - - userdata->copy_fn = NULL; - userdata->free_fn = NULL; - userdata->userdata_len = sizeof(struct packet_struct *); - memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) ); - - /* - * Use the new call to send a query directly to an IP address. - * This sends the query directly to the IP address, and ensures - * the recursion desired flag is not set (you were right Luke :-). - * This function should *only* be called from the WINS server - * code. JRA. - * - * Note that this packet is sent to the current owner of the name, - * not the person who sent the packet - */ - - query_name_from_wins_server( namerec->data.ip[0], - question->name, - question->name_type, - wins_multihomed_register_query_success, - wins_multihomed_register_query_fail, - userdata ); - - return; - } - - /* - * Name did not exist - add it. - */ - - (void)add_name_to_subnet( subrec, question->name, question->name_type, - nb_flags, ttl, REGISTER_NAME, 1, &from_ip); - - if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) { - get_global_id_and_update(&namerec->data.id, True); - update_wins_owner(namerec, our_fake_ip); - update_wins_flag(namerec, WINS_ACTIVE); - wins_hook("add", namerec, ttl); - } - - send_wins_name_registration_response(0, ttl, p); -} - -/*********************************************************************** - Deal with the special name query for *<1b>. -***********************************************************************/ - -static void process_wins_dmb_query_request(struct subnet_record *subrec, - struct packet_struct *p) -{ - struct name_record *namerec = NULL; - char *prdata; - int num_ips; - - /* - * Go through all the ACTIVE names in the WINS db looking for those - * ending in <1b>. Use this to calculate the number of IP - * addresses we need to return. - */ - - num_ips = 0; - for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); - namerec; - namerec = (struct name_record *)ubi_trNext( namerec ) ) - { - if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b ) - num_ips += namerec->data.num_ips; - } - - if(num_ips == 0) - { - /* - * There are no 0x1b names registered. Return name query fail. - */ - send_wins_name_query_response(NAM_ERR, p, NULL); - return; - } - - if((prdata = (char *)malloc( num_ips * 6 )) == NULL) - { - DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n")); - return; - } - - /* - * Go through all the names again in the WINS db looking for those - * ending in <1b>. Add their IP addresses into the list we will - * return. - */ - - num_ips = 0; - for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); - namerec; - namerec = (struct name_record *)ubi_trNext( namerec ) ) - { - if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) - { - int i; - for(i = 0; i < namerec->data.num_ips; i++) - { - set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags); - putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]); - num_ips++; - } - } - } - - /* - * Send back the reply containing the IP list. - */ - - reply_netbios_packet(p, /* Packet to reply to. */ - 0, /* Result code. */ - WINS_QUERY, /* nmbd type code. */ - NMB_NAME_QUERY_OPCODE, /* opcode. */ - lp_min_wins_ttl(), /* ttl. */ - prdata, /* data to send. */ - num_ips*6); /* data length. */ - - SAFE_FREE(prdata); -} - -/**************************************************************************** -Send a WINS name query response. -**************************************************************************/ - -void send_wins_name_query_response(int rcode, struct packet_struct *p, - struct name_record *namerec) -{ - char rdata[6]; - char *prdata = rdata; - int reply_data_len = 0; - int ttl = 0; - int i; - - memset(rdata,'\0',6); - - if(rcode == 0) - { - ttl = (namerec->data.death_time != PERMANENT_TTL) ? - namerec->data.death_time - p->timestamp : lp_max_wins_ttl(); - - /* Copy all known ip addresses into the return data. */ - /* Optimise for the common case of one IP address so - we don't need a malloc. */ - - if( namerec->data.num_ips == 1 ) - prdata = rdata; - else - { - if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL) - { - DEBUG(0,("send_wins_name_query_response: malloc fail !\n")); - return; - } - } - - for(i = 0; i < namerec->data.num_ips; i++) - { - set_nb_flags(&prdata[i*6],namerec->data.nb_flags); - putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]); - } - - sort_query_replies(prdata, i, p->ip); - - reply_data_len = namerec->data.num_ips * 6; - } - - reply_netbios_packet(p, /* Packet to reply to. */ - rcode, /* Result code. */ - WINS_QUERY, /* nmbd type code. */ - NMB_NAME_QUERY_OPCODE, /* opcode. */ - ttl, /* ttl. */ - prdata, /* data to send. */ - reply_data_len); /* data length. */ - - if(prdata != rdata) - SAFE_FREE(prdata); -} - -/*********************************************************************** - Deal with a name query. -***********************************************************************/ - -void wins_process_name_query_request(struct subnet_record *subrec, - struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - struct name_record *namerec = NULL; - - DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n", - nmb_namestr(question), inet_ntoa(p->ip) )); - - /* - * Special name code. If the queried name is *<1b> then search - * the entire WINS database and return a list of all the IP addresses - * registered to any <1b> name. This is to allow domain master browsers - * to discover other domains that may not have a presence on their subnet. - */ - - if(strequal( question->name, "*") && (question->name_type == 0x1b)) - { - process_wins_dmb_query_request( subrec, p); - return; - } - - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); - - if(namerec != NULL) - { - /* - * If the name is not anymore in active state then reply not found. - * it's fair even if we keep it in the cache for days. - */ - if (!WINS_STATE_ACTIVE(namerec)) - { - DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n", - nmb_namestr(question) )); - send_wins_name_query_response(NAM_ERR, p, namerec); - return; - } - /* - * If it's a DNSFAIL_NAME then reply name not found. - */ - - if( namerec->data.source == DNSFAIL_NAME ) - { - DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n", - nmb_namestr(question) )); - send_wins_name_query_response(NAM_ERR, p, namerec); - return; - } - - /* - * If the name has expired then reply name not found. - */ - - if( (namerec->data.death_time != PERMANENT_TTL) - && (namerec->data.death_time < p->timestamp) ) - { - DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n", - nmb_namestr(question) )); - send_wins_name_query_response(NAM_ERR, p, namerec); - return; - } - - DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n", - nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) )); - - send_wins_name_query_response(0, p, namerec); - return; - } - - /* - * Name not found in WINS - try a dns query if it's a 0x20 name. - */ - - if(lp_dns_proxy() && - ((question->name_type == 0x20) || question->name_type == 0)) - { - - DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n", - nmb_namestr(question) )); - - queue_dns_query(p, question, &namerec); - return; - } - - /* - * Name not found - return error. - */ - - send_wins_name_query_response(NAM_ERR, p, NULL); -} - -/**************************************************************************** -Send a WINS name release response. -**************************************************************************/ - -static void send_wins_name_release_response(int rcode, struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - char rdata[6]; - - memcpy(&rdata[0], &nmb->additional->rdata[0], 6); - - reply_netbios_packet(p, /* Packet to reply to. */ - rcode, /* Result code. */ - NMB_REL, /* nmbd type code. */ - NMB_NAME_RELEASE_OPCODE, /* opcode. */ - 0, /* ttl. */ - rdata, /* data to send. */ - 6); /* data length. */ -} - -/*********************************************************************** - Deal with a name release. -***********************************************************************/ - -void wins_process_name_release_request(struct subnet_record *subrec, - struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - BOOL bcast = nmb->header.nm_flags.bcast; - uint16 nb_flags = get_nb_flags(nmb->additional->rdata); - struct name_record *namerec = NULL; - struct in_addr from_ip; - BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;; - - putip((char *)&from_ip,&nmb->additional->rdata[2]); - - if(bcast) - { - /* - * We should only get unicast name registration packets here. - * Anyone trying to register broadcast should not be going to a WINS - * server. Log an error here. - */ - - DEBUG(0,("wins_process_name_release_request: broadcast name registration request \ -received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n", - nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - return; - } - - DEBUG(3,("wins_process_name_release_request: %s name release for name %s \ -IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) )); - - /* - * Deal with policy regarding 0x1d names. - */ - - if(!releasing_group_name && (question->name_type == 0x1d)) - { - DEBUG(3,("wins_process_name_release_request: Ignoring request \ -to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) )); - send_wins_name_release_response(0, p); - return; - } - - /* - * See if the name already exists. - */ - - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); - - if( (namerec == NULL) - || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) - { - send_wins_name_release_response(NAM_ERR, p); - return; - } - - /* - * Check that the sending machine has permission to release this name. - * If it's a group name not ending in 0x1c then just say yes and let - * the group time out. - */ - - if(releasing_group_name && (question->name_type != 0x1c)) - { - send_wins_name_release_response(0, p); - return; - } - - /* - * Check that the releasing node is on the list of IP addresses - * for this name. Disallow the release if not. - */ - - if(!find_ip_in_name_record(namerec, from_ip)) - { - DEBUG(3,("wins_process_name_release_request: Refusing request to \ -release name %s as IP %s is not one of the known IP's for this name.\n", - nmb_namestr(question), inet_ntoa(from_ip) )); - send_wins_name_release_response(NAM_ERR, p); - return; - } - - /* - * Check if the record is active. IF it's already released - * or tombstoned, refuse the release. - */ - if (!WINS_STATE_ACTIVE(namerec)) { - DEBUG(3,("wins_process_name_release_request: Refusing request to \ -release name %s as this record is not anymore active.\n", - nmb_namestr(question) )); - send_wins_name_release_response(NAM_ERR, p); - return; - } - - /* - * Check if the record is a 0x1c group - * and has more then one ip - * remove only this address. - */ - - if(releasing_group_name && - (question->name_type == 0x1c) && - (namerec->data.num_ips > 1)) { - remove_ip_from_name_record(namerec, from_ip); - DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n", - inet_ntoa(from_ip),nmb_namestr(question))); - send_wins_name_release_response(0, p); - return; - } - - /* - * Send a release response. - * Flag the name as released and update the ttl - */ - - send_wins_name_release_response(0, p); - - namerec->data.wins_flags |= WINS_RELEASED; - update_name_ttl(namerec, EXTINCTION_INTERVAL); - - wins_hook("delete", namerec, 0); -} - -/******************************************************************* - WINS time dependent processing. -******************************************************************/ - -void initiate_wins_processing(time_t t) -{ - static time_t lasttime = 0; - struct name_record *namerec; - struct name_record *next_namerec; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - - if (!lasttime) - lasttime = t; - if (t - lasttime < 20) - return; - - lasttime = t; - - if(!lp_we_are_a_wins_server()) - return; - - for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); - namerec; - namerec = next_namerec ) { - next_namerec = (struct name_record *)ubi_trNext( namerec ); - - if( (namerec->data.death_time != PERMANENT_TTL) - && (namerec->data.death_time < t) ) { - - if( namerec->data.source == SELF_NAME ) { - DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF name %s\n", - wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) ); - namerec->data.death_time += 300; - namerec->subnet->namelist_changed = True; - continue; - } - - /* handle records, samba is the wins owner */ - if (ip_equal(namerec->data.wins_ip, our_fake_ip)) { - switch (namerec->data.wins_flags | WINS_STATE_MASK) { - case WINS_ACTIVE: - namerec->data.wins_flags&=~WINS_STATE_MASK; - namerec->data.wins_flags|=WINS_RELEASED; - namerec->data.death_time = t + EXTINCTION_INTERVAL; - DEBUG(3,("initiate_wins_processing: expiring %s\n", nmb_namestr(&namerec->name))); - break; - case WINS_RELEASED: - namerec->data.wins_flags&=~WINS_STATE_MASK; - namerec->data.wins_flags|=WINS_TOMBSTONED; - namerec->data.death_time = t + EXTINCTION_TIMEOUT; - get_global_id_and_update(&namerec->data.id, True); - DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name))); - break; - case WINS_TOMBSTONED: - DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name))); - remove_name_from_namelist( wins_server_subnet, namerec ); - break; - } - } else { - switch (namerec->data.wins_flags | WINS_STATE_MASK) { - case WINS_ACTIVE: - /* that's not as MS says it should be */ - namerec->data.wins_flags&=~WINS_STATE_MASK; - namerec->data.wins_flags|=WINS_TOMBSTONED; - namerec->data.death_time = t + EXTINCTION_TIMEOUT; - DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name))); - case WINS_TOMBSTONED: - DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name))); - remove_name_from_namelist( wins_server_subnet, namerec ); - break; - case WINS_RELEASED: - DEBUG(0,("initiate_wins_processing: %s is in released state and\ -we are not the wins owner !\n", nmb_namestr(&namerec->name))); - break; - } - } - - } - } - - if(wins_server_subnet->namelist_changed) - wins_write_database(True); - - wins_server_subnet->namelist_changed = False; -} - -/******************************************************************* - Write out the current WINS database. -******************************************************************/ -void wins_write_database(BOOL background) -{ - struct name_record *namerec; - pstring fname, fnamenew; - TDB_CONTEXT *tdb; - TDB_DATA kbuf, dbuf; - pstring key, buf; - int len; - int num_record=0; - SMB_BIG_UINT id; - - if(!lp_we_are_a_wins_server()) - return; - - /* we will do the writing in a child process to ensure that the parent - doesn't block while this is done */ - if (background) { - CatchChild(); - if (sys_fork()) { - return; - } - } - - slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST); - all_string_sub(fname,"//", "/", 0); - slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid()); - - tdb = tdb_open_log(fnamenew, 0, TDB_DEFAULT, O_RDWR|O_CREAT|O_TRUNC, 0644); - if (!tdb) { - DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno))); - if (background) - _exit(0); - return; - } - - DEBUG(3,("wins_write_database: Dump of WINS name list.\n")); - - tdb_store_int32(tdb, INFO_VERSION, WINS_VERSION); - - for (namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); - namerec; - namerec = (struct name_record *)ubi_trNext( namerec ) ) { - - int i; - struct tm *tm; - - DEBUGADD(3,("%-19s ", nmb_namestr(&namerec->name) )); - - if( namerec->data.death_time != PERMANENT_TTL ) { - char *ts, *nl; - - tm = localtime(&namerec->data.death_time); - ts = asctime(tm); - nl = strrchr_m( ts, '\n' ); - if( NULL != nl ) - *nl = '\0'; - - DEBUGADD(3,("TTL = %s ", ts )); - } else - DEBUGADD(3,("TTL = PERMANENT ")); - - for (i = 0; i < namerec->data.num_ips; i++) - DEBUGADD(0,("%15s ", inet_ntoa(namerec->data.ip[i]) )); - - DEBUGADD(3,("0x%2x 0x%2x %15s\n", namerec->data.nb_flags, namerec->data.wins_flags, inet_ntoa(namerec->data.wins_ip))); - - if( namerec->data.source == REGISTER_NAME ) { - - /* store the type in the key to make the name unique */ - slprintf(key, sizeof(key), "%s%s#%02x", ENTRY_PREFIX, namerec->name.name, namerec->name.name_type); - - len = tdb_pack(buf, sizeof(buf), "dddfddd", - (int)namerec->data.nb_flags, - (int)(namerec->data.id>>32), - (int)(namerec->data.id&0xffffffff), - inet_ntoa(namerec->data.wins_ip), - (int)namerec->data.death_time, - namerec->data.num_ips, - namerec->data.wins_flags); - - for (i = 0; i < namerec->data.num_ips; i++) - len += tdb_pack(buf+len, sizeof(buf)-len, "f", inet_ntoa(namerec->data.ip[i])); - - kbuf.dsize = strlen(key)+1; - kbuf.dptr = key; - dbuf.dsize = len; - dbuf.dptr = buf; - if (tdb_store(tdb, kbuf, dbuf, TDB_INSERT) != 0) return; - - num_record++; - } - } - - /* store the number of records */ - tdb_store_int32(tdb, INFO_COUNT, num_record); - - /* get and store the last used ID */ - get_global_id_and_update(&id, False); - tdb_store_int32(tdb, INFO_ID_HIGH, id>>32); - tdb_store_int32(tdb, INFO_ID_LOW, id&0xffffffff); - - tdb_close(tdb); - - chmod(fnamenew,0644); - unlink(fname); - rename(fnamenew,fname); - - if (background) - _exit(0); -} - -/**************************************************************************** -process a internal Samba message receiving a wins record -***************************************************************************/ -void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len) -{ - WINS_RECORD *record; - struct name_record *namerec = NULL; - struct name_record *new_namerec = NULL; - struct nmb_name question; - BOOL overwrite=False; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - int i; - - if (buf==NULL) - return; - - record=(WINS_RECORD *)buf; - - ZERO_STRUCT(question); - memcpy(question.name, record->name, 16); - question.name_type=record->type; - - namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME); - - /* record doesn't exist, add it */ - if (namerec == NULL) { - DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n", - record->name, record->type, inet_ntoa(record->wins_ip))); - - new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags, - EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip); - if (new_namerec!=NULL) { - update_wins_owner(new_namerec, record->wins_ip); - update_wins_flag(new_namerec, record->wins_flags); - new_namerec->data.id=record->id; - - wins_server_subnet->namelist_changed = True; - } - } - - /* check if we have a conflict */ - if (namerec != NULL) { - /* both records are UNIQUE */ - if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) { - - /* the database record is a replica */ - if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) { - if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) { - if (ip_equal(namerec->data.wins_ip, record->wins_ip)) - overwrite=True; - } else - overwrite=True; - } else { - /* we are the wins owner of the database record */ - /* the 2 records have the same IP address */ - if (ip_equal(namerec->data.ip[0], record->ip[0])) { - if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) - get_global_id_and_update(&namerec->data.id, True); - else - overwrite=True; - - } else { - /* the 2 records have different IP address */ - if (namerec->data.wins_flags&WINS_ACTIVE) { - if (record->wins_flags&WINS_TOMBSTONED) - get_global_id_and_update(&namerec->data.id, True); - if (record->wins_flags&WINS_ACTIVE) - /* send conflict challenge to the replica node */ - ; - } else - overwrite=True; - } - - } - } - - /* the replica is a standard group */ - if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) { - /* if the database record is unique and active force a name release */ - if (namerec->data.wins_flags&WINS_UNIQUE) - /* send a release name to the unique node */ - ; - overwrite=True; - - } - - /* the replica is a special group */ - if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) { - if (namerec->data.wins_flags&WINS_ACTIVE) { - for (i=0; inum_ips; i++) - if(!find_ip_in_name_record(namerec, record->ip[i])) - add_ip_to_name_record(namerec, record->ip[i]); - } - else - overwrite=True; - } - - /* the replica is a multihomed host */ - - /* I'm giving up on multi homed. Too much complex to understand */ - - if (record->wins_flags&WINS_MHOMED) { - if (! (namerec->data.wins_flags&WINS_ACTIVE)) { - if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP)) - overwrite=True; - } - else { - if (ip_equal(record->wins_ip, namerec->data.wins_ip)) - overwrite=True; - - if (ip_equal(namerec->data.wins_ip, our_fake_ip)) - if (namerec->data.wins_flags&WINS_UNIQUE) - get_global_id_and_update(&namerec->data.id, True); - - } - - if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE) - if (namerec->data.wins_flags&WINS_UNIQUE || - namerec->data.wins_flags&WINS_MHOMED) - if (ip_equal(record->wins_ip, namerec->data.wins_ip)) - overwrite=True; - - } - - if (overwrite == False) - DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n", - record->name, record->type, inet_ntoa(record->wins_ip))); - else { - DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n", - record->name, record->type, inet_ntoa(record->wins_ip))); - - /* remove the old record and add a new one */ - remove_name_from_namelist( wins_server_subnet, namerec ); - new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags, - EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip); - if (new_namerec!=NULL) { - update_wins_owner(new_namerec, record->wins_ip); - update_wins_flag(new_namerec, record->wins_flags); - new_namerec->data.id=record->id; - - wins_server_subnet->namelist_changed = True; - } - - wins_server_subnet->namelist_changed = True; - } - - } -} - - - - - - - - -- cgit