]>
Commit | Line | Data |
---|---|---|
edd7c245 | 1 | /* zebra daemon main routine. |
718e3744 | 2 | * Copyright (C) 1997, 98 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 | * | |
896014f4 DL |
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 | |
718e3744 | 19 | */ |
20 | ||
21 | #include <zebra.h> | |
22 | ||
5e4fa164 | 23 | #include <lib/version.h> |
718e3744 | 24 | #include "getopt.h" |
25 | #include "command.h" | |
26 | #include "thread.h" | |
27 | #include "filter.h" | |
28 | #include "memory.h" | |
4a1ab8e4 | 29 | #include "zebra_memory.h" |
fc7948fa | 30 | #include "memory_vty.h" |
718e3744 | 31 | #include "prefix.h" |
32 | #include "log.h" | |
7514fb77 | 33 | #include "plist.h" |
edd7c245 | 34 | #include "privs.h" |
2d75d052 | 35 | #include "sigevent.h" |
b72ede27 | 36 | #include "vrf.h" |
736d41ad | 37 | #include "logicalrouter.h" |
4f04a76b | 38 | #include "libfrr.h" |
bf094f69 | 39 | #include "routemap.h" |
329e35da | 40 | #include "frr_pthread.h" |
718e3744 | 41 | |
43e52561 | 42 | #include "zebra/zebra_errors.h" |
718e3744 | 43 | #include "zebra/rib.h" |
44 | #include "zebra/zserv.h" | |
45 | #include "zebra/debug.h" | |
18a6dce6 | 46 | #include "zebra/router-id.h" |
ca776988 | 47 | #include "zebra/irdp.h" |
a1ac18c4 | 48 | #include "zebra/rtadv.h" |
244c1cdc | 49 | #include "zebra/zebra_ptm.h" |
fe18ee2d | 50 | #include "zebra/zebra_ns.h" |
e2b1be64 | 51 | #include "zebra/redistribute.h" |
7758e3f3 | 52 | #include "zebra/zebra_mpls.h" |
fea12efb | 53 | #include "zebra/label_manager.h" |
e27dec3c | 54 | #include "zebra/zebra_netns_notify.h" |
453844ab | 55 | #include "zebra/zebra_rnh.h" |
4c0ec639 | 56 | #include "zebra/zebra_pbr.h" |
244c1cdc | 57 | |
acfa8927 | 58 | #if defined(HANDLE_NETLINK_FUZZING) |
81a2f870 | 59 | #include "zebra/kernel_netlink.h" |
acfa8927 | 60 | #endif /* HANDLE_NETLINK_FUZZING */ |
81a2f870 | 61 | |
244c1cdc | 62 | #define ZEBRA_PTM_SUPPORT |
718e3744 | 63 | |
b21b19c5 | 64 | /* Zebra instance */ |
d62a17ae | 65 | struct zebra_t zebrad = { |
66 | .rtm_table_default = 0, | |
a37ef435 | 67 | .packets_to_process = ZEBRA_ZAPI_PACKETS_TO_PROCESS, |
b21b19c5 | 68 | }; |
718e3744 | 69 | |
70 | /* process id. */ | |
718e3744 | 71 | pid_t pid; |
72 | ||
55c72803 | 73 | /* Pacify zclient.o in libfrr, which expects this variable. */ |
87efd646 | 74 | struct thread_master *master; |
75 | ||
718e3744 | 76 | /* Route retain mode flag. */ |
77 | int retain_mode = 0; | |
78 | ||
6baf7bb8 DS |
79 | /* Allow non-quagga entities to delete quagga routes */ |
80 | int allow_delete = 0; | |
81 | ||
718e3744 | 82 | /* Don't delete kernel route. */ |
83 | int keep_kernel_mode = 0; | |
84 | ||
6b093863 DS |
85 | bool v6_rr_semantics = false; |
86 | ||
c34b6b57 | 87 | #ifdef HAVE_NETLINK |
88 | /* Receive buffer size for netlink socket */ | |
d7c0a89a | 89 | uint32_t nl_rcvbufsize = 4194304; |
c34b6b57 | 90 | #endif /* HAVE_NETLINK */ |
91 | ||
6b093863 | 92 | #define OPTION_V6_RR_SEMANTICS 2000 |
718e3744 | 93 | /* Command line options. */ |
6b093863 DS |
94 | struct option longopts[] = { |
95 | {"batch", no_argument, NULL, 'b'}, | |
96 | {"allow_delete", no_argument, NULL, 'a'}, | |
97 | {"keep_kernel", no_argument, NULL, 'k'}, | |
98 | {"socket", required_argument, NULL, 'z'}, | |
99 | {"ecmp", required_argument, NULL, 'e'}, | |
100 | {"label_socket", no_argument, NULL, 'l'}, | |
101 | {"retain", no_argument, NULL, 'r'}, | |
cc6743c2 | 102 | {"vrfdefaultname", required_argument, NULL, 'o'}, |
c34b6b57 | 103 | #ifdef HAVE_NETLINK |
6b093863 DS |
104 | {"vrfwnetns", no_argument, NULL, 'n'}, |
105 | {"nl-bufsize", required_argument, NULL, 's'}, | |
106 | {"v6-rr-semantics", no_argument, NULL, OPTION_V6_RR_SEMANTICS}, | |
c34b6b57 | 107 | #endif /* HAVE_NETLINK */ |
6b093863 | 108 | {0}}; |
718e3744 | 109 | |
d62a17ae | 110 | zebra_capabilities_t _caps_p[] = { |
9d303b37 | 111 | ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN, ZCAP_NET_RAW, |
edd7c245 | 112 | }; |
113 | ||
114 | /* zebra privileges to run with */ | |
d62a17ae | 115 | struct zebra_privs_t zserv_privs = { |
b2f36157 | 116 | #if defined(FRR_USER) && defined(FRR_GROUP) |
d62a17ae | 117 | .user = FRR_USER, |
118 | .group = FRR_GROUP, | |
edd7c245 | 119 | #endif |
120 | #ifdef VTY_GROUP | |
d62a17ae | 121 | .vty_group = VTY_GROUP, |
edd7c245 | 122 | #endif |
d62a17ae | 123 | .caps_p = _caps_p, |
124 | .cap_num_p = array_size(_caps_p), | |
125 | .cap_num_i = 0}; | |
edd7c245 | 126 | |
37fe7731 DS |
127 | unsigned int multipath_num = MULTIPATH_NUM; |
128 | ||
718e3744 | 129 | /* SIGHUP handler. */ |
d62a17ae | 130 | static void sighup(void) |
718e3744 | 131 | { |
d62a17ae | 132 | zlog_info("SIGHUP received"); |
718e3744 | 133 | |
d62a17ae | 134 | /* Reload of config file. */ |
135 | ; | |
718e3744 | 136 | } |
137 | ||
138 | /* SIGINT handler. */ | |
d62a17ae | 139 | static void sigint(void) |
718e3744 | 140 | { |
d62a17ae | 141 | struct vrf *vrf; |
142 | struct zebra_vrf *zvrf; | |
f3e33b69 QY |
143 | struct listnode *ln, *nn; |
144 | struct zserv *client; | |
fe18ee2d | 145 | |
d62a17ae | 146 | zlog_notice("Terminating on signal"); |
718e3744 | 147 | |
03951374 | 148 | frr_early_fini(); |
718e3744 | 149 | |
f3e33b69 QY |
150 | for (ALL_LIST_ELEMENTS(zebrad.client_list, ln, nn, client)) |
151 | zserv_close_client(client); | |
152 | ||
d62a17ae | 153 | list_delete_all_node(zebrad.client_list); |
f88bd20c | 154 | zebra_ptm_finish(); |
d62a17ae | 155 | |
156 | if (retain_mode) | |
a2addae8 | 157 | RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { |
d62a17ae | 158 | zvrf = vrf->info; |
159 | if (zvrf) | |
160 | SET_FLAG(zvrf->flags, ZEBRA_VRF_RETAIN); | |
161 | } | |
40289934 | 162 | if (zebrad.lsp_process_q) |
e208c8f9 | 163 | work_queue_free_and_null(&zebrad.lsp_process_q); |
d62a17ae | 164 | vrf_terminate(); |
165 | ||
ff705b15 | 166 | ns_walk_func(zebra_ns_disabled); |
e27dec3c | 167 | zebra_ns_notify_close(); |
d62a17ae | 168 | |
169 | access_list_reset(); | |
170 | prefix_list_reset(); | |
171 | route_map_finish(); | |
03951374 | 172 | |
affe9e99 | 173 | list_delete_and_null(&zebrad.client_list); |
e208c8f9 | 174 | work_queue_free_and_null(&zebrad.ribq); |
d62a17ae | 175 | meta_queue_free(zebrad.mq); |
d62a17ae | 176 | |
03951374 | 177 | frr_fini(); |
d62a17ae | 178 | exit(0); |
718e3744 | 179 | } |
180 | ||
181 | /* SIGUSR1 handler. */ | |
d62a17ae | 182 | static void sigusr1(void) |
718e3744 | 183 | { |
d62a17ae | 184 | zlog_rotate(); |
718e3744 | 185 | } |
186 | ||
d62a17ae | 187 | struct quagga_signal_t zebra_signals[] = { |
188 | { | |
189 | .signal = SIGHUP, | |
190 | .handler = &sighup, | |
191 | }, | |
192 | { | |
193 | .signal = SIGUSR1, | |
194 | .handler = &sigusr1, | |
195 | }, | |
196 | { | |
197 | .signal = SIGINT, | |
198 | .handler = &sigint, | |
199 | }, | |
200 | { | |
201 | .signal = SIGTERM, | |
202 | .handler = &sigint, | |
203 | }, | |
2d75d052 | 204 | }; |
b72ede27 | 205 | |
d62a17ae | 206 | FRR_DAEMON_INFO( |
207 | zebra, ZEBRA, .vty_port = ZEBRA_VTY_PORT, .flags = FRR_NO_ZCLIENT, | |
4f04a76b | 208 | |
d62a17ae | 209 | .proghelp = |
210 | "Daemon which manages kernel routing table management " | |
4f04a76b DL |
211 | "and\nredistribution between different routing protocols.", |
212 | ||
d62a17ae | 213 | .signals = zebra_signals, .n_signals = array_size(zebra_signals), |
4f04a76b | 214 | |
d62a17ae | 215 | .privs = &zserv_privs, ) |
4f04a76b | 216 | |
718e3744 | 217 | /* Main startup routine. */ |
d62a17ae | 218 | int main(int argc, char **argv) |
718e3744 | 219 | { |
d62a17ae | 220 | // int batch_mode = 0; |
221 | char *zserv_path = NULL; | |
222 | /* Socket to external label manager */ | |
223 | char *lblmgr_path = NULL; | |
689f5a8c DL |
224 | struct sockaddr_storage dummy; |
225 | socklen_t dummylen; | |
411314ed | 226 | #if defined(HANDLE_ZAPI_FUZZING) |
81a2f870 | 227 | char *zapi_fuzzing = NULL; |
acfa8927 SW |
228 | #endif /* HANDLE_ZAPI_FUZZING */ |
229 | #if defined(HANDLE_NETLINK_FUZZING) | |
81a2f870 | 230 | char *netlink_fuzzing = NULL; |
acfa8927 | 231 | #endif /* HANDLE_NETLINK_FUZZING */ |
fea12efb | 232 | |
78dd30b2 | 233 | vrf_configure_backend(VRF_BACKEND_VRF_LITE); |
996c9314 | 234 | logicalrouter_configure_backend(LOGICALROUTER_BACKEND_NETNS); |
78dd30b2 | 235 | |
d62a17ae | 236 | frr_preinit(&zebra_di, argc, argv); |
718e3744 | 237 | |
d62a17ae | 238 | frr_opt_add( |
cc6743c2 | 239 | "bakz:e:l:o:r" |
4f04a76b | 240 | #ifdef HAVE_NETLINK |
78dd30b2 | 241 | "s:n" |
411314ed DS |
242 | #endif |
243 | #if defined(HANDLE_ZAPI_FUZZING) | |
acfa8927 SW |
244 | "c:" |
245 | #endif /* HANDLE_ZAPI_FUZZING */ | |
246 | #if defined(HANDLE_NETLINK_FUZZING) | |
247 | "w:" | |
248 | #endif /* HANDLE_NETLINK_FUZZING */ | |
d62a17ae | 249 | , |
250 | longopts, | |
6b093863 DS |
251 | " -b, --batch Runs in batch mode\n" |
252 | " -a, --allow_delete Allow other processes to delete zebra routes\n" | |
253 | " -z, --socket Set path of zebra socket\n" | |
254 | " -e, --ecmp Specify ECMP to use.\n" | |
255 | " -l, --label_socket Socket to external label manager\n" | |
f6b66ba9 | 256 | " -k, --keep_kernel Don't delete old routes which were installed by zebra.\n" |
6b093863 | 257 | " -r, --retain When program terminates, retain added route by zebra.\n" |
cc6743c2 | 258 | " -o, --vrfdefaultname Set default VRF name.\n" |
4f04a76b | 259 | #ifdef HAVE_NETLINK |
f6b66ba9 | 260 | " -n, --vrfwnetns Use NetNS as VRF backend\n" |
6b093863 DS |
261 | " -s, --nl-bufsize Set netlink receive buffer size\n" |
262 | " --v6-rr-semantics Use v6 RR semantics\n" | |
4f04a76b | 263 | #endif /* HAVE_NETLINK */ |
411314ed | 264 | #if defined(HANDLE_ZAPI_FUZZING) |
81a2f870 | 265 | " -c <file> Bypass normal startup and use this file for testing of zapi\n" |
acfa8927 SW |
266 | #endif /* HANDLE_ZAPI_FUZZING */ |
267 | #if defined(HANDLE_NETLINK_FUZZING) | |
268 | " -w <file> Bypass normal startup and use this file for testing of netlink input\n" | |
269 | #endif /* HANDLE_NETLINK_FUZZING */ | |
6b093863 | 270 | ); |
d62a17ae | 271 | |
272 | while (1) { | |
273 | int opt = frr_getopt(argc, argv, NULL); | |
274 | ||
275 | if (opt == EOF) | |
276 | break; | |
277 | ||
278 | switch (opt) { | |
279 | case 0: | |
280 | break; | |
281 | case 'b': | |
282 | // batch_mode = 1; | |
283 | break; | |
284 | case 'a': | |
285 | allow_delete = 1; | |
286 | break; | |
287 | case 'k': | |
288 | keep_kernel_mode = 1; | |
289 | break; | |
290 | case 'e': | |
291 | multipath_num = atoi(optarg); | |
292 | if (multipath_num > MULTIPATH_NUM | |
293 | || multipath_num <= 0) { | |
af4c2728 | 294 | flog_err( |
e914ccbe | 295 | EC_ZEBRA_BAD_MULTIPATH_NUM, |
d62a17ae | 296 | "Multipath Number specified must be less than %d and greater than 0", |
297 | MULTIPATH_NUM); | |
298 | return 1; | |
299 | } | |
300 | break; | |
cc6743c2 PG |
301 | case 'o': |
302 | vrf_set_default_name(optarg); | |
303 | break; | |
d62a17ae | 304 | case 'z': |
305 | zserv_path = optarg; | |
689f5a8c DL |
306 | if (!frr_zclient_addr(&dummy, &dummylen, optarg)) { |
307 | fprintf(stderr, | |
308 | "Invalid zserv socket path: %s\n", | |
309 | optarg); | |
310 | exit(1); | |
311 | } | |
d62a17ae | 312 | break; |
313 | case 'l': | |
314 | lblmgr_path = optarg; | |
315 | break; | |
316 | case 'r': | |
317 | retain_mode = 1; | |
318 | break; | |
c34b6b57 | 319 | #ifdef HAVE_NETLINK |
d62a17ae | 320 | case 's': |
321 | nl_rcvbufsize = atoi(optarg); | |
322 | break; | |
78dd30b2 PG |
323 | case 'n': |
324 | vrf_configure_backend(VRF_BACKEND_NETNS); | |
736d41ad | 325 | logicalrouter_configure_backend( |
996c9314 | 326 | LOGICALROUTER_BACKEND_OFF); |
78dd30b2 | 327 | break; |
6b093863 DS |
328 | case OPTION_V6_RR_SEMANTICS: |
329 | v6_rr_semantics = true; | |
330 | break; | |
c34b6b57 | 331 | #endif /* HAVE_NETLINK */ |
411314ed DS |
332 | #if defined(HANDLE_ZAPI_FUZZING) |
333 | case 'c': | |
81a2f870 | 334 | zapi_fuzzing = optarg; |
81a2f870 | 335 | break; |
acfa8927 SW |
336 | #endif /* HANDLE_ZAPI_FUZZING */ |
337 | #if defined(HANDLE_NETLINK_FUZZING) | |
81a2f870 SW |
338 | case 'w': |
339 | netlink_fuzzing = optarg; | |
340 | /* This ensures we are aren't writing any of the | |
341 | * startup netlink messages that happen when we | |
342 | * just want to read. | |
343 | */ | |
acfa8927 | 344 | netlink_read = true; |
411314ed | 345 | break; |
acfa8927 | 346 | #endif /* HANDLE_NETLINK_FUZZING */ |
d62a17ae | 347 | default: |
348 | frr_help_exit(1); | |
349 | break; | |
350 | } | |
718e3744 | 351 | } |
d62a17ae | 352 | |
353 | vty_config_lockless(); | |
354 | zebrad.master = frr_init(); | |
355 | ||
356 | /* Zebra related initialize. */ | |
5f145fb8 | 357 | zserv_init(); |
d62a17ae | 358 | rib_init(); |
359 | zebra_if_init(); | |
360 | zebra_debug_init(); | |
361 | router_id_cmd_init(); | |
f84fc2c9 DS |
362 | |
363 | /* | |
364 | * Initialize NS( and implicitly the VRF module), and make kernel | |
365 | * routing socket. */ | |
366 | zebra_ns_init(); | |
367 | ||
368 | zebra_vty_init(); | |
d62a17ae | 369 | access_list_init(); |
370 | prefix_list_init(); | |
371 | #if defined(HAVE_RTADV) | |
372 | rtadv_cmd_init(); | |
36735ed9 | 373 | #endif |
d62a17ae | 374 | /* PTM socket */ |
244c1cdc | 375 | #ifdef ZEBRA_PTM_SUPPORT |
d62a17ae | 376 | zebra_ptm_init(); |
244c1cdc | 377 | #endif |
718e3744 | 378 | |
d62a17ae | 379 | zebra_mpls_init(); |
380 | zebra_mpls_vty_init(); | |
2dd0d726 | 381 | zebra_pw_vty_init(); |
4c0ec639 | 382 | zebra_pbr_init(); |
7758e3f3 | 383 | |
996c9314 LB |
384 | /* For debug purpose. */ |
385 | /* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */ | |
718e3744 | 386 | |
d62a17ae | 387 | /* Process the configuration file. Among other configuration |
9d303b37 DL |
388 | * directives we can meet those installing static routes. Such |
389 | * requests will not be executed immediately, but queued in | |
390 | * zebra->ribq structure until we enter the main execution loop. | |
391 | * The notifications from kernel will show originating PID equal | |
392 | * to that after daemon() completes (if ever called). | |
393 | */ | |
d62a17ae | 394 | frr_config_fork(); |
718e3744 | 395 | |
d62a17ae | 396 | /* After we have successfully acquired the pidfile, we can be sure |
9d303b37 DL |
397 | * about being the only copy of zebra process, which is submitting |
398 | * changes to the FIB. | |
399 | * Clean up zebra-originated routes. The requests will be sent to OS | |
400 | * immediately, so originating PID in notifications from kernel | |
401 | * will be equal to the current getpid(). To know about such routes, | |
402 | * we have to have route_read() called before. | |
403 | */ | |
d62a17ae | 404 | if (!keep_kernel_mode) |
405 | rib_sweep_route(); | |
91b7351d | 406 | |
d62a17ae | 407 | /* Needed for BSD routing socket. */ |
408 | pid = getpid(); | |
718e3744 | 409 | |
21ccc0cf | 410 | /* Intialize pthread library */ |
329e35da QY |
411 | frr_pthread_init(); |
412 | ||
21ccc0cf QY |
413 | /* Start Zebra API server */ |
414 | zserv_start(zserv_path); | |
97be79f9 | 415 | |
d62a17ae | 416 | /* Init label manager */ |
417 | label_manager_init(lblmgr_path); | |
fea12efb | 418 | |
453844ab QY |
419 | /* RNH init */ |
420 | zebra_rnh_init(); | |
5ad4c39c QY |
421 | |
422 | /* Error init */ | |
423 | zebra_error_init(); | |
453844ab | 424 | |
2875801f | 425 | #if defined(HANDLE_ZAPI_FUZZING) |
81a2f870 SW |
426 | if (zapi_fuzzing) { |
427 | zserv_read_file(zapi_fuzzing); | |
428 | exit(0); | |
acfa8927 SW |
429 | } |
430 | #endif /* HANDLE_ZAPI_FUZZING */ | |
431 | #if defined(HANDLE_NETLINK_FUZZING) | |
432 | if (netlink_fuzzing) { | |
81a2f870 | 433 | netlink_read_init(netlink_fuzzing); |
2875801f QY |
434 | exit(0); |
435 | } | |
acfa8927 | 436 | #endif /* HANDLE_NETLINK_FUZZING */ |
2875801f QY |
437 | |
438 | ||
d62a17ae | 439 | frr_run(zebrad.master); |
718e3744 | 440 | |
d62a17ae | 441 | /* Not reached... */ |
442 | return 0; | |
718e3744 | 443 | } |