blob: 1a914266612f11b4dfa4f2171b256c8e1daa1515 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* Kernel routing table updates using netlink over GNU/Linux system.
2 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include <zebra.h>
Timo Teräs954c7d62016-01-15 17:36:33 +020023#include <net/if_arp.h>
paul718e3742002-12-13 20:15:29 +000024
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"
Josh Bailey26e2ae32012-03-22 01:09:21 -070036#include "memory.h"
paul718e3742002-12-13 20:15:29 +000037#include "rib.h"
paule04ab742003-01-17 23:47:00 +000038#include "thread.h"
pauledd7c242003-06-04 13:59:38 +000039#include "privs.h"
Feng Lu0d0686f2015-05-22 11:40:02 +020040#include "vrf.h"
Pradosh Mohapatra60cc9592015-11-09 20:21:41 -050041#include "nexthop.h"
paul718e3742002-12-13 20:15:29 +000042
43#include "zebra/zserv.h"
paul6621ca82005-11-23 13:02:08 +000044#include "zebra/rt.h"
paul718e3742002-12-13 20:15:29 +000045#include "zebra/redistribute.h"
46#include "zebra/interface.h"
47#include "zebra/debug.h"
48
Avneesh Sachdev78deec42012-11-13 22:48:56 +000049#include "rt_netlink.h"
JR Rivers3cadc0c2012-04-01 12:16:31 -070050
Stephen Hemminger1423c802008-08-14 17:59:25 +010051static const struct message nlmsg_str[] = {
paul718e3742002-12-13 20:15:29 +000052 {RTM_NEWROUTE, "RTM_NEWROUTE"},
53 {RTM_DELROUTE, "RTM_DELROUTE"},
54 {RTM_GETROUTE, "RTM_GETROUTE"},
55 {RTM_NEWLINK, "RTM_NEWLINK"},
56 {RTM_DELLINK, "RTM_DELLINK"},
57 {RTM_GETLINK, "RTM_GETLINK"},
58 {RTM_NEWADDR, "RTM_NEWADDR"},
59 {RTM_DELADDR, "RTM_DELADDR"},
60 {RTM_GETADDR, "RTM_GETADDR"},
paul7021c422003-07-15 12:52:22 +000061 {0, NULL}
paul718e3742002-12-13 20:15:29 +000062};
63
paulb21b19c2003-06-15 01:28:29 +000064extern struct zebra_t zebrad;
paul718e3742002-12-13 20:15:29 +000065
pauledd7c242003-06-04 13:59:38 +000066extern struct zebra_privs_t zserv_privs;
67
hassoc34b6b52004-08-31 13:41:49 +000068extern u_int32_t nl_rcvbufsize;
69
ajsd2fc8892005-04-02 18:38:43 +000070/* Note: on netlink systems, there should be a 1-to-1 mapping between interface
71 names and ifindex values. */
72static void
Paul Jakma9099f9b2016-01-18 10:12:10 +000073set_ifindex(struct interface *ifp, ifindex_t ifi_index)
ajsd2fc8892005-04-02 18:38:43 +000074{
75 struct interface *oifp;
76
77 if (((oifp = if_lookup_by_index(ifi_index)) != NULL) && (oifp != ifp))
78 {
79 if (ifi_index == IFINDEX_INTERNAL)
80 zlog_err("Netlink is setting interface %s ifindex to reserved "
81 "internal value %u", ifp->name, ifi_index);
82 else
83 {
84 if (IS_ZEBRA_DEBUG_KERNEL)
85 zlog_debug("interface index %d was renamed from %s to %s",
86 ifi_index, oifp->name, ifp->name);
87 if (if_is_up(oifp))
88 zlog_err("interface rename detected on up interface: index %d "
89 "was renamed from %s to %s, results are uncertain!",
90 ifi_index, oifp->name, ifp->name);
91 if_delete_update(oifp);
92 }
93 }
94 ifp->ifindex = ifi_index;
95}
96
Ulrich Weberf1ef81b2013-01-22 10:39:18 +000097#ifndef SO_RCVBUFFORCE
98#define SO_RCVBUFFORCE (33)
99#endif
100
Stephen Hemminger30afea32008-08-16 18:25:47 +0100101static int
102netlink_recvbuf (struct nlsock *nl, uint32_t newsize)
103{
104 u_int32_t oldsize;
105 socklen_t newlen = sizeof(newsize);
106 socklen_t oldlen = sizeof(oldsize);
107 int ret;
108
109 ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &oldsize, &oldlen);
110 if (ret < 0)
111 {
112 zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name,
113 safe_strerror (errno));
114 return -1;
115 }
116
Ulrich Weberf1ef81b2013-01-22 10:39:18 +0000117 /* Try force option (linux >= 2.6.14) and fall back to normal set */
118 if ( zserv_privs.change (ZPRIVS_RAISE) )
119 zlog_err ("routing_socket: Can't raise privileges");
120 ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUFFORCE, &nl_rcvbufsize,
Stephen Hemminger30afea32008-08-16 18:25:47 +0100121 sizeof(nl_rcvbufsize));
Ulrich Weberf1ef81b2013-01-22 10:39:18 +0000122 if ( zserv_privs.change (ZPRIVS_LOWER) )
123 zlog_err ("routing_socket: Can't lower privileges");
124 if (ret < 0)
125 ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &nl_rcvbufsize,
126 sizeof(nl_rcvbufsize));
Stephen Hemminger30afea32008-08-16 18:25:47 +0100127 if (ret < 0)
128 {
129 zlog (NULL, LOG_ERR, "Can't set %s receive buffer size: %s", nl->name,
130 safe_strerror (errno));
131 return -1;
132 }
133
134 ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &newsize, &newlen);
135 if (ret < 0)
136 {
137 zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name,
138 safe_strerror (errno));
139 return -1;
140 }
141
142 zlog (NULL, LOG_INFO,
143 "Setting netlink socket receive buffer size: %u -> %u",
144 oldsize, newsize);
145 return 0;
146}
147
paul718e3742002-12-13 20:15:29 +0000148/* Make socket for Linux netlink interface. */
149static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800150netlink_socket (struct nlsock *nl, unsigned long groups, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000151{
152 int ret;
153 struct sockaddr_nl snl;
154 int sock;
155 int namelen;
ajs4be019d2005-01-29 16:12:41 +0000156 int save_errno;
paul718e3742002-12-13 20:15:29 +0000157
Michal Sekletar8e998b12014-05-16 14:13:43 +0000158 if (zserv_privs.change (ZPRIVS_RAISE))
159 {
160 zlog (NULL, LOG_ERR, "Can't raise privileges");
161 return -1;
162 }
163
Feng Lu758fb8f2014-07-03 18:23:09 +0800164 sock = vrf_socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE, vrf_id);
paul718e3742002-12-13 20:15:29 +0000165 if (sock < 0)
166 {
167 zlog (NULL, LOG_ERR, "Can't open %s socket: %s", nl->name,
ajs6099b3b2004-11-20 02:06:59 +0000168 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000169 return -1;
170 }
171
paul718e3742002-12-13 20:15:29 +0000172 memset (&snl, 0, sizeof snl);
173 snl.nl_family = AF_NETLINK;
174 snl.nl_groups = groups;
175
176 /* Bind the socket to the netlink structure for anything. */
177 ret = bind (sock, (struct sockaddr *) &snl, sizeof snl);
ajs4be019d2005-01-29 16:12:41 +0000178 save_errno = errno;
hasso55e7ecd2004-08-06 08:41:56 +0000179 if (zserv_privs.change (ZPRIVS_LOWER))
180 zlog (NULL, LOG_ERR, "Can't lower privileges");
181
paul718e3742002-12-13 20:15:29 +0000182 if (ret < 0)
183 {
paul7021c422003-07-15 12:52:22 +0000184 zlog (NULL, LOG_ERR, "Can't bind %s socket to group 0x%x: %s",
ajs4be019d2005-01-29 16:12:41 +0000185 nl->name, snl.nl_groups, safe_strerror (save_errno));
paul718e3742002-12-13 20:15:29 +0000186 close (sock);
187 return -1;
188 }
paul7021c422003-07-15 12:52:22 +0000189
paul718e3742002-12-13 20:15:29 +0000190 /* multiple netlink sockets will have different nl_pid */
191 namelen = sizeof snl;
hassoc9e52be2004-09-26 16:09:34 +0000192 ret = getsockname (sock, (struct sockaddr *) &snl, (socklen_t *) &namelen);
paul718e3742002-12-13 20:15:29 +0000193 if (ret < 0 || namelen != sizeof snl)
194 {
195 zlog (NULL, LOG_ERR, "Can't get %s socket name: %s", nl->name,
ajs6099b3b2004-11-20 02:06:59 +0000196 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000197 close (sock);
198 return -1;
199 }
200
201 nl->snl = snl;
202 nl->sock = sock;
203 return ret;
204}
205
206/* Get type specified information from netlink. */
207static int
208netlink_request (int family, int type, struct nlsock *nl)
209{
210 int ret;
211 struct sockaddr_nl snl;
ajs4be019d2005-01-29 16:12:41 +0000212 int save_errno;
paul718e3742002-12-13 20:15:29 +0000213
214 struct
215 {
216 struct nlmsghdr nlh;
217 struct rtgenmsg g;
218 } req;
219
220
221 /* Check netlink socket. */
222 if (nl->sock < 0)
223 {
224 zlog (NULL, LOG_ERR, "%s socket isn't active.", nl->name);
225 return -1;
226 }
227
228 memset (&snl, 0, sizeof snl);
229 snl.nl_family = AF_NETLINK;
230
ajsc05612b2005-10-01 16:36:54 +0000231 memset (&req, 0, sizeof req);
paul718e3742002-12-13 20:15:29 +0000232 req.nlh.nlmsg_len = sizeof req;
233 req.nlh.nlmsg_type = type;
234 req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
Stephen Hemminger3d265b42008-08-16 17:30:39 +0100235 req.nlh.nlmsg_pid = nl->snl.nl_pid;
paul718e3742002-12-13 20:15:29 +0000236 req.nlh.nlmsg_seq = ++nl->seq;
237 req.g.rtgen_family = family;
pauledd7c242003-06-04 13:59:38 +0000238
239 /* linux appears to check capabilities on every message
240 * have to raise caps for every message sent
241 */
paul7021c422003-07-15 12:52:22 +0000242 if (zserv_privs.change (ZPRIVS_RAISE))
pauledd7c242003-06-04 13:59:38 +0000243 {
244 zlog (NULL, LOG_ERR, "Can't raise privileges");
245 return -1;
246 }
paul7021c422003-07-15 12:52:22 +0000247
248 ret = sendto (nl->sock, (void *) &req, sizeof req, 0,
249 (struct sockaddr *) &snl, sizeof snl);
ajs4be019d2005-01-29 16:12:41 +0000250 save_errno = errno;
paul7021c422003-07-15 12:52:22 +0000251
252 if (zserv_privs.change (ZPRIVS_LOWER))
253 zlog (NULL, LOG_ERR, "Can't lower privileges");
254
paul718e3742002-12-13 20:15:29 +0000255 if (ret < 0)
paul7021c422003-07-15 12:52:22 +0000256 {
257 zlog (NULL, LOG_ERR, "%s sendto failed: %s", nl->name,
ajs4be019d2005-01-29 16:12:41 +0000258 safe_strerror (save_errno));
paul718e3742002-12-13 20:15:29 +0000259 return -1;
260 }
pauledd7c242003-06-04 13:59:38 +0000261
paul718e3742002-12-13 20:15:29 +0000262 return 0;
263}
264
265/* Receive message from netlink interface and pass those information
266 to the given function. */
267static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800268netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *,
269 vrf_id_t),
270 struct nlsock *nl, struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +0000271{
272 int status;
273 int ret = 0;
274 int error;
275
276 while (1)
277 {
JR Rivers3cadc0c2012-04-01 12:16:31 -0700278 char buf[NL_PKT_BUF_SIZE];
Timo Teräsc299ed72014-07-29 09:41:55 +0000279 struct iovec iov = {
280 .iov_base = buf,
281 .iov_len = sizeof buf
282 };
paul718e3742002-12-13 20:15:29 +0000283 struct sockaddr_nl snl;
Timo Teräsc299ed72014-07-29 09:41:55 +0000284 struct msghdr msg = {
285 .msg_name = (void *) &snl,
286 .msg_namelen = sizeof snl,
287 .msg_iov = &iov,
288 .msg_iovlen = 1
289 };
paul718e3742002-12-13 20:15:29 +0000290 struct nlmsghdr *h;
paul7021c422003-07-15 12:52:22 +0000291
paul718e3742002-12-13 20:15:29 +0000292 status = recvmsg (nl->sock, &msg, 0);
paul718e3742002-12-13 20:15:29 +0000293 if (status < 0)
paul7021c422003-07-15 12:52:22 +0000294 {
Stephen Hemminger4c699472008-08-17 17:01:44 +0100295 if (errno == EINTR)
paul7021c422003-07-15 12:52:22 +0000296 continue;
Stephen Hemminger4c699472008-08-17 17:01:44 +0100297 if (errno == EWOULDBLOCK || errno == EAGAIN)
paul7021c422003-07-15 12:52:22 +0000298 break;
ajs4be019d2005-01-29 16:12:41 +0000299 zlog (NULL, LOG_ERR, "%s recvmsg overrun: %s",
Stephen Hemminger4c699472008-08-17 17:01:44 +0100300 nl->name, safe_strerror(errno));
paul7021c422003-07-15 12:52:22 +0000301 continue;
302 }
paul718e3742002-12-13 20:15:29 +0000303
304 if (status == 0)
paul7021c422003-07-15 12:52:22 +0000305 {
306 zlog (NULL, LOG_ERR, "%s EOF", nl->name);
307 return -1;
308 }
paul718e3742002-12-13 20:15:29 +0000309
310 if (msg.msg_namelen != sizeof snl)
paul7021c422003-07-15 12:52:22 +0000311 {
312 zlog (NULL, LOG_ERR, "%s sender address length error: length %d",
313 nl->name, msg.msg_namelen);
314 return -1;
315 }
paulb84d3a12003-11-17 10:31:01 +0000316
hasso206d8052005-04-09 16:38:51 +0000317 for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, (unsigned int) status);
paul7021c422003-07-15 12:52:22 +0000318 h = NLMSG_NEXT (h, status))
319 {
320 /* Finish of reading. */
321 if (h->nlmsg_type == NLMSG_DONE)
322 return ret;
paul718e3742002-12-13 20:15:29 +0000323
paul7021c422003-07-15 12:52:22 +0000324 /* Error handling. */
325 if (h->nlmsg_type == NLMSG_ERROR)
326 {
327 struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h);
Stephen Hemminger898987e2008-08-17 16:56:15 +0100328 int errnum = err->error;
329 int msg_type = err->msg.nlmsg_type;
paul7021c422003-07-15 12:52:22 +0000330
paul718e3742002-12-13 20:15:29 +0000331 /* If the error field is zero, then this is an ACK */
paul7021c422003-07-15 12:52:22 +0000332 if (err->error == 0)
paul718e3742002-12-13 20:15:29 +0000333 {
paul7021c422003-07-15 12:52:22 +0000334 if (IS_ZEBRA_DEBUG_KERNEL)
335 {
hasso1ada8192005-06-12 11:28:18 +0000336 zlog_debug ("%s: %s ACK: type=%s(%u), seq=%u, pid=%u",
paul7021c422003-07-15 12:52:22 +0000337 __FUNCTION__, nl->name,
338 lookup (nlmsg_str, err->msg.nlmsg_type),
339 err->msg.nlmsg_type, err->msg.nlmsg_seq,
340 err->msg.nlmsg_pid);
paul718e3742002-12-13 20:15:29 +0000341 }
paul7021c422003-07-15 12:52:22 +0000342
343 /* return if not a multipart message, otherwise continue */
344 if (!(h->nlmsg_flags & NLM_F_MULTI))
345 {
346 return 0;
paul718e3742002-12-13 20:15:29 +0000347 }
paul7021c422003-07-15 12:52:22 +0000348 continue;
paul718e3742002-12-13 20:15:29 +0000349 }
paul7021c422003-07-15 12:52:22 +0000350
paul718e3742002-12-13 20:15:29 +0000351 if (h->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr)))
paul7021c422003-07-15 12:52:22 +0000352 {
353 zlog (NULL, LOG_ERR, "%s error: message truncated",
354 nl->name);
355 return -1;
356 }
pauld753e9e2003-01-22 19:45:50 +0000357
Stephen Hemminger898987e2008-08-17 16:56:15 +0100358 /* Deal with errors that occur because of races in link handling */
Feng Lu758fb8f2014-07-03 18:23:09 +0800359 if (nl == &zvrf->netlink_cmd
Stephen Hemminger898987e2008-08-17 16:56:15 +0100360 && ((msg_type == RTM_DELROUTE &&
361 (-errnum == ENODEV || -errnum == ESRCH))
362 || (msg_type == RTM_NEWROUTE && -errnum == EEXIST)))
363 {
364 if (IS_ZEBRA_DEBUG_KERNEL)
365 zlog_debug ("%s: error: %s type=%s(%u), seq=%u, pid=%u",
366 nl->name, safe_strerror (-errnum),
367 lookup (nlmsg_str, msg_type),
368 msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid);
369 return 0;
370 }
paul718e3742002-12-13 20:15:29 +0000371
Stephen Hemminger898987e2008-08-17 16:56:15 +0100372 zlog_err ("%s error: %s, type=%s(%u), seq=%u, pid=%u",
373 nl->name, safe_strerror (-errnum),
374 lookup (nlmsg_str, msg_type),
375 msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid);
paul7021c422003-07-15 12:52:22 +0000376 return -1;
377 }
paul718e3742002-12-13 20:15:29 +0000378
paul7021c422003-07-15 12:52:22 +0000379 /* OK we got netlink message. */
380 if (IS_ZEBRA_DEBUG_KERNEL)
hasso1ada8192005-06-12 11:28:18 +0000381 zlog_debug ("netlink_parse_info: %s type %s(%u), seq=%u, pid=%u",
paul7021c422003-07-15 12:52:22 +0000382 nl->name,
383 lookup (nlmsg_str, h->nlmsg_type), h->nlmsg_type,
384 h->nlmsg_seq, h->nlmsg_pid);
385
Christian Franke599da952013-01-24 14:04:43 +0000386 /* skip unsolicited messages originating from command socket
387 * linux sets the originators port-id for {NEW|DEL}ADDR messages,
388 * so this has to be checked here. */
Feng Lu758fb8f2014-07-03 18:23:09 +0800389 if (nl != &zvrf->netlink_cmd
390 && h->nlmsg_pid == zvrf->netlink_cmd.snl.nl_pid
Christian Franke599da952013-01-24 14:04:43 +0000391 && (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR))
paul7021c422003-07-15 12:52:22 +0000392 {
393 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000394 zlog_debug ("netlink_parse_info: %s packet comes from %s",
Feng Lu758fb8f2014-07-03 18:23:09 +0800395 zvrf->netlink_cmd.name, nl->name);
paul7021c422003-07-15 12:52:22 +0000396 continue;
397 }
398
Feng Lu758fb8f2014-07-03 18:23:09 +0800399 error = (*filter) (&snl, h, zvrf->vrf_id);
paul7021c422003-07-15 12:52:22 +0000400 if (error < 0)
401 {
402 zlog (NULL, LOG_ERR, "%s filter function error", nl->name);
403 ret = error;
404 }
405 }
paul718e3742002-12-13 20:15:29 +0000406
407 /* After error care. */
408 if (msg.msg_flags & MSG_TRUNC)
paul7021c422003-07-15 12:52:22 +0000409 {
410 zlog (NULL, LOG_ERR, "%s error: message truncated", nl->name);
411 continue;
412 }
paul718e3742002-12-13 20:15:29 +0000413 if (status)
paul7021c422003-07-15 12:52:22 +0000414 {
415 zlog (NULL, LOG_ERR, "%s error: data remnant size %d", nl->name,
416 status);
417 return -1;
418 }
paul718e3742002-12-13 20:15:29 +0000419 }
420 return ret;
421}
422
423/* Utility function for parse rtattr. */
424static void
paul7021c422003-07-15 12:52:22 +0000425netlink_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta,
426 int len)
paul718e3742002-12-13 20:15:29 +0000427{
paul7021c422003-07-15 12:52:22 +0000428 while (RTA_OK (rta, len))
paul718e3742002-12-13 20:15:29 +0000429 {
430 if (rta->rta_type <= max)
paul7021c422003-07-15 12:52:22 +0000431 tb[rta->rta_type] = rta;
432 rta = RTA_NEXT (rta, len);
paul718e3742002-12-13 20:15:29 +0000433 }
434}
435
Josh Bailey26e2ae32012-03-22 01:09:21 -0700436/* Utility function to parse hardware link-layer address and update ifp */
437static void
438netlink_interface_update_hw_addr (struct rtattr **tb, struct interface *ifp)
439{
440 int i;
441
442 if (tb[IFLA_ADDRESS])
443 {
444 int hw_addr_len;
445
446 hw_addr_len = RTA_PAYLOAD (tb[IFLA_ADDRESS]);
447
448 if (hw_addr_len > INTERFACE_HWADDR_MAX)
449 zlog_warn ("Hardware address is too large: %d", hw_addr_len);
450 else
451 {
452 ifp->hw_addr_len = hw_addr_len;
453 memcpy (ifp->hw_addr, RTA_DATA (tb[IFLA_ADDRESS]), hw_addr_len);
454
455 for (i = 0; i < hw_addr_len; i++)
456 if (ifp->hw_addr[i] != 0)
457 break;
458
459 if (i == hw_addr_len)
460 ifp->hw_addr_len = 0;
461 else
462 ifp->hw_addr_len = hw_addr_len;
463 }
464 }
465}
466
Timo Teräs954c7d62016-01-15 17:36:33 +0200467static enum zebra_link_type
468netlink_to_zebra_link_type (unsigned int hwt)
469{
470 switch (hwt)
471 {
472 case ARPHRD_ETHER: return ZEBRA_LLT_ETHER;
473 case ARPHRD_EETHER: return ZEBRA_LLT_EETHER;
474 case ARPHRD_AX25: return ZEBRA_LLT_AX25;
475 case ARPHRD_PRONET: return ZEBRA_LLT_PRONET;
476 case ARPHRD_IEEE802: return ZEBRA_LLT_IEEE802;
477 case ARPHRD_ARCNET: return ZEBRA_LLT_ARCNET;
478 case ARPHRD_APPLETLK: return ZEBRA_LLT_APPLETLK;
479 case ARPHRD_DLCI: return ZEBRA_LLT_DLCI;
480 case ARPHRD_ATM: return ZEBRA_LLT_ATM;
481 case ARPHRD_METRICOM: return ZEBRA_LLT_METRICOM;
482 case ARPHRD_IEEE1394: return ZEBRA_LLT_IEEE1394;
483 case ARPHRD_EUI64: return ZEBRA_LLT_EUI64;
484 case ARPHRD_INFINIBAND: return ZEBRA_LLT_INFINIBAND;
485 case ARPHRD_SLIP: return ZEBRA_LLT_SLIP;
486 case ARPHRD_CSLIP: return ZEBRA_LLT_CSLIP;
487 case ARPHRD_SLIP6: return ZEBRA_LLT_SLIP6;
488 case ARPHRD_CSLIP6: return ZEBRA_LLT_CSLIP6;
489 case ARPHRD_RSRVD: return ZEBRA_LLT_RSRVD;
490 case ARPHRD_ADAPT: return ZEBRA_LLT_ADAPT;
491 case ARPHRD_ROSE: return ZEBRA_LLT_ROSE;
492 case ARPHRD_X25: return ZEBRA_LLT_X25;
493 case ARPHRD_PPP: return ZEBRA_LLT_PPP;
494 case ARPHRD_CISCO: return ZEBRA_LLT_CHDLC;
495 case ARPHRD_LAPB: return ZEBRA_LLT_LAPB;
496 case ARPHRD_RAWHDLC: return ZEBRA_LLT_RAWHDLC;
497 case ARPHRD_TUNNEL: return ZEBRA_LLT_IPIP;
498 case ARPHRD_TUNNEL6: return ZEBRA_LLT_IPIP6;
499 case ARPHRD_FRAD: return ZEBRA_LLT_FRAD;
500 case ARPHRD_SKIP: return ZEBRA_LLT_SKIP;
501 case ARPHRD_LOOPBACK: return ZEBRA_LLT_LOOPBACK;
502 case ARPHRD_LOCALTLK: return ZEBRA_LLT_LOCALTLK;
503 case ARPHRD_FDDI: return ZEBRA_LLT_FDDI;
504 case ARPHRD_SIT: return ZEBRA_LLT_SIT;
505 case ARPHRD_IPDDP: return ZEBRA_LLT_IPDDP;
506 case ARPHRD_IPGRE: return ZEBRA_LLT_IPGRE;
507 case ARPHRD_PIMREG: return ZEBRA_LLT_PIMREG;
508 case ARPHRD_HIPPI: return ZEBRA_LLT_HIPPI;
509 case ARPHRD_ECONET: return ZEBRA_LLT_ECONET;
510 case ARPHRD_IRDA: return ZEBRA_LLT_IRDA;
511 case ARPHRD_FCPP: return ZEBRA_LLT_FCPP;
512 case ARPHRD_FCAL: return ZEBRA_LLT_FCAL;
513 case ARPHRD_FCPL: return ZEBRA_LLT_FCPL;
514 case ARPHRD_FCFABRIC: return ZEBRA_LLT_FCFABRIC;
515 case ARPHRD_IEEE802_TR: return ZEBRA_LLT_IEEE802_TR;
516 case ARPHRD_IEEE80211: return ZEBRA_LLT_IEEE80211;
517 case ARPHRD_IEEE802154: return ZEBRA_LLT_IEEE802154;
518#ifdef ARPHRD_IP6GRE
519 case ARPHRD_IP6GRE: return ZEBRA_LLT_IP6GRE;
520#endif
521#ifdef ARPHRD_IEEE802154_PHY
522 case ARPHRD_IEEE802154_PHY: return ZEBRA_LLT_IEEE802154_PHY;
523#endif
524
525 default: return ZEBRA_LLT_UNKNOWN;
526 }
527}
528
paul718e3742002-12-13 20:15:29 +0000529/* Called from interface_lookup_netlink(). This function is only used
530 during bootstrap. */
Stephen Hemminger6072b242008-08-14 16:52:26 +0100531static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800532netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h,
533 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000534{
535 int len;
536 struct ifinfomsg *ifi;
537 struct rtattr *tb[IFLA_MAX + 1];
538 struct interface *ifp;
539 char *name;
paul718e3742002-12-13 20:15:29 +0000540
541 ifi = NLMSG_DATA (h);
542
543 if (h->nlmsg_type != RTM_NEWLINK)
544 return 0;
545
546 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
547 if (len < 0)
548 return -1;
549
550 /* Looking up interface name. */
551 memset (tb, 0, sizeof tb);
552 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
paulc15cb242005-01-24 09:05:27 +0000553
paul1e193152005-02-14 23:53:05 +0000554#ifdef IFLA_WIRELESS
paulc15cb242005-01-24 09:05:27 +0000555 /* check for wireless messages to ignore */
556 if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
557 {
558 if (IS_ZEBRA_DEBUG_KERNEL)
559 zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__);
560 return 0;
561 }
paul1e193152005-02-14 23:53:05 +0000562#endif /* IFLA_WIRELESS */
paulc15cb242005-01-24 09:05:27 +0000563
paul718e3742002-12-13 20:15:29 +0000564 if (tb[IFLA_IFNAME] == NULL)
565 return -1;
paul7021c422003-07-15 12:52:22 +0000566 name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
paul718e3742002-12-13 20:15:29 +0000567
568 /* Add interface. */
Feng Lu758fb8f2014-07-03 18:23:09 +0800569 ifp = if_get_by_name_vrf (name, vrf_id);
ajsd2fc8892005-04-02 18:38:43 +0000570 set_ifindex(ifp, ifi->ifi_index);
paul718e3742002-12-13 20:15:29 +0000571 ifp->flags = ifi->ifi_flags & 0x0000fffff;
Stephen Hemminger4308abb2008-12-01 14:19:38 -0800572 ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]);
Brett Cipherydb19c852013-10-03 13:48:54 +0000573 ifp->metric = 0;
paul718e3742002-12-13 20:15:29 +0000574
575 /* Hardware type and address. */
Timo Teräs954c7d62016-01-15 17:36:33 +0200576 ifp->ll_type = netlink_to_zebra_link_type (ifi->ifi_type);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700577 netlink_interface_update_hw_addr (tb, ifp);
paul718e3742002-12-13 20:15:29 +0000578
579 if_add_update (ifp);
580
581 return 0;
582}
583
584/* Lookup interface IPv4/IPv6 address. */
Stephen Hemminger6072b242008-08-14 16:52:26 +0100585static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800586netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h,
587 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000588{
589 int len;
590 struct ifaddrmsg *ifa;
paul7021c422003-07-15 12:52:22 +0000591 struct rtattr *tb[IFA_MAX + 1];
paul718e3742002-12-13 20:15:29 +0000592 struct interface *ifp;
Andrew J. Schorre4529632006-12-12 19:18:21 +0000593 void *addr;
594 void *broad;
paul718e3742002-12-13 20:15:29 +0000595 u_char flags = 0;
596 char *label = NULL;
597
598 ifa = NLMSG_DATA (h);
599
paul7021c422003-07-15 12:52:22 +0000600 if (ifa->ifa_family != AF_INET
paul718e3742002-12-13 20:15:29 +0000601#ifdef HAVE_IPV6
602 && ifa->ifa_family != AF_INET6
603#endif /* HAVE_IPV6 */
paul7021c422003-07-15 12:52:22 +0000604 )
paul718e3742002-12-13 20:15:29 +0000605 return 0;
606
607 if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
608 return 0;
609
paul7021c422003-07-15 12:52:22 +0000610 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifaddrmsg));
paul718e3742002-12-13 20:15:29 +0000611 if (len < 0)
612 return -1;
613
614 memset (tb, 0, sizeof tb);
615 netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len);
616
Feng Lu758fb8f2014-07-03 18:23:09 +0800617 ifp = if_lookup_by_index_vrf (ifa->ifa_index, vrf_id);
paul718e3742002-12-13 20:15:29 +0000618 if (ifp == NULL)
619 {
Feng Lu758fb8f2014-07-03 18:23:09 +0800620 zlog_err ("netlink_interface_addr can't find interface by index %d vrf %u",
621 ifa->ifa_index, vrf_id);
paul718e3742002-12-13 20:15:29 +0000622 return -1;
623 }
624
paul7021c422003-07-15 12:52:22 +0000625 if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */
paul718e3742002-12-13 20:15:29 +0000626 {
paul00df0c12002-12-13 21:07:36 +0000627 char buf[BUFSIZ];
Feng Lu758fb8f2014-07-03 18:23:09 +0800628 zlog_debug ("netlink_interface_addr %s %s vrf %u:",
629 lookup (nlmsg_str, h->nlmsg_type), ifp->name, vrf_id);
paul718e3742002-12-13 20:15:29 +0000630 if (tb[IFA_LOCAL])
hasso206d8052005-04-09 16:38:51 +0000631 zlog_debug (" IFA_LOCAL %s/%d",
632 inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]),
633 buf, BUFSIZ), ifa->ifa_prefixlen);
paul718e3742002-12-13 20:15:29 +0000634 if (tb[IFA_ADDRESS])
hasso206d8052005-04-09 16:38:51 +0000635 zlog_debug (" IFA_ADDRESS %s/%d",
636 inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_ADDRESS]),
637 buf, BUFSIZ), ifa->ifa_prefixlen);
paul718e3742002-12-13 20:15:29 +0000638 if (tb[IFA_BROADCAST])
hasso206d8052005-04-09 16:38:51 +0000639 zlog_debug (" IFA_BROADCAST %s/%d",
640 inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_BROADCAST]),
641 buf, BUFSIZ), ifa->ifa_prefixlen);
paul00df0c12002-12-13 21:07:36 +0000642 if (tb[IFA_LABEL] && strcmp (ifp->name, RTA_DATA (tb[IFA_LABEL])))
ajsb6178002004-12-07 21:12:56 +0000643 zlog_debug (" IFA_LABEL %s", (char *)RTA_DATA (tb[IFA_LABEL]));
pauld34b8992006-01-17 18:03:04 +0000644
645 if (tb[IFA_CACHEINFO])
646 {
647 struct ifa_cacheinfo *ci = RTA_DATA (tb[IFA_CACHEINFO]);
648 zlog_debug (" IFA_CACHEINFO pref %d, valid %d",
649 ci->ifa_prefered, ci->ifa_valid);
650 }
paul718e3742002-12-13 20:15:29 +0000651 }
paul31a476c2003-09-29 19:54:53 +0000652
Andrew J. Schorre4529632006-12-12 19:18:21 +0000653 /* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */
654 if (tb[IFA_LOCAL] == NULL)
655 tb[IFA_LOCAL] = tb[IFA_ADDRESS];
paul31a476c2003-09-29 19:54:53 +0000656 if (tb[IFA_ADDRESS] == NULL)
657 tb[IFA_ADDRESS] = tb[IFA_LOCAL];
658
Andrew J. Schorre4529632006-12-12 19:18:21 +0000659 /* local interface address */
660 addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL);
661
662 /* is there a peer address? */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000663 if (tb[IFA_ADDRESS] &&
vize068fd772007-08-10 06:25:20 +0000664 memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_ADDRESS])))
paul7021c422003-07-15 12:52:22 +0000665 {
Andrew J. Schorre4529632006-12-12 19:18:21 +0000666 broad = RTA_DATA(tb[IFA_ADDRESS]);
667 SET_FLAG (flags, ZEBRA_IFA_PEER);
paul7021c422003-07-15 12:52:22 +0000668 }
paul31a476c2003-09-29 19:54:53 +0000669 else
Andrew J. Schorre4529632006-12-12 19:18:21 +0000670 /* seeking a broadcast address */
671 broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST]) : NULL);
paul00df0c12002-12-13 21:07:36 +0000672
Paul Jakma27b47252006-07-02 16:38:54 +0000673 /* addr is primary key, SOL if we don't have one */
674 if (addr == NULL)
675 {
676 zlog_debug ("%s: NULL address", __func__);
677 return -1;
678 }
679
paul718e3742002-12-13 20:15:29 +0000680 /* Flags. */
681 if (ifa->ifa_flags & IFA_F_SECONDARY)
682 SET_FLAG (flags, ZEBRA_IFA_SECONDARY);
683
684 /* Label */
685 if (tb[IFA_LABEL])
686 label = (char *) RTA_DATA (tb[IFA_LABEL]);
687
688 if (ifp && label && strcmp (ifp->name, label) == 0)
689 label = NULL;
690
691 /* Register interface address to the interface. */
692 if (ifa->ifa_family == AF_INET)
693 {
paul7021c422003-07-15 12:52:22 +0000694 if (h->nlmsg_type == RTM_NEWADDR)
695 connected_add_ipv4 (ifp, flags,
696 (struct in_addr *) addr, ifa->ifa_prefixlen,
697 (struct in_addr *) broad, label);
698 else
699 connected_delete_ipv4 (ifp, flags,
700 (struct in_addr *) addr, ifa->ifa_prefixlen,
paul0752ef02005-11-03 12:35:21 +0000701 (struct in_addr *) broad);
paul718e3742002-12-13 20:15:29 +0000702 }
703#ifdef HAVE_IPV6
704 if (ifa->ifa_family == AF_INET6)
705 {
706 if (h->nlmsg_type == RTM_NEWADDR)
Andrew J. Schorre4529632006-12-12 19:18:21 +0000707 connected_add_ipv6 (ifp, flags,
paul7021c422003-07-15 12:52:22 +0000708 (struct in6_addr *) addr, ifa->ifa_prefixlen,
paul0752ef02005-11-03 12:35:21 +0000709 (struct in6_addr *) broad, label);
paul718e3742002-12-13 20:15:29 +0000710 else
paul7021c422003-07-15 12:52:22 +0000711 connected_delete_ipv6 (ifp,
712 (struct in6_addr *) addr, ifa->ifa_prefixlen,
713 (struct in6_addr *) broad);
paul718e3742002-12-13 20:15:29 +0000714 }
paul7021c422003-07-15 12:52:22 +0000715#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +0000716
717 return 0;
718}
719
720/* Looking up routing table by netlink interface. */
Stephen Hemminger6072b242008-08-14 16:52:26 +0100721static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800722netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
723 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000724{
725 int len;
726 struct rtmsg *rtm;
paul7021c422003-07-15 12:52:22 +0000727 struct rtattr *tb[RTA_MAX + 1];
paul718e3742002-12-13 20:15:29 +0000728 u_char flags = 0;
paul7021c422003-07-15 12:52:22 +0000729
730 char anyaddr[16] = { 0 };
paul718e3742002-12-13 20:15:29 +0000731
732 int index;
733 int table;
Timo Teräsb11f3b52015-11-02 16:50:07 +0200734 u_int32_t mtu = 0;
hasso34195bf2004-04-06 12:07:06 +0000735
paul718e3742002-12-13 20:15:29 +0000736 void *dest;
737 void *gate;
Paul Jakma7514fb72007-05-02 16:05:35 +0000738 void *src;
paul718e3742002-12-13 20:15:29 +0000739
740 rtm = NLMSG_DATA (h);
741
742 if (h->nlmsg_type != RTM_NEWROUTE)
743 return 0;
744 if (rtm->rtm_type != RTN_UNICAST)
745 return 0;
746
747 table = rtm->rtm_table;
paul7021c422003-07-15 12:52:22 +0000748#if 0 /* we weed them out later in rib_weed_tables () */
paulb21b19c2003-06-15 01:28:29 +0000749 if (table != RT_TABLE_MAIN && table != zebrad.rtm_table_default)
paul718e3742002-12-13 20:15:29 +0000750 return 0;
751#endif
752
paul7021c422003-07-15 12:52:22 +0000753 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
paul718e3742002-12-13 20:15:29 +0000754 if (len < 0)
755 return -1;
756
757 memset (tb, 0, sizeof tb);
758 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
759
760 if (rtm->rtm_flags & RTM_F_CLONED)
761 return 0;
762 if (rtm->rtm_protocol == RTPROT_REDIRECT)
763 return 0;
764 if (rtm->rtm_protocol == RTPROT_KERNEL)
765 return 0;
766
767 if (rtm->rtm_src_len != 0)
768 return 0;
769
770 /* Route which inserted by Zebra. */
771 if (rtm->rtm_protocol == RTPROT_ZEBRA)
772 flags |= ZEBRA_FLAG_SELFROUTE;
paul7021c422003-07-15 12:52:22 +0000773
paul718e3742002-12-13 20:15:29 +0000774 index = 0;
775 dest = NULL;
776 gate = NULL;
Paul Jakma7514fb72007-05-02 16:05:35 +0000777 src = NULL;
paul718e3742002-12-13 20:15:29 +0000778
779 if (tb[RTA_OIF])
780 index = *(int *) RTA_DATA (tb[RTA_OIF]);
781
782 if (tb[RTA_DST])
783 dest = RTA_DATA (tb[RTA_DST]);
784 else
785 dest = anyaddr;
786
Paul Jakma7514fb72007-05-02 16:05:35 +0000787 if (tb[RTA_PREFSRC])
788 src = RTA_DATA (tb[RTA_PREFSRC]);
789
paul718e3742002-12-13 20:15:29 +0000790 if (tb[RTA_GATEWAY])
791 gate = RTA_DATA (tb[RTA_GATEWAY]);
792
Timo Teräsb11f3b52015-11-02 16:50:07 +0200793 if (tb[RTA_METRICS])
794 {
795 struct rtattr *mxrta[RTAX_MAX+1];
796
797 memset (mxrta, 0, sizeof mxrta);
798 netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),
799 RTA_PAYLOAD(tb[RTA_METRICS]));
800
801 if (mxrta[RTAX_MTU])
802 mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]);
803 }
804
paul718e3742002-12-13 20:15:29 +0000805 if (rtm->rtm_family == AF_INET)
806 {
807 struct prefix_ipv4 p;
808 p.family = AF_INET;
809 memcpy (&p.prefix, dest, 4);
810 p.prefixlen = rtm->rtm_dst_len;
811
Josh Bailey26e2ae32012-03-22 01:09:21 -0700812 if (!tb[RTA_MULTIPATH])
813 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index,
Timo Teräs4d3ae712016-01-15 17:36:32 +0200814 vrf_id, table, 0, mtu, 0, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700815 else
816 {
817 /* This is a multipath route */
818
819 struct rib *rib;
820 struct rtnexthop *rtnh =
821 (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
822
823 len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
824
825 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
826 rib->type = ZEBRA_ROUTE_KERNEL;
827 rib->distance = 0;
828 rib->flags = flags;
Timo Teräs4d3ae712016-01-15 17:36:32 +0200829 rib->metric = 0;
Timo Teräsb11f3b52015-11-02 16:50:07 +0200830 rib->mtu = mtu;
Feng Lu758fb8f2014-07-03 18:23:09 +0800831 rib->vrf_id = vrf_id;
Josh Bailey26e2ae32012-03-22 01:09:21 -0700832 rib->table = table;
833 rib->nexthop_num = 0;
834 rib->uptime = time (NULL);
835
836 for (;;)
837 {
838 if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
839 break;
840
Josh Bailey26e2ae32012-03-22 01:09:21 -0700841 index = rtnh->rtnh_ifindex;
842 gate = 0;
843 if (rtnh->rtnh_len > sizeof (*rtnh))
844 {
845 memset (tb, 0, sizeof (tb));
846 netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
847 rtnh->rtnh_len - sizeof (*rtnh));
848 if (tb[RTA_GATEWAY])
849 gate = RTA_DATA (tb[RTA_GATEWAY]);
850 }
851
852 if (gate)
853 {
854 if (index)
Pradosh Mohapatra60cc9592015-11-09 20:21:41 -0500855 rib_nexthop_ipv4_ifindex_add (rib, gate, src, index);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700856 else
Pradosh Mohapatra60cc9592015-11-09 20:21:41 -0500857 rib_nexthop_ipv4_add (rib, gate, src);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700858 }
859 else
Pradosh Mohapatra60cc9592015-11-09 20:21:41 -0500860 rib_nexthop_ifindex_add (rib, index);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700861
862 len -= NLMSG_ALIGN(rtnh->rtnh_len);
863 rtnh = RTNH_NEXT(rtnh);
864 }
865
866 if (rib->nexthop_num == 0)
867 XFREE (MTYPE_RIB, rib);
868 else
Avneesh Sachdev14d2bba2012-04-11 23:51:08 -0700869 rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700870 }
paul718e3742002-12-13 20:15:29 +0000871 }
872#ifdef HAVE_IPV6
873 if (rtm->rtm_family == AF_INET6)
874 {
875 struct prefix_ipv6 p;
876 p.family = AF_INET6;
877 memcpy (&p.prefix, dest, 16);
878 p.prefixlen = rtm->rtm_dst_len;
879
Feng Lu758fb8f2014-07-03 18:23:09 +0800880 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, vrf_id,
Timo Teräs4d3ae712016-01-15 17:36:32 +0200881 table, 0, mtu, 0, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000882 }
883#endif /* HAVE_IPV6 */
884
885 return 0;
886}
887
Stephen Hemminger1423c802008-08-14 17:59:25 +0100888static const struct message rtproto_str[] = {
paul718e3742002-12-13 20:15:29 +0000889 {RTPROT_REDIRECT, "redirect"},
890 {RTPROT_KERNEL, "kernel"},
891 {RTPROT_BOOT, "boot"},
892 {RTPROT_STATIC, "static"},
893 {RTPROT_GATED, "GateD"},
894 {RTPROT_RA, "router advertisement"},
895 {RTPROT_MRT, "MRT"},
896 {RTPROT_ZEBRA, "Zebra"},
897#ifdef RTPROT_BIRD
898 {RTPROT_BIRD, "BIRD"},
899#endif /* RTPROT_BIRD */
900 {0, NULL}
901};
902
903/* Routing information change from the kernel. */
Stephen Hemminger6072b242008-08-14 16:52:26 +0100904static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800905netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
906 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000907{
908 int len;
909 struct rtmsg *rtm;
paul7021c422003-07-15 12:52:22 +0000910 struct rtattr *tb[RTA_MAX + 1];
James Li92992c62015-11-09 20:21:57 -0500911 u_char zebra_flags = 0;
paul7021c422003-07-15 12:52:22 +0000912
913 char anyaddr[16] = { 0 };
paul718e3742002-12-13 20:15:29 +0000914
915 int index;
916 int table;
Timo Teräsb11f3b52015-11-02 16:50:07 +0200917 u_int32_t mtu = 0;
Dmitry Popov83d16142011-09-11 13:48:25 +0400918
paul718e3742002-12-13 20:15:29 +0000919 void *dest;
920 void *gate;
Paul Jakma7514fb72007-05-02 16:05:35 +0000921 void *src;
paul718e3742002-12-13 20:15:29 +0000922
923 rtm = NLMSG_DATA (h);
924
paul7021c422003-07-15 12:52:22 +0000925 if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
paul718e3742002-12-13 20:15:29 +0000926 {
927 /* If this is not route add/delete message print warning. */
Feng Lu758fb8f2014-07-03 18:23:09 +0800928 zlog_warn ("Kernel message: %d vrf %u\n", h->nlmsg_type, vrf_id);
paul718e3742002-12-13 20:15:29 +0000929 return 0;
930 }
931
932 /* Connected route. */
933 if (IS_ZEBRA_DEBUG_KERNEL)
Feng Lu758fb8f2014-07-03 18:23:09 +0800934 zlog_debug ("%s %s %s proto %s vrf %u",
paul7021c422003-07-15 12:52:22 +0000935 h->nlmsg_type ==
936 RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
937 rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",
938 rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast",
Feng Lu758fb8f2014-07-03 18:23:09 +0800939 lookup (rtproto_str, rtm->rtm_protocol),
940 vrf_id);
paul718e3742002-12-13 20:15:29 +0000941
942 if (rtm->rtm_type != RTN_UNICAST)
943 {
944 return 0;
945 }
946
947 table = rtm->rtm_table;
paulb21b19c2003-06-15 01:28:29 +0000948 if (table != RT_TABLE_MAIN && table != zebrad.rtm_table_default)
paul718e3742002-12-13 20:15:29 +0000949 {
950 return 0;
951 }
952
paul7021c422003-07-15 12:52:22 +0000953 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
paul718e3742002-12-13 20:15:29 +0000954 if (len < 0)
955 return -1;
956
957 memset (tb, 0, sizeof tb);
958 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
959
960 if (rtm->rtm_flags & RTM_F_CLONED)
961 return 0;
962 if (rtm->rtm_protocol == RTPROT_REDIRECT)
963 return 0;
964 if (rtm->rtm_protocol == RTPROT_KERNEL)
965 return 0;
966
967 if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)
968 return 0;
James Li92992c62015-11-09 20:21:57 -0500969 if (rtm->rtm_protocol == RTPROT_ZEBRA)
970 SET_FLAG(zebra_flags, ZEBRA_FLAG_SELFROUTE);
paul718e3742002-12-13 20:15:29 +0000971
972 if (rtm->rtm_src_len != 0)
973 {
Feng Lu758fb8f2014-07-03 18:23:09 +0800974 zlog_warn ("netlink_route_change(): no src len, vrf %u", vrf_id);
paul718e3742002-12-13 20:15:29 +0000975 return 0;
976 }
paul7021c422003-07-15 12:52:22 +0000977
paul718e3742002-12-13 20:15:29 +0000978 index = 0;
979 dest = NULL;
980 gate = NULL;
Paul Jakma7514fb72007-05-02 16:05:35 +0000981 src = NULL;
paul718e3742002-12-13 20:15:29 +0000982
983 if (tb[RTA_OIF])
984 index = *(int *) RTA_DATA (tb[RTA_OIF]);
985
986 if (tb[RTA_DST])
987 dest = RTA_DATA (tb[RTA_DST]);
988 else
989 dest = anyaddr;
990
991 if (tb[RTA_GATEWAY])
992 gate = RTA_DATA (tb[RTA_GATEWAY]);
993
Paul Jakma7514fb72007-05-02 16:05:35 +0000994 if (tb[RTA_PREFSRC])
995 src = RTA_DATA (tb[RTA_PREFSRC]);
996
Timo Teräsb11f3b52015-11-02 16:50:07 +0200997 if (h->nlmsg_type == RTM_NEWROUTE)
998 {
Timo Teräsb11f3b52015-11-02 16:50:07 +0200999 if (tb[RTA_METRICS])
1000 {
1001 struct rtattr *mxrta[RTAX_MAX+1];
1002
1003 memset (mxrta, 0, sizeof mxrta);
1004 netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),
1005 RTA_PAYLOAD(tb[RTA_METRICS]));
1006
1007 if (mxrta[RTAX_MTU])
1008 mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]);
1009 }
1010 }
Josh Bailey26e2ae32012-03-22 01:09:21 -07001011
paul718e3742002-12-13 20:15:29 +00001012 if (rtm->rtm_family == AF_INET)
1013 {
1014 struct prefix_ipv4 p;
1015 p.family = AF_INET;
1016 memcpy (&p.prefix, dest, 4);
1017 p.prefixlen = rtm->rtm_dst_len;
1018
1019 if (IS_ZEBRA_DEBUG_KERNEL)
paul7021c422003-07-15 12:52:22 +00001020 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001021 char buf[PREFIX_STRLEN];
Feng Lu758fb8f2014-07-03 18:23:09 +08001022 zlog_debug ("%s %s vrf %u",
Timo Teräsbe6335d2015-05-23 11:08:41 +03001023 h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
Feng Lu758fb8f2014-07-03 18:23:09 +08001024 prefix2str (&p, buf, sizeof(buf)), vrf_id);
paul7021c422003-07-15 12:52:22 +00001025 }
paul718e3742002-12-13 20:15:29 +00001026
1027 if (h->nlmsg_type == RTM_NEWROUTE)
Josh Bailey26e2ae32012-03-22 01:09:21 -07001028 {
1029 if (!tb[RTA_MULTIPATH])
Feng Lu758fb8f2014-07-03 18:23:09 +08001030 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, vrf_id,
Timo Teräs4d3ae712016-01-15 17:36:32 +02001031 table, 0, mtu, 0, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -07001032 else
1033 {
1034 /* This is a multipath route */
1035
1036 struct rib *rib;
1037 struct rtnexthop *rtnh =
1038 (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
1039
1040 len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
1041
1042 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1043 rib->type = ZEBRA_ROUTE_KERNEL;
1044 rib->distance = 0;
1045 rib->flags = 0;
Timo Teräs4d3ae712016-01-15 17:36:32 +02001046 rib->metric = 0;
Timo Teräsb11f3b52015-11-02 16:50:07 +02001047 rib->mtu = mtu;
Feng Lu758fb8f2014-07-03 18:23:09 +08001048 rib->vrf_id = vrf_id;
Josh Bailey26e2ae32012-03-22 01:09:21 -07001049 rib->table = table;
1050 rib->nexthop_num = 0;
1051 rib->uptime = time (NULL);
1052
1053 for (;;)
1054 {
1055 if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
1056 break;
1057
Josh Bailey26e2ae32012-03-22 01:09:21 -07001058 index = rtnh->rtnh_ifindex;
1059 gate = 0;
1060 if (rtnh->rtnh_len > sizeof (*rtnh))
1061 {
1062 memset (tb, 0, sizeof (tb));
1063 netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
1064 rtnh->rtnh_len - sizeof (*rtnh));
1065 if (tb[RTA_GATEWAY])
1066 gate = RTA_DATA (tb[RTA_GATEWAY]);
1067 }
1068
1069 if (gate)
1070 {
1071 if (index)
Pradosh Mohapatra60cc9592015-11-09 20:21:41 -05001072 rib_nexthop_ipv4_ifindex_add (rib, gate, src, index);
Josh Bailey26e2ae32012-03-22 01:09:21 -07001073 else
Pradosh Mohapatra60cc9592015-11-09 20:21:41 -05001074 rib_nexthop_ipv4_add (rib, gate, src);
Josh Bailey26e2ae32012-03-22 01:09:21 -07001075 }
1076 else
Pradosh Mohapatra60cc9592015-11-09 20:21:41 -05001077 rib_nexthop_ifindex_add (rib, index);
Josh Bailey26e2ae32012-03-22 01:09:21 -07001078
1079 len -= NLMSG_ALIGN(rtnh->rtnh_len);
1080 rtnh = RTNH_NEXT(rtnh);
1081 }
1082
1083 if (rib->nexthop_num == 0)
1084 XFREE (MTYPE_RIB, rib);
1085 else
Avneesh Sachdev14d2bba2012-04-11 23:51:08 -07001086 rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -07001087 }
1088 }
paul718e3742002-12-13 20:15:29 +00001089 else
James Li92992c62015-11-09 20:21:57 -05001090 rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, gate,
1091 index, vrf_id, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001092 }
1093
1094#ifdef HAVE_IPV6
1095 if (rtm->rtm_family == AF_INET6)
1096 {
1097 struct prefix_ipv6 p;
paul718e3742002-12-13 20:15:29 +00001098
1099 p.family = AF_INET6;
1100 memcpy (&p.prefix, dest, 16);
1101 p.prefixlen = rtm->rtm_dst_len;
1102
1103 if (IS_ZEBRA_DEBUG_KERNEL)
paul7021c422003-07-15 12:52:22 +00001104 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001105 char buf[PREFIX_STRLEN];
Feng Lu758fb8f2014-07-03 18:23:09 +08001106 zlog_debug ("%s %s vrf %u",
Timo Teräsbe6335d2015-05-23 11:08:41 +03001107 h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
Feng Lu758fb8f2014-07-03 18:23:09 +08001108 prefix2str (&p, buf, sizeof(buf)), vrf_id);
paul7021c422003-07-15 12:52:22 +00001109 }
paul718e3742002-12-13 20:15:29 +00001110
1111 if (h->nlmsg_type == RTM_NEWROUTE)
Feng Lu758fb8f2014-07-03 18:23:09 +08001112 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, vrf_id, table,
Timo Teräs4d3ae712016-01-15 17:36:32 +02001113 0, mtu, 0, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001114 else
James Li92992c62015-11-09 20:21:57 -05001115 rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, gate, index, vrf_id,
Feng Lu0d0686f2015-05-22 11:40:02 +02001116 SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001117 }
1118#endif /* HAVE_IPV6 */
1119
1120 return 0;
1121}
1122
Stephen Hemminger6072b242008-08-14 16:52:26 +01001123static int
Feng Lu758fb8f2014-07-03 18:23:09 +08001124netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
1125 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001126{
1127 int len;
1128 struct ifinfomsg *ifi;
paul7021c422003-07-15 12:52:22 +00001129 struct rtattr *tb[IFLA_MAX + 1];
paul718e3742002-12-13 20:15:29 +00001130 struct interface *ifp;
1131 char *name;
1132
1133 ifi = NLMSG_DATA (h);
1134
paul7021c422003-07-15 12:52:22 +00001135 if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
paul718e3742002-12-13 20:15:29 +00001136 {
1137 /* If this is not link add/delete message so print warning. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001138 zlog_warn ("netlink_link_change: wrong kernel message %d vrf %u\n",
1139 h->nlmsg_type, vrf_id);
paul718e3742002-12-13 20:15:29 +00001140 return 0;
1141 }
1142
1143 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
1144 if (len < 0)
1145 return -1;
1146
1147 /* Looking up interface name. */
1148 memset (tb, 0, sizeof tb);
1149 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
paulc15cb242005-01-24 09:05:27 +00001150
paul1e193152005-02-14 23:53:05 +00001151#ifdef IFLA_WIRELESS
paulc15cb242005-01-24 09:05:27 +00001152 /* check for wireless messages to ignore */
1153 if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
1154 {
1155 if (IS_ZEBRA_DEBUG_KERNEL)
Feng Lu758fb8f2014-07-03 18:23:09 +08001156 zlog_debug ("%s: ignoring IFLA_WIRELESS message, vrf %u", __func__,
1157 vrf_id);
paulc15cb242005-01-24 09:05:27 +00001158 return 0;
1159 }
paul1e193152005-02-14 23:53:05 +00001160#endif /* IFLA_WIRELESS */
paulc15cb242005-01-24 09:05:27 +00001161
paul718e3742002-12-13 20:15:29 +00001162 if (tb[IFLA_IFNAME] == NULL)
1163 return -1;
paul7021c422003-07-15 12:52:22 +00001164 name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
paul718e3742002-12-13 20:15:29 +00001165
1166 /* Add interface. */
1167 if (h->nlmsg_type == RTM_NEWLINK)
1168 {
Feng Lu758fb8f2014-07-03 18:23:09 +08001169 ifp = if_lookup_by_name_vrf (name, vrf_id);
paul718e3742002-12-13 20:15:29 +00001170
paul7021c422003-07-15 12:52:22 +00001171 if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1172 {
1173 if (ifp == NULL)
Feng Lu758fb8f2014-07-03 18:23:09 +08001174 ifp = if_get_by_name_vrf (name, vrf_id);
paul718e3742002-12-13 20:15:29 +00001175
ajsd2fc8892005-04-02 18:38:43 +00001176 set_ifindex(ifp, ifi->ifi_index);
paul7021c422003-07-15 12:52:22 +00001177 ifp->flags = ifi->ifi_flags & 0x0000fffff;
paul44145db2004-05-09 11:00:23 +00001178 ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
Brett Cipherydb19c852013-10-03 13:48:54 +00001179 ifp->metric = 0;
paul718e3742002-12-13 20:15:29 +00001180
Josh Bailey26e2ae32012-03-22 01:09:21 -07001181 netlink_interface_update_hw_addr (tb, ifp);
1182
paul7021c422003-07-15 12:52:22 +00001183 /* If new link is added. */
1184 if_add_update (ifp);
1185 }
paul718e3742002-12-13 20:15:29 +00001186 else
paul7021c422003-07-15 12:52:22 +00001187 {
1188 /* Interface status change. */
ajsd2fc8892005-04-02 18:38:43 +00001189 set_ifindex(ifp, ifi->ifi_index);
paul44145db2004-05-09 11:00:23 +00001190 ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
Brett Cipherydb19c852013-10-03 13:48:54 +00001191 ifp->metric = 0;
paul718e3742002-12-13 20:15:29 +00001192
Josh Bailey26e2ae32012-03-22 01:09:21 -07001193 netlink_interface_update_hw_addr (tb, ifp);
1194
paul7021c422003-07-15 12:52:22 +00001195 if (if_is_operative (ifp))
1196 {
1197 ifp->flags = ifi->ifi_flags & 0x0000fffff;
1198 if (!if_is_operative (ifp))
1199 if_down (ifp);
ajsa608bbf2005-03-29 17:03:49 +00001200 else
1201 /* Must notify client daemons of new interface status. */
1202 zebra_interface_up_update (ifp);
paul7021c422003-07-15 12:52:22 +00001203 }
1204 else
1205 {
1206 ifp->flags = ifi->ifi_flags & 0x0000fffff;
1207 if (if_is_operative (ifp))
1208 if_up (ifp);
1209 }
1210 }
paul718e3742002-12-13 20:15:29 +00001211 }
1212 else
1213 {
1214 /* RTM_DELLINK. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001215 ifp = if_lookup_by_name_vrf (name, vrf_id);
paul718e3742002-12-13 20:15:29 +00001216
1217 if (ifp == NULL)
paul7021c422003-07-15 12:52:22 +00001218 {
Feng Lu758fb8f2014-07-03 18:23:09 +08001219 zlog_warn ("interface %s vrf %u is deleted but can't find",
1220 name, vrf_id);
paul7021c422003-07-15 12:52:22 +00001221 return 0;
1222 }
1223
paul718e3742002-12-13 20:15:29 +00001224 if_delete_update (ifp);
1225 }
1226
1227 return 0;
1228}
1229
Stephen Hemminger6072b242008-08-14 16:52:26 +01001230static int
Feng Lu758fb8f2014-07-03 18:23:09 +08001231netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h,
1232 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001233{
Stephen Hemminger3d265b42008-08-16 17:30:39 +01001234 /* JF: Ignore messages that aren't from the kernel */
1235 if ( snl->nl_pid != 0 )
1236 {
1237 zlog ( NULL, LOG_ERR, "Ignoring message from pid %u", snl->nl_pid );
1238 return 0;
1239 }
1240
paul718e3742002-12-13 20:15:29 +00001241 switch (h->nlmsg_type)
1242 {
1243 case RTM_NEWROUTE:
Feng Lu758fb8f2014-07-03 18:23:09 +08001244 return netlink_route_change (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001245 break;
1246 case RTM_DELROUTE:
Feng Lu758fb8f2014-07-03 18:23:09 +08001247 return netlink_route_change (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001248 break;
1249 case RTM_NEWLINK:
Feng Lu758fb8f2014-07-03 18:23:09 +08001250 return netlink_link_change (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001251 break;
1252 case RTM_DELLINK:
Feng Lu758fb8f2014-07-03 18:23:09 +08001253 return netlink_link_change (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001254 break;
1255 case RTM_NEWADDR:
Feng Lu758fb8f2014-07-03 18:23:09 +08001256 return netlink_interface_addr (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001257 break;
1258 case RTM_DELADDR:
Feng Lu758fb8f2014-07-03 18:23:09 +08001259 return netlink_interface_addr (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001260 break;
1261 default:
Feng Lu758fb8f2014-07-03 18:23:09 +08001262 zlog_warn ("Unknown netlink nlmsg_type %d vrf %u\n", h->nlmsg_type,
1263 vrf_id);
paul718e3742002-12-13 20:15:29 +00001264 break;
1265 }
1266 return 0;
1267}
1268
1269/* Interface lookup by netlink socket. */
1270int
Feng Lu758fb8f2014-07-03 18:23:09 +08001271interface_lookup_netlink (struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001272{
1273 int ret;
paul7021c422003-07-15 12:52:22 +00001274
paul718e3742002-12-13 20:15:29 +00001275 /* Get interface information. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001276 ret = netlink_request (AF_PACKET, RTM_GETLINK, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001277 if (ret < 0)
1278 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001279 ret = netlink_parse_info (netlink_interface, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001280 if (ret < 0)
1281 return ret;
1282
1283 /* Get IPv4 address of the interfaces. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001284 ret = netlink_request (AF_INET, RTM_GETADDR, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001285 if (ret < 0)
1286 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001287 ret = netlink_parse_info (netlink_interface_addr, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001288 if (ret < 0)
1289 return ret;
1290
1291#ifdef HAVE_IPV6
1292 /* Get IPv6 address of the interfaces. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001293 ret = netlink_request (AF_INET6, RTM_GETADDR, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001294 if (ret < 0)
1295 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001296 ret = netlink_parse_info (netlink_interface_addr, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001297 if (ret < 0)
1298 return ret;
1299#endif /* HAVE_IPV6 */
1300
1301 return 0;
1302}
1303
1304/* Routing table read function using netlink interface. Only called
1305 bootstrap time. */
1306int
Feng Lu758fb8f2014-07-03 18:23:09 +08001307netlink_route_read (struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001308{
1309 int ret;
paul7021c422003-07-15 12:52:22 +00001310
paul718e3742002-12-13 20:15:29 +00001311 /* Get IPv4 routing table. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001312 ret = netlink_request (AF_INET, RTM_GETROUTE, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001313 if (ret < 0)
1314 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001315 ret = netlink_parse_info (netlink_routing_table, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001316 if (ret < 0)
1317 return ret;
1318
1319#ifdef HAVE_IPV6
1320 /* Get IPv6 routing table. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001321 ret = netlink_request (AF_INET6, RTM_GETROUTE, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001322 if (ret < 0)
1323 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001324 ret = netlink_parse_info (netlink_routing_table, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001325 if (ret < 0)
1326 return ret;
1327#endif /* HAVE_IPV6 */
1328
1329 return 0;
1330}
1331
1332/* Utility function comes from iproute2.
1333 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001334int
Paul Jakma6f235412016-04-05 13:21:20 +01001335addattr_l (struct nlmsghdr *n, size_t maxlen, int type, void *data, size_t alen)
paul718e3742002-12-13 20:15:29 +00001336{
Paul Jakma7aa9dce2014-09-19 14:42:23 +01001337 size_t len;
paul718e3742002-12-13 20:15:29 +00001338 struct rtattr *rta;
1339
paul7021c422003-07-15 12:52:22 +00001340 len = RTA_LENGTH (alen);
paul718e3742002-12-13 20:15:29 +00001341
paul7021c422003-07-15 12:52:22 +00001342 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
paul718e3742002-12-13 20:15:29 +00001343 return -1;
1344
paul7021c422003-07-15 12:52:22 +00001345 rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
paul718e3742002-12-13 20:15:29 +00001346 rta->rta_type = type;
1347 rta->rta_len = len;
paul7021c422003-07-15 12:52:22 +00001348 memcpy (RTA_DATA (rta), data, alen);
paul718e3742002-12-13 20:15:29 +00001349 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1350
1351 return 0;
1352}
1353
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001354int
Paul Jakma6f235412016-04-05 13:21:20 +01001355rta_addattr_l (struct rtattr *rta, size_t maxlen, int type, void *data,
1356 size_t alen)
paul718e3742002-12-13 20:15:29 +00001357{
Paul Jakma6f235412016-04-05 13:21:20 +01001358 size_t len;
paul718e3742002-12-13 20:15:29 +00001359 struct rtattr *subrta;
1360
paul7021c422003-07-15 12:52:22 +00001361 len = RTA_LENGTH (alen);
paul718e3742002-12-13 20:15:29 +00001362
paul7021c422003-07-15 12:52:22 +00001363 if (RTA_ALIGN (rta->rta_len) + len > maxlen)
paul718e3742002-12-13 20:15:29 +00001364 return -1;
1365
paul7021c422003-07-15 12:52:22 +00001366 subrta = (struct rtattr *) (((char *) rta) + RTA_ALIGN (rta->rta_len));
paul718e3742002-12-13 20:15:29 +00001367 subrta->rta_type = type;
1368 subrta->rta_len = len;
paul7021c422003-07-15 12:52:22 +00001369 memcpy (RTA_DATA (subrta), data, alen);
paul718e3742002-12-13 20:15:29 +00001370 rta->rta_len = NLMSG_ALIGN (rta->rta_len) + len;
1371
1372 return 0;
1373}
1374
1375/* Utility function comes from iproute2.
1376 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001377int
Paul Jakma7aa9dce2014-09-19 14:42:23 +01001378addattr32 (struct nlmsghdr *n, size_t maxlen, int type, int data)
paul718e3742002-12-13 20:15:29 +00001379{
Paul Jakma7aa9dce2014-09-19 14:42:23 +01001380 size_t len;
paul718e3742002-12-13 20:15:29 +00001381 struct rtattr *rta;
paul7021c422003-07-15 12:52:22 +00001382
1383 len = RTA_LENGTH (4);
1384
paul718e3742002-12-13 20:15:29 +00001385 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
1386 return -1;
1387
paul7021c422003-07-15 12:52:22 +00001388 rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
paul718e3742002-12-13 20:15:29 +00001389 rta->rta_type = type;
1390 rta->rta_len = len;
paul7021c422003-07-15 12:52:22 +00001391 memcpy (RTA_DATA (rta), &data, 4);
paul718e3742002-12-13 20:15:29 +00001392 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1393
1394 return 0;
1395}
1396
1397static int
Feng Lu758fb8f2014-07-03 18:23:09 +08001398netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h,
1399 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001400{
Feng Lu758fb8f2014-07-03 18:23:09 +08001401 zlog_warn ("netlink_talk: ignoring message type 0x%04x vrf %u", h->nlmsg_type,
1402 vrf_id);
paul718e3742002-12-13 20:15:29 +00001403 return 0;
1404}
1405
1406/* sendmsg() to netlink socket then recvmsg(). */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001407static int
Feng Lu758fb8f2014-07-03 18:23:09 +08001408netlink_talk (struct nlmsghdr *n, struct nlsock *nl, struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001409{
1410 int status;
1411 struct sockaddr_nl snl;
Timo Teräsc299ed72014-07-29 09:41:55 +00001412 struct iovec iov = {
1413 .iov_base = (void *) n,
1414 .iov_len = n->nlmsg_len
1415 };
1416 struct msghdr msg = {
1417 .msg_name = (void *) &snl,
1418 .msg_namelen = sizeof snl,
1419 .msg_iov = &iov,
1420 .msg_iovlen = 1,
1421 };
ajs4be019d2005-01-29 16:12:41 +00001422 int save_errno;
paul7021c422003-07-15 12:52:22 +00001423
paul718e3742002-12-13 20:15:29 +00001424 memset (&snl, 0, sizeof snl);
1425 snl.nl_family = AF_NETLINK;
paul7021c422003-07-15 12:52:22 +00001426
hassob7ed1ec2005-03-31 20:13:49 +00001427 n->nlmsg_seq = ++nl->seq;
paul718e3742002-12-13 20:15:29 +00001428
1429 /* Request an acknowledgement by setting NLM_F_ACK */
1430 n->nlmsg_flags |= NLM_F_ACK;
paul7021c422003-07-15 12:52:22 +00001431
1432 if (IS_ZEBRA_DEBUG_KERNEL)
hassob7ed1ec2005-03-31 20:13:49 +00001433 zlog_debug ("netlink_talk: %s type %s(%u), seq=%u", nl->name,
paul7021c422003-07-15 12:52:22 +00001434 lookup (nlmsg_str, n->nlmsg_type), n->nlmsg_type,
1435 n->nlmsg_seq);
paul718e3742002-12-13 20:15:29 +00001436
1437 /* Send message to netlink interface. */
paul7021c422003-07-15 12:52:22 +00001438 if (zserv_privs.change (ZPRIVS_RAISE))
1439 zlog (NULL, LOG_ERR, "Can't raise privileges");
paul718e3742002-12-13 20:15:29 +00001440 status = sendmsg (nl->sock, &msg, 0);
ajs4be019d2005-01-29 16:12:41 +00001441 save_errno = errno;
paul7021c422003-07-15 12:52:22 +00001442 if (zserv_privs.change (ZPRIVS_LOWER))
1443 zlog (NULL, LOG_ERR, "Can't lower privileges");
1444
paul718e3742002-12-13 20:15:29 +00001445 if (status < 0)
1446 {
1447 zlog (NULL, LOG_ERR, "netlink_talk sendmsg() error: %s",
ajs4be019d2005-01-29 16:12:41 +00001448 safe_strerror (save_errno));
paul718e3742002-12-13 20:15:29 +00001449 return -1;
1450 }
paul7021c422003-07-15 12:52:22 +00001451
paul718e3742002-12-13 20:15:29 +00001452
1453 /*
1454 * Get reply from netlink socket.
1455 * The reply should either be an acknowlegement or an error.
1456 */
Feng Lu758fb8f2014-07-03 18:23:09 +08001457 return netlink_parse_info (netlink_talk_filter, nl, zvrf);
paul718e3742002-12-13 20:15:29 +00001458}
1459
Christian Frankefa713d92013-07-05 15:35:37 +00001460/* This function takes a nexthop as argument and adds
1461 * the appropriate netlink attributes to an existing
1462 * netlink message.
1463 *
1464 * @param routedesc: Human readable description of route type
1465 * (direct/recursive, single-/multipath)
1466 * @param bytelen: Length of addresses in bytes.
1467 * @param nexthop: Nexthop information
1468 * @param nlmsg: nlmsghdr structure to fill in.
1469 * @param req_size: The size allocated for the message.
1470 */
1471static void
1472_netlink_route_build_singlepath(
1473 const char *routedesc,
1474 int bytelen,
1475 struct nexthop *nexthop,
1476 struct nlmsghdr *nlmsg,
Christian Frankee8d3d292013-07-05 15:35:39 +00001477 struct rtmsg *rtmsg,
Christian Frankefa713d92013-07-05 15:35:37 +00001478 size_t req_size)
1479{
Christian Frankee8d3d292013-07-05 15:35:39 +00001480 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
1481 rtmsg->rtm_flags |= RTNH_F_ONLINK;
Christian Frankefa713d92013-07-05 15:35:37 +00001482 if (nexthop->type == NEXTHOP_TYPE_IPV4
1483 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1484 {
1485 addattr_l (nlmsg, req_size, RTA_GATEWAY,
1486 &nexthop->gate.ipv4, bytelen);
1487 if (nexthop->src.ipv4.s_addr)
1488 addattr_l (nlmsg, req_size, RTA_PREFSRC,
1489 &nexthop->src.ipv4, bytelen);
1490
1491 if (IS_ZEBRA_DEBUG_KERNEL)
1492 zlog_debug("netlink_route_multipath() (%s): "
1493 "nexthop via %s if %u",
1494 routedesc,
1495 inet_ntoa (nexthop->gate.ipv4),
1496 nexthop->ifindex);
1497 }
1498#ifdef HAVE_IPV6
1499 if (nexthop->type == NEXTHOP_TYPE_IPV6
1500 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1501 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1502 {
1503 addattr_l (nlmsg, req_size, RTA_GATEWAY,
1504 &nexthop->gate.ipv6, bytelen);
1505
1506 if (IS_ZEBRA_DEBUG_KERNEL)
1507 zlog_debug("netlink_route_multipath() (%s): "
1508 "nexthop via %s if %u",
1509 routedesc,
1510 inet6_ntoa (nexthop->gate.ipv6),
1511 nexthop->ifindex);
1512 }
1513#endif /* HAVE_IPV6 */
1514 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1515 || nexthop->type == NEXTHOP_TYPE_IFNAME
1516 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1517 {
1518 addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
1519
1520 if (nexthop->src.ipv4.s_addr)
1521 addattr_l (nlmsg, req_size, RTA_PREFSRC,
1522 &nexthop->src.ipv4, bytelen);
1523
1524 if (IS_ZEBRA_DEBUG_KERNEL)
1525 zlog_debug("netlink_route_multipath() (%s): "
1526 "nexthop via if %u", routedesc, nexthop->ifindex);
1527 }
1528
1529 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
1530 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
1531 {
1532 addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
1533
1534 if (IS_ZEBRA_DEBUG_KERNEL)
1535 zlog_debug("netlink_route_multipath() (%s): "
1536 "nexthop via if %u", routedesc, nexthop->ifindex);
1537 }
1538}
1539
1540/* This function takes a nexthop as argument and
1541 * appends to the given rtattr/rtnexthop pair the
1542 * representation of the nexthop. If the nexthop
1543 * defines a preferred source, the src parameter
1544 * will be modified to point to that src, otherwise
1545 * it will be kept unmodified.
1546 *
1547 * @param routedesc: Human readable description of route type
1548 * (direct/recursive, single-/multipath)
1549 * @param bytelen: Length of addresses in bytes.
1550 * @param nexthop: Nexthop information
1551 * @param rta: rtnetlink attribute structure
1552 * @param rtnh: pointer to an rtnetlink nexthop structure
1553 * @param src: pointer pointing to a location where
1554 * the prefsrc should be stored.
1555 */
1556static void
1557_netlink_route_build_multipath(
1558 const char *routedesc,
1559 int bytelen,
1560 struct nexthop *nexthop,
1561 struct rtattr *rta,
1562 struct rtnexthop *rtnh,
1563 union g_addr **src
1564 )
1565{
1566 rtnh->rtnh_len = sizeof (*rtnh);
1567 rtnh->rtnh_flags = 0;
1568 rtnh->rtnh_hops = 0;
1569 rta->rta_len += rtnh->rtnh_len;
1570
Christian Frankee8d3d292013-07-05 15:35:39 +00001571 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
1572 rtnh->rtnh_flags |= RTNH_F_ONLINK;
1573
Christian Frankefa713d92013-07-05 15:35:37 +00001574 if (nexthop->type == NEXTHOP_TYPE_IPV4
1575 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1576 {
1577 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
1578 &nexthop->gate.ipv4, bytelen);
Lu Feng621e2aa2014-07-11 07:52:15 +00001579 rtnh->rtnh_len += sizeof (struct rtattr) + bytelen;
Christian Frankefa713d92013-07-05 15:35:37 +00001580
1581 if (nexthop->src.ipv4.s_addr)
1582 *src = &nexthop->src;
1583
1584 if (IS_ZEBRA_DEBUG_KERNEL)
1585 zlog_debug("netlink_route_multipath() (%s): "
1586 "nexthop via %s if %u",
1587 routedesc,
1588 inet_ntoa (nexthop->gate.ipv4),
1589 nexthop->ifindex);
1590 }
1591#ifdef HAVE_IPV6
1592 if (nexthop->type == NEXTHOP_TYPE_IPV6
1593 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1594 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1595 {
1596 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
1597 &nexthop->gate.ipv6, bytelen);
Lu Feng621e2aa2014-07-11 07:52:15 +00001598 rtnh->rtnh_len += sizeof (struct rtattr) + bytelen;
Christian Frankefa713d92013-07-05 15:35:37 +00001599
1600 if (IS_ZEBRA_DEBUG_KERNEL)
1601 zlog_debug("netlink_route_multipath() (%s): "
1602 "nexthop via %s if %u",
1603 routedesc,
1604 inet6_ntoa (nexthop->gate.ipv6),
1605 nexthop->ifindex);
1606 }
1607#endif /* HAVE_IPV6 */
1608 /* ifindex */
1609 if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1610 || nexthop->type == NEXTHOP_TYPE_IFINDEX
1611 || nexthop->type == NEXTHOP_TYPE_IFNAME)
1612 {
1613 rtnh->rtnh_ifindex = nexthop->ifindex;
1614 if (nexthop->src.ipv4.s_addr)
1615 *src = &nexthop->src;
1616 if (IS_ZEBRA_DEBUG_KERNEL)
1617 zlog_debug("netlink_route_multipath() (%s): "
1618 "nexthop via if %u", routedesc, nexthop->ifindex);
1619 }
1620 else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1621 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1622 {
1623 rtnh->rtnh_ifindex = nexthop->ifindex;
1624
1625 if (IS_ZEBRA_DEBUG_KERNEL)
1626 zlog_debug("netlink_route_multipath() (%s): "
1627 "nexthop via if %u", routedesc, nexthop->ifindex);
1628 }
1629 else
1630 {
1631 rtnh->rtnh_ifindex = 0;
1632 }
1633}
1634
1635/* Log debug information for netlink_route_multipath
1636 * if debug logging is enabled.
1637 *
1638 * @param cmd: Netlink command which is to be processed
1639 * @param p: Prefix for which the change is due
1640 * @param nexthop: Nexthop which is currently processed
1641 * @param routedesc: Semantic annotation for nexthop
1642 * (recursive, multipath, etc.)
1643 * @param family: Address family which the change concerns
1644 */
1645static void
1646_netlink_route_debug(
1647 int cmd,
1648 struct prefix *p,
1649 struct nexthop *nexthop,
1650 const char *routedesc,
Feng Lu758fb8f2014-07-03 18:23:09 +08001651 int family,
1652 struct zebra_vrf *zvrf)
Christian Frankefa713d92013-07-05 15:35:37 +00001653{
1654 if (IS_ZEBRA_DEBUG_KERNEL)
1655 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001656 char buf[PREFIX_STRLEN];
Feng Lu758fb8f2014-07-03 18:23:09 +08001657 zlog_debug ("netlink_route_multipath() (%s): %s %s vrf %u type %s",
Christian Frankefa713d92013-07-05 15:35:37 +00001658 routedesc,
1659 lookup (nlmsg_str, cmd),
Timo Teräsbe6335d2015-05-23 11:08:41 +03001660 prefix2str (p, buf, sizeof(buf)),
Kaloyan Kovachev8c56b442015-06-15 17:08:48 +03001661 zvrf->vrf_id,
Timo Teräsbe6335d2015-05-23 11:08:41 +03001662 nexthop_type_to_str (nexthop->type));
Christian Frankefa713d92013-07-05 15:35:37 +00001663 }
1664}
1665
paul718e3742002-12-13 20:15:29 +00001666/* Routing table change via netlink interface. */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001667static int
Timo Teräs0abf6792016-01-15 17:36:29 +02001668netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001669{
1670 int bytelen;
1671 struct sockaddr_nl snl;
Christian Frankefa713d92013-07-05 15:35:37 +00001672 struct nexthop *nexthop = NULL, *tnexthop;
1673 int recursing;
1674 int nexthop_num;
paul718e3742002-12-13 20:15:29 +00001675 int discard;
Timo Teräs0abf6792016-01-15 17:36:29 +02001676 int family = PREFIX_FAMILY(p);
Christian Frankefa713d92013-07-05 15:35:37 +00001677 const char *routedesc;
paul718e3742002-12-13 20:15:29 +00001678
paul7021c422003-07-15 12:52:22 +00001679 struct
paul718e3742002-12-13 20:15:29 +00001680 {
1681 struct nlmsghdr n;
1682 struct rtmsg r;
JR Rivers3cadc0c2012-04-01 12:16:31 -07001683 char buf[NL_PKT_BUF_SIZE];
paul718e3742002-12-13 20:15:29 +00001684 } req;
1685
Feng Lu758fb8f2014-07-03 18:23:09 +08001686 struct zebra_vrf *zvrf = vrf_info_lookup (rib->vrf_id);
1687
Jorge Boncompte [DTI2]a4c06de2012-04-20 14:28:40 +02001688 memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
paul718e3742002-12-13 20:15:29 +00001689
1690 bytelen = (family == AF_INET ? 4 : 16);
1691
1692 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
Timo Teräs0abf6792016-01-15 17:36:29 +02001693 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REPLACE | NLM_F_REQUEST;
paul718e3742002-12-13 20:15:29 +00001694 req.n.nlmsg_type = cmd;
1695 req.r.rtm_family = family;
1696 req.r.rtm_table = rib->table;
1697 req.r.rtm_dst_len = p->prefixlen;
Timo Teräs40da2212008-08-13 17:37:14 +01001698 req.r.rtm_protocol = RTPROT_ZEBRA;
Timo Teräs82a66352016-01-15 17:36:30 +02001699 req.r.rtm_scope = RT_SCOPE_LINK;
paul718e3742002-12-13 20:15:29 +00001700
paul7021c422003-07-15 12:52:22 +00001701 if ((rib->flags & ZEBRA_FLAG_BLACKHOLE) || (rib->flags & ZEBRA_FLAG_REJECT))
paul718e3742002-12-13 20:15:29 +00001702 discard = 1;
1703 else
1704 discard = 0;
1705
paul7021c422003-07-15 12:52:22 +00001706 if (cmd == RTM_NEWROUTE)
paul718e3742002-12-13 20:15:29 +00001707 {
paul7021c422003-07-15 12:52:22 +00001708 if (discard)
paul595db7f2003-05-25 21:35:06 +00001709 {
1710 if (rib->flags & ZEBRA_FLAG_BLACKHOLE)
1711 req.r.rtm_type = RTN_BLACKHOLE;
1712 else if (rib->flags & ZEBRA_FLAG_REJECT)
1713 req.r.rtm_type = RTN_UNREACHABLE;
paul7021c422003-07-15 12:52:22 +00001714 else
1715 assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
1716 }
paul595db7f2003-05-25 21:35:06 +00001717 else
paul7021c422003-07-15 12:52:22 +00001718 req.r.rtm_type = RTN_UNICAST;
paul718e3742002-12-13 20:15:29 +00001719 }
1720
1721 addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
1722
1723 /* Metric. */
Timo Teräs4d3ae712016-01-15 17:36:32 +02001724 addattr32 (&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC);
paul718e3742002-12-13 20:15:29 +00001725
Timo Teräsb11f3b52015-11-02 16:50:07 +02001726 if (rib->mtu || rib->nexthop_mtu)
1727 {
1728 char buf[NL_PKT_BUF_SIZE];
1729 struct rtattr *rta = (void *) buf;
1730 u_int32_t mtu = rib->mtu;
1731 if (!mtu || (rib->nexthop_mtu && rib->nexthop_mtu < mtu))
1732 mtu = rib->nexthop_mtu;
1733 rta->rta_type = RTA_METRICS;
1734 rta->rta_len = RTA_LENGTH(0);
1735 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTAX_MTU, &mtu, sizeof mtu);
1736 addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA (rta),
1737 RTA_PAYLOAD (rta));
1738 }
1739
paul718e3742002-12-13 20:15:29 +00001740 if (discard)
1741 {
1742 if (cmd == RTM_NEWROUTE)
Christian Frankefa713d92013-07-05 15:35:37 +00001743 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1744 {
1745 /* We shouldn't encounter recursive nexthops on discard routes,
1746 * but it is probably better to handle that case correctly anyway.
1747 */
1748 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1749 continue;
1750 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1751 }
paul718e3742002-12-13 20:15:29 +00001752 goto skip;
1753 }
1754
Christian Frankefa713d92013-07-05 15:35:37 +00001755 /* Count overall nexthops so we can decide whether to use singlepath
1756 * or multipath case. */
1757 nexthop_num = 0;
1758 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001759 {
Christian Frankefa713d92013-07-05 15:35:37 +00001760 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1761 continue;
1762 if (cmd == RTM_NEWROUTE && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1763 continue;
1764 if (cmd == RTM_DELROUTE && !CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1765 continue;
1766
Timo Teräs82a66352016-01-15 17:36:30 +02001767 if (nexthop->type != NEXTHOP_TYPE_IFINDEX &&
1768 nexthop->type != NEXTHOP_TYPE_IFNAME)
1769 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1770
Christian Frankefa713d92013-07-05 15:35:37 +00001771 nexthop_num++;
1772 }
1773
1774 /* Singlepath case. */
1775 if (nexthop_num == 1 || MULTIPATH_NUM == 1)
1776 {
1777 nexthop_num = 0;
1778 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul7021c422003-07-15 12:52:22 +00001779 {
Christian Frankefa713d92013-07-05 15:35:37 +00001780 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1781 continue;
paul5ec90d22003-06-19 01:41:37 +00001782
paul7021c422003-07-15 12:52:22 +00001783 if ((cmd == RTM_NEWROUTE
1784 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1785 || (cmd == RTM_DELROUTE
1786 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1787 {
Christian Frankefa713d92013-07-05 15:35:37 +00001788 routedesc = recursing ? "recursive, 1 hop" : "single hop";
paul5ec90d22003-06-19 01:41:37 +00001789
Feng Lu758fb8f2014-07-03 18:23:09 +08001790 _netlink_route_debug(cmd, p, nexthop, routedesc, family, zvrf);
Christian Frankefa713d92013-07-05 15:35:37 +00001791 _netlink_route_build_singlepath(routedesc, bytelen,
Christian Frankee8d3d292013-07-05 15:35:39 +00001792 nexthop, &req.n, &req.r,
1793 sizeof req);
paul718e3742002-12-13 20:15:29 +00001794
paul7021c422003-07-15 12:52:22 +00001795 if (cmd == RTM_NEWROUTE)
1796 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
paul718e3742002-12-13 20:15:29 +00001797
paul7021c422003-07-15 12:52:22 +00001798 nexthop_num++;
1799 break;
1800 }
1801 }
paul718e3742002-12-13 20:15:29 +00001802 }
1803 else
1804 {
JR Rivers3cadc0c2012-04-01 12:16:31 -07001805 char buf[NL_PKT_BUF_SIZE];
paul718e3742002-12-13 20:15:29 +00001806 struct rtattr *rta = (void *) buf;
1807 struct rtnexthop *rtnh;
Paul Jakma7514fb72007-05-02 16:05:35 +00001808 union g_addr *src = NULL;
paul718e3742002-12-13 20:15:29 +00001809
1810 rta->rta_type = RTA_MULTIPATH;
paul7021c422003-07-15 12:52:22 +00001811 rta->rta_len = RTA_LENGTH (0);
1812 rtnh = RTA_DATA (rta);
paul718e3742002-12-13 20:15:29 +00001813
1814 nexthop_num = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001815 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul7021c422003-07-15 12:52:22 +00001816 {
Donald Sharp91ce87a2015-12-09 08:24:45 -05001817 if (nexthop_num >= MULTIPATH_NUM)
Christian Frankefa713d92013-07-05 15:35:37 +00001818 break;
1819
1820 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1821 continue;
1822
paul7021c422003-07-15 12:52:22 +00001823 if ((cmd == RTM_NEWROUTE
1824 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1825 || (cmd == RTM_DELROUTE
1826 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1827 {
Christian Frankefa713d92013-07-05 15:35:37 +00001828 routedesc = recursing ? "recursive, multihop" : "multihop";
paul7021c422003-07-15 12:52:22 +00001829 nexthop_num++;
paul718e3742002-12-13 20:15:29 +00001830
Christian Frankefa713d92013-07-05 15:35:37 +00001831 _netlink_route_debug(cmd, p, nexthop,
Feng Lu758fb8f2014-07-03 18:23:09 +08001832 routedesc, family, zvrf);
Christian Frankefa713d92013-07-05 15:35:37 +00001833 _netlink_route_build_multipath(routedesc, bytelen,
1834 nexthop, rta, rtnh, &src);
paul7021c422003-07-15 12:52:22 +00001835 rtnh = RTNH_NEXT (rtnh);
paul718e3742002-12-13 20:15:29 +00001836
paul7021c422003-07-15 12:52:22 +00001837 if (cmd == RTM_NEWROUTE)
1838 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1839 }
1840 }
Paul Jakma7514fb72007-05-02 16:05:35 +00001841 if (src)
1842 addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src->ipv4, bytelen);
paul718e3742002-12-13 20:15:29 +00001843
1844 if (rta->rta_len > RTA_LENGTH (0))
JR Rivers3cadc0c2012-04-01 12:16:31 -07001845 addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta),
paul7021c422003-07-15 12:52:22 +00001846 RTA_PAYLOAD (rta));
paul718e3742002-12-13 20:15:29 +00001847 }
1848
1849 /* If there is no useful nexthop then return. */
1850 if (nexthop_num == 0)
1851 {
1852 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +00001853 zlog_debug ("netlink_route_multipath(): No useful nexthop.");
paul718e3742002-12-13 20:15:29 +00001854 return 0;
1855 }
1856
paul7021c422003-07-15 12:52:22 +00001857skip:
paul718e3742002-12-13 20:15:29 +00001858
1859 /* Destination netlink address. */
1860 memset (&snl, 0, sizeof snl);
1861 snl.nl_family = AF_NETLINK;
1862
paul718e3742002-12-13 20:15:29 +00001863 /* Talk to netlink socket. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001864 return netlink_talk (&req.n, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001865}
1866
1867int
Timo Teräs0abf6792016-01-15 17:36:29 +02001868kernel_route_rib (struct prefix *p, struct rib *old, struct rib *new)
paul718e3742002-12-13 20:15:29 +00001869{
Timo Teräs0abf6792016-01-15 17:36:29 +02001870 if (!old && new)
1871 return netlink_route_multipath (RTM_NEWROUTE, p, new);
1872 if (old && !new)
1873 return netlink_route_multipath (RTM_DELROUTE, p, old);
paul718e3742002-12-13 20:15:29 +00001874
Timo Teräs4d3ae712016-01-15 17:36:32 +02001875 /* Replace, can be done atomically if metric does not change;
1876 * netlink uses [prefix, tos, priority] to identify prefix.
1877 * Now metric is not sent to kernel, so we can just do atomic replace. */
1878 return netlink_route_multipath (RTM_NEWROUTE, p, new);
paul718e3742002-12-13 20:15:29 +00001879}
David Lamparter6b0655a2014-06-04 06:53:35 +02001880
paul718e3742002-12-13 20:15:29 +00001881/* Interface address modification. */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001882static int
paul718e3742002-12-13 20:15:29 +00001883netlink_address (int cmd, int family, struct interface *ifp,
paul7021c422003-07-15 12:52:22 +00001884 struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001885{
1886 int bytelen;
1887 struct prefix *p;
1888
paul7021c422003-07-15 12:52:22 +00001889 struct
paul718e3742002-12-13 20:15:29 +00001890 {
1891 struct nlmsghdr n;
1892 struct ifaddrmsg ifa;
JR Rivers3cadc0c2012-04-01 12:16:31 -07001893 char buf[NL_PKT_BUF_SIZE];
paul718e3742002-12-13 20:15:29 +00001894 } req;
1895
Feng Lu758fb8f2014-07-03 18:23:09 +08001896 struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
1897
paul718e3742002-12-13 20:15:29 +00001898 p = ifc->address;
Jorge Boncompte [DTI2]a4c06de2012-04-20 14:28:40 +02001899 memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
paul718e3742002-12-13 20:15:29 +00001900
1901 bytelen = (family == AF_INET ? 4 : 16);
1902
paul7021c422003-07-15 12:52:22 +00001903 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg));
paul718e3742002-12-13 20:15:29 +00001904 req.n.nlmsg_flags = NLM_F_REQUEST;
1905 req.n.nlmsg_type = cmd;
1906 req.ifa.ifa_family = family;
1907
1908 req.ifa.ifa_index = ifp->ifindex;
1909 req.ifa.ifa_prefixlen = p->prefixlen;
1910
1911 addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen);
1912
1913 if (family == AF_INET && cmd == RTM_NEWADDR)
1914 {
Andrew J. Schorre4529632006-12-12 19:18:21 +00001915 if (!CONNECTED_PEER(ifc) && ifc->destination)
paul7021c422003-07-15 12:52:22 +00001916 {
1917 p = ifc->destination;
1918 addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix,
1919 bytelen);
1920 }
paul718e3742002-12-13 20:15:29 +00001921 }
1922
1923 if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
1924 SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY);
paul7021c422003-07-15 12:52:22 +00001925
paul718e3742002-12-13 20:15:29 +00001926 if (ifc->label)
1927 addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label,
paul7021c422003-07-15 12:52:22 +00001928 strlen (ifc->label) + 1);
paul718e3742002-12-13 20:15:29 +00001929
Feng Lu758fb8f2014-07-03 18:23:09 +08001930 return netlink_talk (&req.n, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001931}
1932
1933int
1934kernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc)
1935{
1936 return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc);
1937}
1938
1939int
1940kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc)
1941{
1942 return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc);
1943}
1944
paul718e3742002-12-13 20:15:29 +00001945
1946extern struct thread_master *master;
1947
1948/* Kernel route reflection. */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001949static int
paul718e3742002-12-13 20:15:29 +00001950kernel_read (struct thread *thread)
1951{
Feng Lu758fb8f2014-07-03 18:23:09 +08001952 struct zebra_vrf *zvrf = (struct zebra_vrf *)THREAD_ARG (thread);
1953 netlink_parse_info (netlink_information_fetch, &zvrf->netlink, zvrf);
1954 zvrf->t_netlink = thread_add_read (zebrad.master, kernel_read, zvrf,
1955 zvrf->netlink.sock);
paul718e3742002-12-13 20:15:29 +00001956
1957 return 0;
1958}
1959
Stephen Hemminger3d265b42008-08-16 17:30:39 +01001960/* Filter out messages from self that occur on listener socket,
1961 caused by our actions on the command socket
1962 */
1963static void netlink_install_filter (int sock, __u32 pid)
Paul Jakma768a27e2008-05-29 18:23:08 +00001964{
Paul Jakma768a27e2008-05-29 18:23:08 +00001965 struct sock_filter filter[] = {
Stephen Hemminger3d265b42008-08-16 17:30:39 +01001966 /* 0: ldh [4] */
1967 BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)),
1968 /* 1: jeq 0x18 jt 3 jf 6 */
1969 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 1, 0),
1970 /* 2: jeq 0x19 jt 3 jf 6 */
1971 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 0, 3),
1972 /* 3: ldw [12] */
1973 BPF_STMT(BPF_LD|BPF_ABS|BPF_W, offsetof(struct nlmsghdr, nlmsg_pid)),
1974 /* 4: jeq XX jt 5 jf 6 */
1975 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htonl(pid), 0, 1),
1976 /* 5: ret 0 (skip) */
1977 BPF_STMT(BPF_RET|BPF_K, 0),
1978 /* 6: ret 0xffff (keep) */
1979 BPF_STMT(BPF_RET|BPF_K, 0xffff),
Paul Jakma768a27e2008-05-29 18:23:08 +00001980 };
1981
1982 struct sock_fprog prog = {
Balaji.G837d16c2012-09-26 14:09:10 +05301983 .len = array_size(filter),
Paul Jakma768a27e2008-05-29 18:23:08 +00001984 .filter = filter,
1985 };
1986
1987 if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)) < 0)
1988 zlog_warn ("Can't install socket filter: %s\n", safe_strerror(errno));
1989}
1990
paul718e3742002-12-13 20:15:29 +00001991/* Exported interface function. This function simply calls
1992 netlink_socket (). */
1993void
Feng Lu758fb8f2014-07-03 18:23:09 +08001994kernel_init (struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001995{
1996 unsigned long groups;
1997
paul7021c422003-07-15 12:52:22 +00001998 groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR;
paul718e3742002-12-13 20:15:29 +00001999#ifdef HAVE_IPV6
paul7021c422003-07-15 12:52:22 +00002000 groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR;
paul718e3742002-12-13 20:15:29 +00002001#endif /* HAVE_IPV6 */
Feng Lu758fb8f2014-07-03 18:23:09 +08002002 netlink_socket (&zvrf->netlink, groups, zvrf->vrf_id);
2003 netlink_socket (&zvrf->netlink_cmd, 0, zvrf->vrf_id);
paul718e3742002-12-13 20:15:29 +00002004
2005 /* Register kernel socket. */
Feng Lu758fb8f2014-07-03 18:23:09 +08002006 if (zvrf->netlink.sock > 0)
Paul Jakma768a27e2008-05-29 18:23:08 +00002007 {
Stephen Hemminger4cde9312008-08-16 17:51:27 +01002008 /* Only want non-blocking on the netlink event socket */
Feng Lu758fb8f2014-07-03 18:23:09 +08002009 if (fcntl (zvrf->netlink.sock, F_SETFL, O_NONBLOCK) < 0)
2010 zlog_err ("Can't set %s socket flags: %s", zvrf->netlink.name,
2011 safe_strerror (errno));
Stephen Hemminger4cde9312008-08-16 17:51:27 +01002012
Stephen Hemminger30afea32008-08-16 18:25:47 +01002013 /* Set receive buffer size if it's set from command line */
2014 if (nl_rcvbufsize)
Feng Lu758fb8f2014-07-03 18:23:09 +08002015 netlink_recvbuf (&zvrf->netlink, nl_rcvbufsize);
Stephen Hemminger30afea32008-08-16 18:25:47 +01002016
Feng Lu758fb8f2014-07-03 18:23:09 +08002017 netlink_install_filter (zvrf->netlink.sock, zvrf->netlink_cmd.snl.nl_pid);
2018 zvrf->t_netlink = thread_add_read (zebrad.master, kernel_read, zvrf,
2019 zvrf->netlink.sock);
2020 }
2021}
2022
2023void
2024kernel_terminate (struct zebra_vrf *zvrf)
2025{
2026 THREAD_READ_OFF (zvrf->t_netlink);
2027
2028 if (zvrf->netlink.sock >= 0)
2029 {
2030 close (zvrf->netlink.sock);
2031 zvrf->netlink.sock = -1;
2032 }
2033
2034 if (zvrf->netlink_cmd.sock >= 0)
2035 {
2036 close (zvrf->netlink_cmd.sock);
2037 zvrf->netlink_cmd.sock = -1;
Paul Jakma768a27e2008-05-29 18:23:08 +00002038 }
paul718e3742002-12-13 20:15:29 +00002039}
Avneesh Sachdev78deec42012-11-13 22:48:56 +00002040
2041/*
2042 * nl_msg_type_to_str
2043 */
2044const char *
2045nl_msg_type_to_str (uint16_t msg_type)
2046{
2047 return lookup (nlmsg_str, msg_type);
2048}
2049
2050/*
2051 * nl_rtproto_to_str
2052 */
2053const char *
2054nl_rtproto_to_str (u_char rtproto)
2055{
2056 return lookup (rtproto_str, rtproto);
2057}