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