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"