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