/*
* iperf, Copyright (c) 2014-2022, The Regents of the University of
* California, through Lawrence Berkeley National Laboratory (subject
* to receipt of any required approvals from the U.S. Dept. of
* Energy). All rights reserved.
*
* If you have questions about your rights to use or distribute this
* software, please contact Berkeley Lab's Technology Transfer
* Department at TTD@lbl.gov.
*
* NOTICE. This software is owned by the U.S. Department of Energy.
* As such, the U.S. Government has been granted for itself and others
* acting on its behalf a paid-up, nonexclusive, irrevocable,
* worldwide license in the Software to reproduce, prepare derivative
* works, and perform publicly and display publicly. Beginning five
* (5) years after the date permission to assert copyright is obtained
* from the U.S. Department of Energy, and subject to any subsequent
* five (5) year renewals, the U.S. Government is granted for itself
* and others acting on its behalf a paid-up, nonexclusive,
* irrevocable, worldwide license in the Software to reproduce,
* prepare derivative works, distribute copies to the public, perform
* publicly and display publicly, and to permit others to do so.
*
* This code is distributed under a BSD style license, see the LICENSE
* file for complete information.
*/
#include <stdio.h>
#include <errno.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include "iperf.h"
#include "iperf_api.h"
int gerror;
char iperf_timestrerr[100];
/* Do a printf to stderr. */
void
iperf_err(struct iperf_test *test, const char *format, ...)
{
va_list argp;
char str[1000];
time_t now;
struct tm *ltm = NULL;
char *ct = NULL;
/* Timestamp if requested */
if (test != NULL && test->timestamps) {
time(&now);
ltm = localtime(&now);
strftime(iperf_timestrerr, sizeof(iperf_timestrerr), test->timestamp_format, ltm);
ct = iperf_timestrerr;
}
va_start(argp, format);
vsnprintf(str, sizeof(str), format, argp);
if (test != NULL && test->json_output && test->json_top != NULL)
cJSON_AddStringToObject(test->json_top, "error", str);
else {
if (test && test->outfile && test->outfile != stdout) {
if (ct) {
fprintf(test->outfile, "%s", ct);
}
fprintf(test->outfile, "iperf3: %s\n", str);
}
else {
if (ct) {
fprintf(stderr, "%s", ct);
}
fprintf(stderr, "iperf3: %s\n", str);
}
}
va_end(argp);
}
/* Do a printf to stderr or log file as appropriate, then exit. */
void
iperf_errexit(struct iperf_test *test, const char *format, ...)
{
va_list argp;
char str[1000];
time_t now;
struct tm *ltm = NULL;
char *ct = NULL;
/* Timestamp if requested */
if (test != NULL && test->timestamps) {
time(&now);
ltm = localtime(&now);
strftime(iperf_timestrerr, sizeof(iperf_timestrerr), "%c ", ltm);
ct = iperf_timestrerr;
}
va_start(argp, format);
vsnprintf(str, sizeof(str), format, argp);
if (test != NULL && test->json_output) {
if (test->json_top != NULL) {
cJSON_AddStringToObject(test->json_top, "error", str);
}
iperf_json_finish(test);
} else
if (test && test->outfile && test->outfile != stdout) {
if (ct) {
fprintf(test->outfile, "%s", ct);
}
fprintf(test->outfile, "iperf3: %s\n", str);
}
else {
if (ct) {
fprintf(stderr, "%s", ct);
}
fprintf(stderr, "iperf3: %s\n", str);
}
va_end(argp);
if (test)
iperf_delete_pidfile(test);
exit(1);
}
int i_errno;
char *
iperf_strerror(int int_errno)
{
static char errstr[256];
int len, perr, herr;
perr = herr = 0;
len = sizeof(errstr);
memset(errstr, 0, len);
switch (int_errno) {
case IENONE:
snprintf(errstr, len, "no error");
break;
case IESERVCLIENT:
snprintf(errstr, len, "cannot be both server and client");
break;
case IENOROLE:
snprintf(errstr, len, "must either be a client (-c) or server (-s)");
break;
case IESERVERONLY:
snprintf(errstr, len, "some option you are trying to set is server only");
break;
case IECLIENTONLY:
snprintf(errstr, len, "some option you are trying to set is client only");
break;
case IEDURATION:
snprintf(errstr, len, "test duration too long (maximum = %d seconds)", MAX_TIME);
break;
case IENUMSTREAMS:
snprintf(errstr, len, "number of parallel streams too large (maximum = %d)", MAX_STREAMS);
break;
case IEBLOCKSIZE:
snprintf(errstr, len, "block size too large (maximum = %d bytes)", MAX_BLOCKSIZE);
break;
case IEBUFSIZE:
snprintf(errstr, len, "socket buffer size too large (maximum = %d bytes)", MAX_TCP_BUFFER);
break;
case IEINTERVAL:
snprintf(errstr, len, "invalid report interval (min = %g, max = %g seconds)", MIN_INTERVAL, MAX_INTERVAL);
break;
case IEBIND: /* UNUSED */
snprintf(errstr, len, "--bind must be specified to use --cport");
break;
case IEUDPBLOCKSIZE:
snprintf(errstr, len, "block size invalid (minimum = %d bytes, maximum = %d bytes)", MIN_UDP_BLOCKSIZE, MAX_UDP_BLOCKSIZE);
break;
case IEBADTOS:
snprintf(errstr, len, "bad TOS value (must be between 0 and 255 inclusive)");
break;
case IESETCLIENTAUTH:
snprintf(errstr, len, "you must specify a username, password, and path to a valid RSA public key");
break;
case IESETSERVERAUTH:
snprintf(errstr, len, "you must specify a path to a valid RSA private key and a user credential file");
break;
case IEBADFORMAT:
snprintf(errstr, len, "bad format specifier (valid formats are in the set [kmgtKMGT])");
break;
case IEBADPORT:
snprintf(errstr, len, "port number must be between 1 and 65535 inclusive");
break;
case IEMSS:
snprintf(errstr, len, "TCP MSS too large (maximum = %d bytes)", MAX_MSS);
break;
case IENOSENDFILE:
snprintf(errstr, len, "this OS does not support sendfile");
break;
case IEOMIT:
snprintf(errstr, len, "bogus value for --omit");
break;
case IEUNIMP:
snprintf(errstr, len, "an option you are trying to set is not implemented yet");
break;
case IEFILE:
snprintf(errstr, len, "unable to open -F file");
perr = 1;
break;
case IEBURST:
snprintf(errstr, len, "invalid burst count (maximum = %d)", MAX_BURST);
break;
case IEENDCONDITIONS:
snprintf(errstr, len, "only one test end condition (-t, -n, -k) may be specified");
break;
case IELOGFILE:
snprintf(errstr, len, "unable to open log file");
perr = 1;
break;
case IENOSCTP:
snprintf(errstr, len, "no SCTP support available");
break;
case IENEWTEST:
snprintf(errstr, len, "unable to create a new test");
perr = 1;
break;
case IEINITTEST:
snprintf(errstr, len, "test initialization failed");
perr = 1;
break;
case IEAUTHTEST:
snprintf(errstr, len, "test authorization failed");
break;
case IELISTEN:
snprintf(errstr, len, "unable to start listener for connections");
herr = 1;
perr = 1;
break;
case IECONNECT:
snprintf(errstr, len, "unable to connect to server - server may have stopped running or use a different port, firewall issue, etc.");
perr = 1;
herr = 1;
break;
case IEACCEPT:
snprintf(errstr, len, "unable to accept connection from client");
herr = 1;
perr = 1;
break;
case IESENDCOOKIE:
snprintf(errstr, len, "unable to send cookie to server");
perr = 1;
break;
case IERECVCOOKIE:
snprintf(errstr, len, "unable to receive cookie at server");
perr = 1;
break;
case IECTRLWRITE:
snprintf(errstr, len, "unable to write to the control socket");
perr = 1;
break;
case IECTRLREAD:
snprintf(errstr, len, "unable to read from the control socket");
perr = 1;
break;
case IECTRLCLOSE:
snprintf(errstr, len, "control socket has closed unexpectedly");
break;
case IEMESSAGE:
snprintf(errstr, len, "received an unknown control message (ensure other side is iperf3 and not iperf)");
break;
case IESENDMESSAGE:
snprintf(errstr, len, "unable to send control message - port may not be available, the other side may have stopped running, etc.");
perr = 1;
break;
case IERECVMESSAGE:
snprintf(errstr, len, "unable to receive control message - port may not be available, the other side may have stopped running, etc.");
perr = 1;
break;
case IESENDPARAMS:
snprintf(errstr, len, "unable to send parameters to server");
perr = 1;
break;
case IERECVPARAMS:
snprintf(errstr, len, "unable to receive parameters from client");
perr = 1;
break;
case IEPACKAGERESULTS:
snprintf(errstr, len, "unable to package results");
perr = 1;
break;
case IESENDRESULTS:
snprintf(errstr, len, "unable to send results");
perr = 1;
break;
case IERECVRESULTS:
snprintf(errstr, len, "unable to receive results");
perr = 1;
break;
case IESELECT:
snprintf(errstr, len, "select failed");
perr = 1;
break;
case IECLIENTTERM:
snprintf(errstr, len, "the client has terminated");
break;
case IESERVERTERM:
snprintf(errstr, len, "the server has terminated");
break;
case IEACCESSDENIED:
snprintf(errstr, len, "the server is busy running a test. try again later");
break;
case IESETNODELAY:
snprintf(errstr, len, "unable to set TCP/SCTP NODELAY");
perr = 1;
break;
case IESETMSS:
snprintf(errstr, len, "unable to set TCP/SCTP MSS");
perr = 1;
break;
case IESETBUF:
snprintf(errstr, len, "unable to set socket buffer size");
perr = 1;
break;
case IESETTOS:
snprintf(errstr, len, "unable to set IP TOS");
perr = 1;
break;
case IESETCOS:
snprintf(errstr, len, "unable to set IPv6 traffic class");
perr = 1;
break;
case IESETFLOW:
snprintf(errstr, len, "unable to set IPv6 flow label");
break;
case IEREUSEADDR:
snprintf(errstr, len, "unable to reuse address on socket");
perr = 1;
break;
case IENONBLOCKING:
snprintf(errstr, len, "unable to set socket to non-blocking");
perr = 1;
break;
case IESETWINDOWSIZE:
snprintf(errstr, len, "unable to set socket window size");
perr = 1;
break;
case IEPROTOCOL:
snprintf(errstr, len, "protocol does not exist");
break;
case IEAFFINITY:
snprintf(errstr, len, "unable to set CPU affinity");
perr = 1;
break;
case IERCVTIMEOUT:
snprintf(errstr, len, "receive timeout value is incorrect or not in range");
perr = 1;
break;
case IESNDTIMEOUT:
snprintf(errstr, len, "send timeout value is incorrect or not in range");
perr = 1;
break;
case IEUDPFILETRANSFER:
snprintf(errstr, len, "cannot transfer file using UDP");
break;
case IERVRSONLYRCVTIMEOUT:
snprintf(errstr, len, "client receive timeout is valid only in receiving mode");
perr = 1;
break;
case IEDAEMON:
snprintf(errstr, len, "unable to become a daemon");
perr = 1;
break;
case IECREATESTREAM:
snprintf(errstr, len, "unable to create a new stream");
herr = 1;
perr = 1;
break;
case IEINITSTREAM:
snprintf(errstr, len, "unable to initialize stream");
herr = 1;
perr = 1;
break;
case IESTREAMLISTEN:
snprintf(errstr, len, "unable to start stream listener");
herr = 1;
perr = 1;
break;
case IESTREAMCONNECT:
snprintf(errstr, len, "unable to connect stream");
herr = 1;
perr = 1;
break;
case IESTREAMACCEPT:
snprintf(errstr, len, "unable to accept stream connection");
perr = 1;
break;
case IESTREAMWRITE:
snprintf(errstr, len, "unable to write to stream socket");
perr = 1;
break;
case IESTREAMREAD:
snprintf(errstr, len, "unable to read from stream socket");
perr = 1;
break;
case IESTREAMCLOSE:
snprintf(errstr, len, "stream socket has closed unexpectedly");
break;
case IESTREAMID:
snprintf(errstr, len, "stream has an invalid id");
break;
case IENEWTIMER:
snprintf(errstr, len, "unable to create new timer");
perr = 1;
break;
case IEUPDATETIMER:
snprintf(errstr, len, "unable to update timer");
perr = 1;
break;
case IESETCONGESTION:
snprintf(errstr, len, "unable to set TCP_CONGESTION: "
"Supplied congestion control algorithm not supported on this host");
break;
case IEPIDFILE:
snprintf(errstr, len, "unable to write PID file");
perr = 1;
break;
case IEV6ONLY:
snprintf(errstr, len, "Unable to set/reset IPV6_V6ONLY");
perr = 1;
break;
case IESETSCTPDISABLEFRAG:
snprintf(errstr, len, "unable to set SCTP_DISABLE_FRAGMENTS");
perr = 1;
break;
case IESETSCTPNSTREAM:
snprintf(errstr, len, "unable to set SCTP_INIT num of SCTP streams\n");
perr = 1;
break;
case IESETPACING:
snprintf(errstr, len, "unable to set socket pacing");
perr = 1;
break;
case IESETBUF2:
snprintf(errstr, len, "socket buffer size not set correctly");
break;
case IEREVERSEBIDIR:
snprintf(errstr, len, "cannot be both reverse and bidirectional");
break;
case IETOTALRATE:
snprintf(errstr, len, "total required bandwidth is larger than server limit");
break;
case IESKEWTHRESHOLD:
snprintf(errstr, len, "skew threshold must be a positive number");
break;
case IEIDLETIMEOUT:
snprintf(errstr, len, "idle timeout parameter is not positive or larger than allowed limit");
break;
case IEBINDDEV:
snprintf(errstr, len, "Unable to bind-to-device (check perror, maybe permissions?)");
break;
case IEBINDDEVNOSUPPORT:
snprintf(errstr, len, "`<ip>%%<dev>` is not supported as system does not support bind to device");
break;
case IEHOSTDEV:
snprintf(errstr, len, "host device name (ip%%<dev>) is supported (and required) only for IPv6 link-local address");
break;
case IENOMSG:
snprintf(errstr, len, "idle timeout for receiving data");
break;
case IESETDONTFRAGMENT:
snprintf(errstr, len, "unable to set IP Do-Not-Fragment flag");
break;
case IESETUSERTIMEOUT:
snprintf(errstr, len, "unable to set TCP USER_TIMEOUT");
perr = 1;
break;
default:
snprintf(errstr, len, "int_errno=%d", int_errno);
perr = 1;
break;
}
/* Append the result of strerror() or gai_strerror() if appropriate */
if (herr || perr)
strncat(errstr, ": ", len - strlen(errstr) - 1);
if (errno && perr)
strncat(errstr, strerror(errno), len - strlen(errstr) - 1);
else if (herr && gerror) {
strncat(errstr, gai_strerror(gerror), len - strlen(errstr) - 1);
gerror = 0;
}
return errstr;
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>