blob: 562afc20e826fd9ef9adff5266ec8f9e866b6ff7 [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"
Josh Bailey8196f132011-07-20 20:47:07 -070038#include "stream.h"
Feng Lu126215c2015-05-22 11:39:58 +020039#include "vrf.h"
Lou Berger056f3762013-04-10 12:30:04 -070040#include "workqueue.h"
paul718e3742002-12-13 20:15:29 +000041
42#include "bgpd/bgpd.h"
43#include "bgpd/bgp_attr.h"
44#include "bgpd/bgp_mplsvpn.h"
Chris Caputo228da422009-07-18 05:44:03 +000045#include "bgpd/bgp_aspath.h"
46#include "bgpd/bgp_dump.h"
47#include "bgpd/bgp_route.h"
48#include "bgpd/bgp_nexthop.h"
49#include "bgpd/bgp_regex.h"
50#include "bgpd/bgp_clist.h"
51#include "bgpd/bgp_debug.h"
52#include "bgpd/bgp_filter.h"
Josh Bailey8196f132011-07-20 20:47:07 -070053#include "bgpd/bgp_zebra.h"
paul718e3742002-12-13 20:15:29 +000054
55/* bgpd options, we use GNU getopt library. */
Stephen Hemminger372b3c72009-05-15 10:29:41 -070056static const struct option longopts[] =
paul718e3742002-12-13 20:15:29 +000057{
58 { "daemon", no_argument, NULL, 'd'},
59 { "config_file", required_argument, NULL, 'f'},
60 { "pid_file", required_argument, NULL, 'i'},
Vyacheslav Trushkinb5114682011-11-25 18:51:48 +040061 { "socket", required_argument, NULL, 'z'},
paul718e3742002-12-13 20:15:29 +000062 { "bgp_port", required_argument, NULL, 'p'},
Paul Jakma3a02d1f2007-11-01 14:29:11 +000063 { "listenon", required_argument, NULL, 'l'},
paul718e3742002-12-13 20:15:29 +000064 { "vty_addr", required_argument, NULL, 'A'},
65 { "vty_port", required_argument, NULL, 'P'},
66 { "retain", no_argument, NULL, 'r'},
67 { "no_kernel", no_argument, NULL, 'n'},
pauledd7c242003-06-04 13:59:38 +000068 { "user", required_argument, NULL, 'u'},
hassoc0652302004-11-25 19:33:48 +000069 { "group", required_argument, NULL, 'g'},
Lou Bergerac6ff462016-05-17 07:10:37 -040070 { "skip_runas", no_argument, NULL, 'S'},
paul718e3742002-12-13 20:15:29 +000071 { "version", no_argument, NULL, 'v'},
Paul Jakma876b8be2006-10-15 23:35:57 +000072 { "dryrun", no_argument, NULL, 'C'},
paul718e3742002-12-13 20:15:29 +000073 { "help", no_argument, NULL, 'h'},
74 { 0 }
75};
76
paul2d75d052004-01-19 21:31:15 +000077/* signal definitions */
78void sighup (void);
79void sigint (void);
80void sigusr1 (void);
81
Chris Caputo228da422009-07-18 05:44:03 +000082static void bgp_exit (int);
83
Stephen Hemminger372b3c72009-05-15 10:29:41 -070084static struct quagga_signal_t bgp_signals[] =
paul2d75d052004-01-19 21:31:15 +000085{
86 {
87 .signal = SIGHUP,
88 .handler = &sighup,
89 },
90 {
91 .signal = SIGUSR1,
92 .handler = &sigusr1,
93 },
94 {
95 .signal = SIGINT,
96 .handler = &sigint,
97 },
hassof571dab2004-03-22 08:55:25 +000098 {
99 .signal = SIGTERM,
100 .handler = &sigint,
101 },
paul2d75d052004-01-19 21:31:15 +0000102};
103
paul718e3742002-12-13 20:15:29 +0000104/* Configuration file and directory. */
paul718e3742002-12-13 20:15:29 +0000105char config_default[] = SYSCONFDIR BGP_DEFAULT_CONFIG;
106
107/* Route retain mode flag. */
Stephen Hemminger372b3c72009-05-15 10:29:41 -0700108static int retain_mode = 0;
paul718e3742002-12-13 20:15:29 +0000109
paul718e3742002-12-13 20:15:29 +0000110/* Manually specified configuration file name. */
111char *config_file = NULL;
112
113/* Process ID saved for use by init system */
Stephen Hemminger372b3c72009-05-15 10:29:41 -0700114static const char *pid_file = PATH_BGPD_PID;
paul718e3742002-12-13 20:15:29 +0000115
116/* VTY port number and address. */
117int vty_port = BGP_VTY_PORT;
118char *vty_addr = NULL;
119
pauledd7c242003-06-04 13:59:38 +0000120/* privileges */
Stephen Hemminger372b3c72009-05-15 10:29:41 -0700121static zebra_capabilities_t _caps_p [] =
pauledd7c242003-06-04 13:59:38 +0000122{
paul98f51632004-10-25 14:19:15 +0000123 ZCAP_BIND,
paulceacedb2005-09-29 14:39:32 +0000124 ZCAP_NET_RAW,
Chris Luke5c88f192011-10-18 17:26:51 +0400125 ZCAP_NET_ADMIN,
pauledd7c242003-06-04 13:59:38 +0000126};
127
128struct zebra_privs_t bgpd_privs =
129{
pauld81fadf2003-08-14 05:32:12 +0000130#if defined(QUAGGA_USER) && defined(QUAGGA_GROUP)
131 .user = QUAGGA_USER,
132 .group = QUAGGA_GROUP,
133#endif
134#ifdef VTY_GROUP
135 .vty_group = VTY_GROUP,
pauledd7c242003-06-04 13:59:38 +0000136#endif
137 .caps_p = _caps_p,
Balaji.G837d16c2012-09-26 14:09:10 +0530138 .cap_num_p = array_size(_caps_p),
pauledd7c242003-06-04 13:59:38 +0000139 .cap_num_i = 0,
140};
141
paul718e3742002-12-13 20:15:29 +0000142/* Help information display. */
143static void
144usage (char *progname, int status)
145{
146 if (status != 0)
147 fprintf (stderr, "Try `%s --help' for more information.\n", progname);
148 else
149 {
150 printf ("Usage : %s [OPTION...]\n\n\
151Daemon which manages kernel routing table management and \
152redistribution between different routing protocols.\n\n\
153-d, --daemon Runs in daemon mode\n\
154-f, --config_file Set configuration file name\n\
155-i, --pid_file Set process identifier file name\n\
Vyacheslav Trushkinb5114682011-11-25 18:51:48 +0400156-z, --socket Set path of zebra socket\n\
paul718e3742002-12-13 20:15:29 +0000157-p, --bgp_port Set bgp protocol's port number\n\
Paul Jakma3a02d1f2007-11-01 14:29:11 +0000158-l, --listenon Listen on specified address (implies -n)\n\
paul718e3742002-12-13 20:15:29 +0000159-A, --vty_addr Set vty's bind address\n\
160-P, --vty_port Set vty's port number\n\
161-r, --retain When program terminates, retain added route by bgpd.\n\
162-n, --no_kernel Do not install route to kernel.\n\
hassoc0652302004-11-25 19:33:48 +0000163-u, --user User to run as\n\
164-g, --group Group to run as\n\
Lou Bergerac6ff462016-05-17 07:10:37 -0400165-S, --skip_runas Skip user and group run as\n\
paul718e3742002-12-13 20:15:29 +0000166-v, --version Print program version\n\
Paul Jakma876b8be2006-10-15 23:35:57 +0000167-C, --dryrun Check configuration for validity and exit\n\
paul718e3742002-12-13 20:15:29 +0000168-h, --help Display this help and exit\n\
169\n\
170Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
171 }
172
173 exit (status);
174}
David Lamparter6b0655a2014-06-04 06:53:35 +0200175
paul718e3742002-12-13 20:15:29 +0000176/* SIGHUP handler. */
177void
paul2d75d052004-01-19 21:31:15 +0000178sighup (void)
paul718e3742002-12-13 20:15:29 +0000179{
180 zlog (NULL, LOG_INFO, "SIGHUP received");
181
182 /* Terminate all thread. */
183 bgp_terminate ();
184 bgp_reset ();
185 zlog_info ("bgpd restarting!");
186
187 /* Reload config file. */
hasso320ec102004-06-20 19:54:37 +0000188 vty_read_config (config_file, config_default);
paul718e3742002-12-13 20:15:29 +0000189
190 /* Create VTY's socket */
paul4fc4e7a2003-01-22 19:47:09 +0000191 vty_serv_sock (vty_addr, vty_port, BGP_VTYSH_PATH);
paul718e3742002-12-13 20:15:29 +0000192
193 /* Try to return to normal operation. */
194}
195
196/* SIGINT handler. */
197void
paul2d75d052004-01-19 21:31:15 +0000198sigint (void)
paul718e3742002-12-13 20:15:29 +0000199{
ajs887c44a2004-12-03 16:36:46 +0000200 zlog_notice ("Terminating on signal");
paul718e3742002-12-13 20:15:29 +0000201
Lou Berger056f3762013-04-10 12:30:04 -0700202 if (! retain_mode)
203 {
204 bgp_terminate ();
Lou Bergerac6ff462016-05-17 07:10:37 -0400205 if (bgpd_privs.user) /* NULL if skip_runas flag set */
206 zprivs_terminate (&bgpd_privs);
Lou Berger056f3762013-04-10 12:30:04 -0700207 }
paul718e3742002-12-13 20:15:29 +0000208
Chris Caputo228da422009-07-18 05:44:03 +0000209 bgp_exit (0);
paul718e3742002-12-13 20:15:29 +0000210}
211
212/* SIGUSR1 handler. */
213void
paul2d75d052004-01-19 21:31:15 +0000214sigusr1 (void)
paul718e3742002-12-13 20:15:29 +0000215{
216 zlog_rotate (NULL);
217}
Chris Caputo228da422009-07-18 05:44:03 +0000218
219/*
220 Try to free up allocations we know about so that diagnostic tools such as
221 valgrind are able to better illuminate leaks.
222
223 Zebra route removal and protocol teardown are not meant to be done here.
224 For example, "retain_mode" may be set.
225*/
226static void
227bgp_exit (int status)
228{
229 struct bgp *bgp;
230 struct listnode *node, *nnode;
231 int *socket;
232 struct interface *ifp;
Chris Caputo228da422009-07-18 05:44:03 +0000233 extern struct zclient *zlookup;
234
235 /* it only makes sense for this to be called on a clean exit */
236 assert (status == 0);
237
238 /* reverse bgp_master_init */
239 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
240 bgp_delete (bgp);
241 list_free (bm->bgp);
Lou Berger056f3762013-04-10 12:30:04 -0700242 bm->bgp = NULL;
243
244 /*
245 * bgp_delete can re-allocate the process queues after they were
246 * deleted in bgp_terminate. delete them again.
247 *
248 * It might be better to ensure the RIBs (including static routes)
249 * are cleared by bgp_terminate() during its call to bgp_cleanup_routes(),
250 * which currently only deletes the kernel routes.
251 */
252 if (bm->process_main_queue)
253 {
254 work_queue_free (bm->process_main_queue);
255 bm->process_main_queue = NULL;
256 }
257 if (bm->process_rsclient_queue)
258 {
259 work_queue_free (bm->process_rsclient_queue);
260 bm->process_rsclient_queue = NULL;
261 }
262
Chris Caputo228da422009-07-18 05:44:03 +0000263 /* reverse bgp_master_init */
264 for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, socket))
265 {
266 if (close ((int)(long)socket) == -1)
267 zlog_err ("close (%d): %s", (int)(long)socket, safe_strerror (errno));
268 }
269 list_delete (bm->listen_sockets);
270
271 /* reverse bgp_zebra_init/if_init */
272 if (retain_mode)
273 if_add_hook (IF_DELETE_HOOK, NULL);
Feng Lu126215c2015-05-22 11:39:58 +0200274 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
Chris Caputo6c88b442010-07-27 16:28:55 +0000275 {
276 struct listnode *c_node, *c_nnode;
277 struct connected *c;
278
279 for (ALL_LIST_ELEMENTS (ifp->connected, c_node, c_nnode, c))
280 bgp_connected_delete (c);
Chris Caputo6c88b442010-07-27 16:28:55 +0000281 }
Chris Caputo228da422009-07-18 05:44:03 +0000282
283 /* reverse bgp_attr_init */
284 bgp_attr_finish ();
285
286 /* reverse bgp_dump_init */
287 bgp_dump_finish ();
288
289 /* reverse bgp_route_init */
290 bgp_route_finish ();
291
292 /* reverse bgp_route_map_init/route_map_init */
293 route_map_finish ();
294
295 /* reverse bgp_scan_init */
296 bgp_scan_finish ();
297
298 /* reverse access_list_init */
299 access_list_add_hook (NULL);
300 access_list_delete_hook (NULL);
301 access_list_reset ();
302
303 /* reverse bgp_filter_init */
304 as_list_add_hook (NULL);
305 as_list_delete_hook (NULL);
306 bgp_filter_reset ();
307
308 /* reverse prefix_list_init */
309 prefix_list_add_hook (NULL);
310 prefix_list_delete_hook (NULL);
311 prefix_list_reset ();
312
313 /* reverse community_list_init */
314 community_list_terminate (bgp_clist);
315
Feng Lu126215c2015-05-22 11:39:58 +0200316 vrf_terminate ();
Chris Caputo228da422009-07-18 05:44:03 +0000317 cmd_terminate ();
318 vty_terminate ();
Lou Berger63703572016-01-12 13:42:03 -0500319 bgp_address_destroy();
320 bgp_scan_destroy();
321 bgp_zebra_destroy();
Chris Caputo228da422009-07-18 05:44:03 +0000322 if (zlookup)
323 zclient_free (zlookup);
Josh Bailey8196f132011-07-20 20:47:07 -0700324 if (bgp_nexthop_buf)
325 stream_free (bgp_nexthop_buf);
Chris Caputo228da422009-07-18 05:44:03 +0000326
327 /* reverse bgp_master_init */
Donald Sharp774914f2015-10-14 08:50:39 -0400328 if (bm->master)
329 thread_master_free (bm->master);
Chris Caputo228da422009-07-18 05:44:03 +0000330
331 if (zlog_default)
332 closezlog (zlog_default);
333
334 if (CONF_BGP_DEBUG (normal, NORMAL))
335 log_memstats_stderr ("bgpd");
336
337 exit (status);
338}
David Lamparter6b0655a2014-06-04 06:53:35 +0200339
paul718e3742002-12-13 20:15:29 +0000340/* Main routine of bgpd. Treatment of argument and start bgp finite
341 state machine is handled at here. */
342int
343main (int argc, char **argv)
344{
345 char *p;
346 int opt;
347 int daemon_mode = 0;
Paul Jakma876b8be2006-10-15 23:35:57 +0000348 int dryrun = 0;
paul718e3742002-12-13 20:15:29 +0000349 char *progname;
350 struct thread thread;
Paul Jakma0d6b2ee2008-05-29 18:29:16 +0000351 int tmp_port;
Lou Bergerac6ff462016-05-17 07:10:37 -0400352 int skip_runas = 0;
paul718e3742002-12-13 20:15:29 +0000353
354 /* Set umask before anything for security */
355 umask (0027);
356
357 /* Preserve name of myself. */
358 progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
359
ajs274a4a42004-12-07 15:39:31 +0000360 zlog_default = openzlog (progname, ZLOG_BGP,
paul718e3742002-12-13 20:15:29 +0000361 LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
362
363 /* BGP master init. */
364 bgp_master_init ();
365
366 /* Command line argument treatment. */
367 while (1)
368 {
Lou Bergerac6ff462016-05-17 07:10:37 -0400369 opt = getopt_long (argc, argv, "df:i:z:hp:l:A:P:rnu:g:vCS", longopts, 0);
paul718e3742002-12-13 20:15:29 +0000370
371 if (opt == EOF)
372 break;
373
374 switch (opt)
375 {
376 case 0:
377 break;
378 case 'd':
379 daemon_mode = 1;
380 break;
381 case 'f':
382 config_file = optarg;
383 break;
384 case 'i':
385 pid_file = optarg;
386 break;
Vyacheslav Trushkinb5114682011-11-25 18:51:48 +0400387 case 'z':
388 zclient_serv_path_set (optarg);
389 break;
paul718e3742002-12-13 20:15:29 +0000390 case 'p':
Paul Jakma0d6b2ee2008-05-29 18:29:16 +0000391 tmp_port = atoi (optarg);
392 if (tmp_port <= 0 || tmp_port > 0xffff)
393 bm->port = BGP_PORT_DEFAULT;
394 else
395 bm->port = tmp_port;
paul718e3742002-12-13 20:15:29 +0000396 break;
397 case 'A':
398 vty_addr = optarg;
399 break;
400 case 'P':
paul4fc4e7a2003-01-22 19:47:09 +0000401 /* Deal with atoi() returning 0 on failure, and bgpd not
402 listening on bgp port... */
403 if (strcmp(optarg, "0") == 0)
404 {
405 vty_port = 0;
406 break;
407 }
408 vty_port = atoi (optarg);
Paul Jakma0d6b2ee2008-05-29 18:29:16 +0000409 if (vty_port <= 0 || vty_port > 0xffff)
410 vty_port = BGP_VTY_PORT;
paul718e3742002-12-13 20:15:29 +0000411 break;
412 case 'r':
413 retain_mode = 1;
414 break;
Paul Jakma3a02d1f2007-11-01 14:29:11 +0000415 case 'l':
416 bm->address = optarg;
417 /* listenon implies -n */
paul718e3742002-12-13 20:15:29 +0000418 case 'n':
419 bgp_option_set (BGP_OPT_NO_FIB);
420 break;
hassoc0652302004-11-25 19:33:48 +0000421 case 'u':
422 bgpd_privs.user = optarg;
423 break;
424 case 'g':
425 bgpd_privs.group = optarg;
426 break;
Lou Bergerac6ff462016-05-17 07:10:37 -0400427 case 'S': /* skip run as = override bgpd_privs */
428 skip_runas = 1;
429 break;
paul718e3742002-12-13 20:15:29 +0000430 case 'v':
431 print_version (progname);
432 exit (0);
433 break;
Paul Jakma876b8be2006-10-15 23:35:57 +0000434 case 'C':
435 dryrun = 1;
436 break;
paul718e3742002-12-13 20:15:29 +0000437 case 'h':
438 usage (progname, 0);
439 break;
440 default:
441 usage (progname, 1);
442 break;
443 }
444 }
445
paul718e3742002-12-13 20:15:29 +0000446 /* Initializations. */
Donald Sharpf31bab42015-06-19 19:26:19 -0400447 srandom (time (NULL));
Donald Sharp774914f2015-10-14 08:50:39 -0400448 signal_init (bm->master, array_size(bgp_signals), bgp_signals);
Lou Bergerac6ff462016-05-17 07:10:37 -0400449 if (skip_runas)
450 memset (&bgpd_privs, 0, sizeof (bgpd_privs));
pauledd7c242003-06-04 13:59:38 +0000451 zprivs_init (&bgpd_privs);
paul718e3742002-12-13 20:15:29 +0000452 cmd_init (1);
Donald Sharp774914f2015-10-14 08:50:39 -0400453 vty_init (bm->master);
paul718e3742002-12-13 20:15:29 +0000454 memory_init ();
Feng Lu126215c2015-05-22 11:39:58 +0200455 vrf_init ();
paul718e3742002-12-13 20:15:29 +0000456
457 /* BGP related initialization. */
458 bgp_init ();
459
paul718e3742002-12-13 20:15:29 +0000460 /* Parse config file. */
hasso320ec102004-06-20 19:54:37 +0000461 vty_read_config (config_file, config_default);
paul718e3742002-12-13 20:15:29 +0000462
Paul Jakma876b8be2006-10-15 23:35:57 +0000463 /* Start execution only if not in dry-run mode */
464 if(dryrun)
465 return(0);
466
paul718e3742002-12-13 20:15:29 +0000467 /* Turn into daemon if daemon_mode is set. */
Stephen Hemminger372b3c72009-05-15 10:29:41 -0700468 if (daemon_mode && daemon (0, 0) < 0)
469 {
470 zlog_err("BGPd daemon failed: %s", strerror(errno));
471 return (1);
472 }
473
paul718e3742002-12-13 20:15:29 +0000474
475 /* Process ID file creation. */
476 pid_output (pid_file);
477
478 /* Make bgp vty socket. */
479 vty_serv_sock (vty_addr, vty_port, BGP_VTYSH_PATH);
480
481 /* Print banner. */
Lou Berger056f3762013-04-10 12:30:04 -0700482 zlog_notice ("BGPd %s starting: vty@%d, bgp@%s:%d pid %d", QUAGGA_VERSION,
Paul Jakma7e992e92007-11-13 09:32:23 +0000483 vty_port,
Paul Jakmab63e6082007-11-21 21:25:34 +0000484 (bm->address ? bm->address : "<all>"),
Lou Berger056f3762013-04-10 12:30:04 -0700485 bm->port,
486 getpid ());
paul718e3742002-12-13 20:15:29 +0000487
488 /* Start finite state machine, here we go! */
Donald Sharp774914f2015-10-14 08:50:39 -0400489 while (thread_fetch (bm->master, &thread))
paul718e3742002-12-13 20:15:29 +0000490 thread_call (&thread);
491
492 /* Not reached. */
paule8e19462006-01-19 20:16:55 +0000493 return (0);
paul718e3742002-12-13 20:15:29 +0000494}