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