]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_main.c
Merge pull request #3007 from pacovn/static_analysis__shadow_variables2
[mirror_frr.git] / bgpd / bgp_main.c
CommitLineData
718e3744 1/* Main routine of bgpd.
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
718e3744 20
21#include <zebra.h>
22
03014d48 23#include <pthread.h>
718e3744 24#include "vector.h"
718e3744 25#include "command.h"
26#include "getopt.h"
27#include "thread.h"
5e4fa164 28#include <lib/version.h>
718e3744 29#include "memory.h"
fc7948fa 30#include "memory_vty.h"
718e3744 31#include "prefix.h"
32#include "log.h"
edd7c245 33#include "privs.h"
2d75d052 34#include "sigevent.h"
228da428
CC
35#include "zclient.h"
36#include "routemap.h"
37#include "filter.h"
38#include "plist.h"
8196f13d 39#include "stream.h"
3f9c7369 40#include "queue.h"
6a69b354 41#include "vrf.h"
567b877d 42#include "bfd.h"
4f04a76b 43#include "libfrr.h"
61cf4b37 44#include "ns.h"
718e3744 45
46#include "bgpd/bgpd.h"
47#include "bgpd/bgp_attr.h"
b2f0fa55 48#include "bgpd/bgp_route.h"
718e3744 49#include "bgpd/bgp_mplsvpn.h"
228da428
CC
50#include "bgpd/bgp_aspath.h"
51#include "bgpd/bgp_dump.h"
52#include "bgpd/bgp_route.h"
53#include "bgpd/bgp_nexthop.h"
54#include "bgpd/bgp_regex.h"
55#include "bgpd/bgp_clist.h"
56#include "bgpd/bgp_debug.h"
14454c9f 57#include "bgpd/bgp_errors.h"
228da428 58#include "bgpd/bgp_filter.h"
8196f13d 59#include "bgpd/bgp_zebra.h"
d3ecc69e 60#include "bgpd/bgp_packet.h"
03014d48 61#include "bgpd/bgp_keepalives.h"
61cf4b37 62#include "bgpd/bgp_network.h"
def31c13 63#include "bgpd/bgp_errors.h"
718e3744 64
65efcfce 65#ifdef ENABLE_BGP_VNC
f8b6f499 66#include "bgpd/rfapi/rfapi_backend.h"
65efcfce
LB
67#endif
68
718e3744 69/* bgpd options, we use GNU getopt library. */
d62a17ae 70static const struct option longopts[] = {
71 {"bgp_port", required_argument, NULL, 'p'},
72 {"listenon", required_argument, NULL, 'l'},
c8dde10f
QY
73#if CONFDATE > 20190521
74 CPP_NOTICE("-r / --retain has reached deprecation EOL, remove")
75#endif
d62a17ae 76 {"retain", no_argument, NULL, 'r'},
77 {"no_kernel", no_argument, NULL, 'n'},
78 {"skip_runas", no_argument, NULL, 'S'},
79 {"ecmp", required_argument, NULL, 'e'},
80 {0}};
718e3744 81
2d75d052 82/* signal definitions */
d62a17ae 83void sighup(void);
84void sigint(void);
85void sigusr1(void);
2d75d052 86
d62a17ae 87static void bgp_exit(int);
88static void bgp_vrf_terminate(void);
228da428 89
d62a17ae 90static struct quagga_signal_t bgp_signals[] = {
91 {
92 .signal = SIGHUP,
93 .handler = &sighup,
94 },
95 {
96 .signal = SIGUSR1,
97 .handler = &sigusr1,
98 },
99 {
100 .signal = SIGINT,
101 .handler = &sigint,
102 },
103 {
104 .signal = SIGTERM,
105 .handler = &sigint,
106 },
2d75d052 107};
108
edd7c245 109/* privileges */
996c9314
LB
110static zebra_capabilities_t _caps_p[] = {ZCAP_BIND, ZCAP_NET_RAW,
111 ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN};
edd7c245 112
d62a17ae 113struct zebra_privs_t bgpd_privs = {
b2f36157 114#if defined(FRR_USER) && defined(FRR_GROUP)
d62a17ae 115 .user = FRR_USER,
116 .group = FRR_GROUP,
d81fadfd 117#endif
118#ifdef VTY_GROUP
d62a17ae 119 .vty_group = VTY_GROUP,
edd7c245 120#endif
d62a17ae 121 .caps_p = _caps_p,
122 .cap_num_p = array_size(_caps_p),
123 .cap_num_i = 0,
edd7c245 124};
125
eb05883f
DL
126static struct frr_daemon_info bgpd_di;
127
718e3744 128/* SIGHUP handler. */
d62a17ae 129void sighup(void)
718e3744 130{
d62a17ae 131 zlog_info("SIGHUP received");
718e3744 132
d62a17ae 133 /* Terminate all thread. */
134 bgp_terminate();
135 bgp_reset();
136 zlog_info("bgpd restarting!");
718e3744 137
d62a17ae 138 /* Reload config file. */
139 vty_read_config(bgpd_di.config_file, config_default);
718e3744 140
d62a17ae 141 /* Try to return to normal operation. */
718e3744 142}
143
144/* SIGINT handler. */
d62a17ae 145__attribute__((__noreturn__)) void sigint(void)
718e3744 146{
d62a17ae 147 zlog_notice("Terminating on signal");
97b4a0ec
LB
148 assert(bm->terminating == false);
149 bm->terminating = true; /* global flag that shutting down */
718e3744 150
c8dde10f 151 bgp_terminate();
718e3744 152
d62a17ae 153 bgp_exit(0);
540766e7 154
d62a17ae 155 exit(0);
718e3744 156}
157
158/* SIGUSR1 handler. */
d62a17ae 159void sigusr1(void)
718e3744 160{
d62a17ae 161 zlog_rotate();
718e3744 162}
228da428
CC
163
164/*
165 Try to free up allocations we know about so that diagnostic tools such as
166 valgrind are able to better illuminate leaks.
167
168 Zebra route removal and protocol teardown are not meant to be done here.
169 For example, "retain_mode" may be set.
170*/
d62a17ae 171static __attribute__((__noreturn__)) void bgp_exit(int status)
228da428 172{
0e42e319 173 struct bgp *bgp, *bgp_default;
d62a17ae 174 struct listnode *node, *nnode;
228da428 175
d62a17ae 176 /* it only makes sense for this to be called on a clean exit */
177 assert(status == 0);
228da428 178
03951374
DL
179 frr_early_fini();
180
d62a17ae 181 bfd_gbl_exit();
567b877d 182
d62a17ae 183 bgp_close();
1ff9a340 184
0e42e319
DS
185 bgp_default = bgp_get_default();
186
d62a17ae 187 /* reverse bgp_master_init */
0e42e319
DS
188 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
189 if (bgp_default == bgp)
190 continue;
d62a17ae 191 bgp_delete(bgp);
0e42e319 192 }
1f4b2cce
DS
193 if (bgp_default)
194 bgp_delete(bgp_default);
46abd3e3 195
d62a17ae 196 /* reverse bgp_dump_init */
197 bgp_dump_finish();
228da428 198
d62a17ae 199 /* reverse bgp_route_init */
200 bgp_route_finish();
228da428 201
d62a17ae 202 /* cleanup route maps */
203 bgp_route_map_terminate();
228da428 204
d62a17ae 205 /* reverse bgp_attr_init */
206 bgp_attr_finish();
7b8def58 207
2d4ee774
QY
208 /* stop pthreads */
209 bgp_pthreads_finish();
210
d62a17ae 211 /* reverse access_list_init */
212 access_list_add_hook(NULL);
213 access_list_delete_hook(NULL);
214 access_list_reset();
228da428 215
d62a17ae 216 /* reverse bgp_filter_init */
217 as_list_add_hook(NULL);
218 as_list_delete_hook(NULL);
219 bgp_filter_reset();
228da428 220
d62a17ae 221 /* reverse prefix_list_init */
222 prefix_list_add_hook(NULL);
223 prefix_list_delete_hook(NULL);
224 prefix_list_reset();
228da428 225
d62a17ae 226 /* reverse community_list_init */
227 community_list_terminate(bgp_clist);
228da428 228
d62a17ae 229 bgp_vrf_terminate();
65efcfce 230#if ENABLE_BGP_VNC
d62a17ae 231 vnc_zebra_destroy();
65efcfce 232#endif
d62a17ae 233 bgp_zebra_destroy();
228da428 234
3d57c994 235 bf_free(bm->rd_idspace);
affe9e99 236 list_delete_and_null(&bm->bgp);
d62a17ae 237 memset(bm, 0, sizeof(*bm));
46857efe 238
03951374 239 frr_fini();
d62a17ae 240 exit(status);
228da428 241}
6b0655a2 242
d62a17ae 243static int bgp_vrf_new(struct vrf *vrf)
2fcc254e 244{
d62a17ae 245 if (BGP_DEBUG(zebra, ZEBRA))
a8bf7d9c 246 zlog_debug("VRF Created: %s(%u)", vrf->name, vrf->vrf_id);
2fcc254e 247
d62a17ae 248 return 0;
2fcc254e
DS
249}
250
d62a17ae 251static int bgp_vrf_delete(struct vrf *vrf)
2fcc254e 252{
d62a17ae 253 if (BGP_DEBUG(zebra, ZEBRA))
a8bf7d9c 254 zlog_debug("VRF Deletion: %s(%u)", vrf->name, vrf->vrf_id);
2fcc254e 255
d62a17ae 256 return 0;
2fcc254e
DS
257}
258
d62a17ae 259static int bgp_vrf_enable(struct vrf *vrf)
2fcc254e 260{
d62a17ae 261 struct bgp *bgp;
262 vrf_id_t old_vrf_id;
263
264 if (BGP_DEBUG(zebra, ZEBRA))
a8bf7d9c 265 zlog_debug("VRF enable add %s id %u", vrf->name, vrf->vrf_id);
d62a17ae 266
267 bgp = bgp_lookup_by_name(vrf->name);
268 if (bgp) {
9a8bdf1c
PG
269 if (bgp->name && strmatch(vrf->name, VRF_DEFAULT_NAME)) {
270 XFREE(MTYPE_BGP, bgp->name);
271 bgp->name = NULL;
272 XFREE(MTYPE_BGP, bgp->name_pretty);
273 bgp->name_pretty = XSTRDUP(MTYPE_BGP, "VRF default");
274 }
d62a17ae 275 old_vrf_id = bgp->vrf_id;
276 /* We have instance configured, link to VRF and make it "up". */
277 bgp_vrf_link(bgp, vrf);
278
e5619c28 279 bgp_handle_socket(bgp, vrf, old_vrf_id, true);
d62a17ae 280 /* Update any redistribute vrf bitmaps if the vrf_id changed */
281 if (old_vrf_id != bgp->vrf_id)
282 bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
283 bgp_instance_up(bgp);
ddb5b488
PZ
284 vpn_leak_zebra_vrf_label_update(bgp, AFI_IP);
285 vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6);
e504cf3b
DS
286 vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP,
287 bgp_get_default(), bgp);
288 vpn_leak_postchange(BGP_VPN_POLICY_DIR_FROMVPN, AFI_IP,
289 bgp_get_default(), bgp);
290 vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP6,
291 bgp_get_default(), bgp);
292 vpn_leak_postchange(BGP_VPN_POLICY_DIR_FROMVPN, AFI_IP6,
293 bgp_get_default(), bgp);
d62a17ae 294 }
295
296 return 0;
2fcc254e
DS
297}
298
d62a17ae 299static int bgp_vrf_disable(struct vrf *vrf)
2fcc254e 300{
d62a17ae 301 struct bgp *bgp;
302 vrf_id_t old_vrf_id;
303
304 if (vrf->vrf_id == VRF_DEFAULT)
305 return 0;
306
307 if (BGP_DEBUG(zebra, ZEBRA))
308 zlog_debug("VRF disable %s id %d", vrf->name, vrf->vrf_id);
309
310 bgp = bgp_lookup_by_name(vrf->name);
311 if (bgp) {
ddb5b488
PZ
312
313 vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP);
314 vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP6);
e504cf3b
DS
315 vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP,
316 bgp_get_default(), bgp);
317 vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, AFI_IP,
318 bgp_get_default(), bgp);
319 vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP6,
320 bgp_get_default(), bgp);
321 vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, AFI_IP6,
322 bgp_get_default(), bgp);
ddb5b488 323
d62a17ae 324 old_vrf_id = bgp->vrf_id;
e5619c28 325 bgp_handle_socket(bgp, vrf, VRF_UNKNOWN, false);
d62a17ae 326 /* We have instance configured, unlink from VRF and make it
327 * "down". */
328 bgp_vrf_unlink(bgp, vrf);
329 /* Update any redistribute vrf bitmaps if the vrf_id changed */
330 if (old_vrf_id != bgp->vrf_id)
331 bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
332 bgp_instance_down(bgp);
333 }
334
335 /* Note: This is a callback, the VRF will be deleted by the caller. */
336 return 0;
2fcc254e
DS
337}
338
d62a17ae 339static void bgp_vrf_init(void)
2fcc254e 340{
ecbc5a37
PG
341 vrf_init(bgp_vrf_new, bgp_vrf_enable, bgp_vrf_disable,
342 bgp_vrf_delete, NULL);
2fcc254e
DS
343}
344
d62a17ae 345static void bgp_vrf_terminate(void)
021530c1 346{
d62a17ae 347 vrf_terminate();
021530c1 348}
349
d62a17ae 350FRR_DAEMON_INFO(bgpd, BGP, .vty_port = BGP_VTY_PORT,
4f04a76b 351
d62a17ae 352 .proghelp = "Implementation of the BGP routing protocol.",
4f04a76b 353
d62a17ae 354 .signals = bgp_signals, .n_signals = array_size(bgp_signals),
4f04a76b 355
d62a17ae 356 .privs = &bgpd_privs, )
4f04a76b 357
c8dde10f
QY
358#if CONFDATE > 20190521
359CPP_NOTICE("-r / --retain has reached deprecation EOL, remove")
360#endif
361#define DEPRECATED_OPTIONS "r"
362
718e3744 363/* Main routine of bgpd. Treatment of argument and start bgp finite
364 state machine is handled at here. */
d62a17ae 365int main(int argc, char **argv)
718e3744 366{
d62a17ae 367 int opt;
368 int tmp_port;
369
370 int bgp_port = BGP_PORT_DEFAULT;
371 char *bgp_address = NULL;
372 int no_fib_flag = 0;
373 int skip_runas = 0;
374
375 frr_preinit(&bgpd_di, argc, argv);
376 frr_opt_add(
c8dde10f 377 "p:l:Sne:" DEPRECATED_OPTIONS, longopts,
580f8636 378 " -p, --bgp_port Set BGP listen port number (0 means do not listen).\n"
d62a17ae 379 " -l, --listenon Listen on specified address (implies -n)\n"
d62a17ae 380 " -n, --no_kernel Do not install route to kernel.\n"
381 " -S, --skip_runas Skip capabilities checks, and changing user and group IDs.\n"
382 " -e, --ecmp Specify ECMP to use.\n");
383
384 /* Command line argument treatment. */
385 while (1) {
386 opt = frr_getopt(argc, argv, 0);
387
c8dde10f
QY
388 if (opt && opt < 128 && strchr(DEPRECATED_OPTIONS, opt)) {
389 fprintf(stderr,
390 "The -%c option no longer exists.\nPlease refer to the manual.\n",
391 opt);
392 continue;
393 }
394
d62a17ae 395 if (opt == EOF)
396 break;
397
398 switch (opt) {
399 case 0:
400 break;
401 case 'p':
402 tmp_port = atoi(optarg);
580f8636 403 if (tmp_port < 0 || tmp_port > 0xffff)
d62a17ae 404 bgp_port = BGP_PORT_DEFAULT;
405 else
406 bgp_port = tmp_port;
407 break;
408 case 'e':
409 multipath_num = atoi(optarg);
410 if (multipath_num > MULTIPATH_NUM
411 || multipath_num <= 0) {
af4c2728 412 flog_err(
14454c9f 413 BGP_ERR_MULTIPATH,
d62a17ae 414 "Multipath Number specified must be less than %d and greater than 0",
415 MULTIPATH_NUM);
416 return 1;
417 }
418 break;
d62a17ae 419 case 'l':
420 bgp_address = optarg;
421 /* listenon implies -n */
422 /* fallthru */
423 case 'n':
424 no_fib_flag = 1;
425 break;
426 case 'S':
427 skip_runas = 1;
428 break;
429 default:
430 frr_help_exit(1);
431 break;
432 }
718e3744 433 }
d62a17ae 434 if (skip_runas)
435 memset(&bgpd_privs, 0, sizeof(bgpd_privs));
718e3744 436
d62a17ae 437 /* BGP master init. */
438 bgp_master_init(frr_init());
439 bm->port = bgp_port;
580f8636 440 if (bgp_port == 0)
441 bgp_option_set(BGP_OPT_NO_LISTEN);
d62a17ae 442 bm->address = bgp_address;
443 if (no_fib_flag)
444 bgp_option_set(BGP_OPT_NO_FIB);
87d4a781 445
def31c13 446 bgp_error_init();
d62a17ae 447 /* Initializations. */
448 bgp_vrf_init();
718e3744 449
d62a17ae 450 /* BGP related initialization. */
451 bgp_init();
718e3744 452
d62a17ae 453 snprintf(bgpd_di.startinfo, sizeof(bgpd_di.startinfo), ", bgp@%s:%d",
454 (bm->address ? bm->address : "<all>"), bm->port);
718e3744 455
d62a17ae 456 frr_config_fork();
2d4ee774 457 /* must be called after fork() */
419dfe6a 458 bgp_pthreads_run();
d62a17ae 459 frr_run(bm->master);
718e3744 460
d62a17ae 461 /* Not reached. */
462 return (0);
718e3744 463}