19
19
* Website: https://github.com/rtrlib/bird-rtrlib-cli
20
20
*/
21
21
22
+ #include <errno.h>
23
+ #include <signal.h>
22
24
#include <stddef.h>
23
25
#include <stdio.h>
24
26
#include <stdlib.h>
30
32
#include "cli.h"
31
33
#include "config.h"
32
34
#include "rtr.h"
35
+ #include <rtrlib/rtrlib.h>
33
36
34
37
#define CMD_EXIT "exit"
35
-
38
+ #define BIRD_RSP_SIZE (200)
36
39
// Socket to BIRD.
37
40
static int bird_socket = -1 ;
38
-
39
41
// Buffer for BIRD commands.
40
42
static char * bird_command = 0 ;
41
-
42
43
// Length of buffer for BIRD commands.
43
44
static size_t bird_command_length = -1 ;
44
-
45
45
// "add roa" BIRD command "table" part. Defaults to an empty string and becomes
46
46
// "table " + config->bird_roa_table if provided.
47
47
static 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
+ }
48
58
49
59
/**
50
60
* Performs cleanup on resources allocated by `init()`.
51
61
*/
52
- void cleanup (void ) {
62
+ void cleanup (void )
63
+ {
53
64
closelog ();
54
65
}
55
66
56
67
/**
57
68
* Frees memory allocated with the " table <bird_roa_table>" clause for the
58
69
* "add roa" BIRD command.
59
70
*/
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
63
74
if (strcmp (bird_add_roa_table_arg , "" ) != 0 )
64
75
free (bird_add_roa_table_arg );
65
76
}
66
77
67
78
/**
68
79
* Frees memory allocated with the BIRD command buffer.
69
80
*/
70
- void cleanup_bird_command (void ) {
81
+ void cleanup_bird_command (void )
82
+ {
71
83
if (bird_command ) {
72
84
free (bird_command );
73
85
bird_command = 0 ;
@@ -78,29 +90,30 @@ void cleanup_bird_command(void) {
78
90
/**
79
91
* Initializes the application prerequisites.
80
92
*/
81
- void init (void ) {
93
+ void init (void )
94
+ {
82
95
openlog (NULL , LOG_PERROR | LOG_CONS | LOG_PID , LOG_DAEMON );
83
96
}
84
97
85
98
/**
86
99
* Creates and populates the "add roa" command's "table" argument buffer.
87
100
* @param bird_roa_table
88
101
*/
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
+ {
90
104
// Size of the buffer (" table " + <roa_table> + \0).
91
105
const size_t length = (8 + strlen (bird_roa_table )) * sizeof (char );
92
-
93
106
// Allocate buffer.
94
107
bird_add_roa_table_arg = malloc (length );
95
-
96
108
// Populate buffer.
97
109
snprintf (bird_add_roa_table_arg , length , " table %s" , bird_roa_table );
98
110
}
99
111
100
112
/**
101
113
* Creates the buffer for the "add roa" command.
102
114
*/
103
- void init_bird_command (void ) {
115
+ void init_bird_command (void )
116
+ {
104
117
// Size of the buffer ("add roa " + <addr> + "/" + <minlen> + " max " +
105
118
// <maxlen> + " as " + <asnum> + <bird_add_roa_table_cmd> + \0)
106
119
bird_command_length = (
@@ -115,7 +128,6 @@ void init_bird_command(void) {
115
128
strlen (bird_add_roa_table_arg ) + // length of fixed " table " + <table>
116
129
1 // \0
117
130
) * sizeof (char );
118
-
119
131
// Allocate buffer.
120
132
bird_command = malloc (bird_command_length );
121
133
}
@@ -134,13 +146,10 @@ static void pfx_update_callback(struct pfx_table *table,
134
146
{
135
147
// IP address buffer.
136
148
static char ip_addr_str [INET6_ADDRSTRLEN ];
137
-
138
149
// Buffer for BIRD response.
139
- static char bird_response [200 ];
140
-
150
+ static char bird_response [BIRD_RSP_SIZE ];
141
151
// Fetch IP address as string.
142
152
lrtr_ip_addr_to_str (& (record .prefix ), ip_addr_str , sizeof (ip_addr_str ));
143
-
144
153
// Write BIRD command to buffer.
145
154
if (
146
155
snprintf (
@@ -159,14 +168,28 @@ static void pfx_update_callback(struct pfx_table *table,
159
168
syslog (LOG_ERR , "BIRD command too long." );
160
169
return ;
161
170
}
162
-
163
171
// Log the BIRD command and send it to the BIRD server.
164
172
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
+ }
170
193
}
171
194
172
195
/**
@@ -175,53 +198,45 @@ static void pfx_update_callback(struct pfx_table *table,
175
198
* @param argv
176
199
* @return
177
200
*/
178
- int main (int argc , char * argv []) {
179
- // Main configuration.
180
- struct config config ;
181
-
201
+ int main (int argc , char * argv [])
202
+ {
182
203
// Buffer for commands and its length.
183
204
char * command = 0 ;
184
205
size_t command_len = 0 ;
185
-
186
206
// Initialize variables.
187
207
config_init (& config );
188
-
189
208
// Initialize framework.
190
209
init ();
191
-
192
210
// Parse CLI arguments into config and bail out on error.
193
211
if (!parse_cli (argc , argv , & config )) {
194
212
cleanup ();
213
+ fprintf (stderr , "Invalid command line parameter!\n" );
195
214
return EXIT_FAILURE ;
196
215
}
197
-
198
216
// Check config.
199
- if (! config_check (& config )) {
217
+ if (config_check (& config )) {
200
218
cleanup ();
219
+ fprintf (stderr , "Invalid configuration parameters!\n" );
201
220
return EXIT_FAILURE ;
202
221
}
203
-
204
222
// Setup BIRD ROA table command argument.
205
223
if (config .bird_roa_table ) {
206
224
init_bird_add_roa_table_arg (config .bird_roa_table );
207
225
}
208
-
209
226
// Setup BIRD command buffer.
210
227
init_bird_command ();
211
-
212
228
// Try to connect to BIRD and bail out on failure.
213
229
bird_socket = bird_connect (config .bird_socket_path );
214
230
if (bird_socket == -1 ) {
215
231
cleanup ();
232
+ fprintf (stderr , "Failed to connect to BIRD socket!\n" );
216
233
return EXIT_FAILURE ;
217
234
}
218
235
219
236
struct tr_socket tr_sock ;
220
237
struct tr_tcp_config * tcp_config ;
221
238
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.
225
240
switch (config .rtr_connection_type ) {
226
241
case tcp :
227
242
tcp_config = rtr_create_tcp_config (
@@ -237,53 +252,56 @@ int main(int argc, char *argv[]) {
237
252
break ;
238
253
default :
239
254
cleanup ();
255
+ fprintf (stderr , "Invalid connection type, use tcp or ssh!\n" );
240
256
return EXIT_FAILURE ;
241
257
}
242
258
243
259
struct rtr_socket rtr ;
244
260
struct rtr_mgr_config * conf ;
245
261
struct rtr_mgr_group groups [1 ];
246
-
262
+ // init rtr_socket and groups
247
263
rtr .tr_socket = & tr_sock ;
248
264
groups [0 ].sockets_len = 1 ;
249
265
groups [0 ].sockets = malloc (1 * sizeof (rtr ));
250
266
groups [0 ].sockets [0 ] = & rtr ;
251
267
groups [0 ].preference = 1 ;
252
-
268
+ // init rtr_mgr
253
269
int ret = rtr_mgr_init (& conf , groups , 1 , 30 , 600 , 600 ,
254
270
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" );
262
274
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
264
288
rtr_mgr_start (conf );
265
-
266
289
// Server loop. Read commands from stdin.
267
290
while (getline (& command , & command_len , stdin ) != -1 ) {
268
291
if (strncmp (command , CMD_EXIT , strlen (CMD_EXIT )) == 0 )
269
292
break ;
270
293
}
271
-
272
294
// Clean up RTRLIB memory.
273
295
rtr_mgr_stop (conf );
274
296
rtr_mgr_free (conf );
275
297
free (groups [0 ].sockets );
276
-
277
298
// Close BIRD socket.
278
299
close (bird_socket );
279
-
280
300
// Cleanup memory.
281
301
cleanup_bird_command ();
282
302
cleanup_bird_add_roa_table_arg ();
283
-
284
303
// Cleanup framework.
285
304
cleanup ();
286
-
287
305
// Exit with success.
288
306
return EXIT_SUCCESS ;
289
307
}
0 commit comments