blob: fc6e373dbde82ab5f58c16a0fff83b2e464c90ba [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
Paul Jakma6dbb58c2017-02-08 15:05:06 +000070static struct {
71 char *p;
72 size_t size;
73} nl_rcvbuf;
74
ajsd2fc8892005-04-02 18:38:43 +000075/* Note: on netlink systems, there should be a 1-to-1 mapping between interface
76 names and ifindex values. */
77static void
Paul Jakma9099f9b2016-01-18 10:12:10 +000078set_ifindex(struct interface *ifp, ifindex_t ifi_index)
ajsd2fc8892005-04-02 18:38:43 +000079{
80 struct interface *oifp;
81
82 if (((oifp = if_lookup_by_index(ifi_index)) != NULL) && (oifp != ifp))
83 {
84 if (ifi_index == IFINDEX_INTERNAL)
85 zlog_err("Netlink is setting interface %s ifindex to reserved "
86 "internal value %u", ifp->name, ifi_index);
87 else
88 {
89 if (IS_ZEBRA_DEBUG_KERNEL)
90 zlog_debug("interface index %d was renamed from %s to %s",
91 ifi_index, oifp->name, ifp->name);
92 if (if_is_up(oifp))
93 zlog_err("interface rename detected on up interface: index %d "
94 "was renamed from %s to %s, results are uncertain!",
95 ifi_index, oifp->name, ifp->name);
96 if_delete_update(oifp);
97 }
98 }
99 ifp->ifindex = ifi_index;
100}
101
Ulrich Weberf1ef81b2013-01-22 10:39:18 +0000102#ifndef SO_RCVBUFFORCE
103#define SO_RCVBUFFORCE (33)
104#endif
105
Stephen Hemminger30afea32008-08-16 18:25:47 +0100106static int
107netlink_recvbuf (struct nlsock *nl, uint32_t newsize)
108{
109 u_int32_t oldsize;
110 socklen_t newlen = sizeof(newsize);
111 socklen_t oldlen = sizeof(oldsize);
112 int ret;
113
114 ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &oldsize, &oldlen);
115 if (ret < 0)
116 {
117 zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name,
118 safe_strerror (errno));
119 return -1;
120 }
121
Ulrich Weberf1ef81b2013-01-22 10:39:18 +0000122 /* Try force option (linux >= 2.6.14) and fall back to normal set */
123 if ( zserv_privs.change (ZPRIVS_RAISE) )
124 zlog_err ("routing_socket: Can't raise privileges");
125 ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUFFORCE, &nl_rcvbufsize,
Stephen Hemminger30afea32008-08-16 18:25:47 +0100126 sizeof(nl_rcvbufsize));
Ulrich Weberf1ef81b2013-01-22 10:39:18 +0000127 if ( zserv_privs.change (ZPRIVS_LOWER) )
128 zlog_err ("routing_socket: Can't lower privileges");
129 if (ret < 0)
130 ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &nl_rcvbufsize,
131 sizeof(nl_rcvbufsize));
Stephen Hemminger30afea32008-08-16 18:25:47 +0100132 if (ret < 0)
133 {
134 zlog (NULL, LOG_ERR, "Can't set %s receive buffer size: %s", nl->name,
135 safe_strerror (errno));
136 return -1;
137 }
138
139 ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &newsize, &newlen);
140 if (ret < 0)
141 {
142 zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name,
143 safe_strerror (errno));
144 return -1;
145 }
146
147 zlog (NULL, LOG_INFO,
148 "Setting netlink socket receive buffer size: %u -> %u",
149 oldsize, newsize);
150 return 0;
151}
152
paul718e3742002-12-13 20:15:29 +0000153/* Make socket for Linux netlink interface. */
154static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800155netlink_socket (struct nlsock *nl, unsigned long groups, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000156{
157 int ret;
158 struct sockaddr_nl snl;
159 int sock;
160 int namelen;
ajs4be019d2005-01-29 16:12:41 +0000161 int save_errno;
paul718e3742002-12-13 20:15:29 +0000162
Michal Sekletar8e998b12014-05-16 14:13:43 +0000163 if (zserv_privs.change (ZPRIVS_RAISE))
164 {
165 zlog (NULL, LOG_ERR, "Can't raise privileges");
166 return -1;
167 }
168
Feng Lu758fb8f2014-07-03 18:23:09 +0800169 sock = vrf_socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE, vrf_id);
paul718e3742002-12-13 20:15:29 +0000170 if (sock < 0)
171 {
172 zlog (NULL, LOG_ERR, "Can't open %s socket: %s", nl->name,
ajs6099b3b2004-11-20 02:06:59 +0000173 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000174 return -1;
175 }
176
paul718e3742002-12-13 20:15:29 +0000177 memset (&snl, 0, sizeof snl);
178 snl.nl_family = AF_NETLINK;
179 snl.nl_groups = groups;
180
181 /* Bind the socket to the netlink structure for anything. */
182 ret = bind (sock, (struct sockaddr *) &snl, sizeof snl);
ajs4be019d2005-01-29 16:12:41 +0000183 save_errno = errno;
hasso55e7ecd2004-08-06 08:41:56 +0000184 if (zserv_privs.change (ZPRIVS_LOWER))
185 zlog (NULL, LOG_ERR, "Can't lower privileges");
186
paul718e3742002-12-13 20:15:29 +0000187 if (ret < 0)
188 {
paul7021c422003-07-15 12:52:22 +0000189 zlog (NULL, LOG_ERR, "Can't bind %s socket to group 0x%x: %s",
ajs4be019d2005-01-29 16:12:41 +0000190 nl->name, snl.nl_groups, safe_strerror (save_errno));
paul718e3742002-12-13 20:15:29 +0000191 close (sock);
192 return -1;
193 }
paul7021c422003-07-15 12:52:22 +0000194
paul718e3742002-12-13 20:15:29 +0000195 /* multiple netlink sockets will have different nl_pid */
196 namelen = sizeof snl;
hassoc9e52be2004-09-26 16:09:34 +0000197 ret = getsockname (sock, (struct sockaddr *) &snl, (socklen_t *) &namelen);
paul718e3742002-12-13 20:15:29 +0000198 if (ret < 0 || namelen != sizeof snl)
199 {
200 zlog (NULL, LOG_ERR, "Can't get %s socket name: %s", nl->name,
ajs6099b3b2004-11-20 02:06:59 +0000201 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000202 close (sock);
203 return -1;
204 }
205
206 nl->snl = snl;
207 nl->sock = sock;
208 return ret;
209}
210
211/* Get type specified information from netlink. */
212static int
213netlink_request (int family, int type, struct nlsock *nl)
214{
215 int ret;
216 struct sockaddr_nl snl;
ajs4be019d2005-01-29 16:12:41 +0000217 int save_errno;
paul718e3742002-12-13 20:15:29 +0000218
219 struct
220 {
221 struct nlmsghdr nlh;
222 struct rtgenmsg g;
223 } req;
224
225
226 /* Check netlink socket. */
227 if (nl->sock < 0)
228 {
229 zlog (NULL, LOG_ERR, "%s socket isn't active.", nl->name);
230 return -1;
231 }
232
233 memset (&snl, 0, sizeof snl);
234 snl.nl_family = AF_NETLINK;
235
ajsc05612b2005-10-01 16:36:54 +0000236 memset (&req, 0, sizeof req);
paul718e3742002-12-13 20:15:29 +0000237 req.nlh.nlmsg_len = sizeof req;
238 req.nlh.nlmsg_type = type;
239 req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
Stephen Hemminger3d265b42008-08-16 17:30:39 +0100240 req.nlh.nlmsg_pid = nl->snl.nl_pid;
paul718e3742002-12-13 20:15:29 +0000241 req.nlh.nlmsg_seq = ++nl->seq;
242 req.g.rtgen_family = family;
pauledd7c242003-06-04 13:59:38 +0000243
244 /* linux appears to check capabilities on every message
245 * have to raise caps for every message sent
246 */
paul7021c422003-07-15 12:52:22 +0000247 if (zserv_privs.change (ZPRIVS_RAISE))
pauledd7c242003-06-04 13:59:38 +0000248 {
249 zlog (NULL, LOG_ERR, "Can't raise privileges");
250 return -1;
251 }
paul7021c422003-07-15 12:52:22 +0000252
253 ret = sendto (nl->sock, (void *) &req, sizeof req, 0,
254 (struct sockaddr *) &snl, sizeof snl);
ajs4be019d2005-01-29 16:12:41 +0000255 save_errno = errno;
paul7021c422003-07-15 12:52:22 +0000256
257 if (zserv_privs.change (ZPRIVS_LOWER))
258 zlog (NULL, LOG_ERR, "Can't lower privileges");
259
paul718e3742002-12-13 20:15:29 +0000260 if (ret < 0)
paul7021c422003-07-15 12:52:22 +0000261 {
262 zlog (NULL, LOG_ERR, "%s sendto failed: %s", nl->name,
ajs4be019d2005-01-29 16:12:41 +0000263 safe_strerror (save_errno));
paul718e3742002-12-13 20:15:29 +0000264 return -1;
265 }
pauledd7c242003-06-04 13:59:38 +0000266
paul718e3742002-12-13 20:15:29 +0000267 return 0;
268}
269
270/* Receive message from netlink interface and pass those information
271 to the given function. */
272static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800273netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *,
274 vrf_id_t),
275 struct nlsock *nl, struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +0000276{
277 int status;
278 int ret = 0;
279 int error;
280
281 while (1)
282 {
Timo Teräsc299ed72014-07-29 09:41:55 +0000283 struct iovec iov = {
Paul Jakma6dbb58c2017-02-08 15:05:06 +0000284 .iov_base = nl_rcvbuf.p,
285 .iov_len = nl_rcvbuf.size,
Timo Teräsc299ed72014-07-29 09:41:55 +0000286 };
paul718e3742002-12-13 20:15:29 +0000287 struct sockaddr_nl snl;
Timo Teräsc299ed72014-07-29 09:41:55 +0000288 struct msghdr msg = {
289 .msg_name = (void *) &snl,
290 .msg_namelen = sizeof snl,
291 .msg_iov = &iov,
292 .msg_iovlen = 1
293 };
paul718e3742002-12-13 20:15:29 +0000294 struct nlmsghdr *h;
paul7021c422003-07-15 12:52:22 +0000295
paul718e3742002-12-13 20:15:29 +0000296 status = recvmsg (nl->sock, &msg, 0);
paul718e3742002-12-13 20:15:29 +0000297 if (status < 0)
paul7021c422003-07-15 12:52:22 +0000298 {
Stephen Hemminger4c699472008-08-17 17:01:44 +0100299 if (errno == EINTR)
paul7021c422003-07-15 12:52:22 +0000300 continue;
Stephen Hemminger4c699472008-08-17 17:01:44 +0100301 if (errno == EWOULDBLOCK || errno == EAGAIN)
paul7021c422003-07-15 12:52:22 +0000302 break;
ajs4be019d2005-01-29 16:12:41 +0000303 zlog (NULL, LOG_ERR, "%s recvmsg overrun: %s",
Stephen Hemminger4c699472008-08-17 17:01:44 +0100304 nl->name, safe_strerror(errno));
paul7021c422003-07-15 12:52:22 +0000305 continue;
306 }
paul718e3742002-12-13 20:15:29 +0000307
308 if (status == 0)
paul7021c422003-07-15 12:52:22 +0000309 {
310 zlog (NULL, LOG_ERR, "%s EOF", nl->name);
311 return -1;
312 }
paul718e3742002-12-13 20:15:29 +0000313
314 if (msg.msg_namelen != sizeof snl)
paul7021c422003-07-15 12:52:22 +0000315 {
316 zlog (NULL, LOG_ERR, "%s sender address length error: length %d",
317 nl->name, msg.msg_namelen);
318 return -1;
319 }
paulb84d3a12003-11-17 10:31:01 +0000320
Paul Jakma6dbb58c2017-02-08 15:05:06 +0000321 for (h = (struct nlmsghdr *) nl_rcvbuf.p;
322 NLMSG_OK (h, (unsigned int) status);
paul7021c422003-07-15 12:52:22 +0000323 h = NLMSG_NEXT (h, status))
324 {
325 /* Finish of reading. */
326 if (h->nlmsg_type == NLMSG_DONE)
327 return ret;
paul718e3742002-12-13 20:15:29 +0000328
paul7021c422003-07-15 12:52:22 +0000329 /* Error handling. */
330 if (h->nlmsg_type == NLMSG_ERROR)
331 {
332 struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h);
Stephen Hemminger898987e2008-08-17 16:56:15 +0100333 int errnum = err->error;
334 int msg_type = err->msg.nlmsg_type;
paul7021c422003-07-15 12:52:22 +0000335
paul718e3742002-12-13 20:15:29 +0000336 /* If the error field is zero, then this is an ACK */
paul7021c422003-07-15 12:52:22 +0000337 if (err->error == 0)
paul718e3742002-12-13 20:15:29 +0000338 {
paul7021c422003-07-15 12:52:22 +0000339 if (IS_ZEBRA_DEBUG_KERNEL)
340 {
hasso1ada8192005-06-12 11:28:18 +0000341 zlog_debug ("%s: %s ACK: type=%s(%u), seq=%u, pid=%u",
paul7021c422003-07-15 12:52:22 +0000342 __FUNCTION__, nl->name,
343 lookup (nlmsg_str, err->msg.nlmsg_type),
344 err->msg.nlmsg_type, err->msg.nlmsg_seq,
345 err->msg.nlmsg_pid);
paul718e3742002-12-13 20:15:29 +0000346 }
paul7021c422003-07-15 12:52:22 +0000347
348 /* return if not a multipart message, otherwise continue */
349 if (!(h->nlmsg_flags & NLM_F_MULTI))
350 {
351 return 0;
paul718e3742002-12-13 20:15:29 +0000352 }
paul7021c422003-07-15 12:52:22 +0000353 continue;
paul718e3742002-12-13 20:15:29 +0000354 }
paul7021c422003-07-15 12:52:22 +0000355
paul718e3742002-12-13 20:15:29 +0000356 if (h->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr)))
paul7021c422003-07-15 12:52:22 +0000357 {
358 zlog (NULL, LOG_ERR, "%s error: message truncated",
359 nl->name);
360 return -1;
361 }
pauld753e9e2003-01-22 19:45:50 +0000362
Stephen Hemminger898987e2008-08-17 16:56:15 +0100363 /* Deal with errors that occur because of races in link handling */
Feng Lu758fb8f2014-07-03 18:23:09 +0800364 if (nl == &zvrf->netlink_cmd
Stephen Hemminger898987e2008-08-17 16:56:15 +0100365 && ((msg_type == RTM_DELROUTE &&
366 (-errnum == ENODEV || -errnum == ESRCH))
367 || (msg_type == RTM_NEWROUTE && -errnum == EEXIST)))
368 {
369 if (IS_ZEBRA_DEBUG_KERNEL)
370 zlog_debug ("%s: error: %s type=%s(%u), seq=%u, pid=%u",
371 nl->name, safe_strerror (-errnum),
372 lookup (nlmsg_str, msg_type),
373 msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid);
374 return 0;
375 }
paul718e3742002-12-13 20:15:29 +0000376
Stephen Hemminger898987e2008-08-17 16:56:15 +0100377 zlog_err ("%s error: %s, type=%s(%u), seq=%u, pid=%u",
378 nl->name, safe_strerror (-errnum),
379 lookup (nlmsg_str, msg_type),
380 msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid);
paul7021c422003-07-15 12:52:22 +0000381 return -1;
382 }
paul718e3742002-12-13 20:15:29 +0000383
paul7021c422003-07-15 12:52:22 +0000384 /* OK we got netlink message. */
385 if (IS_ZEBRA_DEBUG_KERNEL)
hasso1ada8192005-06-12 11:28:18 +0000386 zlog_debug ("netlink_parse_info: %s type %s(%u), seq=%u, pid=%u",
paul7021c422003-07-15 12:52:22 +0000387 nl->name,
388 lookup (nlmsg_str, h->nlmsg_type), h->nlmsg_type,
389 h->nlmsg_seq, h->nlmsg_pid);
390
Christian Franke599da952013-01-24 14:04:43 +0000391 /* skip unsolicited messages originating from command socket
392 * linux sets the originators port-id for {NEW|DEL}ADDR messages,
393 * so this has to be checked here. */
Feng Lu758fb8f2014-07-03 18:23:09 +0800394 if (nl != &zvrf->netlink_cmd
395 && h->nlmsg_pid == zvrf->netlink_cmd.snl.nl_pid
Christian Franke599da952013-01-24 14:04:43 +0000396 && (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR))
paul7021c422003-07-15 12:52:22 +0000397 {
398 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000399 zlog_debug ("netlink_parse_info: %s packet comes from %s",
Feng Lu758fb8f2014-07-03 18:23:09 +0800400 zvrf->netlink_cmd.name, nl->name);
paul7021c422003-07-15 12:52:22 +0000401 continue;
402 }
403
Feng Lu758fb8f2014-07-03 18:23:09 +0800404 error = (*filter) (&snl, h, zvrf->vrf_id);
paul7021c422003-07-15 12:52:22 +0000405 if (error < 0)
406 {
407 zlog (NULL, LOG_ERR, "%s filter function error", nl->name);
408 ret = error;
409 }
410 }
paul718e3742002-12-13 20:15:29 +0000411
412 /* After error care. */
413 if (msg.msg_flags & MSG_TRUNC)
paul7021c422003-07-15 12:52:22 +0000414 {
Paul Jakma6dbb58c2017-02-08 15:05:06 +0000415 zlog (NULL, LOG_ERR, "%s error: message truncated!", nl->name);
416 zlog (NULL, LOG_ERR,
417 "Must restart with larger --nl-bufsize value!");
paul7021c422003-07-15 12:52:22 +0000418 continue;
419 }
paul718e3742002-12-13 20:15:29 +0000420 if (status)
paul7021c422003-07-15 12:52:22 +0000421 {
422 zlog (NULL, LOG_ERR, "%s error: data remnant size %d", nl->name,
423 status);
424 return -1;
425 }
paul718e3742002-12-13 20:15:29 +0000426 }
427 return ret;
428}
429
430/* Utility function for parse rtattr. */
431static void
paul7021c422003-07-15 12:52:22 +0000432netlink_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta,
433 int len)
paul718e3742002-12-13 20:15:29 +0000434{
paul7021c422003-07-15 12:52:22 +0000435 while (RTA_OK (rta, len))
paul718e3742002-12-13 20:15:29 +0000436 {
437 if (rta->rta_type <= max)
paul7021c422003-07-15 12:52:22 +0000438 tb[rta->rta_type] = rta;
439 rta = RTA_NEXT (rta, len);
paul718e3742002-12-13 20:15:29 +0000440 }
441}
442
Josh Bailey26e2ae32012-03-22 01:09:21 -0700443/* Utility function to parse hardware link-layer address and update ifp */
444static void
445netlink_interface_update_hw_addr (struct rtattr **tb, struct interface *ifp)
446{
447 int i;
448
449 if (tb[IFLA_ADDRESS])
450 {
451 int hw_addr_len;
452
453 hw_addr_len = RTA_PAYLOAD (tb[IFLA_ADDRESS]);
454
455 if (hw_addr_len > INTERFACE_HWADDR_MAX)
456 zlog_warn ("Hardware address is too large: %d", hw_addr_len);
457 else
458 {
459 ifp->hw_addr_len = hw_addr_len;
460 memcpy (ifp->hw_addr, RTA_DATA (tb[IFLA_ADDRESS]), hw_addr_len);
461
462 for (i = 0; i < hw_addr_len; i++)
463 if (ifp->hw_addr[i] != 0)
464 break;
465
466 if (i == hw_addr_len)
467 ifp->hw_addr_len = 0;
468 else
469 ifp->hw_addr_len = hw_addr_len;
470 }
471 }
472}
473
Timo Teräs954c7d62016-01-15 17:36:33 +0200474static enum zebra_link_type
475netlink_to_zebra_link_type (unsigned int hwt)
476{
477 switch (hwt)
478 {
479 case ARPHRD_ETHER: return ZEBRA_LLT_ETHER;
480 case ARPHRD_EETHER: return ZEBRA_LLT_EETHER;
481 case ARPHRD_AX25: return ZEBRA_LLT_AX25;
482 case ARPHRD_PRONET: return ZEBRA_LLT_PRONET;
483 case ARPHRD_IEEE802: return ZEBRA_LLT_IEEE802;
484 case ARPHRD_ARCNET: return ZEBRA_LLT_ARCNET;
485 case ARPHRD_APPLETLK: return ZEBRA_LLT_APPLETLK;
486 case ARPHRD_DLCI: return ZEBRA_LLT_DLCI;
487 case ARPHRD_ATM: return ZEBRA_LLT_ATM;
488 case ARPHRD_METRICOM: return ZEBRA_LLT_METRICOM;
489 case ARPHRD_IEEE1394: return ZEBRA_LLT_IEEE1394;
490 case ARPHRD_EUI64: return ZEBRA_LLT_EUI64;
491 case ARPHRD_INFINIBAND: return ZEBRA_LLT_INFINIBAND;
492 case ARPHRD_SLIP: return ZEBRA_LLT_SLIP;
493 case ARPHRD_CSLIP: return ZEBRA_LLT_CSLIP;
494 case ARPHRD_SLIP6: return ZEBRA_LLT_SLIP6;
495 case ARPHRD_CSLIP6: return ZEBRA_LLT_CSLIP6;
496 case ARPHRD_RSRVD: return ZEBRA_LLT_RSRVD;
497 case ARPHRD_ADAPT: return ZEBRA_LLT_ADAPT;
498 case ARPHRD_ROSE: return ZEBRA_LLT_ROSE;
499 case ARPHRD_X25: return ZEBRA_LLT_X25;
500 case ARPHRD_PPP: return ZEBRA_LLT_PPP;
501 case ARPHRD_CISCO: return ZEBRA_LLT_CHDLC;
502 case ARPHRD_LAPB: return ZEBRA_LLT_LAPB;
503 case ARPHRD_RAWHDLC: return ZEBRA_LLT_RAWHDLC;
504 case ARPHRD_TUNNEL: return ZEBRA_LLT_IPIP;
505 case ARPHRD_TUNNEL6: return ZEBRA_LLT_IPIP6;
506 case ARPHRD_FRAD: return ZEBRA_LLT_FRAD;
507 case ARPHRD_SKIP: return ZEBRA_LLT_SKIP;
508 case ARPHRD_LOOPBACK: return ZEBRA_LLT_LOOPBACK;
509 case ARPHRD_LOCALTLK: return ZEBRA_LLT_LOCALTLK;
510 case ARPHRD_FDDI: return ZEBRA_LLT_FDDI;
511 case ARPHRD_SIT: return ZEBRA_LLT_SIT;
512 case ARPHRD_IPDDP: return ZEBRA_LLT_IPDDP;
513 case ARPHRD_IPGRE: return ZEBRA_LLT_IPGRE;
514 case ARPHRD_PIMREG: return ZEBRA_LLT_PIMREG;
515 case ARPHRD_HIPPI: return ZEBRA_LLT_HIPPI;
516 case ARPHRD_ECONET: return ZEBRA_LLT_ECONET;
517 case ARPHRD_IRDA: return ZEBRA_LLT_IRDA;
518 case ARPHRD_FCPP: return ZEBRA_LLT_FCPP;
519 case ARPHRD_FCAL: return ZEBRA_LLT_FCAL;
520 case ARPHRD_FCPL: return ZEBRA_LLT_FCPL;
521 case ARPHRD_FCFABRIC: return ZEBRA_LLT_FCFABRIC;
522 case ARPHRD_IEEE802_TR: return ZEBRA_LLT_IEEE802_TR;
523 case ARPHRD_IEEE80211: return ZEBRA_LLT_IEEE80211;
524 case ARPHRD_IEEE802154: return ZEBRA_LLT_IEEE802154;
525#ifdef ARPHRD_IP6GRE
526 case ARPHRD_IP6GRE: return ZEBRA_LLT_IP6GRE;
527#endif
528#ifdef ARPHRD_IEEE802154_PHY
529 case ARPHRD_IEEE802154_PHY: return ZEBRA_LLT_IEEE802154_PHY;
530#endif
531
532 default: return ZEBRA_LLT_UNKNOWN;
533 }
534}
535
paul718e3742002-12-13 20:15:29 +0000536/* Called from interface_lookup_netlink(). This function is only used
537 during bootstrap. */
Stephen Hemminger6072b242008-08-14 16:52:26 +0100538static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800539netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h,
540 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000541{
542 int len;
543 struct ifinfomsg *ifi;
544 struct rtattr *tb[IFLA_MAX + 1];
545 struct interface *ifp;
546 char *name;
paul718e3742002-12-13 20:15:29 +0000547
548 ifi = NLMSG_DATA (h);
549
550 if (h->nlmsg_type != RTM_NEWLINK)
551 return 0;
552
553 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
554 if (len < 0)
555 return -1;
556
557 /* Looking up interface name. */
558 memset (tb, 0, sizeof tb);
559 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
paulc15cb242005-01-24 09:05:27 +0000560
paul1e193152005-02-14 23:53:05 +0000561#ifdef IFLA_WIRELESS
paulc15cb242005-01-24 09:05:27 +0000562 /* check for wireless messages to ignore */
563 if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
564 {
565 if (IS_ZEBRA_DEBUG_KERNEL)
566 zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__);
567 return 0;
568 }
paul1e193152005-02-14 23:53:05 +0000569#endif /* IFLA_WIRELESS */
paulc15cb242005-01-24 09:05:27 +0000570
paul718e3742002-12-13 20:15:29 +0000571 if (tb[IFLA_IFNAME] == NULL)
572 return -1;
paul7021c422003-07-15 12:52:22 +0000573 name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
paul718e3742002-12-13 20:15:29 +0000574
575 /* Add interface. */
Feng Lu758fb8f2014-07-03 18:23:09 +0800576 ifp = if_get_by_name_vrf (name, vrf_id);
ajsd2fc8892005-04-02 18:38:43 +0000577 set_ifindex(ifp, ifi->ifi_index);
paul718e3742002-12-13 20:15:29 +0000578 ifp->flags = ifi->ifi_flags & 0x0000fffff;
Stephen Hemminger4308abb2008-12-01 14:19:38 -0800579 ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]);
Brett Cipherydb19c852013-10-03 13:48:54 +0000580 ifp->metric = 0;
paul718e3742002-12-13 20:15:29 +0000581
582 /* Hardware type and address. */
Timo Teräs954c7d62016-01-15 17:36:33 +0200583 ifp->ll_type = netlink_to_zebra_link_type (ifi->ifi_type);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700584 netlink_interface_update_hw_addr (tb, ifp);
paul718e3742002-12-13 20:15:29 +0000585
586 if_add_update (ifp);
587
588 return 0;
589}
590
591/* Lookup interface IPv4/IPv6 address. */
Stephen Hemminger6072b242008-08-14 16:52:26 +0100592static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800593netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h,
594 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000595{
596 int len;
597 struct ifaddrmsg *ifa;
paul7021c422003-07-15 12:52:22 +0000598 struct rtattr *tb[IFA_MAX + 1];
paul718e3742002-12-13 20:15:29 +0000599 struct interface *ifp;
Andrew J. Schorre4529632006-12-12 19:18:21 +0000600 void *addr;
601 void *broad;
paul718e3742002-12-13 20:15:29 +0000602 u_char flags = 0;
603 char *label = NULL;
604
605 ifa = NLMSG_DATA (h);
606
paul7021c422003-07-15 12:52:22 +0000607 if (ifa->ifa_family != AF_INET
paul718e3742002-12-13 20:15:29 +0000608#ifdef HAVE_IPV6
609 && ifa->ifa_family != AF_INET6
610#endif /* HAVE_IPV6 */
paul7021c422003-07-15 12:52:22 +0000611 )
paul718e3742002-12-13 20:15:29 +0000612 return 0;
613
614 if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
615 return 0;
616
paul7021c422003-07-15 12:52:22 +0000617 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifaddrmsg));
paul718e3742002-12-13 20:15:29 +0000618 if (len < 0)
619 return -1;
620
621 memset (tb, 0, sizeof tb);
622 netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len);
623
Feng Lu758fb8f2014-07-03 18:23:09 +0800624 ifp = if_lookup_by_index_vrf (ifa->ifa_index, vrf_id);
paul718e3742002-12-13 20:15:29 +0000625 if (ifp == NULL)
626 {
Feng Lu758fb8f2014-07-03 18:23:09 +0800627 zlog_err ("netlink_interface_addr can't find interface by index %d vrf %u",
628 ifa->ifa_index, vrf_id);
paul718e3742002-12-13 20:15:29 +0000629 return -1;
630 }
631
paul7021c422003-07-15 12:52:22 +0000632 if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */
paul718e3742002-12-13 20:15:29 +0000633 {
paul00df0c12002-12-13 21:07:36 +0000634 char buf[BUFSIZ];
Feng Lu758fb8f2014-07-03 18:23:09 +0800635 zlog_debug ("netlink_interface_addr %s %s vrf %u:",
636 lookup (nlmsg_str, h->nlmsg_type), ifp->name, vrf_id);
paul718e3742002-12-13 20:15:29 +0000637 if (tb[IFA_LOCAL])
hasso206d8052005-04-09 16:38:51 +0000638 zlog_debug (" IFA_LOCAL %s/%d",
639 inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]),
640 buf, BUFSIZ), ifa->ifa_prefixlen);
paul718e3742002-12-13 20:15:29 +0000641 if (tb[IFA_ADDRESS])
hasso206d8052005-04-09 16:38:51 +0000642 zlog_debug (" IFA_ADDRESS %s/%d",
643 inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_ADDRESS]),
644 buf, BUFSIZ), ifa->ifa_prefixlen);
paul718e3742002-12-13 20:15:29 +0000645 if (tb[IFA_BROADCAST])
hasso206d8052005-04-09 16:38:51 +0000646 zlog_debug (" IFA_BROADCAST %s/%d",
647 inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_BROADCAST]),
648 buf, BUFSIZ), ifa->ifa_prefixlen);
paul00df0c12002-12-13 21:07:36 +0000649 if (tb[IFA_LABEL] && strcmp (ifp->name, RTA_DATA (tb[IFA_LABEL])))
ajsb6178002004-12-07 21:12:56 +0000650 zlog_debug (" IFA_LABEL %s", (char *)RTA_DATA (tb[IFA_LABEL]));
pauld34b8992006-01-17 18:03:04 +0000651
652 if (tb[IFA_CACHEINFO])
653 {
654 struct ifa_cacheinfo *ci = RTA_DATA (tb[IFA_CACHEINFO]);
655 zlog_debug (" IFA_CACHEINFO pref %d, valid %d",
656 ci->ifa_prefered, ci->ifa_valid);
657 }
paul718e3742002-12-13 20:15:29 +0000658 }
paul31a476c2003-09-29 19:54:53 +0000659
Andrew J. Schorre4529632006-12-12 19:18:21 +0000660 /* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */
661 if (tb[IFA_LOCAL] == NULL)
662 tb[IFA_LOCAL] = tb[IFA_ADDRESS];
paul31a476c2003-09-29 19:54:53 +0000663 if (tb[IFA_ADDRESS] == NULL)
664 tb[IFA_ADDRESS] = tb[IFA_LOCAL];
665
Andrew J. Schorre4529632006-12-12 19:18:21 +0000666 /* local interface address */
667 addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL);
668
669 /* is there a peer address? */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000670 if (tb[IFA_ADDRESS] &&
vize068fd772007-08-10 06:25:20 +0000671 memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_ADDRESS])))
paul7021c422003-07-15 12:52:22 +0000672 {
Andrew J. Schorre4529632006-12-12 19:18:21 +0000673 broad = RTA_DATA(tb[IFA_ADDRESS]);
674 SET_FLAG (flags, ZEBRA_IFA_PEER);
paul7021c422003-07-15 12:52:22 +0000675 }
paul31a476c2003-09-29 19:54:53 +0000676 else
Andrew J. Schorre4529632006-12-12 19:18:21 +0000677 /* seeking a broadcast address */
678 broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST]) : NULL);
paul00df0c12002-12-13 21:07:36 +0000679
Paul Jakma27b47252006-07-02 16:38:54 +0000680 /* addr is primary key, SOL if we don't have one */
681 if (addr == NULL)
682 {
683 zlog_debug ("%s: NULL address", __func__);
684 return -1;
685 }
686
paul718e3742002-12-13 20:15:29 +0000687 /* Flags. */
688 if (ifa->ifa_flags & IFA_F_SECONDARY)
689 SET_FLAG (flags, ZEBRA_IFA_SECONDARY);
690
691 /* Label */
692 if (tb[IFA_LABEL])
693 label = (char *) RTA_DATA (tb[IFA_LABEL]);
694
695 if (ifp && label && strcmp (ifp->name, label) == 0)
696 label = NULL;
697
698 /* Register interface address to the interface. */
699 if (ifa->ifa_family == AF_INET)
700 {
paul7021c422003-07-15 12:52:22 +0000701 if (h->nlmsg_type == RTM_NEWADDR)
702 connected_add_ipv4 (ifp, flags,
703 (struct in_addr *) addr, ifa->ifa_prefixlen,
704 (struct in_addr *) broad, label);
705 else
706 connected_delete_ipv4 (ifp, flags,
707 (struct in_addr *) addr, ifa->ifa_prefixlen,
paul0752ef02005-11-03 12:35:21 +0000708 (struct in_addr *) broad);
paul718e3742002-12-13 20:15:29 +0000709 }
710#ifdef HAVE_IPV6
711 if (ifa->ifa_family == AF_INET6)
712 {
713 if (h->nlmsg_type == RTM_NEWADDR)
Andrew J. Schorre4529632006-12-12 19:18:21 +0000714 connected_add_ipv6 (ifp, flags,
paul7021c422003-07-15 12:52:22 +0000715 (struct in6_addr *) addr, ifa->ifa_prefixlen,
paul0752ef02005-11-03 12:35:21 +0000716 (struct in6_addr *) broad, label);
paul718e3742002-12-13 20:15:29 +0000717 else
paul7021c422003-07-15 12:52:22 +0000718 connected_delete_ipv6 (ifp,
719 (struct in6_addr *) addr, ifa->ifa_prefixlen,
720 (struct in6_addr *) broad);
paul718e3742002-12-13 20:15:29 +0000721 }
paul7021c422003-07-15 12:52:22 +0000722#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +0000723
724 return 0;
725}
726
727/* Looking up routing table by netlink interface. */
Stephen Hemminger6072b242008-08-14 16:52:26 +0100728static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800729netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
730 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000731{
732 int len;
733 struct rtmsg *rtm;
paul7021c422003-07-15 12:52:22 +0000734 struct rtattr *tb[RTA_MAX + 1];
paul718e3742002-12-13 20:15:29 +0000735 u_char flags = 0;
paul7021c422003-07-15 12:52:22 +0000736
737 char anyaddr[16] = { 0 };
paul718e3742002-12-13 20:15:29 +0000738
739 int index;
740 int table;
Timo Teräsb11f3b52015-11-02 16:50:07 +0200741 u_int32_t mtu = 0;
hasso34195bf2004-04-06 12:07:06 +0000742
paul718e3742002-12-13 20:15:29 +0000743 void *dest;
744 void *gate;
Paul Jakma7514fb72007-05-02 16:05:35 +0000745 void *src;
paul718e3742002-12-13 20:15:29 +0000746
747 rtm = NLMSG_DATA (h);
748
749 if (h->nlmsg_type != RTM_NEWROUTE)
750 return 0;
751 if (rtm->rtm_type != RTN_UNICAST)
752 return 0;
753
754 table = rtm->rtm_table;
paul7021c422003-07-15 12:52:22 +0000755#if 0 /* we weed them out later in rib_weed_tables () */
paulb21b19c2003-06-15 01:28:29 +0000756 if (table != RT_TABLE_MAIN && table != zebrad.rtm_table_default)
paul718e3742002-12-13 20:15:29 +0000757 return 0;
758#endif
759
paul7021c422003-07-15 12:52:22 +0000760 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
paul718e3742002-12-13 20:15:29 +0000761 if (len < 0)
762 return -1;
763
764 memset (tb, 0, sizeof tb);
765 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
766
767 if (rtm->rtm_flags & RTM_F_CLONED)
768 return 0;
769 if (rtm->rtm_protocol == RTPROT_REDIRECT)
770 return 0;
771 if (rtm->rtm_protocol == RTPROT_KERNEL)
772 return 0;
773
774 if (rtm->rtm_src_len != 0)
775 return 0;
776
777 /* Route which inserted by Zebra. */
778 if (rtm->rtm_protocol == RTPROT_ZEBRA)
779 flags |= ZEBRA_FLAG_SELFROUTE;
paul7021c422003-07-15 12:52:22 +0000780
paul718e3742002-12-13 20:15:29 +0000781 index = 0;
782 dest = NULL;
783 gate = NULL;
Paul Jakma7514fb72007-05-02 16:05:35 +0000784 src = NULL;
paul718e3742002-12-13 20:15:29 +0000785
786 if (tb[RTA_OIF])
787 index = *(int *) RTA_DATA (tb[RTA_OIF]);
788
789 if (tb[RTA_DST])
790 dest = RTA_DATA (tb[RTA_DST]);
791 else
792 dest = anyaddr;
793
Paul Jakma7514fb72007-05-02 16:05:35 +0000794 if (tb[RTA_PREFSRC])
795 src = RTA_DATA (tb[RTA_PREFSRC]);
796
paul718e3742002-12-13 20:15:29 +0000797 if (tb[RTA_GATEWAY])
798 gate = RTA_DATA (tb[RTA_GATEWAY]);
799
Timo Teräsb11f3b52015-11-02 16:50:07 +0200800 if (tb[RTA_METRICS])
801 {
802 struct rtattr *mxrta[RTAX_MAX+1];
803
804 memset (mxrta, 0, sizeof mxrta);
805 netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),
806 RTA_PAYLOAD(tb[RTA_METRICS]));
807
808 if (mxrta[RTAX_MTU])
809 mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]);
810 }
811
paul718e3742002-12-13 20:15:29 +0000812 if (rtm->rtm_family == AF_INET)
813 {
814 struct prefix_ipv4 p;
815 p.family = AF_INET;
816 memcpy (&p.prefix, dest, 4);
817 p.prefixlen = rtm->rtm_dst_len;
818
Josh Bailey26e2ae32012-03-22 01:09:21 -0700819 if (!tb[RTA_MULTIPATH])
820 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index,
Timo Teräs4d3ae712016-01-15 17:36:32 +0200821 vrf_id, table, 0, mtu, 0, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700822 else
823 {
824 /* This is a multipath route */
825
826 struct rib *rib;
827 struct rtnexthop *rtnh =
828 (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
829
830 len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
831
832 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
833 rib->type = ZEBRA_ROUTE_KERNEL;
834 rib->distance = 0;
835 rib->flags = flags;
Timo Teräs4d3ae712016-01-15 17:36:32 +0200836 rib->metric = 0;
Timo Teräsb11f3b52015-11-02 16:50:07 +0200837 rib->mtu = mtu;
Feng Lu758fb8f2014-07-03 18:23:09 +0800838 rib->vrf_id = vrf_id;
Josh Bailey26e2ae32012-03-22 01:09:21 -0700839 rib->table = table;
840 rib->nexthop_num = 0;
841 rib->uptime = time (NULL);
842
843 for (;;)
844 {
845 if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
846 break;
847
Josh Bailey26e2ae32012-03-22 01:09:21 -0700848 index = rtnh->rtnh_ifindex;
849 gate = 0;
850 if (rtnh->rtnh_len > sizeof (*rtnh))
851 {
852 memset (tb, 0, sizeof (tb));
853 netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
854 rtnh->rtnh_len - sizeof (*rtnh));
855 if (tb[RTA_GATEWAY])
856 gate = RTA_DATA (tb[RTA_GATEWAY]);
857 }
858
859 if (gate)
860 {
861 if (index)
Pradosh Mohapatra60cc9592015-11-09 20:21:41 -0500862 rib_nexthop_ipv4_ifindex_add (rib, gate, src, index);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700863 else
Pradosh Mohapatra60cc9592015-11-09 20:21:41 -0500864 rib_nexthop_ipv4_add (rib, gate, src);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700865 }
866 else
Pradosh Mohapatra60cc9592015-11-09 20:21:41 -0500867 rib_nexthop_ifindex_add (rib, index);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700868
869 len -= NLMSG_ALIGN(rtnh->rtnh_len);
870 rtnh = RTNH_NEXT(rtnh);
871 }
872
873 if (rib->nexthop_num == 0)
874 XFREE (MTYPE_RIB, rib);
875 else
Avneesh Sachdev14d2bba2012-04-11 23:51:08 -0700876 rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700877 }
paul718e3742002-12-13 20:15:29 +0000878 }
879#ifdef HAVE_IPV6
880 if (rtm->rtm_family == AF_INET6)
881 {
882 struct prefix_ipv6 p;
883 p.family = AF_INET6;
884 memcpy (&p.prefix, dest, 16);
885 p.prefixlen = rtm->rtm_dst_len;
886
Feng Lu758fb8f2014-07-03 18:23:09 +0800887 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, vrf_id,
Timo Teräs4d3ae712016-01-15 17:36:32 +0200888 table, 0, mtu, 0, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000889 }
890#endif /* HAVE_IPV6 */
891
892 return 0;
893}
894
Stephen Hemminger1423c802008-08-14 17:59:25 +0100895static const struct message rtproto_str[] = {
paul718e3742002-12-13 20:15:29 +0000896 {RTPROT_REDIRECT, "redirect"},
897 {RTPROT_KERNEL, "kernel"},
898 {RTPROT_BOOT, "boot"},
899 {RTPROT_STATIC, "static"},
900 {RTPROT_GATED, "GateD"},
901 {RTPROT_RA, "router advertisement"},
902 {RTPROT_MRT, "MRT"},
903 {RTPROT_ZEBRA, "Zebra"},
904#ifdef RTPROT_BIRD
905 {RTPROT_BIRD, "BIRD"},
906#endif /* RTPROT_BIRD */
907 {0, NULL}
908};
909
910/* Routing information change from the kernel. */
Stephen Hemminger6072b242008-08-14 16:52:26 +0100911static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800912netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
913 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000914{
915 int len;
916 struct rtmsg *rtm;
paul7021c422003-07-15 12:52:22 +0000917 struct rtattr *tb[RTA_MAX + 1];
James Li92992c62015-11-09 20:21:57 -0500918 u_char zebra_flags = 0;
paul7021c422003-07-15 12:52:22 +0000919
920 char anyaddr[16] = { 0 };
paul718e3742002-12-13 20:15:29 +0000921
922 int index;
923 int table;
Timo Teräsb11f3b52015-11-02 16:50:07 +0200924 u_int32_t mtu = 0;
Dmitry Popov83d16142011-09-11 13:48:25 +0400925
paul718e3742002-12-13 20:15:29 +0000926 void *dest;
927 void *gate;
Paul Jakma7514fb72007-05-02 16:05:35 +0000928 void *src;
paul718e3742002-12-13 20:15:29 +0000929
930 rtm = NLMSG_DATA (h);
931
paul7021c422003-07-15 12:52:22 +0000932 if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
paul718e3742002-12-13 20:15:29 +0000933 {
934 /* If this is not route add/delete message print warning. */
Feng Lu758fb8f2014-07-03 18:23:09 +0800935 zlog_warn ("Kernel message: %d vrf %u\n", h->nlmsg_type, vrf_id);
paul718e3742002-12-13 20:15:29 +0000936 return 0;
937 }
938
939 /* Connected route. */
940 if (IS_ZEBRA_DEBUG_KERNEL)
Feng Lu758fb8f2014-07-03 18:23:09 +0800941 zlog_debug ("%s %s %s proto %s vrf %u",
paul7021c422003-07-15 12:52:22 +0000942 h->nlmsg_type ==
943 RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
944 rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",
945 rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast",
Feng Lu758fb8f2014-07-03 18:23:09 +0800946 lookup (rtproto_str, rtm->rtm_protocol),
947 vrf_id);
paul718e3742002-12-13 20:15:29 +0000948
949 if (rtm->rtm_type != RTN_UNICAST)
950 {
951 return 0;
952 }
953
954 table = rtm->rtm_table;
paulb21b19c2003-06-15 01:28:29 +0000955 if (table != RT_TABLE_MAIN && table != zebrad.rtm_table_default)
paul718e3742002-12-13 20:15:29 +0000956 {
957 return 0;
958 }
959
paul7021c422003-07-15 12:52:22 +0000960 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
paul718e3742002-12-13 20:15:29 +0000961 if (len < 0)
962 return -1;
963
964 memset (tb, 0, sizeof tb);
965 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
966
967 if (rtm->rtm_flags & RTM_F_CLONED)
968 return 0;
969 if (rtm->rtm_protocol == RTPROT_REDIRECT)
970 return 0;
971 if (rtm->rtm_protocol == RTPROT_KERNEL)
972 return 0;
973
974 if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)
975 return 0;
James Li92992c62015-11-09 20:21:57 -0500976 if (rtm->rtm_protocol == RTPROT_ZEBRA)
977 SET_FLAG(zebra_flags, ZEBRA_FLAG_SELFROUTE);
paul718e3742002-12-13 20:15:29 +0000978
979 if (rtm->rtm_src_len != 0)
980 {
Feng Lu758fb8f2014-07-03 18:23:09 +0800981 zlog_warn ("netlink_route_change(): no src len, vrf %u", vrf_id);
paul718e3742002-12-13 20:15:29 +0000982 return 0;
983 }
paul7021c422003-07-15 12:52:22 +0000984
paul718e3742002-12-13 20:15:29 +0000985 index = 0;
986 dest = NULL;
987 gate = NULL;
Paul Jakma7514fb72007-05-02 16:05:35 +0000988 src = NULL;
paul718e3742002-12-13 20:15:29 +0000989
990 if (tb[RTA_OIF])
991 index = *(int *) RTA_DATA (tb[RTA_OIF]);
992
993 if (tb[RTA_DST])
994 dest = RTA_DATA (tb[RTA_DST]);
995 else
996 dest = anyaddr;
997
998 if (tb[RTA_GATEWAY])
999 gate = RTA_DATA (tb[RTA_GATEWAY]);
1000
Paul Jakma7514fb72007-05-02 16:05:35 +00001001 if (tb[RTA_PREFSRC])
1002 src = RTA_DATA (tb[RTA_PREFSRC]);
1003
Timo Teräsb11f3b52015-11-02 16:50:07 +02001004 if (h->nlmsg_type == RTM_NEWROUTE)
1005 {
Timo Teräsb11f3b52015-11-02 16:50:07 +02001006 if (tb[RTA_METRICS])
1007 {
1008 struct rtattr *mxrta[RTAX_MAX+1];
1009
1010 memset (mxrta, 0, sizeof mxrta);
1011 netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),
1012 RTA_PAYLOAD(tb[RTA_METRICS]));
1013
1014 if (mxrta[RTAX_MTU])
1015 mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]);
1016 }
1017 }
Josh Bailey26e2ae32012-03-22 01:09:21 -07001018
paul718e3742002-12-13 20:15:29 +00001019 if (rtm->rtm_family == AF_INET)
1020 {
1021 struct prefix_ipv4 p;
1022 p.family = AF_INET;
1023 memcpy (&p.prefix, dest, 4);
1024 p.prefixlen = rtm->rtm_dst_len;
1025
1026 if (IS_ZEBRA_DEBUG_KERNEL)
paul7021c422003-07-15 12:52:22 +00001027 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001028 char buf[PREFIX_STRLEN];
Feng Lu758fb8f2014-07-03 18:23:09 +08001029 zlog_debug ("%s %s vrf %u",
Timo Teräsbe6335d2015-05-23 11:08:41 +03001030 h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
Feng Lu758fb8f2014-07-03 18:23:09 +08001031 prefix2str (&p, buf, sizeof(buf)), vrf_id);
paul7021c422003-07-15 12:52:22 +00001032 }
paul718e3742002-12-13 20:15:29 +00001033
1034 if (h->nlmsg_type == RTM_NEWROUTE)
Josh Bailey26e2ae32012-03-22 01:09:21 -07001035 {
1036 if (!tb[RTA_MULTIPATH])
Feng Lu758fb8f2014-07-03 18:23:09 +08001037 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, vrf_id,
Timo Teräs4d3ae712016-01-15 17:36:32 +02001038 table, 0, mtu, 0, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -07001039 else
1040 {
1041 /* This is a multipath route */
1042
1043 struct rib *rib;
1044 struct rtnexthop *rtnh =
1045 (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
1046
1047 len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
1048
1049 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1050 rib->type = ZEBRA_ROUTE_KERNEL;
1051 rib->distance = 0;
1052 rib->flags = 0;
Timo Teräs4d3ae712016-01-15 17:36:32 +02001053 rib->metric = 0;
Timo Teräsb11f3b52015-11-02 16:50:07 +02001054 rib->mtu = mtu;
Feng Lu758fb8f2014-07-03 18:23:09 +08001055 rib->vrf_id = vrf_id;
Josh Bailey26e2ae32012-03-22 01:09:21 -07001056 rib->table = table;
1057 rib->nexthop_num = 0;
1058 rib->uptime = time (NULL);
1059
1060 for (;;)
1061 {
1062 if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
1063 break;
1064
Josh Bailey26e2ae32012-03-22 01:09:21 -07001065 index = rtnh->rtnh_ifindex;
1066 gate = 0;
1067 if (rtnh->rtnh_len > sizeof (*rtnh))
1068 {
1069 memset (tb, 0, sizeof (tb));
1070 netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
1071 rtnh->rtnh_len - sizeof (*rtnh));
1072 if (tb[RTA_GATEWAY])
1073 gate = RTA_DATA (tb[RTA_GATEWAY]);
1074 }
1075
1076 if (gate)
1077 {
1078 if (index)
Pradosh Mohapatra60cc9592015-11-09 20:21:41 -05001079 rib_nexthop_ipv4_ifindex_add (rib, gate, src, index);
Josh Bailey26e2ae32012-03-22 01:09:21 -07001080 else
Pradosh Mohapatra60cc9592015-11-09 20:21:41 -05001081 rib_nexthop_ipv4_add (rib, gate, src);
Josh Bailey26e2ae32012-03-22 01:09:21 -07001082 }
1083 else
Pradosh Mohapatra60cc9592015-11-09 20:21:41 -05001084 rib_nexthop_ifindex_add (rib, index);
Josh Bailey26e2ae32012-03-22 01:09:21 -07001085
1086 len -= NLMSG_ALIGN(rtnh->rtnh_len);
1087 rtnh = RTNH_NEXT(rtnh);
1088 }
1089
1090 if (rib->nexthop_num == 0)
1091 XFREE (MTYPE_RIB, rib);
1092 else
Avneesh Sachdev14d2bba2012-04-11 23:51:08 -07001093 rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -07001094 }
1095 }
paul718e3742002-12-13 20:15:29 +00001096 else
James Li92992c62015-11-09 20:21:57 -05001097 rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, gate,
1098 index, vrf_id, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001099 }
1100
1101#ifdef HAVE_IPV6
1102 if (rtm->rtm_family == AF_INET6)
1103 {
1104 struct prefix_ipv6 p;
paul718e3742002-12-13 20:15:29 +00001105
1106 p.family = AF_INET6;
1107 memcpy (&p.prefix, dest, 16);
1108 p.prefixlen = rtm->rtm_dst_len;
1109
1110 if (IS_ZEBRA_DEBUG_KERNEL)
paul7021c422003-07-15 12:52:22 +00001111 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001112 char buf[PREFIX_STRLEN];
Feng Lu758fb8f2014-07-03 18:23:09 +08001113 zlog_debug ("%s %s vrf %u",
Timo Teräsbe6335d2015-05-23 11:08:41 +03001114 h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
Feng Lu758fb8f2014-07-03 18:23:09 +08001115 prefix2str (&p, buf, sizeof(buf)), vrf_id);
paul7021c422003-07-15 12:52:22 +00001116 }
paul718e3742002-12-13 20:15:29 +00001117
1118 if (h->nlmsg_type == RTM_NEWROUTE)
Feng Lu758fb8f2014-07-03 18:23:09 +08001119 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, vrf_id, table,
Timo Teräs4d3ae712016-01-15 17:36:32 +02001120 0, mtu, 0, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001121 else
James Li92992c62015-11-09 20:21:57 -05001122 rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, gate, index, vrf_id,
Feng Lu0d0686f2015-05-22 11:40:02 +02001123 SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001124 }
1125#endif /* HAVE_IPV6 */
1126
1127 return 0;
1128}
1129
Stephen Hemminger6072b242008-08-14 16:52:26 +01001130static int
Feng Lu758fb8f2014-07-03 18:23:09 +08001131netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
1132 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001133{
1134 int len;
1135 struct ifinfomsg *ifi;
paul7021c422003-07-15 12:52:22 +00001136 struct rtattr *tb[IFLA_MAX + 1];
paul718e3742002-12-13 20:15:29 +00001137 struct interface *ifp;
1138 char *name;
1139
1140 ifi = NLMSG_DATA (h);
1141
paul7021c422003-07-15 12:52:22 +00001142 if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
paul718e3742002-12-13 20:15:29 +00001143 {
1144 /* If this is not link add/delete message so print warning. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001145 zlog_warn ("netlink_link_change: wrong kernel message %d vrf %u\n",
1146 h->nlmsg_type, vrf_id);
paul718e3742002-12-13 20:15:29 +00001147 return 0;
1148 }
1149
1150 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
1151 if (len < 0)
1152 return -1;
1153
1154 /* Looking up interface name. */
1155 memset (tb, 0, sizeof tb);
1156 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
paulc15cb242005-01-24 09:05:27 +00001157
paul1e193152005-02-14 23:53:05 +00001158#ifdef IFLA_WIRELESS
paulc15cb242005-01-24 09:05:27 +00001159 /* check for wireless messages to ignore */
1160 if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
1161 {
1162 if (IS_ZEBRA_DEBUG_KERNEL)
Feng Lu758fb8f2014-07-03 18:23:09 +08001163 zlog_debug ("%s: ignoring IFLA_WIRELESS message, vrf %u", __func__,
1164 vrf_id);
paulc15cb242005-01-24 09:05:27 +00001165 return 0;
1166 }
paul1e193152005-02-14 23:53:05 +00001167#endif /* IFLA_WIRELESS */
paulc15cb242005-01-24 09:05:27 +00001168
paul718e3742002-12-13 20:15:29 +00001169 if (tb[IFLA_IFNAME] == NULL)
1170 return -1;
paul7021c422003-07-15 12:52:22 +00001171 name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
paul718e3742002-12-13 20:15:29 +00001172
1173 /* Add interface. */
1174 if (h->nlmsg_type == RTM_NEWLINK)
1175 {
Feng Lu758fb8f2014-07-03 18:23:09 +08001176 ifp = if_lookup_by_name_vrf (name, vrf_id);
paul718e3742002-12-13 20:15:29 +00001177
paul7021c422003-07-15 12:52:22 +00001178 if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1179 {
1180 if (ifp == NULL)
Feng Lu758fb8f2014-07-03 18:23:09 +08001181 ifp = if_get_by_name_vrf (name, vrf_id);
paul718e3742002-12-13 20:15:29 +00001182
ajsd2fc8892005-04-02 18:38:43 +00001183 set_ifindex(ifp, ifi->ifi_index);
paul7021c422003-07-15 12:52:22 +00001184 ifp->flags = ifi->ifi_flags & 0x0000fffff;
paul44145db2004-05-09 11:00:23 +00001185 ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
Brett Cipherydb19c852013-10-03 13:48:54 +00001186 ifp->metric = 0;
paul718e3742002-12-13 20:15:29 +00001187
Josh Bailey26e2ae32012-03-22 01:09:21 -07001188 netlink_interface_update_hw_addr (tb, ifp);
1189
paul7021c422003-07-15 12:52:22 +00001190 /* If new link is added. */
1191 if_add_update (ifp);
1192 }
paul718e3742002-12-13 20:15:29 +00001193 else
paul7021c422003-07-15 12:52:22 +00001194 {
1195 /* Interface status change. */
ajsd2fc8892005-04-02 18:38:43 +00001196 set_ifindex(ifp, ifi->ifi_index);
paul44145db2004-05-09 11:00:23 +00001197 ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
Brett Cipherydb19c852013-10-03 13:48:54 +00001198 ifp->metric = 0;
paul718e3742002-12-13 20:15:29 +00001199
Josh Bailey26e2ae32012-03-22 01:09:21 -07001200 netlink_interface_update_hw_addr (tb, ifp);
1201
paul7021c422003-07-15 12:52:22 +00001202 if (if_is_operative (ifp))
1203 {
1204 ifp->flags = ifi->ifi_flags & 0x0000fffff;
1205 if (!if_is_operative (ifp))
1206 if_down (ifp);
ajsa608bbf2005-03-29 17:03:49 +00001207 else
1208 /* Must notify client daemons of new interface status. */
1209 zebra_interface_up_update (ifp);
paul7021c422003-07-15 12:52:22 +00001210 }
1211 else
1212 {
1213 ifp->flags = ifi->ifi_flags & 0x0000fffff;
1214 if (if_is_operative (ifp))
1215 if_up (ifp);
1216 }
1217 }
paul718e3742002-12-13 20:15:29 +00001218 }
1219 else
1220 {
1221 /* RTM_DELLINK. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001222 ifp = if_lookup_by_name_vrf (name, vrf_id);
paul718e3742002-12-13 20:15:29 +00001223
1224 if (ifp == NULL)
paul7021c422003-07-15 12:52:22 +00001225 {
Feng Lu758fb8f2014-07-03 18:23:09 +08001226 zlog_warn ("interface %s vrf %u is deleted but can't find",
1227 name, vrf_id);
paul7021c422003-07-15 12:52:22 +00001228 return 0;
1229 }
1230
paul718e3742002-12-13 20:15:29 +00001231 if_delete_update (ifp);
1232 }
1233
1234 return 0;
1235}
1236
Stephen Hemminger6072b242008-08-14 16:52:26 +01001237static int
Feng Lu758fb8f2014-07-03 18:23:09 +08001238netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h,
1239 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001240{
Stephen Hemminger3d265b42008-08-16 17:30:39 +01001241 /* JF: Ignore messages that aren't from the kernel */
1242 if ( snl->nl_pid != 0 )
1243 {
1244 zlog ( NULL, LOG_ERR, "Ignoring message from pid %u", snl->nl_pid );
1245 return 0;
1246 }
1247
paul718e3742002-12-13 20:15:29 +00001248 switch (h->nlmsg_type)
1249 {
1250 case RTM_NEWROUTE:
Feng Lu758fb8f2014-07-03 18:23:09 +08001251 return netlink_route_change (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001252 break;
1253 case RTM_DELROUTE:
Feng Lu758fb8f2014-07-03 18:23:09 +08001254 return netlink_route_change (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001255 break;
1256 case RTM_NEWLINK:
Feng Lu758fb8f2014-07-03 18:23:09 +08001257 return netlink_link_change (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001258 break;
1259 case RTM_DELLINK:
Feng Lu758fb8f2014-07-03 18:23:09 +08001260 return netlink_link_change (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001261 break;
1262 case RTM_NEWADDR:
Feng Lu758fb8f2014-07-03 18:23:09 +08001263 return netlink_interface_addr (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001264 break;
1265 case RTM_DELADDR:
Feng Lu758fb8f2014-07-03 18:23:09 +08001266 return netlink_interface_addr (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001267 break;
1268 default:
Feng Lu758fb8f2014-07-03 18:23:09 +08001269 zlog_warn ("Unknown netlink nlmsg_type %d vrf %u\n", h->nlmsg_type,
1270 vrf_id);
paul718e3742002-12-13 20:15:29 +00001271 break;
1272 }
1273 return 0;
1274}
1275
1276/* Interface lookup by netlink socket. */
1277int
Feng Lu758fb8f2014-07-03 18:23:09 +08001278interface_lookup_netlink (struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001279{
1280 int ret;
paul7021c422003-07-15 12:52:22 +00001281
paul718e3742002-12-13 20:15:29 +00001282 /* Get interface information. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001283 ret = netlink_request (AF_PACKET, RTM_GETLINK, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001284 if (ret < 0)
1285 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001286 ret = netlink_parse_info (netlink_interface, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001287 if (ret < 0)
1288 return ret;
1289
1290 /* Get IPv4 address of the interfaces. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001291 ret = netlink_request (AF_INET, RTM_GETADDR, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001292 if (ret < 0)
1293 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001294 ret = netlink_parse_info (netlink_interface_addr, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001295 if (ret < 0)
1296 return ret;
1297
1298#ifdef HAVE_IPV6
1299 /* Get IPv6 address of the interfaces. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001300 ret = netlink_request (AF_INET6, RTM_GETADDR, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001301 if (ret < 0)
1302 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001303 ret = netlink_parse_info (netlink_interface_addr, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001304 if (ret < 0)
1305 return ret;
1306#endif /* HAVE_IPV6 */
1307
1308 return 0;
1309}
1310
1311/* Routing table read function using netlink interface. Only called
1312 bootstrap time. */
1313int
Feng Lu758fb8f2014-07-03 18:23:09 +08001314netlink_route_read (struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001315{
1316 int ret;
paul7021c422003-07-15 12:52:22 +00001317
paul718e3742002-12-13 20:15:29 +00001318 /* Get IPv4 routing table. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001319 ret = netlink_request (AF_INET, RTM_GETROUTE, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001320 if (ret < 0)
1321 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001322 ret = netlink_parse_info (netlink_routing_table, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001323 if (ret < 0)
1324 return ret;
1325
1326#ifdef HAVE_IPV6
1327 /* Get IPv6 routing table. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001328 ret = netlink_request (AF_INET6, RTM_GETROUTE, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001329 if (ret < 0)
1330 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001331 ret = netlink_parse_info (netlink_routing_table, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001332 if (ret < 0)
1333 return ret;
1334#endif /* HAVE_IPV6 */
1335
1336 return 0;
1337}
1338
1339/* Utility function comes from iproute2.
1340 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001341int
Paul Jakma6f235412016-04-05 13:21:20 +01001342addattr_l (struct nlmsghdr *n, size_t maxlen, int type, void *data, size_t alen)
paul718e3742002-12-13 20:15:29 +00001343{
Paul Jakma7aa9dce2014-09-19 14:42:23 +01001344 size_t len;
paul718e3742002-12-13 20:15:29 +00001345 struct rtattr *rta;
1346
paul7021c422003-07-15 12:52:22 +00001347 len = RTA_LENGTH (alen);
paul718e3742002-12-13 20:15:29 +00001348
paul7021c422003-07-15 12:52:22 +00001349 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
paul718e3742002-12-13 20:15:29 +00001350 return -1;
1351
paul7021c422003-07-15 12:52:22 +00001352 rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
paul718e3742002-12-13 20:15:29 +00001353 rta->rta_type = type;
1354 rta->rta_len = len;
paul7021c422003-07-15 12:52:22 +00001355 memcpy (RTA_DATA (rta), data, alen);
paul718e3742002-12-13 20:15:29 +00001356 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1357
1358 return 0;
1359}
1360
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001361int
Paul Jakma6f235412016-04-05 13:21:20 +01001362rta_addattr_l (struct rtattr *rta, size_t maxlen, int type, void *data,
1363 size_t alen)
paul718e3742002-12-13 20:15:29 +00001364{
Paul Jakma6f235412016-04-05 13:21:20 +01001365 size_t len;
paul718e3742002-12-13 20:15:29 +00001366 struct rtattr *subrta;
1367
paul7021c422003-07-15 12:52:22 +00001368 len = RTA_LENGTH (alen);
paul718e3742002-12-13 20:15:29 +00001369
paul7021c422003-07-15 12:52:22 +00001370 if (RTA_ALIGN (rta->rta_len) + len > maxlen)
paul718e3742002-12-13 20:15:29 +00001371 return -1;
1372
paul7021c422003-07-15 12:52:22 +00001373 subrta = (struct rtattr *) (((char *) rta) + RTA_ALIGN (rta->rta_len));
paul718e3742002-12-13 20:15:29 +00001374 subrta->rta_type = type;
1375 subrta->rta_len = len;
paul7021c422003-07-15 12:52:22 +00001376 memcpy (RTA_DATA (subrta), data, alen);
paul718e3742002-12-13 20:15:29 +00001377 rta->rta_len = NLMSG_ALIGN (rta->rta_len) + len;
1378
1379 return 0;
1380}
1381
1382/* Utility function comes from iproute2.
1383 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001384int
Paul Jakma7aa9dce2014-09-19 14:42:23 +01001385addattr32 (struct nlmsghdr *n, size_t maxlen, int type, int data)
paul718e3742002-12-13 20:15:29 +00001386{
Paul Jakma7aa9dce2014-09-19 14:42:23 +01001387 size_t len;
paul718e3742002-12-13 20:15:29 +00001388 struct rtattr *rta;
paul7021c422003-07-15 12:52:22 +00001389
1390 len = RTA_LENGTH (4);
1391
paul718e3742002-12-13 20:15:29 +00001392 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
1393 return -1;
1394
paul7021c422003-07-15 12:52:22 +00001395 rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
paul718e3742002-12-13 20:15:29 +00001396 rta->rta_type = type;
1397 rta->rta_len = len;
paul7021c422003-07-15 12:52:22 +00001398 memcpy (RTA_DATA (rta), &data, 4);
paul718e3742002-12-13 20:15:29 +00001399 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1400
1401 return 0;
1402}
1403
1404static int
Feng Lu758fb8f2014-07-03 18:23:09 +08001405netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h,
1406 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001407{
Feng Lu758fb8f2014-07-03 18:23:09 +08001408 zlog_warn ("netlink_talk: ignoring message type 0x%04x vrf %u", h->nlmsg_type,
1409 vrf_id);
paul718e3742002-12-13 20:15:29 +00001410 return 0;
1411}
1412
1413/* sendmsg() to netlink socket then recvmsg(). */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001414static int
Feng Lu758fb8f2014-07-03 18:23:09 +08001415netlink_talk (struct nlmsghdr *n, struct nlsock *nl, struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001416{
1417 int status;
1418 struct sockaddr_nl snl;
Timo Teräsc299ed72014-07-29 09:41:55 +00001419 struct iovec iov = {
1420 .iov_base = (void *) n,
1421 .iov_len = n->nlmsg_len
1422 };
1423 struct msghdr msg = {
1424 .msg_name = (void *) &snl,
1425 .msg_namelen = sizeof snl,
1426 .msg_iov = &iov,
1427 .msg_iovlen = 1,
1428 };
ajs4be019d2005-01-29 16:12:41 +00001429 int save_errno;
paul7021c422003-07-15 12:52:22 +00001430
paul718e3742002-12-13 20:15:29 +00001431 memset (&snl, 0, sizeof snl);
1432 snl.nl_family = AF_NETLINK;
paul7021c422003-07-15 12:52:22 +00001433
hassob7ed1ec2005-03-31 20:13:49 +00001434 n->nlmsg_seq = ++nl->seq;
paul718e3742002-12-13 20:15:29 +00001435
1436 /* Request an acknowledgement by setting NLM_F_ACK */
1437 n->nlmsg_flags |= NLM_F_ACK;
paul7021c422003-07-15 12:52:22 +00001438
1439 if (IS_ZEBRA_DEBUG_KERNEL)
hassob7ed1ec2005-03-31 20:13:49 +00001440 zlog_debug ("netlink_talk: %s type %s(%u), seq=%u", nl->name,
paul7021c422003-07-15 12:52:22 +00001441 lookup (nlmsg_str, n->nlmsg_type), n->nlmsg_type,
1442 n->nlmsg_seq);
paul718e3742002-12-13 20:15:29 +00001443
1444 /* Send message to netlink interface. */
paul7021c422003-07-15 12:52:22 +00001445 if (zserv_privs.change (ZPRIVS_RAISE))
1446 zlog (NULL, LOG_ERR, "Can't raise privileges");
paul718e3742002-12-13 20:15:29 +00001447 status = sendmsg (nl->sock, &msg, 0);
ajs4be019d2005-01-29 16:12:41 +00001448 save_errno = errno;
paul7021c422003-07-15 12:52:22 +00001449 if (zserv_privs.change (ZPRIVS_LOWER))
1450 zlog (NULL, LOG_ERR, "Can't lower privileges");
1451
paul718e3742002-12-13 20:15:29 +00001452 if (status < 0)
1453 {
1454 zlog (NULL, LOG_ERR, "netlink_talk sendmsg() error: %s",
ajs4be019d2005-01-29 16:12:41 +00001455 safe_strerror (save_errno));
paul718e3742002-12-13 20:15:29 +00001456 return -1;
1457 }
paul7021c422003-07-15 12:52:22 +00001458
paul718e3742002-12-13 20:15:29 +00001459
1460 /*
1461 * Get reply from netlink socket.
1462 * The reply should either be an acknowlegement or an error.
1463 */
Feng Lu758fb8f2014-07-03 18:23:09 +08001464 return netlink_parse_info (netlink_talk_filter, nl, zvrf);
paul718e3742002-12-13 20:15:29 +00001465}
1466
Christian Frankefa713d92013-07-05 15:35:37 +00001467/* This function takes a nexthop as argument and adds
1468 * the appropriate netlink attributes to an existing
1469 * netlink message.
1470 *
1471 * @param routedesc: Human readable description of route type
1472 * (direct/recursive, single-/multipath)
1473 * @param bytelen: Length of addresses in bytes.
1474 * @param nexthop: Nexthop information
1475 * @param nlmsg: nlmsghdr structure to fill in.
1476 * @param req_size: The size allocated for the message.
1477 */
1478static void
1479_netlink_route_build_singlepath(
1480 const char *routedesc,
1481 int bytelen,
1482 struct nexthop *nexthop,
1483 struct nlmsghdr *nlmsg,
Christian Frankee8d3d292013-07-05 15:35:39 +00001484 struct rtmsg *rtmsg,
Christian Frankefa713d92013-07-05 15:35:37 +00001485 size_t req_size)
1486{
Christian Frankee8d3d292013-07-05 15:35:39 +00001487 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
1488 rtmsg->rtm_flags |= RTNH_F_ONLINK;
Christian Frankefa713d92013-07-05 15:35:37 +00001489 if (nexthop->type == NEXTHOP_TYPE_IPV4
1490 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1491 {
1492 addattr_l (nlmsg, req_size, RTA_GATEWAY,
1493 &nexthop->gate.ipv4, bytelen);
1494 if (nexthop->src.ipv4.s_addr)
1495 addattr_l (nlmsg, req_size, RTA_PREFSRC,
1496 &nexthop->src.ipv4, bytelen);
1497
1498 if (IS_ZEBRA_DEBUG_KERNEL)
1499 zlog_debug("netlink_route_multipath() (%s): "
1500 "nexthop via %s if %u",
1501 routedesc,
1502 inet_ntoa (nexthop->gate.ipv4),
1503 nexthop->ifindex);
1504 }
1505#ifdef HAVE_IPV6
1506 if (nexthop->type == NEXTHOP_TYPE_IPV6
1507 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1508 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1509 {
1510 addattr_l (nlmsg, req_size, RTA_GATEWAY,
1511 &nexthop->gate.ipv6, bytelen);
1512
1513 if (IS_ZEBRA_DEBUG_KERNEL)
1514 zlog_debug("netlink_route_multipath() (%s): "
1515 "nexthop via %s if %u",
1516 routedesc,
1517 inet6_ntoa (nexthop->gate.ipv6),
1518 nexthop->ifindex);
1519 }
1520#endif /* HAVE_IPV6 */
1521 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1522 || nexthop->type == NEXTHOP_TYPE_IFNAME
1523 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1524 {
1525 addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
1526
1527 if (nexthop->src.ipv4.s_addr)
1528 addattr_l (nlmsg, req_size, RTA_PREFSRC,
1529 &nexthop->src.ipv4, bytelen);
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 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
1537 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
1538 {
1539 addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
1540
1541 if (IS_ZEBRA_DEBUG_KERNEL)
1542 zlog_debug("netlink_route_multipath() (%s): "
1543 "nexthop via if %u", routedesc, nexthop->ifindex);
1544 }
1545}
1546
1547/* This function takes a nexthop as argument and
1548 * appends to the given rtattr/rtnexthop pair the
1549 * representation of the nexthop. If the nexthop
1550 * defines a preferred source, the src parameter
1551 * will be modified to point to that src, otherwise
1552 * it will be kept unmodified.
1553 *
1554 * @param routedesc: Human readable description of route type
1555 * (direct/recursive, single-/multipath)
1556 * @param bytelen: Length of addresses in bytes.
1557 * @param nexthop: Nexthop information
1558 * @param rta: rtnetlink attribute structure
1559 * @param rtnh: pointer to an rtnetlink nexthop structure
1560 * @param src: pointer pointing to a location where
1561 * the prefsrc should be stored.
1562 */
1563static void
1564_netlink_route_build_multipath(
1565 const char *routedesc,
1566 int bytelen,
1567 struct nexthop *nexthop,
1568 struct rtattr *rta,
1569 struct rtnexthop *rtnh,
1570 union g_addr **src
1571 )
1572{
1573 rtnh->rtnh_len = sizeof (*rtnh);
1574 rtnh->rtnh_flags = 0;
1575 rtnh->rtnh_hops = 0;
1576 rta->rta_len += rtnh->rtnh_len;
1577
Christian Frankee8d3d292013-07-05 15:35:39 +00001578 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
1579 rtnh->rtnh_flags |= RTNH_F_ONLINK;
1580
Christian Frankefa713d92013-07-05 15:35:37 +00001581 if (nexthop->type == NEXTHOP_TYPE_IPV4
1582 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1583 {
1584 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
1585 &nexthop->gate.ipv4, bytelen);
Lu Feng621e2aa2014-07-11 07:52:15 +00001586 rtnh->rtnh_len += sizeof (struct rtattr) + bytelen;
Christian Frankefa713d92013-07-05 15:35:37 +00001587
1588 if (nexthop->src.ipv4.s_addr)
1589 *src = &nexthop->src;
1590
1591 if (IS_ZEBRA_DEBUG_KERNEL)
1592 zlog_debug("netlink_route_multipath() (%s): "
1593 "nexthop via %s if %u",
1594 routedesc,
1595 inet_ntoa (nexthop->gate.ipv4),
1596 nexthop->ifindex);
1597 }
1598#ifdef HAVE_IPV6
1599 if (nexthop->type == NEXTHOP_TYPE_IPV6
1600 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1601 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1602 {
1603 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
1604 &nexthop->gate.ipv6, bytelen);
Lu Feng621e2aa2014-07-11 07:52:15 +00001605 rtnh->rtnh_len += sizeof (struct rtattr) + bytelen;
Christian Frankefa713d92013-07-05 15:35:37 +00001606
1607 if (IS_ZEBRA_DEBUG_KERNEL)
1608 zlog_debug("netlink_route_multipath() (%s): "
1609 "nexthop via %s if %u",
1610 routedesc,
1611 inet6_ntoa (nexthop->gate.ipv6),
1612 nexthop->ifindex);
1613 }
1614#endif /* HAVE_IPV6 */
1615 /* ifindex */
1616 if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1617 || nexthop->type == NEXTHOP_TYPE_IFINDEX
1618 || nexthop->type == NEXTHOP_TYPE_IFNAME)
1619 {
1620 rtnh->rtnh_ifindex = nexthop->ifindex;
1621 if (nexthop->src.ipv4.s_addr)
1622 *src = &nexthop->src;
1623 if (IS_ZEBRA_DEBUG_KERNEL)
1624 zlog_debug("netlink_route_multipath() (%s): "
1625 "nexthop via if %u", routedesc, nexthop->ifindex);
1626 }
1627 else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1628 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1629 {
1630 rtnh->rtnh_ifindex = nexthop->ifindex;
1631
1632 if (IS_ZEBRA_DEBUG_KERNEL)
1633 zlog_debug("netlink_route_multipath() (%s): "
1634 "nexthop via if %u", routedesc, nexthop->ifindex);
1635 }
1636 else
1637 {
1638 rtnh->rtnh_ifindex = 0;
1639 }
1640}
1641
1642/* Log debug information for netlink_route_multipath
1643 * if debug logging is enabled.
1644 *
1645 * @param cmd: Netlink command which is to be processed
1646 * @param p: Prefix for which the change is due
1647 * @param nexthop: Nexthop which is currently processed
1648 * @param routedesc: Semantic annotation for nexthop
1649 * (recursive, multipath, etc.)
1650 * @param family: Address family which the change concerns
1651 */
1652static void
1653_netlink_route_debug(
1654 int cmd,
1655 struct prefix *p,
1656 struct nexthop *nexthop,
1657 const char *routedesc,
Feng Lu758fb8f2014-07-03 18:23:09 +08001658 int family,
1659 struct zebra_vrf *zvrf)
Christian Frankefa713d92013-07-05 15:35:37 +00001660{
1661 if (IS_ZEBRA_DEBUG_KERNEL)
1662 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001663 char buf[PREFIX_STRLEN];
Feng Lu758fb8f2014-07-03 18:23:09 +08001664 zlog_debug ("netlink_route_multipath() (%s): %s %s vrf %u type %s",
Christian Frankefa713d92013-07-05 15:35:37 +00001665 routedesc,
1666 lookup (nlmsg_str, cmd),
Timo Teräsbe6335d2015-05-23 11:08:41 +03001667 prefix2str (p, buf, sizeof(buf)),
Kaloyan Kovachev8c56b442015-06-15 17:08:48 +03001668 zvrf->vrf_id,
Timo Teräsbe6335d2015-05-23 11:08:41 +03001669 nexthop_type_to_str (nexthop->type));
Christian Frankefa713d92013-07-05 15:35:37 +00001670 }
1671}
1672
paul718e3742002-12-13 20:15:29 +00001673/* Routing table change via netlink interface. */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001674static int
Timo Teräs0abf6792016-01-15 17:36:29 +02001675netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001676{
1677 int bytelen;
1678 struct sockaddr_nl snl;
Christian Frankefa713d92013-07-05 15:35:37 +00001679 struct nexthop *nexthop = NULL, *tnexthop;
1680 int recursing;
1681 int nexthop_num;
paul718e3742002-12-13 20:15:29 +00001682 int discard;
Timo Teräs0abf6792016-01-15 17:36:29 +02001683 int family = PREFIX_FAMILY(p);
Christian Frankefa713d92013-07-05 15:35:37 +00001684 const char *routedesc;
paul718e3742002-12-13 20:15:29 +00001685
paul7021c422003-07-15 12:52:22 +00001686 struct
paul718e3742002-12-13 20:15:29 +00001687 {
1688 struct nlmsghdr n;
1689 struct rtmsg r;
JR Rivers3cadc0c2012-04-01 12:16:31 -07001690 char buf[NL_PKT_BUF_SIZE];
paul718e3742002-12-13 20:15:29 +00001691 } req;
1692
Feng Lu758fb8f2014-07-03 18:23:09 +08001693 struct zebra_vrf *zvrf = vrf_info_lookup (rib->vrf_id);
1694
Jorge Boncompte [DTI2]a4c06de2012-04-20 14:28:40 +02001695 memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
paul718e3742002-12-13 20:15:29 +00001696
1697 bytelen = (family == AF_INET ? 4 : 16);
1698
1699 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
Timo Teräs0abf6792016-01-15 17:36:29 +02001700 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REPLACE | NLM_F_REQUEST;
paul718e3742002-12-13 20:15:29 +00001701 req.n.nlmsg_type = cmd;
1702 req.r.rtm_family = family;
1703 req.r.rtm_table = rib->table;
1704 req.r.rtm_dst_len = p->prefixlen;
Timo Teräs40da2212008-08-13 17:37:14 +01001705 req.r.rtm_protocol = RTPROT_ZEBRA;
Timo Teräs82a66352016-01-15 17:36:30 +02001706 req.r.rtm_scope = RT_SCOPE_LINK;
paul718e3742002-12-13 20:15:29 +00001707
paul7021c422003-07-15 12:52:22 +00001708 if ((rib->flags & ZEBRA_FLAG_BLACKHOLE) || (rib->flags & ZEBRA_FLAG_REJECT))
paul718e3742002-12-13 20:15:29 +00001709 discard = 1;
1710 else
1711 discard = 0;
1712
paul7021c422003-07-15 12:52:22 +00001713 if (cmd == RTM_NEWROUTE)
paul718e3742002-12-13 20:15:29 +00001714 {
paul7021c422003-07-15 12:52:22 +00001715 if (discard)
paul595db7f2003-05-25 21:35:06 +00001716 {
1717 if (rib->flags & ZEBRA_FLAG_BLACKHOLE)
1718 req.r.rtm_type = RTN_BLACKHOLE;
1719 else if (rib->flags & ZEBRA_FLAG_REJECT)
1720 req.r.rtm_type = RTN_UNREACHABLE;
paul7021c422003-07-15 12:52:22 +00001721 else
1722 assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
1723 }
paul595db7f2003-05-25 21:35:06 +00001724 else
paul7021c422003-07-15 12:52:22 +00001725 req.r.rtm_type = RTN_UNICAST;
paul718e3742002-12-13 20:15:29 +00001726 }
1727
1728 addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
1729
1730 /* Metric. */
Timo Teräs4d3ae712016-01-15 17:36:32 +02001731 addattr32 (&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC);
paul718e3742002-12-13 20:15:29 +00001732
Timo Teräsb11f3b52015-11-02 16:50:07 +02001733 if (rib->mtu || rib->nexthop_mtu)
1734 {
1735 char buf[NL_PKT_BUF_SIZE];
1736 struct rtattr *rta = (void *) buf;
1737 u_int32_t mtu = rib->mtu;
1738 if (!mtu || (rib->nexthop_mtu && rib->nexthop_mtu < mtu))
1739 mtu = rib->nexthop_mtu;
1740 rta->rta_type = RTA_METRICS;
1741 rta->rta_len = RTA_LENGTH(0);
1742 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTAX_MTU, &mtu, sizeof mtu);
1743 addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA (rta),
1744 RTA_PAYLOAD (rta));
1745 }
1746
paul718e3742002-12-13 20:15:29 +00001747 if (discard)
1748 {
1749 if (cmd == RTM_NEWROUTE)
Christian Frankefa713d92013-07-05 15:35:37 +00001750 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1751 {
1752 /* We shouldn't encounter recursive nexthops on discard routes,
1753 * but it is probably better to handle that case correctly anyway.
1754 */
1755 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1756 continue;
1757 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1758 }
paul718e3742002-12-13 20:15:29 +00001759 goto skip;
1760 }
1761
Christian Frankefa713d92013-07-05 15:35:37 +00001762 /* Count overall nexthops so we can decide whether to use singlepath
1763 * or multipath case. */
1764 nexthop_num = 0;
1765 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001766 {
Christian Frankefa713d92013-07-05 15:35:37 +00001767 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1768 continue;
1769 if (cmd == RTM_NEWROUTE && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1770 continue;
1771 if (cmd == RTM_DELROUTE && !CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1772 continue;
1773
Timo Teräs82a66352016-01-15 17:36:30 +02001774 if (nexthop->type != NEXTHOP_TYPE_IFINDEX &&
1775 nexthop->type != NEXTHOP_TYPE_IFNAME)
1776 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1777
Christian Frankefa713d92013-07-05 15:35:37 +00001778 nexthop_num++;
1779 }
1780
1781 /* Singlepath case. */
1782 if (nexthop_num == 1 || MULTIPATH_NUM == 1)
1783 {
1784 nexthop_num = 0;
1785 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul7021c422003-07-15 12:52:22 +00001786 {
Christian Frankefa713d92013-07-05 15:35:37 +00001787 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1788 continue;
paul5ec90d22003-06-19 01:41:37 +00001789
paul7021c422003-07-15 12:52:22 +00001790 if ((cmd == RTM_NEWROUTE
1791 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1792 || (cmd == RTM_DELROUTE
1793 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1794 {
Christian Frankefa713d92013-07-05 15:35:37 +00001795 routedesc = recursing ? "recursive, 1 hop" : "single hop";
paul5ec90d22003-06-19 01:41:37 +00001796
Feng Lu758fb8f2014-07-03 18:23:09 +08001797 _netlink_route_debug(cmd, p, nexthop, routedesc, family, zvrf);
Christian Frankefa713d92013-07-05 15:35:37 +00001798 _netlink_route_build_singlepath(routedesc, bytelen,
Christian Frankee8d3d292013-07-05 15:35:39 +00001799 nexthop, &req.n, &req.r,
1800 sizeof req);
paul718e3742002-12-13 20:15:29 +00001801
paul7021c422003-07-15 12:52:22 +00001802 if (cmd == RTM_NEWROUTE)
1803 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
paul718e3742002-12-13 20:15:29 +00001804
paul7021c422003-07-15 12:52:22 +00001805 nexthop_num++;
1806 break;
1807 }
1808 }
paul718e3742002-12-13 20:15:29 +00001809 }
1810 else
1811 {
JR Rivers3cadc0c2012-04-01 12:16:31 -07001812 char buf[NL_PKT_BUF_SIZE];
paul718e3742002-12-13 20:15:29 +00001813 struct rtattr *rta = (void *) buf;
1814 struct rtnexthop *rtnh;
Paul Jakma7514fb72007-05-02 16:05:35 +00001815 union g_addr *src = NULL;
paul718e3742002-12-13 20:15:29 +00001816
1817 rta->rta_type = RTA_MULTIPATH;
paul7021c422003-07-15 12:52:22 +00001818 rta->rta_len = RTA_LENGTH (0);
1819 rtnh = RTA_DATA (rta);
paul718e3742002-12-13 20:15:29 +00001820
1821 nexthop_num = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001822 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul7021c422003-07-15 12:52:22 +00001823 {
Donald Sharp91ce87a2015-12-09 08:24:45 -05001824 if (nexthop_num >= MULTIPATH_NUM)
Christian Frankefa713d92013-07-05 15:35:37 +00001825 break;
1826
1827 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1828 continue;
1829
paul7021c422003-07-15 12:52:22 +00001830 if ((cmd == RTM_NEWROUTE
1831 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1832 || (cmd == RTM_DELROUTE
1833 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1834 {
Christian Frankefa713d92013-07-05 15:35:37 +00001835 routedesc = recursing ? "recursive, multihop" : "multihop";
paul7021c422003-07-15 12:52:22 +00001836 nexthop_num++;
paul718e3742002-12-13 20:15:29 +00001837
Christian Frankefa713d92013-07-05 15:35:37 +00001838 _netlink_route_debug(cmd, p, nexthop,
Feng Lu758fb8f2014-07-03 18:23:09 +08001839 routedesc, family, zvrf);
Christian Frankefa713d92013-07-05 15:35:37 +00001840 _netlink_route_build_multipath(routedesc, bytelen,
1841 nexthop, rta, rtnh, &src);
paul7021c422003-07-15 12:52:22 +00001842 rtnh = RTNH_NEXT (rtnh);
paul718e3742002-12-13 20:15:29 +00001843
paul7021c422003-07-15 12:52:22 +00001844 if (cmd == RTM_NEWROUTE)
1845 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1846 }
1847 }
Paul Jakma7514fb72007-05-02 16:05:35 +00001848 if (src)
1849 addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src->ipv4, bytelen);
paul718e3742002-12-13 20:15:29 +00001850
1851 if (rta->rta_len > RTA_LENGTH (0))
JR Rivers3cadc0c2012-04-01 12:16:31 -07001852 addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta),
paul7021c422003-07-15 12:52:22 +00001853 RTA_PAYLOAD (rta));
paul718e3742002-12-13 20:15:29 +00001854 }
1855
1856 /* If there is no useful nexthop then return. */
1857 if (nexthop_num == 0)
1858 {
1859 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +00001860 zlog_debug ("netlink_route_multipath(): No useful nexthop.");
paul718e3742002-12-13 20:15:29 +00001861 return 0;
1862 }
1863
paul7021c422003-07-15 12:52:22 +00001864skip:
paul718e3742002-12-13 20:15:29 +00001865
1866 /* Destination netlink address. */
1867 memset (&snl, 0, sizeof snl);
1868 snl.nl_family = AF_NETLINK;
1869
paul718e3742002-12-13 20:15:29 +00001870 /* Talk to netlink socket. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001871 return netlink_talk (&req.n, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001872}
1873
1874int
Timo Teräs0abf6792016-01-15 17:36:29 +02001875kernel_route_rib (struct prefix *p, struct rib *old, struct rib *new)
paul718e3742002-12-13 20:15:29 +00001876{
Timo Teräs0abf6792016-01-15 17:36:29 +02001877 if (!old && new)
1878 return netlink_route_multipath (RTM_NEWROUTE, p, new);
1879 if (old && !new)
1880 return netlink_route_multipath (RTM_DELROUTE, p, old);
paul718e3742002-12-13 20:15:29 +00001881
Timo Teräs4d3ae712016-01-15 17:36:32 +02001882 /* Replace, can be done atomically if metric does not change;
1883 * netlink uses [prefix, tos, priority] to identify prefix.
1884 * Now metric is not sent to kernel, so we can just do atomic replace. */
1885 return netlink_route_multipath (RTM_NEWROUTE, p, new);
paul718e3742002-12-13 20:15:29 +00001886}
David Lamparter6b0655a2014-06-04 06:53:35 +02001887
paul718e3742002-12-13 20:15:29 +00001888/* Interface address modification. */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001889static int
paul718e3742002-12-13 20:15:29 +00001890netlink_address (int cmd, int family, struct interface *ifp,
paul7021c422003-07-15 12:52:22 +00001891 struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001892{
1893 int bytelen;
1894 struct prefix *p;
1895
paul7021c422003-07-15 12:52:22 +00001896 struct
paul718e3742002-12-13 20:15:29 +00001897 {
1898 struct nlmsghdr n;
1899 struct ifaddrmsg ifa;
JR Rivers3cadc0c2012-04-01 12:16:31 -07001900 char buf[NL_PKT_BUF_SIZE];
paul718e3742002-12-13 20:15:29 +00001901 } req;
1902
Feng Lu758fb8f2014-07-03 18:23:09 +08001903 struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
1904
paul718e3742002-12-13 20:15:29 +00001905 p = ifc->address;
Jorge Boncompte [DTI2]a4c06de2012-04-20 14:28:40 +02001906 memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
paul718e3742002-12-13 20:15:29 +00001907
1908 bytelen = (family == AF_INET ? 4 : 16);
1909
paul7021c422003-07-15 12:52:22 +00001910 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg));
paul718e3742002-12-13 20:15:29 +00001911 req.n.nlmsg_flags = NLM_F_REQUEST;
1912 req.n.nlmsg_type = cmd;
1913 req.ifa.ifa_family = family;
1914
1915 req.ifa.ifa_index = ifp->ifindex;
1916 req.ifa.ifa_prefixlen = p->prefixlen;
1917
1918 addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen);
1919
1920 if (family == AF_INET && cmd == RTM_NEWADDR)
1921 {
Andrew J. Schorre4529632006-12-12 19:18:21 +00001922 if (!CONNECTED_PEER(ifc) && ifc->destination)
paul7021c422003-07-15 12:52:22 +00001923 {
1924 p = ifc->destination;
1925 addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix,
1926 bytelen);
1927 }
paul718e3742002-12-13 20:15:29 +00001928 }
1929
1930 if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
1931 SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY);
paul7021c422003-07-15 12:52:22 +00001932
paul718e3742002-12-13 20:15:29 +00001933 if (ifc->label)
1934 addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label,
paul7021c422003-07-15 12:52:22 +00001935 strlen (ifc->label) + 1);
paul718e3742002-12-13 20:15:29 +00001936
Feng Lu758fb8f2014-07-03 18:23:09 +08001937 return netlink_talk (&req.n, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001938}
1939
1940int
1941kernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc)
1942{
1943 return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc);
1944}
1945
1946int
1947kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc)
1948{
1949 return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc);
1950}
1951
paul718e3742002-12-13 20:15:29 +00001952
1953extern struct thread_master *master;
1954
1955/* Kernel route reflection. */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001956static int
paul718e3742002-12-13 20:15:29 +00001957kernel_read (struct thread *thread)
1958{
Feng Lu758fb8f2014-07-03 18:23:09 +08001959 struct zebra_vrf *zvrf = (struct zebra_vrf *)THREAD_ARG (thread);
1960 netlink_parse_info (netlink_information_fetch, &zvrf->netlink, zvrf);
1961 zvrf->t_netlink = thread_add_read (zebrad.master, kernel_read, zvrf,
1962 zvrf->netlink.sock);
paul718e3742002-12-13 20:15:29 +00001963
1964 return 0;
1965}
1966
Stephen Hemminger3d265b42008-08-16 17:30:39 +01001967/* Filter out messages from self that occur on listener socket,
1968 caused by our actions on the command socket
1969 */
1970static void netlink_install_filter (int sock, __u32 pid)
Paul Jakma768a27e2008-05-29 18:23:08 +00001971{
Paul Jakma768a27e2008-05-29 18:23:08 +00001972 struct sock_filter filter[] = {
Stephen Hemminger3d265b42008-08-16 17:30:39 +01001973 /* 0: ldh [4] */
1974 BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)),
1975 /* 1: jeq 0x18 jt 3 jf 6 */
1976 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 1, 0),
1977 /* 2: jeq 0x19 jt 3 jf 6 */
1978 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 0, 3),
1979 /* 3: ldw [12] */
1980 BPF_STMT(BPF_LD|BPF_ABS|BPF_W, offsetof(struct nlmsghdr, nlmsg_pid)),
1981 /* 4: jeq XX jt 5 jf 6 */
1982 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htonl(pid), 0, 1),
1983 /* 5: ret 0 (skip) */
1984 BPF_STMT(BPF_RET|BPF_K, 0),
1985 /* 6: ret 0xffff (keep) */
1986 BPF_STMT(BPF_RET|BPF_K, 0xffff),
Paul Jakma768a27e2008-05-29 18:23:08 +00001987 };
1988
1989 struct sock_fprog prog = {
Balaji.G837d16c2012-09-26 14:09:10 +05301990 .len = array_size(filter),
Paul Jakma768a27e2008-05-29 18:23:08 +00001991 .filter = filter,
1992 };
1993
1994 if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)) < 0)
1995 zlog_warn ("Can't install socket filter: %s\n", safe_strerror(errno));
1996}
1997
paul718e3742002-12-13 20:15:29 +00001998/* Exported interface function. This function simply calls
1999 netlink_socket (). */
2000void
Feng Lu758fb8f2014-07-03 18:23:09 +08002001kernel_init (struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00002002{
2003 unsigned long groups;
2004
paul7021c422003-07-15 12:52:22 +00002005 groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR;
paul718e3742002-12-13 20:15:29 +00002006#ifdef HAVE_IPV6
paul7021c422003-07-15 12:52:22 +00002007 groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR;
paul718e3742002-12-13 20:15:29 +00002008#endif /* HAVE_IPV6 */
Feng Lu758fb8f2014-07-03 18:23:09 +08002009 netlink_socket (&zvrf->netlink, groups, zvrf->vrf_id);
2010 netlink_socket (&zvrf->netlink_cmd, 0, zvrf->vrf_id);
paul718e3742002-12-13 20:15:29 +00002011
2012 /* Register kernel socket. */
Feng Lu758fb8f2014-07-03 18:23:09 +08002013 if (zvrf->netlink.sock > 0)
Paul Jakma768a27e2008-05-29 18:23:08 +00002014 {
Paul Jakma6dbb58c2017-02-08 15:05:06 +00002015 size_t bufsize = MAX(nl_rcvbufsize, 2 * sysconf(_SC_PAGESIZE));
2016
Stephen Hemminger4cde9312008-08-16 17:51:27 +01002017 /* Only want non-blocking on the netlink event socket */
Feng Lu758fb8f2014-07-03 18:23:09 +08002018 if (fcntl (zvrf->netlink.sock, F_SETFL, O_NONBLOCK) < 0)
2019 zlog_err ("Can't set %s socket flags: %s", zvrf->netlink.name,
2020 safe_strerror (errno));
Stephen Hemminger4cde9312008-08-16 17:51:27 +01002021
Stephen Hemminger30afea32008-08-16 18:25:47 +01002022 /* Set receive buffer size if it's set from command line */
2023 if (nl_rcvbufsize)
Feng Lu758fb8f2014-07-03 18:23:09 +08002024 netlink_recvbuf (&zvrf->netlink, nl_rcvbufsize);
Paul Jakma6dbb58c2017-02-08 15:05:06 +00002025
2026 nl_rcvbuf.p = XMALLOC (MTYPE_NETLINK_RCVBUF, bufsize);
2027 nl_rcvbuf.size = bufsize;
2028
Feng Lu758fb8f2014-07-03 18:23:09 +08002029 netlink_install_filter (zvrf->netlink.sock, zvrf->netlink_cmd.snl.nl_pid);
2030 zvrf->t_netlink = thread_add_read (zebrad.master, kernel_read, zvrf,
2031 zvrf->netlink.sock);
2032 }
2033}
2034
2035void
2036kernel_terminate (struct zebra_vrf *zvrf)
2037{
2038 THREAD_READ_OFF (zvrf->t_netlink);
2039
2040 if (zvrf->netlink.sock >= 0)
2041 {
2042 close (zvrf->netlink.sock);
2043 zvrf->netlink.sock = -1;
2044 }
2045
2046 if (zvrf->netlink_cmd.sock >= 0)
2047 {
2048 close (zvrf->netlink_cmd.sock);
2049 zvrf->netlink_cmd.sock = -1;
Paul Jakma768a27e2008-05-29 18:23:08 +00002050 }
paul718e3742002-12-13 20:15:29 +00002051}
Avneesh Sachdev78deec42012-11-13 22:48:56 +00002052
2053/*
2054 * nl_msg_type_to_str
2055 */
2056const char *
2057nl_msg_type_to_str (uint16_t msg_type)
2058{
2059 return lookup (nlmsg_str, msg_type);
2060}
2061
2062/*
2063 * nl_rtproto_to_str
2064 */
2065const char *
2066nl_rtproto_to_str (u_char rtproto)
2067{
2068 return lookup (rtproto_str, rtproto);
2069}