blob: 105e5593851dd5a27ac4ab1b98143999893851bd [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];
911
912 char anyaddr[16] = { 0 };
paul718e3742002-12-13 20:15:29 +0000913
914 int index;
915 int table;
Timo Teräsb11f3b52015-11-02 16:50:07 +0200916 u_int32_t mtu = 0;
Dmitry Popov83d16142011-09-11 13:48:25 +0400917
paul718e3742002-12-13 20:15:29 +0000918 void *dest;
919 void *gate;
Paul Jakma7514fb72007-05-02 16:05:35 +0000920 void *src;
paul718e3742002-12-13 20:15:29 +0000921
922 rtm = NLMSG_DATA (h);
923
paul7021c422003-07-15 12:52:22 +0000924 if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
paul718e3742002-12-13 20:15:29 +0000925 {
926 /* If this is not route add/delete message print warning. */
Feng Lu758fb8f2014-07-03 18:23:09 +0800927 zlog_warn ("Kernel message: %d vrf %u\n", h->nlmsg_type, vrf_id);
paul718e3742002-12-13 20:15:29 +0000928 return 0;
929 }
930
931 /* Connected route. */
932 if (IS_ZEBRA_DEBUG_KERNEL)
Feng Lu758fb8f2014-07-03 18:23:09 +0800933 zlog_debug ("%s %s %s proto %s vrf %u",
paul7021c422003-07-15 12:52:22 +0000934 h->nlmsg_type ==
935 RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
936 rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",
937 rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast",
Feng Lu758fb8f2014-07-03 18:23:09 +0800938 lookup (rtproto_str, rtm->rtm_protocol),
939 vrf_id);
paul718e3742002-12-13 20:15:29 +0000940
941 if (rtm->rtm_type != RTN_UNICAST)
942 {
943 return 0;
944 }
945
946 table = rtm->rtm_table;
paulb21b19c2003-06-15 01:28:29 +0000947 if (table != RT_TABLE_MAIN && table != zebrad.rtm_table_default)
paul718e3742002-12-13 20:15:29 +0000948 {
949 return 0;
950 }
951
paul7021c422003-07-15 12:52:22 +0000952 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
paul718e3742002-12-13 20:15:29 +0000953 if (len < 0)
954 return -1;
955
956 memset (tb, 0, sizeof tb);
957 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
958
959 if (rtm->rtm_flags & RTM_F_CLONED)
960 return 0;
961 if (rtm->rtm_protocol == RTPROT_REDIRECT)
962 return 0;
963 if (rtm->rtm_protocol == RTPROT_KERNEL)
964 return 0;
965
966 if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)
967 return 0;
968
969 if (rtm->rtm_src_len != 0)
970 {
Feng Lu758fb8f2014-07-03 18:23:09 +0800971 zlog_warn ("netlink_route_change(): no src len, vrf %u", vrf_id);
paul718e3742002-12-13 20:15:29 +0000972 return 0;
973 }
paul7021c422003-07-15 12:52:22 +0000974
paul718e3742002-12-13 20:15:29 +0000975 index = 0;
976 dest = NULL;
977 gate = NULL;
Paul Jakma7514fb72007-05-02 16:05:35 +0000978 src = NULL;
paul718e3742002-12-13 20:15:29 +0000979
980 if (tb[RTA_OIF])
981 index = *(int *) RTA_DATA (tb[RTA_OIF]);
982
983 if (tb[RTA_DST])
984 dest = RTA_DATA (tb[RTA_DST]);
985 else
986 dest = anyaddr;
987
988 if (tb[RTA_GATEWAY])
989 gate = RTA_DATA (tb[RTA_GATEWAY]);
990
Paul Jakma7514fb72007-05-02 16:05:35 +0000991 if (tb[RTA_PREFSRC])
992 src = RTA_DATA (tb[RTA_PREFSRC]);
993
Timo Teräsb11f3b52015-11-02 16:50:07 +0200994 if (h->nlmsg_type == RTM_NEWROUTE)
995 {
Timo Teräsb11f3b52015-11-02 16:50:07 +0200996 if (tb[RTA_METRICS])
997 {
998 struct rtattr *mxrta[RTAX_MAX+1];
999
1000 memset (mxrta, 0, sizeof mxrta);
1001 netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),
1002 RTA_PAYLOAD(tb[RTA_METRICS]));
1003
1004 if (mxrta[RTAX_MTU])
1005 mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]);
1006 }
1007 }
Josh Bailey26e2ae32012-03-22 01:09:21 -07001008
paul718e3742002-12-13 20:15:29 +00001009 if (rtm->rtm_family == AF_INET)
1010 {
1011 struct prefix_ipv4 p;
1012 p.family = AF_INET;
1013 memcpy (&p.prefix, dest, 4);
1014 p.prefixlen = rtm->rtm_dst_len;
1015
1016 if (IS_ZEBRA_DEBUG_KERNEL)
paul7021c422003-07-15 12:52:22 +00001017 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001018 char buf[PREFIX_STRLEN];
Feng Lu758fb8f2014-07-03 18:23:09 +08001019 zlog_debug ("%s %s vrf %u",
Timo Teräsbe6335d2015-05-23 11:08:41 +03001020 h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
Feng Lu758fb8f2014-07-03 18:23:09 +08001021 prefix2str (&p, buf, sizeof(buf)), vrf_id);
paul7021c422003-07-15 12:52:22 +00001022 }
paul718e3742002-12-13 20:15:29 +00001023
1024 if (h->nlmsg_type == RTM_NEWROUTE)
Josh Bailey26e2ae32012-03-22 01:09:21 -07001025 {
1026 if (!tb[RTA_MULTIPATH])
Feng Lu758fb8f2014-07-03 18:23:09 +08001027 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, vrf_id,
Timo Teräs4d3ae712016-01-15 17:36:32 +02001028 table, 0, mtu, 0, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -07001029 else
1030 {
1031 /* This is a multipath route */
1032
1033 struct rib *rib;
1034 struct rtnexthop *rtnh =
1035 (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
1036
1037 len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
1038
1039 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1040 rib->type = ZEBRA_ROUTE_KERNEL;
1041 rib->distance = 0;
1042 rib->flags = 0;
Timo Teräs4d3ae712016-01-15 17:36:32 +02001043 rib->metric = 0;
Timo Teräsb11f3b52015-11-02 16:50:07 +02001044 rib->mtu = mtu;
Feng Lu758fb8f2014-07-03 18:23:09 +08001045 rib->vrf_id = vrf_id;
Josh Bailey26e2ae32012-03-22 01:09:21 -07001046 rib->table = table;
1047 rib->nexthop_num = 0;
1048 rib->uptime = time (NULL);
1049
1050 for (;;)
1051 {
1052 if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
1053 break;
1054
Josh Bailey26e2ae32012-03-22 01:09:21 -07001055 index = rtnh->rtnh_ifindex;
1056 gate = 0;
1057 if (rtnh->rtnh_len > sizeof (*rtnh))
1058 {
1059 memset (tb, 0, sizeof (tb));
1060 netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
1061 rtnh->rtnh_len - sizeof (*rtnh));
1062 if (tb[RTA_GATEWAY])
1063 gate = RTA_DATA (tb[RTA_GATEWAY]);
1064 }
1065
1066 if (gate)
1067 {
1068 if (index)
Pradosh Mohapatra60cc9592015-11-09 20:21:41 -05001069 rib_nexthop_ipv4_ifindex_add (rib, gate, src, index);
Josh Bailey26e2ae32012-03-22 01:09:21 -07001070 else
Pradosh Mohapatra60cc9592015-11-09 20:21:41 -05001071 rib_nexthop_ipv4_add (rib, gate, src);
Josh Bailey26e2ae32012-03-22 01:09:21 -07001072 }
1073 else
Pradosh Mohapatra60cc9592015-11-09 20:21:41 -05001074 rib_nexthop_ifindex_add (rib, index);
Josh Bailey26e2ae32012-03-22 01:09:21 -07001075
1076 len -= NLMSG_ALIGN(rtnh->rtnh_len);
1077 rtnh = RTNH_NEXT(rtnh);
1078 }
1079
1080 if (rib->nexthop_num == 0)
1081 XFREE (MTYPE_RIB, rib);
1082 else
Avneesh Sachdev14d2bba2012-04-11 23:51:08 -07001083 rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -07001084 }
1085 }
paul718e3742002-12-13 20:15:29 +00001086 else
Feng Lu758fb8f2014-07-03 18:23:09 +08001087 rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, vrf_id,
Feng Lu0d0686f2015-05-22 11:40:02 +02001088 SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001089 }
1090
1091#ifdef HAVE_IPV6
1092 if (rtm->rtm_family == AF_INET6)
1093 {
1094 struct prefix_ipv6 p;
paul718e3742002-12-13 20:15:29 +00001095
1096 p.family = AF_INET6;
1097 memcpy (&p.prefix, dest, 16);
1098 p.prefixlen = rtm->rtm_dst_len;
1099
1100 if (IS_ZEBRA_DEBUG_KERNEL)
paul7021c422003-07-15 12:52:22 +00001101 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001102 char buf[PREFIX_STRLEN];
Feng Lu758fb8f2014-07-03 18:23:09 +08001103 zlog_debug ("%s %s vrf %u",
Timo Teräsbe6335d2015-05-23 11:08:41 +03001104 h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
Feng Lu758fb8f2014-07-03 18:23:09 +08001105 prefix2str (&p, buf, sizeof(buf)), vrf_id);
paul7021c422003-07-15 12:52:22 +00001106 }
paul718e3742002-12-13 20:15:29 +00001107
1108 if (h->nlmsg_type == RTM_NEWROUTE)
Feng Lu758fb8f2014-07-03 18:23:09 +08001109 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, vrf_id, table,
Timo Teräs4d3ae712016-01-15 17:36:32 +02001110 0, mtu, 0, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001111 else
Feng Lu758fb8f2014-07-03 18:23:09 +08001112 rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, vrf_id,
Feng Lu0d0686f2015-05-22 11:40:02 +02001113 SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001114 }
1115#endif /* HAVE_IPV6 */
1116
1117 return 0;
1118}
1119
Stephen Hemminger6072b242008-08-14 16:52:26 +01001120static int
Feng Lu758fb8f2014-07-03 18:23:09 +08001121netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
1122 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001123{
1124 int len;
1125 struct ifinfomsg *ifi;
paul7021c422003-07-15 12:52:22 +00001126 struct rtattr *tb[IFLA_MAX + 1];
paul718e3742002-12-13 20:15:29 +00001127 struct interface *ifp;
1128 char *name;
1129
1130 ifi = NLMSG_DATA (h);
1131
paul7021c422003-07-15 12:52:22 +00001132 if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
paul718e3742002-12-13 20:15:29 +00001133 {
1134 /* If this is not link add/delete message so print warning. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001135 zlog_warn ("netlink_link_change: wrong kernel message %d vrf %u\n",
1136 h->nlmsg_type, vrf_id);
paul718e3742002-12-13 20:15:29 +00001137 return 0;
1138 }
1139
1140 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
1141 if (len < 0)
1142 return -1;
1143
1144 /* Looking up interface name. */
1145 memset (tb, 0, sizeof tb);
1146 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
paulc15cb242005-01-24 09:05:27 +00001147
paul1e193152005-02-14 23:53:05 +00001148#ifdef IFLA_WIRELESS
paulc15cb242005-01-24 09:05:27 +00001149 /* check for wireless messages to ignore */
1150 if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
1151 {
1152 if (IS_ZEBRA_DEBUG_KERNEL)
Feng Lu758fb8f2014-07-03 18:23:09 +08001153 zlog_debug ("%s: ignoring IFLA_WIRELESS message, vrf %u", __func__,
1154 vrf_id);
paulc15cb242005-01-24 09:05:27 +00001155 return 0;
1156 }
paul1e193152005-02-14 23:53:05 +00001157#endif /* IFLA_WIRELESS */
paulc15cb242005-01-24 09:05:27 +00001158
paul718e3742002-12-13 20:15:29 +00001159 if (tb[IFLA_IFNAME] == NULL)
1160 return -1;
paul7021c422003-07-15 12:52:22 +00001161 name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
paul718e3742002-12-13 20:15:29 +00001162
1163 /* Add interface. */
1164 if (h->nlmsg_type == RTM_NEWLINK)
1165 {
Feng Lu758fb8f2014-07-03 18:23:09 +08001166 ifp = if_lookup_by_name_vrf (name, vrf_id);
paul718e3742002-12-13 20:15:29 +00001167
paul7021c422003-07-15 12:52:22 +00001168 if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1169 {
1170 if (ifp == NULL)
Feng Lu758fb8f2014-07-03 18:23:09 +08001171 ifp = if_get_by_name_vrf (name, vrf_id);
paul718e3742002-12-13 20:15:29 +00001172
ajsd2fc8892005-04-02 18:38:43 +00001173 set_ifindex(ifp, ifi->ifi_index);
paul7021c422003-07-15 12:52:22 +00001174 ifp->flags = ifi->ifi_flags & 0x0000fffff;
paul44145db2004-05-09 11:00:23 +00001175 ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
Brett Cipherydb19c852013-10-03 13:48:54 +00001176 ifp->metric = 0;
paul718e3742002-12-13 20:15:29 +00001177
Josh Bailey26e2ae32012-03-22 01:09:21 -07001178 netlink_interface_update_hw_addr (tb, ifp);
1179
paul7021c422003-07-15 12:52:22 +00001180 /* If new link is added. */
1181 if_add_update (ifp);
1182 }
paul718e3742002-12-13 20:15:29 +00001183 else
paul7021c422003-07-15 12:52:22 +00001184 {
1185 /* Interface status change. */
ajsd2fc8892005-04-02 18:38:43 +00001186 set_ifindex(ifp, ifi->ifi_index);
paul44145db2004-05-09 11:00:23 +00001187 ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
Brett Cipherydb19c852013-10-03 13:48:54 +00001188 ifp->metric = 0;
paul718e3742002-12-13 20:15:29 +00001189
Josh Bailey26e2ae32012-03-22 01:09:21 -07001190 netlink_interface_update_hw_addr (tb, ifp);
1191
paul7021c422003-07-15 12:52:22 +00001192 if (if_is_operative (ifp))
1193 {
1194 ifp->flags = ifi->ifi_flags & 0x0000fffff;
1195 if (!if_is_operative (ifp))
1196 if_down (ifp);
ajsa608bbf2005-03-29 17:03:49 +00001197 else
1198 /* Must notify client daemons of new interface status. */
1199 zebra_interface_up_update (ifp);
paul7021c422003-07-15 12:52:22 +00001200 }
1201 else
1202 {
1203 ifp->flags = ifi->ifi_flags & 0x0000fffff;
1204 if (if_is_operative (ifp))
1205 if_up (ifp);
1206 }
1207 }
paul718e3742002-12-13 20:15:29 +00001208 }
1209 else
1210 {
1211 /* RTM_DELLINK. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001212 ifp = if_lookup_by_name_vrf (name, vrf_id);
paul718e3742002-12-13 20:15:29 +00001213
1214 if (ifp == NULL)
paul7021c422003-07-15 12:52:22 +00001215 {
Feng Lu758fb8f2014-07-03 18:23:09 +08001216 zlog_warn ("interface %s vrf %u is deleted but can't find",
1217 name, vrf_id);
paul7021c422003-07-15 12:52:22 +00001218 return 0;
1219 }
1220
paul718e3742002-12-13 20:15:29 +00001221 if_delete_update (ifp);
1222 }
1223
1224 return 0;
1225}
1226
Stephen Hemminger6072b242008-08-14 16:52:26 +01001227static int
Feng Lu758fb8f2014-07-03 18:23:09 +08001228netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h,
1229 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001230{
Stephen Hemminger3d265b42008-08-16 17:30:39 +01001231 /* JF: Ignore messages that aren't from the kernel */
1232 if ( snl->nl_pid != 0 )
1233 {
1234 zlog ( NULL, LOG_ERR, "Ignoring message from pid %u", snl->nl_pid );
1235 return 0;
1236 }
1237
paul718e3742002-12-13 20:15:29 +00001238 switch (h->nlmsg_type)
1239 {
1240 case RTM_NEWROUTE:
Feng Lu758fb8f2014-07-03 18:23:09 +08001241 return netlink_route_change (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001242 break;
1243 case RTM_DELROUTE:
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_NEWLINK:
Feng Lu758fb8f2014-07-03 18:23:09 +08001247 return netlink_link_change (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001248 break;
1249 case RTM_DELLINK:
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_NEWADDR:
Feng Lu758fb8f2014-07-03 18:23:09 +08001253 return netlink_interface_addr (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001254 break;
1255 case RTM_DELADDR:
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 default:
Feng Lu758fb8f2014-07-03 18:23:09 +08001259 zlog_warn ("Unknown netlink nlmsg_type %d vrf %u\n", h->nlmsg_type,
1260 vrf_id);
paul718e3742002-12-13 20:15:29 +00001261 break;
1262 }
1263 return 0;
1264}
1265
1266/* Interface lookup by netlink socket. */
1267int
Feng Lu758fb8f2014-07-03 18:23:09 +08001268interface_lookup_netlink (struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001269{
1270 int ret;
paul7021c422003-07-15 12:52:22 +00001271
paul718e3742002-12-13 20:15:29 +00001272 /* Get interface information. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001273 ret = netlink_request (AF_PACKET, RTM_GETLINK, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001274 if (ret < 0)
1275 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001276 ret = netlink_parse_info (netlink_interface, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001277 if (ret < 0)
1278 return ret;
1279
1280 /* Get IPv4 address of the interfaces. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001281 ret = netlink_request (AF_INET, RTM_GETADDR, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001282 if (ret < 0)
1283 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001284 ret = netlink_parse_info (netlink_interface_addr, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001285 if (ret < 0)
1286 return ret;
1287
1288#ifdef HAVE_IPV6
1289 /* Get IPv6 address of the interfaces. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001290 ret = netlink_request (AF_INET6, RTM_GETADDR, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001291 if (ret < 0)
1292 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001293 ret = netlink_parse_info (netlink_interface_addr, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001294 if (ret < 0)
1295 return ret;
1296#endif /* HAVE_IPV6 */
1297
1298 return 0;
1299}
1300
1301/* Routing table read function using netlink interface. Only called
1302 bootstrap time. */
1303int
Feng Lu758fb8f2014-07-03 18:23:09 +08001304netlink_route_read (struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001305{
1306 int ret;
paul7021c422003-07-15 12:52:22 +00001307
paul718e3742002-12-13 20:15:29 +00001308 /* Get IPv4 routing table. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001309 ret = netlink_request (AF_INET, RTM_GETROUTE, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001310 if (ret < 0)
1311 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001312 ret = netlink_parse_info (netlink_routing_table, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001313 if (ret < 0)
1314 return ret;
1315
1316#ifdef HAVE_IPV6
1317 /* Get IPv6 routing table. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001318 ret = netlink_request (AF_INET6, RTM_GETROUTE, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001319 if (ret < 0)
1320 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001321 ret = netlink_parse_info (netlink_routing_table, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001322 if (ret < 0)
1323 return ret;
1324#endif /* HAVE_IPV6 */
1325
1326 return 0;
1327}
1328
1329/* Utility function comes from iproute2.
1330 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001331int
Paul Jakma6f235412016-04-05 13:21:20 +01001332addattr_l (struct nlmsghdr *n, size_t maxlen, int type, void *data, size_t alen)
paul718e3742002-12-13 20:15:29 +00001333{
Paul Jakma7aa9dce2014-09-19 14:42:23 +01001334 size_t len;
paul718e3742002-12-13 20:15:29 +00001335 struct rtattr *rta;
1336
paul7021c422003-07-15 12:52:22 +00001337 len = RTA_LENGTH (alen);
paul718e3742002-12-13 20:15:29 +00001338
paul7021c422003-07-15 12:52:22 +00001339 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
paul718e3742002-12-13 20:15:29 +00001340 return -1;
1341
paul7021c422003-07-15 12:52:22 +00001342 rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
paul718e3742002-12-13 20:15:29 +00001343 rta->rta_type = type;
1344 rta->rta_len = len;
paul7021c422003-07-15 12:52:22 +00001345 memcpy (RTA_DATA (rta), data, alen);
paul718e3742002-12-13 20:15:29 +00001346 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1347
1348 return 0;
1349}
1350
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001351int
Paul Jakma6f235412016-04-05 13:21:20 +01001352rta_addattr_l (struct rtattr *rta, size_t maxlen, int type, void *data,
1353 size_t alen)
paul718e3742002-12-13 20:15:29 +00001354{
Paul Jakma6f235412016-04-05 13:21:20 +01001355 size_t len;
paul718e3742002-12-13 20:15:29 +00001356 struct rtattr *subrta;
1357
paul7021c422003-07-15 12:52:22 +00001358 len = RTA_LENGTH (alen);
paul718e3742002-12-13 20:15:29 +00001359
paul7021c422003-07-15 12:52:22 +00001360 if (RTA_ALIGN (rta->rta_len) + len > maxlen)
paul718e3742002-12-13 20:15:29 +00001361 return -1;
1362
paul7021c422003-07-15 12:52:22 +00001363 subrta = (struct rtattr *) (((char *) rta) + RTA_ALIGN (rta->rta_len));
paul718e3742002-12-13 20:15:29 +00001364 subrta->rta_type = type;
1365 subrta->rta_len = len;
paul7021c422003-07-15 12:52:22 +00001366 memcpy (RTA_DATA (subrta), data, alen);
paul718e3742002-12-13 20:15:29 +00001367 rta->rta_len = NLMSG_ALIGN (rta->rta_len) + len;
1368
1369 return 0;
1370}
1371
1372/* Utility function comes from iproute2.
1373 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001374int
Paul Jakma7aa9dce2014-09-19 14:42:23 +01001375addattr32 (struct nlmsghdr *n, size_t maxlen, int type, int data)
paul718e3742002-12-13 20:15:29 +00001376{
Paul Jakma7aa9dce2014-09-19 14:42:23 +01001377 size_t len;
paul718e3742002-12-13 20:15:29 +00001378 struct rtattr *rta;
paul7021c422003-07-15 12:52:22 +00001379
1380 len = RTA_LENGTH (4);
1381
paul718e3742002-12-13 20:15:29 +00001382 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
1383 return -1;
1384
paul7021c422003-07-15 12:52:22 +00001385 rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
paul718e3742002-12-13 20:15:29 +00001386 rta->rta_type = type;
1387 rta->rta_len = len;
paul7021c422003-07-15 12:52:22 +00001388 memcpy (RTA_DATA (rta), &data, 4);
paul718e3742002-12-13 20:15:29 +00001389 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1390
1391 return 0;
1392}
1393
1394static int
Feng Lu758fb8f2014-07-03 18:23:09 +08001395netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h,
1396 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001397{
Feng Lu758fb8f2014-07-03 18:23:09 +08001398 zlog_warn ("netlink_talk: ignoring message type 0x%04x vrf %u", h->nlmsg_type,
1399 vrf_id);
paul718e3742002-12-13 20:15:29 +00001400 return 0;
1401}
1402
1403/* sendmsg() to netlink socket then recvmsg(). */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001404static int
Feng Lu758fb8f2014-07-03 18:23:09 +08001405netlink_talk (struct nlmsghdr *n, struct nlsock *nl, struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001406{
1407 int status;
1408 struct sockaddr_nl snl;
Timo Teräsc299ed72014-07-29 09:41:55 +00001409 struct iovec iov = {
1410 .iov_base = (void *) n,
1411 .iov_len = n->nlmsg_len
1412 };
1413 struct msghdr msg = {
1414 .msg_name = (void *) &snl,
1415 .msg_namelen = sizeof snl,
1416 .msg_iov = &iov,
1417 .msg_iovlen = 1,
1418 };
ajs4be019d2005-01-29 16:12:41 +00001419 int save_errno;
paul7021c422003-07-15 12:52:22 +00001420
paul718e3742002-12-13 20:15:29 +00001421 memset (&snl, 0, sizeof snl);
1422 snl.nl_family = AF_NETLINK;
paul7021c422003-07-15 12:52:22 +00001423
hassob7ed1ec2005-03-31 20:13:49 +00001424 n->nlmsg_seq = ++nl->seq;
paul718e3742002-12-13 20:15:29 +00001425
1426 /* Request an acknowledgement by setting NLM_F_ACK */
1427 n->nlmsg_flags |= NLM_F_ACK;
paul7021c422003-07-15 12:52:22 +00001428
1429 if (IS_ZEBRA_DEBUG_KERNEL)
hassob7ed1ec2005-03-31 20:13:49 +00001430 zlog_debug ("netlink_talk: %s type %s(%u), seq=%u", nl->name,
paul7021c422003-07-15 12:52:22 +00001431 lookup (nlmsg_str, n->nlmsg_type), n->nlmsg_type,
1432 n->nlmsg_seq);
paul718e3742002-12-13 20:15:29 +00001433
1434 /* Send message to netlink interface. */
paul7021c422003-07-15 12:52:22 +00001435 if (zserv_privs.change (ZPRIVS_RAISE))
1436 zlog (NULL, LOG_ERR, "Can't raise privileges");
paul718e3742002-12-13 20:15:29 +00001437 status = sendmsg (nl->sock, &msg, 0);
ajs4be019d2005-01-29 16:12:41 +00001438 save_errno = errno;
paul7021c422003-07-15 12:52:22 +00001439 if (zserv_privs.change (ZPRIVS_LOWER))
1440 zlog (NULL, LOG_ERR, "Can't lower privileges");
1441
paul718e3742002-12-13 20:15:29 +00001442 if (status < 0)
1443 {
1444 zlog (NULL, LOG_ERR, "netlink_talk sendmsg() error: %s",
ajs4be019d2005-01-29 16:12:41 +00001445 safe_strerror (save_errno));
paul718e3742002-12-13 20:15:29 +00001446 return -1;
1447 }
paul7021c422003-07-15 12:52:22 +00001448
paul718e3742002-12-13 20:15:29 +00001449
1450 /*
1451 * Get reply from netlink socket.
1452 * The reply should either be an acknowlegement or an error.
1453 */
Feng Lu758fb8f2014-07-03 18:23:09 +08001454 return netlink_parse_info (netlink_talk_filter, nl, zvrf);
paul718e3742002-12-13 20:15:29 +00001455}
1456
Christian Frankefa713d92013-07-05 15:35:37 +00001457/* This function takes a nexthop as argument and adds
1458 * the appropriate netlink attributes to an existing
1459 * netlink message.
1460 *
1461 * @param routedesc: Human readable description of route type
1462 * (direct/recursive, single-/multipath)
1463 * @param bytelen: Length of addresses in bytes.
1464 * @param nexthop: Nexthop information
1465 * @param nlmsg: nlmsghdr structure to fill in.
1466 * @param req_size: The size allocated for the message.
1467 */
1468static void
1469_netlink_route_build_singlepath(
1470 const char *routedesc,
1471 int bytelen,
1472 struct nexthop *nexthop,
1473 struct nlmsghdr *nlmsg,
Christian Frankee8d3d292013-07-05 15:35:39 +00001474 struct rtmsg *rtmsg,
Christian Frankefa713d92013-07-05 15:35:37 +00001475 size_t req_size)
1476{
Christian Frankee8d3d292013-07-05 15:35:39 +00001477 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
1478 rtmsg->rtm_flags |= RTNH_F_ONLINK;
Christian Frankefa713d92013-07-05 15:35:37 +00001479 if (nexthop->type == NEXTHOP_TYPE_IPV4
1480 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1481 {
1482 addattr_l (nlmsg, req_size, RTA_GATEWAY,
1483 &nexthop->gate.ipv4, bytelen);
1484 if (nexthop->src.ipv4.s_addr)
1485 addattr_l (nlmsg, req_size, RTA_PREFSRC,
1486 &nexthop->src.ipv4, bytelen);
1487
1488 if (IS_ZEBRA_DEBUG_KERNEL)
1489 zlog_debug("netlink_route_multipath() (%s): "
1490 "nexthop via %s if %u",
1491 routedesc,
1492 inet_ntoa (nexthop->gate.ipv4),
1493 nexthop->ifindex);
1494 }
1495#ifdef HAVE_IPV6
1496 if (nexthop->type == NEXTHOP_TYPE_IPV6
1497 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1498 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1499 {
1500 addattr_l (nlmsg, req_size, RTA_GATEWAY,
1501 &nexthop->gate.ipv6, bytelen);
1502
1503 if (IS_ZEBRA_DEBUG_KERNEL)
1504 zlog_debug("netlink_route_multipath() (%s): "
1505 "nexthop via %s if %u",
1506 routedesc,
1507 inet6_ntoa (nexthop->gate.ipv6),
1508 nexthop->ifindex);
1509 }
1510#endif /* HAVE_IPV6 */
1511 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1512 || nexthop->type == NEXTHOP_TYPE_IFNAME
1513 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1514 {
1515 addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
1516
1517 if (nexthop->src.ipv4.s_addr)
1518 addattr_l (nlmsg, req_size, RTA_PREFSRC,
1519 &nexthop->src.ipv4, bytelen);
1520
1521 if (IS_ZEBRA_DEBUG_KERNEL)
1522 zlog_debug("netlink_route_multipath() (%s): "
1523 "nexthop via if %u", routedesc, nexthop->ifindex);
1524 }
1525
1526 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
1527 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
1528 {
1529 addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
1530
1531 if (IS_ZEBRA_DEBUG_KERNEL)
1532 zlog_debug("netlink_route_multipath() (%s): "
1533 "nexthop via if %u", routedesc, nexthop->ifindex);
1534 }
1535}
1536
1537/* This function takes a nexthop as argument and
1538 * appends to the given rtattr/rtnexthop pair the
1539 * representation of the nexthop. If the nexthop
1540 * defines a preferred source, the src parameter
1541 * will be modified to point to that src, otherwise
1542 * it will be kept unmodified.
1543 *
1544 * @param routedesc: Human readable description of route type
1545 * (direct/recursive, single-/multipath)
1546 * @param bytelen: Length of addresses in bytes.
1547 * @param nexthop: Nexthop information
1548 * @param rta: rtnetlink attribute structure
1549 * @param rtnh: pointer to an rtnetlink nexthop structure
1550 * @param src: pointer pointing to a location where
1551 * the prefsrc should be stored.
1552 */
1553static void
1554_netlink_route_build_multipath(
1555 const char *routedesc,
1556 int bytelen,
1557 struct nexthop *nexthop,
1558 struct rtattr *rta,
1559 struct rtnexthop *rtnh,
1560 union g_addr **src
1561 )
1562{
1563 rtnh->rtnh_len = sizeof (*rtnh);
1564 rtnh->rtnh_flags = 0;
1565 rtnh->rtnh_hops = 0;
1566 rta->rta_len += rtnh->rtnh_len;
1567
Christian Frankee8d3d292013-07-05 15:35:39 +00001568 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
1569 rtnh->rtnh_flags |= RTNH_F_ONLINK;
1570
Christian Frankefa713d92013-07-05 15:35:37 +00001571 if (nexthop->type == NEXTHOP_TYPE_IPV4
1572 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1573 {
1574 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
1575 &nexthop->gate.ipv4, bytelen);
Lu Feng621e2aa2014-07-11 07:52:15 +00001576 rtnh->rtnh_len += sizeof (struct rtattr) + bytelen;
Christian Frankefa713d92013-07-05 15:35:37 +00001577
1578 if (nexthop->src.ipv4.s_addr)
1579 *src = &nexthop->src;
1580
1581 if (IS_ZEBRA_DEBUG_KERNEL)
1582 zlog_debug("netlink_route_multipath() (%s): "
1583 "nexthop via %s if %u",
1584 routedesc,
1585 inet_ntoa (nexthop->gate.ipv4),
1586 nexthop->ifindex);
1587 }
1588#ifdef HAVE_IPV6
1589 if (nexthop->type == NEXTHOP_TYPE_IPV6
1590 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1591 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1592 {
1593 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
1594 &nexthop->gate.ipv6, bytelen);
Lu Feng621e2aa2014-07-11 07:52:15 +00001595 rtnh->rtnh_len += sizeof (struct rtattr) + bytelen;
Christian Frankefa713d92013-07-05 15:35:37 +00001596
1597 if (IS_ZEBRA_DEBUG_KERNEL)
1598 zlog_debug("netlink_route_multipath() (%s): "
1599 "nexthop via %s if %u",
1600 routedesc,
1601 inet6_ntoa (nexthop->gate.ipv6),
1602 nexthop->ifindex);
1603 }
1604#endif /* HAVE_IPV6 */
1605 /* ifindex */
1606 if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1607 || nexthop->type == NEXTHOP_TYPE_IFINDEX
1608 || nexthop->type == NEXTHOP_TYPE_IFNAME)
1609 {
1610 rtnh->rtnh_ifindex = nexthop->ifindex;
1611 if (nexthop->src.ipv4.s_addr)
1612 *src = &nexthop->src;
1613 if (IS_ZEBRA_DEBUG_KERNEL)
1614 zlog_debug("netlink_route_multipath() (%s): "
1615 "nexthop via if %u", routedesc, nexthop->ifindex);
1616 }
1617 else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1618 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1619 {
1620 rtnh->rtnh_ifindex = nexthop->ifindex;
1621
1622 if (IS_ZEBRA_DEBUG_KERNEL)
1623 zlog_debug("netlink_route_multipath() (%s): "
1624 "nexthop via if %u", routedesc, nexthop->ifindex);
1625 }
1626 else
1627 {
1628 rtnh->rtnh_ifindex = 0;
1629 }
1630}
1631
1632/* Log debug information for netlink_route_multipath
1633 * if debug logging is enabled.
1634 *
1635 * @param cmd: Netlink command which is to be processed
1636 * @param p: Prefix for which the change is due
1637 * @param nexthop: Nexthop which is currently processed
1638 * @param routedesc: Semantic annotation for nexthop
1639 * (recursive, multipath, etc.)
1640 * @param family: Address family which the change concerns
1641 */
1642static void
1643_netlink_route_debug(
1644 int cmd,
1645 struct prefix *p,
1646 struct nexthop *nexthop,
1647 const char *routedesc,
Feng Lu758fb8f2014-07-03 18:23:09 +08001648 int family,
1649 struct zebra_vrf *zvrf)
Christian Frankefa713d92013-07-05 15:35:37 +00001650{
1651 if (IS_ZEBRA_DEBUG_KERNEL)
1652 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001653 char buf[PREFIX_STRLEN];
Feng Lu758fb8f2014-07-03 18:23:09 +08001654 zlog_debug ("netlink_route_multipath() (%s): %s %s vrf %u type %s",
Christian Frankefa713d92013-07-05 15:35:37 +00001655 routedesc,
1656 lookup (nlmsg_str, cmd),
Timo Teräsbe6335d2015-05-23 11:08:41 +03001657 prefix2str (p, buf, sizeof(buf)),
Kaloyan Kovachev8c56b442015-06-15 17:08:48 +03001658 zvrf->vrf_id,
Timo Teräsbe6335d2015-05-23 11:08:41 +03001659 nexthop_type_to_str (nexthop->type));
Christian Frankefa713d92013-07-05 15:35:37 +00001660 }
1661}
1662
paul718e3742002-12-13 20:15:29 +00001663/* Routing table change via netlink interface. */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001664static int
Timo Teräs0abf6792016-01-15 17:36:29 +02001665netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001666{
1667 int bytelen;
1668 struct sockaddr_nl snl;
Christian Frankefa713d92013-07-05 15:35:37 +00001669 struct nexthop *nexthop = NULL, *tnexthop;
1670 int recursing;
1671 int nexthop_num;
paul718e3742002-12-13 20:15:29 +00001672 int discard;
Timo Teräs0abf6792016-01-15 17:36:29 +02001673 int family = PREFIX_FAMILY(p);
Christian Frankefa713d92013-07-05 15:35:37 +00001674 const char *routedesc;
paul718e3742002-12-13 20:15:29 +00001675
paul7021c422003-07-15 12:52:22 +00001676 struct
paul718e3742002-12-13 20:15:29 +00001677 {
1678 struct nlmsghdr n;
1679 struct rtmsg r;
JR Rivers3cadc0c2012-04-01 12:16:31 -07001680 char buf[NL_PKT_BUF_SIZE];
paul718e3742002-12-13 20:15:29 +00001681 } req;
1682
Feng Lu758fb8f2014-07-03 18:23:09 +08001683 struct zebra_vrf *zvrf = vrf_info_lookup (rib->vrf_id);
1684
Jorge Boncompte [DTI2]a4c06de2012-04-20 14:28:40 +02001685 memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
paul718e3742002-12-13 20:15:29 +00001686
1687 bytelen = (family == AF_INET ? 4 : 16);
1688
1689 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
Timo Teräs0abf6792016-01-15 17:36:29 +02001690 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REPLACE | NLM_F_REQUEST;
paul718e3742002-12-13 20:15:29 +00001691 req.n.nlmsg_type = cmd;
1692 req.r.rtm_family = family;
1693 req.r.rtm_table = rib->table;
1694 req.r.rtm_dst_len = p->prefixlen;
Timo Teräs40da2212008-08-13 17:37:14 +01001695 req.r.rtm_protocol = RTPROT_ZEBRA;
Timo Teräs82a66352016-01-15 17:36:30 +02001696 req.r.rtm_scope = RT_SCOPE_LINK;
paul718e3742002-12-13 20:15:29 +00001697
paul7021c422003-07-15 12:52:22 +00001698 if ((rib->flags & ZEBRA_FLAG_BLACKHOLE) || (rib->flags & ZEBRA_FLAG_REJECT))
paul718e3742002-12-13 20:15:29 +00001699 discard = 1;
1700 else
1701 discard = 0;
1702
paul7021c422003-07-15 12:52:22 +00001703 if (cmd == RTM_NEWROUTE)
paul718e3742002-12-13 20:15:29 +00001704 {
paul7021c422003-07-15 12:52:22 +00001705 if (discard)
paul595db7f2003-05-25 21:35:06 +00001706 {
1707 if (rib->flags & ZEBRA_FLAG_BLACKHOLE)
1708 req.r.rtm_type = RTN_BLACKHOLE;
1709 else if (rib->flags & ZEBRA_FLAG_REJECT)
1710 req.r.rtm_type = RTN_UNREACHABLE;
paul7021c422003-07-15 12:52:22 +00001711 else
1712 assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
1713 }
paul595db7f2003-05-25 21:35:06 +00001714 else
paul7021c422003-07-15 12:52:22 +00001715 req.r.rtm_type = RTN_UNICAST;
paul718e3742002-12-13 20:15:29 +00001716 }
1717
1718 addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
1719
1720 /* Metric. */
Timo Teräs4d3ae712016-01-15 17:36:32 +02001721 addattr32 (&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC);
paul718e3742002-12-13 20:15:29 +00001722
Timo Teräsb11f3b52015-11-02 16:50:07 +02001723 if (rib->mtu || rib->nexthop_mtu)
1724 {
1725 char buf[NL_PKT_BUF_SIZE];
1726 struct rtattr *rta = (void *) buf;
1727 u_int32_t mtu = rib->mtu;
1728 if (!mtu || (rib->nexthop_mtu && rib->nexthop_mtu < mtu))
1729 mtu = rib->nexthop_mtu;
1730 rta->rta_type = RTA_METRICS;
1731 rta->rta_len = RTA_LENGTH(0);
1732 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTAX_MTU, &mtu, sizeof mtu);
1733 addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA (rta),
1734 RTA_PAYLOAD (rta));
1735 }
1736
paul718e3742002-12-13 20:15:29 +00001737 if (discard)
1738 {
1739 if (cmd == RTM_NEWROUTE)
Christian Frankefa713d92013-07-05 15:35:37 +00001740 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1741 {
1742 /* We shouldn't encounter recursive nexthops on discard routes,
1743 * but it is probably better to handle that case correctly anyway.
1744 */
1745 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1746 continue;
1747 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1748 }
paul718e3742002-12-13 20:15:29 +00001749 goto skip;
1750 }
1751
Christian Frankefa713d92013-07-05 15:35:37 +00001752 /* Count overall nexthops so we can decide whether to use singlepath
1753 * or multipath case. */
1754 nexthop_num = 0;
1755 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001756 {
Christian Frankefa713d92013-07-05 15:35:37 +00001757 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1758 continue;
1759 if (cmd == RTM_NEWROUTE && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1760 continue;
1761 if (cmd == RTM_DELROUTE && !CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1762 continue;
1763
Timo Teräs82a66352016-01-15 17:36:30 +02001764 if (nexthop->type != NEXTHOP_TYPE_IFINDEX &&
1765 nexthop->type != NEXTHOP_TYPE_IFNAME)
1766 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1767
Christian Frankefa713d92013-07-05 15:35:37 +00001768 nexthop_num++;
1769 }
1770
1771 /* Singlepath case. */
1772 if (nexthop_num == 1 || MULTIPATH_NUM == 1)
1773 {
1774 nexthop_num = 0;
1775 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul7021c422003-07-15 12:52:22 +00001776 {
Christian Frankefa713d92013-07-05 15:35:37 +00001777 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1778 continue;
paul5ec90d22003-06-19 01:41:37 +00001779
paul7021c422003-07-15 12:52:22 +00001780 if ((cmd == RTM_NEWROUTE
1781 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1782 || (cmd == RTM_DELROUTE
1783 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1784 {
Christian Frankefa713d92013-07-05 15:35:37 +00001785 routedesc = recursing ? "recursive, 1 hop" : "single hop";
paul5ec90d22003-06-19 01:41:37 +00001786
Feng Lu758fb8f2014-07-03 18:23:09 +08001787 _netlink_route_debug(cmd, p, nexthop, routedesc, family, zvrf);
Christian Frankefa713d92013-07-05 15:35:37 +00001788 _netlink_route_build_singlepath(routedesc, bytelen,
Christian Frankee8d3d292013-07-05 15:35:39 +00001789 nexthop, &req.n, &req.r,
1790 sizeof req);
paul718e3742002-12-13 20:15:29 +00001791
paul7021c422003-07-15 12:52:22 +00001792 if (cmd == RTM_NEWROUTE)
1793 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
paul718e3742002-12-13 20:15:29 +00001794
paul7021c422003-07-15 12:52:22 +00001795 nexthop_num++;
1796 break;
1797 }
1798 }
paul718e3742002-12-13 20:15:29 +00001799 }
1800 else
1801 {
JR Rivers3cadc0c2012-04-01 12:16:31 -07001802 char buf[NL_PKT_BUF_SIZE];
paul718e3742002-12-13 20:15:29 +00001803 struct rtattr *rta = (void *) buf;
1804 struct rtnexthop *rtnh;
Paul Jakma7514fb72007-05-02 16:05:35 +00001805 union g_addr *src = NULL;
paul718e3742002-12-13 20:15:29 +00001806
1807 rta->rta_type = RTA_MULTIPATH;
paul7021c422003-07-15 12:52:22 +00001808 rta->rta_len = RTA_LENGTH (0);
1809 rtnh = RTA_DATA (rta);
paul718e3742002-12-13 20:15:29 +00001810
1811 nexthop_num = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001812 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul7021c422003-07-15 12:52:22 +00001813 {
Donald Sharp91ce87a2015-12-09 08:24:45 -05001814 if (nexthop_num >= MULTIPATH_NUM)
Christian Frankefa713d92013-07-05 15:35:37 +00001815 break;
1816
1817 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1818 continue;
1819
paul7021c422003-07-15 12:52:22 +00001820 if ((cmd == RTM_NEWROUTE
1821 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1822 || (cmd == RTM_DELROUTE
1823 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1824 {
Christian Frankefa713d92013-07-05 15:35:37 +00001825 routedesc = recursing ? "recursive, multihop" : "multihop";
paul7021c422003-07-15 12:52:22 +00001826 nexthop_num++;
paul718e3742002-12-13 20:15:29 +00001827
Christian Frankefa713d92013-07-05 15:35:37 +00001828 _netlink_route_debug(cmd, p, nexthop,
Feng Lu758fb8f2014-07-03 18:23:09 +08001829 routedesc, family, zvrf);
Christian Frankefa713d92013-07-05 15:35:37 +00001830 _netlink_route_build_multipath(routedesc, bytelen,
1831 nexthop, rta, rtnh, &src);
paul7021c422003-07-15 12:52:22 +00001832 rtnh = RTNH_NEXT (rtnh);
paul718e3742002-12-13 20:15:29 +00001833
paul7021c422003-07-15 12:52:22 +00001834 if (cmd == RTM_NEWROUTE)
1835 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1836 }
1837 }
Paul Jakma7514fb72007-05-02 16:05:35 +00001838 if (src)
1839 addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src->ipv4, bytelen);
paul718e3742002-12-13 20:15:29 +00001840
1841 if (rta->rta_len > RTA_LENGTH (0))
JR Rivers3cadc0c2012-04-01 12:16:31 -07001842 addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta),
paul7021c422003-07-15 12:52:22 +00001843 RTA_PAYLOAD (rta));
paul718e3742002-12-13 20:15:29 +00001844 }
1845
1846 /* If there is no useful nexthop then return. */
1847 if (nexthop_num == 0)
1848 {
1849 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +00001850 zlog_debug ("netlink_route_multipath(): No useful nexthop.");
paul718e3742002-12-13 20:15:29 +00001851 return 0;
1852 }
1853
paul7021c422003-07-15 12:52:22 +00001854skip:
paul718e3742002-12-13 20:15:29 +00001855
1856 /* Destination netlink address. */
1857 memset (&snl, 0, sizeof snl);
1858 snl.nl_family = AF_NETLINK;
1859
paul718e3742002-12-13 20:15:29 +00001860 /* Talk to netlink socket. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001861 return netlink_talk (&req.n, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001862}
1863
1864int
Timo Teräs0abf6792016-01-15 17:36:29 +02001865kernel_route_rib (struct prefix *p, struct rib *old, struct rib *new)
paul718e3742002-12-13 20:15:29 +00001866{
Timo Teräs0abf6792016-01-15 17:36:29 +02001867 if (!old && new)
1868 return netlink_route_multipath (RTM_NEWROUTE, p, new);
1869 if (old && !new)
1870 return netlink_route_multipath (RTM_DELROUTE, p, old);
paul718e3742002-12-13 20:15:29 +00001871
Timo Teräs4d3ae712016-01-15 17:36:32 +02001872 /* Replace, can be done atomically if metric does not change;
1873 * netlink uses [prefix, tos, priority] to identify prefix.
1874 * Now metric is not sent to kernel, so we can just do atomic replace. */
1875 return netlink_route_multipath (RTM_NEWROUTE, p, new);
paul718e3742002-12-13 20:15:29 +00001876}
David Lamparter6b0655a2014-06-04 06:53:35 +02001877
paul718e3742002-12-13 20:15:29 +00001878/* Interface address modification. */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001879static int
paul718e3742002-12-13 20:15:29 +00001880netlink_address (int cmd, int family, struct interface *ifp,
paul7021c422003-07-15 12:52:22 +00001881 struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001882{
1883 int bytelen;
1884 struct prefix *p;
1885
paul7021c422003-07-15 12:52:22 +00001886 struct
paul718e3742002-12-13 20:15:29 +00001887 {
1888 struct nlmsghdr n;
1889 struct ifaddrmsg ifa;
JR Rivers3cadc0c2012-04-01 12:16:31 -07001890 char buf[NL_PKT_BUF_SIZE];
paul718e3742002-12-13 20:15:29 +00001891 } req;
1892
Feng Lu758fb8f2014-07-03 18:23:09 +08001893 struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
1894
paul718e3742002-12-13 20:15:29 +00001895 p = ifc->address;
Jorge Boncompte [DTI2]a4c06de2012-04-20 14:28:40 +02001896 memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
paul718e3742002-12-13 20:15:29 +00001897
1898 bytelen = (family == AF_INET ? 4 : 16);
1899
paul7021c422003-07-15 12:52:22 +00001900 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg));
paul718e3742002-12-13 20:15:29 +00001901 req.n.nlmsg_flags = NLM_F_REQUEST;
1902 req.n.nlmsg_type = cmd;
1903 req.ifa.ifa_family = family;
1904
1905 req.ifa.ifa_index = ifp->ifindex;
1906 req.ifa.ifa_prefixlen = p->prefixlen;
1907
1908 addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen);
1909
1910 if (family == AF_INET && cmd == RTM_NEWADDR)
1911 {
Andrew J. Schorre4529632006-12-12 19:18:21 +00001912 if (!CONNECTED_PEER(ifc) && ifc->destination)
paul7021c422003-07-15 12:52:22 +00001913 {
1914 p = ifc->destination;
1915 addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix,
1916 bytelen);
1917 }
paul718e3742002-12-13 20:15:29 +00001918 }
1919
1920 if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
1921 SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY);
paul7021c422003-07-15 12:52:22 +00001922
paul718e3742002-12-13 20:15:29 +00001923 if (ifc->label)
1924 addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label,
paul7021c422003-07-15 12:52:22 +00001925 strlen (ifc->label) + 1);
paul718e3742002-12-13 20:15:29 +00001926
Feng Lu758fb8f2014-07-03 18:23:09 +08001927 return netlink_talk (&req.n, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001928}
1929
1930int
1931kernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc)
1932{
1933 return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc);
1934}
1935
1936int
1937kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc)
1938{
1939 return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc);
1940}
1941
paul718e3742002-12-13 20:15:29 +00001942
1943extern struct thread_master *master;
1944
1945/* Kernel route reflection. */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001946static int
paul718e3742002-12-13 20:15:29 +00001947kernel_read (struct thread *thread)
1948{
Feng Lu758fb8f2014-07-03 18:23:09 +08001949 struct zebra_vrf *zvrf = (struct zebra_vrf *)THREAD_ARG (thread);
1950 netlink_parse_info (netlink_information_fetch, &zvrf->netlink, zvrf);
1951 zvrf->t_netlink = thread_add_read (zebrad.master, kernel_read, zvrf,
1952 zvrf->netlink.sock);
paul718e3742002-12-13 20:15:29 +00001953
1954 return 0;
1955}
1956
Stephen Hemminger3d265b42008-08-16 17:30:39 +01001957/* Filter out messages from self that occur on listener socket,
1958 caused by our actions on the command socket
1959 */
1960static void netlink_install_filter (int sock, __u32 pid)
Paul Jakma768a27e2008-05-29 18:23:08 +00001961{
Paul Jakma768a27e2008-05-29 18:23:08 +00001962 struct sock_filter filter[] = {
Stephen Hemminger3d265b42008-08-16 17:30:39 +01001963 /* 0: ldh [4] */
1964 BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)),
1965 /* 1: jeq 0x18 jt 3 jf 6 */
1966 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 1, 0),
1967 /* 2: jeq 0x19 jt 3 jf 6 */
1968 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 0, 3),
1969 /* 3: ldw [12] */
1970 BPF_STMT(BPF_LD|BPF_ABS|BPF_W, offsetof(struct nlmsghdr, nlmsg_pid)),
1971 /* 4: jeq XX jt 5 jf 6 */
1972 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htonl(pid), 0, 1),
1973 /* 5: ret 0 (skip) */
1974 BPF_STMT(BPF_RET|BPF_K, 0),
1975 /* 6: ret 0xffff (keep) */
1976 BPF_STMT(BPF_RET|BPF_K, 0xffff),
Paul Jakma768a27e2008-05-29 18:23:08 +00001977 };
1978
1979 struct sock_fprog prog = {
Balaji.G837d16c2012-09-26 14:09:10 +05301980 .len = array_size(filter),
Paul Jakma768a27e2008-05-29 18:23:08 +00001981 .filter = filter,
1982 };
1983
1984 if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)) < 0)
1985 zlog_warn ("Can't install socket filter: %s\n", safe_strerror(errno));
1986}
1987
paul718e3742002-12-13 20:15:29 +00001988/* Exported interface function. This function simply calls
1989 netlink_socket (). */
1990void
Feng Lu758fb8f2014-07-03 18:23:09 +08001991kernel_init (struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001992{
1993 unsigned long groups;
1994
paul7021c422003-07-15 12:52:22 +00001995 groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR;
paul718e3742002-12-13 20:15:29 +00001996#ifdef HAVE_IPV6
paul7021c422003-07-15 12:52:22 +00001997 groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR;
paul718e3742002-12-13 20:15:29 +00001998#endif /* HAVE_IPV6 */
Feng Lu758fb8f2014-07-03 18:23:09 +08001999 netlink_socket (&zvrf->netlink, groups, zvrf->vrf_id);
2000 netlink_socket (&zvrf->netlink_cmd, 0, zvrf->vrf_id);
paul718e3742002-12-13 20:15:29 +00002001
2002 /* Register kernel socket. */
Feng Lu758fb8f2014-07-03 18:23:09 +08002003 if (zvrf->netlink.sock > 0)
Paul Jakma768a27e2008-05-29 18:23:08 +00002004 {
Stephen Hemminger4cde9312008-08-16 17:51:27 +01002005 /* Only want non-blocking on the netlink event socket */
Feng Lu758fb8f2014-07-03 18:23:09 +08002006 if (fcntl (zvrf->netlink.sock, F_SETFL, O_NONBLOCK) < 0)
2007 zlog_err ("Can't set %s socket flags: %s", zvrf->netlink.name,
2008 safe_strerror (errno));
Stephen Hemminger4cde9312008-08-16 17:51:27 +01002009
Stephen Hemminger30afea32008-08-16 18:25:47 +01002010 /* Set receive buffer size if it's set from command line */
2011 if (nl_rcvbufsize)
Feng Lu758fb8f2014-07-03 18:23:09 +08002012 netlink_recvbuf (&zvrf->netlink, nl_rcvbufsize);
Stephen Hemminger30afea32008-08-16 18:25:47 +01002013
Feng Lu758fb8f2014-07-03 18:23:09 +08002014 netlink_install_filter (zvrf->netlink.sock, zvrf->netlink_cmd.snl.nl_pid);
2015 zvrf->t_netlink = thread_add_read (zebrad.master, kernel_read, zvrf,
2016 zvrf->netlink.sock);
2017 }
2018}
2019
2020void
2021kernel_terminate (struct zebra_vrf *zvrf)
2022{
2023 THREAD_READ_OFF (zvrf->t_netlink);
2024
2025 if (zvrf->netlink.sock >= 0)
2026 {
2027 close (zvrf->netlink.sock);
2028 zvrf->netlink.sock = -1;
2029 }
2030
2031 if (zvrf->netlink_cmd.sock >= 0)
2032 {
2033 close (zvrf->netlink_cmd.sock);
2034 zvrf->netlink_cmd.sock = -1;
Paul Jakma768a27e2008-05-29 18:23:08 +00002035 }
paul718e3742002-12-13 20:15:29 +00002036}
Avneesh Sachdev78deec42012-11-13 22:48:56 +00002037
2038/*
2039 * nl_msg_type_to_str
2040 */
2041const char *
2042nl_msg_type_to_str (uint16_t msg_type)
2043{
2044 return lookup (nlmsg_str, msg_type);
2045}
2046
2047/*
2048 * nl_rtproto_to_str
2049 */
2050const char *
2051nl_rtproto_to_str (u_char rtproto)
2052{
2053 return lookup (rtproto_str, rtproto);
2054}