/*-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 #include #include #include #include #include #ifdef HAVE_SIGHANDLER_T # define __USE_GNU # include #else # include 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); }