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