]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_main.c
lib: hooks: support priority ordering & reversing
[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
23#include "vector.h"
718e3744 24#include "command.h"
25#include "getopt.h"
26#include "thread.h"
5e4fa164 27#include <lib/version.h>
718e3744 28#include "memory.h"
fc7948fa 29#include "memory_vty.h"
718e3744 30#include "prefix.h"
31#include "log.h"
edd7c245 32#include "privs.h"
2d75d052 33#include "sigevent.h"
228da428
CC
34#include "zclient.h"
35#include "routemap.h"
36#include "filter.h"
37#include "plist.h"
8196f13d 38#include "stream.h"
3f9c7369 39#include "queue.h"
6a69b354 40#include "vrf.h"
567b877d 41#include "bfd.h"
4f04a76b 42#include "libfrr.h"
718e3744 43
44#include "bgpd/bgpd.h"
45#include "bgpd/bgp_attr.h"
b2f0fa55 46#include "bgpd/bgp_route.h"
718e3744 47#include "bgpd/bgp_mplsvpn.h"
228da428
CC
48#include "bgpd/bgp_aspath.h"
49#include "bgpd/bgp_dump.h"
50#include "bgpd/bgp_route.h"
51#include "bgpd/bgp_nexthop.h"
52#include "bgpd/bgp_regex.h"
53#include "bgpd/bgp_clist.h"
54#include "bgpd/bgp_debug.h"
55#include "bgpd/bgp_filter.h"
8196f13d 56#include "bgpd/bgp_zebra.h"
718e3744 57
65efcfce 58#ifdef ENABLE_BGP_VNC
f8b6f499 59#include "bgpd/rfapi/rfapi_backend.h"
65efcfce
LB
60#endif
61
718e3744 62/* bgpd options, we use GNU getopt library. */
d62a17ae 63static const struct option longopts[] = {
64 {"bgp_port", required_argument, NULL, 'p'},
65 {"listenon", required_argument, NULL, 'l'},
66 {"retain", no_argument, NULL, 'r'},
67 {"no_kernel", no_argument, NULL, 'n'},
68 {"skip_runas", no_argument, NULL, 'S'},
69 {"ecmp", required_argument, NULL, 'e'},
70 {0}};
718e3744 71
2d75d052 72/* signal definitions */
d62a17ae 73void sighup(void);
74void sigint(void);
75void sigusr1(void);
2d75d052 76
d62a17ae 77static void bgp_exit(int);
78static void bgp_vrf_terminate(void);
228da428 79
d62a17ae 80static struct quagga_signal_t bgp_signals[] = {
81 {
82 .signal = SIGHUP,
83 .handler = &sighup,
84 },
85 {
86 .signal = SIGUSR1,
87 .handler = &sigusr1,
88 },
89 {
90 .signal = SIGINT,
91 .handler = &sigint,
92 },
93 {
94 .signal = SIGTERM,
95 .handler = &sigint,
96 },
2d75d052 97};
98
718e3744 99/* Route retain mode flag. */
372b3c70 100static int retain_mode = 0;
718e3744 101
edd7c245 102/* privileges */
d62a17ae 103static zebra_capabilities_t _caps_p[] = {
9d303b37 104 ZCAP_BIND, ZCAP_NET_RAW, ZCAP_NET_ADMIN,
edd7c245 105};
106
d62a17ae 107struct zebra_privs_t bgpd_privs = {
b2f36157 108#if defined(FRR_USER) && defined(FRR_GROUP)
d62a17ae 109 .user = FRR_USER,
110 .group = FRR_GROUP,
d81fadfd 111#endif
112#ifdef VTY_GROUP
d62a17ae 113 .vty_group = VTY_GROUP,
edd7c245 114#endif
d62a17ae 115 .caps_p = _caps_p,
116 .cap_num_p = array_size(_caps_p),
117 .cap_num_i = 0,
edd7c245 118};
119
eb05883f
DL
120static struct frr_daemon_info bgpd_di;
121
718e3744 122/* SIGHUP handler. */
d62a17ae 123void sighup(void)
718e3744 124{
d62a17ae 125 zlog_info("SIGHUP received");
718e3744 126
d62a17ae 127 /* Terminate all thread. */
128 bgp_terminate();
129 bgp_reset();
130 zlog_info("bgpd restarting!");
718e3744 131
d62a17ae 132 /* Reload config file. */
133 vty_read_config(bgpd_di.config_file, config_default);
718e3744 134
d62a17ae 135 /* Try to return to normal operation. */
718e3744 136}
137
138/* SIGINT handler. */
d62a17ae 139__attribute__((__noreturn__)) void sigint(void)
718e3744 140{
d62a17ae 141 zlog_notice("Terminating on signal");
718e3744 142
d62a17ae 143 if (!retain_mode) {
144 bgp_terminate();
145 if (bgpd_privs.user) /* NULL if skip_runas flag set */
146 zprivs_terminate(&bgpd_privs);
147 }
718e3744 148
d62a17ae 149 bgp_exit(0);
540766e7 150
d62a17ae 151 exit(0);
718e3744 152}
153
154/* SIGUSR1 handler. */
d62a17ae 155void sigusr1(void)
718e3744 156{
d62a17ae 157 zlog_rotate();
718e3744 158}
228da428
CC
159
160/*
161 Try to free up allocations we know about so that diagnostic tools such as
162 valgrind are able to better illuminate leaks.
163
164 Zebra route removal and protocol teardown are not meant to be done here.
165 For example, "retain_mode" may be set.
166*/
d62a17ae 167static __attribute__((__noreturn__)) void bgp_exit(int status)
228da428 168{
d62a17ae 169 struct bgp *bgp;
170 struct listnode *node, *nnode;
228da428 171
d62a17ae 172 /* it only makes sense for this to be called on a clean exit */
173 assert(status == 0);
228da428 174
d62a17ae 175 bfd_gbl_exit();
567b877d 176
d62a17ae 177 bgp_close();
1ff9a340 178
d62a17ae 179 if (retain_mode)
180 if_add_hook(IF_DELETE_HOOK, NULL);
ad4cbda1 181
d62a17ae 182 /* reverse bgp_master_init */
183 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
184 bgp_delete(bgp);
46abd3e3 185
d62a17ae 186 /* reverse bgp_dump_init */
187 bgp_dump_finish();
228da428 188
d62a17ae 189 /* reverse bgp_route_init */
190 bgp_route_finish();
228da428 191
d62a17ae 192 /* cleanup route maps */
193 bgp_route_map_terminate();
228da428 194
d62a17ae 195 /* reverse bgp_attr_init */
196 bgp_attr_finish();
7b8def58 197
d62a17ae 198 /* reverse access_list_init */
199 access_list_add_hook(NULL);
200 access_list_delete_hook(NULL);
201 access_list_reset();
228da428 202
d62a17ae 203 /* reverse bgp_filter_init */
204 as_list_add_hook(NULL);
205 as_list_delete_hook(NULL);
206 bgp_filter_reset();
228da428 207
d62a17ae 208 /* reverse prefix_list_init */
209 prefix_list_add_hook(NULL);
210 prefix_list_delete_hook(NULL);
211 prefix_list_reset();
228da428 212
d62a17ae 213 /* reverse community_list_init */
214 community_list_terminate(bgp_clist);
228da428 215
d62a17ae 216 bgp_vrf_terminate();
217 cmd_terminate();
218 vty_terminate();
65efcfce 219#if ENABLE_BGP_VNC
d62a17ae 220 vnc_zebra_destroy();
65efcfce 221#endif
d62a17ae 222 bgp_zebra_destroy();
228da428 223
d62a17ae 224 /* reverse bgp_master_init */
225 if (bm->master)
226 thread_master_free(bm->master);
228da428 227
d62a17ae 228 closezlog();
228da428 229
d62a17ae 230 list_delete(bm->bgp);
231 memset(bm, 0, sizeof(*bm));
46857efe 232
d62a17ae 233 if (bgp_debug_count())
234 log_memstats_stderr("bgpd");
235 exit(status);
228da428 236}
6b0655a2 237
d62a17ae 238static int bgp_vrf_new(struct vrf *vrf)
2fcc254e 239{
d62a17ae 240 if (BGP_DEBUG(zebra, ZEBRA))
241 zlog_debug("VRF Created: %s(%d)", vrf->name, vrf->vrf_id);
2fcc254e 242
d62a17ae 243 return 0;
2fcc254e
DS
244}
245
d62a17ae 246static int bgp_vrf_delete(struct vrf *vrf)
2fcc254e 247{
d62a17ae 248 if (BGP_DEBUG(zebra, ZEBRA))
249 zlog_debug("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id);
2fcc254e 250
d62a17ae 251 return 0;
2fcc254e
DS
252}
253
d62a17ae 254static int bgp_vrf_enable(struct vrf *vrf)
2fcc254e 255{
d62a17ae 256 struct bgp *bgp;
257 vrf_id_t old_vrf_id;
258
259 if (BGP_DEBUG(zebra, ZEBRA))
260 zlog_debug("VRF enable add %s id %d", vrf->name, vrf->vrf_id);
261
262 bgp = bgp_lookup_by_name(vrf->name);
263 if (bgp) {
264 old_vrf_id = bgp->vrf_id;
265 /* We have instance configured, link to VRF and make it "up". */
266 bgp_vrf_link(bgp, vrf);
267
268 /* Update any redistribute vrf bitmaps if the vrf_id changed */
269 if (old_vrf_id != bgp->vrf_id)
270 bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
271 bgp_instance_up(bgp);
272 }
273
274 return 0;
2fcc254e
DS
275}
276
d62a17ae 277static int bgp_vrf_disable(struct vrf *vrf)
2fcc254e 278{
d62a17ae 279 struct bgp *bgp;
280 vrf_id_t old_vrf_id;
281
282 if (vrf->vrf_id == VRF_DEFAULT)
283 return 0;
284
285 if (BGP_DEBUG(zebra, ZEBRA))
286 zlog_debug("VRF disable %s id %d", vrf->name, vrf->vrf_id);
287
288 bgp = bgp_lookup_by_name(vrf->name);
289 if (bgp) {
290 old_vrf_id = bgp->vrf_id;
291 /* We have instance configured, unlink from VRF and make it
292 * "down". */
293 bgp_vrf_unlink(bgp, vrf);
294 /* Update any redistribute vrf bitmaps if the vrf_id changed */
295 if (old_vrf_id != bgp->vrf_id)
296 bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
297 bgp_instance_down(bgp);
298 }
299
300 /* Note: This is a callback, the VRF will be deleted by the caller. */
301 return 0;
2fcc254e
DS
302}
303
d62a17ae 304static void bgp_vrf_init(void)
2fcc254e 305{
d62a17ae 306 vrf_init(bgp_vrf_new, bgp_vrf_enable, bgp_vrf_disable, bgp_vrf_delete);
2fcc254e
DS
307}
308
d62a17ae 309static void bgp_vrf_terminate(void)
021530c1 310{
d62a17ae 311 vrf_terminate();
021530c1 312}
313
d62a17ae 314FRR_DAEMON_INFO(bgpd, BGP, .vty_port = BGP_VTY_PORT,
4f04a76b 315
d62a17ae 316 .proghelp = "Implementation of the BGP routing protocol.",
4f04a76b 317
d62a17ae 318 .signals = bgp_signals, .n_signals = array_size(bgp_signals),
4f04a76b 319
d62a17ae 320 .privs = &bgpd_privs, )
4f04a76b 321
718e3744 322/* Main routine of bgpd. Treatment of argument and start bgp finite
323 state machine is handled at here. */
d62a17ae 324int main(int argc, char **argv)
718e3744 325{
d62a17ae 326 int opt;
327 int tmp_port;
328
329 int bgp_port = BGP_PORT_DEFAULT;
330 char *bgp_address = NULL;
331 int no_fib_flag = 0;
332 int skip_runas = 0;
333
334 frr_preinit(&bgpd_di, argc, argv);
335 frr_opt_add(
336 "p:l:rne:", longopts,
337 " -p, --bgp_port Set bgp protocol's port number\n"
338 " -l, --listenon Listen on specified address (implies -n)\n"
339 " -r, --retain When program terminates, retain added route by bgpd.\n"
340 " -n, --no_kernel Do not install route to kernel.\n"
341 " -S, --skip_runas Skip capabilities checks, and changing user and group IDs.\n"
342 " -e, --ecmp Specify ECMP to use.\n");
343
344 /* Command line argument treatment. */
345 while (1) {
346 opt = frr_getopt(argc, argv, 0);
347
348 if (opt == EOF)
349 break;
350
351 switch (opt) {
352 case 0:
353 break;
354 case 'p':
355 tmp_port = atoi(optarg);
356 if (tmp_port <= 0 || tmp_port > 0xffff)
357 bgp_port = BGP_PORT_DEFAULT;
358 else
359 bgp_port = tmp_port;
360 break;
361 case 'e':
362 multipath_num = atoi(optarg);
363 if (multipath_num > MULTIPATH_NUM
364 || multipath_num <= 0) {
365 zlog_err(
366 "Multipath Number specified must be less than %d and greater than 0",
367 MULTIPATH_NUM);
368 return 1;
369 }
370 break;
371 case 'r':
372 retain_mode = 1;
373 break;
374 case 'l':
375 bgp_address = optarg;
376 /* listenon implies -n */
377 /* fallthru */
378 case 'n':
379 no_fib_flag = 1;
380 break;
381 case 'S':
382 skip_runas = 1;
383 break;
384 default:
385 frr_help_exit(1);
386 break;
387 }
718e3744 388 }
d62a17ae 389 if (skip_runas)
390 memset(&bgpd_privs, 0, sizeof(bgpd_privs));
718e3744 391
d62a17ae 392 /* BGP master init. */
393 bgp_master_init(frr_init());
394 bm->port = bgp_port;
395 bm->address = bgp_address;
396 if (no_fib_flag)
397 bgp_option_set(BGP_OPT_NO_FIB);
87d4a781 398
d62a17ae 399 /* Initializations. */
400 bgp_vrf_init();
718e3744 401
d62a17ae 402 /* BGP related initialization. */
403 bgp_init();
718e3744 404
d62a17ae 405 snprintf(bgpd_di.startinfo, sizeof(bgpd_di.startinfo), ", bgp@%s:%d",
406 (bm->address ? bm->address : "<all>"), bm->port);
718e3744 407
d62a17ae 408 frr_config_fork();
409 frr_run(bm->master);
718e3744 410
d62a17ae 411 /* Not reached. */
412 return (0);
718e3744 413}