Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 74 additions & 56 deletions bird-rtrlib-cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
* Website: https://github.com/rtrlib/bird-rtrlib-cli
*/

#include <errno.h>
#include <signal.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
Expand All @@ -30,44 +32,54 @@
#include "cli.h"
#include "config.h"
#include "rtr.h"
#include <rtrlib/rtrlib.h>

#define CMD_EXIT "exit"

#define BIRD_RSP_SIZE (200)
// Socket to BIRD.
static int bird_socket = -1;

// Buffer for BIRD commands.
static char *bird_command = 0;

// Length of buffer for BIRD commands.
static size_t bird_command_length = -1;

// "add roa" BIRD command "table" part. Defaults to an empty string and becomes
// "table " + config->bird_roa_table if provided.
static char *bird_add_roa_table_arg = "";
// Main configuration.
static struct config config;

/**
* Handle SIGPIPE on bird_socket, write error log entry
*/
void sigpipe_handler(int signum)
{
syslog(LOG_ERR, "Caught SIGPIPE %d.", signum);
}

/**
* Performs cleanup on resources allocated by `init()`.
*/
void cleanup(void) {
void cleanup(void)
{
closelog();
}

/**
* Frees memory allocated with the " table <bird_roa_table>" clause for the
* "add roa" BIRD command.
*/
void cleanup_bird_add_roa_table_arg(void) {
// If the buffer is "", it has never been changed, thus there is no malloc'd
// buffer.
void cleanup_bird_add_roa_table_arg(void)
{
// free buffer only, if not empty - i.e., mem was malloc'd
if (strcmp(bird_add_roa_table_arg, "") != 0)
free(bird_add_roa_table_arg);
}

/**
* Frees memory allocated with the BIRD command buffer.
*/
void cleanup_bird_command(void) {
void cleanup_bird_command(void)
{
if (bird_command) {
free(bird_command);
bird_command = 0;
Expand All @@ -78,29 +90,30 @@ void cleanup_bird_command(void) {
/**
* Initializes the application prerequisites.
*/
void init(void) {
void init(void)
{
openlog(NULL, LOG_PERROR | LOG_CONS | LOG_PID, LOG_DAEMON);
}

/**
* Creates and populates the "add roa" command's "table" argument buffer.
* @param bird_roa_table
*/
void init_bird_add_roa_table_arg(char *bird_roa_table) {
void init_bird_add_roa_table_arg(char *bird_roa_table)
{
// Size of the buffer (" table " + <roa_table> + \0).
const size_t length = (8 + strlen(bird_roa_table)) * sizeof (char);

// Allocate buffer.
bird_add_roa_table_arg = malloc(length);

// Populate buffer.
snprintf(bird_add_roa_table_arg, length, " table %s", bird_roa_table);
}

/**
* Creates the buffer for the "add roa" command.
*/
void init_bird_command(void) {
void init_bird_command(void)
{
// Size of the buffer ("add roa " + <addr> + "/" + <minlen> + " max " +
// <maxlen> + " as " + <asnum> + <bird_add_roa_table_cmd> + \0)
bird_command_length = (
Expand All @@ -115,7 +128,6 @@ void init_bird_command(void) {
strlen(bird_add_roa_table_arg) + // length of fixed " table " + <table>
1 // \0
) * sizeof (char);

// Allocate buffer.
bird_command = malloc(bird_command_length);
}
Expand All @@ -134,13 +146,10 @@ static void pfx_update_callback(struct pfx_table *table,
{
// IP address buffer.
static char ip_addr_str[INET6_ADDRSTRLEN];

// Buffer for BIRD response.
static char bird_response[200];

static char bird_response[BIRD_RSP_SIZE];
// Fetch IP address as string.
lrtr_ip_addr_to_str(&(record.prefix), ip_addr_str, sizeof(ip_addr_str));

// Write BIRD command to buffer.
if (
snprintf(
Expand All @@ -159,14 +168,28 @@ static void pfx_update_callback(struct pfx_table *table,
syslog(LOG_ERR, "BIRD command too long.");
return;
}

// Log the BIRD command and send it to the BIRD server.
syslog(LOG_INFO, "To BIRD: %s", bird_command);
write(bird_socket, bird_command, strlen(bird_command));

// Fetch the answer and log.
bird_response[read(bird_socket, bird_response, sizeof(bird_response)-1)] = 0;
syslog(LOG_INFO, "From BIRD: %s", bird_response);
// reconnect bird_socket on SIGPIPE error, and resend BIRD command
while ((write(bird_socket, bird_command, strlen(bird_command)) < 0) &&
(errno == EPIPE)) {
syslog(LOG_ERR, "BIRD socket send failed, try reconnect!");
close(bird_socket);
bird_socket = bird_connect(config.bird_socket_path);
}
// Fetch BIRD answer, reconnect bird_socket on SIGPIPE while receive
int size = -1;
while (((size = read(bird_socket, bird_response, BIRD_RSP_SIZE-1)) <0) &&
(errno == EPIPE)){
syslog(LOG_ERR, "BIRD socket recv failed, try reconnect!");
close(bird_socket);
bird_socket = bird_connect(config.bird_socket_path);
}
// log answer, if any valid response
if (size > 0) {
bird_response[size] = 0;
syslog(LOG_INFO, "From BIRD: %s", bird_response);
}
}

/**
Expand All @@ -175,53 +198,45 @@ static void pfx_update_callback(struct pfx_table *table,
* @param argv
* @return
*/
int main(int argc, char *argv[]) {
// Main configuration.
struct config config;

int main(int argc, char *argv[])
{
// Buffer for commands and its length.
char *command = 0;
size_t command_len = 0;

// Initialize variables.
config_init(&config);

// Initialize framework.
init();

// Parse CLI arguments into config and bail out on error.
if (!parse_cli(argc, argv, &config)) {
cleanup();
fprintf(stderr, "Invalid command line parameter!\n");
return EXIT_FAILURE;
}

// Check config.
if (!config_check(&config)) {
if (config_check(&config)) {
cleanup();
fprintf(stderr, "Invalid configuration parameters!\n");
return EXIT_FAILURE;
}

// Setup BIRD ROA table command argument.
if (config.bird_roa_table) {
init_bird_add_roa_table_arg(config.bird_roa_table);
}

// Setup BIRD command buffer.
init_bird_command();

// Try to connect to BIRD and bail out on failure.
bird_socket = bird_connect(config.bird_socket_path);
if (bird_socket == -1) {
cleanup();
fprintf(stderr, "Failed to connect to BIRD socket!\n");
return EXIT_FAILURE;
}

struct tr_socket tr_sock;
struct tr_tcp_config *tcp_config;
struct tr_ssh_config *ssh_config;

// Try to connect to the RTR server depending on the requested connection
// type.
// Try to connect to the RTR server depending on requested connection type.
switch (config.rtr_connection_type) {
case tcp:
tcp_config = rtr_create_tcp_config(
Expand All @@ -237,53 +252,56 @@ int main(int argc, char *argv[]) {
break;
default:
cleanup();
fprintf(stderr, "Invalid connection type, use tcp or ssh!\n");
return EXIT_FAILURE;
}

struct rtr_socket rtr;
struct rtr_mgr_config *conf;
struct rtr_mgr_group groups[1];

// init rtr_socket and groups
rtr.tr_socket = &tr_sock;
groups[0].sockets_len = 1;
groups[0].sockets = malloc(1 * sizeof(rtr));
groups[0].sockets[0] = &rtr;
groups[0].preference = 1;

// init rtr_mgr
int ret = rtr_mgr_init(&conf, groups, 1, 30, 600, 600,
pfx_update_callback, NULL, NULL, NULL);

if (ret == RTR_ERROR)
printf("Error in rtr_mgr_init!\n");
else if (ret == RTR_INVALID_PARAM)
printf("Invalid params passed to rtr_mgr_init\n");

if (!conf)
// check for init errors
if (ret == RTR_ERROR) {
fprintf(stderr, "Error in rtr_mgr_init!\n");
return EXIT_FAILURE;

}
else if (ret == RTR_INVALID_PARAM) {
fprintf(stderr, "Invalid params passed to rtr_mgr_init\n");
return EXIT_FAILURE;
}
// check if rtr_mgr config valid
if (!conf) {
fprintf(stderr, "No config for rtr manager!\n");
return EXIT_FAILURE;
}
// set handler for SIGPIPE
signal(SIGPIPE, sigpipe_handler);
// start rtr_mgr
rtr_mgr_start(conf);

// Server loop. Read commands from stdin.
while (getline(&command, &command_len, stdin) != -1) {
if (strncmp(command, CMD_EXIT, strlen(CMD_EXIT)) == 0)
break;
}

// Clean up RTRLIB memory.
rtr_mgr_stop(conf);
rtr_mgr_free(conf);
free(groups[0].sockets);

// Close BIRD socket.
close(bird_socket);

// Cleanup memory.
cleanup_bird_command();
cleanup_bird_add_roa_table_arg();

// Cleanup framework.
cleanup();

// Exit with success.
return EXIT_SUCCESS;
}
9 changes: 2 additions & 7 deletions bird.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,38 +27,33 @@

#include "bird.h"

int bird_connect(const char *socket_path) {
int bird_connect(const char *socket_path)
{
// Result value containing the socket to the BIRD.
int bird_socket = -1;

// Socket address to the BIRD.
struct sockaddr_un addr;

// Check socket path length.
if (strlen(socket_path) >= sizeof addr.sun_path) {
syslog(LOG_EMERG, "Socket path too long");
return -1;
}

// Create socket and bail out on error.
bird_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (bird_socket < 0) {
syslog(LOG_EMERG, "Socket creation error: %m");
return -1;
}

// Create socket address.
memset(&addr, 0, sizeof addr);
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, socket_path);

// Try to connect to BIRD.
if (connect(bird_socket, (struct sockaddr *) &addr, sizeof addr) == -1) {
syslog(LOG_EMERG, "BIRD connection to %s failed: %m", socket_path);
close(bird_socket);
return -1;
}

// Return socket.
return bird_socket;
}
11 changes: 4 additions & 7 deletions cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@
#define ARGKEY_RTRSSH_USERNAME 0x103

// Parser function for argp_parse().
static error_t argp_parser(int key, char *arg, struct argp_state *state) {
static error_t argp_parser(int key, char *arg, struct argp_state *state)
{
// Shortcut to config object passed to argp_parse().
struct config *config = state->input;

// Process command line argument.
switch (key) {
case ARGKEY_BIRD_ROA_TABLE:
Expand Down Expand Up @@ -71,13 +71,13 @@ static error_t argp_parser(int key, char *arg, struct argp_state *state) {
// Process unknown argument.
return ARGP_ERR_UNKNOWN;
}

// Return success.
return 0;
}

// Parses the specified command line arguments into the program config.
int parse_cli(int argc, char **argv, struct config *config) {
int parse_cli(int argc, char **argv, struct config *config)
{
// Command line options definition.
const struct argp_option argp_options[] = {
{
Expand Down Expand Up @@ -150,7 +150,6 @@ int parse_cli(int argc, char **argv, struct config *config) {
},
{0}
};

// argp structure to be passed to argp_parse().
const struct argp argp = {
argp_options,
Expand All @@ -161,10 +160,8 @@ int parse_cli(int argc, char **argv, struct config *config) {
NULL,
NULL
};

// Parse command line. Exits on errors.
argp_parse(&argp, argc, argv, 0, NULL, config);

// Return success.
return 1;
}
Loading