From: Ben Pfaff Date: Mon, 2 Mar 2009 22:27:10 +0000 (-0800) Subject: secchan: Make secchan into a library. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3c5ac64f3e6b8636e510016f185b98acfa3ba90e;p=openvswitch secchan: Make secchan into a library. --- diff --git a/secchan/automake.mk b/secchan/automake.mk index 76a279dd..d3e4e819 100644 --- a/secchan/automake.mk +++ b/secchan/automake.mk @@ -1,11 +1,15 @@ bin_PROGRAMS += secchan/secchan man_MANS += secchan/secchan.8 -# secchan/stp-secchan.c \ -# secchan/stp-secchan.h -# +secchan_secchan_SOURCES = secchan/main.c +secchan_secchan_LDADD = \ + secchan/libsecchan.a \ + lib/libopenflow.a \ + $(FAULT_LIBS) \ + $(SSL_LIBS) -secchan_secchan_SOURCES = \ +noinst_LIBRARIES += secchan/libsecchan.a +secchan_libsecchan_a_SOURCES = \ secchan/discovery.c \ secchan/discovery.h \ secchan/executer.c \ @@ -22,16 +26,8 @@ secchan_secchan_SOURCES = \ secchan/pktbuf.h \ secchan/pinsched.c \ secchan/pinsched.h \ - secchan/secchan.c \ - secchan/secchan.h \ secchan/status.c \ secchan/status.h -#if SUPPORT_SNAT -#secchan_secchan_SOURCES += \ -# secchan/snat.c \ -# secchan/snat.h -#endif -secchan_secchan_LDADD = lib/libopenflow.a $(FAULT_LIBS) $(SSL_LIBS) EXTRA_DIST += secchan/secchan.8.in DISTCLEANFILES += secchan/secchan.8 diff --git a/secchan/discovery.c b/secchan/discovery.c index 105614ff..42f40f14 100644 --- a/secchan/discovery.c +++ b/secchan/discovery.c @@ -43,7 +43,6 @@ #include "netdev.h" #include "openflow/openflow.h" #include "packets.h" -#include "secchan.h" #include "status.h" #define THIS_MODULE VLM_discovery diff --git a/secchan/executer.c b/secchan/executer.c index b235862b..5f59832c 100644 --- a/secchan/executer.c +++ b/secchan/executer.c @@ -50,7 +50,6 @@ #include "openflow/openflow.h" #include "poll-loop.h" #include "rconn.h" -#include "secchan.h" #include "socket-util.h" #include "util.h" #include "vconn.h" diff --git a/secchan/main.c b/secchan/main.c new file mode 100644 index 00000000..18a591fb --- /dev/null +++ b/secchan/main.c @@ -0,0 +1,488 @@ +/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford + * Junior University + * + * We are making the OpenFlow specification and associated documentation + * (Software) available for public use and benefit with the expectation + * that others will use, modify and enhance the Software and contribute + * those enhancements back to the community. However, since we would + * like to make the Software available for broadest use, with as few + * restrictions as possible permission is hereby granted, free of + * charge, to any person obtaining a copy of this Software to deal in + * the Software under the copyrights without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The name and trademarks of copyright holder(s) may NOT be used in + * advertising or publicity pertaining to the Software or any + * derivatives without specific, written prior permission. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cfg.h" +#include "command-line.h" +#include "compiler.h" +#include "daemon.h" +#include "dirs.h" +#include "discovery.h" +#include "dpif.h" +#include "fail-open.h" +#include "fault.h" +#include "in-band.h" +#include "leak-checker.h" +#include "list.h" +#include "netdev.h" +#include "ofpbuf.h" +#include "ofproto.h" +#include "openflow/openflow.h" +#include "packets.h" +#include "poll-loop.h" +#include "rconn.h" +#include "signals.h" +#include "status.h" +#include "timeval.h" +#include "util.h" +#include "vconn-ssl.h" +#include "vconn.h" +#include "vlog-socket.h" + +#include "vlog.h" +#define THIS_MODULE VLM_secchan + +static void reconfigure(struct ofproto *); +static void parse_options(int argc, char *argv[], struct ofsettings *); +static void usage(void) NO_RETURN; + +int +main(int argc, char *argv[]) +{ + struct signal *sighup; + struct ofproto *ofproto; + struct ofsettings s; + int retval; + + set_program_name(argv[0]); + register_fault_handlers(); + time_init(); + vlog_init(); + parse_options(argc, argv, &s); + signal(SIGPIPE, SIG_IGN); + sighup = signal_register(SIGHUP); + + die_if_already_running(); + daemonize(); + + /* Start listening for vlogconf requests. */ + retval = vlog_server_listen(NULL, NULL); + if (retval) { + ofp_fatal(retval, "Could not listen for vlog connections"); + } + + VLOG_INFO("OpenFlow reference implementation version %s", VERSION BUILDNR); + VLOG_INFO("OpenFlow protocol version 0x%02x", OFP_VERSION); + + /* Start OpenFlow processing. */ + ofproto = ofproto_create(&s); + + reconfigure(ofproto); + while (ofproto_is_alive(ofproto)) { + if (signal_poll(sighup)) { + reconfigure(ofproto); + } + + /* Do work. */ + ofproto_run(ofproto); + + /* Wait for something to happen. */ + ofproto_wait(ofproto); + signal_wait(sighup); + poll_block(); + } + + return 0; +} + +static void +reconfigure(struct ofproto *ofproto) +{ + cfg_read(); + ofproto_reconfigure(ofproto); +} + +/* User interface. */ + +static void +parse_options(int argc, char *argv[], struct ofsettings *s) +{ + enum { + OPT_DATAPATH_ID = UCHAR_MAX + 1, + OPT_MANUFACTURER, + OPT_HARDWARE, + OPT_SOFTWARE, + OPT_SERIAL, + OPT_ACCEPT_VCONN, + OPT_NO_RESOLV_CONF, + OPT_BR_NAME, + OPT_FAIL_MODE, + OPT_INACTIVITY_PROBE, + OPT_MAX_IDLE, + OPT_MAX_BACKOFF, + OPT_RATE_LIMIT, + OPT_BURST_LIMIT, + OPT_BOOTSTRAP_CA_CERT, + OPT_STP, + OPT_NO_STP, + OPT_OUT_OF_BAND, + OPT_IN_BAND, + OPT_COMMAND_ACL, + OPT_COMMAND_DIR, + VLOG_OPTION_ENUMS, + LEAK_CHECKER_OPTION_ENUMS + }; + static struct option long_options[] = { + {"datapath-id", required_argument, 0, OPT_DATAPATH_ID}, + {"manufacturer", required_argument, 0, OPT_MANUFACTURER}, + {"hardware", required_argument, 0, OPT_HARDWARE}, + {"software", required_argument, 0, OPT_SOFTWARE}, + {"serial", required_argument, 0, OPT_SERIAL}, + {"accept-vconn", required_argument, 0, OPT_ACCEPT_VCONN}, + {"no-resolv-conf", no_argument, 0, OPT_NO_RESOLV_CONF}, + {"config", required_argument, 0, 'F'}, + {"br-name", required_argument, 0, OPT_BR_NAME}, + {"fail", required_argument, 0, OPT_FAIL_MODE}, + {"inactivity-probe", required_argument, 0, OPT_INACTIVITY_PROBE}, + {"max-idle", required_argument, 0, OPT_MAX_IDLE}, + {"max-backoff", required_argument, 0, OPT_MAX_BACKOFF}, + {"listen", required_argument, 0, 'l'}, + {"rate-limit", optional_argument, 0, OPT_RATE_LIMIT}, + {"burst-limit", required_argument, 0, OPT_BURST_LIMIT}, + {"stp", no_argument, 0, OPT_STP}, + {"no-stp", no_argument, 0, OPT_NO_STP}, + {"out-of-band", no_argument, 0, OPT_OUT_OF_BAND}, + {"in-band", no_argument, 0, OPT_IN_BAND}, + {"command-acl", required_argument, 0, OPT_COMMAND_ACL}, + {"command-dir", required_argument, 0, OPT_COMMAND_DIR}, + {"verbose", optional_argument, 0, 'v'}, + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + DAEMON_LONG_OPTIONS, + VLOG_LONG_OPTIONS, + LEAK_CHECKER_LONG_OPTIONS, +#ifdef HAVE_OPENSSL + VCONN_SSL_LONG_OPTIONS + {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT}, +#endif + {0, 0, 0, 0}, + }; + char *short_options = long_options_to_short_options(long_options); + + /* Set defaults that we can figure out before parsing options. */ + s->datapath_id = 0; + s->mfr_desc = "Nicira Networks, Inc."; + s->hw_desc = "Reference Implementation"; + s->sw_desc = VERSION BUILDNR; + s->serial_desc = "None"; + s->n_listeners = 0; + s->fail_mode = FAIL_OPEN; + s->max_idle = 15; + s->probe_interval = 15; + s->max_backoff = 15; + s->update_resolv_conf = true; + s->rate_limit = 0; + s->burst_limit = 0; + s->accept_controller_re = NULL; + s->enable_stp = false; + s->in_band = true; + s->command_acl = ""; + s->command_dir = xasprintf("%s/commands", ofp_pkgdatadir); + for (;;) { + int error; + int c; + + c = getopt_long(argc, argv, short_options, long_options, NULL); + if (c == -1) { + break; + } + + switch (c) { + case OPT_DATAPATH_ID: + if (strlen(optarg) != 12 + || strspn(optarg, "0123456789abcdefABCDEF") != 12) { + ofp_fatal(0, "argument to --datapath-id must be " + "exactly 12 hex digits"); + } + s->datapath_id = strtoll(optarg, NULL, 16); + if (!s->datapath_id) { + ofp_fatal(0, "argument to --datapath-id must be nonzero"); + } + break; + + case OPT_MANUFACTURER: + s->mfr_desc = optarg; + break; + + case OPT_HARDWARE: + s->hw_desc = optarg; + break; + + case OPT_SOFTWARE: + s->sw_desc = optarg; + break; + + case OPT_SERIAL: + s->serial_desc = optarg; + break; + + case OPT_ACCEPT_VCONN: + s->accept_controller_re = (optarg[0] == '^' ? optarg + : xasprintf("^%s", optarg)); + break; + + case OPT_BR_NAME: + s->br_name = optarg; + break; + + case OPT_NO_RESOLV_CONF: + s->update_resolv_conf = false; + break; + + case OPT_FAIL_MODE: + if (!strcmp(optarg, "open")) { + s->fail_mode = FAIL_OPEN; + } else if (!strcmp(optarg, "closed")) { + s->fail_mode = FAIL_CLOSED; + } else { + ofp_fatal(0, "-f or --fail argument must be \"open\" " + "or \"closed\""); + } + break; + + case OPT_INACTIVITY_PROBE: + s->probe_interval = atoi(optarg); + if (s->probe_interval < 5) { + ofp_fatal(0, "--inactivity-probe argument must be at least 5"); + } + break; + + case OPT_MAX_IDLE: + if (!strcmp(optarg, "permanent")) { + s->max_idle = OFP_FLOW_PERMANENT; + } else { + s->max_idle = atoi(optarg); + if (s->max_idle < 1 || s->max_idle > 65535) { + ofp_fatal(0, "--max-idle argument must be between 1 and " + "65535 or the word 'permanent'"); + } + } + break; + + case OPT_MAX_BACKOFF: + s->max_backoff = atoi(optarg); + if (s->max_backoff < 1) { + ofp_fatal(0, "--max-backoff argument must be at least 1"); + } else if (s->max_backoff > 3600) { + s->max_backoff = 3600; + } + break; + + case OPT_RATE_LIMIT: + if (optarg) { + s->rate_limit = atoi(optarg); + if (s->rate_limit < 1) { + ofp_fatal(0, "--rate-limit argument must be at least 1"); + } + } else { + s->rate_limit = 1000; + } + break; + + case OPT_BURST_LIMIT: + s->burst_limit = atoi(optarg); + if (s->burst_limit < 1) { + ofp_fatal(0, "--burst-limit argument must be at least 1"); + } + break; + + case OPT_STP: + s->enable_stp = true; + break; + + case OPT_NO_STP: + s->enable_stp = false; + break; + + case OPT_OUT_OF_BAND: + s->in_band = false; + break; + + case OPT_IN_BAND: + s->in_band = true; + break; + + case OPT_COMMAND_ACL: + s->command_acl = (s->command_acl[0] + ? xasprintf("%s,%s", s->command_acl, optarg) + : optarg); + break; + + case OPT_COMMAND_DIR: + s->command_dir = optarg; + break; + + case 'F': + error = cfg_add_file(optarg); + if (error) { + ofp_fatal(error, "failed to add configuration file or " + "directory \"%s\"", optarg); + } + break; + + case 'l': + if (s->n_listeners >= MAX_MGMT) { + ofp_fatal(0, + "-l or --listen may be specified at most %d times", + MAX_MGMT); + } + s->listener_names[s->n_listeners++] = optarg; + break; + + case 'h': + usage(); + + case 'V': + printf("%s %s compiled "__DATE__" "__TIME__"\n", + program_name, VERSION BUILDNR); + exit(EXIT_SUCCESS); + + DAEMON_OPTION_HANDLERS + + VLOG_OPTION_HANDLERS + + LEAK_CHECKER_OPTION_HANDLERS + +#ifdef HAVE_OPENSSL + VCONN_SSL_OPTION_HANDLERS + + case OPT_BOOTSTRAP_CA_CERT: + vconn_ssl_set_ca_cert_file(optarg, true); + break; +#endif + + case '?': + exit(EXIT_FAILURE); + + default: + abort(); + } + } + free(short_options); + + argc -= optind; + argv += optind; + if (argc < 1 || argc > 2) { + ofp_fatal(0, "need one or two non-option arguments; " + "use --help for usage"); + } + + /* Local and remote vconns. */ + s->dp_name = argv[0]; + s->controller_name = argc > 1 ? xstrdup(argv[1]) : NULL; + + /* Set accept_controller_regex. */ + if (!s->accept_controller_re) { + s->accept_controller_re = vconn_ssl_is_configured() ? "^ssl:.*" : ".*"; + } + + /* Mode of operation. */ + s->discovery = s->controller_name == NULL; + if (s->discovery && !s->in_band) { + ofp_fatal(0, "Cannot perform discovery with out-of-band control"); + } + + /* Rate limiting. */ + if (s->rate_limit) { + if (s->rate_limit < 100) { + VLOG_WARN("Rate limit set to unusually low value %d", + s->rate_limit); + } + if (!s->burst_limit) { + s->burst_limit = s->rate_limit / 4; + } + s->burst_limit = MAX(s->burst_limit, 1); + s->burst_limit = MIN(s->burst_limit, INT_MAX / 1000); + } +} + +static void +usage(void) +{ + printf("%s: secure channel, a relay for OpenFlow messages.\n" + "usage: %s [OPTIONS] DATAPATH [CONTROLLER]\n" + "DATAPATH is a local datapath (e.g. \"dp0\").\n" + "CONTROLLER is an active OpenFlow connection method; if it is\n" + "omitted, then secchan performs controller discovery.\n", + program_name, program_name); + vconn_usage(true, true, true); + printf("\nConfiguration options:\n" + " -F, --config=FILE|DIR reads configuration from FILE or DIR\n" + " --br-name=NAME bridge name to use for configuration\n" + "\nOpenFlow options:\n" + " -d, --datapath-id=ID Use ID as the OpenFlow switch ID\n" + " (ID must consist of 12 hex digits)\n" + " --manufacturer=MFR Identify manufacturer as MFR\n" + " --hardware=HW Identify hardware as HW\n" + " --software=SW Identify software as SW\n" + " --serial=SERIAL Identify serial number as SERIAL\n" + "\nController discovery options:\n" + " --accept-vconn=REGEX accept matching discovered controllers\n" + " --no-resolv-conf do not update /etc/resolv.conf\n" + "\nNetworking options:\n" + " --fail=open|closed when controller connection fails:\n" + " closed: drop all packets\n" + " open (default): act as learning switch\n" + " --inactivity-probe=SECS time between inactivity probes\n" + " --max-idle=SECS max idle for flows set up by secchan\n" + " --max-backoff=SECS max time between controller connection\n" + " attempts (default: 15 seconds)\n" + " -l, --listen=METHOD allow management connections on METHOD\n" + " (a passive OpenFlow connection method)\n" + " --out-of-band controller connection is out-of-band\n" + " --stp enable 802.1D Spanning Tree Protocol\n" + " --no-stp disable 802.1D Spanning Tree Protocol\n" + "\nRate-limiting of \"packet-in\" messages to the controller:\n" + " --rate-limit[=PACKETS] max rate, in packets/s (default: 1000)\n" + " --burst-limit=BURST limit on packet credit for idle time\n" + "\nRemote command execution options:\n" + " --command-acl=[!]GLOB[,[!]GLOB...] set allowed/denied commands\n" + " --command-dir=DIR set command dir (default: %s/commands)\n", + ofp_pkgdatadir); + daemon_usage(); + vlog_usage(); + printf("\nOther options:\n" + " -h, --help display this help message\n" + " -V, --version display version information\n"); + leak_checker_usage(); + exit(EXIT_SUCCESS); +} diff --git a/secchan/netflow.c b/secchan/netflow.c index 193109c4..c08b3d8c 100644 --- a/secchan/netflow.c +++ b/secchan/netflow.c @@ -41,7 +41,6 @@ #include "flow.h" #include "netflow.h" #include "packets.h" -#include "secchan.h" #include "socket-util.h" #include "svec.h" #include "timeval.h" diff --git a/secchan/ofproto.c b/secchan/ofproto.c index 1485e453..f61a35f1 100644 --- a/secchan/ofproto.c +++ b/secchan/ofproto.c @@ -57,7 +57,6 @@ #include "poll-loop.h" #include "port-array.h" #include "rconn.h" -#include "secchan.h" #include "shash.h" #include "status.h" #include "svec.h" @@ -194,7 +193,7 @@ static uint16_t odp_port_to_ofp_port(uint16_t odp_port); static uint16_t ofp_port_to_odp_port(uint16_t ofp_port); struct ofproto * -ofproto_create(const struct settings *settings) +ofproto_create(const struct ofsettings *settings) { struct dpifmon *dpifmon; struct rconn *controller; diff --git a/secchan/ofproto.h b/secchan/ofproto.h index df0acd8b..a9351c92 100644 --- a/secchan/ofproto.h +++ b/secchan/ofproto.h @@ -34,14 +34,66 @@ #ifndef OFPROTO_H #define OFPROTO_H 1 +#include +#include #include "flow.h" -struct dpif; -struct ofproto; -struct settings; -struct switch_status; +/* Behavior when the connection to the controller fails. */ +enum fail_mode { + FAIL_OPEN, /* Act as learning switch. */ + FAIL_CLOSED /* Drop all packets. */ +}; -struct ofproto *ofproto_create(const struct settings *); +/* Maximum number of management connection listeners. */ +#define MAX_MGMT 8 + +/* Settings that may be configured by the user. */ +struct ofsettings { + /* Configuration. */ + const char *br_name; /* Bridge name to use for configuration lookup */ + + /* Overall mode of operation. */ + bool discovery; /* Discover the controller automatically? */ + bool in_band; /* Connect to controller in-band? */ + + /* Datapath. */ + uint64_t datapath_id; /* Datapath ID. */ + const char *dp_name; /* Name of local datapath. */ + + /* Description strings. */ + const char *mfr_desc; /* Manufacturer. */ + const char *hw_desc; /* Hardware. */ + const char *sw_desc; /* Software version. */ + const char *serial_desc; /* Serial number. */ + + /* Related vconns and network devices. */ + const char *controller_name; /* Controller (if not discovery mode). */ + const char *listener_names[MAX_MGMT]; /* Listen for mgmt connections. */ + size_t n_listeners; /* Number of mgmt connection listeners. */ + + /* Failure behavior. */ + enum fail_mode fail_mode; /* Act as learning switch if no controller? */ + int max_idle; /* Idle time for flows in fail-open mode. */ + int probe_interval; /* # seconds idle before sending echo request. */ + int max_backoff; /* Max # seconds between connection attempts. */ + + /* Packet-in rate-limiting. */ + int rate_limit; /* Tokens added to bucket per second. */ + int burst_limit; /* Maximum number token bucket size. */ + + /* Discovery behavior. */ + const char *accept_controller_re; /* Controller vconns to accept. */ + bool update_resolv_conf; /* Update /etc/resolv.conf? */ + + /* Spanning tree protocol. */ + bool enable_stp; + + /* Remote command execution. */ + char *command_acl; /* Command white/blacklist, as shell globs. */ + char *command_dir; /* Directory that contains commands. */ +}; + +struct ofproto *ofproto_create(const struct ofsettings *); void ofproto_reconfigure(struct ofproto *); void ofproto_run(struct ofproto *); void ofproto_wait(struct ofproto *); diff --git a/secchan/pinsched.c b/secchan/pinsched.c index fd877e43..31254fb9 100644 --- a/secchan/pinsched.c +++ b/secchan/pinsched.c @@ -42,7 +42,6 @@ #include "queue.h" #include "random.h" #include "rconn.h" -#include "secchan.h" #include "status.h" #include "timeval.h" #include "vconn.h" diff --git a/secchan/secchan.c b/secchan/secchan.c deleted file mode 100644 index 3411e4ea..00000000 --- a/secchan/secchan.c +++ /dev/null @@ -1,489 +0,0 @@ -/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford - * Junior University - * - * We are making the OpenFlow specification and associated documentation - * (Software) available for public use and benefit with the expectation - * that others will use, modify and enhance the Software and contribute - * those enhancements back to the community. However, since we would - * like to make the Software available for broadest use, with as few - * restrictions as possible permission is hereby granted, free of - * charge, to any person obtaining a copy of this Software to deal in - * the Software under the copyrights without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * The name and trademarks of copyright holder(s) may NOT be used in - * advertising or publicity pertaining to the Software or any - * derivatives without specific, written prior permission. - */ - -#include -#include "secchan.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cfg.h" -#include "command-line.h" -#include "compiler.h" -#include "daemon.h" -#include "dirs.h" -#include "discovery.h" -#include "dpif.h" -#include "fail-open.h" -#include "fault.h" -#include "in-band.h" -#include "leak-checker.h" -#include "list.h" -#include "netdev.h" -#include "ofpbuf.h" -#include "ofproto.h" -#include "openflow/openflow.h" -#include "packets.h" -#include "poll-loop.h" -#include "rconn.h" -#include "signals.h" -#include "status.h" -#include "timeval.h" -#include "util.h" -#include "vconn-ssl.h" -#include "vconn.h" -#include "vlog-socket.h" - -#include "vlog.h" -#define THIS_MODULE VLM_secchan - -static void reconfigure(struct ofproto *); -static void parse_options(int argc, char *argv[], struct settings *); -static void usage(void) NO_RETURN; - -int -main(int argc, char *argv[]) -{ - struct signal *sighup; - struct ofproto *ofproto; - struct settings s; - int retval; - - set_program_name(argv[0]); - register_fault_handlers(); - time_init(); - vlog_init(); - parse_options(argc, argv, &s); - signal(SIGPIPE, SIG_IGN); - sighup = signal_register(SIGHUP); - - die_if_already_running(); - daemonize(); - - /* Start listening for vlogconf requests. */ - retval = vlog_server_listen(NULL, NULL); - if (retval) { - ofp_fatal(retval, "Could not listen for vlog connections"); - } - - VLOG_INFO("OpenFlow reference implementation version %s", VERSION BUILDNR); - VLOG_INFO("OpenFlow protocol version 0x%02x", OFP_VERSION); - - /* Start OpenFlow processing. */ - ofproto = ofproto_create(&s); - - reconfigure(ofproto); - while (ofproto_is_alive(ofproto)) { - if (signal_poll(sighup)) { - reconfigure(ofproto); - } - - /* Do work. */ - ofproto_run(ofproto); - - /* Wait for something to happen. */ - ofproto_wait(ofproto); - signal_wait(sighup); - poll_block(); - } - - return 0; -} - -static void -reconfigure(struct ofproto *ofproto) -{ - cfg_read(); - ofproto_reconfigure(ofproto); -} - -/* User interface. */ - -static void -parse_options(int argc, char *argv[], struct settings *s) -{ - enum { - OPT_DATAPATH_ID = UCHAR_MAX + 1, - OPT_MANUFACTURER, - OPT_HARDWARE, - OPT_SOFTWARE, - OPT_SERIAL, - OPT_ACCEPT_VCONN, - OPT_NO_RESOLV_CONF, - OPT_BR_NAME, - OPT_FAIL_MODE, - OPT_INACTIVITY_PROBE, - OPT_MAX_IDLE, - OPT_MAX_BACKOFF, - OPT_RATE_LIMIT, - OPT_BURST_LIMIT, - OPT_BOOTSTRAP_CA_CERT, - OPT_STP, - OPT_NO_STP, - OPT_OUT_OF_BAND, - OPT_IN_BAND, - OPT_COMMAND_ACL, - OPT_COMMAND_DIR, - VLOG_OPTION_ENUMS, - LEAK_CHECKER_OPTION_ENUMS - }; - static struct option long_options[] = { - {"datapath-id", required_argument, 0, OPT_DATAPATH_ID}, - {"manufacturer", required_argument, 0, OPT_MANUFACTURER}, - {"hardware", required_argument, 0, OPT_HARDWARE}, - {"software", required_argument, 0, OPT_SOFTWARE}, - {"serial", required_argument, 0, OPT_SERIAL}, - {"accept-vconn", required_argument, 0, OPT_ACCEPT_VCONN}, - {"no-resolv-conf", no_argument, 0, OPT_NO_RESOLV_CONF}, - {"config", required_argument, 0, 'F'}, - {"br-name", required_argument, 0, OPT_BR_NAME}, - {"fail", required_argument, 0, OPT_FAIL_MODE}, - {"inactivity-probe", required_argument, 0, OPT_INACTIVITY_PROBE}, - {"max-idle", required_argument, 0, OPT_MAX_IDLE}, - {"max-backoff", required_argument, 0, OPT_MAX_BACKOFF}, - {"listen", required_argument, 0, 'l'}, - {"rate-limit", optional_argument, 0, OPT_RATE_LIMIT}, - {"burst-limit", required_argument, 0, OPT_BURST_LIMIT}, - {"stp", no_argument, 0, OPT_STP}, - {"no-stp", no_argument, 0, OPT_NO_STP}, - {"out-of-band", no_argument, 0, OPT_OUT_OF_BAND}, - {"in-band", no_argument, 0, OPT_IN_BAND}, - {"command-acl", required_argument, 0, OPT_COMMAND_ACL}, - {"command-dir", required_argument, 0, OPT_COMMAND_DIR}, - {"verbose", optional_argument, 0, 'v'}, - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - DAEMON_LONG_OPTIONS, - VLOG_LONG_OPTIONS, - LEAK_CHECKER_LONG_OPTIONS, -#ifdef HAVE_OPENSSL - VCONN_SSL_LONG_OPTIONS - {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT}, -#endif - {0, 0, 0, 0}, - }; - char *short_options = long_options_to_short_options(long_options); - - /* Set defaults that we can figure out before parsing options. */ - s->datapath_id = 0; - s->mfr_desc = "Nicira Networks, Inc."; - s->hw_desc = "Reference Implementation"; - s->sw_desc = VERSION BUILDNR; - s->serial_desc = "None"; - s->n_listeners = 0; - s->fail_mode = FAIL_OPEN; - s->max_idle = 15; - s->probe_interval = 15; - s->max_backoff = 15; - s->update_resolv_conf = true; - s->rate_limit = 0; - s->burst_limit = 0; - s->accept_controller_re = NULL; - s->enable_stp = false; - s->in_band = true; - s->command_acl = ""; - s->command_dir = xasprintf("%s/commands", ofp_pkgdatadir); - for (;;) { - int error; - int c; - - c = getopt_long(argc, argv, short_options, long_options, NULL); - if (c == -1) { - break; - } - - switch (c) { - case OPT_DATAPATH_ID: - if (strlen(optarg) != 12 - || strspn(optarg, "0123456789abcdefABCDEF") != 12) { - ofp_fatal(0, "argument to --datapath-id must be " - "exactly 12 hex digits"); - } - s->datapath_id = strtoll(optarg, NULL, 16); - if (!s->datapath_id) { - ofp_fatal(0, "argument to --datapath-id must be nonzero"); - } - break; - - case OPT_MANUFACTURER: - s->mfr_desc = optarg; - break; - - case OPT_HARDWARE: - s->hw_desc = optarg; - break; - - case OPT_SOFTWARE: - s->sw_desc = optarg; - break; - - case OPT_SERIAL: - s->serial_desc = optarg; - break; - - case OPT_ACCEPT_VCONN: - s->accept_controller_re = (optarg[0] == '^' ? optarg - : xasprintf("^%s", optarg)); - break; - - case OPT_BR_NAME: - s->br_name = optarg; - break; - - case OPT_NO_RESOLV_CONF: - s->update_resolv_conf = false; - break; - - case OPT_FAIL_MODE: - if (!strcmp(optarg, "open")) { - s->fail_mode = FAIL_OPEN; - } else if (!strcmp(optarg, "closed")) { - s->fail_mode = FAIL_CLOSED; - } else { - ofp_fatal(0, "-f or --fail argument must be \"open\" " - "or \"closed\""); - } - break; - - case OPT_INACTIVITY_PROBE: - s->probe_interval = atoi(optarg); - if (s->probe_interval < 5) { - ofp_fatal(0, "--inactivity-probe argument must be at least 5"); - } - break; - - case OPT_MAX_IDLE: - if (!strcmp(optarg, "permanent")) { - s->max_idle = OFP_FLOW_PERMANENT; - } else { - s->max_idle = atoi(optarg); - if (s->max_idle < 1 || s->max_idle > 65535) { - ofp_fatal(0, "--max-idle argument must be between 1 and " - "65535 or the word 'permanent'"); - } - } - break; - - case OPT_MAX_BACKOFF: - s->max_backoff = atoi(optarg); - if (s->max_backoff < 1) { - ofp_fatal(0, "--max-backoff argument must be at least 1"); - } else if (s->max_backoff > 3600) { - s->max_backoff = 3600; - } - break; - - case OPT_RATE_LIMIT: - if (optarg) { - s->rate_limit = atoi(optarg); - if (s->rate_limit < 1) { - ofp_fatal(0, "--rate-limit argument must be at least 1"); - } - } else { - s->rate_limit = 1000; - } - break; - - case OPT_BURST_LIMIT: - s->burst_limit = atoi(optarg); - if (s->burst_limit < 1) { - ofp_fatal(0, "--burst-limit argument must be at least 1"); - } - break; - - case OPT_STP: - s->enable_stp = true; - break; - - case OPT_NO_STP: - s->enable_stp = false; - break; - - case OPT_OUT_OF_BAND: - s->in_band = false; - break; - - case OPT_IN_BAND: - s->in_band = true; - break; - - case OPT_COMMAND_ACL: - s->command_acl = (s->command_acl[0] - ? xasprintf("%s,%s", s->command_acl, optarg) - : optarg); - break; - - case OPT_COMMAND_DIR: - s->command_dir = optarg; - break; - - case 'F': - error = cfg_add_file(optarg); - if (error) { - ofp_fatal(error, "failed to add configuration file or " - "directory \"%s\"", optarg); - } - break; - - case 'l': - if (s->n_listeners >= MAX_MGMT) { - ofp_fatal(0, - "-l or --listen may be specified at most %d times", - MAX_MGMT); - } - s->listener_names[s->n_listeners++] = optarg; - break; - - case 'h': - usage(); - - case 'V': - printf("%s %s compiled "__DATE__" "__TIME__"\n", - program_name, VERSION BUILDNR); - exit(EXIT_SUCCESS); - - DAEMON_OPTION_HANDLERS - - VLOG_OPTION_HANDLERS - - LEAK_CHECKER_OPTION_HANDLERS - -#ifdef HAVE_OPENSSL - VCONN_SSL_OPTION_HANDLERS - - case OPT_BOOTSTRAP_CA_CERT: - vconn_ssl_set_ca_cert_file(optarg, true); - break; -#endif - - case '?': - exit(EXIT_FAILURE); - - default: - abort(); - } - } - free(short_options); - - argc -= optind; - argv += optind; - if (argc < 1 || argc > 2) { - ofp_fatal(0, "need one or two non-option arguments; " - "use --help for usage"); - } - - /* Local and remote vconns. */ - s->dp_name = argv[0]; - s->controller_name = argc > 1 ? xstrdup(argv[1]) : NULL; - - /* Set accept_controller_regex. */ - if (!s->accept_controller_re) { - s->accept_controller_re = vconn_ssl_is_configured() ? "^ssl:.*" : ".*"; - } - - /* Mode of operation. */ - s->discovery = s->controller_name == NULL; - if (s->discovery && !s->in_band) { - ofp_fatal(0, "Cannot perform discovery with out-of-band control"); - } - - /* Rate limiting. */ - if (s->rate_limit) { - if (s->rate_limit < 100) { - VLOG_WARN("Rate limit set to unusually low value %d", - s->rate_limit); - } - if (!s->burst_limit) { - s->burst_limit = s->rate_limit / 4; - } - s->burst_limit = MAX(s->burst_limit, 1); - s->burst_limit = MIN(s->burst_limit, INT_MAX / 1000); - } -} - -static void -usage(void) -{ - printf("%s: secure channel, a relay for OpenFlow messages.\n" - "usage: %s [OPTIONS] DATAPATH [CONTROLLER]\n" - "DATAPATH is a local datapath (e.g. \"dp0\").\n" - "CONTROLLER is an active OpenFlow connection method; if it is\n" - "omitted, then secchan performs controller discovery.\n", - program_name, program_name); - vconn_usage(true, true, true); - printf("\nConfiguration options:\n" - " -F, --config=FILE|DIR reads configuration from FILE or DIR\n" - " --br-name=NAME bridge name to use for configuration\n" - "\nOpenFlow options:\n" - " -d, --datapath-id=ID Use ID as the OpenFlow switch ID\n" - " (ID must consist of 12 hex digits)\n" - " --manufacturer=MFR Identify manufacturer as MFR\n" - " --hardware=HW Identify hardware as HW\n" - " --software=SW Identify software as SW\n" - " --serial=SERIAL Identify serial number as SERIAL\n" - "\nController discovery options:\n" - " --accept-vconn=REGEX accept matching discovered controllers\n" - " --no-resolv-conf do not update /etc/resolv.conf\n" - "\nNetworking options:\n" - " --fail=open|closed when controller connection fails:\n" - " closed: drop all packets\n" - " open (default): act as learning switch\n" - " --inactivity-probe=SECS time between inactivity probes\n" - " --max-idle=SECS max idle for flows set up by secchan\n" - " --max-backoff=SECS max time between controller connection\n" - " attempts (default: 15 seconds)\n" - " -l, --listen=METHOD allow management connections on METHOD\n" - " (a passive OpenFlow connection method)\n" - " --out-of-band controller connection is out-of-band\n" - " --stp enable 802.1D Spanning Tree Protocol\n" - " --no-stp disable 802.1D Spanning Tree Protocol\n" - "\nRate-limiting of \"packet-in\" messages to the controller:\n" - " --rate-limit[=PACKETS] max rate, in packets/s (default: 1000)\n" - " --burst-limit=BURST limit on packet credit for idle time\n" - "\nRemote command execution options:\n" - " --command-acl=[!]GLOB[,[!]GLOB...] set allowed/denied commands\n" - " --command-dir=DIR set command dir (default: %s/commands)\n", - ofp_pkgdatadir); - daemon_usage(); - vlog_usage(); - printf("\nOther options:\n" - " -h, --help display this help message\n" - " -V, --version display version information\n"); - leak_checker_usage(); - exit(EXIT_SUCCESS); -} diff --git a/secchan/secchan.h b/secchan/secchan.h deleted file mode 100644 index a8564b86..00000000 --- a/secchan/secchan.h +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford - * Junior University - * - * We are making the OpenFlow specification and associated documentation - * (Software) available for public use and benefit with the expectation - * that others will use, modify and enhance the Software and contribute - * those enhancements back to the community. However, since we would - * like to make the Software available for broadest use, with as few - * restrictions as possible permission is hereby granted, free of - * charge, to any person obtaining a copy of this Software to deal in - * the Software under the copyrights without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * The name and trademarks of copyright holder(s) may NOT be used in - * advertising or publicity pertaining to the Software or any - * derivatives without specific, written prior permission. - */ - -#ifndef SECCHAN_H -#define SECCHAN_H 1 - -#include -#include -#include "list.h" - -/* Behavior when the connection to the controller fails. */ -enum fail_mode { - FAIL_OPEN, /* Act as learning switch. */ - FAIL_CLOSED /* Drop all packets. */ -}; - -/* Maximum number of management connection listeners. */ -#define MAX_MGMT 8 - -/* Settings that may be configured by the user. */ -struct settings { - /* Configuration. */ - const char *br_name; /* Bridge name to use for configuration lookup */ - - /* Overall mode of operation. */ - bool discovery; /* Discover the controller automatically? */ - bool in_band; /* Connect to controller in-band? */ - - /* Datapath. */ - uint64_t datapath_id; /* Datapath ID. */ - const char *dp_name; /* Name of local datapath. */ - - /* Description strings. */ - const char *mfr_desc; /* Manufacturer. */ - const char *hw_desc; /* Hardware. */ - const char *sw_desc; /* Software version. */ - const char *serial_desc; /* Serial number. */ - - /* Related vconns and network devices. */ - const char *controller_name; /* Controller (if not discovery mode). */ - const char *listener_names[MAX_MGMT]; /* Listen for mgmt connections. */ - size_t n_listeners; /* Number of mgmt connection listeners. */ - - /* Failure behavior. */ - enum fail_mode fail_mode; /* Act as learning switch if no controller? */ - int max_idle; /* Idle time for flows in fail-open mode. */ - int probe_interval; /* # seconds idle before sending echo request. */ - int max_backoff; /* Max # seconds between connection attempts. */ - - /* Packet-in rate-limiting. */ - int rate_limit; /* Tokens added to bucket per second. */ - int burst_limit; /* Maximum number token bucket size. */ - - /* Discovery behavior. */ - const char *accept_controller_re; /* Controller vconns to accept. */ - bool update_resolv_conf; /* Update /etc/resolv.conf? */ - - /* Spanning tree protocol. */ - bool enable_stp; - - /* Remote command execution. */ - char *command_acl; /* Command white/blacklist, as shell globs. */ - char *command_dir; /* Directory that contains commands. */ -}; - -#endif /* secchan.h */ diff --git a/secchan/status.c b/secchan/status.c index fd57e514..3f9b0f4b 100644 --- a/secchan/status.c +++ b/secchan/status.c @@ -39,9 +39,9 @@ #include #include "dynamic-string.h" #include "ofpbuf.h" +#include "ofproto.h" #include "openflow/nicira-ext.h" #include "rconn.h" -#include "secchan.h" #include "timeval.h" #include "vconn.h" @@ -126,7 +126,7 @@ rconn_status_cb(struct status_reply *sr, void *rconn_) static void config_status_cb(struct status_reply *sr, void *s_) { - const struct settings *s = s_; + const struct ofsettings *s = s_; size_t i; for (i = 0; i < s->n_listeners; i++) { @@ -152,7 +152,7 @@ switch_status_cb(struct status_reply *sr, void *ss_) } struct switch_status * -switch_status_create(const struct settings *settings) +switch_status_create(const struct ofsettings *settings) { struct switch_status *ss = xcalloc(1, sizeof *ss); ss->booted = time_now(); diff --git a/secchan/status.h b/secchan/status.h index dbb0300a..f8766206 100644 --- a/secchan/status.h +++ b/secchan/status.h @@ -39,10 +39,10 @@ struct nicira_header; struct rconn; struct secchan; -struct settings; +struct ofsettings; struct status_reply; -struct switch_status *switch_status_create(const struct settings *); +struct switch_status *switch_status_create(const struct ofsettings *); int switch_status_handle_request(struct switch_status *, struct rconn *, struct nicira_header *);