it under the terms of the GNU General Public License as published by
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,
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, see <http://www.gnu.org/licenses/>.
-
+
Converted to store WINS data in a tdb. Dec 2005. JRA.
*/
#include "system/filesys.h"
#include "nmbd/nmbd.h"
#include "util_tdb.h"
+#include "lib/util/util_file.h"
#define WINS_LIST "wins.dat"
#define WINS_VERSION 1
static struct name_record *wins_record_to_name_record(TDB_DATA key, TDB_DATA data)
{
struct name_record *namerec = NULL;
- uint16 nb_flags;
+ uint16_t nb_flags;
unsigned char nr_src;
- uint32 death_time, refresh_time;
- uint32 id_low, id_high;
- uint32 saddr;
- uint32 wins_flags;
- uint32 num_ips;
+ uint32_t death_time, refresh_time;
+ uint32_t id_low, id_high;
+ uint32_t saddr;
+ uint32_t wins_flags;
+ uint32_t num_ips;
size_t len;
int i;
/* We're using a byte-by-byte compare, so we must be sure that
* unused space doesn't have garbage in it.
*/
-
+
for( i = strlen( namerec->name.name ); i < sizeof( namerec->name.name ); i++ ) {
namerec->name.name[i] = '\0';
}
namerec->data.death_time = (time_t)death_time;
namerec->data.refresh_time = (time_t)refresh_time;
namerec->data.id = id_low;
-#if defined(HAVE_LONGLONG)
namerec->data.id |= ((uint64_t)id_high << 32);
-#endif
namerec->data.wins_ip.s_addr = saddr;
namerec->data.wins_flags = wins_flags,
namerec->data.num_ips = num_ips;
TDB_DATA data;
size_t len = 0;
int i;
- uint32 id_low = (namerec->data.id & 0xFFFFFFFF);
-#if defined(HAVE_LONGLONG)
- uint32 id_high = (namerec->data.id >> 32) & 0xFFFFFFFF;
-#else
- uint32 id_high = 0;
-#endif
+ uint32_t id_low = (namerec->data.id & 0xFFFFFFFF);
+ uint32_t id_high = (namerec->data.id >> 32) & 0xFFFFFFFF;
ZERO_STRUCT(data);
len = (2 + 1 + (7*4)); /* "wbddddddd" */
len += (namerec->data.num_ips * 4);
- data.dptr = (uint8 *)SMB_MALLOC(len);
+ data.dptr = (uint8_t *)SMB_MALLOC(len);
if (!data.dptr) {
return data;
}
len = tdb_pack(data.dptr, data.dsize, "wbddddddd",
namerec->data.nb_flags,
(unsigned char)namerec->data.source,
- (uint32)namerec->data.death_time,
- (uint32)namerec->data.refresh_time,
+ (uint32_t)namerec->data.death_time,
+ (uint32_t)namerec->data.refresh_time,
id_low,
id_high,
- (uint32)namerec->data.wins_ip.s_addr,
- (uint32)namerec->data.wins_flags,
- (uint32)namerec->data.num_ips );
+ (uint32_t)namerec->data.wins_ip.s_addr,
+ (uint32_t)namerec->data.wins_flags,
+ (uint32_t)namerec->data.num_ips );
for (i = 0; i < namerec->data.num_ips; i++) {
SIVAL(data.dptr, len + (i*4), namerec->data.ip[i].s_addr);
memset(keydata, '\0', sizeof(keydata));
pull_ascii_nstring(keydata, sizeof(unstring), nmbname->name);
- strupper_m(keydata);
+ (void)strupper_m(keydata);
keydata[sizeof(unstring)] = nmbname->name_type;
- key.dptr = (uint8 *)keydata;
+ key.dptr = (uint8_t *)keydata;
key.dsize = sizeof(keydata);
return key;
}
key = name_to_key(nmbname);
- data = tdb_fetch_compat(wins_tdb, key);
+ data = tdb_fetch(wins_tdb, key);
if (data.dsize == 0) {
return NULL;
break;
}
}
-
+
DLIST_ADD(wins_server_subnet->namelist, namerec);
return namerec;
}
static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
{
struct name_record *namerec = NULL;
- XFILE *fp = (XFILE *)state;
+ FILE *fp = (FILE *)state;
if (kbuf.dsize != sizeof(unstring) + 1) {
return 0;
return 0;
}
-void dump_wins_subnet_namelist(XFILE *fp)
+void dump_wins_subnet_namelist(FILE *fp)
{
tdb_traverse(wins_tdb, traverse_fn, (void *)fp);
}
static uint64_t 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++;
}
static void wins_hook(const char *operation, struct name_record *namerec, int ttl)
{
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
char *command = NULL;
- char *cmd = lp_wins_hook();
+ char *cmd = lp_wins_hook(talloc_tos(), lp_sub);
char *p, *namestr;
int i;
TALLOC_CTX *ctx = talloc_tos();
return;
}
}
-
+
/* Use the name without the nametype (and scope) appended */
namestr = nmb_namestr(&namerec->name);
}
DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
- smbrun(command, NULL);
+ smbrun(command, NULL, NULL);
TALLOC_FREE(command);
}
bool initialise_wins(void)
{
time_t time_now = time(NULL);
- XFILE *fp;
+ FILE *fp;
char line[1024];
+ char *db_path;
+ char *list_path;
if(!lp_we_are_a_wins_server()) {
return True;
}
+ db_path = state_path(talloc_tos(), "wins.tdb");
+ if (db_path == NULL) {
+ return false;
+ }
+
/* Open the wins.tdb. */
- wins_tdb = tdb_open_log(state_path("wins.tdb"), 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
+ wins_tdb = tdb_open_log(db_path, 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
O_CREAT|O_RDWR, 0600);
+ TALLOC_FREE(db_path);
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(state_path(WINS_LIST),O_RDONLY,0)) == NULL) {
+ list_path = state_path(talloc_tos(), WINS_LIST);
+ if (list_path == NULL) {
+ tdb_close(wins_tdb);
+ return false;
+ }
+
+ fp = fopen(list_path, "r");
+ TALLOC_FREE(list_path);
+ if (fp == 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)) {
+ while (!feof(fp)) {
char *name_str = NULL;
char *ip_str = NULL;
char *ttl_str = NULL, *nb_flags_str = NULL;
/* Read a line from the wins.dat file. Strips whitespace
from the beginning and end of the line. */
- if (!fgets_slash(line,sizeof(line),fp)) {
+ if (!fgets_slash(NULL, line, sizeof(line), fp)) {
continue;
}
if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||
version != WINS_VERSION) {
DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line));
- x_fclose(fp);
+ fclose(fp);
return True;
}
continue;
/* Allocate the space for the ip_list. */
if((ip_list = SMB_MALLOC_ARRAY( struct in_addr, num_ips)) == NULL) {
DEBUG(0,("initialise_wins: Malloc fail !\n"));
- x_fclose(fp);
+ fclose(fp);
TALLOC_FREE(frame);
return False;
}
SAFE_FREE(ip_list);
}
- x_fclose(fp);
+ 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;
- uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
+ uint16_t 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);
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.
+ a registration failure to the original requester.
************************************************************************/
static void wins_register_query_success(struct subnet_record *subrec,
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);
+ send_wins_name_registration_response(ACT_ERR, 0, orig_reg_packet);
orig_reg_packet->locked = False;
free_packet(orig_reg_packet);
/*
* 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
+ * didn't want it. But we can't just do that as an arbitrary
* 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
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);
+ uint16_t 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;
/*
* 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
+ * machine claims to own it. But we can't just do that as an arbitrary
* 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
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);
+ uint16_t 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;
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",
+received for name %s from IP %s on subnet %s. Error - group names should not be multihomed.\n",
nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
return;
}
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) ));
+to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
send_wins_name_registration_response(0, ttl, p);
return;
}
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
update_wins_owner(namerec, our_fake_ip);
update_wins_flag(namerec, WINS_ACTIVE);
}
-
+
wins_hook("refresh", namerec, ttl);
send_wins_name_registration_response(0, ttl, p);
return;
/***********************************************************************
Deal with the special name query for *<1b>.
***********************************************************************/
-
-static void process_wins_dmb_query_request(struct subnet_record *subrec,
+
+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;
* 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)) {
+ if(lp_wins_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) ));
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);
+ uint16_t 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;
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) ));
+to release name %s from IP %s.\n", 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)) ) {
Write out one record.
******************************************************************/
-void wins_write_name_record(struct name_record *namerec, XFILE *fp)
+void wins_write_name_record(struct name_record *namerec, FILE *fp)
{
int i;
struct tm *tm;
if( namerec->data.source == REGISTER_NAME ) {
unstring name;
pull_ascii_nstring(name, sizeof(name), namerec->name.name);
- x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */
+ fprintf(fp, "\"%s#%02x\" %d ", name,
+ namerec->name.name_type, /* Ignore scope. */
(int)namerec->data.death_time);
for (i = 0; i < namerec->data.num_ips; i++)
- x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
- x_fprintf( fp, "%2xR\n", namerec->data.nb_flags );
+ fprintf(fp, "%s ", inet_ntoa(namerec->data.ip[i]));
+ fprintf(fp, "%2xR\n", namerec->data.nb_flags);
}
}
static int wins_writedb_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
{
struct name_record *namerec = NULL;
- XFILE *fp = (XFILE *)state;
+ FILE *fp = (FILE *)state;
if (kbuf.dsize != sizeof(unstring) + 1) {
return 0;
char *fname = NULL;
char *fnamenew = NULL;
- XFILE *fp;
+ int fd;
+ FILE *fp;
if (background) {
if (!last_write_time) {
/* 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()) {
+ if (fork()) {
return;
}
if (tdb_reopen(wins_tdb)) {
}
}
- if (!(fname = state_path(WINS_LIST))) {
+ if (!(fname = state_path(talloc_tos(), WINS_LIST))) {
goto err_exit;
}
/* This is safe as the 0 length means "don't expand". */
all_string_sub(fname,"//", "/", 0);
- if (asprintf(&fnamenew, "%s.%u", fname, (unsigned int)sys_getpid()) < 0) {
+ if (asprintf(&fnamenew, "%s.%u", fname, (unsigned int)getpid()) < 0) {
+ goto err_exit;
+ }
+
+ fd = open(fnamenew, O_WRONLY|O_CREAT, 0644);
+ if (fd == -1) {
+ DBG_ERR("Can't open %s: %s\n", fnamenew, strerror(errno));
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)));
+ fp = fdopen(fd, "w");
+ if (fp == NULL) {
+ DBG_ERR("fdopen failed: %s\n", strerror(errno));
+ close(fd);
goto err_exit;
}
+ fd = -1;
DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
- x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0);
+ fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0);
tdb_traverse(wins_tdb, wins_writedb_traverse_fn, fp);
- x_fclose(fp);
+ fclose(fp);
chmod(fnamenew,0644);
unlink(fname);
rename(fnamenew,fname);
if (buf==NULL) {
return;
}
-
+
/* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */
record=(WINS_RECORD *)buf;
-
+
make_nmb_name(&question, record->name, record->type);
namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
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) {
}
}
-
+
/* 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 */
/* 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) {
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))
else {
if (ip_equal_v4(record->wins_ip, namerec->data.wins_ip))
overwrite=True;
-
+
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_v4(record->wins_ip, namerec->data.wins_ip))
overwrite=True;
-
+
}
if (overwrite == False)