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