]>
Commit | Line | Data |
---|---|---|
e9e2c950 RZ |
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 | ||
e9e2c950 RZ |
23 | #include "bfd.h" |
24 | #include "lib/version.h" | |
6ed84949 | 25 | |
e9e2c950 RZ |
26 | |
27 | /* | |
28 | * FRR related code. | |
29 | */ | |
30 | DEFINE_MGROUP(BFDD, "Bidirectional Forwarding Detection Daemon"); | |
31 | DEFINE_MTYPE(BFDD, BFDD_TMP, "short-lived temporary memory"); | |
32 | DEFINE_MTYPE(BFDD, BFDD_CONFIG, "long-lived configuration memory"); | |
33 | DEFINE_MTYPE(BFDD, BFDD_LABEL, "long-lived label memory"); | |
34 | DEFINE_MTYPE(BFDD, BFDD_CONTROL, "long-lived control socket memory"); | |
35 | DEFINE_MTYPE(BFDD, BFDD_NOTIFICATION, "short-lived control notification data"); | |
36 | ||
37 | /* Master of threads. */ | |
38 | struct thread_master *master; | |
39 | ||
40 | /* BFDd privileges */ | |
41 | static zebra_capabilities_t _caps_p[] = {ZCAP_BIND}; | |
42 | ||
43 | struct zebra_privs_t bfdd_privs = { | |
44 | #if defined(FRR_USER) && defined(FRR_GROUP) | |
45 | .user = FRR_USER, | |
46 | .group = FRR_GROUP, | |
47 | #endif | |
48 | #if defined(VTY_GROUP) | |
49 | .vty_group = VTY_GROUP, | |
50 | #endif | |
51 | .caps_p = _caps_p, | |
52 | .cap_num_p = array_size(_caps_p), | |
53 | .cap_num_i = 0, | |
54 | }; | |
55 | ||
56 | void socket_close(int *s) | |
57 | { | |
58 | if (*s <= 0) | |
59 | return; | |
60 | ||
61 | if (close(*s) != 0) | |
62 | log_error("%s: close(%d): (%d) %s", __func__, *s, errno, | |
63 | strerror(errno)); | |
64 | ||
65 | *s = -1; | |
66 | } | |
67 | ||
68 | static void sigusr1_handler(void) | |
69 | { | |
70 | zlog_rotate(); | |
71 | } | |
72 | ||
73 | static void sigterm_handler(void) | |
74 | { | |
75 | /* Signalize shutdown. */ | |
76 | frr_early_fini(); | |
77 | ||
d3af6147 RZ |
78 | /* Stop receiving message from zebra. */ |
79 | bfdd_zclient_stop(); | |
80 | ||
e9e2c950 RZ |
81 | /* Shutdown controller to avoid receiving anymore commands. */ |
82 | control_shutdown(); | |
83 | ||
84 | /* Shutdown and free all protocol related memory. */ | |
85 | bfd_shutdown(); | |
86 | ||
87 | /* Close all descriptors. */ | |
88 | socket_close(&bglobal.bg_echo); | |
89 | socket_close(&bglobal.bg_shop); | |
90 | socket_close(&bglobal.bg_mhop); | |
91 | socket_close(&bglobal.bg_shop6); | |
92 | socket_close(&bglobal.bg_mhop6); | |
93 | socket_close(&bglobal.bg_vxlan); | |
94 | ||
95 | /* Terminate and free() FRR related memory. */ | |
96 | frr_fini(); | |
97 | ||
98 | exit(0); | |
99 | } | |
100 | ||
101 | static struct quagga_signal_t bfd_signals[] = { | |
102 | { | |
103 | .signal = SIGUSR1, | |
104 | .handler = &sigusr1_handler, | |
105 | }, | |
106 | { | |
107 | .signal = SIGTERM, | |
108 | .handler = &sigterm_handler, | |
109 | }, | |
110 | { | |
111 | .signal = SIGINT, | |
112 | .handler = &sigterm_handler, | |
113 | }, | |
114 | }; | |
115 | ||
116 | FRR_DAEMON_INFO(bfdd, BFD, .vty_port = 2617, | |
117 | .proghelp = "Implementation of the BFD protocol.", | |
118 | .signals = bfd_signals, .n_signals = array_size(bfd_signals), | |
119 | .privs = &bfdd_privs) | |
120 | ||
121 | #define OPTION_CTLSOCK 1001 | |
122 | static struct option longopts[] = { | |
123 | {"bfdctl", required_argument, NULL, OPTION_CTLSOCK}, | |
124 | {0} | |
125 | }; | |
126 | ||
127 | ||
128 | /* | |
129 | * BFD daemon related code. | |
130 | */ | |
131 | struct bfd_global bglobal; | |
132 | ||
133 | struct bfd_diag_str_list diag_list[] = { | |
134 | {.str = "NeighDown", .type = BFD_DIAGNEIGHDOWN}, | |
135 | {.str = "DetectTime", .type = BFD_DIAGDETECTTIME}, | |
136 | {.str = "AdminDown", .type = BFD_DIAGADMINDOWN}, | |
137 | {.str = NULL}, | |
138 | }; | |
139 | ||
140 | struct bfd_state_str_list state_list[] = { | |
141 | {.str = "AdminDown", .type = PTM_BFD_ADM_DOWN}, | |
142 | {.str = "Down", .type = PTM_BFD_DOWN}, | |
143 | {.str = "Init", .type = PTM_BFD_INIT}, | |
144 | {.str = "Up", .type = PTM_BFD_UP}, | |
145 | {.str = NULL}, | |
146 | }; | |
147 | ||
148 | ||
149 | static void bg_init(void) | |
150 | { | |
151 | TAILQ_INIT(&bglobal.bg_bcslist); | |
152 | ||
153 | bglobal.bg_shop = bp_udp_shop(); | |
154 | bglobal.bg_mhop = bp_udp_mhop(); | |
155 | bglobal.bg_shop6 = bp_udp6_shop(); | |
156 | bglobal.bg_mhop6 = bp_udp6_mhop(); | |
157 | bglobal.bg_echo = ptm_bfd_echo_sock_init(); | |
158 | bglobal.bg_vxlan = ptm_bfd_vxlan_sock_init(); | |
159 | } | |
160 | ||
161 | int main(int argc, char *argv[]) | |
162 | { | |
163 | const char *ctl_path = BFDD_CONTROL_SOCKET; | |
164 | int opt; | |
165 | ||
166 | frr_preinit(&bfdd_di, argc, argv); | |
167 | frr_opt_add("", longopts, | |
168 | " --bfdctl Specify bfdd control socket\n"); | |
169 | ||
170 | while (true) { | |
171 | opt = frr_getopt(argc, argv, NULL); | |
172 | if (opt == EOF) | |
173 | break; | |
174 | ||
175 | switch (opt) { | |
176 | case OPTION_CTLSOCK: | |
177 | ctl_path = optarg; | |
178 | break; | |
179 | ||
180 | default: | |
181 | frr_help_exit(1); | |
182 | break; | |
183 | } | |
184 | } | |
185 | ||
186 | #if 0 /* TODO add support for JSON configuration files. */ | |
187 | parse_config(conf); | |
188 | #endif | |
189 | ||
190 | /* Initialize logging API. */ | |
191 | log_init(1, BLOG_DEBUG, &bfdd_di); | |
192 | ||
193 | /* Initialize system sockets. */ | |
194 | bg_init(); | |
195 | ||
196 | /* Initialize control socket. */ | |
197 | control_init(ctl_path); | |
198 | ||
199 | /* Initialize FRR infrastructure. */ | |
200 | master = frr_init(); | |
201 | ||
202 | /* Initialize BFD data structures. */ | |
203 | bfd_initialize(); | |
204 | ||
d3af6147 RZ |
205 | /* Initialize zebra connection. */ |
206 | bfdd_zclient_init(&bfdd_privs); | |
207 | ||
e9e2c950 RZ |
208 | /* Add descriptors to the event loop. */ |
209 | thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_shop, | |
210 | &bglobal.bg_ev[0]); | |
211 | thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_mhop, | |
212 | &bglobal.bg_ev[1]); | |
213 | thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_shop6, | |
214 | &bglobal.bg_ev[2]); | |
215 | thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_mhop6, | |
216 | &bglobal.bg_ev[3]); | |
217 | thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_echo, | |
218 | &bglobal.bg_ev[4]); | |
219 | #if 0 /* TODO VxLAN support. */ | |
220 | thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_vxlan, | |
221 | &bglobal.bg_ev[5]); | |
222 | #endif | |
223 | thread_add_read(master, control_accept, NULL, bglobal.bg_csock, | |
224 | &bglobal.bg_csockev); | |
225 | ||
c2f29cf3 RZ |
226 | /* Install commands. */ |
227 | bfdd_vty_init(); | |
228 | ||
e9e2c950 RZ |
229 | /* read configuration file and daemonize */ |
230 | frr_config_fork(); | |
231 | ||
232 | frr_run(master); | |
233 | /* NOTREACHED */ | |
234 | ||
235 | return 0; | |
236 | } |