]> git.proxmox.com Git - mirror_frr.git/blob - vrrpd/vrrp_zebra.c
vrrpd: fix broken reads when reinitializing
[mirror_frr.git] / vrrpd / vrrp_zebra.c
1 /*
2 * VRRP Zebra interfacing.
3 * Copyright (C) 2018-2019 Cumulus Networks, Inc.
4 * Quentin Young
5 *
6 * This program 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 Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * 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 #include <zebra.h>
21
22 #include "lib/if.h"
23 #include "lib/linklist.h"
24 #include "lib/log.h"
25 #include "lib/prefix.h"
26 #include "lib/vty.h"
27 #include "lib/zclient.h"
28
29 #include "vrrp.h"
30 #include "vrrp_debug.h"
31 #include "vrrp_zebra.h"
32
33 #define VRRP_LOGPFX "[ZEBRA] "
34
35 static struct zclient *zclient = NULL;
36
37 static void vrrp_zebra_debug_if_state(struct interface *ifp, vrf_id_t vrf_id,
38 const char *func)
39 {
40 DEBUGD(&vrrp_dbg_zebra,
41 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
42 func, ifp->name, ifp->ifindex, vrf_id, (long)ifp->flags,
43 ifp->metric, ifp->mtu, if_is_operative(ifp));
44 }
45
46 static void vrrp_zebra_debug_if_dump_address(struct interface *ifp,
47 const char *func)
48 {
49 struct connected *ifc;
50 struct listnode *node;
51
52 DEBUGD(&vrrp_dbg_zebra, "%s: interface %s addresses:", func, ifp->name);
53
54 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
55 struct prefix *p = ifc->address;
56
57 DEBUGD(&vrrp_dbg_zebra, "%s: interface %s address %s %s", func,
58 ifp->name, inet_ntoa(p->u.prefix4),
59 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ? "secondary"
60 : "primary");
61 }
62 }
63
64
65 static void vrrp_zebra_connected(struct zclient *zclient)
66 {
67 zclient_send_reg_requests(zclient, VRF_DEFAULT);
68 }
69
70 /* Router-id update message from zebra. */
71 static int vrrp_router_id_update_zebra(int command, struct zclient *zclient,
72 zebra_size_t length, vrf_id_t vrf_id)
73 {
74 struct prefix router_id;
75
76 zebra_router_id_update_read(zclient->ibuf, &router_id);
77
78 return 0;
79 }
80
81 static int vrrp_zebra_if_add(int command, struct zclient *zclient,
82 zebra_size_t length, vrf_id_t vrf_id)
83 {
84 struct interface *ifp;
85
86 /*
87 * zebra api adds/dels interfaces using the same call
88 * interface_add_read below, see comments in lib/zclient.c
89 */
90 ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
91
92 if (!ifp)
93 return 0;
94
95 vrrp_zebra_debug_if_state(ifp, vrf_id, __func__);
96
97 vrrp_if_add(ifp);
98
99 return 0;
100 }
101
102 static int vrrp_zebra_if_del(int command, struct zclient *zclient,
103 zebra_size_t length, vrf_id_t vrf_id)
104 {
105 struct interface *ifp;
106
107 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
108
109 if (!ifp)
110 return 0;
111
112 vrrp_zebra_debug_if_state(ifp, vrf_id, __func__);
113
114 vrrp_if_del(ifp);
115
116 return 0;
117 }
118
119 static int vrrp_zebra_if_state_up(int command, struct zclient *zclient,
120 zebra_size_t length, vrf_id_t vrf_id)
121 {
122 struct interface *ifp;
123
124 /*
125 * zebra api notifies interface up/down events by using the same call
126 * zebra_interface_state_read below, see comments in lib/zclient.c ifp =
127 * zebra_interface_state_read(zclient->ibuf, vrf_id);
128 */
129 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
130
131 if (!ifp)
132 return 0;
133
134 vrrp_zebra_debug_if_state(ifp, vrf_id, __func__);
135
136 vrrp_if_up(ifp);
137
138 return 0;
139 }
140
141 static int vrrp_zebra_if_state_down(int command, struct zclient *zclient,
142 zebra_size_t length, vrf_id_t vrf_id)
143 {
144 struct interface *ifp;
145
146 /*
147 * zebra api notifies interface up/down events by using the same call
148 * zebra_interface_state_read below, see comments in lib/zclient.c
149 */
150 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
151
152 if (!ifp)
153 return 0;
154
155 vrrp_zebra_debug_if_state(ifp, vrf_id, __func__);
156
157 vrrp_if_down(ifp);
158
159 return 0;
160 }
161
162 static int vrrp_zebra_if_address_add(int command, struct zclient *zclient,
163 zebra_size_t length, vrf_id_t vrf_id)
164 {
165 struct connected *c;
166
167 /*
168 * zebra api notifies address adds/dels events by using the same call
169 * interface_add_read below, see comments in lib/zclient.c
170 *
171 * zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
172 * will add address to interface list by calling
173 * connected_add_by_prefix()
174 */
175 c = zebra_interface_address_read(command, zclient->ibuf, vrf_id);
176
177 if (!c)
178 return 0;
179
180 vrrp_zebra_debug_if_state(c->ifp, vrf_id, __func__);
181 vrrp_zebra_debug_if_dump_address(c->ifp, __func__);
182
183 vrrp_if_address_add(c->ifp);
184
185 return 0;
186 }
187
188 static int vrrp_zebra_if_address_del(int command, struct zclient *client,
189 zebra_size_t length, vrf_id_t vrf_id)
190 {
191 struct connected *c;
192
193 /*
194 * zebra api notifies address adds/dels events by using the same call
195 * interface_add_read below, see comments in lib/zclient.c
196 *
197 * zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
198 * will remove address from interface list by calling
199 * connected_delete_by_prefix()
200 */
201 c = zebra_interface_address_read(command, client->ibuf, vrf_id);
202
203 if (!c)
204 return 0;
205
206 vrrp_zebra_debug_if_state(c->ifp, vrf_id, __func__);
207 vrrp_zebra_debug_if_dump_address(c->ifp, __func__);
208
209 vrrp_if_address_del(c->ifp);
210
211 return 0;
212 }
213
214 void vrrp_zebra_radv_set(struct vrrp_router *r, bool enable)
215 {
216 DEBUGD(&vrrp_dbg_zebra,
217 VRRP_LOGPFX VRRP_LOGPFX_VRID
218 "Requesting Zebra to turn router advertisements %s for %s",
219 r->vr->vrid, enable ? "on" : "off", r->mvl_ifp->name);
220
221 zclient_send_interface_radv_req(zclient, VRF_DEFAULT, r->mvl_ifp,
222 enable, VRRP_RADV_INT);
223 }
224
225 int vrrp_zclient_send_interface_protodown(struct interface *ifp, bool down)
226 {
227 DEBUGD(&vrrp_dbg_zebra,
228 VRRP_LOGPFX "Requesting Zebra to set %s protodown %s", ifp->name,
229 down ? "on" : "off");
230
231 return zclient_send_interface_protodown(zclient, VRF_DEFAULT, ifp,
232 down);
233 }
234
235 void vrrp_zebra_init(void)
236 {
237 /* Socket for receiving updates from Zebra daemon */
238 zclient = zclient_new(master, &zclient_options_default);
239
240 zclient->zebra_connected = vrrp_zebra_connected;
241 zclient->router_id_update = vrrp_router_id_update_zebra;
242 zclient->interface_add = vrrp_zebra_if_add;
243 zclient->interface_delete = vrrp_zebra_if_del;
244 zclient->interface_up = vrrp_zebra_if_state_up;
245 zclient->interface_down = vrrp_zebra_if_state_down;
246 zclient->interface_address_add = vrrp_zebra_if_address_add;
247 zclient->interface_address_delete = vrrp_zebra_if_address_del;
248
249 zclient_init(zclient, 0, 0, &vrrp_privs);
250
251 zlog_notice("%s: zclient socket initialized", __PRETTY_FUNCTION__);
252 }