/*-GNU-GPL-BEGIN-*
nepim - network pipemeter
Copyright (C) 2005 Everton da Silva Marques
nepim 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, or (at your option)
any later version.
nepim 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 nepim; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*-GNU-GPL-END-*/
/*
nepim - network pipemeter
$Id: main.c,v 1.31 2005/10/13 19:02:20 evertonm Exp $
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <oop.h>
#include <assert.h>
#ifdef HAVE_SIGHANDLER_T
# define __USE_GNU
# include <signal.h>
#else
# include <signal.h>
typedef void (*sighandler_t)(int);
#endif
#include "conf.h"
#include "common.h"
#include "str.h"
#include "int.h"
#include "udp_header.h"
extern void nepim_server_run();
extern void nepim_client_run();
static void usage(FILE *out, const char *prog_name)
{
char buf[100];
char buf2[100];
char *bit_rate;
char *pkt_rate;
if (nepim_global.bit_rate < 0) {
bit_rate = "unlimited";
} else {
int wr = snprintf(buf, sizeof(buf), "%lld", nepim_global.bit_rate);
assert(wr > 0);
assert(wr < sizeof(buf));
bit_rate = buf;
}
if (nepim_global.pkt_rate < 0) {
pkt_rate = "unlimited";
} else {
int wr = snprintf(buf2, sizeof(buf2), "%d", nepim_global.pkt_rate);
assert(wr > 0);
assert(wr < sizeof(buf2));
pkt_rate = buf2;
}
fprintf(out,
"usage: %s [options]\n"
"\n"
"common (client/server) options:\n"
" -h help\n"
" -v show program version\n"
" -p port server port number (defaults to %s)\n"
" -m mode path MTU discovery mode (defaults to %d)\n"
" modes: -1 = use system-wide settings\n"
" 0 = DONT (never do PMTU discovery, DF=0)\n"
" 1 = WANT (use per-route hints)\n"
" 2 = DO (always do PMTU discovery, DF=1)\n"
" -t ttl TTL for sending packets (defaults to system)\n"
" -w size TCP write size (defaults to %d bytes)\n"
" -z size TCP read size (defaults to %d bytes)\n"
" -W size UDP write size (defaults to %d bytes)\n"
" -Z size UDP read size (defaults to %d bytes)\n"
" -O size maximum socket send buffer in bytes\n"
" -I size maximum socket receive buffer in bytes\n"
" -k password server authentication secret\n"
" -6 disable IPv6\n"
" -4 disable IPv4\n"
" -x [win] experimental UDP reception statistics (win=%d)\n"
" -L loss experimental UDP sending loss\n"
" -D dup experimental UDP sending duplication\n"
"client-only options:\n"
" -u UDP mode (defaults to TCP)\n"
" -s client-send simplex mode (defaults to server-send)\n"
" -d duplex traffic (defaults to simplex)\n"
" -M enable multicast-compatible options\n"
" -c host-list client mode (defaults to server mode)\n"
" -n pipes number of parallel pipes (defaults to %d)\n"
" -r bit-rate upper bit rate limit (defaults to %s bps)\n"
" -R pkt-rate upper packet rate limit (defaults to %s pps)\n"
" -i interval statistics report interval (defaults to %d seconds)\n"
" -a age test duration (defaults to %d seconds)\n"
"server-only options:\n"
" -f [lib-name] enable TCP wrapper filtering\n"
" -b addr-list bind to specific addresses (defaults to any)\n"
" -j addr-list join multicast groups (defaults to empty)\n"
" addr-list: addr_1[,port_1][/.../addr_n[,port_n]]\n"
" example: 10.0.0.1/192.168.0.1,5000/::1\n"
" -l backlog TCP listen(2) backlog (defaults to %d)\n"
" -T mcast-ttl TTL for multicast packets (defaults to system)\n"
,
nepim_global.prog_name,
nepim_global.portname,
nepim_global.pmtu_mode,
nepim_global.tcp_write_size,
nepim_global.tcp_read_size,
nepim_global.udp_write_size,
nepim_global.udp_read_size,
nepim_global.udp_win_max,
nepim_global.pipes,
bit_rate,
pkt_rate,
nepim_global.stat_interval,
nepim_global.test_duration,
nepim_global.listen_backlog
);
}
static void init_event_loop()
{
sighandler_t handler;
handler = signal(SIGPIPE, SIG_IGN);
assert(handler != SIG_ERR);
nepim_global.oop_sys = oop_sys_new();
assert(nepim_global.oop_sys);
nepim_global.oop_src = oop_sys_source(nepim_global.oop_sys);
assert(nepim_global.oop_src);
}
static void show_version_brief()
{
printf("nepim - network pipemeter - version %s\n", nepim_version());
}
static void show_version()
{
show_version_brief();
printf(
"Copyright (C) 2005 Everton da Silva marques\n"
"\n"
"This program is free software; you can redistribute it and/or\n"
"modify it under the terms of the GNU General Public License\n"
"as published by the Free Software Foundation; either version 2\n"
"of the License, or (at your option) any later version.\n"
"\n"
"This program is distributed in the hope that it will be useful,\n"
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
"GNU General Public License for more details.\n"
);
}
int main(int argc, const char *argv[])
{
int i;
nepim_int_sanity();
for (i = 1; i < argc; ++i) {
const char *arg = argv[i];
if (!strcmp(arg, "-f")) {
int j = i + 1;
nepim_global.tcpwrap = "libwrap.so";
if (j < argc)
if (*argv[j] != '-') {
++i;
nepim_global.tcpwrap = argv[i];
}
continue;
}
if (!strcmp(arg, "-L")) {
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing UDP loss\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.udp_exp_loss = atoi(argv[i]);
continue;
}
if (!strcmp(arg, "-D")) {
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing UDP duplication\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.udp_exp_dup = atoi(argv[i]);
continue;
}
if (!strcmp(arg, "-x")) {
int j = i + 1;
nepim_global.udp_exp_stats = 1;
if (j < argc)
if (*argv[j] != '-') {
++i;
nepim_global.udp_win_max = atoi(argv[i]);
}
continue;
}
if (!strcmp(arg, "-4")) {
nepim_global.no_inet4 = 1;
continue;
}
if (!strcmp(arg, "-6")) {
nepim_global.no_inet6 = 1;
continue;
}
if (!strcmp(arg, "-k")) {
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing password\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.password = argv[i];
continue;
}
if (!strcmp(arg, "-a")) {
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing test duration\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.test_duration = atoi(argv[i]);
continue;
}
if (!strcmp(arg, "-b")) {
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing bind address list\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.bind_list = addr_list_append(nepim_global.bind_list, argv[i]);
continue;
}
if (!strcmp(arg, "-c")) {
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing hostname list\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.client_mode = 1;
nepim_global.hostname = addr_list_append(nepim_global.hostname, argv[i]);
continue;
}
if (!strcmp(arg, "-d")) {
nepim_global.duplex_mode = 1;
continue;
}
if (!strcmp(arg, "-h")) {
usage(stdout, nepim_global.prog_name);
exit(0);
}
if (!strcmp(arg, "-i")) {
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing report interval\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.stat_interval = atoi(argv[i]);
continue;
}
if (!strcmp(arg, "-j")) {
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing multicast join list\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.join_list = addr_list_append(nepim_global.join_list, argv[i]);
continue;
}
if (!strcmp(arg, "-n")) {
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing number of pipes\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.pipes = atoi(argv[i]);
continue;
}
if (!strcmp(arg, "-p")) {
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing port number\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.portname = argv[i];
continue;
}
if (!strcmp(arg, "-m")) {
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing PMTU discovery mode\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.pmtu_mode = atoi(argv[i]);
continue;
}
if (!strcmp(arg, "-M")) {
nepim_global.udp_mode = 1; /* boolean */
nepim_global.simplex_client_send = 1; /* boolean */
nepim_global.udp_keepalive_require = 0; /* boolean */
nepim_global.udp_require_greet_reply = 0; /* boolean */
nepim_global.max_greetings = 1; /* counter */
continue;
}
if (!strcmp(arg, "-r")) {
int bytes;
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing bit-rate\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.bit_rate = strtoll(argv[i], 0, 10);
bytes = nepim_bps2bytes(nepim_global.bit_rate,
nepim_global.write_delay);
if (bytes < 1) {
long long min_bps = nepim_min_bps(nepim_global.write_delay);
fprintf(stderr,
"%s: bit-rate=%lld (bytes=%d) lower than minimum=%lld\n",
nepim_global.prog_name,
nepim_global.bit_rate, bytes, min_bps);
exit(1);
}
assert(nepim_global.bit_rate >= nepim_min_bps(nepim_global.write_delay));
continue;
}
if (!strcmp(arg, "-R")) {
int pkts;
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing pkt-rate\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.pkt_rate = atoi(argv[i]);
pkts = nepim_pps2packets(nepim_global.pkt_rate,
nepim_global.write_delay);
if (pkts < 1) {
int min_pps = nepim_min_pps(nepim_global.write_delay);
fprintf(stderr,
"%s: pkt-rate=%d (pkts=%d) lower than minimum=%d\n",
nepim_global.prog_name,
nepim_global.pkt_rate, pkts, min_pps);
exit(1);
}
assert(nepim_global.pkt_rate >= nepim_min_pps(nepim_global.write_delay));
continue;
}
if (!strcmp(arg, "-s")) {
nepim_global.simplex_client_send = 1;
continue;
}
if (!strcmp(arg, "-t")) {
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing ttl\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.ttl = atoi(argv[i]);
continue;
}
if (!strcmp(arg, "-T")) {
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing multicast-ttl\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.mcast_ttl = atoi(argv[i]);
continue;
}
if (!strcmp(arg, "-u")) {
nepim_global.udp_mode = 1;
continue;
}
if (!strcmp(arg, "-v")) {
show_version();
exit(0);
}
if (!strcmp(arg, "-w")) {
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing TCP write size\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.tcp_write_size = atoi(argv[i]);
continue;
}
if (!strcmp(arg, "-z")) {
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing TCP read size\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.tcp_read_size = atoi(argv[i]);
continue;
}
if (!strcmp(arg, "-W")) {
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing UDP write size\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.udp_write_size = atoi(argv[i]);
if (nepim_global.udp_write_size < UDP_HEADER_LEN) {
fprintf(stderr,
"%s: %d is less than minimum UDP write size (%d)\n",
nepim_global.prog_name, nepim_global.udp_write_size,
UDP_HEADER_LEN);
exit(1);
}
continue;
}
if (!strcmp(arg, "-Z")) {
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing UDP read size\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.udp_read_size = atoi(argv[i]);
continue;
}
if (!strcmp(arg, "-l")) {
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing listen backlog\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.listen_backlog = atoi(argv[i]);
continue;
}
if (!strcmp(arg, "-O")) {
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing maximum socket send buffer size\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.win_send = atoi(argv[i]);
continue;
}
if (!strcmp(arg, "-I")) {
++i;
if (i >= argc) {
fprintf(stderr, "%s: missing maximum socket read buffer size\n",
nepim_global.prog_name);
exit(1);
}
nepim_global.win_recv = atoi(argv[i]);
continue;
}
fprintf(stderr, "%s: unknown option: %s\n",
nepim_global.prog_name, arg);
usage(stderr, nepim_global.prog_name);
exit(1);
}
show_version_brief();
init_event_loop();
if (nepim_global.client_mode) {
if (nepim_global.udp_mode)
fprintf(stderr,
"client: udp_read=%d udp_write=%d\n",
nepim_global.udp_read_size,
nepim_global.udp_write_size);
else
fprintf(stderr,
"client: tcp_read=%d tcp_write=%d\n",
nepim_global.tcp_read_size,
nepim_global.tcp_write_size);
nepim_client_run();
fprintf(stderr, "%s: done\n", nepim_global.prog_name);
exit(0);
}
fprintf(stderr,
"server: tcp_read=%d tcp_write=%d udp_read=%d udp_write=%d\n",
nepim_global.tcp_read_size,
nepim_global.tcp_write_size,
nepim_global.udp_read_size,
nepim_global.udp_write_size);
nepim_server_run();
fprintf(stderr, "%s: done\n", nepim_global.prog_name);
exit(0);
}
syntax highlighted by Code2HTML, v. 0.9.1