blob: 1a460c6bbecd7d6814e27c91851df6967de354e3 [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))
Chris Caputo6c88b442010-07-27 16:28:55 +0000246 {
247 struct listnode *c_node, *c_nnode;
248 struct connected *c;
249
250 for (ALL_LIST_ELEMENTS (ifp->connected, c_node, c_nnode, c))
251 bgp_connected_delete (c);
252
253 if_delete (ifp);
254 }
Chris Caputo228da422009-07-18 05:44:03 +0000255 list_free (iflist);
256
257 /* reverse bgp_attr_init */
258 bgp_attr_finish ();
259
260 /* reverse bgp_dump_init */
261 bgp_dump_finish ();
262
263 /* reverse bgp_route_init */
264 bgp_route_finish ();
265
266 /* reverse bgp_route_map_init/route_map_init */
267 route_map_finish ();
268
269 /* reverse bgp_scan_init */
270 bgp_scan_finish ();
271
272 /* reverse access_list_init */
273 access_list_add_hook (NULL);
274 access_list_delete_hook (NULL);
275 access_list_reset ();
276
277 /* reverse bgp_filter_init */
278 as_list_add_hook (NULL);
279 as_list_delete_hook (NULL);
280 bgp_filter_reset ();
281
282 /* reverse prefix_list_init */
283 prefix_list_add_hook (NULL);
284 prefix_list_delete_hook (NULL);
285 prefix_list_reset ();
286
287 /* reverse community_list_init */
288 community_list_terminate (bgp_clist);
289
290 cmd_terminate ();
291 vty_terminate ();
292 if (zclient)
293 zclient_free (zclient);
294 if (zlookup)
295 zclient_free (zlookup);
296
297 /* reverse bgp_master_init */
298 if (master)
299 thread_master_free (master);
300
301 if (zlog_default)
302 closezlog (zlog_default);
303
304 if (CONF_BGP_DEBUG (normal, NORMAL))
305 log_memstats_stderr ("bgpd");
306
307 exit (status);
308}
paul718e3742002-12-13 20:15:29 +0000309
310/* Main routine of bgpd. Treatment of argument and start bgp finite
311 state machine is handled at here. */
312int
313main (int argc, char **argv)
314{
315 char *p;
316 int opt;
317 int daemon_mode = 0;
Paul Jakma876b8be2006-10-15 23:35:57 +0000318 int dryrun = 0;
paul718e3742002-12-13 20:15:29 +0000319 char *progname;
320 struct thread thread;
Paul Jakma0d6b2ee2008-05-29 18:29:16 +0000321 int tmp_port;
paul718e3742002-12-13 20:15:29 +0000322
323 /* Set umask before anything for security */
324 umask (0027);
325
326 /* Preserve name of myself. */
327 progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
328
ajs274a4a42004-12-07 15:39:31 +0000329 zlog_default = openzlog (progname, ZLOG_BGP,
paul718e3742002-12-13 20:15:29 +0000330 LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
331
332 /* BGP master init. */
333 bgp_master_init ();
334
335 /* Command line argument treatment. */
336 while (1)
337 {
Paul Jakma3a02d1f2007-11-01 14:29:11 +0000338 opt = getopt_long (argc, argv, "df:i:hp:l:A:P:rnu:g:vC", longopts, 0);
paul718e3742002-12-13 20:15:29 +0000339
340 if (opt == EOF)
341 break;
342
343 switch (opt)
344 {
345 case 0:
346 break;
347 case 'd':
348 daemon_mode = 1;
349 break;
350 case 'f':
351 config_file = optarg;
352 break;
353 case 'i':
354 pid_file = optarg;
355 break;
356 case 'p':
Paul Jakma0d6b2ee2008-05-29 18:29:16 +0000357 tmp_port = atoi (optarg);
358 if (tmp_port <= 0 || tmp_port > 0xffff)
359 bm->port = BGP_PORT_DEFAULT;
360 else
361 bm->port = tmp_port;
paul718e3742002-12-13 20:15:29 +0000362 break;
363 case 'A':
364 vty_addr = optarg;
365 break;
366 case 'P':
paul4fc4e7a2003-01-22 19:47:09 +0000367 /* Deal with atoi() returning 0 on failure, and bgpd not
368 listening on bgp port... */
369 if (strcmp(optarg, "0") == 0)
370 {
371 vty_port = 0;
372 break;
373 }
374 vty_port = atoi (optarg);
Paul Jakma0d6b2ee2008-05-29 18:29:16 +0000375 if (vty_port <= 0 || vty_port > 0xffff)
376 vty_port = BGP_VTY_PORT;
paul718e3742002-12-13 20:15:29 +0000377 break;
378 case 'r':
379 retain_mode = 1;
380 break;
Paul Jakma3a02d1f2007-11-01 14:29:11 +0000381 case 'l':
382 bm->address = optarg;
383 /* listenon implies -n */
paul718e3742002-12-13 20:15:29 +0000384 case 'n':
385 bgp_option_set (BGP_OPT_NO_FIB);
386 break;
hassoc0652302004-11-25 19:33:48 +0000387 case 'u':
388 bgpd_privs.user = optarg;
389 break;
390 case 'g':
391 bgpd_privs.group = optarg;
392 break;
paul718e3742002-12-13 20:15:29 +0000393 case 'v':
394 print_version (progname);
395 exit (0);
396 break;
Paul Jakma876b8be2006-10-15 23:35:57 +0000397 case 'C':
398 dryrun = 1;
399 break;
paul718e3742002-12-13 20:15:29 +0000400 case 'h':
401 usage (progname, 0);
402 break;
403 default:
404 usage (progname, 1);
405 break;
406 }
407 }
408
409 /* Make thread master. */
410 master = bm->master;
411
412 /* Initializations. */
413 srand (time (NULL));
paul2d75d052004-01-19 21:31:15 +0000414 signal_init (master, Q_SIGC(bgp_signals), bgp_signals);
pauledd7c242003-06-04 13:59:38 +0000415 zprivs_init (&bgpd_privs);
paul718e3742002-12-13 20:15:29 +0000416 cmd_init (1);
paulb21b19c2003-06-15 01:28:29 +0000417 vty_init (master);
paul718e3742002-12-13 20:15:29 +0000418 memory_init ();
419
420 /* BGP related initialization. */
421 bgp_init ();
422
423 /* Sort CLI commands. */
424 sort_node ();
425
426 /* Parse config file. */
hasso320ec102004-06-20 19:54:37 +0000427 vty_read_config (config_file, config_default);
paul718e3742002-12-13 20:15:29 +0000428
Paul Jakma876b8be2006-10-15 23:35:57 +0000429 /* Start execution only if not in dry-run mode */
430 if(dryrun)
431 return(0);
432
paul718e3742002-12-13 20:15:29 +0000433 /* Turn into daemon if daemon_mode is set. */
Stephen Hemminger372b3c72009-05-15 10:29:41 -0700434 if (daemon_mode && daemon (0, 0) < 0)
435 {
436 zlog_err("BGPd daemon failed: %s", strerror(errno));
437 return (1);
438 }
439
paul718e3742002-12-13 20:15:29 +0000440
441 /* Process ID file creation. */
442 pid_output (pid_file);
443
444 /* Make bgp vty socket. */
445 vty_serv_sock (vty_addr, vty_port, BGP_VTYSH_PATH);
446
447 /* Print banner. */
Paul Jakma3a02d1f2007-11-01 14:29:11 +0000448 zlog_notice ("BGPd %s starting: vty@%d, bgp@%s:%d", QUAGGA_VERSION,
Paul Jakma7e992e92007-11-13 09:32:23 +0000449 vty_port,
Paul Jakmab63e6082007-11-21 21:25:34 +0000450 (bm->address ? bm->address : "<all>"),
Paul Jakma7e992e92007-11-13 09:32:23 +0000451 bm->port);
paul718e3742002-12-13 20:15:29 +0000452
453 /* Start finite state machine, here we go! */
454 while (thread_fetch (master, &thread))
455 thread_call (&thread);
456
457 /* Not reached. */
paule8e19462006-01-19 20:16:55 +0000458 return (0);
paul718e3742002-12-13 20:15:29 +0000459}