]> git.proxmox.com Git - mirror_frr.git/blame - zebra/rt_socket.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / zebra / rt_socket.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
718e3744 2/*
3 * Kernel routing table updates by routing socket.
4 * Copyright (C) 1997, 98 Kunihiro Ishiguro
718e3744 5 */
6
7#include <zebra.h>
ddfeb486
DL
8
9#ifndef HAVE_NETLINK
10
fe6c7157 11#ifdef __OpenBSD__
d3e2c74a
RW
12#include <netmpls/mpls.h>
13#endif
718e3744 14
15#include "if.h"
16#include "prefix.h"
17#include "sockunion.h"
18#include "log.h"
edd7c245 19#include "privs.h"
13d60d35 20#include "vxlan.h"
174482ef 21#include "lib_errors.h"
718e3744 22
23#include "zebra/debug.h"
24#include "zebra/rib.h"
6621ca86 25#include "zebra/rt.h"
dc95824a 26#include "zebra/kernel_socket.h"
d3e2c74a 27#include "zebra/zebra_mpls.h"
364fed6b 28#include "zebra/zebra_errors.h"
718e3744 29
edd7c245 30extern struct zebra_privs_t zserv_privs;
31
5e8c8947 32#ifdef __OpenBSD__
8ecdb26e 33static int kernel_rtm_add_labels(struct mpls_label_stack *nh_label,
5e8c8947
RW
34 struct sockaddr_mpls *smpls)
35{
36 if (nh_label->num_labels > 1) {
e914ccbe 37 flog_warn(EC_ZEBRA_MAX_LABELS_PUSH,
3efd0893 38 "%s: can't push %u labels at once (maximum is 1)",
9df414fe 39 __func__, nh_label->num_labels);
5e8c8947
RW
40 return -1;
41 }
42
43 memset(smpls, 0, sizeof(*smpls));
44 smpls->smpls_len = sizeof(*smpls);
45 smpls->smpls_family = AF_MPLS;
46 smpls->smpls_label = htonl(nh_label->label[0] << MPLS_LABEL_OFFSET);
47
48 return 0;
49}
50#endif
51
718e3744 52/* Interface between zebra message and rtm message. */
08ea27d1
DS
53static int kernel_rtm(int cmd, const struct prefix *p,
54 const struct nexthop_group *ng, uint32_t metric)
718e3744 55
56{
ca2c70bd 57 union sockunion sin_dest, sin_mask, sin_gate;
fe6c7157 58#ifdef __OpenBSD__
d62a17ae 59 struct sockaddr_mpls smpls;
d3e2c74a 60#endif
d62a17ae 61 union sockunion *smplsp = NULL;
62 struct nexthop *nexthop;
63 int nexthop_num = 0;
64 ifindex_t ifindex = 0;
4dd39a0e 65 bool gate = false;
d62a17ae 66 int error;
981dc13f 67 char gate_buf[INET6_BUFSIZ];
a8309422 68 enum blackhole_type bh_type = BLACKHOLE_UNSPEC;
d62a17ae 69
86afd529
DS
70 /*
71 * We only have the ability to ADD or DELETE at this point
72 * in time.
73 */
74 if (cmd != RTM_ADD && cmd != RTM_DELETE) {
75 if (IS_ZEBRA_DEBUG_KERNEL)
2dbe669b 76 zlog_debug("%s: %pFX odd command %s", __func__, p,
5ea8213f 77 lookup_msg(rtm_type_str, cmd, NULL));
86afd529
DS
78 return 0;
79 }
80
08ea27d1
DS
81 memset(&sin_dest, 0, sizeof(sin_dest));
82 memset(&sin_gate, 0, sizeof(sin_gate));
ca2c70bd 83 memset(&sin_mask, 0, sizeof(sin_mask));
718e3744 84
08ea27d1
DS
85 switch (p->family) {
86 case AF_INET:
87 sin_dest.sin.sin_family = AF_INET;
08ea27d1
DS
88 sin_dest.sin.sin_addr = p->u.prefix4;
89 sin_gate.sin.sin_family = AF_INET;
0413dd75
RZ
90#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
91 sin_dest.sin.sin_len = sizeof(struct sockaddr_in);
92 sin_gate.sin.sin_len = sizeof(struct sockaddr_in);
93#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
08ea27d1
DS
94 break;
95 case AF_INET6:
96 sin_dest.sin6.sin6_family = AF_INET6;
08ea27d1
DS
97 sin_dest.sin6.sin6_addr = p->u.prefix6;
98 sin_gate.sin6.sin6_family = AF_INET6;
0413dd75
RZ
99#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
100 sin_dest.sin6.sin6_len = sizeof(struct sockaddr_in6);
101 sin_gate.sin6.sin6_len = sizeof(struct sockaddr_in6);
102#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
08ea27d1
DS
103 break;
104 }
718e3744 105
d62a17ae 106 /* Make gateway. */
01ce7cba 107 for (ALL_NEXTHOPS_PTR(ng, nexthop)) {
86afd529
DS
108 /*
109 * We only want to use the actual good nexthops
110 */
111 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ||
112 !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
d62a17ae 113 continue;
114
c2519893 115 smplsp = NULL;
4dd39a0e 116 gate = false;
981dc13f 117 snprintf(gate_buf, sizeof(gate_buf), "NULL");
d62a17ae 118
86afd529
DS
119 switch (nexthop->type) {
120 case NEXTHOP_TYPE_IPV4:
121 case NEXTHOP_TYPE_IPV4_IFINDEX:
122 sin_gate.sin.sin_addr = nexthop->gate.ipv4;
123 sin_gate.sin.sin_family = AF_INET;
0413dd75
RZ
124#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
125 sin_gate.sin.sin_len = sizeof(struct sockaddr_in);
126#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
86afd529 127 ifindex = nexthop->ifindex;
4dd39a0e 128 gate = true;
86afd529
DS
129 break;
130 case NEXTHOP_TYPE_IPV6:
131 case NEXTHOP_TYPE_IPV6_IFINDEX:
132 sin_gate.sin6.sin6_addr = nexthop->gate.ipv6;
133 sin_gate.sin6.sin6_family = AF_INET6;
0413dd75
RZ
134#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
135 sin_gate.sin6.sin6_len = sizeof(struct sockaddr_in6);
136#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
86afd529 137 ifindex = nexthop->ifindex;
08ea27d1
DS
138/* Under kame set interface index to link local address */
139#ifdef KAME
140
141#define SET_IN6_LINKLOCAL_IFINDEX(a, i) \
c9277ebb
DS
142 do { \
143 (a).s6_addr[2] = ((i) >> 8) & 0xff; \
144 (a).s6_addr[3] = (i)&0xff; \
145 } while (0)
08ea27d1 146
86afd529
DS
147 if (IN6_IS_ADDR_LINKLOCAL(&sin_gate.sin6.sin6_addr))
148 SET_IN6_LINKLOCAL_IFINDEX(
149 sin_gate.sin6.sin6_addr,
150 ifindex);
08ea27d1
DS
151#endif /* KAME */
152
4dd39a0e 153 gate = true;
86afd529
DS
154 break;
155 case NEXTHOP_TYPE_IFINDEX:
156 ifindex = nexthop->ifindex;
157 break;
158 case NEXTHOP_TYPE_BLACKHOLE:
159 bh_type = nexthop->bh_type;
160 switch (p->family) {
c3d6b386 161 case AF_INET: {
86afd529 162 struct in_addr loopback;
381477e8 163
86afd529
DS
164 loopback.s_addr = htonl(INADDR_LOOPBACK);
165 sin_gate.sin.sin_addr = loopback;
0413dd75
RZ
166#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
167 sin_gate.sin.sin_len =
168 sizeof(struct sockaddr_in);
169#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
4dd39a0e 170 gate = true;
381477e8
DS
171 } break;
172 case AF_INET6: {
173 struct in6_addr loopback;
174
175 inet_pton(AF_INET6, "::1", &loopback);
176
177 sin_gate.sin6.sin6_addr = loopback;
178 sin_gate.sin6.sin6_family = AF_INET6;
179
180#ifdef HAVE_STRUCTSOCKADDR_SA_LEN
181 sin_gate.sin6.sin6_len =
182 sizeof(struct sockaddr_in6);
183#endif /* HAVE_STRUCTSOCKADDR_SA_LEN */
184 gate = true;
185 } break;
d62a17ae 186 }
86afd529
DS
187 }
188
189 switch (p->family) {
190 case AF_INET:
18d10d88
DS
191 masklen2ip(p->prefixlen, &sin_mask.sin.sin_addr);
192 sin_mask.sin.sin_family = AF_INET;
0413dd75
RZ
193#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
194 sin_mask.sin.sin_len = sizeof(struct sockaddr_in);
195#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
86afd529
DS
196 break;
197 case AF_INET6:
18d10d88
DS
198 masklen2ip6(p->prefixlen, &sin_mask.sin6.sin6_addr);
199 sin_mask.sin6.sin6_family = AF_INET6;
0413dd75
RZ
200#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
201 sin_mask.sin6.sin6_len = sizeof(struct sockaddr_in6);
202#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
86afd529
DS
203 break;
204 }
718e3744 205
fe6c7157 206#ifdef __OpenBSD__
b24204be
MS
207 if (nexthop->nh_label) {
208 if (kernel_rtm_add_labels(nexthop->nh_label,
209 &smpls) != 0)
210 continue;
211 smplsp = (union sockunion *)&smpls;
212 }
d3e2c74a 213#endif
18d10d88 214 error = rtm_write(cmd, &sin_dest, &sin_mask,
86afd529
DS
215 gate ? &sin_gate : NULL, smplsp,
216 ifindex, bh_type, metric);
217
218 if (IS_ZEBRA_DEBUG_KERNEL) {
219 if (!gate) {
981dc13f 220 zlog_debug(
2dbe669b
DA
221 "%s: %pFX: attention! gate not found for re",
222 __func__, p);
981dc13f
RZ
223 } else {
224 switch (p->family) {
c3d6b386 225 case AF_INET:
981dc13f
RZ
226 inet_ntop(AF_INET,
227 &sin_gate.sin.sin_addr,
228 gate_buf, sizeof(gate_buf));
229 break;
230
c3d6b386 231 case AF_INET6:
981dc13f
RZ
232 inet_ntop(AF_INET6,
233 &sin_gate.sin6.sin6_addr,
234 gate_buf, sizeof(gate_buf));
235 break;
236
237 default:
238 snprintf(gate_buf, sizeof(gate_buf),
239 "(invalid-af)");
240 break;
241 }
242 }
86afd529
DS
243 }
244 switch (error) {
245 /* We only flag nexthops as being in FIB if
246 * rtm_write() did its work. */
247 case ZEBRA_ERR_NOERROR:
248 nexthop_num++;
249 if (IS_ZEBRA_DEBUG_KERNEL)
2dbe669b
DA
250 zlog_debug("%s: %pFX: successfully did NH %s",
251 __func__, p, gate_buf);
86afd529
DS
252 if (cmd == RTM_ADD)
253 SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
254 break;
255
256 /* The only valid case for this error is
257 * kernel's failure to install a multipath
258 * route, which is common for FreeBSD. This
259 * should be ignored silently, but logged as an error
260 * otherwise.
261 */
262 case ZEBRA_ERR_RTEXIST:
263 if (cmd != RTM_ADD)
264 flog_err(EC_LIB_SYSTEM_CALL,
265 "%s: rtm_write() returned %d for command %d",
266 __func__, error, cmd);
267 continue;
d62a17ae 268
86afd529 269 /* Note any unexpected status returns */
f2f2a16a
DS
270 case ZEBRA_ERR_RTNOEXIST:
271 if (cmd != RTM_DELETE)
272 flog_err(EC_LIB_SYSTEM_CALL,
273 "%s: rtm_write() returned %d for command %d",
274 __func__, error, cmd);
275 break;
86afd529 276 default:
31be7dbb
RZ
277 flog_err(
278 EC_LIB_SYSTEM_CALL,
2dbe669b
DA
279 "%s: %pFX: rtm_write() unexpectedly returned %d for command %s",
280 __func__, p, error,
31be7dbb 281 lookup_msg(rtm_type_str, cmd, NULL));
86afd529
DS
282 break;
283 }
d62a17ae 284 } /* for (ALL_NEXTHOPS(...))*/
285
286 /* If there was no useful nexthop, then complain. */
560e3136
DS
287 if (nexthop_num == 0) {
288 if (IS_ZEBRA_DEBUG_KERNEL)
31be7dbb 289 zlog_debug(
2dbe669b
DA
290 "%s: No useful nexthops were found in RIB prefix %pFX",
291 __func__, p);
560e3136
DS
292 return 1;
293 }
d62a17ae 294
295 return 0; /*XXX*/
718e3744 296}
297
01ce7cba
MS
298/*
299 * Update or delete a prefix from the kernel,
300 * using info from a dataplane context struct.
301 */
25779064 302enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx)
01ce7cba
MS
303{
304 enum zebra_dplane_result res = ZEBRA_DPLANE_REQUEST_SUCCESS;
3cdba47a 305 uint32_t type, old_type;
01ce7cba
MS
306
307 if (dplane_ctx_get_src(ctx) != NULL) {
308 zlog_err("route add: IPv6 sourcedest routes unsupported!");
e677d109 309 return ZEBRA_DPLANE_REQUEST_FAILURE;
01ce7cba
MS
310 }
311
3cdba47a
DS
312 type = dplane_ctx_get_type(ctx);
313 old_type = dplane_ctx_get_old_type(ctx);
314
0cf6db21 315 frr_with_privs(&zserv_privs) {
f183e380 316
3cdba47a
DS
317 if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_DELETE) {
318 if (!RSYSTEM_ROUTE(type))
319 kernel_rtm(RTM_DELETE, dplane_ctx_get_dest(ctx),
320 dplane_ctx_get_ng(ctx),
321 dplane_ctx_get_metric(ctx));
322 } else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_INSTALL) {
323 if (!RSYSTEM_ROUTE(type))
324 kernel_rtm(RTM_ADD, dplane_ctx_get_dest(ctx),
325 dplane_ctx_get_ng(ctx),
326 dplane_ctx_get_metric(ctx));
327 } else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_UPDATE) {
f183e380
MS
328 /* Must do delete and add separately -
329 * no update available
330 */
3cdba47a
DS
331 if (!RSYSTEM_ROUTE(old_type))
332 kernel_rtm(RTM_DELETE, dplane_ctx_get_dest(ctx),
333 dplane_ctx_get_old_ng(ctx),
334 dplane_ctx_get_old_metric(ctx));
335
336 if (!RSYSTEM_ROUTE(type))
337 kernel_rtm(RTM_ADD, dplane_ctx_get_dest(ctx),
338 dplane_ctx_get_ng(ctx),
339 dplane_ctx_get_metric(ctx));
f183e380
MS
340 } else {
341 zlog_err("Invalid routing socket update op %s (%u)",
342 dplane_op2str(dplane_ctx_get_op(ctx)),
343 dplane_ctx_get_op(ctx));
344 res = ZEBRA_DPLANE_REQUEST_FAILURE;
345 }
346 } /* Elevated privs */
01ce7cba 347
01ce7cba
MS
348 return res;
349}
350
07cc1745
SW
351enum zebra_dplane_result kernel_nexthop_update(struct zebra_dplane_ctx *ctx)
352{
353 return ZEBRA_DPLANE_REQUEST_SUCCESS;
354}
355
7723e8d3
PG
356int kernel_neigh_register(vrf_id_t vrf_id, struct zserv *client, bool reg)
357{
358 /* TODO */
359 return 0;
360}
361
05657ec2
PG
362int kernel_neigh_update(int add, int ifindex, void *addr, char *lla, int llalen,
363 ns_id_t ns_id, uint8_t family, bool permanent)
6b8a5694 364{
d62a17ae 365 /* TODO */
366 return 0;
6b8a5694 367}
1498c059 368
931fa60c
MS
369/* NYI on routing-socket platforms, but we've always returned 'success'... */
370enum zebra_dplane_result kernel_neigh_update_ctx(struct zebra_dplane_ctx *ctx)
371{
372 return ZEBRA_DPLANE_REQUEST_SUCCESS;
373}
374
43b5cc5e 375extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute)
1498c059 376{
d62a17ae 377 return 0;
1498c059 378}
13d60d35 379
036d93c0
MS
380/*
381 * Update MAC, using dataplane context object. No-op here for now.
382 */
383enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx)
2232a77c 384{
036d93c0 385 return ZEBRA_DPLANE_REQUEST_SUCCESS;
2232a77c 386}
387
e0ae31b8
DS
388extern int kernel_interface_set_master(struct interface *master,
389 struct interface *slave)
390{
391 return 0;
392}
0ecfe5bf 393
594c2878 394uint32_t kernel_get_speed(struct interface *ifp, int *error)
dc7b3cae
DS
395{
396 return ifp->speed;
397}
398
265fa78d
AK
399int kernel_upd_mac_nh(uint32_t nh_id, struct in_addr vtep_ip)
400{
401 return 0;
402}
403
404int kernel_del_mac_nh(uint32_t nh_id)
405{
406 return 0;
407}
408
409int kernel_upd_mac_nhg(uint32_t nhg_id, uint32_t nh_cnt,
410 struct nh_grp *nh_ids)
411{
412 return 0;
413}
414
415int kernel_del_mac_nhg(uint32_t nhg_id)
416{
417 return 0;
418}
419
ddfeb486 420#endif /* !HAVE_NETLINK */