]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_main.c
bgpd: skip run as option can be reused
[mirror_frr.git] / bgpd / bgp_main.c
CommitLineData
718e3744 1/* 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"
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. */
ac4d0be5 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 */
ac4d0be5 73void sighup(void);
74void sigint(void);
75void sigusr1(void);
2d75d052 76
ac4d0be5 77static void bgp_exit(int);
78static void bgp_vrf_terminate(void);
228da428 79
ac4d0be5 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 */
ac4d0be5 103static zebra_capabilities_t _caps_p[] = {
104 ZCAP_BIND, ZCAP_NET_RAW, ZCAP_NET_ADMIN,
edd7c245 105};
106
ac4d0be5 107struct zebra_privs_t bgpd_privs = {
b2f36157 108#if defined(FRR_USER) && defined(FRR_GROUP)
ac4d0be5 109 .user = FRR_USER,
110 .group = FRR_GROUP,
d81fadfd 111#endif
112#ifdef VTY_GROUP
ac4d0be5 113 .vty_group = VTY_GROUP,
edd7c245 114#endif
ac4d0be5 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. */
ac4d0be5 123void sighup(void)
718e3744 124{
ac4d0be5 125 zlog_info("SIGHUP received");
718e3744 126
ac4d0be5 127 /* Terminate all thread. */
128 bgp_terminate();
129 bgp_reset();
130 zlog_info("bgpd restarting!");
718e3744 131
ac4d0be5 132 /* Reload config file. */
133 vty_read_config(bgpd_di.config_file, config_default);
718e3744 134
ac4d0be5 135 /* Try to return to normal operation. */
718e3744 136}
137
138/* SIGINT handler. */
ac4d0be5 139__attribute__((__noreturn__)) void sigint(void)
718e3744 140{
ac4d0be5 141 zlog_notice("Terminating on signal");
718e3744 142
ac4d0be5 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
ac4d0be5 149 bgp_exit(0);
540766e7 150
ac4d0be5 151 exit(0);
718e3744 152}
153
154/* SIGUSR1 handler. */
ac4d0be5 155void sigusr1(void)
718e3744 156{
ac4d0be5 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*/
ac4d0be5 167static __attribute__((__noreturn__)) void bgp_exit(int status)
228da428 168{
ac4d0be5 169 struct bgp *bgp;
170 struct listnode *node, *nnode;
228da428 171
ac4d0be5 172 /* it only makes sense for this to be called on a clean exit */
173 assert(status == 0);
228da428 174
ac4d0be5 175 bfd_gbl_exit();
567b877d 176
ac4d0be5 177 bgp_close();
1ff9a340 178
ac4d0be5 179 if (retain_mode)
180 if_add_hook(IF_DELETE_HOOK, NULL);
ad4cbda1 181
ac4d0be5 182 /* reverse bgp_master_init */
183 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
184 bgp_delete(bgp);
185 list_free(bm->bgp);
46abd3e3 186
ac4d0be5 187 /* reverse bgp_dump_init */
188 bgp_dump_finish();
228da428 189
ac4d0be5 190 /* reverse bgp_route_init */
191 bgp_route_finish();
228da428 192
ac4d0be5 193 /* cleanup route maps */
194 bgp_route_map_terminate();
228da428 195
ac4d0be5 196 /* reverse bgp_attr_init */
197 bgp_attr_finish();
7b8def58 198
ac4d0be5 199 /* reverse access_list_init */
200 access_list_add_hook(NULL);
201 access_list_delete_hook(NULL);
202 access_list_reset();
228da428 203
ac4d0be5 204 /* reverse bgp_filter_init */
205 as_list_add_hook(NULL);
206 as_list_delete_hook(NULL);
207 bgp_filter_reset();
228da428 208
ac4d0be5 209 /* reverse prefix_list_init */
210 prefix_list_add_hook(NULL);
211 prefix_list_delete_hook(NULL);
212 prefix_list_reset();
228da428 213
ac4d0be5 214 /* reverse community_list_init */
215 community_list_terminate(bgp_clist);
228da428 216
ac4d0be5 217 bgp_vrf_terminate();
218 cmd_terminate();
219 vty_terminate();
65efcfce 220#if ENABLE_BGP_VNC
ac4d0be5 221 vnc_zebra_destroy();
65efcfce 222#endif
ac4d0be5 223 bgp_zebra_destroy();
224 if (bgp_nexthop_buf)
225 stream_free(bgp_nexthop_buf);
226 if (bgp_ifindices_buf)
227 stream_free(bgp_ifindices_buf);
228da428 228
ac4d0be5 229 /* reverse bgp_master_init */
230 if (bm->master)
231 thread_master_free(bm->master);
228da428 232
ac4d0be5 233 closezlog();
228da428 234
ac4d0be5 235 memset(bm, 0, sizeof(*bm));
46857efe 236
ac4d0be5 237 if (bgp_debug_count())
238 log_memstats_stderr("bgpd");
239 exit(status);
228da428 240}
6b0655a2 241
ac4d0be5 242static int bgp_vrf_new(struct vrf *vrf)
2fcc254e 243{
ac4d0be5 244 if (BGP_DEBUG(zebra, ZEBRA))
245 zlog_debug("VRF Created: %s(%d)", vrf->name, vrf->vrf_id);
2fcc254e 246
ac4d0be5 247 return 0;
2fcc254e
DS
248}
249
ac4d0be5 250static int bgp_vrf_delete(struct vrf *vrf)
2fcc254e 251{
ac4d0be5 252 if (BGP_DEBUG(zebra, ZEBRA))
253 zlog_debug("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id);
2fcc254e 254
ac4d0be5 255 return 0;
2fcc254e
DS
256}
257
ac4d0be5 258static int bgp_vrf_enable(struct vrf *vrf)
2fcc254e 259{
ac4d0be5 260 struct bgp *bgp;
261 vrf_id_t old_vrf_id;
262
263 if (BGP_DEBUG(zebra, ZEBRA))
264 zlog_debug("VRF enable add %s id %d", vrf->name, vrf->vrf_id);
265
266 bgp = bgp_lookup_by_name(vrf->name);
267 if (bgp) {
268 old_vrf_id = bgp->vrf_id;
269 /* We have instance configured, link to VRF and make it "up". */
270 bgp_vrf_link(bgp, vrf);
271
272 /* Update any redistribute vrf bitmaps if the vrf_id changed */
273 if (old_vrf_id != bgp->vrf_id)
274 bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
275 bgp_instance_up(bgp);
276 }
277
278 return 0;
2fcc254e
DS
279}
280
ac4d0be5 281static int bgp_vrf_disable(struct vrf *vrf)
2fcc254e 282{
ac4d0be5 283 struct bgp *bgp;
284 vrf_id_t old_vrf_id;
285
286 if (vrf->vrf_id == VRF_DEFAULT)
287 return 0;
288
289 if (BGP_DEBUG(zebra, ZEBRA))
290 zlog_debug("VRF disable %s id %d", vrf->name, vrf->vrf_id);
291
292 bgp = bgp_lookup_by_name(vrf->name);
293 if (bgp) {
294 old_vrf_id = bgp->vrf_id;
295 /* We have instance configured, unlink from VRF and make it
296 * "down". */
297 bgp_vrf_unlink(bgp, vrf);
298 /* Update any redistribute vrf bitmaps if the vrf_id changed */
299 if (old_vrf_id != bgp->vrf_id)
300 bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
301 bgp_instance_down(bgp);
302 }
303
304 /* Note: This is a callback, the VRF will be deleted by the caller. */
305 return 0;
2fcc254e
DS
306}
307
ac4d0be5 308static void bgp_vrf_init(void)
2fcc254e 309{
ac4d0be5 310 vrf_add_hook(VRF_NEW_HOOK, bgp_vrf_new);
311 vrf_add_hook(VRF_ENABLE_HOOK, bgp_vrf_enable);
312 vrf_add_hook(VRF_DISABLE_HOOK, bgp_vrf_disable);
313 vrf_add_hook(VRF_DELETE_HOOK, bgp_vrf_delete);
2fcc254e 314
ac4d0be5 315 vrf_init();
2fcc254e
DS
316}
317
ac4d0be5 318static void bgp_vrf_terminate(void)
021530c1 319{
ac4d0be5 320 vrf_add_hook(VRF_NEW_HOOK, NULL);
321 vrf_add_hook(VRF_ENABLE_HOOK, NULL);
322 vrf_add_hook(VRF_DISABLE_HOOK, NULL);
323 vrf_add_hook(VRF_DELETE_HOOK, NULL);
021530c1 324
ac4d0be5 325 vrf_terminate();
021530c1 326}
327
ac4d0be5 328FRR_DAEMON_INFO(bgpd, BGP, .vty_port = BGP_VTY_PORT,
4f04a76b 329
ac4d0be5 330 .proghelp = "Implementation of the BGP routing protocol.",
4f04a76b 331
ac4d0be5 332 .signals = bgp_signals, .n_signals = array_size(bgp_signals),
4f04a76b 333
ac4d0be5 334 .privs = &bgpd_privs, )
4f04a76b 335
718e3744 336/* Main routine of bgpd. Treatment of argument and start bgp finite
337 state machine is handled at here. */
ac4d0be5 338int main(int argc, char **argv)
718e3744 339{
ac4d0be5 340 int opt;
341 int tmp_port;
342
343 int bgp_port = BGP_PORT_DEFAULT;
344 char *bgp_address = NULL;
345 int no_fib_flag = 0;
346 int skip_runas = 0;
347
348 frr_preinit(&bgpd_di, argc, argv);
349 frr_opt_add(
acb1655d 350 "p:l:rSne:", longopts,
ac4d0be5 351 " -p, --bgp_port Set bgp protocol's port number\n"
352 " -l, --listenon Listen on specified address (implies -n)\n"
353 " -r, --retain When program terminates, retain added route by bgpd.\n"
354 " -n, --no_kernel Do not install route to kernel.\n"
355 " -S, --skip_runas Skip capabilities checks, and changing user and group IDs.\n"
356 " -e, --ecmp Specify ECMP to use.\n");
357
358 /* Command line argument treatment. */
359 while (1) {
360 opt = frr_getopt(argc, argv, 0);
361
362 if (opt == EOF)
363 break;
364
365 switch (opt) {
366 case 0:
367 break;
368 case 'p':
369 tmp_port = atoi(optarg);
370 if (tmp_port <= 0 || tmp_port > 0xffff)
371 bgp_port = BGP_PORT_DEFAULT;
372 else
373 bgp_port = tmp_port;
374 break;
375 case 'e':
376 multipath_num = atoi(optarg);
377 if (multipath_num > MULTIPATH_NUM
378 || multipath_num <= 0) {
379 zlog_err(
380 "Multipath Number specified must be less than %d and greater than 0",
381 MULTIPATH_NUM);
382 return 1;
383 }
384 break;
385 case 'r':
386 retain_mode = 1;
387 break;
388 case 'l':
389 bgp_address = optarg;
390 /* listenon implies -n */
391 case 'n':
392 no_fib_flag = 1;
393 break;
394 case 'S':
395 skip_runas = 1;
396 break;
397 default:
398 frr_help_exit(1);
399 break;
400 }
718e3744 401 }
ac4d0be5 402 if (skip_runas)
403 memset(&bgpd_privs, 0, sizeof(bgpd_privs));
718e3744 404
ac4d0be5 405 /* BGP master init. */
406 bgp_master_init(frr_init());
407 bm->port = bgp_port;
408 bm->address = bgp_address;
409 if (no_fib_flag)
410 bgp_option_set(BGP_OPT_NO_FIB);
87d4a781 411
ac4d0be5 412 /* Initializations. */
413 bgp_vrf_init();
718e3744 414
ac4d0be5 415 /* BGP related initialization. */
416 bgp_init();
718e3744 417
ac4d0be5 418 snprintf(bgpd_di.startinfo, sizeof(bgpd_di.startinfo), ", bgp@%s:%d",
419 (bm->address ? bm->address : "<all>"), bm->port);
718e3744 420
ac4d0be5 421 frr_config_fork();
422 frr_run(bm->master);
718e3744 423
ac4d0be5 424 /* Not reached. */
425 return (0);
718e3744 426}