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/>.
*/
#include "includes.h"
+#include "system/time.h"
+#include "system/filesys.h"
+#include "libcli/raw/request.h"
+#include "libcli/libcli.h"
#include "libcli/raw/libcliraw.h"
+#include "librpc/gen_ndr/security.h"
+#include "auth/credentials/credentials.h"
+#include "auth/gensec/gensec.h"
#define NSERVERS 2
#define NINSTANCES 2
struct smbcli_state *cli[NINSTANCES];
char *server_name;
char *share_name;
- char *username;
- char *password;
+ struct cli_credentials *credentials;
} servers[NSERVERS];
/* the seeds and flags for each operation */
static struct {
int notify_count;
NTSTATUS status;
- struct smb_notify notify;
+ union smb_notify notify;
} notifies[NSERVERS][NINSTANCES];
/* info relevant to the current operation */
for (j=0;j<NINSTANCES;j++) {
if (servers[i].cli[j]) {
smbcli_tdis(servers[i].cli[j]);
- smbcli_shutdown(servers[i].cli[j]);
+ talloc_free(servers[i].cli[j]);
servers[i].cli[j] = NULL;
}
}
NTSTATUS status;
printf("Connecting to \\\\%s\\%s as %s - instance %d\n",
servers[i].server_name, servers[i].share_name,
- servers[i].username, j);
+ servers[i].credentials->username, j);
+
+ cli_credentials_set_workstation(servers[i].credentials,
+ "gentest", CRED_SPECIFIED);
+
status = smbcli_full_connection(NULL, &servers[i].cli[j],
- "gentest",
- servers[i].server_name, NULL,
- servers[i].share_name, "?????",
- servers[i].username, lp_workgroup(),
- servers[i].password, 0, NULL);
+ servers[i].server_name,
+ servers[i].share_name, NULL,
+ servers[i].credentials, NULL);
if (!NT_STATUS_IS_OK(status)) {
printf("Failed to connect to \\\\%s\\%s - %s\n",
servers[i].server_name, servers[i].share_name,
}
smbcli_oplock_handler(servers[i].cli[j]->transport, oplock_handler, NULL);
- smbcli_transport_idle_handler(servers[i].cli[j]->transport, idle_func, 1, NULL);
+ smbcli_transport_idle_handler(servers[i].cli[j]->transport, idle_func, 50000, NULL);
}
}
static uint_t time_skew(void)
{
uint_t ret;
- ret = ABS(servers[0].cli[0]->transport->negotiate.server_time -
+ ret = labs(servers[0].cli[0]->transport->negotiate.server_time -
servers[1].cli[0]->transport->negotiate.server_time);
return ret + 300;
}
*/
static uint32_t gen_access_mask(void)
{
- if (gen_chance(50)) return SEC_RIGHT_MAXIMUM_ALLOWED;
- if (gen_chance(20)) return GENERIC_RIGHTS_FILE_ALL_ACCESS;
+ if (gen_chance(50)) return SEC_FLAG_MAXIMUM_ALLOWED;
+ if (gen_chance(20)) return SEC_FILE_ALL;
return gen_bits_mask(0xFFFFFFFF);
}
"ASOMEWHATLONGERATTRIBUTEVALUE"};
int i;
+ ZERO_STRUCT(ea);
+
do {
i = gen_int_range(0, ARRAY_SIZE(names)-1);
} while (ignore_pattern(names[i]));
*/
static void async_notify(struct smbcli_request *req)
{
- struct smb_notify notify;
+ union smb_notify notify;
NTSTATUS status;
int i, j;
uint16_t tid;
tid = SVAL(req->in.hdr, HDR_TID);
+ notify.nttrans.level = RAW_NOTIFY_NTTRANS;
status = smb_raw_changenotify_recv(req, current_op.mem_ctx, ¬ify);
if (NT_STATUS_IS_OK(status)) {
printf("notify tid=%d num_changes=%d action=%d name=%s\n",
tid,
- notify.out.num_changes,
- notify.out.changes[0].action,
- notify.out.changes[0].name.s);
+ notify.nttrans.out.num_changes,
+ notify.nttrans.out.changes[0].action,
+ notify.nttrans.out.changes[0].name.s);
}
for (i=0;i<NSERVERS;i++) {
}
}
+static void oplock_handler_close_recv(struct smbcli_request *req)
+{
+ NTSTATUS status;
+ status = smbcli_request_simple_recv(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("close failed in oplock_handler\n");
+ smb_panic("close failed in oplock_handler");
+ }
+}
+
/*
the oplock handler will either ack the break or close the file
*/
static BOOL oplock_handler(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *private)
{
union smb_close io;
- NTSTATUS status;
int i, j;
BOOL do_close;
struct smbcli_tree *tree = NULL;
+ struct smbcli_request *req;
srandom(current_op.seed);
do_close = gen_chance(50);
printf("oplock close fnum=%d\n", fnum);
io.close.level = RAW_CLOSE_CLOSE;
- io.close.in.fnum = fnum;
+ io.close.in.file.fnum = fnum;
io.close.in.write_time = 0;
- status = smb_raw_close(tree, &io);
+ req = smb_raw_close_send(tree, &io);
- if (!NT_STATUS_IS_OK(status)) {
- printf("WARNING: close failed in oplock_handler_close - %s\n", nt_errstr(status));
+ if (req == NULL) {
+ printf("WARNING: close failed in oplock_handler_close\n");
+ return False;
}
+
+ req->async.fn = oplock_handler_close_recv;
+ req->async.private = NULL;
+
return True;
}
for (j=0;j<NINSTANCES;j++) {
for (i=1;i<NSERVERS;i++) {
int n;
- struct smb_notify not1, not2;
+ union smb_notify not1, not2;
if (notifies[0][j].notify_count != notifies[i][j].notify_count) {
if (tries++ < 10) goto again;
not1 = notifies[0][j].notify;
not2 = notifies[i][j].notify;
- for (n=0;n<not1.out.num_changes;n++) {
- if (not1.out.changes[n].action !=
- not2.out.changes[n].action) {
+ for (n=0;n<not1.nttrans.out.num_changes;n++) {
+ if (not1.nttrans.out.changes[n].action !=
+ not2.nttrans.out.changes[n].action) {
printf("Notify action %d inconsistent %d %d\n", n,
- not1.out.changes[n].action,
- not2.out.changes[n].action);
+ not1.nttrans.out.changes[n].action,
+ not2.nttrans.out.changes[n].action);
return False;
}
- if (strcmp(not1.out.changes[n].name.s,
- not2.out.changes[n].name.s)) {
+ if (strcmp(not1.nttrans.out.changes[n].name.s,
+ not2.nttrans.out.changes[n].name.s)) {
printf("Notify name %d inconsistent %s %s\n", n,
- not1.out.changes[n].name.s,
- not2.out.changes[n].name.s);
+ not1.nttrans.out.changes[n].name.s,
+ not2.nttrans.out.changes[n].name.s);
return False;
}
- if (not1.out.changes[n].name.private_length !=
- not2.out.changes[n].name.private_length) {
+ if (not1.nttrans.out.changes[n].name.private_length !=
+ not2.nttrans.out.changes[n].name.private_length) {
printf("Notify name length %d inconsistent %d %d\n", n,
- not1.out.changes[n].name.private_length,
- not2.out.changes[n].name.private_length);
+ not1.nttrans.out.changes[n].name.private_length,
+ not2.nttrans.out.changes[n].name.private_length);
return False;
}
}
} while(0)
#define CHECK_TIMES_EQUAL(field) do { \
- if (ABS(parm[0].field - parm[1].field) > time_skew() && \
+ if (labs(parm[0].field - parm[1].field) > time_skew() && \
!ignore_pattern(#field)) { \
printf("Mismatch in %s - 0x%x 0x%x\n", #field, \
(int)parm[0].field, (int)parm[1].field); \
} while(0)
#define CHECK_NTTIMES_EQUAL(field) do { \
- if (ABS(nt_time_to_unix(parm[0].field) - \
+ if (labs(nt_time_to_unix(parm[0].field) - \
nt_time_to_unix(parm[1].field)) > time_skew() && \
!ignore_pattern(#field)) { \
printf("Mismatch in %s - 0x%x 0x%x\n", #field, \
CHECK_TIMES_EQUAL(openx.out.write_time);
/* open creates a new file handle */
- ADD_HANDLE(parm[0].openx.in.fname, openx.out.fnum);
+ ADD_HANDLE(parm[0].openx.in.fname, openx.out.file.fnum);
return True;
}
union smb_open parm[NSERVERS];
NTSTATUS status[NSERVERS];
- parm[0].open.level = RAW_OPEN_OPEN;
- parm[0].open.in.flags = gen_bits_mask2(0xF, 0xFFFF);
- parm[0].open.in.search_attrs = gen_attrib();
- parm[0].open.in.fname = gen_fname_open(instance);
+ parm[0].openold.level = RAW_OPEN_OPEN;
+ parm[0].openold.in.open_mode = gen_bits_mask2(0xF, 0xFFFF);
+ parm[0].openold.in.search_attrs = gen_attrib();
+ parm[0].openold.in.fname = gen_fname_open(instance);
if (!options.use_oplocks) {
/* mask out oplocks */
- parm[0].open.in.flags &= ~(OPENX_FLAGS_REQUEST_OPLOCK|
- OPENX_FLAGS_REQUEST_BATCH_OPLOCK);
+ parm[0].openold.in.open_mode &= ~(OPENX_FLAGS_REQUEST_OPLOCK|
+ OPENX_FLAGS_REQUEST_BATCH_OPLOCK);
}
GEN_COPY_PARM;
GEN_CALL(smb_raw_open(tree, current_op.mem_ctx, &parm[i]));
- CHECK_EQUAL(open.out.attrib);
- CHECK_TIMES_EQUAL(open.out.write_time);
- CHECK_EQUAL(open.out.size);
- CHECK_EQUAL(open.out.rmode);
+ CHECK_EQUAL(openold.out.attrib);
+ CHECK_TIMES_EQUAL(openold.out.write_time);
+ CHECK_EQUAL(openold.out.size);
+ CHECK_EQUAL(openold.out.rmode);
/* open creates a new file handle */
- ADD_HANDLE(parm[0].open.in.fname, open.out.fnum);
+ ADD_HANDLE(parm[0].openold.in.fname, openold.out.file.fnum);
return True;
}
CHECK_EQUAL(ntcreatex.out.is_directory);
/* ntcreatex creates a new file handle */
- ADD_HANDLE(parm[0].ntcreatex.in.fname, ntcreatex.out.fnum);
+ ADD_HANDLE(parm[0].ntcreatex.in.fname, ntcreatex.out.file.fnum);
return True;
}
NTSTATUS status[NSERVERS];
parm[0].close.level = RAW_CLOSE_CLOSE;
- parm[0].close.in.fnum = gen_fnum_close(instance);
+ parm[0].close.in.file.fnum = gen_fnum_close(instance);
parm[0].close.in.write_time = gen_timet();
GEN_COPY_PARM;
- GEN_SET_FNUM(close.in.fnum);
+ GEN_SET_FNUM(close.in.file.fnum);
GEN_CALL(smb_raw_close(tree, &parm[i]));
- REMOVE_HANDLE(close.in.fnum);
+ REMOVE_HANDLE(close.in.file.fnum);
return True;
}
*/
static BOOL handler_unlink(int instance)
{
- struct smb_unlink parm[NSERVERS];
+ union smb_unlink parm[NSERVERS];
NTSTATUS status[NSERVERS];
- parm[0].in.pattern = gen_pattern();
- parm[0].in.attrib = gen_attrib();
+ parm[0].unlink.in.pattern = gen_pattern();
+ parm[0].unlink.in.attrib = gen_attrib();
GEN_COPY_PARM;
GEN_CALL(smb_raw_unlink(tree, &parm[i]));
*/
static BOOL handler_chkpath(int instance)
{
- struct smb_chkpath parm[NSERVERS];
+ union smb_chkpath parm[NSERVERS];
NTSTATUS status[NSERVERS];
- parm[0].in.path = gen_fname_open(instance);
+ parm[0].chkpath.in.path = gen_fname_open(instance);
GEN_COPY_PARM;
GEN_CALL(smb_raw_chkpath(tree, &parm[i]));
*/
static BOOL handler_seek(int instance)
{
- struct smb_seek parm[NSERVERS];
+ union smb_seek parm[NSERVERS];
NTSTATUS status[NSERVERS];
- parm[0].in.fnum = gen_fnum(instance);
- parm[0].in.mode = gen_bits_mask2(0x3, 0xFFFF);
- parm[0].in.offset = gen_offset();
+ parm[0].lseek.in.file.fnum = gen_fnum(instance);
+ parm[0].lseek.in.mode = gen_bits_mask2(0x3, 0xFFFF);
+ parm[0].lseek.in.offset = gen_offset();
GEN_COPY_PARM;
- GEN_SET_FNUM(in.fnum);
+ GEN_SET_FNUM(lseek.in.file.fnum);
GEN_CALL(smb_raw_seek(tree, &parm[i]));
- CHECK_EQUAL(out.offset);
+ CHECK_EQUAL(lseek.out.offset);
return True;
}
NTSTATUS status[NSERVERS];
parm[0].readx.level = RAW_READ_READX;
- parm[0].readx.in.fnum = gen_fnum(instance);
+ parm[0].readx.in.file.fnum = gen_fnum(instance);
parm[0].readx.in.offset = gen_offset();
parm[0].readx.in.mincnt = gen_io_count();
parm[0].readx.in.maxcnt = gen_io_count();
parm[0].readx.in.remaining = gen_io_count();
- parm[0].readx.out.data = talloc(current_op.mem_ctx,
- MAX(parm[0].readx.in.mincnt, parm[0].readx.in.maxcnt));
+ parm[0].readx.in.read_for_execute = gen_bool();
+ parm[0].readx.out.data = talloc_size(current_op.mem_ctx,
+ MAX(parm[0].readx.in.mincnt, parm[0].readx.in.maxcnt));
GEN_COPY_PARM;
- GEN_SET_FNUM(readx.in.fnum);
+ GEN_SET_FNUM(readx.in.file.fnum);
GEN_CALL(smb_raw_read(tree, &parm[i]));
CHECK_EQUAL(readx.out.remaining);
NTSTATUS status[NSERVERS];
parm[0].writex.level = RAW_WRITE_WRITEX;
- parm[0].writex.in.fnum = gen_fnum(instance);
+ parm[0].writex.in.file.fnum = gen_fnum(instance);
parm[0].writex.in.offset = gen_offset();
parm[0].writex.in.wmode = gen_bits_mask(0xFFFF);
parm[0].writex.in.remaining = gen_io_count();
parm[0].writex.in.count = gen_io_count();
- parm[0].writex.in.data = talloc_zero(current_op.mem_ctx, parm[0].writex.in.count);
+ parm[0].writex.in.data = talloc_zero_size(current_op.mem_ctx, parm[0].writex.in.count);
GEN_COPY_PARM;
- GEN_SET_FNUM(writex.in.fnum);
+ GEN_SET_FNUM(writex.in.file.fnum);
GEN_CALL(smb_raw_write(tree, &parm[i]));
CHECK_EQUAL(writex.out.nwritten);
int n, nlocks;
parm[0].lockx.level = RAW_LOCK_LOCKX;
- parm[0].lockx.in.fnum = gen_fnum(instance);
+ parm[0].lockx.in.file.fnum = gen_fnum(instance);
parm[0].lockx.in.mode = gen_lock_mode();
parm[0].lockx.in.timeout = gen_timeout();
do {
} while (nlocks == 0);
if (nlocks > 0) {
- parm[0].lockx.in.locks = talloc(current_op.mem_ctx,
- sizeof(parm[0].lockx.in.locks[0]) * nlocks);
+ parm[0].lockx.in.locks = talloc_array(current_op.mem_ctx,
+ struct smb_lock_entry,
+ nlocks);
for (n=0;n<nlocks;n++) {
parm[0].lockx.in.locks[n].pid = gen_pid();
parm[0].lockx.in.locks[n].offset = gen_offset();
}
GEN_COPY_PARM;
- GEN_SET_FNUM(lockx.in.fnum);
+ GEN_SET_FNUM(lockx.in.file.fnum);
GEN_CALL(smb_raw_lock(tree, &parm[i]));
return True;
CHECK_EQUAL(attribute_tag_information.out.attrib);
CHECK_EQUAL(attribute_tag_information.out.reparse_tag);
break;
+
+ /* Unhandled levels */
+
+ case RAW_FILEINFO_SEC_DESC:
+ case RAW_FILEINFO_EA_LIST:
+ case RAW_FILEINFO_UNIX_BASIC:
+ case RAW_FILEINFO_UNIX_LINK:
+ case RAW_FILEINFO_SMB2_ALL_EAS:
+ case RAW_FILEINFO_SMB2_ALL_INFORMATION:
+ break;
}
return True;
union smb_fileinfo parm[NSERVERS];
NTSTATUS status[NSERVERS];
- parm[0].generic.in.fname = gen_fname_open(instance);
+ parm[0].generic.in.file.path = gen_fname_open(instance);
gen_fileinfo(instance, &parm[0]);
union smb_fileinfo parm[NSERVERS];
NTSTATUS status[NSERVERS];
- parm[0].generic.in.fnum = gen_fnum(instance);
+ parm[0].generic.in.file.fnum = gen_fnum(instance);
gen_fileinfo(instance, &parm[0]);
GEN_COPY_PARM;
- GEN_SET_FNUM(generic.in.fnum);
+ GEN_SET_FNUM(generic.in.file.fnum);
GEN_CALL(smb_raw_fileinfo(tree, current_op.mem_ctx, &parm[i]));
return cmp_fileinfo(instance, parm, status);
info->standard.in.access_time = gen_timet();
info->standard.in.write_time = gen_timet();
break;
- case RAW_SFILEINFO_EA_SET:
- info->ea_set.in.ea = gen_ea_struct();
+ case RAW_SFILEINFO_EA_SET: {
+ static struct ea_struct ea;
+ info->ea_set.in.num_eas = 1;
+ info->ea_set.in.eas = &ea;
+ info->ea_set.in.eas[0] = gen_ea_struct();
+ }
break;
case RAW_SFILEINFO_BASIC_INFO:
case RAW_SFILEINFO_BASIC_INFORMATION:
case RAW_SFILEINFO_MODE_INFORMATION:
info->mode_information.in.mode = gen_bits_mask(0xFFFFFFFF);
break;
+ case RAW_SFILEINFO_GENERIC:
+ case RAW_SFILEINFO_SEC_DESC:
+ case RAW_SFILEINFO_UNIX_BASIC:
+ case RAW_SFILEINFO_UNIX_LINK:
+ case RAW_SFILEINFO_UNIX_HLINK:
+ case RAW_SFILEINFO_1023:
+ case RAW_SFILEINFO_1025:
+ case RAW_SFILEINFO_1029:
+ case RAW_SFILEINFO_1032:
+ case RAW_SFILEINFO_1039:
+ case RAW_SFILEINFO_1040:
+ /* Untested */
+ break;
}
}
union smb_setfileinfo parm[NSERVERS];
NTSTATUS status[NSERVERS];
- parm[0].generic.file.fname = gen_fname_open(instance);
+ parm[0].generic.in.file.path = gen_fname_open(instance);
gen_setfileinfo(instance, &parm[0]);
union smb_setfileinfo parm[NSERVERS];
NTSTATUS status[NSERVERS];
- parm[0].generic.file.fnum = gen_fnum(instance);
+ parm[0].generic.in.file.fnum = gen_fnum(instance);
gen_setfileinfo(instance, &parm[0]);
GEN_COPY_PARM;
- GEN_SET_FNUM(generic.file.fnum);
+ GEN_SET_FNUM(generic.in.file.fnum);
GEN_CALL(smb_raw_setfileinfo(tree, &parm[i]));
return True;
*/
static BOOL handler_notify(int instance)
{
- struct smb_notify parm[NSERVERS];
+ union smb_notify parm[NSERVERS];
int n;
- parm[0].in.buffer_size = gen_io_count();
- parm[0].in.completion_filter = gen_bits_mask(0xFF);
- parm[0].in.fnum = gen_fnum(instance);
- parm[0].in.recursive = gen_bool();
+ ZERO_STRUCT(parm[0]);
+ parm[0].nttrans.level = RAW_NOTIFY_NTTRANS;
+ parm[0].nttrans.in.buffer_size = gen_io_count();
+ parm[0].nttrans.in.completion_filter = gen_bits_mask(0xFF);
+ parm[0].nttrans.in.file.fnum = gen_fnum(instance);
+ parm[0].nttrans.in.recursive = gen_bool();
GEN_COPY_PARM;
- GEN_SET_FNUM(in.fnum);
+ GEN_SET_FNUM(nttrans.in.file.fnum);
for (n=0;n<NSERVERS;n++) {
struct smbcli_request *req;
current_op.opnum = op;
current_op.name = gen_ops[which_op].name;
current_op.status = NT_STATUS_OK;
- current_op.mem_ctx = talloc_init("%s", current_op.name);
+ current_op.mem_ctx = talloc_named(NULL, 0, "%s", current_op.name);
ret = gen_ops[which_op].handler(instance);
- talloc_destroy(current_op.mem_ctx);
+ talloc_free(current_op.mem_ctx);
gen_ops[which_op].count++;
if (NT_STATUS_IS_OK(current_op.status)) {
/* generate the seeds - after this everything is deterministic */
if (options.use_preset_seeds) {
int numops;
- char **preset = file_lines_load(options.seeds_file, &numops);
+ char **preset = file_lines_load(options.seeds_file, &numops, NULL);
if (!preset) {
printf("Failed to load %s - %s\n", options.seeds_file, strerror(errno));
exit(1);
");
}
+/**
+ split a UNC name into server and share names
+*/
+static BOOL split_unc_name(const char *unc, char **server, char **share)
+{
+ char *p = strdup(unc);
+ if (!p) return False;
+ all_string_sub(p, "\\", "/", 0);
+ if (strncmp(p, "//", 2) != 0) return False;
+
+ (*server) = p+2;
+ p = strchr(*server, '/');
+ if (!p) return False;
+
+ *p = 0;
+ (*share) = p+1;
+
+ return True;
+}
+
+
+
/****************************************************************************
main program
****************************************************************************/
int main(int argc, char *argv[])
{
int opt;
- int i;
+ int i, username_count=0;
BOOL ret;
setlinebuf(stdout);
for (i=0;i<NSERVERS;i++) {
const char *share = argv[1+i];
+ servers[i].credentials = cli_credentials_init(NULL);
if (!split_unc_name(share, &servers[i].server_name, &servers[i].share_name)) {
printf("Invalid share name '%s'\n", share);
return -1;
argc -= NSERVERS;
argv += NSERVERS;
- lp_load(dyn_CONFIGFILE,True,False,False);
- load_interfaces();
+ lp_load();
+
+ servers[0].credentials = cli_credentials_init(talloc_autofree_context());
+ servers[1].credentials = cli_credentials_init(talloc_autofree_context());
+ cli_credentials_guess(servers[0].credentials);
+ cli_credentials_guess(servers[1].credentials);
options.seed = time(NULL);
options.numops = 1000;
while ((opt = getopt(argc, argv, "U:s:o:ad:i:AOhS:LFXC")) != EOF) {
switch (opt) {
case 'U':
- i = servers[0].username?1:0;
- if (!split_username(optarg,
- &servers[i].username,
- &servers[i].password)) {
- printf("Must supply USER%%PASS\n");
- return -1;
+ if (username_count == 2) {
+ usage();
+ exit(1);
}
+ cli_credentials_parse_string(servers[username_count].credentials,
+ optarg, CRED_SPECIFIED);
+ username_count++;
break;
case 'd':
DEBUGLEVEL = atoi(optarg);
options.analyze_continuous = True;
break;
case 'i':
- options.ignore_patterns = file_lines_load(optarg, NULL);
+ options.ignore_patterns = file_lines_load(optarg, NULL, NULL);
break;
case 'h':
usage();
}
}
- if (!servers[0].username) {
+ gensec_init();
+
+ if (username_count == 0) {
usage();
return -1;
}
- if (!servers[1].username) {
- servers[1].username = servers[0].username;
- servers[1].password = servers[0].password;
+ if (username_count == 1) {
+ servers[1].credentials = servers[0].credentials;
}
printf("seed=%u\n", options.seed);