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