Flowgrind
Advanced TCP traffic generator
flowgrind_stop.c
Go to the documentation of this file.
1 
6 /*
7  * Copyright (C) 2013-2014 Alexander Zimmermann <alexander.zimmermann@netapp.com>
8  * Copyright (C) 2010-2013 Christian Samsel <christian.samsel@rwth-aachen.de>
9  * Copyright (C) 2009 Tim Kosse <tim.kosse@gmx.de>
10  * Copyright (C) 2007-2008 Daniel Schaffrath <daniel.schaffrath@mac.com>
11  *
12  * This file is part of Flowgrind.
13  *
14  * Flowgrind is free software: you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation, either version 3 of the License, or
17  * (at your option) any later version.
18  *
19  * Flowgrind is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with Flowgrind. If not, see <http://www.gnu.org/licenses/>.
26  *
27  */
28 
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif /* HAVE_CONFIG_H */
32 
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 /* for inet_pton */
37 #include <arpa/inet.h>
38 /* for AF_INET6 */
39 #include <sys/socket.h>
40 /* for sockaddr_in6 */
41 #include <netinet/in.h>
42 /* xmlrpc-c */
43 #include <xmlrpc-c/base.h>
44 #include <xmlrpc-c/client.h>
45 
46 #include "common.h"
47 #include "fg_definitions.h"
48 #include "fg_error.h"
49 #include "fg_progname.h"
50 #include "fg_rpc_client.h"
51 #include "fg_argparser.h"
52 
53 /* External global variables. */
54 extern const char *progname;
55 
57 static struct arg_parser parser;
58 
59 /* Forward declarations. */
60 static void usage(short status) __attribute__((noreturn));
61 
65 static void usage(short status)
66 {
67  /* Syntax error. Emit 'try help' to stderr and exit */
68  if (status != EXIT_SUCCESS) {
69  fprintf(stderr, "Try '%s -h' for more information\n", progname);
70  exit(status);
71  }
72 
73  fprintf(stdout,
74  "Usage: %1$s [OPTION]... [ADDRESS]...\n"
75  "Stop all flows on the daemons running at the given addresses.\n\n"
76 
77  "Mandatory arguments to long options are mandatory for short options too.\n"
78  " -h, --help display this help and exit\n"
79  " -v, --version print version information and exit\n\n"
80 
81  "Example:\n"
82  " %1$s localhost 127.2.3.4:5999 example.com\n",
83  progname);
84  exit(EXIT_SUCCESS);
85 }
86 
87 static void stop_flows(const char* address)
88 {
89  xmlrpc_env env;
90  xmlrpc_client *client = 0;
91  xmlrpc_value * resultP = 0;
93  bool is_ipv6 = false;
94  char *arg, *url = 0;
95  char *rpc_address = arg = strdup(address);
96  struct sockaddr_in6 source_in6;
97  source_in6.sin6_family = AF_INET6;
98 
99  parse_rpc_address(&rpc_address, &port, &is_ipv6);
100 
101  if (is_ipv6 && (inet_pton(AF_INET6, rpc_address,
102  (char*)&source_in6.sin6_addr) <= 0))
103  errx("invalid IPv6 address '%s' for RPC", rpc_address);
104 
105  if (port < 1 || port > 65535)
106  errx("invalid port for RPC");
107 
108  int rc = 0;
109  if (is_ipv6)
110  rc = asprintf(&url, "http://[%s]:%d/RPC2", rpc_address, port);
111  else
112  rc = asprintf(&url, "http://%s:%d/RPC2", rpc_address, port);
113 
114  if (rc == -1)
115  critx("could not allocate memory for RPC URL");
116 
117  printf("Stopping all flows on %s\n", url);
118 
119  /* Stop the flows */
120  xmlrpc_env_init(&env);
121  xmlrpc_client_create(&env, XMLRPC_CLIENT_NO_FLAGS, "Flowgrind", FLOWGRIND_VERSION, NULL, 0, &client);
122  if (env.fault_occurred)
123  goto cleanup;
124 
125  xmlrpc_client_call2f(&env, client, url, "stop_flow", &resultP,
126  "({s:i})", "flow_id", -1); /* -1 stops all flows */
127  if (resultP)
128  xmlrpc_DECREF(resultP);
129 
130 cleanup:
131  if (env.fault_occurred) {
132  warnx("could not stop flows on %s: %s (%d)",
133  url, env.fault_string, env.fault_code);
134  }
135  if (client)
136  xmlrpc_client_destroy(client);
137  xmlrpc_env_clean(&env);
138  free_all(arg, url);
139 }
140 
141 int main(int argc, char *argv[])
142 {
143  /* update progname from argv[0] */
144  set_progname(argv[0]);
145 
146  const struct ap_Option options[] = {
147  {'h', "help", ap_no, 0, 0},
148  {'v', "version", ap_no, 0, 0},
149  {0, 0, ap_no, 0, 0}
150  };
151 
152  if (!ap_init(&parser, argc, (const char* const*) argv, options, 0))
153  critx("could not allocate memory for option parser");
154  if (ap_error(&parser)) {
155  errx("%s", ap_error(&parser));
156  usage(EXIT_FAILURE);
157  }
158 
159  /* parse command line */
160  for (int argind = 0; argind < ap_arguments(&parser); argind++) {
161  const int code = ap_code(&parser, argind);
162 
163  switch (code) {
164  case 0:
165  break;
166  case 'h':
167  usage(EXIT_SUCCESS);
168  break;
169  case 'v':
170  fprintf(stdout, "%s %s\n%s\n%s\n\n%s\n", progname,
173  exit(EXIT_SUCCESS);
174  break;
175  default:
176  errx("uncaught option: %s", ap_argument(&parser, argind));
177  usage(EXIT_FAILURE);
178  break;
179  }
180  }
181 
182  if (!ap_arguments(&parser)) {
183  errx("no address given");
184  usage(EXIT_FAILURE);
185  }
186 
187  xmlrpc_env rpc_env;
188  xmlrpc_env_init(&rpc_env);
189  xmlrpc_client_setup_global_const(&rpc_env);
190 
191  for (int argind = 0; argind < ap_arguments(&parser); argind++)
192  /* if non-option, it is an address */
193  if (!ap_code(&parser, argind))
194  stop_flows(ap_argument(&parser, argind));
195 
196  xmlrpc_env_clean(&rpc_env);
197  xmlrpc_client_teardown_global_const();
198  ap_free(&parser);
199 }
fg_progname.h
Program name management.
ap_code
int ap_code(const struct arg_parser *const ap, const int i)
Returns the code of a parsed option with given index.
Definition: fg_argparser.c:468
ap_argument
const char * ap_argument(const struct arg_parser *const ap, const int i)
Returns the argument of a parsed option.
Definition: fg_argparser.c:478
ap_error
const char * ap_error(const struct arg_parser *const ap)
Get the string containing errors encountered during parsing.
Definition: fg_argparser.c:458
FLOWGRIND_COPYRIGHT
#define FLOWGRIND_COPYRIGHT
Flowgrind's copyright year.
Definition: common.h:82
port
static unsigned port
Definition: flowgrindd.c:95
arg_parser
Internal state of the argument parser.
Definition: fg_argparser.h:73
parser
static struct arg_parser parser
Command line option parser.
Definition: flowgrind_stop.c:57
fg_error.h
Error-reporting routines used by Flowgrind.
ap_no
@ ap_no
Option without argument (flag).
Definition: fg_argparser.h:37
warnx
#define warnx(...)
To report a warning w/ a system error message.
Definition: fg_error.h:54
main
int main(int argc, char *argv[])
Definition: flowgrind_stop.c:141
fg_rpc_client.h
RPC related functions used by the Flowgrind controller flowgrind-stop.
ap_Option::code
int code
Short option letter or code (code != 0).
Definition: fg_argparser.h:47
errx
#define errx(...)
To report an error w/o a system error message.
Definition: fg_error.h:47
ap_free
void ap_free(struct arg_parser *const ap)
Free internal state of arg-parser.
Definition: fg_argparser.c:448
FLOWGRIND_COPYING
#define FLOWGRIND_COPYING
Standard GPL3 no warranty message.
Definition: common.h:85
critx
#define critx(...)
To report an critical error w/o a system error message.
Definition: fg_error.h:40
progname
const char * progname
String containing name the program is called with.
Definition: fg_progname.c:35
FLOWGRIND_AUTHORS
#define FLOWGRIND_AUTHORS
Flowgrind's authors in a printable string.
Definition: common.h:91
ap_arguments
int ap_arguments(const struct arg_parser *const ap)
Number of arguments parsed (may be different from argc).
Definition: fg_argparser.c:463
fg_argparser.h
Command line argument parser.
rpc_env
static xmlrpc_env rpc_env
Definition: flowgrind.c:104
ap_Option
Defines a valid command line option.
Definition: fg_argparser.h:45
fg_definitions.h
Common definitions used by the Flowgrind daemon, controller, and libs.
FLOWGRIND_VERSION
#define FLOWGRIND_VERSION
Flowgrind version number.
Definition: common.h:44
free_all
#define free_all(...)
To free() an arbitrary number of variables.
Definition: fg_definitions.h:59
common.h
Data structures used by the Flowgrind daemon and controller.
set_progname
void set_progname(const char *argv0)
Set global variable 'progname', based on argv[0].
Definition: fg_progname.c:37
config.h
DEFAULT_LISTEN_PORT
#define DEFAULT_LISTEN_PORT
Daemon's default listen port.
Definition: common.h:55
ap_init
bool ap_init(struct arg_parser *const ap, const int argc, const char *const argv[], const struct ap_Option options[], const char in_order)
Initialize the arg-parser given command line and user-defined options.
Definition: fg_argparser.c:374
stop_flows
static void stop_flows(const char *address)
Definition: flowgrind_stop.c:87
parse_rpc_address
void parse_rpc_address(char **rpc_address, int *port, bool *is_ipv6)
Parse RPC address for the xmlrpc control connection.
Definition: fg_rpc_client.c:40
usage
static void usage(short status) __attribute__((noreturn))
Print flowgrind-stop usage and exit.
Definition: flowgrind_stop.c:65