Rename controller_connection to rconn and use it in secchan also.
[openvswitch] / secchan / secchan.c
1 /* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
2  * Junior University
3  * 
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:
16  * 
17  * The above copyright notice and this permission notice shall be
18  * included in all copies or substantial portions of the Software.
19  * 
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
27  * SOFTWARE.
28  * 
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.
32  */
33
34 #include <errno.h>
35 #include <getopt.h>
36 #include <poll.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <time.h>
40 #include <unistd.h>
41
42 #include "buffer.h"
43 #include "command-line.h"
44 #include "compiler.h"
45 #include "fault.h"
46 #include "util.h"
47 #include "rconn.h"
48 #include "vconn-ssl.h"
49 #include "vlog-socket.h"
50 #include "openflow.h"
51 #include "poll-loop.h"
52
53 #include "vlog.h"
54 #define THIS_MODULE VLM_secchan
55
56 static void parse_options(int argc, char *argv[]);
57 static void usage(void) NO_RETURN;
58
59 static bool reliable = true;
60
61 int
62 main(int argc, char *argv[])
63 {
64     struct half {
65         struct rconn *rconn;
66         struct buffer *rxbuf;
67     };
68
69     struct half halves[2];
70     int retval;
71     int i;
72
73     set_program_name(argv[0]);
74     register_fault_handlers();
75     vlog_init();
76     parse_options(argc, argv);
77
78     if (argc - optind != 2) {
79         fatal(0, "exactly two peer arguments required; use --help for usage");
80     }
81
82     retval = vlog_server_listen(NULL, NULL);
83     if (retval) {
84         fatal(retval, "Could not listen for vlog connections");
85     }
86
87     for (i = 0; i < 2; i++) {
88         halves[i].rconn = rconn_new(argv[optind + i], 1);
89         halves[i].rxbuf = NULL;
90     }
91     for (;;) {
92         /* Do some work.  Limit the number of iterations so that callbacks
93          * registered with the poll loop don't starve. */
94         int iteration;
95
96         for (i = 0; i < 2; i++) {
97             rconn_run(halves[i].rconn);
98         }
99
100         for (iteration = 0; iteration < 50; iteration++) {
101             bool progress = false;
102             for (i = 0; i < 2; i++) {
103                 struct half *this = &halves[i];
104                 struct half *peer = &halves[!i];
105
106                 if (!this->rxbuf) {
107                     this->rxbuf = rconn_recv(this->rconn);
108                 }
109
110                 if (this->rxbuf) {
111                     retval = rconn_send(peer->rconn, this->rxbuf);
112                     if (retval != EAGAIN) {
113                         this->rxbuf = NULL;
114                         if (!retval) {
115                             progress = true;
116                         }
117                     }
118                 }
119             }
120             if (!progress) {
121                 break;
122             }
123         }
124
125         /* Wait for something to happen. */
126         for (i = 0; i < 2; i++) {
127             struct half *this = &halves[i];
128
129             rconn_run_wait(this->rconn);
130             if (!this->rxbuf) {
131                 rconn_recv_wait(this->rconn);
132             }
133         }
134         poll_block();
135     }
136
137     return 0;
138 }
139
140 static void
141 parse_options(int argc, char *argv[]) 
142 {
143     static struct option long_options[] = {
144         {"verbose",     optional_argument, 0, 'v'},
145         {"help",        no_argument, 0, 'h'},
146         {"version",     no_argument, 0, 'V'},
147 #ifdef HAVE_OPENSSL
148         {"private-key", required_argument, 0, 'p'},
149         {"certificate", required_argument, 0, 'c'},
150         {"ca-cert",     required_argument, 0, 'C'},
151 #endif
152         {0, 0, 0, 0},
153     };
154     char *short_options = long_options_to_short_options(long_options);
155     
156     for (;;) {
157         int indexptr;
158         int c;
159
160         c = getopt_long(argc, argv, short_options, long_options, &indexptr);
161         if (c == -1) {
162             break;
163         }
164
165         switch (c) {
166         case 'h':
167             usage();
168
169         case 'V':
170             printf("%s "VERSION" compiled "__DATE__" "__TIME__"\n", argv[0]);
171             exit(EXIT_SUCCESS);
172
173         case 'v':
174             vlog_set_verbosity(optarg);
175             break;
176
177 #ifdef HAVE_OPENSSL
178         case 'p':
179             vconn_ssl_set_private_key_file(optarg);
180             break;
181
182         case 'c':
183             vconn_ssl_set_certificate_file(optarg);
184             break;
185
186         case 'C':
187             vconn_ssl_set_ca_cert_file(optarg);
188             break;
189 #endif
190
191         case '?':
192             exit(EXIT_FAILURE);
193
194         default:
195             abort();
196         }
197     }
198     free(short_options);
199 }
200
201 static void
202 usage(void)
203 {
204     printf("%s: Secure Channel\n"
205            "usage: %s [OPTIONS] LOCAL REMOTE\n"
206            "\nRelays OpenFlow message between LOCAL and REMOTE datapaths.\n"
207            "LOCAL and REMOTE must each be one of the following:\n"
208            "  tcp:HOST[:PORT]         PORT (default: %d) on remote TCP HOST\n",
209            program_name, program_name, OFP_TCP_PORT);
210 #ifdef HAVE_NETLINK
211     printf("  nl:DP_IDX               local datapath DP_IDX\n");
212 #endif
213 #ifdef HAVE_OPENSSL
214     printf("  ssl:HOST[:PORT]         SSL PORT (default: %d) on remote HOST\n"
215            "\nPKI configuration (required to use SSL):\n"
216            "  -p, --private-key=FILE  file with private key\n"
217            "  -c, --certificate=FILE  file with certificate for private key\n"
218            "  -C, --ca-cert=FILE      file with peer CA certificate\n",
219            OFP_SSL_PORT);
220 #endif
221     printf("\nOther options:\n"
222            "  -v, --verbose           set maximum verbosity level\n"
223            "  -h, --help              display this help message\n"
224            "  -V, --version           display version information\n");
225     exit(EXIT_SUCCESS);
226 }