mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +00:00
Additional CLI and TCP control sockets
This commit is contained in:
parent
a794b2e8c1
commit
1ef65e7a7e
@ -14,6 +14,9 @@
|
|||||||
#include "lib/hash.h"
|
#include "lib/hash.h"
|
||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
#include "lib/timer.h"
|
#include "lib/timer.h"
|
||||||
|
#include "lib/tlists.h"
|
||||||
|
|
||||||
|
#include "sysdep/unix/conf.h"
|
||||||
|
|
||||||
/* Configuration structure */
|
/* Configuration structure */
|
||||||
|
|
||||||
@ -31,6 +34,8 @@ struct config {
|
|||||||
struct rtable_config *def_tables[NET_MAX]; /* Default routing tables for each network */
|
struct rtable_config *def_tables[NET_MAX]; /* Default routing tables for each network */
|
||||||
struct iface_patt *router_id_from; /* Configured list of router ID iface patterns */
|
struct iface_patt *router_id_from; /* Configured list of router ID iface patterns */
|
||||||
|
|
||||||
|
TLIST_LIST(control_socket_config) control_socket; /* Control socket definitions */
|
||||||
|
|
||||||
u32 router_id; /* Our Router ID */
|
u32 router_id; /* Our Router ID */
|
||||||
u32 proto_default_debug; /* Default protocol debug mask */
|
u32 proto_default_debug; /* Default protocol debug mask */
|
||||||
u32 proto_default_mrtdump; /* Default protocol mrtdump mask */
|
u32 proto_default_mrtdump; /* Default protocol mrtdump mask */
|
||||||
|
@ -95,6 +95,7 @@ CF_DECLS
|
|||||||
struct timeformat *tf;
|
struct timeformat *tf;
|
||||||
mpls_label_stack *mls;
|
mpls_label_stack *mls;
|
||||||
struct bytestring *bs;
|
struct bytestring *bs;
|
||||||
|
struct control_socket_config *control_socket_config;
|
||||||
}
|
}
|
||||||
|
|
||||||
%token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT
|
%token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT
|
||||||
|
@ -179,7 +179,8 @@ BIRD executable by configuring out routing protocols you don't use, and
|
|||||||
|
|
||||||
<tag><label id="argv-socket">-s <m/name of communication socket/</tag>
|
<tag><label id="argv-socket">-s <m/name of communication socket/</tag>
|
||||||
use given filename for a socket for communications with the client,
|
use given filename for a socket for communications with the client,
|
||||||
default is <it/prefix/<file>/var/run/bird.ctl</file>.
|
default is <it/prefix/<file>/var/run/bird.ctl</file>. See also
|
||||||
|
<ref id="opt-commands" name="commands config option">.
|
||||||
|
|
||||||
<tag><label id="argv-user">-u <m/user/</tag>
|
<tag><label id="argv-user">-u <m/user/</tag>
|
||||||
drop privileges and use that user ID, see the next section for details.
|
drop privileges and use that user ID, see the next section for details.
|
||||||
@ -471,6 +472,11 @@ ipv6 table
|
|||||||
include "tablename.conf";;
|
include "tablename.conf";;
|
||||||
</code>
|
</code>
|
||||||
|
|
||||||
|
<tag><label id="opt-commands">commands [ restrict ] "<m/filename/" | <m/ip/ port <m/port/;</tag>
|
||||||
|
Open an additional UNIX or TCP control socket for client communication.
|
||||||
|
When <cf>restrict</cf> is specified, the socket is restricted as if <tt/-r/
|
||||||
|
was always given to <tt/birdc/.
|
||||||
|
|
||||||
<tag><label id="opt-log">log "<m/filename/" [<m/limit/ "<m/backup/"] | syslog [name <m/name/] | stderr all|{ <m/list of classes/ }</tag>
|
<tag><label id="opt-log">log "<m/filename/" [<m/limit/ "<m/backup/"] | syslog [name <m/name/] | stderr all|{ <m/list of classes/ }</tag>
|
||||||
Set logging of messages having the given class (either <cf/all/ or <cf>{
|
Set logging of messages having the given class (either <cf/all/ or <cf>{
|
||||||
error|trace [, <m/.../] }</cf> etc.) into selected destination - a file
|
error|trace [, <m/.../] }</cf> etc.) into selected destination - a file
|
||||||
|
49
sysdep/unix/conf.h
Normal file
49
sysdep/unix/conf.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* BIRD -- Unix Port Config Structures
|
||||||
|
*
|
||||||
|
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
|
||||||
|
* (c) 2023 Maria Matejka <mq@jmq.cz>
|
||||||
|
*
|
||||||
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BIRD_UNIX_CONFIG_H_
|
||||||
|
#define _BIRD_UNIX_CONFIG_H_
|
||||||
|
|
||||||
|
#include "lib/tlists.h"
|
||||||
|
|
||||||
|
#define TLIST_PREFIX control_socket_config
|
||||||
|
#define TLIST_TYPE struct control_socket_config
|
||||||
|
#define TLIST_ITEM n
|
||||||
|
#define TLIST_WANT_WALK
|
||||||
|
#define TLIST_WANT_ADD_TAIL
|
||||||
|
|
||||||
|
struct control_socket_config {
|
||||||
|
TLIST_DEFAULT_NODE;
|
||||||
|
struct config *config;
|
||||||
|
struct control_socket *cs;
|
||||||
|
|
||||||
|
ip_addr addr;
|
||||||
|
uint port;
|
||||||
|
|
||||||
|
const char *unix;
|
||||||
|
uid_t uid;
|
||||||
|
gid_t gid;
|
||||||
|
u8 restricted;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "lib/tlists.h"
|
||||||
|
|
||||||
|
struct log_config {
|
||||||
|
node n;
|
||||||
|
uint mask; /* Classes to log */
|
||||||
|
void *fh; /* FILE to log to, NULL=syslog */
|
||||||
|
struct rfile *rf; /* Resource for log file */
|
||||||
|
const char *filename; /* Log filename */
|
||||||
|
const char *backup; /* Secondary filename (for log rotation) */
|
||||||
|
off_t pos; /* Position/size of current log */
|
||||||
|
off_t limit; /* Log size limit */
|
||||||
|
int terminal_flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -25,6 +25,7 @@ CF_KEYWORDS(GRACEFUL, RESTART)
|
|||||||
%type <t> cfg_name
|
%type <t> cfg_name
|
||||||
%type <tf> timeformat_which
|
%type <tf> timeformat_which
|
||||||
%type <t> syslog_name
|
%type <t> syslog_name
|
||||||
|
%type <control_socket_config> control_socket_listen
|
||||||
|
|
||||||
CF_GRAMMAR
|
CF_GRAMMAR
|
||||||
|
|
||||||
@ -101,6 +102,32 @@ mrtdump_base:
|
|||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
conf: control_socket ';' ;
|
||||||
|
|
||||||
|
control_socket:
|
||||||
|
COMMANDS control_socket_listen {
|
||||||
|
control_socket_config_add_tail(&new_config->control_socket, $2);
|
||||||
|
}
|
||||||
|
| COMMANDS RESTRICT control_socket_listen {
|
||||||
|
$3->restricted = 1;
|
||||||
|
control_socket_config_add_tail(&new_config->control_socket, $3);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
control_socket_listen:
|
||||||
|
ipa PORT expr {
|
||||||
|
$$ = cfg_allocz(sizeof(struct control_socket_config));
|
||||||
|
$$->config = new_config;
|
||||||
|
$$->addr = $1;
|
||||||
|
$$->port = $3;
|
||||||
|
}
|
||||||
|
| text {
|
||||||
|
$$ = cfg_allocz(sizeof(struct control_socket_config));
|
||||||
|
$$->config = new_config;
|
||||||
|
$$->unix = $1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
conf: debug_unix ;
|
conf: debug_unix ;
|
||||||
|
|
||||||
debug_unix:
|
debug_unix:
|
||||||
|
@ -1498,7 +1498,7 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sk_open_unix(sock *s, char *name)
|
sk_open_unix(sock *s, const char *name)
|
||||||
{
|
{
|
||||||
struct sockaddr_un sa;
|
struct sockaddr_un sa;
|
||||||
int fd;
|
int fd;
|
||||||
@ -2401,7 +2401,7 @@ io_loop(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_old_bird(char *path)
|
test_old_bird(const char *path)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
struct sockaddr_un sa;
|
struct sockaddr_un sa;
|
||||||
|
@ -198,10 +198,22 @@ sysdep_preconfig(struct config *c)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int control_socket_open(struct control_socket_config *csc);
|
||||||
|
static void control_socket_close(struct control_socket_config *csc);
|
||||||
|
|
||||||
int
|
int
|
||||||
sysdep_commit(struct config *new, struct config *old UNUSED)
|
sysdep_commit(struct config *new, struct config *old)
|
||||||
{
|
{
|
||||||
log_switch(0, &new->logfiles, new->syslog_name);
|
log_switch(0, &new->logfiles, new->syslog_name);
|
||||||
|
|
||||||
|
WALK_TLIST(control_socket_config, csc, &new->control_socket)
|
||||||
|
control_socket_open(csc);
|
||||||
|
|
||||||
|
if (old)
|
||||||
|
WALK_TLIST(control_socket_config, csc, &old->control_socket)
|
||||||
|
if (csc->cs)
|
||||||
|
control_socket_close(csc);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,9 +406,24 @@ cmd_reconfig_status(void)
|
|||||||
* Command-Line Interface
|
* Command-Line Interface
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static sock *cli_sk;
|
#define TLIST_PREFIX control_socket
|
||||||
static char *path_control_socket = PATH_CONTROL_SOCKET;
|
#define TLIST_TYPE struct control_socket
|
||||||
|
#define TLIST_ITEM n
|
||||||
|
#define TLIST_WANT_WALK
|
||||||
|
#define TLIST_WANT_ADD_TAIL
|
||||||
|
|
||||||
|
struct control_socket {
|
||||||
|
TLIST_DEFAULT_NODE;
|
||||||
|
struct control_socket_config *cf;
|
||||||
|
sock *s;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "lib/tlists.h"
|
||||||
|
|
||||||
|
static TLIST_LIST(control_socket) control_sockets;
|
||||||
|
static struct control_socket_config args_control_socket = {
|
||||||
|
.unix = PATH_CONTROL_SOCKET,
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cli_write(cli *c)
|
cli_write(cli *c)
|
||||||
@ -503,6 +530,8 @@ cli_connect_err(sock *s UNUSED, int err)
|
|||||||
static int
|
static int
|
||||||
cli_connect(sock *s, uint size UNUSED)
|
cli_connect(sock *s, uint size UNUSED)
|
||||||
{
|
{
|
||||||
|
struct control_socket_config *csc = s->data;
|
||||||
|
|
||||||
cli *c;
|
cli *c;
|
||||||
|
|
||||||
if (config->cli_debug)
|
if (config->cli_debug)
|
||||||
@ -514,37 +543,136 @@ cli_connect(sock *s, uint size UNUSED)
|
|||||||
s->pool = c->pool; /* We need to have all the socket buffers allocated in the cli pool */
|
s->pool = c->pool; /* We need to have all the socket buffers allocated in the cli pool */
|
||||||
s->fast_rx = 1;
|
s->fast_rx = 1;
|
||||||
c->rx_pos = c->rx_buf;
|
c->rx_pos = c->rx_buf;
|
||||||
|
c->restricted = csc->restricted;
|
||||||
rmove(s, c->pool);
|
rmove(s, c->pool);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
control_socket_open(struct control_socket_config *csc)
|
||||||
|
{
|
||||||
|
/* Find existing socket */
|
||||||
|
WALK_TLIST(control_socket, cs, &control_sockets)
|
||||||
|
{
|
||||||
|
if (ipa_equal(cs->cf->addr, csc->addr) &&
|
||||||
|
(cs->cf->port == csc->port) &&
|
||||||
|
(!cs->cf->unix && !csc->unix || !strcmp(cs->cf->unix, csc->unix)))
|
||||||
|
{
|
||||||
|
if (!cs->cf->config)
|
||||||
|
{
|
||||||
|
log(L_ERR "Can't configure the same control socket in config and args: %s", cs->cf->unix);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cs->cf->config == csc->config)
|
||||||
|
{
|
||||||
|
if (csc->unix)
|
||||||
|
log(L_ERR "Duplicate control socket config: %s", csc->unix);
|
||||||
|
else
|
||||||
|
log(L_ERR "Duplicate control socket config: %I port %d", csc->addr, csc->port);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cs->cf->cs = NULL;
|
||||||
|
cs->cf = csc;
|
||||||
|
csc->cs = cs;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct control_socket *cs = mb_allocz(cli_pool, sizeof(struct control_socket));
|
||||||
|
cs->s = sk_new(cli_pool);
|
||||||
|
cs->s->data = csc;
|
||||||
|
|
||||||
|
cs->s->rx_hook = cli_connect;
|
||||||
|
cs->s->err_hook = cli_connect_err;
|
||||||
|
cs->s->rbsize = 1024;
|
||||||
|
cs->s->fast_rx = 1;
|
||||||
|
|
||||||
|
if (csc->unix)
|
||||||
|
{
|
||||||
|
cs->s->type = SK_UNIX_PASSIVE;
|
||||||
|
int ok = 0;
|
||||||
|
do {
|
||||||
|
/* Just a cleanup, no need to check the return value */
|
||||||
|
unlink(csc->unix);
|
||||||
|
|
||||||
|
if (sk_open_unix(cs->s, csc->unix) < 0)
|
||||||
|
{
|
||||||
|
log(L_ERR "Cannot create control socket %s: %m", csc->unix);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (csc->uid || csc->gid)
|
||||||
|
if (chown(csc->unix, csc->uid, csc->gid) < 0)
|
||||||
|
{
|
||||||
|
log(L_ERR "Cannot chown control socket %s: %m", csc->unix);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chmod(csc->unix, 0660) < 0)
|
||||||
|
{
|
||||||
|
log(L_ERR "Cannot chmod control socket %s: %m", csc->unix);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok = 1;
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
rfree(cs->s);
|
||||||
|
mb_free(cs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cs->s->type = SK_TCP_PASSIVE;
|
||||||
|
cs->s->saddr = csc->addr;
|
||||||
|
cs->s->sport = csc->port;
|
||||||
|
|
||||||
|
if (sk_open(cs->s) < 0)
|
||||||
|
{
|
||||||
|
log(L_ERR "Cannot open control socket at %I port %d", csc->addr, csc->port);
|
||||||
|
rfree(cs->s);
|
||||||
|
mb_free(cs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cs->cf = csc;
|
||||||
|
csc->cs = cs;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
control_socket_close(struct control_socket_config *csc)
|
||||||
|
{
|
||||||
|
ASSERT_DIE(csc->cs);
|
||||||
|
if (!csc->cs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (csc->unix)
|
||||||
|
unlink(csc->unix);
|
||||||
|
|
||||||
|
rfree(csc->cs->s);
|
||||||
|
mb_free(csc->cs);
|
||||||
|
csc->cs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cli_init_unix(uid_t use_uid, gid_t use_gid)
|
cli_init_unix(uid_t use_uid, gid_t use_gid)
|
||||||
{
|
{
|
||||||
sock *s;
|
|
||||||
|
|
||||||
cli_init();
|
cli_init();
|
||||||
s = cli_sk = sk_new(cli_pool);
|
args_control_socket.uid = use_uid;
|
||||||
s->type = SK_UNIX_PASSIVE;
|
args_control_socket.gid = use_gid;
|
||||||
s->rx_hook = cli_connect;
|
|
||||||
s->err_hook = cli_connect_err;
|
|
||||||
s->rbsize = 1024;
|
|
||||||
s->fast_rx = 1;
|
|
||||||
|
|
||||||
/* Return value intentionally ignored */
|
if (!control_socket_open(&args_control_socket))
|
||||||
unlink(path_control_socket);
|
die("Failed to create control socket: %s", args_control_socket.unix);
|
||||||
|
|
||||||
if (sk_open_unix(s, path_control_socket) < 0)
|
|
||||||
die("Cannot create control socket %s: %m", path_control_socket);
|
|
||||||
|
|
||||||
if (use_uid || use_gid)
|
|
||||||
if (chown(path_control_socket, use_uid, use_gid) < 0)
|
|
||||||
die("chown: %m");
|
|
||||||
|
|
||||||
if (chmod(path_control_socket, 0660) < 0)
|
|
||||||
die("chmod: %m");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PID file
|
* PID file
|
||||||
*/
|
*/
|
||||||
@ -622,7 +750,7 @@ void
|
|||||||
sysdep_shutdown_done(void)
|
sysdep_shutdown_done(void)
|
||||||
{
|
{
|
||||||
unlink_pid_file();
|
unlink_pid_file();
|
||||||
unlink(path_control_socket);
|
control_socket_close(&args_control_socket);
|
||||||
log_msg(L_FATAL "Shutdown completed");
|
log_msg(L_FATAL "Shutdown completed");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
@ -834,7 +962,7 @@ parse_args(int argc, char **argv)
|
|||||||
parse_and_exit = 1;
|
parse_and_exit = 1;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
path_control_socket = optarg;
|
args_control_socket.unix = optarg;
|
||||||
socket_changed = 1;
|
socket_changed = 1;
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
@ -853,7 +981,7 @@ parse_args(int argc, char **argv)
|
|||||||
if (!config_changed)
|
if (!config_changed)
|
||||||
config_name = xbasename(config_name);
|
config_name = xbasename(config_name);
|
||||||
if (!socket_changed)
|
if (!socket_changed)
|
||||||
path_control_socket = xbasename(path_control_socket);
|
args_control_socket.unix = xbasename(args_control_socket.unix);
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'R':
|
||||||
graceful_restart_recovery();
|
graceful_restart_recovery();
|
||||||
@ -903,7 +1031,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
if (!parse_and_exit)
|
if (!parse_and_exit)
|
||||||
{
|
{
|
||||||
test_old_bird(path_control_socket);
|
test_old_bird(args_control_socket.unix);
|
||||||
cli_init_unix(use_uid, use_gid);
|
cli_init_unix(use_uid, use_gid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,11 +107,11 @@ extern volatile sig_atomic_t async_shutdown_flag;
|
|||||||
void io_init(void);
|
void io_init(void);
|
||||||
void io_loop(void);
|
void io_loop(void);
|
||||||
void io_log_dump(void);
|
void io_log_dump(void);
|
||||||
int sk_open_unix(struct birdsock *s, char *name);
|
int sk_open_unix(struct birdsock *s, const char *name);
|
||||||
struct rfile *rf_open(struct pool *, const char *name, const char *mode);
|
struct rfile *rf_open(struct pool *, const char *name, const char *mode);
|
||||||
void *rf_file(struct rfile *f);
|
void *rf_file(struct rfile *f);
|
||||||
int rf_fileno(struct rfile *f);
|
int rf_fileno(struct rfile *f);
|
||||||
void test_old_bird(char *path);
|
void test_old_bird(const char *path);
|
||||||
|
|
||||||
/* krt.c bits */
|
/* krt.c bits */
|
||||||
|
|
||||||
@ -123,16 +123,4 @@ void main_thread_init(void);
|
|||||||
void log_init_debug(char *); /* Initialize debug dump to given file (NULL=stderr, ""=off) */
|
void log_init_debug(char *); /* Initialize debug dump to given file (NULL=stderr, ""=off) */
|
||||||
void log_switch(int initial, list *l, const char *);
|
void log_switch(int initial, list *l, const char *);
|
||||||
|
|
||||||
struct log_config {
|
|
||||||
node n;
|
|
||||||
uint mask; /* Classes to log */
|
|
||||||
void *fh; /* FILE to log to, NULL=syslog */
|
|
||||||
struct rfile *rf; /* Resource for log file */
|
|
||||||
const char *filename; /* Log filename */
|
|
||||||
const char *backup; /* Secondary filename (for log rotation) */
|
|
||||||
off_t pos; /* Position/size of current log */
|
|
||||||
off_t limit; /* Log size limit */
|
|
||||||
int terminal_flag;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user