blob: 9d14683caf3780242d615267d02976acdc0a8886 [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,
pauledd7c242003-06-04 13:59:38 +0000122};
123
124struct zebra_privs_t bgpd_privs =
125{
pauld81fadf2003-08-14 05:32:12 +0000126#if defined(QUAGGA_USER) && defined(QUAGGA_GROUP)
127 .user = QUAGGA_USER,
128 .group = QUAGGA_GROUP,
129#endif
130#ifdef VTY_GROUP
131 .vty_group = VTY_GROUP,
pauledd7c242003-06-04 13:59:38 +0000132#endif
133 .caps_p = _caps_p,
134 .cap_num_p = sizeof(_caps_p)/sizeof(_caps_p[0]),
135 .cap_num_i = 0,
136};
137
paul718e3742002-12-13 20:15:29 +0000138/* Help information display. */
139static void
140usage (char *progname, int status)
141{
142 if (status != 0)
143 fprintf (stderr, "Try `%s --help' for more information.\n", progname);
144 else
145 {
146 printf ("Usage : %s [OPTION...]\n\n\
147Daemon which manages kernel routing table management and \
148redistribution between different routing protocols.\n\n\
149-d, --daemon Runs in daemon mode\n\
150-f, --config_file Set configuration file name\n\
151-i, --pid_file Set process identifier file name\n\
152-p, --bgp_port Set bgp protocol's port number\n\
Paul Jakma3a02d1f2007-11-01 14:29:11 +0000153-l, --listenon Listen on specified address (implies -n)\n\
paul718e3742002-12-13 20:15:29 +0000154-A, --vty_addr Set vty's bind address\n\
155-P, --vty_port Set vty's port number\n\
156-r, --retain When program terminates, retain added route by bgpd.\n\
157-n, --no_kernel Do not install route to kernel.\n\
hassoc0652302004-11-25 19:33:48 +0000158-u, --user User to run as\n\
159-g, --group Group to run as\n\
paul718e3742002-12-13 20:15:29 +0000160-v, --version Print program version\n\
Paul Jakma876b8be2006-10-15 23:35:57 +0000161-C, --dryrun Check configuration for validity and exit\n\
paul718e3742002-12-13 20:15:29 +0000162-h, --help Display this help and exit\n\
163\n\
164Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
165 }
166
167 exit (status);
168}
169
170/* SIGHUP handler. */
171void
paul2d75d052004-01-19 21:31:15 +0000172sighup (void)
paul718e3742002-12-13 20:15:29 +0000173{
174 zlog (NULL, LOG_INFO, "SIGHUP received");
175
176 /* Terminate all thread. */
177 bgp_terminate ();
178 bgp_reset ();
179 zlog_info ("bgpd restarting!");
180
181 /* Reload config file. */
hasso320ec102004-06-20 19:54:37 +0000182 vty_read_config (config_file, config_default);
paul718e3742002-12-13 20:15:29 +0000183
184 /* Create VTY's socket */
paul4fc4e7a2003-01-22 19:47:09 +0000185 vty_serv_sock (vty_addr, vty_port, BGP_VTYSH_PATH);
paul718e3742002-12-13 20:15:29 +0000186
187 /* Try to return to normal operation. */
188}
189
190/* SIGINT handler. */
191void
paul2d75d052004-01-19 21:31:15 +0000192sigint (void)
paul718e3742002-12-13 20:15:29 +0000193{
ajs887c44a2004-12-03 16:36:46 +0000194 zlog_notice ("Terminating on signal");
paul718e3742002-12-13 20:15:29 +0000195
196 if (! retain_mode)
197 bgp_terminate ();
198
Chris Caputo228da422009-07-18 05:44:03 +0000199 bgp_exit (0);
paul718e3742002-12-13 20:15:29 +0000200}
201
202/* SIGUSR1 handler. */
203void
paul2d75d052004-01-19 21:31:15 +0000204sigusr1 (void)
paul718e3742002-12-13 20:15:29 +0000205{
206 zlog_rotate (NULL);
207}
Chris Caputo228da422009-07-18 05:44:03 +0000208
209/*
210 Try to free up allocations we know about so that diagnostic tools such as
211 valgrind are able to better illuminate leaks.
212
213 Zebra route removal and protocol teardown are not meant to be done here.
214 For example, "retain_mode" may be set.
215*/
216static void
217bgp_exit (int status)
218{
219 struct bgp *bgp;
220 struct listnode *node, *nnode;
221 int *socket;
222 struct interface *ifp;
223 extern struct zclient *zclient;
224 extern struct zclient *zlookup;
225
226 /* it only makes sense for this to be called on a clean exit */
227 assert (status == 0);
228
229 /* reverse bgp_master_init */
230 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
231 bgp_delete (bgp);
232 list_free (bm->bgp);
233
234 /* reverse bgp_master_init */
235 for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, socket))
236 {
237 if (close ((int)(long)socket) == -1)
238 zlog_err ("close (%d): %s", (int)(long)socket, safe_strerror (errno));
239 }
240 list_delete (bm->listen_sockets);
241
242 /* reverse bgp_zebra_init/if_init */
243 if (retain_mode)
244 if_add_hook (IF_DELETE_HOOK, NULL);
245 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
246 if_delete (ifp);
247 list_free (iflist);
248
249 /* reverse bgp_attr_init */
250 bgp_attr_finish ();
251
252 /* reverse bgp_dump_init */
253 bgp_dump_finish ();
254
255 /* reverse bgp_route_init */
256 bgp_route_finish ();
257
258 /* reverse bgp_route_map_init/route_map_init */
259 route_map_finish ();
260
261 /* reverse bgp_scan_init */
262 bgp_scan_finish ();
263
264 /* reverse access_list_init */
265 access_list_add_hook (NULL);
266 access_list_delete_hook (NULL);
267 access_list_reset ();
268
269 /* reverse bgp_filter_init */
270 as_list_add_hook (NULL);
271 as_list_delete_hook (NULL);
272 bgp_filter_reset ();
273
274 /* reverse prefix_list_init */
275 prefix_list_add_hook (NULL);
276 prefix_list_delete_hook (NULL);
277 prefix_list_reset ();
278
279 /* reverse community_list_init */
280 community_list_terminate (bgp_clist);
281
282 cmd_terminate ();
283 vty_terminate ();
284 if (zclient)
285 zclient_free (zclient);
286 if (zlookup)
287 zclient_free (zlookup);
288
289 /* reverse bgp_master_init */
290 if (master)
291 thread_master_free (master);
292
293 if (zlog_default)
294 closezlog (zlog_default);
295
296 if (CONF_BGP_DEBUG (normal, NORMAL))
297 log_memstats_stderr ("bgpd");
298
299 exit (status);
300}
paul718e3742002-12-13 20:15:29 +0000301
302/* Main routine of bgpd. Treatment of argument and start bgp finite
303 state machine is handled at here. */
304int
305main (int argc, char **argv)
306{
307 char *p;
308 int opt;
309 int daemon_mode = 0;
Paul Jakma876b8be2006-10-15 23:35:57 +0000310 int dryrun = 0;
paul718e3742002-12-13 20:15:29 +0000311 char *progname;
312 struct thread thread;
Paul Jakma0d6b2ee2008-05-29 18:29:16 +0000313 int tmp_port;
paul718e3742002-12-13 20:15:29 +0000314
315 /* Set umask before anything for security */
316 umask (0027);
317
318 /* Preserve name of myself. */
319 progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
320
ajs274a4a42004-12-07 15:39:31 +0000321 zlog_default = openzlog (progname, ZLOG_BGP,
paul718e3742002-12-13 20:15:29 +0000322 LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
323
324 /* BGP master init. */
325 bgp_master_init ();
326
327 /* Command line argument treatment. */
328 while (1)
329 {
Paul Jakma3a02d1f2007-11-01 14:29:11 +0000330 opt = getopt_long (argc, argv, "df:i:hp:l:A:P:rnu:g:vC", longopts, 0);
paul718e3742002-12-13 20:15:29 +0000331
332 if (opt == EOF)
333 break;
334
335 switch (opt)
336 {
337 case 0:
338 break;
339 case 'd':
340 daemon_mode = 1;
341 break;
342 case 'f':
343 config_file = optarg;
344 break;
345 case 'i':
346 pid_file = optarg;
347 break;
348 case 'p':
Paul Jakma0d6b2ee2008-05-29 18:29:16 +0000349 tmp_port = atoi (optarg);
350 if (tmp_port <= 0 || tmp_port > 0xffff)
351 bm->port = BGP_PORT_DEFAULT;
352 else
353 bm->port = tmp_port;
paul718e3742002-12-13 20:15:29 +0000354 break;
355 case 'A':
356 vty_addr = optarg;
357 break;
358 case 'P':
paul4fc4e7a2003-01-22 19:47:09 +0000359 /* Deal with atoi() returning 0 on failure, and bgpd not
360 listening on bgp port... */
361 if (strcmp(optarg, "0") == 0)
362 {
363 vty_port = 0;
364 break;
365 }
366 vty_port = atoi (optarg);
Paul Jakma0d6b2ee2008-05-29 18:29:16 +0000367 if (vty_port <= 0 || vty_port > 0xffff)
368 vty_port = BGP_VTY_PORT;
paul718e3742002-12-13 20:15:29 +0000369 break;
370 case 'r':
371 retain_mode = 1;
372 break;
Paul Jakma3a02d1f2007-11-01 14:29:11 +0000373 case 'l':
374 bm->address = optarg;
375 /* listenon implies -n */
paul718e3742002-12-13 20:15:29 +0000376 case 'n':
377 bgp_option_set (BGP_OPT_NO_FIB);
378 break;
hassoc0652302004-11-25 19:33:48 +0000379 case 'u':
380 bgpd_privs.user = optarg;
381 break;
382 case 'g':
383 bgpd_privs.group = optarg;
384 break;
paul718e3742002-12-13 20:15:29 +0000385 case 'v':
386 print_version (progname);
387 exit (0);
388 break;
Paul Jakma876b8be2006-10-15 23:35:57 +0000389 case 'C':
390 dryrun = 1;
391 break;
paul718e3742002-12-13 20:15:29 +0000392 case 'h':
393 usage (progname, 0);
394 break;
395 default:
396 usage (progname, 1);
397 break;
398 }
399 }
400
401 /* Make thread master. */
402 master = bm->master;
403
404 /* Initializations. */
405 srand (time (NULL));
paul2d75d052004-01-19 21:31:15 +0000406 signal_init (master, Q_SIGC(bgp_signals), bgp_signals);
pauledd7c242003-06-04 13:59:38 +0000407 zprivs_init (&bgpd_privs);
paul718e3742002-12-13 20:15:29 +0000408 cmd_init (1);
paulb21b19c2003-06-15 01:28:29 +0000409 vty_init (master);
paul718e3742002-12-13 20:15:29 +0000410 memory_init ();
411
412 /* BGP related initialization. */
413 bgp_init ();
414
415 /* Sort CLI commands. */
416 sort_node ();
417
418 /* Parse config file. */
hasso320ec102004-06-20 19:54:37 +0000419 vty_read_config (config_file, config_default);
paul718e3742002-12-13 20:15:29 +0000420
Paul Jakma876b8be2006-10-15 23:35:57 +0000421 /* Start execution only if not in dry-run mode */
422 if(dryrun)
423 return(0);
424
paul718e3742002-12-13 20:15:29 +0000425 /* Turn into daemon if daemon_mode is set. */
Stephen Hemminger372b3c72009-05-15 10:29:41 -0700426 if (daemon_mode && daemon (0, 0) < 0)
427 {
428 zlog_err("BGPd daemon failed: %s", strerror(errno));
429 return (1);
430 }
431
paul718e3742002-12-13 20:15:29 +0000432
433 /* Process ID file creation. */
434 pid_output (pid_file);
435
436 /* Make bgp vty socket. */
437 vty_serv_sock (vty_addr, vty_port, BGP_VTYSH_PATH);
438
439 /* Print banner. */
Paul Jakma3a02d1f2007-11-01 14:29:11 +0000440 zlog_notice ("BGPd %s starting: vty@%d, bgp@%s:%d", QUAGGA_VERSION,
Paul Jakma7e992e92007-11-13 09:32:23 +0000441 vty_port,
Paul Jakmab63e6082007-11-21 21:25:34 +0000442 (bm->address ? bm->address : "<all>"),
Paul Jakma7e992e92007-11-13 09:32:23 +0000443 bm->port);
paul718e3742002-12-13 20:15:29 +0000444
445 /* Start finite state machine, here we go! */
446 while (thread_fetch (master, &thread))
447 thread_call (&thread);
448
449 /* Not reached. */
paule8e19462006-01-19 20:16:55 +0000450 return (0);
paul718e3742002-12-13 20:15:29 +0000451}