WINSEDIT.C

Stefan (metze) Metzmacher metze at metzemix.de
Thu May 1 07:33:17 GMT 2003


Sorry, I missed the file :-)

Hi Jan,Volker

here is the start of the winsedit tool.

It would be cool if someone can finish it,
because I'm busy with the vfs interface and the quota stuff.

for now it can list all entries form the wins_test.tdb.
(We don't want to destroy the wins.tdb :-)

A nice feature would be if it's possible to specify the location of the 
wins.tdb
e.g. winsedit -l -f wins2-tdb

Please note:

When the winsedit tool will be able to edit entries in the wins.tdb
YOU MUST USE IT WHEN NMBD IS  *NOT* RUNNING!!!!
otherwise the information will not be used and overwritten!!!
Because of the current layout of nmbd.
nmbd read's the wins.tdb on start and then holds the a list in memory.
then it flushes all entries to a new wins.tdb file periodicly and delete 
the old file!!!

For the winsserver it would be good if we would have a proper interface to 
a winsdb backend.
witch would finally allow us to have allternative backends like LDAP.

But with the current nmbd layout it makes REALLY NO SENSE!


metze
-----------------------------------------------------------------------------
Stefan "metze" Metzmacher <metze at metzemix.de>  
-------------- next part --------------
/* 
   Unix SMB/CIFS implementation.
   winsdb editing frontend
      
   Copyright (C) Stefan (metze) Metzmacher 2003

   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_test.tdb"
#define WINS_VERSION 1

static void dump_name_record(struct name_record *rec, BOOL verbose)
{
	int i;

	if (verbose) {
		d_printf("name: %s#%02X\n",rec->name.name,rec->name.name_type);
#ifdef LARGE_SMB_OFF_T
		d_printf(" wins flags[%X] unique id[%llu]\n",
			rec->data.wins_flags,rec->data.id);
#else
		d_printf(" wins flags[%X] unique id[%lu]\n",
			rec->data.wins_flags,rec->data.id);
#endif
		for (i=0;i<rec->data.num_ips;i++) {
			d_printf("  ip: %s",
				inet_ntoa(rec->data.ip[i]));
			d_printf(" deadtime[%d] refreshtime[%d]",
				rec->data.death_time,rec->data.refresh_time);
			d_printf(" ownerip[%s]\n",inet_ntoa(rec->data.wins_ip));
		}
	} else {
		d_printf("%s#%02X ",rec->name.name,rec->name.name_type);
		
		for (i=0;i<rec->data.num_ips;i++) {
			d_printf(" %s",
				inet_ntoa(rec->data.ip[i]));
		}
		d_printf("\n");			
	}
}

/****************************************************************************
List all WINS database records.
*****************************************************************************/

BOOL list_wins_records(BOOL verbose)
{
	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;
*/
	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);

 		/* 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);
		}

		if((namerec=(struct name_record *)malloc(sizeof(struct name_record)))==NULL) {
			SAFE_FREE(ip_list);
			SAFE_FREE(dbuf.dptr);
			DEBUG(0,("initialise_wins: Malloc fail !\n"));
			return False;		
		}
		ZERO_STRUCTP(namerec);
		
		safe_strcpy(namerec->name.name,name,16);
		namerec->name.name_type = type;
		namerec->data.nb_flags = nb_flags;
		namerec->data.num_ips = num_ips;
		namerec->data.ip = ip_list;
		namerec->data.wins_ip = wins_ip;
		namerec->data.death_time = ttl;
		namerec->data.source = REGISTER_NAME;

		dump_name_record(namerec,verbose);
		SAFE_FREE(dbuf.dptr);
		SAFE_FREE(ip_list);
		SAFE_FREE(namerec);
	}
    
	tdb_close(tdb);
	return True;
}

static BOOL search_record_winsdb(const char *name, uint16 type)
{
	TDB_CONTEXT 		*tdb;
	TDB_DATA 		data, key;
	fstring 		keystr;
	fstring			name;
	fstring			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;

	/* set search key */
	slprintf(keystr, sizeof(keystr)-1, "%s%s#%02x", ENTRY_PREFIX, name, type);
	key.dptr = keystr;
	key.dsize = strlen (keystr) + 1;

	if (!(tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDONLY, 0600))) {
		return False;
	}

	/* get the record */
	data = tdb_fetch (pwd_tdb, key);
	if (!data.dptr) {
		DEBUG(0, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
		tdb_close (tdb);
		return False;
	}

	fstrcpy(name, kbuf.dptr+strlen(ENTRY_PREFIX));

	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);

	/* 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);
	}

	if((namerec=(struct name_record *)malloc(sizeof(struct name_record)))==NULL) {
		SAFE_FREE(ip_list);
		SAFE_FREE(dbuf.dptr);
		DEBUG(0,("initialise_wins: Malloc fail !\n"));
		return False;		
	}
	ZERO_STRUCTP(namerec);
	
	safe_strcpy(namerec->name.name,name,16);
	namerec->name.name_type = type;
	namerec->data.nb_flags = nb_flags;
	namerec->data.num_ips = num_ips;
	namerec->data.ip = ip_list;
	namerec->data.wins_ip = wins_ip;
	namerec->data.death_time = ttl;
	namerec->data.source = REGISTER_NAME;

	dump_name_record(namerec,verbose);
	SAFE_FREE(dbuf.dptr);
	SAFE_FREE(ip_list);
	SAFE_FREE(namerec);
	
	tdb_close(tdb);
	return True;
}

 int main (int argc, const char **argv)
{
	int opt;
	BOOL static_entry=True;
	BOOL default_times=False;
	BOOL verbose=False;
	poptContext pc;
	struct poptOption long_options[] = {
		POPT_AUTOHELP
		{"create",	'c', POPT_ARG_STRING, NULL, 0, "create/change record", "NAME"},
		{"add",		'a', POPT_ARG_STRING, NULL, 0, "an alias for create", "NAME:IPADDRESS"},
		{"delete",	'x', POPT_ARG_STRING, NULL, 0, "delete record", "NAME:IPADDRESS"},
		{"list",	'l', POPT_ARG_STRING, NULL, 0, "list all record", "[NAME]"},
		{"UNIQUE",	'U', POPT_ARG_STRING, NULL, 0, "unique name", "NAMETYPES"},
		{"GROUP",	'G', POPT_ARG_STRING, NULL, 0, "group name", "NAMETYPES"},
		{"wins-server",	'T', POPT_ARG_STRING, NULL, 0, "target wins server", "IPADDRESS"},
		{"static",	'S', POPT_ARG_NONE, &static_entry, True, "record don't expire", NULL},
		{"default-times",'D',POPT_ARG_NONE, &default_times, False, "default times for death and refresh time", NULL},
/* This parameter can be added when we have a better
   database format, witch will store all information
   to make wins replication completely working.
   --metze
		{"death-time",	't', POPT_ARG_STRING, NULL, 0, "death time", "TIME"},
		{"refresh-time",'r', POPT_ARG_STRING, NULL, 0, "refresh time", "TIME"},		
*/		{"verbose",	'v', POPT_ARG_NONE, &verbose, False, "be verbose", NULL},
		POPT_COMMON_SAMBA
		POPT_TABLEEND
	};

	setup_logging("winsedit", True);

	pc = poptGetContext(NULL, argc, argv, long_options,
			    POPT_CONTEXT_KEEP_FIRST);

	while((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt) {
			case 'c':
			case 'a':
				break;
			case 'x':
				break;
			case 'l':
				break;
			case 'T':
				break;
/*
			case 't':
				break;
			case 'r':
				break;
*/			default:
				poptPrintHelp(pc, stderr, 0);
				exit(1);
		}
	}

	poptGetArg(pc); /* Drop argv[0], the program name */

	if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
		fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE);
		exit(1);
	}

	if (!init_names())
		exit(1);

	list_wins_records(verbose);

	return 1;
}


More information about the samba-technical mailing list