blob: 0e85d57e538ece35e55cdf6092a4ebaf7fcf7725 [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
Chris Caputo228da422009-07-18 05:44:03 +0000200 bgp_exit (0);
paul718e3742002-12-13 20:15:29 +0000201}
202
203/* SIGUSR1 handler. */
204void
paul2d75d052004-01-19 21:31:15 +0000205sigusr1 (void)
paul718e3742002-12-13 20:15:29 +0000206{
207 zlog_rotate (NULL);
208}
Chris Caputo228da422009-07-18 05:44:03 +0000209
210/*
211 Try to free up allocations we know about so that diagnostic tools such as
212 valgrind are able to better illuminate leaks.
213
214 Zebra route removal and protocol teardown are not meant to be done here.
215 For example, "retain_mode" may be set.
216*/
217static void
218bgp_exit (int status)
219{
220 struct bgp *bgp;
221 struct listnode *node, *nnode;
222 int *socket;
223 struct interface *ifp;
224 extern struct zclient *zclient;
225 extern struct zclient *zlookup;
226
227 /* it only makes sense for this to be called on a clean exit */
228 assert (status == 0);
229
230 /* reverse bgp_master_init */
231 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
232 bgp_delete (bgp);
233 list_free (bm->bgp);
234
235 /* reverse bgp_master_init */
236 for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, socket))
237 {
238 if (close ((int)(long)socket) == -1)
239 zlog_err ("close (%d): %s", (int)(long)socket, safe_strerror (errno));
240 }
241 list_delete (bm->listen_sockets);
242
243 /* reverse bgp_zebra_init/if_init */
244 if (retain_mode)
245 if_add_hook (IF_DELETE_HOOK, NULL);
246 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
Chris Caputo6c88b442010-07-27 16:28:55 +0000247 {
248 struct listnode *c_node, *c_nnode;
249 struct connected *c;
250
251 for (ALL_LIST_ELEMENTS (ifp->connected, c_node, c_nnode, c))
252 bgp_connected_delete (c);
253
254 if_delete (ifp);
255 }
Chris Caputo228da422009-07-18 05:44:03 +0000256 list_free (iflist);
257
258 /* reverse bgp_attr_init */
259 bgp_attr_finish ();
260
261 /* reverse bgp_dump_init */
262 bgp_dump_finish ();
263
264 /* reverse bgp_route_init */
265 bgp_route_finish ();
266
267 /* reverse bgp_route_map_init/route_map_init */
268 route_map_finish ();
269
270 /* reverse bgp_scan_init */
271 bgp_scan_finish ();
272
273 /* reverse access_list_init */
274 access_list_add_hook (NULL);
275 access_list_delete_hook (NULL);
276 access_list_reset ();
277
278 /* reverse bgp_filter_init */
279 as_list_add_hook (NULL);
280 as_list_delete_hook (NULL);
281 bgp_filter_reset ();
282
283 /* reverse prefix_list_init */
284 prefix_list_add_hook (NULL);
285 prefix_list_delete_hook (NULL);
286 prefix_list_reset ();
287
288 /* reverse community_list_init */
289 community_list_terminate (bgp_clist);
290
291 cmd_terminate ();
292 vty_terminate ();
293 if (zclient)
294 zclient_free (zclient);
295 if (zlookup)
296 zclient_free (zlookup);
297
298 /* reverse bgp_master_init */
299 if (master)
300 thread_master_free (master);
301
302 if (zlog_default)
303 closezlog (zlog_default);
304
305 if (CONF_BGP_DEBUG (normal, NORMAL))
306 log_memstats_stderr ("bgpd");
307
308 exit (status);
309}
paul718e3742002-12-13 20:15:29 +0000310
311/* Main routine of bgpd. Treatment of argument and start bgp finite
312 state machine is handled at here. */
313int
314main (int argc, char **argv)
315{
316 char *p;
317 int opt;
318 int daemon_mode = 0;
Paul Jakma876b8be2006-10-15 23:35:57 +0000319 int dryrun = 0;
paul718e3742002-12-13 20:15:29 +0000320 char *progname;
321 struct thread thread;
Paul Jakma0d6b2ee2008-05-29 18:29:16 +0000322 int tmp_port;
paul718e3742002-12-13 20:15:29 +0000323
324 /* Set umask before anything for security */
325 umask (0027);
326
327 /* Preserve name of myself. */
328 progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
329
ajs274a4a42004-12-07 15:39:31 +0000330 zlog_default = openzlog (progname, ZLOG_BGP,
paul718e3742002-12-13 20:15:29 +0000331 LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
332
333 /* BGP master init. */
334 bgp_master_init ();
335
336 /* Command line argument treatment. */
337 while (1)
338 {
Paul Jakma3a02d1f2007-11-01 14:29:11 +0000339 opt = getopt_long (argc, argv, "df:i:hp:l:A:P:rnu:g:vC", longopts, 0);
paul718e3742002-12-13 20:15:29 +0000340
341 if (opt == EOF)
342 break;
343
344 switch (opt)
345 {
346 case 0:
347 break;
348 case 'd':
349 daemon_mode = 1;
350 break;
351 case 'f':
352 config_file = optarg;
353 break;
354 case 'i':
355 pid_file = optarg;
356 break;
357 case 'p':
Paul Jakma0d6b2ee2008-05-29 18:29:16 +0000358 tmp_port = atoi (optarg);
359 if (tmp_port <= 0 || tmp_port > 0xffff)
360 bm->port = BGP_PORT_DEFAULT;
361 else
362 bm->port = tmp_port;
paul718e3742002-12-13 20:15:29 +0000363 break;
364 case 'A':
365 vty_addr = optarg;
366 break;
367 case 'P':
paul4fc4e7a2003-01-22 19:47:09 +0000368 /* Deal with atoi() returning 0 on failure, and bgpd not
369 listening on bgp port... */
370 if (strcmp(optarg, "0") == 0)
371 {
372 vty_port = 0;
373 break;
374 }
375 vty_port = atoi (optarg);
Paul Jakma0d6b2ee2008-05-29 18:29:16 +0000376 if (vty_port <= 0 || vty_port > 0xffff)
377 vty_port = BGP_VTY_PORT;
paul718e3742002-12-13 20:15:29 +0000378 break;
379 case 'r':
380 retain_mode = 1;
381 break;
Paul Jakma3a02d1f2007-11-01 14:29:11 +0000382 case 'l':
383 bm->address = optarg;
384 /* listenon implies -n */
paul718e3742002-12-13 20:15:29 +0000385 case 'n':
386 bgp_option_set (BGP_OPT_NO_FIB);
387 break;
hassoc0652302004-11-25 19:33:48 +0000388 case 'u':
389 bgpd_privs.user = optarg;
390 break;
391 case 'g':
392 bgpd_privs.group = optarg;
393 break;
paul718e3742002-12-13 20:15:29 +0000394 case 'v':
395 print_version (progname);
396 exit (0);
397 break;
Paul Jakma876b8be2006-10-15 23:35:57 +0000398 case 'C':
399 dryrun = 1;
400 break;
paul718e3742002-12-13 20:15:29 +0000401 case 'h':
402 usage (progname, 0);
403 break;
404 default:
405 usage (progname, 1);
406 break;
407 }
408 }
409
410 /* Make thread master. */
411 master = bm->master;
412
413 /* Initializations. */
414 srand (time (NULL));
paul2d75d052004-01-19 21:31:15 +0000415 signal_init (master, Q_SIGC(bgp_signals), bgp_signals);
pauledd7c242003-06-04 13:59:38 +0000416 zprivs_init (&bgpd_privs);
paul718e3742002-12-13 20:15:29 +0000417 cmd_init (1);
paulb21b19c2003-06-15 01:28:29 +0000418 vty_init (master);
paul718e3742002-12-13 20:15:29 +0000419 memory_init ();
420
421 /* BGP related initialization. */
422 bgp_init ();
423
424 /* Sort CLI commands. */
425 sort_node ();
426
427 /* Parse config file. */
hasso320ec102004-06-20 19:54:37 +0000428 vty_read_config (config_file, config_default);
paul718e3742002-12-13 20:15:29 +0000429
Paul Jakma876b8be2006-10-15 23:35:57 +0000430 /* Start execution only if not in dry-run mode */
431 if(dryrun)
432 return(0);
433
paul718e3742002-12-13 20:15:29 +0000434 /* Turn into daemon if daemon_mode is set. */
Stephen Hemminger372b3c72009-05-15 10:29:41 -0700435 if (daemon_mode && daemon (0, 0) < 0)
436 {
437 zlog_err("BGPd daemon failed: %s", strerror(errno));
438 return (1);
439 }
440
paul718e3742002-12-13 20:15:29 +0000441
442 /* Process ID file creation. */
443 pid_output (pid_file);
444
445 /* Make bgp vty socket. */
446 vty_serv_sock (vty_addr, vty_port, BGP_VTYSH_PATH);
447
448 /* Print banner. */
Paul Jakma3a02d1f2007-11-01 14:29:11 +0000449 zlog_notice ("BGPd %s starting: vty@%d, bgp@%s:%d", QUAGGA_VERSION,
Paul Jakma7e992e92007-11-13 09:32:23 +0000450 vty_port,
Paul Jakmab63e6082007-11-21 21:25:34 +0000451 (bm->address ? bm->address : "<all>"),
Paul Jakma7e992e92007-11-13 09:32:23 +0000452 bm->port);
paul718e3742002-12-13 20:15:29 +0000453
454 /* Start finite state machine, here we go! */
455 while (thread_fetch (master, &thread))
456 thread_call (&thread);
457
458 /* Not reached. */
paule8e19462006-01-19 20:16:55 +0000459 return (0);
paul718e3742002-12-13 20:15:29 +0000460}