test_client.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 1993-2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <syslog.h>
#include <signal.h>
#include <time.h>
#include <limits.h>
#include <sys/resource.h>
#include <fcntl.h>
#include <sys/resource.h>
#include <sys/systeminfo.h>
#include <errno.h>
#include <dhcp_impl.h>
#include <synch.h>
#include <netdb.h>
#include <locale.h>
#include <mtmalloc.h>
#include <libinetutil.h>
struct client {
int proto;
char chost[40];
int hlen;
int flags;
int state;
};
#define CLIENT_BUSY 0x1
#define CLIENT_FIRSTTIME 0x2
int fast = 0; /* higher load */
int bound = 0; /* only broadcast on given interface */
static int startindex;
static boolean_t time_to_go;
static int release_time = 0;
static int desynch = 1;
static double avg = 0;
static timespec_t avgslp;
static volatile int minind;
long sample_time = 10L;
long nsamples = 2;
static volatile ulong_t ops_outstanding;
int verbose = 0;
int dohost = 0;
int randcl = 0;
int randhlen = 0;
int randerr = 0;
int dos = 0;
int dofork = 0;
int printid = 0;
static void corrupt(char *, int);
static void
{
char *p;
switch (pkt) {
case DISCOVER:
p = "DISCOVER";
break;
case OFFER:
p = "OFFER";
break;
case REQUEST:
p = "REQUEST";
break;
case DECLINE:
p = "DECLINE";
break;
case ACK:
p = "ACK";
break;
case NAK:
p = "NAK";
break;
case RELEASE:
p = "RELEASE";
break;
case INFORM:
p = "INFORM";
break;
default:
p = "UNKNOWN";
break;
}
}
static int
{
int error = 0;
"Client %04d - can't get interface flags on %s\n", myself,
cifname);
error = 7;
}
"Client %04d - can't set interface flags on %s\n", myself,
cifname);
error = 7;
}
"Client %04d - Can't unset address on %s\n", myself,
cifname);
error = 8;
}
return (error);
}
static void *
{
int error = 0;
char host[40];
char domain[40];
int moldy;
int i;
char *domainp;
if (bp) {
}
if (!time_to_go) {
} else {
tops++;
}
if (avg)
}
if (desynch)
if (verbose == 1)
/* reset client addr each time */
} else {
}
if (randcl) {
/* Further randomize. */
if (randhlen > 0) {
}
}
}
&cidlen);
} else {
}
/* Use global descriptor at first */
ms = s;
do {
"client",
"client%debug 'in func client'",
if (time_to_go) {
if (verbose == 1)
"Client %04d - RELEASEing %s\n",
else if (verbose == 2)
(void) memset((char *)unused_optp, 0,
(char *)unused_optp));
} else {
if (verbose == 1)
"Client %04d - terminated.\n",
myself);
break;
}
} else if (release_time || avg) {
/* lru testing: don't release lease */
if (randcl & 0x2) {
sleep_time = 0;
if (bp) {
}
goto forever;
}
if (verbose == 1)
"Client %04d - RELEASEing %s\n",
else if (verbose == 2)
(void) memset((char *)unused_optp, 0,
(char *)unused_optp));
}
}
/* drop back to INIT state. */
if (verbose == 1)
"Client %04d - Dropping back to INIT.\n",
myself);
sleep_time = 0;
if (bp) {
}
goto forever;
}
tops++;
if (avg)
}
/* Send request... */
/* Randomly corrupt packets of a certain type. */
if (randerr & 0x10) {
/* Randomly corrupt entire request. */
} else {
/* Randomly corrupt options. */
}
}
perror("Sendto");
error = 4;
}
if (!avg) {
"can't get interface flags on %s\n",
error = 7;
}
"can't set interface flags on %s\n",
error = 7;
}
"Can't unset address on %s\n",
error = 8;
}
}
if (release_time || avg) {
sleep_time = 0;
if (bp) {
}
goto forever;
}
break;
}
/* await reply */
if (retry_time > 64)
retry_time = 2;
else if (fast)
retry_time += 2;
else
retry_time *= 2;
break;
} else {
if (time_to_go)
break;
}
if (time_to_go || timeout)
continue;
moldy = 0;
if (bp) {
}
continue;
}
if (verbose == 1)
"Client %04d - Moldy xid\n", myself);
moldy++;
}
if (moldy > 0)
goto moldy;
continue;
}
/*
* Scan for CD_DHCP_TYPE, CD_SERVER_ID, and
* CD_LEASE_TIME if proto.
*/
nstate = 0;
case CD_HOSTNAME:
break;
case CD_DNSDOMAIN:
break;
case CD_DHCP_TYPE:
break;
case CD_SUBNETMASK:
sizeof (struct in_addr));
break;
case CD_SERVER_ID:
sizeof (struct in_addr));
break;
case CD_LEASE_TIME:
sizeof (time_t));
break;
}
}
/*
* Add in the requested IP address option and
* server ID.
*/
sizeof (struct in_addr));
sizeof (struct in_addr)];
sizeof (struct in_addr));
sizeof (struct in_addr)];
if (dohost == 0) {
if (bp) {
}
continue;
}
"%s", domainp);
}
if (dohost & 0x2) {
if (domain[0])
sizeof (host), "%s.%s",
else
}
/* create a random name */
if (i & 1)
else
/* use the previous one */
}
if (bp) {
}
continue;
/*
* we're bound. defend the lease. Add the
* address to our interface. Due to the
* service architecture of this program, we
* can't unset the broadcast bit..
*/
nstate = 0;
retry_time = 2;
optp = unused_optp;
sizeof (time_t));
(char *)optp));
if (lease == -1) {
sleep_time = 0;
} else {
}
if (release_time || avg) {
}
if (verbose == 1)
"Client %04d(%s) - DHCP: %s == %s",
else if (verbose == 2)
cid);
/* Add mask and address */
0)) < 0) {
"Client %04d - can't open "
"DGRAM socket.\n", myself);
error = 7;
break;
}
/*
* XXXX: needed in on81
* for initial
* interface creation
*/
"Client %04d - Can't set "
"netmask: %s on %s\n",
cifname);
error = 7;
break;
}
"Client %04d - can't get "
"interface flags on %s\n",
error = 7;
break;
}
"Client %04d - can't set "
"interface flags on %s\n",
error = 7;
break;
}
"Client %04d - Can't set "
"address on %s\n",
error = 8;
break;
}
}
if (sleep_time != 0) {
/* Go to sleep for 50% of lease time. */
if (verbose == 1)
"Client %04d - sleeping "
"until %s", myself,
(void) mutex_lock(&go_mtx);
while (!time_to_go) {
if (cond_timedwait(&go_cv,
break;
}
(void) mutex_unlock(&go_mtx);
if (verbose == 1)
"Client %04d - awake\n",
myself);
}
/* drop back to INIT state. */
if (verbose == 1) {
"DHCP: we got NAKed.\n", myself);
"Dropping back to INIT.\n", myself);
}
if (!avg)
sleep_time = 0;
if (bp) {
}
goto forever;
} else {
"unexpected mesg: %s, when I'm in state: "
error = 9;
break;
}
} else {
if (verbose == 1)
"Client %04d(%s) - BOOTP: %s\n", myself,
if (release_time || avg) {
sleep_time = 0;
if (bp) {
}
goto forever;
}
}
if (bp) {
}
} while (!done);
if (!done) {
"Client %04d - %s: configuration failed.\n",
}
}
return (NULL); /* NOTREACHED */
}
/*
* Never returns. Just loads client lists.
*/
static void *
{
int error = 0;
int len, i;
} else {
}
for (;;) {
error = 5;
break;
}
(void) mutex_lock(&go_mtx);
if (time_to_go) {
error = 0;
break;
}
(void) mutex_unlock(&go_mtx);
else {
}
if (len < 0) {
error = 6;
break;
} else {
for (i = 0; i < clients; i++) {
if (verbose == 1)
"Service - received packet "
"for thread %04d...\n",
} else {
/* null */;
}
break;
}
}
if (i >= clients)
}
}
return (NULL); /* NOTREACHED */
}
/* ARGSUSED */
static void *
sig_handle(void *arg)
{
int sig;
char buf[SIG2STR_MAX];
int i;
int oldi;
int kicked;
(void) sigfillset(&set);
if (avg == 0) {
}
while (!leave) {
case SIGHUP:
case -1:
kicked = 0;
for (i = 0; i < clients; i++) {
/* Start next client at avgslp offset */
(CLIENT_FIRSTTIME | CLIENT_BUSY)) == 0) {
kicked++;
}
case DISCOVER:
discover++;
break;
case OFFER:
offer++;
break;
case REQUEST:
req++;
break;
case DECLINE:
decline++;
break;
case ACK:
ack++;
break;
case NAK:
nak++;
break;
case RELEASE:
release++;
break;
case INFORM:
inform++;
break;
default:
unknown++;
break;
}
unstarted++;
oldi = i;
}
}
}
continue;
if (start == 0) {
/* toss initial sample */
minind = 0;
} else {
minind + 1;
minstime = 0;
minavg = 0;
for (i = 0; i < nsamples; i++) {
if (mintim[i])
if (minstime == 0)
else if (mintim[i] &&
}
"Persec %4.2f (%4.2f) Oldest %d (%d) "
- minstime),
"decl %d ack %d nak %d rel %d inf %d "
unknown);
}
break;
case SIGINT:
/* FALLTHRU */
case SIGTERM:
"Signal: %s received...Exiting\n", buf);
(void) mutex_lock(&go_mtx);
time_to_go = B_TRUE;
(void) cond_broadcast(&go_cv);
(void) mutex_unlock(&go_mtx);
for (i = 0; i < clients; i++) {
}
break;
default:
"Signal: %s received...Ignoring\n", buf);
break;
}
}
return (NULL); /* NOTREACHED */
}
int
{
int sockoptbuf = 1;
int slen;
unsigned int ifceno;
if (randcl)
if (dofork) {
if (fork() != 0)
exit(0);
}
}
/* handle cases where limit is infinity */
}
/* set NOFILE to unlimited */
}
if (argc < 5) {
"<clients> [time] [desynch] [avg] [relayaddr]\n", argv[0]);
return (1);
}
*endp = '\0';
}
else
if (argc >= 6) {
}
if (argc >= 7)
if (argc >= 8) {
if (avg > 0.0) {
(double)((int)avg)) * 1000000000.0;
} else if (avg < 0.0) {
1000000000.0;
}
}
if (argc >= 9)
if (argc >= 10)
else
perror("Socket");
return (1);
}
(int)sizeof (sockoptbuf)) < 0) {
perror("Setsockopt");
return (2);
}
(char *)&sockoptbuf, (int)sizeof (sockoptbuf)) < 0) {
perror("Setsockopt: REUSEADDR");
return (2);
}
if (lrecv) {
} else {
((struct sockaddr_in *)
}
}
perror("Socket");
return (1);
}
(char *)&sockoptbuf, (int)sizeof (sockoptbuf)) < 0) {
perror("Setsockopt: REUSEADDR");
return (2);
}
sizeof (relfrom)) < 0) {
perror("Bind");
return (3);
}
if (bound) {
(char *)&ifceno, (int)sizeof (char *)) < 0) {
perror("Setsockopt bind");
return (3);
}
}
}
} else {
}
perror("Bind");
return (3);
}
if (bound) {
(char *)&ifceno, (int)sizeof (char *)) < 0) {
perror("Setsockopt bind");
return (3);
}
}
*endp++ = '\0';
}
/* broadcast bit */
/* magic cookie */
if (proto) {
/* Pretend to be a discover packet */
}
(void) sigfillset(&set);
/*
* Create the client threads
*/
return (1);
for (i = 0; i < clients; i++) {
if (i > 100)
j = 3;
else if (i > 50)
j = 2;
else
j = 1;
if (i) {
}
if (printid)
}
}
/*
* Create signal handling thread.
*/
return (1);
} else
sig_id);
/*
*/
&service_id) != 0) {
exit(1);
} else
/*
* Continue the client threads.
*/
for (i = 0; i < clients; i++) {
}
/*
* join them
*/
for (i = 0; i < clients; i++) {
if (threrror != 0) {
"Client %04d - exited with %d\n",
}
}
}
(void) close(s); /* force service out of poll */
if (threrror != 0) {
threrror);
}
}
return (0);
}
/*
* corrupt: simulate packet corruption for debugging server
*/
static void
{
int c;
int i;
int p;
char *pp;
i = (rand() % c)>>1;
while (--i > 0) {
p = (rand() % c);
}
}
}