From: Romain Lenglet <romain.leng...@berabera.info> Modify the nox_core command line arguments to accept the socket bind address for the ptcp: and pssl: interfaces. This is particularly important for the ptcp: method, as it can help improving security and performance in some cases. For instance, if a controller connects only to datapaths on the same host, using ptcp: and binding to 127.0.0.1 limits to connections from the localhost. Otherwise, pssl: must be used, which is less efficient.
More precisely, support the following extra interface syntaxes: ptcp:[IP]:[PORT] in addition to ptcp:[PORT], and pssl:[IP]:[PORT]:KEY:CERT:CONTROLLER_CA_CERT in addition to pssl:[PORT]:KEY:CERT:CONTROLLER_CA_CERT. --- src/include/openflow.hh | 8 +++++- src/lib/openflow.cc | 58 ++++++++++++++++++++++++++++++++++++---------- src/nox_main.cc | 11 ++++++-- 3 files changed, 59 insertions(+), 18 deletions(-) diff --git a/src/include/openflow.hh b/src/include/openflow.hh index 02e6f9f..5248bbb 100644 --- a/src/include/openflow.hh +++ b/src/include/openflow.hh @@ -284,13 +284,15 @@ class Passive_tcp_openflow_connection_factory : public Openflow_connection_factory { public: - Passive_tcp_openflow_connection_factory(uint16_t port); + Passive_tcp_openflow_connection_factory(const char* bind_ip, + uint16_t port); Openflow_connection* connect(int& error); void connect_wait(); std::string to_string(); bool passive() { return true; } private: Tcp_socket socket; + ipaddr bind_ip; uint16_t port; }; @@ -314,7 +316,8 @@ class Passive_ssl_openflow_connection_factory : public Openflow_connection_factory { public: - Passive_ssl_openflow_connection_factory(uint16_t port, const char *key, + Passive_ssl_openflow_connection_factory(const char* bind_ip, + uint16_t port, const char *key, const char *cert, const char *CAfile); Openflow_connection* connect(int& error); @@ -324,6 +327,7 @@ public: private: boost::shared_ptr<Ssl_config> config; Ssl_socket socket; + ipaddr bind_ip; uint16_t port; }; diff --git a/src/lib/openflow.cc b/src/lib/openflow.cc index e23cb20..f7ee232 100644 --- a/src/lib/openflow.cc +++ b/src/lib/openflow.cc @@ -1134,11 +1134,24 @@ Openflow_connection_factory* Openflow_connection_factory::create( ? atoi(tokens[2].c_str()) : OFP_TCP_PORT; return new Tcp_openflow_connection_factory(tokens[1], htons(port)); } else if (tokens[0] == "ptcp") { - uint16_t port = atoi(tokens[1].c_str()); + const char* bind_ip = "0.0.0.0"; + uint16_t port = 0; + if (tokens.size() == 2) { + port = atoi(tokens[1].c_str()); + } else if (tokens.size() == 3) { + if (tokens[1].size() > 0) { + bind_ip = tokens[1].c_str(); + } + port = atoi(tokens[2].c_str()); + } else { + log.err("ptcp connection name not in the form ptcp:[PORT] or ptcp:[IP]:[PORT]"); + exit(EXIT_FAILURE); + } if (!port) { port = OFP_TCP_PORT; } - return new Passive_tcp_openflow_connection_factory(htons(port)); + return new Passive_tcp_openflow_connection_factory(bind_ip, + htons(port)); } else if (tokens[0] == "ssl") { if (tokens.size() != 6) { log.err("ssl connection name not in the form ssl:HOST:[PORT]:KEY:CERT:CAFILE"); @@ -1152,17 +1165,33 @@ Openflow_connection_factory* Openflow_connection_factory::create( tokens[1], htons(port), tokens[3].c_str(), tokens[4].c_str(), tokens[5].c_str()); } else if (tokens[0] == "pssl") { - if (tokens.size() != 5) { - log.err("pssl connection name not in the form pssl:[PORT]:KEY:CERT:CAFILE"); + const char* bind_ip = "0.0.0.0"; + uint16_t port = 0; + const char* ssl_key = ""; + const char* ssl_cert = ""; + const char* ssl_cafile = ""; + if (tokens.size() == 5) { + port = atoi(tokens[1].c_str()); + ssl_key = tokens[2].c_str(); + ssl_cert = tokens[3].c_str(); + ssl_cafile = tokens[4].c_str(); + } else if (tokens.size() == 6) { + if (tokens[1].size() > 0) { + bind_ip = tokens[1].c_str(); + } + port = atoi(tokens[2].c_str()); + ssl_key = tokens[3].c_str(); + ssl_cert = tokens[4].c_str(); + ssl_cafile = tokens[5].c_str(); + } else { + log.err("pssl connection name not in the form pssl:[PORT]:KEY:CERT:CAFILE or pssl:[IP]:[PORT]:KEY:CERT:CAFILE"); exit(EXIT_FAILURE); } - uint16_t port = atoi(tokens[1].c_str()); if (!port) { port = OFP_SSL_PORT; } return new Passive_ssl_openflow_connection_factory( - htons(port), tokens[2].c_str(), tokens[3].c_str(), - tokens[4].c_str()); + bind_ip, htons(port), ssl_key, ssl_cert, ssl_cafile); } else if (tokens[0] == "pcap") { #ifndef HAVE_PCAP log.err("pcap support not built in. Ensure you have pcap installed and rebuild"); @@ -1248,11 +1277,12 @@ Tcp_openflow_connection_factory::to_string() } Passive_tcp_openflow_connection_factory -::Passive_tcp_openflow_connection_factory(uint16_t port_) - : port(port_) +::Passive_tcp_openflow_connection_factory(const char* bind_ip_, + uint16_t port_) + : bind_ip(bind_ip_), port(port_) { socket.set_reuseaddr(); - int error = socket.bind(htonl(INADDR_ANY), port); + int error = socket.bind(bind_ip, port); if (error) { throw errno_exception(error, "bind"); } @@ -1336,17 +1366,19 @@ Ssl_openflow_connection_factory::to_string() } Passive_ssl_openflow_connection_factory -::Passive_ssl_openflow_connection_factory(uint16_t port_, - const char *key, const char *cert, +::Passive_ssl_openflow_connection_factory(const char* bind_ip_, + uint16_t port_, const char *key, + const char *cert, const char *CAfile) : config(new Ssl_config(Ssl_config::SSLv3 | Ssl_config::TLSv1, Ssl_config::AUTHENTICATE_SERVER, Ssl_config::REQUIRE_CLIENT_CERT, key, cert, CAfile)), socket(config), + bind_ip(bind_ip_), port(port_) { - int error = socket.bind(htonl(INADDR_ANY), port); + int error = socket.bind(bind_ip, port); if (error) { throw errno_exception(error, "bind"); } diff --git a/src/nox_main.cc b/src/nox_main.cc index 1901672..ebf4dc8 100644 --- a/src/nox_main.cc +++ b/src/nox_main.cc @@ -158,15 +158,20 @@ void usage(const char* program_name) #ifdef HAVE_NETLINK " -i nl:DP_ID via netlink to local datapath DP_IDX\n" #endif - " -i ptcp:[PORT] listen to TCP PORT (default: %d)\n" + " -i ptcp:[PORT] listen to TCP PORT (default: %d) on all IP addresses\n" + " -i ptcp:[IP]:[PORT] listen to TCP PORT (default: %d) on the given IP\n" + " (default: all IP addresses)\n" " -i pssl:[PORT]:KEY:CERT:CONTROLLER_CA_CERT\n" - " listen to SSL PORT (default: %d)\n" + " listen to SSL PORT (default: %d) on all IP addresses\n" + " -i pssl:[IP]:[PORT]:KEY:CERT:CONTROLLER_CA_CERT\n" + " listen to SSL PORT (default: %d) on the given IP\n" + " (default: all IP addresses)\n" " -i pcap:FILE[:OUTFILE] via pcap from FILE (for testing) write to OUTFILE\n" " -i pcapt:FILE[:OUTFILE] same as \"pcap\", but delay packets based on pcap timestamps\n" " -i pgen: continuously generate packet-in events\n" "\nNetwork control options (must also specify an interface):\n" " -u, --unreliable do not reconnect to interfaces on error\n", - program_name, program_name, OFP_TCP_PORT, OFP_SSL_PORT); + program_name, program_name, OFP_TCP_PORT, OFP_TCP_PORT, OFP_SSL_PORT, OFP_SSL_PORT); leak_checker_usage(); printf("\nOther options:\n" " -c, --conf=FILE set configuration file\n" -- 1.7.2.3 _______________________________________________ nox-dev mailing list nox-dev@noxrepo.org http://noxrepo.org/mailman/listinfo/nox-dev_noxrepo.org