]> git.proxmox.com Git - mirror_frr.git/blame - zebra/rt_netlink.c
Merge pull request #679 from dslicenc/cm16513
[mirror_frr.git] / zebra / rt_netlink.c
CommitLineData
718e3744 1/* Kernel routing table updates using netlink over GNU/Linux system.
2 * Copyright (C) 1997, 98, 99 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 *
896014f4
DL
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
718e3744 19 */
20
21#include <zebra.h>
8ccc7e80 22#include <net/if_arp.h>
718e3744 23
24/* Hack for GNU libc version 2. */
25#ifndef MSG_TRUNC
26#define MSG_TRUNC 0x20
27#endif /* MSG_TRUNC */
28
29#include "linklist.h"
30#include "if.h"
31#include "log.h"
32#include "prefix.h"
33#include "connected.h"
34#include "table.h"
26e2ae36 35#include "memory.h"
4a1ab8e4 36#include "zebra_memory.h"
718e3744 37#include "rib.h"
e04ab74d 38#include "thread.h"
edd7c245 39#include "privs.h"
fb018d25 40#include "nexthop.h"
78104b9b 41#include "vrf.h"
5e6a74d8 42#include "vty.h"
40c7bdb0 43#include "mpls.h"
718e3744 44
45#include "zebra/zserv.h"
fe18ee2d 46#include "zebra/zebra_ns.h"
7c551956 47#include "zebra/zebra_vrf.h"
6621ca86 48#include "zebra/rt.h"
718e3744 49#include "zebra/redistribute.h"
50#include "zebra/interface.h"
51#include "zebra/debug.h"
12f6fb97 52#include "zebra/rtadv.h"
567b877d 53#include "zebra/zebra_ptm.h"
40c7bdb0 54#include "zebra/zebra_mpls.h"
1fdc9eae 55#include "zebra/kernel_netlink.h"
56#include "zebra/rt_netlink.h"
e3be0432
DS
57#include "zebra/zebra_mroute.h"
58
7021c425 59
40c7bdb0 60/* TODO - Temporary definitions, need to refine. */
61#ifndef AF_MPLS
62#define AF_MPLS 28
63#endif
64
65#ifndef RTA_VIA
c0f4be83 66#define RTA_VIA 18
40c7bdb0 67#endif
68
69#ifndef RTA_NEWDST
70#define RTA_NEWDST 19
71#endif
c0f4be83 72
73#ifndef RTA_ENCAP_TYPE
74#define RTA_ENCAP_TYPE 21
75#endif
76
77#ifndef RTA_ENCAP
78#define RTA_ENCAP 22
79#endif
80
113db945
DS
81#ifndef RTA_EXPIRES
82#define RTA_EXPIRES 23
83#endif
84
c0f4be83 85#ifndef LWTUNNEL_ENCAP_MPLS
86#define LWTUNNEL_ENCAP_MPLS 1
87#endif
88
89#ifndef MPLS_IPTUNNEL_DST
90#define MPLS_IPTUNNEL_DST 1
91#endif
52d8f0d8
DS
92
93#ifndef NDA_MASTER
94#define NDA_MASTER 9
95#endif
40c7bdb0 96/* End of temporary definitions */
97
98struct gw_family_t
99{
100 u_int16_t filler;
101 u_int16_t family;
102 union g_addr gate;
103};
104
8755598a
DS
105char ipv4_ll_buf[16] = "169.254.0.1";
106struct in_addr ipv4_ll;
107
108/*
109 * The ipv4_ll data structure is used for all 5549
110 * additions to the kernel. Let's figure out the
111 * correct value one time instead for every
112 * install/remove of a 5549 type route
113 */
114void
115rt_netlink_init (void)
116{
117 inet_pton (AF_INET, ipv4_ll_buf, &ipv4_ll);
118}
119
23b1f334
DD
120static inline int is_selfroute(int proto)
121{
122 if ((proto == RTPROT_BGP) || (proto == RTPROT_OSPF) ||
123 (proto == RTPROT_STATIC) || (proto == RTPROT_ZEBRA) ||
1f047d8d
DS
124 (proto == RTPROT_ISIS) || (proto == RTPROT_RIPNG) ||
125 (proto == RTPROT_NHRP) || (proto == RTPROT_EIGRP) ||
126 (proto == RTPROT_LDP)) {
23b1f334
DD
127 return 1;
128 }
129
130 return 0;
131}
132
133static inline int get_rt_proto(int proto)
134{
135 switch (proto) {
136 case ZEBRA_ROUTE_BGP:
137 proto = RTPROT_BGP;
138 break;
139 case ZEBRA_ROUTE_OSPF:
140 case ZEBRA_ROUTE_OSPF6:
141 proto = RTPROT_OSPF;
142 break;
143 case ZEBRA_ROUTE_STATIC:
144 proto = RTPROT_STATIC;
145 break;
146 case ZEBRA_ROUTE_ISIS:
147 proto = RTPROT_ISIS;
148 break;
149 case ZEBRA_ROUTE_RIP:
150 proto = RTPROT_RIP;
151 break;
152 case ZEBRA_ROUTE_RIPNG:
153 proto = RTPROT_RIPNG;
154 break;
1f047d8d
DS
155 case ZEBRA_ROUTE_NHRP:
156 proto = RTPROT_NHRP;
157 break;
158 case ZEBRA_ROUTE_EIGRP:
159 proto = RTPROT_EIGRP;
160 break;
161 case ZEBRA_ROUTE_LDP:
162 proto = RTPROT_LDP;
163 break;
23b1f334
DD
164 default:
165 proto = RTPROT_ZEBRA;
166 break;
167 }
168
169 return proto;
170}
171
12f6fb97
DS
172/*
173Pending: create an efficient table_id (in a tree/hash) based lookup)
174 */
175static vrf_id_t
176vrf_lookup_by_table (u_int32_t table_id)
177{
1a1a7065 178 struct vrf *vrf;
12f6fb97 179 struct zebra_vrf *zvrf;
12f6fb97 180
1a1a7065 181 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
12f6fb97 182 {
1a1a7065 183 if ((zvrf = vrf->info) == NULL ||
12f6fb97
DS
184 (zvrf->table_id != table_id))
185 continue;
186
661512bf 187 return zvrf_id (zvrf);
12f6fb97
DS
188 }
189
190 return VRF_DEFAULT;
191}
192
718e3744 193/* Looking up routing table by netlink interface. */
6072b24e 194static int
89a9069a
DS
195netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h,
196 ns_id_t ns_id, int startup)
718e3744 197{
198 int len;
199 struct rtmsg *rtm;
7021c425 200 struct rtattr *tb[RTA_MAX + 1];
718e3744 201 u_char flags = 0;
3b1098be 202 struct prefix p;
05737783 203 struct prefix_ipv6 src_p;
d552ed06 204 vrf_id_t vrf_id = VRF_DEFAULT;
7021c425 205
206 char anyaddr[16] = { 0 };
718e3744 207
05737783 208 int index = 0;
718e3744 209 int table;
05737783 210 int metric = 0;
c50ca33a 211 u_int32_t mtu = 0;
34195bf6 212
05737783
CF
213 void *dest = NULL;
214 void *gate = NULL;
215 void *prefsrc = NULL; /* IPv4 preferred source host address */
216 void *src = NULL; /* IPv6 srcdest source prefix */
718e3744 217
218 rtm = NLMSG_DATA (h);
219
89a9069a 220 if (startup && h->nlmsg_type != RTM_NEWROUTE)
718e3744 221 return 0;
89a9069a 222 if (startup && rtm->rtm_type != RTN_UNICAST)
718e3744 223 return 0;
224
7021c425 225 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
718e3744 226 if (len < 0)
227 return -1;
228
229 memset (tb, 0, sizeof tb);
230 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
231
232 if (rtm->rtm_flags & RTM_F_CLONED)
233 return 0;
234 if (rtm->rtm_protocol == RTPROT_REDIRECT)
235 return 0;
236 if (rtm->rtm_protocol == RTPROT_KERNEL)
237 return 0;
238
89a9069a 239 if (!startup &&
23b1f334 240 is_selfroute (rtm->rtm_protocol) &&
89a9069a
DS
241 h->nlmsg_type == RTM_NEWROUTE)
242 return 0;
243
40c7bdb0 244 /* We don't care about change notifications for the MPLS table. */
245 /* TODO: Revisit this. */
246 if (rtm->rtm_family == AF_MPLS)
247 return 0;
248
ca46a78e 249 /* Table corresponding to route. */
250 if (tb[RTA_TABLE])
251 table = *(int *) RTA_DATA (tb[RTA_TABLE]);
252 else
253 table = rtm->rtm_table;
254
255 /* Map to VRF */
256 vrf_id = vrf_lookup_by_table(table);
257 if (vrf_id == VRF_DEFAULT)
258 {
259 if (!is_zebra_valid_kernel_table(table) &&
260 !is_zebra_main_routing_table(table))
261 return 0;
262 }
263
718e3744 264 /* Route which inserted by Zebra. */
23b1f334 265 if (is_selfroute(rtm->rtm_protocol))
718e3744 266 flags |= ZEBRA_FLAG_SELFROUTE;
7021c425 267
718e3744 268 if (tb[RTA_OIF])
269 index = *(int *) RTA_DATA (tb[RTA_OIF]);
270
271 if (tb[RTA_DST])
272 dest = RTA_DATA (tb[RTA_DST]);
273 else
274 dest = anyaddr;
275
05737783
CF
276 if (tb[RTA_SRC])
277 src = RTA_DATA (tb[RTA_SRC]);
278 else
279 src = anyaddr;
280
7514fb77 281 if (tb[RTA_PREFSRC])
05737783 282 prefsrc = RTA_DATA (tb[RTA_PREFSRC]);
7514fb77 283
718e3744 284 if (tb[RTA_GATEWAY])
285 gate = RTA_DATA (tb[RTA_GATEWAY]);
286
c50ca33a
TT
287 if (h->nlmsg_type == RTM_NEWROUTE)
288 {
289 if (tb[RTA_PRIORITY])
290 metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
291
292 if (tb[RTA_METRICS])
293 {
294 struct rtattr *mxrta[RTAX_MAX+1];
295
296 memset (mxrta, 0, sizeof mxrta);
297 netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),
298 RTA_PAYLOAD(tb[RTA_METRICS]));
299
300 if (mxrta[RTAX_MTU])
301 mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]);
302 }
303 }
26e2ae36 304
718e3744 305 if (rtm->rtm_family == AF_INET)
306 {
718e3744 307 p.family = AF_INET;
616368ed 308 memcpy (&p.u.prefix4, dest, 4);
718e3744 309 p.prefixlen = rtm->rtm_dst_len;
a2ca67d1
DS
310 }
311 else if (rtm->rtm_family == AF_INET6)
312 {
313 p.family = AF_INET6;
314 memcpy (&p.u.prefix6, dest, 16);
315 p.prefixlen = rtm->rtm_dst_len;
718e3744 316
a2ca67d1
DS
317 src_p.family = AF_INET6;
318 memcpy (&src_p.prefix, src, 16);
319 src_p.prefixlen = rtm->rtm_src_len;
320 }
05737783 321
a2ca67d1
DS
322 if (rtm->rtm_src_len != 0)
323 {
324 char buf[PREFIX_STRLEN];
325 zlog_warn ("unsupported IPv[4|6] sourcedest route (dest %s vrf %u)",
326 prefix2str (&p, buf, sizeof(buf)), vrf_id);
327 return 0;
328 }
329
330 if (IS_ZEBRA_DEBUG_KERNEL)
331 {
332 char buf[PREFIX_STRLEN];
333 char buf2[PREFIX_STRLEN];
334 zlog_debug ("%s %s%s%s vrf %u",
335 nl_msg_type_to_str (h->nlmsg_type),
336 prefix2str (&p, buf, sizeof(buf)),
337 src_p.prefixlen ? " from " : "",
338 src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2)) : "",
339 vrf_id);
340 }
718e3744 341
a2ca67d1
DS
342 afi_t afi = AFI_IP;
343 if (rtm->rtm_family == AF_INET6)
344 afi = AFI_IP6;
345
346 if (h->nlmsg_type == RTM_NEWROUTE)
347 {
348 if (!tb[RTA_MULTIPATH])
349 rib_add (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
350 0, flags, &p, NULL, gate, prefsrc, index,
351 table, metric, mtu, 0);
352 else
26e2ae36 353 {
a2ca67d1
DS
354 /* This is a multipath route */
355
f0f77c9a 356 struct route_entry *re;
a2ca67d1
DS
357 struct rtnexthop *rtnh =
358 (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
359
360 len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
361
f0f77c9a
DS
362 re = XCALLOC (MTYPE_RE, sizeof (struct route_entry));
363 re->type = ZEBRA_ROUTE_KERNEL;
364 re->distance = 0;
365 re->flags = flags;
366 re->metric = metric;
367 re->mtu = mtu;
368 re->vrf_id = vrf_id;
369 re->table = table;
370 re->nexthop_num = 0;
371 re->uptime = time (NULL);
a2ca67d1
DS
372
373 for (;;)
26e2ae36 374 {
a2ca67d1
DS
375 if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
376 break;
26e2ae36 377
a2ca67d1
DS
378 index = rtnh->rtnh_ifindex;
379 gate = 0;
380 if (rtnh->rtnh_len > sizeof (*rtnh))
381 {
382 memset (tb, 0, sizeof (tb));
383 netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
384 rtnh->rtnh_len - sizeof (*rtnh));
385 if (tb[RTA_GATEWAY])
386 gate = RTA_DATA (tb[RTA_GATEWAY]);
387 }
26e2ae36 388
a2ca67d1
DS
389 if (gate)
390 {
391 if (rtm->rtm_family == AF_INET)
26e2ae36
JB
392 {
393 if (index)
f0f77c9a 394 route_entry_nexthop_ipv4_ifindex_add (re, gate, prefsrc, index);
26e2ae36 395 else
f0f77c9a 396 route_entry_nexthop_ipv4_add (re, gate, prefsrc);
26e2ae36 397 }
a2ca67d1
DS
398 else if (rtm->rtm_family == AF_INET6)
399 {
400 if (index)
f0f77c9a 401 route_entry_nexthop_ipv6_ifindex_add (re, gate, index);
a2ca67d1 402 else
f0f77c9a 403 route_entry_nexthop_ipv6_add (re,gate);
a2ca67d1 404 }
1fdc9eae 405 }
1fdc9eae 406 else
f0f77c9a 407 route_entry_nexthop_ifindex_add (re, index);
26e2ae36 408
a2ca67d1
DS
409 len -= NLMSG_ALIGN(rtnh->rtnh_len);
410 rtnh = RTNH_NEXT(rtnh);
411 }
05737783 412
a2ca67d1 413 zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
f0f77c9a
DS
414 re->nexthop_num);
415 if (re->nexthop_num == 0)
416 XFREE (MTYPE_RE, re);
a2ca67d1 417 else
f0f77c9a 418 rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, NULL, re);
7021c425 419 }
718e3744 420 }
a2ca67d1 421 else
2f8685a2
DS
422 {
423 if (!tb[RTA_MULTIPATH])
424 rib_delete (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags,
425 &p, NULL, gate, index, table);
426 else
427 {
428 struct rtnexthop *rtnh =
429 (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
430
431 len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
432
433 for (;;)
434 {
435 if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
436 break;
437
438 gate = NULL;
439 if (rtnh->rtnh_len > sizeof (*rtnh))
440 {
441 memset (tb, 0, sizeof (tb));
442 netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
443 rtnh->rtnh_len - sizeof (*rtnh));
444 if (tb[RTA_GATEWAY])
445 gate = RTA_DATA (tb[RTA_GATEWAY]);
446 }
447
448 if (gate)
449 rib_delete (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags,
450 &p, NULL, gate, index, table);
451
452 len -= NLMSG_ALIGN(rtnh->rtnh_len);
453 rtnh = RTNH_NEXT(rtnh);
454 }
455 }
456 }
718e3744 457
458 return 0;
459}
460
e3be0432
DS
461static struct mcast_route_data *mroute = NULL;
462
565fdc75
DS
463static int
464netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h,
936ebf0a 465 ns_id_t ns_id, int startup)
565fdc75
DS
466{
467 int len;
468 struct rtmsg *rtm;
469 struct rtattr *tb[RTA_MAX + 1];
e3be0432
DS
470 struct mcast_route_data *m;
471 struct mcast_route_data mr;
90d82769
DS
472 int iif = 0;
473 int count;
474 int oif[256];
475 int oif_count = 0;
476 char sbuf[40];
477 char gbuf[40];
478 char oif_list[256] = "\0";
90d82769 479 vrf_id_t vrf = ns_id;
565fdc75 480
e3be0432
DS
481 if (mroute)
482 m = mroute;
483 else
f0242f68
DS
484 {
485 memset (&mr, 0, sizeof (mr));
486 m = &mr;
487 }
e3be0432 488
565fdc75
DS
489 rtm = NLMSG_DATA (h);
490
491 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
492
493 memset (tb, 0, sizeof tb);
494 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
495
90d82769
DS
496 if (tb[RTA_IIF])
497 iif = *(int *)RTA_DATA (tb[RTA_IIF]);
498
499 if (tb[RTA_SRC])
e3be0432 500 m->sg.src = *(struct in_addr *)RTA_DATA (tb[RTA_SRC]);
90d82769
DS
501
502 if (tb[RTA_DST])
e3be0432 503 m->sg.grp = *(struct in_addr *)RTA_DATA (tb[RTA_DST]);
90d82769 504
113db945 505 if ((RTA_EXPIRES <= RTA_MAX) && tb[RTA_EXPIRES])
e3be0432 506 m->lastused = *(unsigned long long *)RTA_DATA (tb[RTA_EXPIRES]);
90d82769
DS
507
508 if (tb[RTA_MULTIPATH])
509 {
510 struct rtnexthop *rtnh =
511 (struct rtnexthop *)RTA_DATA (tb[RTA_MULTIPATH]);
512
513 len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
514 for (;;)
515 {
516 if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
517 break;
518
519 oif[oif_count] = rtnh->rtnh_ifindex;
520 oif_count++;
521
522 len -= NLMSG_ALIGN (rtnh->rtnh_len);
523 rtnh = RTNH_NEXT (rtnh);
524 }
525 }
526
527 if (IS_ZEBRA_DEBUG_KERNEL)
528 {
82d64e8e 529 struct interface *ifp;
e3be0432
DS
530 strcpy (sbuf, inet_ntoa (m->sg.src));
531 strcpy (gbuf, inet_ntoa (m->sg.grp));
90d82769
DS
532 for (count = 0; count < oif_count; count++)
533 {
7e2b7603 534 ifp = if_lookup_by_index (oif[count], vrf);
90d82769
DS
535 char temp[256];
536
537 sprintf (temp, "%s ", ifp->name);
538 strcat (oif_list, temp);
539 }
7e2b7603 540 ifp = if_lookup_by_index (iif, vrf);
82d64e8e
DS
541 zlog_debug ("MCAST %s (%s,%s) IIF: %s OIF: %s jiffies: %lld",
542 nl_msg_type_to_str(h->nlmsg_type), sbuf, gbuf, ifp->name, oif_list, m->lastused);
90d82769 543 }
565fdc75
DS
544 return 0;
545}
546
547int
548netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
936ebf0a 549 ns_id_t ns_id, int startup)
565fdc75
DS
550{
551 int len;
552 vrf_id_t vrf_id = ns_id;
553 struct rtmsg *rtm;
554
555 rtm = NLMSG_DATA (h);
556
557 if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
558 {
559 /* If this is not route add/delete message print warning. */
560 zlog_warn ("Kernel message: %d vrf %u\n", h->nlmsg_type, vrf_id);
561 return 0;
562 }
563
564 /* Connected route. */
565 if (IS_ZEBRA_DEBUG_KERNEL)
566 zlog_debug ("%s %s %s proto %s vrf %u",
90d82769
DS
567 nl_msg_type_to_str (h->nlmsg_type),
568 nl_family_to_str (rtm->rtm_family),
569 nl_rttype_to_str (rtm->rtm_type),
565fdc75 570 nl_rtproto_to_str (rtm->rtm_protocol),
90d82769 571 vrf_id);
565fdc75
DS
572
573 /* We don't care about change notifications for the MPLS table. */
574 /* TODO: Revisit this. */
575 if (rtm->rtm_family == AF_MPLS)
576 return 0;
577
578 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
579 if (len < 0)
580 return -1;
581
582 switch (rtm->rtm_type)
583 {
584 case RTN_UNICAST:
936ebf0a 585 netlink_route_change_read_unicast (snl, h, ns_id, startup);
565fdc75
DS
586 break;
587 case RTN_MULTICAST:
936ebf0a 588 netlink_route_change_read_multicast (snl, h, ns_id, startup);
565fdc75
DS
589 break;
590 default:
591 return 0;
592 break;
593 }
594
595 return 0;
596}
597
718e3744 598/* Routing table read function using netlink interface. Only called
599 bootstrap time. */
600int
12f6fb97 601netlink_route_read (struct zebra_ns *zns)
718e3744 602{
603 int ret;
7021c425 604
718e3744 605 /* Get IPv4 routing table. */
12f6fb97 606 ret = netlink_request (AF_INET, RTM_GETROUTE, &zns->netlink_cmd);
718e3744 607 if (ret < 0)
608 return ret;
89a9069a 609 ret = netlink_parse_info (netlink_route_change_read_unicast, &zns->netlink_cmd, zns, 0, 1);
718e3744 610 if (ret < 0)
611 return ret;
612
718e3744 613 /* Get IPv6 routing table. */
12f6fb97 614 ret = netlink_request (AF_INET6, RTM_GETROUTE, &zns->netlink_cmd);
718e3744 615 if (ret < 0)
616 return ret;
89a9069a 617 ret = netlink_parse_info (netlink_route_change_read_unicast, &zns->netlink_cmd, zns, 0, 1);
718e3744 618 if (ret < 0)
619 return ret;
718e3744 620
621 return 0;
622}
623
40c7bdb0 624static void
625_netlink_route_nl_add_gateway_info (u_char route_family, u_char gw_family,
626 struct nlmsghdr *nlmsg,
627 size_t req_size, int bytelen,
628 struct nexthop *nexthop)
629{
630 if (route_family == AF_MPLS)
631 {
632 struct gw_family_t gw_fam;
633
634 gw_fam.family = gw_family;
635 if (gw_family == AF_INET)
636 memcpy (&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen);
637 else
638 memcpy (&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen);
639 addattr_l (nlmsg, req_size, RTA_VIA, &gw_fam.family, bytelen+2);
640 }
641 else
642 {
643 if (gw_family == AF_INET)
644 addattr_l (nlmsg, req_size, RTA_GATEWAY, &nexthop->gate.ipv4, bytelen);
645 else
646 addattr_l (nlmsg, req_size, RTA_GATEWAY, &nexthop->gate.ipv6, bytelen);
647 }
648}
649
650static void
651_netlink_route_rta_add_gateway_info (u_char route_family, u_char gw_family,
652 struct rtattr *rta, struct rtnexthop *rtnh,
653 size_t req_size, int bytelen,
654 struct nexthop *nexthop)
655{
656 if (route_family == AF_MPLS)
657 {
658 struct gw_family_t gw_fam;
659
660 gw_fam.family = gw_family;
661 if (gw_family == AF_INET)
662 memcpy (&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen);
663 else
664 memcpy (&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen);
665 rta_addattr_l (rta, req_size, RTA_VIA, &gw_fam.family, bytelen+2);
666 rtnh->rtnh_len += RTA_LENGTH (bytelen + 2);
667 }
668 else
669 {
670 if (gw_family == AF_INET)
671 rta_addattr_l (rta, req_size, RTA_GATEWAY, &nexthop->gate.ipv4, bytelen);
672 else
673 rta_addattr_l (rta, req_size, RTA_GATEWAY, &nexthop->gate.ipv6, bytelen);
674 rtnh->rtnh_len += sizeof (struct rtattr) + bytelen;
675 }
676}
677
fa713d9e
CF
678/* This function takes a nexthop as argument and adds
679 * the appropriate netlink attributes to an existing
680 * netlink message.
681 *
682 * @param routedesc: Human readable description of route type
683 * (direct/recursive, single-/multipath)
684 * @param bytelen: Length of addresses in bytes.
685 * @param nexthop: Nexthop information
686 * @param nlmsg: nlmsghdr structure to fill in.
687 * @param req_size: The size allocated for the message.
688 */
689static void
690_netlink_route_build_singlepath(
691 const char *routedesc,
692 int bytelen,
693 struct nexthop *nexthop,
694 struct nlmsghdr *nlmsg,
e8d3d299 695 struct rtmsg *rtmsg,
c52ef59f
DS
696 size_t req_size,
697 int cmd)
fa713d9e 698{
c0f4be83 699 struct nexthop_label *nh_label;
700 mpls_lse_t out_lse[MPLS_MAX_LABELS];
40c7bdb0 701 char label_buf[100];
5c610faf 702
66d42727
DS
703 /*
704 * label_buf is *only* currently used within debugging.
705 * As such when we assign it we are guarding it inside
706 * a debug test. If you want to change this make sure
707 * you fix this assumption
708 */
40c7bdb0 709 label_buf[0] = '\0';
c0f4be83 710 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
711 * (in the case of LER)
712 */
713 nh_label = nexthop->nh_label;
40c7bdb0 714 if (rtmsg->rtm_family == AF_MPLS)
715 {
c0f4be83 716 assert (nh_label);
717 assert (nh_label->num_labels == 1);
718 }
40c7bdb0 719
c0f4be83 720 if (nh_label && nh_label->num_labels)
721 {
722 int i, num_labels = 0;
723 u_int32_t bos;
724 char label_buf1[20];
e52702f2 725
c0f4be83 726 for (i = 0; i < nh_label->num_labels; i++)
40c7bdb0 727 {
c0f4be83 728 if (nh_label->label[i] != MPLS_IMP_NULL_LABEL)
729 {
730 bos = ((i == (nh_label->num_labels - 1)) ? 1 : 0);
731 out_lse[i] = mpls_lse_encode (nh_label->label[i], 0, 0, bos);
66d42727
DS
732 if (IS_ZEBRA_DEBUG_KERNEL)
733 {
734 if (!num_labels)
735 sprintf (label_buf, "label %d", nh_label->label[i]);
736 else
737 {
738 sprintf (label_buf1, "/%d", nh_label->label[i]);
739 strcat (label_buf, label_buf1);
740 }
741 }
c0f4be83 742 num_labels++;
743 }
744 }
745 if (num_labels)
746 {
747 if (rtmsg->rtm_family == AF_MPLS)
748 addattr_l (nlmsg, req_size, RTA_NEWDST,
749 &out_lse, num_labels * sizeof(mpls_lse_t));
750 else
751 {
752 struct rtattr *nest;
753 u_int16_t encap = LWTUNNEL_ENCAP_MPLS;
754
755 addattr_l(nlmsg, req_size, RTA_ENCAP_TYPE,
756 &encap, sizeof (u_int16_t));
757 nest = addattr_nest(nlmsg, req_size, RTA_ENCAP);
758 addattr_l (nlmsg, req_size, MPLS_IPTUNNEL_DST,
759 &out_lse, num_labels * sizeof(mpls_lse_t));
760 addattr_nest_end(nlmsg, nest);
761 }
40c7bdb0 762 }
763 }
764
e8d3d299
CF
765 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
766 rtmsg->rtm_flags |= RTNH_F_ONLINK;
5c610faf 767
6a2ef37a
RW
768 if (rtmsg->rtm_family == AF_INET &&
769 (nexthop->type == NEXTHOP_TYPE_IPV6
770 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX))
771 {
772 rtmsg->rtm_flags |= RTNH_F_ONLINK;
773 addattr_l (nlmsg, req_size, RTA_GATEWAY, &ipv4_ll, 4);
774 addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
775
776 if (nexthop->rmap_src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
777 addattr_l (nlmsg, req_size, RTA_PREFSRC,
778 &nexthop->rmap_src.ipv4, bytelen);
779 else if (nexthop->src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
780 addattr_l (nlmsg, req_size, RTA_PREFSRC,
781 &nexthop->src.ipv4, bytelen);
782
783 if (IS_ZEBRA_DEBUG_KERNEL)
784 zlog_debug(" 5549: _netlink_route_build_singlepath() (%s): "
785 "nexthop via %s %s if %u",
786 routedesc, ipv4_ll_buf, label_buf, nexthop->ifindex);
787 return;
788 }
789
fa713d9e
CF
790 if (nexthop->type == NEXTHOP_TYPE_IPV4
791 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
792 {
659b52a8
DS
793 /* Send deletes to the kernel without specifying the next-hop */
794 if (cmd != RTM_DELROUTE)
795 _netlink_route_nl_add_gateway_info (rtmsg->rtm_family, AF_INET, nlmsg,
796 req_size, bytelen, nexthop);
c52ef59f 797
0aabccc0
DD
798 if (cmd == RTM_NEWROUTE)
799 {
800 if (nexthop->rmap_src.ipv4.s_addr)
801 addattr_l (nlmsg, req_size, RTA_PREFSRC,
802 &nexthop->rmap_src.ipv4, bytelen);
803 else if (nexthop->src.ipv4.s_addr)
804 addattr_l (nlmsg, req_size, RTA_PREFSRC,
805 &nexthop->src.ipv4, bytelen);
806 }
fa713d9e
CF
807
808 if (IS_ZEBRA_DEBUG_KERNEL)
809 zlog_debug("netlink_route_multipath() (%s): "
40c7bdb0 810 "nexthop via %s %s if %u",
fa713d9e
CF
811 routedesc,
812 inet_ntoa (nexthop->gate.ipv4),
40c7bdb0 813 label_buf, nexthop->ifindex);
fa713d9e 814 }
6a2ef37a 815
fa713d9e 816 if (nexthop->type == NEXTHOP_TYPE_IPV6
fa713d9e
CF
817 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
818 {
40c7bdb0 819 _netlink_route_nl_add_gateway_info (rtmsg->rtm_family, AF_INET6, nlmsg,
820 req_size, bytelen, nexthop);
fa713d9e 821
0aabccc0
DD
822 if (cmd == RTM_NEWROUTE)
823 {
824 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
825 addattr_l (nlmsg, req_size, RTA_PREFSRC,
826 &nexthop->rmap_src.ipv6, bytelen);
827 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
828 addattr_l (nlmsg, req_size, RTA_PREFSRC,
829 &nexthop->src.ipv6, bytelen);
830 }
831
fa713d9e
CF
832 if (IS_ZEBRA_DEBUG_KERNEL)
833 zlog_debug("netlink_route_multipath() (%s): "
40c7bdb0 834 "nexthop via %s %s if %u",
fa713d9e
CF
835 routedesc,
836 inet6_ntoa (nexthop->gate.ipv6),
40c7bdb0 837 label_buf, nexthop->ifindex);
fa713d9e 838 }
fa713d9e 839 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
fa713d9e
CF
840 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
841 {
842 addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
843
0aabccc0
DD
844 if (cmd == RTM_NEWROUTE)
845 {
846 if (nexthop->rmap_src.ipv4.s_addr)
847 addattr_l (nlmsg, req_size, RTA_PREFSRC,
848 &nexthop->rmap_src.ipv4, bytelen);
849 else if (nexthop->src.ipv4.s_addr)
850 addattr_l (nlmsg, req_size, RTA_PREFSRC,
851 &nexthop->src.ipv4, bytelen);
852 }
fa713d9e
CF
853
854 if (IS_ZEBRA_DEBUG_KERNEL)
855 zlog_debug("netlink_route_multipath() (%s): "
856 "nexthop via if %u", routedesc, nexthop->ifindex);
857 }
858
3ee39b5b 859 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
fa713d9e
CF
860 {
861 addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
862
0aabccc0
DD
863 if (cmd == RTM_NEWROUTE)
864 {
865 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
866 addattr_l (nlmsg, req_size, RTA_PREFSRC,
867 &nexthop->rmap_src.ipv6, bytelen);
868 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
869 addattr_l (nlmsg, req_size, RTA_PREFSRC,
870 &nexthop->src.ipv6, bytelen);
871 }
872
fa713d9e
CF
873 if (IS_ZEBRA_DEBUG_KERNEL)
874 zlog_debug("netlink_route_multipath() (%s): "
875 "nexthop via if %u", routedesc, nexthop->ifindex);
876 }
877}
878
879/* This function takes a nexthop as argument and
880 * appends to the given rtattr/rtnexthop pair the
881 * representation of the nexthop. If the nexthop
882 * defines a preferred source, the src parameter
883 * will be modified to point to that src, otherwise
884 * it will be kept unmodified.
885 *
886 * @param routedesc: Human readable description of route type
887 * (direct/recursive, single-/multipath)
888 * @param bytelen: Length of addresses in bytes.
889 * @param nexthop: Nexthop information
890 * @param rta: rtnetlink attribute structure
891 * @param rtnh: pointer to an rtnetlink nexthop structure
892 * @param src: pointer pointing to a location where
893 * the prefsrc should be stored.
894 */
895static void
896_netlink_route_build_multipath(
897 const char *routedesc,
898 int bytelen,
899 struct nexthop *nexthop,
900 struct rtattr *rta,
901 struct rtnexthop *rtnh,
5c610faf
DS
902 struct rtmsg *rtmsg,
903 union g_addr **src)
fa713d9e 904{
c0f4be83 905 struct nexthop_label *nh_label;
906 mpls_lse_t out_lse[MPLS_MAX_LABELS];
40c7bdb0 907 char label_buf[100];
908
fa713d9e
CF
909 rtnh->rtnh_len = sizeof (*rtnh);
910 rtnh->rtnh_flags = 0;
911 rtnh->rtnh_hops = 0;
912 rta->rta_len += rtnh->rtnh_len;
913
66d42727
DS
914 /*
915 * label_buf is *only* currently used within debugging.
916 * As such when we assign it we are guarding it inside
917 * a debug test. If you want to change this make sure
918 * you fix this assumption
919 */
40c7bdb0 920 label_buf[0] = '\0';
c0f4be83 921 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
922 * (in the case of LER)
923 */
924 nh_label = nexthop->nh_label;
40c7bdb0 925 if (rtmsg->rtm_family == AF_MPLS)
926 {
c0f4be83 927 assert (nh_label);
928 assert (nh_label->num_labels == 1);
929 }
930
931 if (nh_label && nh_label->num_labels)
932 {
933 int i, num_labels = 0;
934 u_int32_t bos;
935 char label_buf1[20];
40c7bdb0 936
c0f4be83 937 for (i = 0; i < nh_label->num_labels; i++)
40c7bdb0 938 {
c0f4be83 939 if (nh_label->label[i] != MPLS_IMP_NULL_LABEL)
940 {
941 bos = ((i == (nh_label->num_labels - 1)) ? 1 : 0);
942 out_lse[i] = mpls_lse_encode (nh_label->label[i], 0, 0, bos);
66d42727
DS
943 if (IS_ZEBRA_DEBUG_KERNEL)
944 {
945 if (!num_labels)
946 sprintf (label_buf, "label %d", nh_label->label[i]);
947 else
948 {
949 sprintf (label_buf1, "/%d", nh_label->label[i]);
950 strcat (label_buf, label_buf1);
951 }
952 }
c0f4be83 953 num_labels++;
954 }
955 }
956 if (num_labels)
957 {
958 if (rtmsg->rtm_family == AF_MPLS)
959 {
960 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_NEWDST,
961 &out_lse, num_labels * sizeof(mpls_lse_t));
962 rtnh->rtnh_len += RTA_LENGTH (num_labels * sizeof(mpls_lse_t));
963 }
964 else
965 {
966 struct rtattr *nest;
967 u_int16_t encap = LWTUNNEL_ENCAP_MPLS;
968 int len = rta->rta_len;
969
970 rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_ENCAP_TYPE,
971 &encap, sizeof (u_int16_t));
972 nest = rta_nest(rta, NL_PKT_BUF_SIZE, RTA_ENCAP);
973 rta_addattr_l (rta, NL_PKT_BUF_SIZE, MPLS_IPTUNNEL_DST,
974 &out_lse, num_labels * sizeof(mpls_lse_t));
975 rta_nest_end(rta, nest);
976 rtnh->rtnh_len += rta->rta_len - len;
977 }
40c7bdb0 978 }
979 }
5c610faf 980
e8d3d299
CF
981 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
982 rtnh->rtnh_flags |= RTNH_F_ONLINK;
983
6a2ef37a
RW
984 if (rtmsg->rtm_family == AF_INET &&
985 (nexthop->type == NEXTHOP_TYPE_IPV6
986 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX))
987 {
988 bytelen = 4;
989 rtnh->rtnh_flags |= RTNH_F_ONLINK;
990 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
991 &ipv4_ll, bytelen);
992 rtnh->rtnh_len += sizeof (struct rtattr) + bytelen;
993 rtnh->rtnh_ifindex = nexthop->ifindex;
994
995 if (nexthop->rmap_src.ipv4.s_addr)
996 *src = &nexthop->rmap_src;
997 else if (nexthop->src.ipv4.s_addr)
998 *src = &nexthop->src;
999
1000 if (IS_ZEBRA_DEBUG_KERNEL)
1001 zlog_debug(" 5549: netlink_route_build_multipath() (%s): "
1002 "nexthop via %s %s if %u",
1003 routedesc, ipv4_ll_buf, label_buf, nexthop->ifindex);
1004 return;
1005 }
1006
fa713d9e
CF
1007 if (nexthop->type == NEXTHOP_TYPE_IPV4
1008 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1009 {
40c7bdb0 1010 _netlink_route_rta_add_gateway_info (rtmsg->rtm_family, AF_INET, rta,
1011 rtnh, NL_PKT_BUF_SIZE, bytelen, nexthop);
c52ef59f
DS
1012 if (nexthop->rmap_src.ipv4.s_addr)
1013 *src = &nexthop->rmap_src;
1014 else if (nexthop->src.ipv4.s_addr)
1015 *src = &nexthop->src;
fa713d9e
CF
1016
1017 if (IS_ZEBRA_DEBUG_KERNEL)
1018 zlog_debug("netlink_route_multipath() (%s): "
40c7bdb0 1019 "nexthop via %s %s if %u",
fa713d9e
CF
1020 routedesc,
1021 inet_ntoa (nexthop->gate.ipv4),
40c7bdb0 1022 label_buf, nexthop->ifindex);
fa713d9e 1023 }
fa713d9e 1024 if (nexthop->type == NEXTHOP_TYPE_IPV6
fa713d9e
CF
1025 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1026 {
40c7bdb0 1027 _netlink_route_rta_add_gateway_info (rtmsg->rtm_family, AF_INET6, rta,
1028 rtnh, NL_PKT_BUF_SIZE, bytelen, nexthop);
0aabccc0
DD
1029
1030 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
1031 *src = &nexthop->rmap_src;
1032 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
1033 *src = &nexthop->src;
1034
fa713d9e
CF
1035 if (IS_ZEBRA_DEBUG_KERNEL)
1036 zlog_debug("netlink_route_multipath() (%s): "
40c7bdb0 1037 "nexthop via %s %s if %u",
fa713d9e
CF
1038 routedesc,
1039 inet6_ntoa (nexthop->gate.ipv6),
40c7bdb0 1040 label_buf, nexthop->ifindex);
fa713d9e 1041 }
fa713d9e
CF
1042 /* ifindex */
1043 if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
3ee39b5b 1044 || nexthop->type == NEXTHOP_TYPE_IFINDEX)
fa713d9e
CF
1045 {
1046 rtnh->rtnh_ifindex = nexthop->ifindex;
c52ef59f
DS
1047
1048 if (nexthop->rmap_src.ipv4.s_addr)
1049 *src = &nexthop->rmap_src;
1050 else if (nexthop->src.ipv4.s_addr)
fa713d9e 1051 *src = &nexthop->src;
c52ef59f 1052
fa713d9e
CF
1053 if (IS_ZEBRA_DEBUG_KERNEL)
1054 zlog_debug("netlink_route_multipath() (%s): "
1055 "nexthop via if %u", routedesc, nexthop->ifindex);
1056 }
3ee39b5b 1057 else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
fa713d9e
CF
1058 {
1059 rtnh->rtnh_ifindex = nexthop->ifindex;
1060
1061 if (IS_ZEBRA_DEBUG_KERNEL)
1062 zlog_debug("netlink_route_multipath() (%s): "
1063 "nexthop via if %u", routedesc, nexthop->ifindex);
1064 }
1065 else
1066 {
1067 rtnh->rtnh_ifindex = 0;
1068 }
1069}
1070
40c7bdb0 1071static inline void
1072_netlink_mpls_build_singlepath(
1073 const char *routedesc,
1074 zebra_nhlfe_t *nhlfe,
1075 struct nlmsghdr *nlmsg,
1076 struct rtmsg *rtmsg,
1077 size_t req_size,
1078 int cmd)
1079{
1080 int bytelen;
1081 u_char family;
1082
1083 family = NHLFE_FAMILY (nhlfe);
1084 bytelen = (family == AF_INET ? 4 : 16);
1085 _netlink_route_build_singlepath(routedesc, bytelen, nhlfe->nexthop,
1086 nlmsg, rtmsg, req_size, cmd);
1087}
1088
1089
1090static inline void
1091_netlink_mpls_build_multipath(
1092 const char *routedesc,
1093 zebra_nhlfe_t *nhlfe,
1094 struct rtattr *rta,
1095 struct rtnexthop *rtnh,
1096 struct rtmsg *rtmsg,
1097 union g_addr **src)
1098{
1099 int bytelen;
1100 u_char family;
1101
1102 family = NHLFE_FAMILY (nhlfe);
1103 bytelen = (family == AF_INET ? 4 : 16);
1104 _netlink_route_build_multipath(routedesc, bytelen, nhlfe->nexthop,
1105 rta, rtnh, rtmsg, src);
1106}
1107
1108
fa713d9e
CF
1109/* Log debug information for netlink_route_multipath
1110 * if debug logging is enabled.
1111 *
1112 * @param cmd: Netlink command which is to be processed
1113 * @param p: Prefix for which the change is due
1114 * @param nexthop: Nexthop which is currently processed
1115 * @param routedesc: Semantic annotation for nexthop
1116 * (recursive, multipath, etc.)
1117 * @param family: Address family which the change concerns
1118 */
1119static void
1120_netlink_route_debug(
1121 int cmd,
1122 struct prefix *p,
1123 struct nexthop *nexthop,
1124 const char *routedesc,
8f7d9fc0
FL
1125 int family,
1126 struct zebra_vrf *zvrf)
fa713d9e
CF
1127{
1128 if (IS_ZEBRA_DEBUG_KERNEL)
1129 {
35d921cc
TT
1130 char buf[PREFIX_STRLEN];
1131 zlog_debug ("netlink_route_multipath() (%s): %s %s vrf %u type %s",
1132 routedesc,
1fdc9eae 1133 nl_msg_type_to_str (cmd),
661512bf 1134 prefix2str (p, buf, sizeof(buf)), zvrf_id (zvrf),
40c7bdb0 1135 (nexthop) ? nexthop_type_to_str (nexthop->type) : "UNK");
fa713d9e 1136 }
e52702f2 1137 }
fa713d9e 1138
40c7bdb0 1139static void
1140_netlink_mpls_debug(
1141 int cmd,
1142 u_int32_t label,
1143 const char *routedesc)
1144{
1145 if (IS_ZEBRA_DEBUG_KERNEL)
1146 zlog_debug ("netlink_mpls_multipath() (%s): %s %u/20",
1fdc9eae 1147 routedesc, nl_msg_type_to_str (cmd), label);
fa713d9e
CF
1148}
1149
6b8a5694 1150static int
1bb6e9b7 1151netlink_neigh_update (int cmd, int ifindex, uint32_t addr, char *lla, int llalen)
5c610faf
DS
1152{
1153 struct {
1154 struct nlmsghdr n;
1155 struct ndmsg ndm;
1156 char buf[256];
1157 } req;
1158
fe18ee2d 1159 struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
8f7d9fc0 1160
5c610faf
DS
1161 memset(&req.n, 0, sizeof(req.n));
1162 memset(&req.ndm, 0, sizeof(req.ndm));
1163
1164 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
1165 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1166 req.n.nlmsg_type = cmd; //RTM_NEWNEIGH or RTM_DELNEIGH
1167 req.ndm.ndm_family = AF_INET;
1168 req.ndm.ndm_state = NUD_PERMANENT;
1169 req.ndm.ndm_ifindex = ifindex;
1170 req.ndm.ndm_type = RTN_UNICAST;
1171
1172 addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4);
1173 addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
1174
936ebf0a 1175 return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0);
5c610faf
DS
1176}
1177
718e3744 1178/* Routing table change via netlink interface. */
6ae24471 1179/* Update flag indicates whether this is a "replace" or not. */
6072b24e 1180static int
05737783 1181netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p,
f0f77c9a 1182 struct route_entry *re, int update)
718e3744 1183{
1184 int bytelen;
1185 struct sockaddr_nl snl;
fa713d9e
CF
1186 struct nexthop *nexthop = NULL, *tnexthop;
1187 int recursing;
37fe7731 1188 unsigned int nexthop_num;
718e3744 1189 int discard;
be717a0a 1190 int family = PREFIX_FAMILY(p);
fa713d9e 1191 const char *routedesc;
c52ef59f
DS
1192 int setsrc = 0;
1193 union g_addr src;
718e3744 1194
7021c425 1195 struct
718e3744 1196 {
1197 struct nlmsghdr n;
1198 struct rtmsg r;
3cadc0cd 1199 char buf[NL_PKT_BUF_SIZE];
718e3744 1200 } req;
1201
fe18ee2d 1202 struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
f0f77c9a 1203 struct zebra_vrf *zvrf = vrf_info_lookup (re->vrf_id);
8f7d9fc0 1204
a4c06dec 1205 memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
718e3744 1206
1207 bytelen = (family == AF_INET ? 4 : 16);
1208
1209 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1210 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
6ae24471
DS
1211 if ((cmd == RTM_NEWROUTE) && update)
1212 req.n.nlmsg_flags |= NLM_F_REPLACE;
718e3744 1213 req.n.nlmsg_type = cmd;
1214 req.r.rtm_family = family;
718e3744 1215 req.r.rtm_dst_len = p->prefixlen;
05737783 1216 req.r.rtm_src_len = src_p ? src_p->prefixlen : 0;
f0f77c9a 1217 req.r.rtm_protocol = get_rt_proto(re->type);
40da2216 1218 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
718e3744 1219
f0f77c9a 1220 if ((re->flags & ZEBRA_FLAG_BLACKHOLE) || (re->flags & ZEBRA_FLAG_REJECT))
718e3744 1221 discard = 1;
1222 else
1223 discard = 0;
1224
7021c425 1225 if (cmd == RTM_NEWROUTE)
718e3744 1226 {
7021c425 1227 if (discard)
595db7f1 1228 {
f0f77c9a 1229 if (re->flags & ZEBRA_FLAG_BLACKHOLE)
595db7f1 1230 req.r.rtm_type = RTN_BLACKHOLE;
f0f77c9a 1231 else if (re->flags & ZEBRA_FLAG_REJECT)
595db7f1 1232 req.r.rtm_type = RTN_UNREACHABLE;
7021c425 1233 else
1234 assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
1235 }
595db7f1 1236 else
7021c425 1237 req.r.rtm_type = RTN_UNICAST;
718e3744 1238 }
1239
1240 addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
05737783
CF
1241 if (src_p)
1242 addattr_l (&req.n, sizeof req, RTA_SRC, &src_p->u.prefix, bytelen);
718e3744 1243
1244 /* Metric. */
1f5705f0
DS
1245 /* Hardcode the metric for all routes coming from zebra. Metric isn't used
1246 * either by the kernel or by zebra. Its purely for calculating best path(s)
1247 * by the routing protocol and for communicating with protocol peers.
1248 */
1249 addattr32 (&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC);
718e3744 1250
ca46a78e 1251 /* Table corresponding to this route. */
f0f77c9a
DS
1252 if (re->table < 256)
1253 req.r.rtm_table = re->table;
ca46a78e 1254 else
1255 {
1256 req.r.rtm_table = RT_TABLE_UNSPEC;
f0f77c9a 1257 addattr32(&req.n, sizeof req, RTA_TABLE, re->table);
ca46a78e 1258 }
1259
f0f77c9a 1260 if (re->mtu || re->nexthop_mtu)
c50ca33a
TT
1261 {
1262 char buf[NL_PKT_BUF_SIZE];
1263 struct rtattr *rta = (void *) buf;
f0f77c9a
DS
1264 u_int32_t mtu = re->mtu;
1265 if (!mtu || (re->nexthop_mtu && re->nexthop_mtu < mtu))
1266 mtu = re->nexthop_mtu;
c50ca33a
TT
1267 rta->rta_type = RTA_METRICS;
1268 rta->rta_len = RTA_LENGTH(0);
1269 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTAX_MTU, &mtu, sizeof mtu);
1270 addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA (rta),
1271 RTA_PAYLOAD (rta));
1272 }
1273
718e3744 1274 if (discard)
1275 {
1276 if (cmd == RTM_NEWROUTE)
f0f77c9a 1277 for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
fa713d9e
CF
1278 {
1279 /* We shouldn't encounter recursive nexthops on discard routes,
1280 * but it is probably better to handle that case correctly anyway.
1281 */
1282 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1283 continue;
fa713d9e 1284 }
718e3744 1285 goto skip;
1286 }
1287
fa713d9e
CF
1288 /* Count overall nexthops so we can decide whether to use singlepath
1289 * or multipath case. */
1290 nexthop_num = 0;
f0f77c9a 1291 for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
fa713d9e
CF
1292 {
1293 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1294 continue;
1295 if (cmd == RTM_NEWROUTE && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1296 continue;
1297 if (cmd == RTM_DELROUTE && !CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1298 continue;
1299
1300 nexthop_num++;
1301 }
1302
1303 /* Singlepath case. */
37fe7731 1304 if (nexthop_num == 1 || multipath_num == 1)
718e3744 1305 {
fa713d9e 1306 nexthop_num = 0;
f0f77c9a 1307 for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
7021c425 1308 {
fa713d9e 1309 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
c52ef59f 1310 {
c52ef59f
DS
1311 if (!setsrc)
1312 {
0aabccc0
DD
1313 if (family == AF_INET)
1314 {
1315 if (nexthop->rmap_src.ipv4.s_addr != 0)
1316 {
1317 src.ipv4 = nexthop->rmap_src.ipv4;
1318 setsrc = 1;
1319 }
1320 else if (nexthop->src.ipv4.s_addr != 0)
1321 {
1322 src.ipv4 = nexthop->src.ipv4;
1323 setsrc = 1;
1324 }
1325 }
1326 else if (family == AF_INET6)
1327 {
1328 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
1329 {
1330 src.ipv6 = nexthop->rmap_src.ipv6;
1331 setsrc = 1;
1332 }
1333 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
1334 {
1335 src.ipv6 = nexthop->src.ipv6;
1336 setsrc = 1;
1337 }
1338 }
c52ef59f
DS
1339 }
1340 continue;
1341 }
7021c425 1342
1343 if ((cmd == RTM_NEWROUTE
1344 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1345 || (cmd == RTM_DELROUTE
1346 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1347 {
fa713d9e 1348 routedesc = recursing ? "recursive, 1 hop" : "single hop";
7021c425 1349
8f7d9fc0 1350 _netlink_route_debug(cmd, p, nexthop, routedesc, family, zvrf);
fa713d9e 1351 _netlink_route_build_singlepath(routedesc, bytelen,
e8d3d299 1352 nexthop, &req.n, &req.r,
c52ef59f 1353 sizeof req, cmd);
7021c425 1354 nexthop_num++;
1355 break;
1356 }
1357 }
c52ef59f 1358 if (setsrc && (cmd == RTM_NEWROUTE))
0aabccc0
DD
1359 {
1360 if (family == AF_INET)
1361 addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen);
1362 else if (family == AF_INET6)
1363 addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv6, bytelen);
1364 }
718e3744 1365 }
1366 else
1367 {
3cadc0cd 1368 char buf[NL_PKT_BUF_SIZE];
718e3744 1369 struct rtattr *rta = (void *) buf;
1370 struct rtnexthop *rtnh;
c52ef59f 1371 union g_addr *src1 = NULL;
718e3744 1372
1373 rta->rta_type = RTA_MULTIPATH;
7021c425 1374 rta->rta_len = RTA_LENGTH (0);
1375 rtnh = RTA_DATA (rta);
718e3744 1376
1377 nexthop_num = 0;
f0f77c9a 1378 for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
7021c425 1379 {
37fe7731 1380 if (nexthop_num >= multipath_num)
fa713d9e
CF
1381 break;
1382
1383 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
c52ef59f
DS
1384 {
1385 /* This only works for IPv4 now */
1386 if (!setsrc)
1387 {
0aabccc0
DD
1388 if (family == AF_INET)
1389 {
1390 if (nexthop->rmap_src.ipv4.s_addr != 0)
1391 {
1392 src.ipv4 = nexthop->rmap_src.ipv4;
1393 setsrc = 1;
1394 }
1395 else if (nexthop->src.ipv4.s_addr != 0)
1396 {
1397 src.ipv4 = nexthop->src.ipv4;
1398 setsrc = 1;
1399 }
1400 }
1401 else if (family == AF_INET6)
1402 {
1403 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
1404 {
1405 src.ipv6 = nexthop->rmap_src.ipv6;
1406 setsrc = 1;
1407 }
1408 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
1409 {
1410 src.ipv6 = nexthop->src.ipv6;
1411 setsrc = 1;
1412 }
1413 }
c52ef59f
DS
1414 }
1415 continue;
1416 }
fa713d9e 1417
7021c425 1418 if ((cmd == RTM_NEWROUTE
1419 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1420 || (cmd == RTM_DELROUTE
1421 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1422 {
fa713d9e 1423 routedesc = recursing ? "recursive, multihop" : "multihop";
7021c425 1424 nexthop_num++;
1425
fa713d9e 1426 _netlink_route_debug(cmd, p, nexthop,
8f7d9fc0 1427 routedesc, family, zvrf);
fa713d9e 1428 _netlink_route_build_multipath(routedesc, bytelen,
5c610faf 1429 nexthop, rta, rtnh, &req.r, &src1);
7021c425 1430 rtnh = RTNH_NEXT (rtnh);
1431
c52ef59f
DS
1432 if (!setsrc && src1)
1433 {
0aabccc0
DD
1434 if (family == AF_INET)
1435 src.ipv4 = src1->ipv4;
1436 else if (family == AF_INET6)
1437 src.ipv6 = src1->ipv6;
1438
c52ef59f
DS
1439 setsrc = 1;
1440 }
7021c425 1441 }
1442 }
c52ef59f 1443 if (setsrc && (cmd == RTM_NEWROUTE))
0aabccc0
DD
1444 {
1445 if (family == AF_INET)
1446 addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen);
1447 else if (family == AF_INET6)
1448 addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv6, bytelen);
82a95360
DS
1449 if (IS_ZEBRA_DEBUG_KERNEL)
1450 zlog_debug("Setting source");
0aabccc0 1451 }
718e3744 1452
1453 if (rta->rta_len > RTA_LENGTH (0))
3cadc0cd 1454 addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta),
7021c425 1455 RTA_PAYLOAD (rta));
718e3744 1456 }
1457
1458 /* If there is no useful nexthop then return. */
1459 if (nexthop_num == 0)
1460 {
1461 if (IS_ZEBRA_DEBUG_KERNEL)
b6178002 1462 zlog_debug ("netlink_route_multipath(): No useful nexthop.");
718e3744 1463 return 0;
1464 }
1465
7021c425 1466skip:
718e3744 1467
1468 /* Destination netlink address. */
1469 memset (&snl, 0, sizeof snl);
1470 snl.nl_family = AF_NETLINK;
1471
718e3744 1472 /* Talk to netlink socket. */
936ebf0a 1473 return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0);
718e3744 1474}
1475
e3be0432 1476int
1498c059 1477kernel_get_ipmr_sg_stats (void *in)
e3be0432
DS
1478{
1479 int suc = 0;
1480 struct mcast_route_data *mr = (struct mcast_route_data *)in;
1481 struct {
1482 struct nlmsghdr n;
1483 struct ndmsg ndm;
1484 char buf[256];
1485 } req;
1486
1487 mroute = mr;
1488 struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
1489
1490 memset(&req.n, 0, sizeof(req.n));
1491 memset(&req.ndm, 0, sizeof(req.ndm));
1492
1493 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
1494 req.n.nlmsg_flags = NLM_F_REQUEST;
1495 req.ndm.ndm_family = AF_INET;
1496 req.n.nlmsg_type = RTM_GETROUTE;
1497
1498 addattr_l (&req.n, sizeof (req), RTA_IIF, &mroute->ifindex, 4);
1499 addattr_l (&req.n, sizeof (req), RTA_OIF, &mroute->ifindex, 4);
1500 addattr_l (&req.n, sizeof (req), RTA_SRC, &mroute->sg.src.s_addr, 4);
1501 addattr_l (&req.n, sizeof (req), RTA_DST, &mroute->sg.grp.s_addr, 4);
1502
936ebf0a 1503 suc = netlink_talk (netlink_route_change_read_multicast, &req.n, &zns->netlink_cmd, zns, 0);
e3be0432
DS
1504
1505 mroute = NULL;
1506 return suc;
1507}
1508
718e3744 1509int
05737783 1510kernel_route_rib (struct prefix *p, struct prefix *src_p,
f0f77c9a 1511 struct route_entry *old, struct route_entry *new)
718e3744 1512{
be717a0a 1513 if (!old && new)
05737783 1514 return netlink_route_multipath (RTM_NEWROUTE, p, src_p, new, 0);
be717a0a 1515 if (old && !new)
05737783 1516 return netlink_route_multipath (RTM_DELROUTE, p, src_p, old, 0);
718e3744 1517
05737783 1518 return netlink_route_multipath (RTM_NEWROUTE, p, src_p, new, 1);
718e3744 1519}
1520
6b8a5694
RW
1521int
1522kernel_neigh_update (int add, int ifindex, uint32_t addr, char *lla, int llalen)
1523{
1524 return netlink_neigh_update(add ? RTM_NEWNEIGH : RTM_DELNEIGH, ifindex, addr,
1525 lla, llalen);
1526}
718e3744 1527
40c7bdb0 1528/*
1529 * MPLS label forwarding table change via netlink interface.
1530 */
be0dba35 1531int
40c7bdb0 1532netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp)
1533{
1534 mpls_lse_t lse;
1535 zebra_nhlfe_t *nhlfe;
1536 struct nexthop *nexthop = NULL;
37fe7731 1537 unsigned int nexthop_num;
40c7bdb0 1538 const char *routedesc;
1539 struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
1540
1541 struct
1542 {
1543 struct nlmsghdr n;
1544 struct rtmsg r;
1545 char buf[NL_PKT_BUF_SIZE];
1546 } req;
1547
1548 memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
1549
1550
1551 /*
1552 * Count # nexthops so we can decide whether to use singlepath
1553 * or multipath case.
1554 */
1555 nexthop_num = 0;
1556 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next)
1557 {
1558 nexthop = nhlfe->nexthop;
1559 if (!nexthop)
1560 continue;
1561 if (cmd == RTM_NEWROUTE)
1562 {
1563 /* Count all selected NHLFEs */
1564 if (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED) &&
1565 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1566 nexthop_num++;
1567 }
1568 else /* DEL */
1569 {
1570 /* Count all installed NHLFEs */
1571 if (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) &&
1572 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1573 nexthop_num++;
1574 }
1575 }
1576
1577 if (nexthop_num == 0) // unexpected
1578 return 0;
1579
1580 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1581 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1582 req.n.nlmsg_type = cmd;
1583 req.r.rtm_family = AF_MPLS;
1584 req.r.rtm_table = RT_TABLE_MAIN;
1585 req.r.rtm_dst_len = MPLS_LABEL_LEN_BITS;
1586 req.r.rtm_protocol = RTPROT_ZEBRA;
1587 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1588 req.r.rtm_type = RTN_UNICAST;
1589
1590 if (cmd == RTM_NEWROUTE)
1591 /* We do a replace to handle update. */
1592 req.n.nlmsg_flags |= NLM_F_REPLACE;
1593
1594 /* Fill destination */
1595 lse = mpls_lse_encode (lsp->ile.in_label, 0, 0, 1);
1596 addattr_l (&req.n, sizeof req, RTA_DST, &lse, sizeof(mpls_lse_t));
1597
1598 /* Fill nexthops (paths) based on single-path or multipath. The paths
1599 * chosen depend on the operation.
1600 */
37fe7731 1601 if (nexthop_num == 1 || multipath_num == 1)
40c7bdb0 1602 {
1603 routedesc = "single hop";
1604 _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc);
1605
1606 nexthop_num = 0;
1607 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next)
1608 {
1609 nexthop = nhlfe->nexthop;
1610 if (!nexthop)
1611 continue;
1612
1613 if ((cmd == RTM_NEWROUTE &&
1614 (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED) &&
1615 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))) ||
1616 (cmd == RTM_DELROUTE &&
1617 (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) &&
1618 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))))
1619 {
1620 /* Add the gateway */
1621 _netlink_mpls_build_singlepath(routedesc, nhlfe,
1622 &req.n, &req.r, sizeof req, cmd);
1623 if (cmd == RTM_NEWROUTE)
1624 {
1625 SET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED);
1626 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1627 }
1628 else
1629 {
1630 UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED);
1631 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1632 }
1633 nexthop_num++;
1634 break;
1635 }
1636 }
1637 }
1638 else /* Multipath case */
1639 {
1640 char buf[NL_PKT_BUF_SIZE];
1641 struct rtattr *rta = (void *) buf;
1642 struct rtnexthop *rtnh;
1643 union g_addr *src1 = NULL;
1644
1645 rta->rta_type = RTA_MULTIPATH;
1646 rta->rta_len = RTA_LENGTH (0);
1647 rtnh = RTA_DATA (rta);
1648
1649 routedesc = "multihop";
1650 _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc);
1651
1652 nexthop_num = 0;
1653 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next)
1654 {
1655 nexthop = nhlfe->nexthop;
1656 if (!nexthop)
1657 continue;
1658
37fe7731 1659 if (nexthop_num >= multipath_num)
40c7bdb0 1660 break;
1661
1662 if ((cmd == RTM_NEWROUTE &&
1663 (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED) &&
1664 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))) ||
1665 (cmd == RTM_DELROUTE &&
1666 (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) &&
1667 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))))
1668 {
1669 nexthop_num++;
1670
1671 /* Build the multipath */
1672 _netlink_mpls_build_multipath(routedesc, nhlfe, rta,
1673 rtnh, &req.r, &src1);
1674 rtnh = RTNH_NEXT (rtnh);
1675
1676 if (cmd == RTM_NEWROUTE)
1677 {
1678 SET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED);
1679 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1680 }
1681 else
1682 {
1683 UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED);
1684 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1685 }
1686
1687 }
1688 }
1689
1690 /* Add the multipath */
1691 if (rta->rta_len > RTA_LENGTH (0))
1692 addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta),
1693 RTA_PAYLOAD (rta));
1694 }
1695
1696 /* Talk to netlink socket. */
936ebf0a 1697 return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0);
40c7bdb0 1698}
1699
1700/*
1701 * Handle failure in LSP install, clear flags for NHLFE.
1702 */
be0dba35 1703void
40c7bdb0 1704clear_nhlfe_installed (zebra_lsp_t *lsp)
1705{
1706 zebra_nhlfe_t *nhlfe;
1707 struct nexthop *nexthop;
1708
1709 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next)
1710 {
1711 nexthop = nhlfe->nexthop;
1712 if (!nexthop)
1713 continue;
1714
1715 UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED);
1716 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1717 }
1718}