Skip to content

Commit

Permalink
grpc: add ability to specify grpc host
Browse files Browse the repository at this point in the history
This update lets you specify the network interface for gRPC.
For example, using 127.0.0.1 restricts gRPC access to the local machine, enhancing security since gRPC is not publicly exposed.
For backward compatibility, the default remains 0.0.0.0.

Signed-off-by: Vladimir Buyanov <[email protected]>
  • Loading branch information
cl-bvl committed Feb 19, 2025
1 parent bd80b10 commit 7ebb5df
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 18 deletions.
2 changes: 1 addition & 1 deletion doc/developer/grpc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Northbound gRPC
To enable gRPC support one needs to add `--enable-grpc` when running
`configure`. Additionally, when launching each daemon one needs to request
the gRPC module be loaded and which port to bind to. This can be done by adding
`-M grpc:<port>` to the daemon's CLI arguments.
`-M grpc:<host>:<port>` or `-M grpc:<port>` (default host is `0.0.0.0`) to the daemon's CLI arguments.

Currently there is no gRPC "routing" so you will need to bind your gRPC
`channel` to the particular daemon's gRPC port to interact with that daemon's
Expand Down
70 changes: 53 additions & 17 deletions lib/northbound_grpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1131,18 +1131,15 @@ static grpc::Server *s_server;
static void *grpc_pthread_start(void *arg)
{
struct frr_pthread *fpt = static_cast<frr_pthread *>(arg);
uint port = (uint) reinterpret_cast<intptr_t>(fpt->data);
std::string endpoint = *static_cast<std::string *>(fpt->data);

Candidates candidates;
grpc::ServerBuilder builder;
std::stringstream server_address;
frr::Northbound::AsyncService service;

frr_pthread_set_name(fpt);

server_address << "0.0.0.0:" << port;
builder.AddListeningPort(server_address.str(),
grpc::InsecureServerCredentials());
builder.AddListeningPort(endpoint, grpc::InsecureServerCredentials());
builder.RegisterService(&service);
builder.AddChannelArgument(
GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS, 5000);
Expand Down Expand Up @@ -1172,8 +1169,7 @@ static void *grpc_pthread_start(void *arg)
REQUEST_NEWRPC_STREAMING(Get);
REQUEST_NEWRPC_STREAMING(ListTransactions);

zlog_notice("gRPC server listening on %s",
server_address.str().c_str());
zlog_notice("gRPC server listening on %s", endpoint.c_str());

/* Process inbound RPCs */
bool ok;
Expand Down Expand Up @@ -1225,7 +1221,7 @@ static void *grpc_pthread_start(void *arg)
}


static int frr_grpc_init(uint port)
static int frr_grpc_init(const std::string &endpoint)
{
struct frr_pthread_attr attr = {
.start = grpc_pthread_start,
Expand All @@ -1235,12 +1231,14 @@ static int frr_grpc_init(uint port)
grpc_debug("%s: entered", __func__);

fpt = frr_pthread_new(&attr, "frr-grpc", "frr-grpc");
fpt->data = reinterpret_cast<void *>((intptr_t)port);
std::string *ep = new std::string(endpoint);
fpt->data = reinterpret_cast<void *>(ep);

/* Create a pthread for gRPC since it runs its own event loop. */
if (frr_pthread_run(fpt, NULL) < 0) {
flog_err(EC_LIB_SYSTEM_CALL, "%s: error creating pthread: %s",
__func__, safe_strerror(errno));
delete ep;
return -1;
}

Expand Down Expand Up @@ -1288,19 +1286,57 @@ static int frr_grpc_finish(void)
static void frr_grpc_module_very_late_init(struct event *thread)
{
const char *args = THIS_MODULE->load_args;
uint port = GRPC_DEFAULT_PORT;
std::string endpoint;

if (args) {
port = std::stoul(args);
if (port < 1024 || port > UINT16_MAX) {
flog_err(EC_LIB_GRPC_INIT,
"%s: port number must be between 1025 and %d",
__func__, UINT16_MAX);
goto error;
std::string arg_str(args);

if (arg_str.find(':') != std::string::npos) {
size_t pos = arg_str.rfind(':');
std::string port_str = arg_str.substr(pos + 1);
uint port = 0;
try {
port = std::stoul(port_str);
} catch (const std::exception &e) {
flog_err(EC_LIB_GRPC_INIT,
"%s: invalid port number in host:port format: %s",
__func__, e.what());
goto error;
}

if (port < 1024 || port > UINT16_MAX) {
flog_err(EC_LIB_GRPC_INIT,
"%s: port number must be between 1025 and %d", __func__,
UINT16_MAX);
goto error;
}
endpoint = arg_str;
} else {
if (!arg_str.empty() && arg_str[0] == ':')
arg_str = arg_str.substr(1);

uint port = 0;
try {
port = std::stoul(arg_str);
} catch (const std::exception &e) {
flog_err(EC_LIB_GRPC_INIT, "%s: invalid port number: %s", __func__,
e.what());
goto error;
}

if (port < 1024 || port > UINT16_MAX) {
flog_err(EC_LIB_GRPC_INIT,
"%s: port number must be between 1025 and %d", __func__,
UINT16_MAX);
goto error;
}
endpoint = "0.0.0.0:" + arg_str;
}
} else {
endpoint = "0.0.0.0:" + std::to_string(GRPC_DEFAULT_PORT);
}

if (frr_grpc_init(port) < 0)
if (frr_grpc_init(endpoint) < 0)
goto error;

return;
Expand Down

0 comments on commit 7ebb5df

Please sign in to comment.