ospfd: OSPFAPI Server options to limit to local connections and per-instance TCP

This commit include OSPFAPI Server options to:

 1. Allow specification of the OSPFAPI server local address.
 2. Allow different OSPFAPI server TCP ports to be specified for different
    OSPF instances in /etc/services.

Signed-off-by: Acee Lindem <acee@lindem.com>
This commit is contained in:
Acee Lindem 2024-04-19 15:33:20 +00:00
parent 8e7fb950c1
commit 3b75723061
4 changed files with 51 additions and 14 deletions

View file

@ -28,6 +28,12 @@ Configuring OSPF
Enable the OSPF API server. This is required to use ``ospfclient``. Enable the OSPF API server. This is required to use ``ospfclient``.
.. option:: -l, --apiserver_addr <address>
Specify the local IPv4 address to which to bind the OSPF API server socket.
If unspecified, connections are accepted to any address. Specification of
127.0.0.1 can be used to limit socket access to local applications.
*ospfd* must acquire interface information from *zebra* in order to function. *ospfd* must acquire interface information from *zebra* in order to function.
Therefore *zebra* must be running before invoking *ospfd*. Also, if *zebra* is Therefore *zebra* must be running before invoking *ospfd*. Also, if *zebra* is
restarted then *ospfd* must be too. restarted then *ospfd* must be too.

View file

@ -62,6 +62,11 @@ DEFINE_MTYPE_STATIC(OSPFD, APISERVER_MSGFILTER, "API Server Message Filter");
/* List of all active connections. */ /* List of all active connections. */
struct list *apiserver_list; struct list *apiserver_list;
/* Indicates that API the server socket local addresss has been
* specified.
*/
struct in_addr ospf_apiserver_addr;
/* ----------------------------------------------------------- /* -----------------------------------------------------------
* Functions to lookup interfaces * Functions to lookup interfaces
* ----------------------------------------------------------- * -----------------------------------------------------------
@ -109,7 +114,21 @@ struct ospf_interface *ospf_apiserver_if_lookup_by_ifp(struct interface *ifp)
unsigned short ospf_apiserver_getport(void) unsigned short ospf_apiserver_getport(void)
{ {
struct servent *sp = getservbyname("ospfapi", "tcp"); struct servent *sp = NULL;
char sbuf[16];
/*
* Allow the OSPF API server port to be specified per-instance by
* including the instance ID in the /etc/services name. Use the
* prior name if no per-instance service is specified.
*/
if (ospf_instance) {
snprintfrr(sbuf, sizeof(sbuf), "ospfapi-%d", ospf_instance);
sp = getservbyname(sbuf, "tcp");
}
if (!sp)
sp = getservbyname("ospfapi", "tcp");
return sp ? ntohs(sp->s_port) : OSPF_API_SYNC_PORT; return sp ? ntohs(sp->s_port) : OSPF_API_SYNC_PORT;
} }
@ -557,8 +576,10 @@ int ospf_apiserver_serv_sock_family(unsigned short port, int family)
sockopt_reuseaddr(accept_sock); sockopt_reuseaddr(accept_sock);
sockopt_reuseport(accept_sock); sockopt_reuseport(accept_sock);
/* Bind socket to address and given port. */ /* Bind socket to optional lcoal address and port. */
rc = sockunion_bind(accept_sock, &su, port, NULL); if (ospf_apiserver_addr.s_addr)
sockunion2ip(&su) = ospf_apiserver_addr.s_addr;
rc = sockunion_bind(accept_sock, &su, port, &su);
if (rc < 0) { if (rc < 0) {
close(accept_sock); /* Close socket */ close(accept_sock); /* Close socket */
return rc; return rc;

View file

@ -66,6 +66,14 @@ enum ospf_apiserver_event {
OSPF_APISERVER_ASYNC_WRITE OSPF_APISERVER_ASYNC_WRITE
}; };
/* -----------------------------------------------------------
* External definitions for OSPF API ospfd parameters.
* -----------------------------------------------------------
*/
extern int ospf_apiserver_enable;
extern struct in_addr ospf_apiserver_addr;
/* ----------------------------------------------------------- /* -----------------------------------------------------------
* Following are functions to manage client connections. * Following are functions to manage client connections.
* ----------------------------------------------------------- * -----------------------------------------------------------

View file

@ -44,6 +44,7 @@
#include "ospfd/ospf_errors.h" #include "ospfd/ospf_errors.h"
#include "ospfd/ospf_ldp_sync.h" #include "ospfd/ospf_ldp_sync.h"
#include "ospfd/ospf_routemap_nb.h" #include "ospfd/ospf_routemap_nb.h"
#include "ospfd/ospf_apiserver.h"
#define OSPFD_STATE_NAME "%s/ospfd.json", frr_libstatedir #define OSPFD_STATE_NAME "%s/ospfd.json", frr_libstatedir
#define OSPFD_INST_STATE_NAME(i) "%s/ospfd-%d.json", frr_runstatedir, i #define OSPFD_INST_STATE_NAME(i) "%s/ospfd-%d.json", frr_runstatedir, i
@ -75,6 +76,7 @@ struct zebra_privs_t ospfd_privs = {
const struct option longopts[] = { const struct option longopts[] = {
{"instance", required_argument, NULL, 'n'}, {"instance", required_argument, NULL, 'n'},
{"apiserver", no_argument, NULL, 'a'}, {"apiserver", no_argument, NULL, 'a'},
{"apiserver_addr", required_argument, NULL, 'l'},
{0} {0}
}; };
@ -83,10 +85,6 @@ const struct option longopts[] = {
/* Master of threads. */ /* Master of threads. */
struct event_loop *master; struct event_loop *master;
#ifdef SUPPORT_OSPF_API
extern int ospf_apiserver_enable;
#endif /* SUPPORT_OSPF_API */
/* SIGHUP handler. */ /* SIGHUP handler. */
static void sighup(void) static void sighup(void)
{ {
@ -193,15 +191,11 @@ static void ospf_config_end(void)
/* OSPFd main routine. */ /* OSPFd main routine. */
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
#ifdef SUPPORT_OSPF_API
/* OSPF apiserver is disabled by default. */
ospf_apiserver_enable = 0;
#endif /* SUPPORT_OSPF_API */
frr_preinit(&ospfd_di, argc, argv); frr_preinit(&ospfd_di, argc, argv);
frr_opt_add("n:a", longopts, frr_opt_add("n:al:", longopts,
" -n, --instance Set the instance id\n" " -n, --instance Set the instance id\n"
" -a, --apiserver Enable OSPF apiserver\n"); " -a, --apiserver Enable OSPF apiserver\n"
" -l, --apiserver_addr Set OSPF apiserver bind address\n");
while (1) { while (1) {
int opt; int opt;
@ -223,6 +217,14 @@ int main(int argc, char **argv)
case 'a': case 'a':
ospf_apiserver_enable = 1; ospf_apiserver_enable = 1;
break; break;
case 'l':
if (inet_pton(AF_INET, optarg, &ospf_apiserver_addr) <=
0) {
zlog_err("OSPF: Invalid API Server IPv4 address %s specified",
optarg);
exit(0);
}
break;
#endif /* SUPPORT_OSPF_API */ #endif /* SUPPORT_OSPF_API */
default: default:
frr_help_exit(1); frr_help_exit(1);