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