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``.
.. 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.
Therefore *zebra* must be running before invoking *ospfd*. Also, if *zebra* is
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. */
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
* -----------------------------------------------------------
@ -109,7 +114,21 @@ struct ospf_interface *ospf_apiserver_if_lookup_by_ifp(struct interface *ifp)
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;
}
@ -557,8 +576,10 @@ int ospf_apiserver_serv_sock_family(unsigned short port, int family)
sockopt_reuseaddr(accept_sock);
sockopt_reuseport(accept_sock);
/* Bind socket to address and given port. */
rc = sockunion_bind(accept_sock, &su, port, NULL);
/* Bind socket to optional lcoal address and port. */
if (ospf_apiserver_addr.s_addr)
sockunion2ip(&su) = ospf_apiserver_addr.s_addr;
rc = sockunion_bind(accept_sock, &su, port, &su);
if (rc < 0) {
close(accept_sock); /* Close socket */
return rc;

View file

@ -66,6 +66,14 @@ enum ospf_apiserver_event {
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.
* -----------------------------------------------------------

View file

@ -44,6 +44,7 @@
#include "ospfd/ospf_errors.h"
#include "ospfd/ospf_ldp_sync.h"
#include "ospfd/ospf_routemap_nb.h"
#include "ospfd/ospf_apiserver.h"
#define OSPFD_STATE_NAME "%s/ospfd.json", frr_libstatedir
#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[] = {
{"instance", required_argument, NULL, 'n'},
{"apiserver", no_argument, NULL, 'a'},
{"apiserver_addr", required_argument, NULL, 'l'},
{0}
};
@ -83,10 +85,6 @@ const struct option longopts[] = {
/* Master of threads. */
struct event_loop *master;
#ifdef SUPPORT_OSPF_API
extern int ospf_apiserver_enable;
#endif /* SUPPORT_OSPF_API */
/* SIGHUP handler. */
static void sighup(void)
{
@ -193,15 +191,11 @@ static void ospf_config_end(void)
/* OSPFd main routine. */
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_opt_add("n:a", longopts,
frr_opt_add("n:al:", longopts,
" -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) {
int opt;
@ -223,6 +217,14 @@ int main(int argc, char **argv)
case 'a':
ospf_apiserver_enable = 1;
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 */
default:
frr_help_exit(1);