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