1 /* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
4 * We are making the OpenFlow specification and associated documentation
5 * (Software) available for public use and benefit with the expectation
6 * that others will use, modify and enhance the Software and contribute
7 * those enhancements back to the community. However, since we would
8 * like to make the Software available for broadest use, with as few
9 * restrictions as possible permission is hereby granted, free of
10 * charge, to any person obtaining a copy of this Software to deal in
11 * the Software under the copyrights without restriction, including
12 * without limitation the rights to use, copy, modify, merge, publish,
13 * distribute, sublicense, and/or sell copies of the Software, and to
14 * permit persons to whom the Software is furnished to do so, subject to
15 * the following conditions:
17 * The above copyright notice and this permission notice shall be
18 * included in all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
24 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 * The name and trademarks of copyright holder(s) may NOT be used in
30 * advertising or publicity pertaining to the Software or any
31 * derivatives without specific, written prior permission.
43 #include "command-line.h"
47 #include "vconn-ssl.h"
49 #include "vlog-socket.h"
51 #include "poll-loop.h"
54 #define THIS_MODULE VLM_secchan
56 static void parse_options(int argc, char *argv[]);
57 static void usage(void) NO_RETURN;
59 static bool reliable = true;
65 time_t backoff_deadline;
69 static void reconnect(struct half *);
72 main(int argc, char *argv[])
74 struct half halves[2];
78 set_program_name(argv[0]);
79 register_fault_handlers();
81 parse_options(argc, argv);
83 if (argc - optind != 2) {
84 fatal(0, "exactly two peer arguments required; use --help for usage");
87 retval = vlog_server_listen(NULL, NULL);
89 fatal(retval, "Could not listen for vlog connections");
92 for (i = 0; i < 2; i++) {
93 halves[i].name = argv[optind + i];
94 halves[i].vconn = NULL;
95 halves[i].rxbuf = NULL;
96 halves[i].backoff_deadline = 0;
97 halves[i].backoff = 1;
98 reconnect(&halves[i]);
101 /* Do some work. Limit the number of iterations so that callbacks
102 * registered with the poll loop don't starve. */
104 for (iteration = 0; iteration < 50; iteration++) {
105 bool progress = false;
106 for (i = 0; i < 2; i++) {
107 struct half *this = &halves[i];
108 struct half *peer = &halves[!i];
111 retval = vconn_recv(this->vconn, &this->rxbuf);
112 if (retval && retval != EAGAIN) {
114 VLOG_DBG("%s: connection closed by remote host",
117 VLOG_DBG("%s: recv: closing connection: %s",
118 this->name, strerror(retval));
126 retval = vconn_send(peer->vconn, this->rxbuf);
130 } else if (retval != EAGAIN) {
131 VLOG_DBG("%s: send: closing connection: %s",
132 peer->name, strerror(retval));
143 /* Wait for something to happen. */
144 for (i = 0; i < 2; i++) {
145 struct half *this = &halves[i];
146 struct half *peer = &halves[!i];
148 vconn_recv_wait(this->vconn);
150 vconn_send_wait(peer->vconn);
160 reconnect(struct half *this)
162 if (this->vconn != NULL) {
164 fatal(0, "%s: connection dropped", this->name);
167 VLOG_WARN("%s: connection dropped, reconnecting", this->name);
168 vconn_close(this->vconn);
170 buffer_delete(this->rxbuf);
175 time_t now = time(0);
178 if (now >= this->backoff_deadline) {
182 if (this->backoff > 60) {
185 VLOG_WARN("%s: waiting %d seconds before reconnect\n",
186 this->name, (int) (this->backoff_deadline - now));
187 poll_timer_wait((this->backoff_deadline - now) * 1000);
191 retval = vconn_open_block(this->name, &this->vconn);
193 VLOG_WARN("%s: connected", this->name);
194 if (vconn_is_passive(this->vconn)) {
195 fatal(0, "%s: passive vconn not supported in control path",
198 this->backoff_deadline = now + this->backoff;
203 fatal(0, "%s: connection failed", this->name);
205 VLOG_WARN("%s: connection failed (%s)", this->name, strerror(retval));
206 this->backoff_deadline = time(0) + this->backoff;
211 parse_options(int argc, char *argv[])
213 static struct option long_options[] = {
214 {"unreliable", no_argument, 0, 'u'},
215 {"verbose", optional_argument, 0, 'v'},
216 {"help", no_argument, 0, 'h'},
217 {"version", no_argument, 0, 'V'},
219 {"private-key", required_argument, 0, 'p'},
220 {"certificate", required_argument, 0, 'c'},
221 {"ca-cert", required_argument, 0, 'C'},
225 char *short_options = long_options_to_short_options(long_options);
231 c = getopt_long(argc, argv, short_options, long_options, &indexptr);
245 printf("%s "VERSION" compiled "__DATE__" "__TIME__"\n", argv[0]);
249 vlog_set_verbosity(optarg);
254 vconn_ssl_set_private_key_file(optarg);
258 vconn_ssl_set_certificate_file(optarg);
262 vconn_ssl_set_ca_cert_file(optarg);
279 printf("%s: Secure Channel\n"
280 "usage: %s [OPTIONS] LOCAL REMOTE\n"
281 "\nRelays OpenFlow message between LOCAL and REMOTE datapaths.\n"
282 "LOCAL and REMOTE must each be one of the following:\n"
283 " tcp:HOST[:PORT] PORT (default: %d) on remote TCP HOST\n",
284 program_name, program_name, OFP_TCP_PORT);
286 printf(" nl:DP_IDX local datapath DP_IDX\n");
289 printf(" ssl:HOST[:PORT] SSL PORT (default: %d) on remote HOST\n"
290 "\nPKI configuration (required to use SSL):\n"
291 " -p, --private-key=FILE file with private key\n"
292 " -c, --certificate=FILE file with certificate for private key\n"
293 " -C, --ca-cert=FILE file with peer CA certificate\n",
296 printf("\nNetworking options:\n"
297 " -u, --unreliable do not reconnect after connections drop\n"
299 " -v, --verbose set maximum verbosity level\n"
300 " -h, --help display this help message\n"
301 " -V, --version display version information\n");