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
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
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.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
Converted to store WINS data in a tdb. Dec 2005. JRA.
*/
#include "includes.h"
+#include "system/filesys.h"
+#include "nmbd/nmbd.h"
+#include "util_tdb.h"
#define WINS_LIST "wins.dat"
#define WINS_VERSION 1
}
/****************************************************************************
- Convert a wins.tdb record to a struct name_record. Add in our global_scope().
+ Delete all the temporary 1b name records on the in-memory linked list.
+*****************************************************************************/
+
+static void wins_delete_all_1b_in_memory_records(void)
+{
+ struct name_record *nr = NULL;
+ struct name_record *nrnext = NULL;
+
+ /* Delete all temporary 1b name records on the wins subnet linked list. */
+ for( nr = wins_server_subnet->namelist; nr; nr = nrnext) {
+ nrnext = nr->next;
+ if (nr->name.name_type == 0x1b) {
+ DLIST_REMOVE(wins_server_subnet->namelist, nr);
+ SAFE_FREE(nr->data.ip);
+ SAFE_FREE(nr);
+ }
+ }
+}
+
+/****************************************************************************
+ Convert a wins.tdb record to a struct name_record. Add in our lp_netbios_scope().
*****************************************************************************/
static struct name_record *wins_record_to_name_record(TDB_DATA key, TDB_DATA data)
push_ascii_nstring(namerec->name.name, (const char *)key.dptr);
namerec->name.name_type = key.dptr[sizeof(unstring)];
/* Add the scope. */
- push_ascii(namerec->name.scope, global_scope(), 64, STR_TERMINATE);
+ push_ascii(namerec->name.scope, lp_netbios_scope(), 64, STR_TERMINATE);
/* We're using a byte-by-byte compare, so we must be sure that
* unused space doesn't have garbage in it.
namerec->data.refresh_time = (time_t)refresh_time;
namerec->data.id = id_low;
#if defined(HAVE_LONGLONG)
- namerec->data.id |= ((SMB_BIG_UINT)id_high << 32);
+ namerec->data.id |= ((uint64_t)id_high << 32);
#endif
namerec->data.wins_ip.s_addr = saddr;
namerec->data.wins_flags = wins_flags,
on the linked list. We will free this later in XXXX().
*****************************************************************************/
-struct name_record *find_name_on_wins_subnet(const struct nmb_name *nmbname, BOOL self_only)
+struct name_record *find_name_on_wins_subnet(const struct nmb_name *nmbname, bool self_only)
{
TDB_DATA data, key;
struct name_record *nr = NULL;
Overwrite or add a given name in the wins.tdb.
*****************************************************************************/
-static BOOL store_or_replace_wins_namerec(const struct name_record *namerec, int tdb_flag)
+static bool store_or_replace_wins_namerec(const struct name_record *namerec, int tdb_flag)
{
TDB_DATA key, data;
int ret;
Overwrite a given name in the wins.tdb.
*****************************************************************************/
-BOOL wins_store_changed_namerec(const struct name_record *namerec)
+bool wins_store_changed_namerec(const struct name_record *namerec)
{
return store_or_replace_wins_namerec(namerec, TDB_REPLACE);
}
Primary interface into creating and overwriting records in the wins.tdb.
*****************************************************************************/
-BOOL add_name_to_wins_subnet(const struct name_record *namerec)
+bool add_name_to_wins_subnet(const struct name_record *namerec)
{
return store_or_replace_wins_namerec(namerec, TDB_INSERT);
}
on the linked list.
*****************************************************************************/
-BOOL remove_name_from_wins_namelist(struct name_record *namerec)
+bool remove_name_from_wins_namelist(struct name_record *namerec)
{
TDB_DATA key;
int ret;
/* 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",
+ DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: %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)
+static void get_global_id_and_update(uint64_t *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;
+ static uint64_t general_id = 1;
DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id));
static void wins_hook(const char *operation, struct name_record *namerec, int ttl)
{
- pstring command;
+ char *command = NULL;
char *cmd = lp_wins_hook();
char *p, *namestr;
int i;
+ TALLOC_CTX *ctx = talloc_tos();
wins_store_changed_namerec(namerec);
*p = 0;
}
- p = command;
- p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d",
- cmd,
- operation,
- namestr,
- namerec->name.name_type,
- ttl);
+ command = talloc_asprintf(ctx,
+ "%s %s %s %02x %d",
+ cmd,
+ operation,
+ namestr,
+ namerec->name.name_type,
+ ttl);
+ if (!command) {
+ return;
+ }
for (i=0;i<namerec->data.num_ips;i++) {
- p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.ip[i]));
+ command = talloc_asprintf_append(command,
+ " %s",
+ inet_ntoa(namerec->data.ip[i]));
+ if (!command) {
+ return;
+ }
}
DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
smbrun(command, NULL);
+ TALLOC_FREE(command);
}
/****************************************************************************
Determine if this packet should be allocated to the WINS server.
*****************************************************************************/
-BOOL packet_is_for_wins_server(struct packet_struct *packet)
+bool packet_is_for_wins_server(struct packet_struct *packet)
{
struct nmb_packet *nmb = &packet->packet.nmb;
Load or create the WINS database.
*****************************************************************************/
-BOOL initialise_wins(void)
+bool initialise_wins(void)
{
time_t time_now = time(NULL);
XFILE *fp;
- pstring line;
+ char line[1024];
if(!lp_we_are_a_wins_server()) {
return True;
}
/* Open the wins.tdb. */
- wins_tdb = tdb_open_log(lock_path("wins.tdb"), 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST, O_CREAT|O_RDWR, 0600);
+ wins_tdb = tdb_open_log(state_path("wins.tdb"), 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
+ O_CREAT|O_RDWR, 0600);
if (!wins_tdb) {
DEBUG(0,("initialise_wins: failed to open wins.tdb. Error was %s\n",
strerror(errno) ));
add_samba_names_to_subnet(wins_server_subnet);
- if((fp = x_fopen(lock_path(WINS_LIST),O_RDONLY,0)) == NULL) {
+ if((fp = x_fopen(state_path(WINS_LIST),O_RDONLY,0)) == NULL) {
DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
WINS_LIST, strerror(errno) ));
return True;
}
while (!x_feof(fp)) {
- pstring name_str, ip_str, ttl_str, nb_flags_str;
+ char *name_str = NULL;
+ char *ip_str = NULL;
+ char *ttl_str = NULL, *nb_flags_str = NULL;
unsigned int num_ips;
- pstring name;
- struct in_addr *ip_list;
+ char *name = NULL;
+ struct in_addr *ip_list = NULL;
int type = 0;
int nb_flags;
int ttl;
const char *ptr;
- char *p;
- BOOL got_token;
- BOOL was_ip;
+ char *p = NULL;
+ bool got_token;
+ bool was_ip;
int i;
unsigned int hash;
int version;
+ TALLOC_CTX *frame = NULL;
/* Read a line from the wins.dat file. Strips whitespace
from the beginning and end of the line. */
- if (!fgets_slash(line,sizeof(pstring),fp))
+ if (!fgets_slash(line,sizeof(line),fp)) {
continue;
-
- if (*line == '#')
+ }
+
+ if (*line == '#') {
continue;
+ }
if (strncmp(line,"VERSION ", 8) == 0) {
if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||
ptr = line;
- /*
+ /*
* Now we handle multiple IP addresses per name we need
* to iterate over the line twice. The first time to
* determine how many IP addresses there are, the second
* time to actually parse them into the ip_list array.
*/
- if (!next_token(&ptr,name_str,NULL,sizeof(name_str))) {
+ frame = talloc_stackframe();
+ if (!next_token_talloc(frame,&ptr,&name_str,NULL)) {
DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));
+ TALLOC_FREE(frame);
continue;
}
- if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str))) {
+ if (!next_token_talloc(frame,&ptr,&ttl_str,NULL)) {
DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));
+ TALLOC_FREE(frame);
continue;
}
*/
num_ips = 0;
do {
- got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str));
+ got_token = next_token_talloc(frame,&ptr,&ip_str,NULL);
was_ip = False;
if(got_token && strchr(ip_str, '.')) {
num_ips++;
was_ip = True;
}
- } while( got_token && was_ip);
+ } while(got_token && was_ip);
if(num_ips == 0) {
DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line ));
+ TALLOC_FREE(frame);
continue;
}
if(!got_token) {
DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line ));
+ TALLOC_FREE(frame);
continue;
}
if((ip_list = SMB_MALLOC_ARRAY( struct in_addr, num_ips)) == NULL) {
DEBUG(0,("initialise_wins: Malloc fail !\n"));
x_fclose(fp);
+ TALLOC_FREE(frame);
return False;
}
-
+
/* Reset and re-parse the line. */
ptr = line;
- next_token(&ptr,name_str,NULL,sizeof(name_str));
- next_token(&ptr,ttl_str,NULL,sizeof(ttl_str));
+ next_token_talloc(frame,&ptr,&name_str,NULL);
+ next_token_talloc(frame,&ptr,&ttl_str,NULL);
for(i = 0; i < num_ips; i++) {
- next_token(&ptr, ip_str, NULL, sizeof(ip_str));
- ip_list[i] = *interpret_addr2(ip_str);
+ next_token_talloc(frame,&ptr, &ip_str, NULL);
+ ip_list[i] = interpret_addr2(ip_str);
}
- next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str));
+ next_token_talloc(frame,&ptr,&nb_flags_str,NULL);
- /*
+ /*
* Deal with SELF or REGISTER name encoding. Default is REGISTER
* for compatibility with old nmbds.
*/
if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') {
DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line));
SAFE_FREE(ip_list);
+ TALLOC_FREE(frame);
continue;
}
-
+
if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') {
nb_flags_str[strlen(nb_flags_str)-1] = '\0';
}
-
+
/* Netbios name. # divides the name from the type (hex): netbios#xx */
- pstrcpy(name,name_str);
-
+ name = name_str;
+
if((p = strchr(name,'#')) != NULL) {
*p = 0;
sscanf(p+1,"%x",&type);
}
-
+
/* Decode the netbios flags (hex) and the time-to-live (in seconds). */
sscanf(nb_flags_str,"%x",&nb_flags);
sscanf(ttl_str,"%d",&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));
name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
}
+ TALLOC_FREE(frame);
SAFE_FREE(ip_list);
- }
-
+ }
+
x_fclose(fp);
return True;
}
{
struct nmb_packet *nmb = &p->packet.nmb;
struct nmb_name *question = &nmb->question.question_name;
- BOOL bcast = nmb->header.nm_flags.bcast;
+ bool bcast = nmb->header.nm_flags.bcast;
uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
- BOOL group = (nb_flags & NB_GROUP) ? True : False;
+ 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");
+ struct in_addr our_fake_ip;
+ our_fake_ip = interpret_addr2("0.0.0.0");
putip( (char *)&from_ip, &nmb->additional->rdata[2] );
if(bcast) {
* if the record is a replica:
* we take ownership and update the version ID.
*/
- if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
+ if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
update_wins_owner(namerec, our_fake_ip);
get_global_id_and_update(&namerec->data.id, True);
}
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)) {
+ ip_equal_v4(rrec->packet->ip, *namerec->data.ip)) {
remove_name_from_namelist( subrec, namerec);
namerec = NULL;
}
unstring name;
struct nmb_packet *nmb = &p->packet.nmb;
struct nmb_name *question = &nmb->question.question_name;
- BOOL bcast = nmb->header.nm_flags.bcast;
+ 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");
+ bool registering_group_name = (nb_flags & NB_GROUP) ? True : False;
+ struct in_addr our_fake_ip;
+ our_fake_ip = interpret_addr2("0.0.0.0");
putip((char *)&from_ip,&nmb->additional->rdata[2]);
if(bcast) {
*/
if(registering_group_name && (question->name_type != 0x1c)) {
- from_ip = *interpret_addr2("255.255.255.255");
+ from_ip = interpret_addr2("255.255.255.255");
}
/*
*/
if(!find_ip_in_name_record(namerec, from_ip)) {
+ /*
+ * Need to emulate the behaviour of Windows, as
+ * described in:
+ * http://lists.samba.org/archive/samba-technical/2001-October/016236.html
+ * (is there an MS reference for this
+ * somewhere?) because if the 1c list gets over
+ * 86 entries, the reply packet is too big
+ * (rdata>576 bytes) so no reply is sent.
+ *
+ * Keep only the "latest" 25 records, while
+ * ensuring that the PDC (0x1b) is never removed
+ * We do this by removing the first entry that
+ * isn't the 1b entry for the same name,
+ * on the grounds that insertion is at the end
+ * of the list, so the oldest entries are at
+ * the start.
+ *
+ */
+ while(namerec->data.num_ips>=25) {
+ struct name_record *name1brec = NULL;
+
+ /* We only do this for 1c types. */
+ if (namerec->name.name_type != 0x1c) {
+ break;
+ }
+ DEBUG(3,("wins_process_name_registration_request: "
+ "More than 25 IPs already in "
+ "the list. Looking for a 1b "
+ "record\n"));
+
+ /* Ensure we have all the active 1b
+ * names on the list. */
+ wins_delete_all_1b_in_memory_records();
+ fetch_all_active_wins_1b_names();
+
+ /* Per the above, find the 1b record,
+ and then remove the first IP that isn't the same */
+ for(name1brec = subrec->namelist;
+ name1brec;
+ name1brec = name1brec->next ) {
+ if( WINS_STATE_ACTIVE(name1brec) &&
+ name1brec->name.name_type == 0x1b) {
+ DEBUG(3,("wins_process_name_registration_request: "
+ "Found the #1b record "
+ "with ip %s\n",
+ inet_ntoa(name1brec->data.ip[0])));
+ break;
+ }
+ }
+ if(!name1brec) {
+ DEBUG(3,("wins_process_name_registration_request: "
+ "Didn't find a #1b name record. "
+ "Removing the first available "
+ "entry %s\n",
+ inet_ntoa(namerec->data.ip[0])));
+ remove_ip_from_name_record(namerec, namerec->data.ip[0]);
+ wins_hook("delete", namerec, 0);
+ } else {
+ int i;
+ for(i=0; i<namerec->data.num_ips; i++) {
+ /* The name1brec should only have
+ * the single IP address in it,
+ * so we only check against the first one*/
+ if(!ip_equal_v4( namerec->data.ip[i], name1brec->data.ip[0])) {
+ /* The i'th entry isn't the 1b address; delete it */
+ DEBUG(3,("wins_process_name_registration_request: "
+ "Entry at %d is not the #1b address. "
+ "About to remove it\n",
+ i));
+ remove_ip_from_name_record(namerec, namerec->data.ip[i]);
+ wins_hook("delete", namerec, 0);
+ break;
+ }
+ }
+ }
+ }
+ /* The list is guaranteed to be < 25 entries now
+ * - safe to add a new one */
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 ( namerec != NULL ) {
pull_ascii_nstring(name, sizeof(name), namerec->name.name);
if( is_myname(name) ) {
- if(!ismyip(from_ip)) {
+ if(!ismyip_v4(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);
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) ) {
+ && ip_equal_v4( namerec->data.ip[0], from_ip )
+ && ip_equal_v4(namerec->data.wins_ip, our_fake_ip) ) {
update_name_ttl( namerec, ttl );
wins_hook("refresh", namerec, ttl);
send_wins_name_registration_response( 0, ttl, p );
struct name_record *namerec = NULL;
struct in_addr from_ip;
int ttl;
- struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
+ struct in_addr our_fake_ip;
+ 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;
{
struct nmb_packet *nmb = &p->packet.nmb;
struct nmb_name *question = &nmb->question.question_name;
- BOOL bcast = nmb->header.nm_flags.bcast;
+ 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");
+ bool group = (nb_flags & NB_GROUP) ? True : False;
+ struct in_addr our_fake_ip;
unstring qname;
+ our_fake_ip = interpret_addr2("0.0.0.0");
putip((char *)&from_ip,&nmb->additional->rdata[2]);
if(bcast) {
*/
if((namerec != NULL) && (is_myname(namerec->name.name)) ) {
- if(!ismyip(from_ip)) {
+ if(!ismyip_v4(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);
* 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)) {
+ if (!ip_equal_v4(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);
memset(rdata,'\0',6);
if(rcode == 0) {
+
+ int ip_count;
+
ttl = (namerec->data.death_time != PERMANENT_TTL) ? namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
+ /* The netbios reply packet data section is limited to 576 bytes. In theory
+ * this should give us space for 96 addresses, but in practice, 86 appears
+ * to be the max (don't know why). If we send any more than that,
+ * reply_netbios_packet will fail to send a reply to avoid a memcpy buffer
+ * overflow. Keep the count to 85 and it will be ok */
+ ip_count=namerec->data.num_ips;
+ if(ip_count>85) {
+ ip_count=85;
+ }
+
/* 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 ) {
+ if( ip_count == 1 ) {
prdata = rdata;
} else {
- if((prdata = (char *)SMB_MALLOC( namerec->data.num_ips * 6 )) == NULL) {
+ if((prdata = (char *)SMB_MALLOC( ip_count * 6 )) == NULL) {
DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
return;
}
}
- for(i = 0; i < namerec->data.num_ips; i++) {
+ for(i = 0; i < ip_count; 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_data_len = ip_count * 6;
}
reply_netbios_packet(p, /* Packet to reply to. */
{
struct nmb_packet *nmb = &p->packet.nmb;
struct nmb_name *question = &nmb->question.question_name;
- BOOL bcast = nmb->header.nm_flags.bcast;
+ 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;;
+ bool releasing_group_name = (nb_flags & NB_GROUP) ? True : False;
putip((char *)&from_ip,&nmb->additional->rdata[2]);
static int wins_processing_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
{
time_t t = *(time_t *)state;
- BOOL store_record = False;
+ bool store_record = False;
struct name_record *namerec = NULL;
- struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
+ struct in_addr our_fake_ip;
+ our_fake_ip = interpret_addr2("0.0.0.0");
if (kbuf.dsize != sizeof(unstring) + 1) {
return 0;
}
}
/* 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) {
+ if (ip_equal_v4(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;
goto done;
}
} else {
- switch (namerec->data.wins_flags | WINS_STATE_MASK) {
+ 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;
}
-void wins_write_database(time_t t, BOOL background)
+void wins_write_database(time_t t, bool background)
{
static time_t last_write_time = 0;
- pstring fname, fnamenew;
+ char *fname = NULL;
+ char *fnamenew = NULL;
XFILE *fp;
-
+
if (background) {
if (!last_write_time) {
last_write_time = t;
if (tdb_reopen(wins_tdb)) {
DEBUG(0,("wins_write_database: tdb_reopen failed. Error was %s\n",
strerror(errno)));
+ _exit(0);
return;
}
}
- slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST);
+ if (!(fname = state_path(WINS_LIST))) {
+ goto err_exit;
+ }
+ /* This is safe as the 0 length means "don't expand". */
all_string_sub(fname,"//", "/", 0);
- slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid());
+
+ if (asprintf(&fnamenew, "%s.%u", fname, (unsigned int)sys_getpid()) < 0) {
+ goto err_exit;
+ }
if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) {
DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
- if (background) {
- _exit(0);
- }
- return;
+ goto err_exit;
}
DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0);
-
+
tdb_traverse(wins_tdb, wins_writedb_traverse_fn, fp);
x_fclose(fp);
chmod(fnamenew,0644);
unlink(fname);
rename(fnamenew,fname);
+
+ err_exit:
+
+ SAFE_FREE(fnamenew);
+ TALLOC_FREE(fname);
+
if (background) {
_exit(0);
}
Process a internal Samba message receiving a wins record.
***************************************************************************/
-void nmbd_wins_new_entry(int msg_type, struct process_id src,
- void *buf, size_t len, void *private_data)
+void nmbd_wins_new_entry(struct messaging_context *msg,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id server_id,
+ DATA_BLOB *data)
{
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");
+ bool overwrite=False;
+ struct in_addr our_fake_ip;
int i;
+ our_fake_ip = interpret_addr2("0.0.0.0");
if (buf==NULL) {
return;
}
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 (!ip_equal_v4(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))
+ if (ip_equal_v4(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 (ip_equal_v4(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 {
- if (ip_equal(record->wins_ip, namerec->data.wins_ip))
+ if (ip_equal_v4(record->wins_ip, namerec->data.wins_ip))
overwrite=True;
- if (ip_equal(namerec->data.wins_ip, our_fake_ip))
+ if (ip_equal_v4(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))
+ if (ip_equal_v4(record->wins_ip, namerec->data.wins_ip))
overwrite=True;
}