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