1919 * Website: https://github.com/rtrlib/bird-rtrlib-cli
2020 */
2121
22+ #include <errno.h>
23+ #include <signal.h>
2224#include <stddef.h>
2325#include <stdio.h>
2426#include <stdlib.h>
3032#include "cli.h"
3133#include "config.h"
3234#include "rtr.h"
35+ #include <rtrlib/rtrlib.h>
3336
3437#define CMD_EXIT "exit"
35-
38+ #define BIRD_RSP_SIZE (200)
3639// Socket to BIRD.
3740static int bird_socket = -1 ;
38-
3941// Buffer for BIRD commands.
4042static char * bird_command = 0 ;
41-
4243// Length of buffer for BIRD commands.
4344static size_t bird_command_length = -1 ;
44-
4545// "add roa" BIRD command "table" part. Defaults to an empty string and becomes
4646// "table " + config->bird_roa_table if provided.
4747static char * bird_add_roa_table_arg = "" ;
48+ // Main configuration.
49+ static struct config config ;
50+
51+ /**
52+ * Handle SIGPIPE on bird_socket, write error log entry
53+ */
54+ void sigpipe_handler (int signum )
55+ {
56+ syslog (LOG_ERR , "Caught SIGPIPE %d." , signum );
57+ }
4858
4959/**
5060 * Performs cleanup on resources allocated by `init()`.
5161 */
52- void cleanup (void ) {
62+ void cleanup (void )
63+ {
5364 closelog ();
5465}
5566
5667/**
5768 * Frees memory allocated with the " table <bird_roa_table>" clause for the
5869 * "add roa" BIRD command.
5970 */
60- void cleanup_bird_add_roa_table_arg (void ) {
61- // If the buffer is "", it has never been changed, thus there is no malloc'd
62- // buffer.
71+ void cleanup_bird_add_roa_table_arg (void )
72+ {
73+ // free buffer only, if not empty - i.e., mem was malloc'd
6374 if (strcmp (bird_add_roa_table_arg , "" ) != 0 )
6475 free (bird_add_roa_table_arg );
6576}
6677
6778/**
6879 * Frees memory allocated with the BIRD command buffer.
6980 */
70- void cleanup_bird_command (void ) {
81+ void cleanup_bird_command (void )
82+ {
7183 if (bird_command ) {
7284 free (bird_command );
7385 bird_command = 0 ;
@@ -78,29 +90,30 @@ void cleanup_bird_command(void) {
7890/**
7991 * Initializes the application prerequisites.
8092 */
81- void init (void ) {
93+ void init (void )
94+ {
8295 openlog (NULL , LOG_PERROR | LOG_CONS | LOG_PID , LOG_DAEMON );
8396}
8497
8598/**
8699 * Creates and populates the "add roa" command's "table" argument buffer.
87100 * @param bird_roa_table
88101 */
89- void init_bird_add_roa_table_arg (char * bird_roa_table ) {
102+ void init_bird_add_roa_table_arg (char * bird_roa_table )
103+ {
90104 // Size of the buffer (" table " + <roa_table> + \0).
91105 const size_t length = (8 + strlen (bird_roa_table )) * sizeof (char );
92-
93106 // Allocate buffer.
94107 bird_add_roa_table_arg = malloc (length );
95-
96108 // Populate buffer.
97109 snprintf (bird_add_roa_table_arg , length , " table %s" , bird_roa_table );
98110}
99111
100112/**
101113 * Creates the buffer for the "add roa" command.
102114 */
103- void init_bird_command (void ) {
115+ void init_bird_command (void )
116+ {
104117 // Size of the buffer ("add roa " + <addr> + "/" + <minlen> + " max " +
105118 // <maxlen> + " as " + <asnum> + <bird_add_roa_table_cmd> + \0)
106119 bird_command_length = (
@@ -115,7 +128,6 @@ void init_bird_command(void) {
115128 strlen (bird_add_roa_table_arg ) + // length of fixed " table " + <table>
116129 1 // \0
117130 ) * sizeof (char );
118-
119131 // Allocate buffer.
120132 bird_command = malloc (bird_command_length );
121133}
@@ -134,13 +146,10 @@ static void pfx_update_callback(struct pfx_table *table,
134146{
135147 // IP address buffer.
136148 static char ip_addr_str [INET6_ADDRSTRLEN ];
137-
138149 // Buffer for BIRD response.
139- static char bird_response [200 ];
140-
150+ static char bird_response [BIRD_RSP_SIZE ];
141151 // Fetch IP address as string.
142152 lrtr_ip_addr_to_str (& (record .prefix ), ip_addr_str , sizeof (ip_addr_str ));
143-
144153 // Write BIRD command to buffer.
145154 if (
146155 snprintf (
@@ -159,14 +168,28 @@ static void pfx_update_callback(struct pfx_table *table,
159168 syslog (LOG_ERR , "BIRD command too long." );
160169 return ;
161170 }
162-
163171 // Log the BIRD command and send it to the BIRD server.
164172 syslog (LOG_INFO , "To BIRD: %s" , bird_command );
165- write (bird_socket , bird_command , strlen (bird_command ));
166-
167- // Fetch the answer and log.
168- bird_response [read (bird_socket , bird_response , sizeof (bird_response )- 1 )] = 0 ;
169- syslog (LOG_INFO , "From BIRD: %s" , bird_response );
173+ // reconnect bird_socket on SIGPIPE error, and resend BIRD command
174+ while ((write (bird_socket , bird_command , strlen (bird_command )) < 0 ) &&
175+ (errno == EPIPE )) {
176+ syslog (LOG_ERR , "BIRD socket send failed, try reconnect!" );
177+ close (bird_socket );
178+ bird_socket = bird_connect (config .bird_socket_path );
179+ }
180+ // Fetch BIRD answer, reconnect bird_socket on SIGPIPE while receive
181+ int size = -1 ;
182+ while (((size = read (bird_socket , bird_response , BIRD_RSP_SIZE - 1 )) < 0 ) &&
183+ (errno == EPIPE )){
184+ syslog (LOG_ERR , "BIRD socket recv failed, try reconnect!" );
185+ close (bird_socket );
186+ bird_socket = bird_connect (config .bird_socket_path );
187+ }
188+ // log answer, if any valid response
189+ if (size > 0 ) {
190+ bird_response [size ] = 0 ;
191+ syslog (LOG_INFO , "From BIRD: %s" , bird_response );
192+ }
170193}
171194
172195/**
@@ -175,53 +198,45 @@ static void pfx_update_callback(struct pfx_table *table,
175198 * @param argv
176199 * @return
177200 */
178- int main (int argc , char * argv []) {
179- // Main configuration.
180- struct config config ;
181-
201+ int main (int argc , char * argv [])
202+ {
182203 // Buffer for commands and its length.
183204 char * command = 0 ;
184205 size_t command_len = 0 ;
185-
186206 // Initialize variables.
187207 config_init (& config );
188-
189208 // Initialize framework.
190209 init ();
191-
192210 // Parse CLI arguments into config and bail out on error.
193211 if (!parse_cli (argc , argv , & config )) {
194212 cleanup ();
213+ fprintf (stderr , "Invalid command line parameter!\n" );
195214 return EXIT_FAILURE ;
196215 }
197-
198216 // Check config.
199- if (! config_check (& config )) {
217+ if (config_check (& config )) {
200218 cleanup ();
219+ fprintf (stderr , "Invalid configuration parameters!\n" );
201220 return EXIT_FAILURE ;
202221 }
203-
204222 // Setup BIRD ROA table command argument.
205223 if (config .bird_roa_table ) {
206224 init_bird_add_roa_table_arg (config .bird_roa_table );
207225 }
208-
209226 // Setup BIRD command buffer.
210227 init_bird_command ();
211-
212228 // Try to connect to BIRD and bail out on failure.
213229 bird_socket = bird_connect (config .bird_socket_path );
214230 if (bird_socket == -1 ) {
215231 cleanup ();
232+ fprintf (stderr , "Failed to connect to BIRD socket!\n" );
216233 return EXIT_FAILURE ;
217234 }
218235
219236 struct tr_socket tr_sock ;
220237 struct tr_tcp_config * tcp_config ;
221238 struct tr_ssh_config * ssh_config ;
222-
223- // Try to connect to the RTR server depending on the requested connection
224- // type.
239+ // Try to connect to the RTR server depending on requested connection type.
225240 switch (config .rtr_connection_type ) {
226241 case tcp :
227242 tcp_config = rtr_create_tcp_config (
@@ -237,53 +252,56 @@ int main(int argc, char *argv[]) {
237252 break ;
238253 default :
239254 cleanup ();
255+ fprintf (stderr , "Invalid connection type, use tcp or ssh!\n" );
240256 return EXIT_FAILURE ;
241257 }
242258
243259 struct rtr_socket rtr ;
244260 struct rtr_mgr_config * conf ;
245261 struct rtr_mgr_group groups [1 ];
246-
262+ // init rtr_socket and groups
247263 rtr .tr_socket = & tr_sock ;
248264 groups [0 ].sockets_len = 1 ;
249265 groups [0 ].sockets = malloc (1 * sizeof (rtr ));
250266 groups [0 ].sockets [0 ] = & rtr ;
251267 groups [0 ].preference = 1 ;
252-
268+ // init rtr_mgr
253269 int ret = rtr_mgr_init (& conf , groups , 1 , 30 , 600 , 600 ,
254270 pfx_update_callback , NULL , NULL , NULL );
255-
256- if (ret == RTR_ERROR )
257- printf ("Error in rtr_mgr_init!\n" );
258- else if (ret == RTR_INVALID_PARAM )
259- printf ("Invalid params passed to rtr_mgr_init\n" );
260-
261- if (!conf )
271+ // check for init errors
272+ if (ret == RTR_ERROR ) {
273+ fprintf (stderr , "Error in rtr_mgr_init!\n" );
262274 return EXIT_FAILURE ;
263-
275+ }
276+ else if (ret == RTR_INVALID_PARAM ) {
277+ fprintf (stderr , "Invalid params passed to rtr_mgr_init\n" );
278+ return EXIT_FAILURE ;
279+ }
280+ // check if rtr_mgr config valid
281+ if (!conf ) {
282+ fprintf (stderr , "No config for rtr manager!\n" );
283+ return EXIT_FAILURE ;
284+ }
285+ // set handler for SIGPIPE
286+ signal (SIGPIPE , sigpipe_handler );
287+ // start rtr_mgr
264288 rtr_mgr_start (conf );
265-
266289 // Server loop. Read commands from stdin.
267290 while (getline (& command , & command_len , stdin ) != -1 ) {
268291 if (strncmp (command , CMD_EXIT , strlen (CMD_EXIT )) == 0 )
269292 break ;
270293 }
271-
272294 // Clean up RTRLIB memory.
273295 rtr_mgr_stop (conf );
274296 rtr_mgr_free (conf );
275297 free (groups [0 ].sockets );
276-
277298 // Close BIRD socket.
278299 close (bird_socket );
279-
280300 // Cleanup memory.
281301 cleanup_bird_command ();
282302 cleanup_bird_add_roa_table_arg ();
283-
284303 // Cleanup framework.
285304 cleanup ();
286-
287305 // Exit with success.
288306 return EXIT_SUCCESS ;
289307}
0 commit comments