blob: 822805ce736d2da33f5d6bc1f3f066292a68e1b4 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* Main routine of bgpd.
2 Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "vector.h"
24#include "vty.h"
25#include "command.h"
26#include "getopt.h"
27#include "thread.h"
gdt5e4fa162004-03-16 14:38:36 +000028#include <lib/version.h>
paul718e3742002-12-13 20:15:29 +000029#include "memory.h"
30#include "prefix.h"
31#include "log.h"
pauledd7c242003-06-04 13:59:38 +000032#include "privs.h"
paul2d75d052004-01-19 21:31:15 +000033#include "sigevent.h"
Chris Caputo228da422009-07-18 05:44:03 +000034#include "zclient.h"
35#include "routemap.h"
36#include "filter.h"
37#include "plist.h"
paul718e3742002-12-13 20:15:29 +000038
39#include "bgpd/bgpd.h"
40#include "bgpd/bgp_attr.h"
41#include "bgpd/bgp_mplsvpn.h"
Chris Caputo228da422009-07-18 05:44:03 +000042#include "bgpd/bgp_aspath.h"
43#include "bgpd/bgp_dump.h"
44#include "bgpd/bgp_route.h"
45#include "bgpd/bgp_nexthop.h"
46#include "bgpd/bgp_regex.h"
47#include "bgpd/bgp_clist.h"
48#include "bgpd/bgp_debug.h"
49#include "bgpd/bgp_filter.h"
paul718e3742002-12-13 20:15:29 +000050
51/* bgpd options, we use GNU getopt library. */
Stephen Hemminger372b3c72009-05-15 10:29:41 -070052static const struct option longopts[] =
paul718e3742002-12-13 20:15:29 +000053{
54 { "daemon", no_argument, NULL, 'd'},
55 { "config_file", required_argument, NULL, 'f'},
56 { "pid_file", required_argument, NULL, 'i'},
57 { "bgp_port", required_argument, NULL, 'p'},
Paul Jakma3a02d1f2007-11-01 14:29:11 +000058 { "listenon", required_argument, NULL, 'l'},
paul718e3742002-12-13 20:15:29 +000059 { "vty_addr", required_argument, NULL, 'A'},
60 { "vty_port", required_argument, NULL, 'P'},
61 { "retain", no_argument, NULL, 'r'},
62 { "no_kernel", no_argument, NULL, 'n'},
pauledd7c242003-06-04 13:59:38 +000063 { "user", required_argument, NULL, 'u'},
hassoc0652302004-11-25 19:33:48 +000064 { "group", required_argument, NULL, 'g'},
paul718e3742002-12-13 20:15:29 +000065 { "version", no_argument, NULL, 'v'},
Paul Jakma876b8be2006-10-15 23:35:57 +000066 { "dryrun", no_argument, NULL, 'C'},
paul718e3742002-12-13 20:15:29 +000067 { "help", no_argument, NULL, 'h'},
68 { 0 }
69};
70
paul2d75d052004-01-19 21:31:15 +000071/* signal definitions */
72void sighup (void);
73void sigint (void);
74void sigusr1 (void);
75
Chris Caputo228da422009-07-18 05:44:03 +000076static void bgp_exit (int);
77
Stephen Hemminger372b3c72009-05-15 10:29:41 -070078static struct quagga_signal_t bgp_signals[] =
paul2d75d052004-01-19 21:31:15 +000079{
80 {
81 .signal = SIGHUP,
82 .handler = &sighup,
83 },
84 {
85 .signal = SIGUSR1,
86 .handler = &sigusr1,
87 },
88 {
89 .signal = SIGINT,
90 .handler = &sigint,
91 },
hassof571dab2004-03-22 08:55:25 +000092 {
93 .signal = SIGTERM,
94 .handler = &sigint,
95 },
paul2d75d052004-01-19 21:31:15 +000096};
97
paul718e3742002-12-13 20:15:29 +000098/* Configuration file and directory. */
paul718e3742002-12-13 20:15:29 +000099char config_default[] = SYSCONFDIR BGP_DEFAULT_CONFIG;
100
101/* Route retain mode flag. */
Stephen Hemminger372b3c72009-05-15 10:29:41 -0700102static int retain_mode = 0;
paul718e3742002-12-13 20:15:29 +0000103
104/* Master of threads. */
105struct thread_master *master;
106
107/* Manually specified configuration file name. */
108char *config_file = NULL;
109
110/* Process ID saved for use by init system */
Stephen Hemminger372b3c72009-05-15 10:29:41 -0700111static const char *pid_file = PATH_BGPD_PID;
paul718e3742002-12-13 20:15:29 +0000112
113/* VTY port number and address. */
114int vty_port = BGP_VTY_PORT;
115char *vty_addr = NULL;
116
pauledd7c242003-06-04 13:59:38 +0000117/* privileges */
Stephen Hemminger372b3c72009-05-15 10:29:41 -0700118static zebra_capabilities_t _caps_p [] =
pauledd7c242003-06-04 13:59:38 +0000119{
paul98f51632004-10-25 14:19:15 +0000120 ZCAP_BIND,
paulceacedb2005-09-29 14:39:32 +0000121 ZCAP_NET_RAW,
Chris Luke5c88f192011-10-18 17:26:51 +0400122 ZCAP_NET_ADMIN,
pauledd7c242003-06-04 13:59:38 +0000123};
124
125struct zebra_privs_t bgpd_privs =
126{
pauld81fadf2003-08-14 05:32:12 +0000127#if defined(QUAGGA_USER) && defined(QUAGGA_GROUP)
128 .user = QUAGGA_USER,
129 .group = QUAGGA_GROUP,
130#endif
131#ifdef VTY_GROUP
132 .vty_group = VTY_GROUP,
pauledd7c242003-06-04 13:59:38 +0000133#endif
134 .caps_p = _caps_p,
135 .cap_num_p = sizeof(_caps_p)/sizeof(_caps_p[0]),
136 .cap_num_i = 0,
137};
138
paul718e3742002-12-13 20:15:29 +0000139/* Help information display. */
140static void
141usage (char *progname, int status)
142{
143 if (status != 0)
144 fprintf (stderr, "Try `%s --help' for more information.\n", progname);
145 else
146 {
147 printf ("Usage : %s [OPTION...]\n\n\
148Daemon which manages kernel routing table management and \
149redistribution between different routing protocols.\n\n\
150-d, --daemon Runs in daemon mode\n\
151-f, --config_file Set configuration file name\n\
152-i, --pid_file Set process identifier file name\n\
153-p, --bgp_port Set bgp protocol's port number\n\
Paul Jakma3a02d1f2007-11-01 14:29:11 +0000154-l, --listenon Listen on specified address (implies -n)\n\
paul718e3742002-12-13 20:15:29 +0000155-A, --vty_addr Set vty's bind address\n\
156-P, --vty_port Set vty's port number\n\
157-r, --retain When program terminates, retain added route by bgpd.\n\
158-n, --no_kernel Do not install route to kernel.\n\
hassoc0652302004-11-25 19:33:48 +0000159-u, --user User to run as\n\
160-g, --group Group to run as\n\
paul718e3742002-12-13 20:15:29 +0000161-v, --version Print program version\n\
Paul Jakma876b8be2006-10-15 23:35:57 +0000162-C, --dryrun Check configuration for validity and exit\n\
paul718e3742002-12-13 20:15:29 +0000163-h, --help Display this help and exit\n\
164\n\
165Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
166 }
167
168 exit (status);
169}
170
171/* SIGHUP handler. */
172void
paul2d75d052004-01-19 21:31:15 +0000173sighup (void)
paul718e3742002-12-13 20:15:29 +0000174{
175 zlog (NULL, LOG_INFO, "SIGHUP received");
176
177 /* Terminate all thread. */
178 bgp_terminate ();
179 bgp_reset ();
180 zlog_info ("bgpd restarting!");
181
182 /* Reload config file. */
hasso320ec102004-06-20 19:54:37 +0000183 vty_read_config (config_file, config_default);
paul718e3742002-12-13 20:15:29 +0000184
185 /* Create VTY's socket */
paul4fc4e7a2003-01-22 19:47:09 +0000186 vty_serv_sock (vty_addr, vty_port, BGP_VTYSH_PATH);
paul718e3742002-12-13 20:15:29 +0000187
188 /* Try to return to normal operation. */
189}
190
191/* SIGINT handler. */
192void
paul2d75d052004-01-19 21:31:15 +0000193sigint (void)
paul718e3742002-12-13 20:15:29 +0000194{
ajs887c44a2004-12-03 16:36:46 +0000195 zlog_notice ("Terminating on signal");
paul718e3742002-12-13 20:15:29 +0000196
197 if (! retain_mode)
198 bgp_terminate ();
199
Stephen Hemminger04d5e242011-12-07 00:04:46 +0400200 zprivs_terminate (&bgpd_privs);
Chris Caputo228da422009-07-18 05:44:03 +0000201 bgp_exit (0);
paul718e3742002-12-13 20:15:29 +0000202}
203
204/* SIGUSR1 handler. */
205void
paul2d75d052004-01-19 21:31:15 +0000206sigusr1 (void)
paul718e3742002-12-13 20:15:29 +0000207{
208 zlog_rotate (NULL);
209}
Chris Caputo228da422009-07-18 05:44:03 +0000210
211/*
212 Try to free up allocations we know about so that diagnostic tools such as
213 valgrind are able to better illuminate leaks.
214
215 Zebra route removal and protocol teardown are not meant to be done here.
216 For example, "retain_mode" may be set.
217*/
218static void
219bgp_exit (int status)
220{
221 struct bgp *bgp;
222 struct listnode *node, *nnode;
223 int *socket;
224 struct interface *ifp;
225 extern struct zclient *zclient;
226 extern struct zclient *zlookup;
227
228 /* it only makes sense for this to be called on a clean exit */
229 assert (status == 0);
230
231 /* reverse bgp_master_init */
232 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
233 bgp_delete (bgp);
234 list_free (bm->bgp);
235
236 /* reverse bgp_master_init */
237 for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, socket))
238 {
239 if (close ((int)(long)socket) == -1)
240 zlog_err ("close (%d): %s", (int)(long)socket, safe_strerror (errno));
241 }
242 list_delete (bm->listen_sockets);
243
244 /* reverse bgp_zebra_init/if_init */
245 if (retain_mode)
246 if_add_hook (IF_DELETE_HOOK, NULL);
247 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
Chris Caputo6c88b442010-07-27 16:28:55 +0000248 {
249 struct listnode *c_node, *c_nnode;
250 struct connected *c;
251
252 for (ALL_LIST_ELEMENTS (ifp->connected, c_node, c_nnode, c))
253 bgp_connected_delete (c);
254
255 if_delete (ifp);
256 }
Chris Caputo228da422009-07-18 05:44:03 +0000257 list_free (iflist);
258
259 /* reverse bgp_attr_init */
260 bgp_attr_finish ();
261
262 /* reverse bgp_dump_init */
263 bgp_dump_finish ();
264
265 /* reverse bgp_route_init */
266 bgp_route_finish ();
267
268 /* reverse bgp_route_map_init/route_map_init */
269 route_map_finish ();
270
271 /* reverse bgp_scan_init */
272 bgp_scan_finish ();
273
274 /* reverse access_list_init */
275 access_list_add_hook (NULL);
276 access_list_delete_hook (NULL);
277 access_list_reset ();
278
279 /* reverse bgp_filter_init */
280 as_list_add_hook (NULL);
281 as_list_delete_hook (NULL);
282 bgp_filter_reset ();
283
284 /* reverse prefix_list_init */
285 prefix_list_add_hook (NULL);
286 prefix_list_delete_hook (NULL);
287 prefix_list_reset ();
288
289 /* reverse community_list_init */
290 community_list_terminate (bgp_clist);
291
292 cmd_terminate ();
293 vty_terminate ();
294 if (zclient)
295 zclient_free (zclient);
296 if (zlookup)
297 zclient_free (zlookup);
298
299 /* reverse bgp_master_init */
300 if (master)
301 thread_master_free (master);
302
303 if (zlog_default)
304 closezlog (zlog_default);
305
306 if (CONF_BGP_DEBUG (normal, NORMAL))
307 log_memstats_stderr ("bgpd");
308
309 exit (status);
310}
paul718e3742002-12-13 20:15:29 +0000311
312/* Main routine of bgpd. Treatment of argument and start bgp finite
313 state machine is handled at here. */
314int
315main (int argc, char **argv)
316{
317 char *p;
318 int opt;
319 int daemon_mode = 0;
Paul Jakma876b8be2006-10-15 23:35:57 +0000320 int dryrun = 0;
paul718e3742002-12-13 20:15:29 +0000321 char *progname;
322 struct thread thread;
Paul Jakma0d6b2ee2008-05-29 18:29:16 +0000323 int tmp_port;
paul718e3742002-12-13 20:15:29 +0000324
325 /* Set umask before anything for security */
326 umask (0027);
327
328 /* Preserve name of myself. */
329 progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
330
ajs274a4a42004-12-07 15:39:31 +0000331 zlog_default = openzlog (progname, ZLOG_BGP,
paul718e3742002-12-13 20:15:29 +0000332 LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
333
334 /* BGP master init. */
335 bgp_master_init ();
336
337 /* Command line argument treatment. */
338 while (1)
339 {
Paul Jakma3a02d1f2007-11-01 14:29:11 +0000340 opt = getopt_long (argc, argv, "df:i:hp:l:A:P:rnu:g:vC", longopts, 0);
paul718e3742002-12-13 20:15:29 +0000341
342 if (opt == EOF)
343 break;
344
345 switch (opt)
346 {
347 case 0:
348 break;
349 case 'd':
350 daemon_mode = 1;
351 break;
352 case 'f':
353 config_file = optarg;
354 break;
355 case 'i':
356 pid_file = optarg;
357 break;
358 case 'p':
Paul Jakma0d6b2ee2008-05-29 18:29:16 +0000359 tmp_port = atoi (optarg);
360 if (tmp_port <= 0 || tmp_port > 0xffff)
361 bm->port = BGP_PORT_DEFAULT;
362 else
363 bm->port = tmp_port;
paul718e3742002-12-13 20:15:29 +0000364 break;
365 case 'A':
366 vty_addr = optarg;
367 break;
368 case 'P':
paul4fc4e7a2003-01-22 19:47:09 +0000369 /* Deal with atoi() returning 0 on failure, and bgpd not
370 listening on bgp port... */
371 if (strcmp(optarg, "0") == 0)
372 {
373 vty_port = 0;
374 break;
375 }
376 vty_port = atoi (optarg);
Paul Jakma0d6b2ee2008-05-29 18:29:16 +0000377 if (vty_port <= 0 || vty_port > 0xffff)
378 vty_port = BGP_VTY_PORT;
paul718e3742002-12-13 20:15:29 +0000379 break;
380 case 'r':
381 retain_mode = 1;
382 break;
Paul Jakma3a02d1f2007-11-01 14:29:11 +0000383 case 'l':
384 bm->address = optarg;
385 /* listenon implies -n */
paul718e3742002-12-13 20:15:29 +0000386 case 'n':
387 bgp_option_set (BGP_OPT_NO_FIB);
388 break;
hassoc0652302004-11-25 19:33:48 +0000389 case 'u':
390 bgpd_privs.user = optarg;
391 break;
392 case 'g':
393 bgpd_privs.group = optarg;
394 break;
paul718e3742002-12-13 20:15:29 +0000395 case 'v':
396 print_version (progname);
397 exit (0);
398 break;
Paul Jakma876b8be2006-10-15 23:35:57 +0000399 case 'C':
400 dryrun = 1;
401 break;
paul718e3742002-12-13 20:15:29 +0000402 case 'h':
403 usage (progname, 0);
404 break;
405 default:
406 usage (progname, 1);
407 break;
408 }
409 }
410
411 /* Make thread master. */
412 master = bm->master;
413
414 /* Initializations. */
415 srand (time (NULL));
paul2d75d052004-01-19 21:31:15 +0000416 signal_init (master, Q_SIGC(bgp_signals), bgp_signals);
pauledd7c242003-06-04 13:59:38 +0000417 zprivs_init (&bgpd_privs);
paul718e3742002-12-13 20:15:29 +0000418 cmd_init (1);
paulb21b19c2003-06-15 01:28:29 +0000419 vty_init (master);
paul718e3742002-12-13 20:15:29 +0000420 memory_init ();
421
422 /* BGP related initialization. */
423 bgp_init ();
424
425 /* Sort CLI commands. */
426 sort_node ();
427
428 /* Parse config file. */
hasso320ec102004-06-20 19:54:37 +0000429 vty_read_config (config_file, config_default);
paul718e3742002-12-13 20:15:29 +0000430
Paul Jakma876b8be2006-10-15 23:35:57 +0000431 /* Start execution only if not in dry-run mode */
432 if(dryrun)
433 return(0);
434
paul718e3742002-12-13 20:15:29 +0000435 /* Turn into daemon if daemon_mode is set. */
Stephen Hemminger372b3c72009-05-15 10:29:41 -0700436 if (daemon_mode && daemon (0, 0) < 0)
437 {
438 zlog_err("BGPd daemon failed: %s", strerror(errno));
439 return (1);
440 }
441
paul718e3742002-12-13 20:15:29 +0000442
443 /* Process ID file creation. */
444 pid_output (pid_file);
445
446 /* Make bgp vty socket. */
447 vty_serv_sock (vty_addr, vty_port, BGP_VTYSH_PATH);
448
449 /* Print banner. */
Paul Jakma3a02d1f2007-11-01 14:29:11 +0000450 zlog_notice ("BGPd %s starting: vty@%d, bgp@%s:%d", QUAGGA_VERSION,
Paul Jakma7e992e92007-11-13 09:32:23 +0000451 vty_port,
Paul Jakmab63e6082007-11-21 21:25:34 +0000452 (bm->address ? bm->address : "<all>"),
Paul Jakma7e992e92007-11-13 09:32:23 +0000453 bm->port);
paul718e3742002-12-13 20:15:29 +0000454
455 /* Start finite state machine, here we go! */
456 while (thread_fetch (master, &thread))
457 thread_call (&thread);
458
459 /* Not reached. */
paule8e19462006-01-19 20:16:55 +0000460 return (0);
paul718e3742002-12-13 20:15:29 +0000461}