]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_main.c
*: reindent
[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 "vector.h"
24 #include "command.h"
25 #include "getopt.h"
26 #include "thread.h"
27 #include <lib/version.h>
28 #include "memory.h"
29 #include "memory_vty.h"
30 #include "prefix.h"
31 #include "log.h"
32 #include "privs.h"
33 #include "sigevent.h"
34 #include "zclient.h"
35 #include "routemap.h"
36 #include "filter.h"
37 #include "plist.h"
38 #include "stream.h"
39 #include "queue.h"
40 #include "vrf.h"
41 #include "bfd.h"
42 #include "libfrr.h"
43
44 #include "bgpd/bgpd.h"
45 #include "bgpd/bgp_attr.h"
46 #include "bgpd/bgp_route.h"
47 #include "bgpd/bgp_mplsvpn.h"
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"
56 #include "bgpd/bgp_zebra.h"
57
58 #ifdef ENABLE_BGP_VNC
59 #include "bgpd/rfapi/rfapi_backend.h"
60 #endif
61
62 /* bgpd options, we use GNU getopt library. */
63 static 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}};
71
72 /* signal definitions */
73 void sighup(void);
74 void sigint(void);
75 void sigusr1(void);
76
77 static void bgp_exit(int);
78 static void bgp_vrf_terminate(void);
79
80 static 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 },
97 };
98
99 /* Route retain mode flag. */
100 static int retain_mode = 0;
101
102 /* privileges */
103 static zebra_capabilities_t _caps_p[] = {
104 ZCAP_BIND, ZCAP_NET_RAW, ZCAP_NET_ADMIN,
105 };
106
107 struct zebra_privs_t bgpd_privs = {
108 #if defined(FRR_USER) && defined(FRR_GROUP)
109 .user = FRR_USER,
110 .group = FRR_GROUP,
111 #endif
112 #ifdef VTY_GROUP
113 .vty_group = VTY_GROUP,
114 #endif
115 .caps_p = _caps_p,
116 .cap_num_p = array_size(_caps_p),
117 .cap_num_i = 0,
118 };
119
120 static struct frr_daemon_info bgpd_di;
121
122 /* SIGHUP handler. */
123 void sighup(void)
124 {
125 zlog_info("SIGHUP received");
126
127 /* Terminate all thread. */
128 bgp_terminate();
129 bgp_reset();
130 zlog_info("bgpd restarting!");
131
132 /* Reload config file. */
133 vty_read_config(bgpd_di.config_file, config_default);
134
135 /* Try to return to normal operation. */
136 }
137
138 /* SIGINT handler. */
139 __attribute__((__noreturn__)) void sigint(void)
140 {
141 zlog_notice("Terminating on signal");
142
143 if (!retain_mode) {
144 bgp_terminate();
145 if (bgpd_privs.user) /* NULL if skip_runas flag set */
146 zprivs_terminate(&bgpd_privs);
147 }
148
149 bgp_exit(0);
150
151 exit(0);
152 }
153
154 /* SIGUSR1 handler. */
155 void sigusr1(void)
156 {
157 zlog_rotate();
158 }
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 */
167 static __attribute__((__noreturn__)) void bgp_exit(int status)
168 {
169 struct bgp *bgp;
170 struct listnode *node, *nnode;
171
172 /* it only makes sense for this to be called on a clean exit */
173 assert(status == 0);
174
175 bfd_gbl_exit();
176
177 bgp_close();
178
179 if (retain_mode)
180 if_add_hook(IF_DELETE_HOOK, NULL);
181
182 /* reverse bgp_master_init */
183 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
184 bgp_delete(bgp);
185
186 /* reverse bgp_dump_init */
187 bgp_dump_finish();
188
189 /* reverse bgp_route_init */
190 bgp_route_finish();
191
192 /* cleanup route maps */
193 bgp_route_map_terminate();
194
195 /* reverse bgp_attr_init */
196 bgp_attr_finish();
197
198 /* reverse access_list_init */
199 access_list_add_hook(NULL);
200 access_list_delete_hook(NULL);
201 access_list_reset();
202
203 /* reverse bgp_filter_init */
204 as_list_add_hook(NULL);
205 as_list_delete_hook(NULL);
206 bgp_filter_reset();
207
208 /* reverse prefix_list_init */
209 prefix_list_add_hook(NULL);
210 prefix_list_delete_hook(NULL);
211 prefix_list_reset();
212
213 /* reverse community_list_init */
214 community_list_terminate(bgp_clist);
215
216 bgp_vrf_terminate();
217 cmd_terminate();
218 vty_terminate();
219 #if ENABLE_BGP_VNC
220 vnc_zebra_destroy();
221 #endif
222 bgp_zebra_destroy();
223
224 /* reverse bgp_master_init */
225 if (bm->master)
226 thread_master_free(bm->master);
227
228 closezlog();
229
230 list_delete(bm->bgp);
231 memset(bm, 0, sizeof(*bm));
232
233 if (bgp_debug_count())
234 log_memstats_stderr("bgpd");
235 exit(status);
236 }
237
238 static int bgp_vrf_new(struct vrf *vrf)
239 {
240 if (BGP_DEBUG(zebra, ZEBRA))
241 zlog_debug("VRF Created: %s(%d)", vrf->name, vrf->vrf_id);
242
243 return 0;
244 }
245
246 static int bgp_vrf_delete(struct vrf *vrf)
247 {
248 if (BGP_DEBUG(zebra, ZEBRA))
249 zlog_debug("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id);
250
251 return 0;
252 }
253
254 static int bgp_vrf_enable(struct vrf *vrf)
255 {
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;
275 }
276
277 static int bgp_vrf_disable(struct vrf *vrf)
278 {
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;
302 }
303
304 static void bgp_vrf_init(void)
305 {
306 vrf_init(bgp_vrf_new, bgp_vrf_enable, bgp_vrf_disable, bgp_vrf_delete);
307 }
308
309 static void bgp_vrf_terminate(void)
310 {
311 vrf_terminate();
312 }
313
314 FRR_DAEMON_INFO(bgpd, BGP, .vty_port = BGP_VTY_PORT,
315
316 .proghelp = "Implementation of the BGP routing protocol.",
317
318 .signals = bgp_signals, .n_signals = array_size(bgp_signals),
319
320 .privs = &bgpd_privs, )
321
322 /* Main routine of bgpd. Treatment of argument and start bgp finite
323 state machine is handled at here. */
324 int main(int argc, char **argv)
325 {
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 }
388 }
389 if (skip_runas)
390 memset(&bgpd_privs, 0, sizeof(bgpd_privs));
391
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);
398
399 /* Initializations. */
400 bgp_vrf_init();
401
402 /* BGP related initialization. */
403 bgp_init();
404
405 snprintf(bgpd_di.startinfo, sizeof(bgpd_di.startinfo), ", bgp@%s:%d",
406 (bm->address ? bm->address : "<all>"), bm->port);
407
408 frr_config_fork();
409 frr_run(bm->master);
410
411 /* Not reached. */
412 return (0);
413 }