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