]> git.proxmox.com Git - mirror_frr.git/blob - bfdd/bfdd.c
3313c8137ccd34a8aca7301e322079ca5a19e29f
[mirror_frr.git] / bfdd / bfdd.c
1 /*
2 * BFD daemon code
3 * Copyright (C) 2018 Network Device Education Foundation, Inc. ("NetDEF")
4 *
5 * FRR is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2, or (at your option) any
8 * later version.
9 *
10 * FRR is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with FRR; see the file COPYING. If not, write to the Free
17 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18 * 02111-1307, USA.
19 */
20
21 #include <zebra.h>
22
23 #include <err.h>
24 #include <errno.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29
30 #include "bfd.h"
31 #include "lib/version.h"
32 #include "lib/libfrr.h"
33
34 /*
35 * FRR related code.
36 */
37 DEFINE_MGROUP(BFDD, "Bidirectional Forwarding Detection Daemon");
38 DEFINE_MTYPE(BFDD, BFDD_TMP, "short-lived temporary memory");
39 DEFINE_MTYPE(BFDD, BFDD_CONFIG, "long-lived configuration memory");
40 DEFINE_MTYPE(BFDD, BFDD_LABEL, "long-lived label memory");
41 DEFINE_MTYPE(BFDD, BFDD_CONTROL, "long-lived control socket memory");
42 DEFINE_MTYPE(BFDD, BFDD_NOTIFICATION, "short-lived control notification data");
43
44 /* Master of threads. */
45 struct thread_master *master;
46
47 /* BFDd privileges */
48 static zebra_capabilities_t _caps_p[] = {ZCAP_BIND};
49
50 struct zebra_privs_t bfdd_privs = {
51 #if defined(FRR_USER) && defined(FRR_GROUP)
52 .user = FRR_USER,
53 .group = FRR_GROUP,
54 #endif
55 #if defined(VTY_GROUP)
56 .vty_group = VTY_GROUP,
57 #endif
58 .caps_p = _caps_p,
59 .cap_num_p = array_size(_caps_p),
60 .cap_num_i = 0,
61 };
62
63 void socket_close(int *s)
64 {
65 if (*s <= 0)
66 return;
67
68 if (close(*s) != 0)
69 log_error("%s: close(%d): (%d) %s", __func__, *s, errno,
70 strerror(errno));
71
72 *s = -1;
73 }
74
75 static void sigusr1_handler(void)
76 {
77 zlog_rotate();
78 }
79
80 static void sigterm_handler(void)
81 {
82 /* Signalize shutdown. */
83 frr_early_fini();
84
85 /* Shutdown controller to avoid receiving anymore commands. */
86 control_shutdown();
87
88 /* Shutdown and free all protocol related memory. */
89 bfd_shutdown();
90
91 /* Close all descriptors. */
92 socket_close(&bglobal.bg_echo);
93 socket_close(&bglobal.bg_shop);
94 socket_close(&bglobal.bg_mhop);
95 socket_close(&bglobal.bg_shop6);
96 socket_close(&bglobal.bg_mhop6);
97 socket_close(&bglobal.bg_vxlan);
98
99 /* Terminate and free() FRR related memory. */
100 frr_fini();
101
102 exit(0);
103 }
104
105 static struct quagga_signal_t bfd_signals[] = {
106 {
107 .signal = SIGUSR1,
108 .handler = &sigusr1_handler,
109 },
110 {
111 .signal = SIGTERM,
112 .handler = &sigterm_handler,
113 },
114 {
115 .signal = SIGINT,
116 .handler = &sigterm_handler,
117 },
118 };
119
120 FRR_DAEMON_INFO(bfdd, BFD, .vty_port = 2617,
121 .proghelp = "Implementation of the BFD protocol.",
122 .signals = bfd_signals, .n_signals = array_size(bfd_signals),
123 .privs = &bfdd_privs)
124
125 #define OPTION_CTLSOCK 1001
126 static struct option longopts[] = {
127 {"bfdctl", required_argument, NULL, OPTION_CTLSOCK},
128 {0}
129 };
130
131
132 /*
133 * BFD daemon related code.
134 */
135 struct bfd_global bglobal;
136
137 struct bfd_diag_str_list diag_list[] = {
138 {.str = "NeighDown", .type = BFD_DIAGNEIGHDOWN},
139 {.str = "DetectTime", .type = BFD_DIAGDETECTTIME},
140 {.str = "AdminDown", .type = BFD_DIAGADMINDOWN},
141 {.str = NULL},
142 };
143
144 struct bfd_state_str_list state_list[] = {
145 {.str = "AdminDown", .type = PTM_BFD_ADM_DOWN},
146 {.str = "Down", .type = PTM_BFD_DOWN},
147 {.str = "Init", .type = PTM_BFD_INIT},
148 {.str = "Up", .type = PTM_BFD_UP},
149 {.str = NULL},
150 };
151
152
153 static void bg_init(void)
154 {
155 TAILQ_INIT(&bglobal.bg_bcslist);
156
157 bglobal.bg_shop = bp_udp_shop();
158 bglobal.bg_mhop = bp_udp_mhop();
159 bglobal.bg_shop6 = bp_udp6_shop();
160 bglobal.bg_mhop6 = bp_udp6_mhop();
161 bglobal.bg_echo = ptm_bfd_echo_sock_init();
162 bglobal.bg_vxlan = ptm_bfd_vxlan_sock_init();
163 }
164
165 int main(int argc, char *argv[])
166 {
167 const char *ctl_path = BFDD_CONTROL_SOCKET;
168 int opt;
169
170 frr_preinit(&bfdd_di, argc, argv);
171 frr_opt_add("", longopts,
172 " --bfdctl Specify bfdd control socket\n");
173
174 while (true) {
175 opt = frr_getopt(argc, argv, NULL);
176 if (opt == EOF)
177 break;
178
179 switch (opt) {
180 case OPTION_CTLSOCK:
181 ctl_path = optarg;
182 break;
183
184 default:
185 frr_help_exit(1);
186 break;
187 }
188 }
189
190 #if 0 /* TODO add support for JSON configuration files. */
191 parse_config(conf);
192 #endif
193
194 /* Initialize logging API. */
195 log_init(1, BLOG_DEBUG, &bfdd_di);
196
197 /* Initialize system sockets. */
198 bg_init();
199
200 /* Initialize control socket. */
201 control_init(ctl_path);
202
203 /* Initialize FRR infrastructure. */
204 master = frr_init();
205
206 /* Initialize BFD data structures. */
207 bfd_initialize();
208
209 /* Add descriptors to the event loop. */
210 thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_shop,
211 &bglobal.bg_ev[0]);
212 thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_mhop,
213 &bglobal.bg_ev[1]);
214 thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_shop6,
215 &bglobal.bg_ev[2]);
216 thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_mhop6,
217 &bglobal.bg_ev[3]);
218 thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_echo,
219 &bglobal.bg_ev[4]);
220 #if 0 /* TODO VxLAN support. */
221 thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_vxlan,
222 &bglobal.bg_ev[5]);
223 #endif
224 thread_add_read(master, control_accept, NULL, bglobal.bg_csock,
225 &bglobal.bg_csockev);
226
227 /* read configuration file and daemonize */
228 frr_config_fork();
229
230 frr_run(master);
231 /* NOTREACHED */
232
233 return 0;
234 }