blob: 2539d614ab7da66f1a13813ac381c696a02d2789 [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"
paul718e3742002-12-13 20:15:29 +000041
42#include "zebra/zserv.h"
paul6621ca82005-11-23 13:02:08 +000043#include "zebra/rt.h"
paul718e3742002-12-13 20:15:29 +000044#include "zebra/redistribute.h"
45#include "zebra/interface.h"
46#include "zebra/debug.h"
47
Avneesh Sachdev78deec42012-11-13 22:48:56 +000048#include "rt_netlink.h"
JR Rivers3cadc0c2012-04-01 12:16:31 -070049
Stephen Hemminger1423c802008-08-14 17:59:25 +010050static const struct message nlmsg_str[] = {
paul718e3742002-12-13 20:15:29 +000051 {RTM_NEWROUTE, "RTM_NEWROUTE"},
52 {RTM_DELROUTE, "RTM_DELROUTE"},
53 {RTM_GETROUTE, "RTM_GETROUTE"},
54 {RTM_NEWLINK, "RTM_NEWLINK"},
55 {RTM_DELLINK, "RTM_DELLINK"},
56 {RTM_GETLINK, "RTM_GETLINK"},
57 {RTM_NEWADDR, "RTM_NEWADDR"},
58 {RTM_DELADDR, "RTM_DELADDR"},
59 {RTM_GETADDR, "RTM_GETADDR"},
paul7021c422003-07-15 12:52:22 +000060 {0, NULL}
paul718e3742002-12-13 20:15:29 +000061};
62
paulb21b19c2003-06-15 01:28:29 +000063extern struct zebra_t zebrad;
paul718e3742002-12-13 20:15:29 +000064
pauledd7c242003-06-04 13:59:38 +000065extern struct zebra_privs_t zserv_privs;
66
hassoc34b6b52004-08-31 13:41:49 +000067extern u_int32_t nl_rcvbufsize;
68
ajsd2fc8892005-04-02 18:38:43 +000069/* Note: on netlink systems, there should be a 1-to-1 mapping between interface
70 names and ifindex values. */
71static void
Paul Jakma9099f9b2016-01-18 10:12:10 +000072set_ifindex(struct interface *ifp, ifindex_t ifi_index)
ajsd2fc8892005-04-02 18:38:43 +000073{
74 struct interface *oifp;
75
76 if (((oifp = if_lookup_by_index(ifi_index)) != NULL) && (oifp != ifp))
77 {
78 if (ifi_index == IFINDEX_INTERNAL)
79 zlog_err("Netlink is setting interface %s ifindex to reserved "
80 "internal value %u", ifp->name, ifi_index);
81 else
82 {
83 if (IS_ZEBRA_DEBUG_KERNEL)
84 zlog_debug("interface index %d was renamed from %s to %s",
85 ifi_index, oifp->name, ifp->name);
86 if (if_is_up(oifp))
87 zlog_err("interface rename detected on up interface: index %d "
88 "was renamed from %s to %s, results are uncertain!",
89 ifi_index, oifp->name, ifp->name);
90 if_delete_update(oifp);
91 }
92 }
93 ifp->ifindex = ifi_index;
94}
95
Ulrich Weberf1ef81b2013-01-22 10:39:18 +000096#ifndef SO_RCVBUFFORCE
97#define SO_RCVBUFFORCE (33)
98#endif
99
Stephen Hemminger30afea32008-08-16 18:25:47 +0100100static int
101netlink_recvbuf (struct nlsock *nl, uint32_t newsize)
102{
103 u_int32_t oldsize;
104 socklen_t newlen = sizeof(newsize);
105 socklen_t oldlen = sizeof(oldsize);
106 int ret;
107
108 ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &oldsize, &oldlen);
109 if (ret < 0)
110 {
111 zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name,
112 safe_strerror (errno));
113 return -1;
114 }
115
Ulrich Weberf1ef81b2013-01-22 10:39:18 +0000116 /* Try force option (linux >= 2.6.14) and fall back to normal set */
117 if ( zserv_privs.change (ZPRIVS_RAISE) )
118 zlog_err ("routing_socket: Can't raise privileges");
119 ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUFFORCE, &nl_rcvbufsize,
Stephen Hemminger30afea32008-08-16 18:25:47 +0100120 sizeof(nl_rcvbufsize));
Ulrich Weberf1ef81b2013-01-22 10:39:18 +0000121 if ( zserv_privs.change (ZPRIVS_LOWER) )
122 zlog_err ("routing_socket: Can't lower privileges");
123 if (ret < 0)
124 ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &nl_rcvbufsize,
125 sizeof(nl_rcvbufsize));
Stephen Hemminger30afea32008-08-16 18:25:47 +0100126 if (ret < 0)
127 {
128 zlog (NULL, LOG_ERR, "Can't set %s receive buffer size: %s", nl->name,
129 safe_strerror (errno));
130 return -1;
131 }
132
133 ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &newsize, &newlen);
134 if (ret < 0)
135 {
136 zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name,
137 safe_strerror (errno));
138 return -1;
139 }
140
141 zlog (NULL, LOG_INFO,
142 "Setting netlink socket receive buffer size: %u -> %u",
143 oldsize, newsize);
144 return 0;
145}
146
paul718e3742002-12-13 20:15:29 +0000147/* Make socket for Linux netlink interface. */
148static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800149netlink_socket (struct nlsock *nl, unsigned long groups, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000150{
151 int ret;
152 struct sockaddr_nl snl;
153 int sock;
154 int namelen;
ajs4be019d2005-01-29 16:12:41 +0000155 int save_errno;
paul718e3742002-12-13 20:15:29 +0000156
Michal Sekletar8e998b12014-05-16 14:13:43 +0000157 if (zserv_privs.change (ZPRIVS_RAISE))
158 {
159 zlog (NULL, LOG_ERR, "Can't raise privileges");
160 return -1;
161 }
162
Feng Lu758fb8f2014-07-03 18:23:09 +0800163 sock = vrf_socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE, vrf_id);
paul718e3742002-12-13 20:15:29 +0000164 if (sock < 0)
165 {
166 zlog (NULL, LOG_ERR, "Can't open %s socket: %s", nl->name,
ajs6099b3b2004-11-20 02:06:59 +0000167 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000168 return -1;
169 }
170
paul718e3742002-12-13 20:15:29 +0000171 memset (&snl, 0, sizeof snl);
172 snl.nl_family = AF_NETLINK;
173 snl.nl_groups = groups;
174
175 /* Bind the socket to the netlink structure for anything. */
176 ret = bind (sock, (struct sockaddr *) &snl, sizeof snl);
ajs4be019d2005-01-29 16:12:41 +0000177 save_errno = errno;
hasso55e7ecd2004-08-06 08:41:56 +0000178 if (zserv_privs.change (ZPRIVS_LOWER))
179 zlog (NULL, LOG_ERR, "Can't lower privileges");
180
paul718e3742002-12-13 20:15:29 +0000181 if (ret < 0)
182 {
paul7021c422003-07-15 12:52:22 +0000183 zlog (NULL, LOG_ERR, "Can't bind %s socket to group 0x%x: %s",
ajs4be019d2005-01-29 16:12:41 +0000184 nl->name, snl.nl_groups, safe_strerror (save_errno));
paul718e3742002-12-13 20:15:29 +0000185 close (sock);
186 return -1;
187 }
paul7021c422003-07-15 12:52:22 +0000188
paul718e3742002-12-13 20:15:29 +0000189 /* multiple netlink sockets will have different nl_pid */
190 namelen = sizeof snl;
hassoc9e52be2004-09-26 16:09:34 +0000191 ret = getsockname (sock, (struct sockaddr *) &snl, (socklen_t *) &namelen);
paul718e3742002-12-13 20:15:29 +0000192 if (ret < 0 || namelen != sizeof snl)
193 {
194 zlog (NULL, LOG_ERR, "Can't get %s socket name: %s", nl->name,
ajs6099b3b2004-11-20 02:06:59 +0000195 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000196 close (sock);
197 return -1;
198 }
199
200 nl->snl = snl;
201 nl->sock = sock;
202 return ret;
203}
204
205/* Get type specified information from netlink. */
206static int
207netlink_request (int family, int type, struct nlsock *nl)
208{
209 int ret;
210 struct sockaddr_nl snl;
ajs4be019d2005-01-29 16:12:41 +0000211 int save_errno;
paul718e3742002-12-13 20:15:29 +0000212
213 struct
214 {
215 struct nlmsghdr nlh;
216 struct rtgenmsg g;
217 } req;
218
219
220 /* Check netlink socket. */
221 if (nl->sock < 0)
222 {
223 zlog (NULL, LOG_ERR, "%s socket isn't active.", nl->name);
224 return -1;
225 }
226
227 memset (&snl, 0, sizeof snl);
228 snl.nl_family = AF_NETLINK;
229
ajsc05612b2005-10-01 16:36:54 +0000230 memset (&req, 0, sizeof req);
paul718e3742002-12-13 20:15:29 +0000231 req.nlh.nlmsg_len = sizeof req;
232 req.nlh.nlmsg_type = type;
233 req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
Stephen Hemminger3d265b42008-08-16 17:30:39 +0100234 req.nlh.nlmsg_pid = nl->snl.nl_pid;
paul718e3742002-12-13 20:15:29 +0000235 req.nlh.nlmsg_seq = ++nl->seq;
236 req.g.rtgen_family = family;
pauledd7c242003-06-04 13:59:38 +0000237
238 /* linux appears to check capabilities on every message
239 * have to raise caps for every message sent
240 */
paul7021c422003-07-15 12:52:22 +0000241 if (zserv_privs.change (ZPRIVS_RAISE))
pauledd7c242003-06-04 13:59:38 +0000242 {
243 zlog (NULL, LOG_ERR, "Can't raise privileges");
244 return -1;
245 }
paul7021c422003-07-15 12:52:22 +0000246
247 ret = sendto (nl->sock, (void *) &req, sizeof req, 0,
248 (struct sockaddr *) &snl, sizeof snl);
ajs4be019d2005-01-29 16:12:41 +0000249 save_errno = errno;
paul7021c422003-07-15 12:52:22 +0000250
251 if (zserv_privs.change (ZPRIVS_LOWER))
252 zlog (NULL, LOG_ERR, "Can't lower privileges");
253
paul718e3742002-12-13 20:15:29 +0000254 if (ret < 0)
paul7021c422003-07-15 12:52:22 +0000255 {
256 zlog (NULL, LOG_ERR, "%s sendto failed: %s", nl->name,
ajs4be019d2005-01-29 16:12:41 +0000257 safe_strerror (save_errno));
paul718e3742002-12-13 20:15:29 +0000258 return -1;
259 }
pauledd7c242003-06-04 13:59:38 +0000260
paul718e3742002-12-13 20:15:29 +0000261 return 0;
262}
263
264/* Receive message from netlink interface and pass those information
265 to the given function. */
266static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800267netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *,
268 vrf_id_t),
269 struct nlsock *nl, struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +0000270{
271 int status;
272 int ret = 0;
273 int error;
274
275 while (1)
276 {
JR Rivers3cadc0c2012-04-01 12:16:31 -0700277 char buf[NL_PKT_BUF_SIZE];
Timo Teräsc299ed72014-07-29 09:41:55 +0000278 struct iovec iov = {
279 .iov_base = buf,
280 .iov_len = sizeof buf
281 };
paul718e3742002-12-13 20:15:29 +0000282 struct sockaddr_nl snl;
Timo Teräsc299ed72014-07-29 09:41:55 +0000283 struct msghdr msg = {
284 .msg_name = (void *) &snl,
285 .msg_namelen = sizeof snl,
286 .msg_iov = &iov,
287 .msg_iovlen = 1
288 };
paul718e3742002-12-13 20:15:29 +0000289 struct nlmsghdr *h;
paul7021c422003-07-15 12:52:22 +0000290
paul718e3742002-12-13 20:15:29 +0000291 status = recvmsg (nl->sock, &msg, 0);
paul718e3742002-12-13 20:15:29 +0000292 if (status < 0)
paul7021c422003-07-15 12:52:22 +0000293 {
Stephen Hemminger4c699472008-08-17 17:01:44 +0100294 if (errno == EINTR)
paul7021c422003-07-15 12:52:22 +0000295 continue;
Stephen Hemminger4c699472008-08-17 17:01:44 +0100296 if (errno == EWOULDBLOCK || errno == EAGAIN)
paul7021c422003-07-15 12:52:22 +0000297 break;
ajs4be019d2005-01-29 16:12:41 +0000298 zlog (NULL, LOG_ERR, "%s recvmsg overrun: %s",
Stephen Hemminger4c699472008-08-17 17:01:44 +0100299 nl->name, safe_strerror(errno));
paul7021c422003-07-15 12:52:22 +0000300 continue;
301 }
paul718e3742002-12-13 20:15:29 +0000302
303 if (status == 0)
paul7021c422003-07-15 12:52:22 +0000304 {
305 zlog (NULL, LOG_ERR, "%s EOF", nl->name);
306 return -1;
307 }
paul718e3742002-12-13 20:15:29 +0000308
309 if (msg.msg_namelen != sizeof snl)
paul7021c422003-07-15 12:52:22 +0000310 {
311 zlog (NULL, LOG_ERR, "%s sender address length error: length %d",
312 nl->name, msg.msg_namelen);
313 return -1;
314 }
paulb84d3a12003-11-17 10:31:01 +0000315
hasso206d8052005-04-09 16:38:51 +0000316 for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, (unsigned int) status);
paul7021c422003-07-15 12:52:22 +0000317 h = NLMSG_NEXT (h, status))
318 {
319 /* Finish of reading. */
320 if (h->nlmsg_type == NLMSG_DONE)
321 return ret;
paul718e3742002-12-13 20:15:29 +0000322
paul7021c422003-07-15 12:52:22 +0000323 /* Error handling. */
324 if (h->nlmsg_type == NLMSG_ERROR)
325 {
326 struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h);
Stephen Hemminger898987e2008-08-17 16:56:15 +0100327 int errnum = err->error;
328 int msg_type = err->msg.nlmsg_type;
paul7021c422003-07-15 12:52:22 +0000329
paul718e3742002-12-13 20:15:29 +0000330 /* If the error field is zero, then this is an ACK */
paul7021c422003-07-15 12:52:22 +0000331 if (err->error == 0)
paul718e3742002-12-13 20:15:29 +0000332 {
paul7021c422003-07-15 12:52:22 +0000333 if (IS_ZEBRA_DEBUG_KERNEL)
334 {
hasso1ada8192005-06-12 11:28:18 +0000335 zlog_debug ("%s: %s ACK: type=%s(%u), seq=%u, pid=%u",
paul7021c422003-07-15 12:52:22 +0000336 __FUNCTION__, nl->name,
337 lookup (nlmsg_str, err->msg.nlmsg_type),
338 err->msg.nlmsg_type, err->msg.nlmsg_seq,
339 err->msg.nlmsg_pid);
paul718e3742002-12-13 20:15:29 +0000340 }
paul7021c422003-07-15 12:52:22 +0000341
342 /* return if not a multipart message, otherwise continue */
343 if (!(h->nlmsg_flags & NLM_F_MULTI))
344 {
345 return 0;
paul718e3742002-12-13 20:15:29 +0000346 }
paul7021c422003-07-15 12:52:22 +0000347 continue;
paul718e3742002-12-13 20:15:29 +0000348 }
paul7021c422003-07-15 12:52:22 +0000349
paul718e3742002-12-13 20:15:29 +0000350 if (h->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr)))
paul7021c422003-07-15 12:52:22 +0000351 {
352 zlog (NULL, LOG_ERR, "%s error: message truncated",
353 nl->name);
354 return -1;
355 }
pauld753e9e2003-01-22 19:45:50 +0000356
Stephen Hemminger898987e2008-08-17 16:56:15 +0100357 /* Deal with errors that occur because of races in link handling */
Feng Lu758fb8f2014-07-03 18:23:09 +0800358 if (nl == &zvrf->netlink_cmd
Stephen Hemminger898987e2008-08-17 16:56:15 +0100359 && ((msg_type == RTM_DELROUTE &&
360 (-errnum == ENODEV || -errnum == ESRCH))
361 || (msg_type == RTM_NEWROUTE && -errnum == EEXIST)))
362 {
363 if (IS_ZEBRA_DEBUG_KERNEL)
364 zlog_debug ("%s: error: %s type=%s(%u), seq=%u, pid=%u",
365 nl->name, safe_strerror (-errnum),
366 lookup (nlmsg_str, msg_type),
367 msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid);
368 return 0;
369 }
paul718e3742002-12-13 20:15:29 +0000370
Stephen Hemminger898987e2008-08-17 16:56:15 +0100371 zlog_err ("%s error: %s, type=%s(%u), seq=%u, pid=%u",
372 nl->name, safe_strerror (-errnum),
373 lookup (nlmsg_str, msg_type),
374 msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid);
paul7021c422003-07-15 12:52:22 +0000375 return -1;
376 }
paul718e3742002-12-13 20:15:29 +0000377
paul7021c422003-07-15 12:52:22 +0000378 /* OK we got netlink message. */
379 if (IS_ZEBRA_DEBUG_KERNEL)
hasso1ada8192005-06-12 11:28:18 +0000380 zlog_debug ("netlink_parse_info: %s type %s(%u), seq=%u, pid=%u",
paul7021c422003-07-15 12:52:22 +0000381 nl->name,
382 lookup (nlmsg_str, h->nlmsg_type), h->nlmsg_type,
383 h->nlmsg_seq, h->nlmsg_pid);
384
Christian Franke599da952013-01-24 14:04:43 +0000385 /* skip unsolicited messages originating from command socket
386 * linux sets the originators port-id for {NEW|DEL}ADDR messages,
387 * so this has to be checked here. */
Feng Lu758fb8f2014-07-03 18:23:09 +0800388 if (nl != &zvrf->netlink_cmd
389 && h->nlmsg_pid == zvrf->netlink_cmd.snl.nl_pid
Christian Franke599da952013-01-24 14:04:43 +0000390 && (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR))
paul7021c422003-07-15 12:52:22 +0000391 {
392 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000393 zlog_debug ("netlink_parse_info: %s packet comes from %s",
Feng Lu758fb8f2014-07-03 18:23:09 +0800394 zvrf->netlink_cmd.name, nl->name);
paul7021c422003-07-15 12:52:22 +0000395 continue;
396 }
397
Feng Lu758fb8f2014-07-03 18:23:09 +0800398 error = (*filter) (&snl, h, zvrf->vrf_id);
paul7021c422003-07-15 12:52:22 +0000399 if (error < 0)
400 {
401 zlog (NULL, LOG_ERR, "%s filter function error", nl->name);
402 ret = error;
403 }
404 }
paul718e3742002-12-13 20:15:29 +0000405
406 /* After error care. */
407 if (msg.msg_flags & MSG_TRUNC)
paul7021c422003-07-15 12:52:22 +0000408 {
409 zlog (NULL, LOG_ERR, "%s error: message truncated", nl->name);
410 continue;
411 }
paul718e3742002-12-13 20:15:29 +0000412 if (status)
paul7021c422003-07-15 12:52:22 +0000413 {
414 zlog (NULL, LOG_ERR, "%s error: data remnant size %d", nl->name,
415 status);
416 return -1;
417 }
paul718e3742002-12-13 20:15:29 +0000418 }
419 return ret;
420}
421
422/* Utility function for parse rtattr. */
423static void
paul7021c422003-07-15 12:52:22 +0000424netlink_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta,
425 int len)
paul718e3742002-12-13 20:15:29 +0000426{
paul7021c422003-07-15 12:52:22 +0000427 while (RTA_OK (rta, len))
paul718e3742002-12-13 20:15:29 +0000428 {
429 if (rta->rta_type <= max)
paul7021c422003-07-15 12:52:22 +0000430 tb[rta->rta_type] = rta;
431 rta = RTA_NEXT (rta, len);
paul718e3742002-12-13 20:15:29 +0000432 }
433}
434
Josh Bailey26e2ae32012-03-22 01:09:21 -0700435/* Utility function to parse hardware link-layer address and update ifp */
436static void
437netlink_interface_update_hw_addr (struct rtattr **tb, struct interface *ifp)
438{
439 int i;
440
441 if (tb[IFLA_ADDRESS])
442 {
443 int hw_addr_len;
444
445 hw_addr_len = RTA_PAYLOAD (tb[IFLA_ADDRESS]);
446
447 if (hw_addr_len > INTERFACE_HWADDR_MAX)
448 zlog_warn ("Hardware address is too large: %d", hw_addr_len);
449 else
450 {
451 ifp->hw_addr_len = hw_addr_len;
452 memcpy (ifp->hw_addr, RTA_DATA (tb[IFLA_ADDRESS]), hw_addr_len);
453
454 for (i = 0; i < hw_addr_len; i++)
455 if (ifp->hw_addr[i] != 0)
456 break;
457
458 if (i == hw_addr_len)
459 ifp->hw_addr_len = 0;
460 else
461 ifp->hw_addr_len = hw_addr_len;
462 }
463 }
464}
465
Timo Teräs954c7d62016-01-15 17:36:33 +0200466static enum zebra_link_type
467netlink_to_zebra_link_type (unsigned int hwt)
468{
469 switch (hwt)
470 {
471 case ARPHRD_ETHER: return ZEBRA_LLT_ETHER;
472 case ARPHRD_EETHER: return ZEBRA_LLT_EETHER;
473 case ARPHRD_AX25: return ZEBRA_LLT_AX25;
474 case ARPHRD_PRONET: return ZEBRA_LLT_PRONET;
475 case ARPHRD_IEEE802: return ZEBRA_LLT_IEEE802;
476 case ARPHRD_ARCNET: return ZEBRA_LLT_ARCNET;
477 case ARPHRD_APPLETLK: return ZEBRA_LLT_APPLETLK;
478 case ARPHRD_DLCI: return ZEBRA_LLT_DLCI;
479 case ARPHRD_ATM: return ZEBRA_LLT_ATM;
480 case ARPHRD_METRICOM: return ZEBRA_LLT_METRICOM;
481 case ARPHRD_IEEE1394: return ZEBRA_LLT_IEEE1394;
482 case ARPHRD_EUI64: return ZEBRA_LLT_EUI64;
483 case ARPHRD_INFINIBAND: return ZEBRA_LLT_INFINIBAND;
484 case ARPHRD_SLIP: return ZEBRA_LLT_SLIP;
485 case ARPHRD_CSLIP: return ZEBRA_LLT_CSLIP;
486 case ARPHRD_SLIP6: return ZEBRA_LLT_SLIP6;
487 case ARPHRD_CSLIP6: return ZEBRA_LLT_CSLIP6;
488 case ARPHRD_RSRVD: return ZEBRA_LLT_RSRVD;
489 case ARPHRD_ADAPT: return ZEBRA_LLT_ADAPT;
490 case ARPHRD_ROSE: return ZEBRA_LLT_ROSE;
491 case ARPHRD_X25: return ZEBRA_LLT_X25;
492 case ARPHRD_PPP: return ZEBRA_LLT_PPP;
493 case ARPHRD_CISCO: return ZEBRA_LLT_CHDLC;
494 case ARPHRD_LAPB: return ZEBRA_LLT_LAPB;
495 case ARPHRD_RAWHDLC: return ZEBRA_LLT_RAWHDLC;
496 case ARPHRD_TUNNEL: return ZEBRA_LLT_IPIP;
497 case ARPHRD_TUNNEL6: return ZEBRA_LLT_IPIP6;
498 case ARPHRD_FRAD: return ZEBRA_LLT_FRAD;
499 case ARPHRD_SKIP: return ZEBRA_LLT_SKIP;
500 case ARPHRD_LOOPBACK: return ZEBRA_LLT_LOOPBACK;
501 case ARPHRD_LOCALTLK: return ZEBRA_LLT_LOCALTLK;
502 case ARPHRD_FDDI: return ZEBRA_LLT_FDDI;
503 case ARPHRD_SIT: return ZEBRA_LLT_SIT;
504 case ARPHRD_IPDDP: return ZEBRA_LLT_IPDDP;
505 case ARPHRD_IPGRE: return ZEBRA_LLT_IPGRE;
506 case ARPHRD_PIMREG: return ZEBRA_LLT_PIMREG;
507 case ARPHRD_HIPPI: return ZEBRA_LLT_HIPPI;
508 case ARPHRD_ECONET: return ZEBRA_LLT_ECONET;
509 case ARPHRD_IRDA: return ZEBRA_LLT_IRDA;
510 case ARPHRD_FCPP: return ZEBRA_LLT_FCPP;
511 case ARPHRD_FCAL: return ZEBRA_LLT_FCAL;
512 case ARPHRD_FCPL: return ZEBRA_LLT_FCPL;
513 case ARPHRD_FCFABRIC: return ZEBRA_LLT_FCFABRIC;
514 case ARPHRD_IEEE802_TR: return ZEBRA_LLT_IEEE802_TR;
515 case ARPHRD_IEEE80211: return ZEBRA_LLT_IEEE80211;
516 case ARPHRD_IEEE802154: return ZEBRA_LLT_IEEE802154;
517#ifdef ARPHRD_IP6GRE
518 case ARPHRD_IP6GRE: return ZEBRA_LLT_IP6GRE;
519#endif
520#ifdef ARPHRD_IEEE802154_PHY
521 case ARPHRD_IEEE802154_PHY: return ZEBRA_LLT_IEEE802154_PHY;
522#endif
523
524 default: return ZEBRA_LLT_UNKNOWN;
525 }
526}
527
paul718e3742002-12-13 20:15:29 +0000528/* Called from interface_lookup_netlink(). This function is only used
529 during bootstrap. */
Stephen Hemminger6072b242008-08-14 16:52:26 +0100530static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800531netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h,
532 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000533{
534 int len;
535 struct ifinfomsg *ifi;
536 struct rtattr *tb[IFLA_MAX + 1];
537 struct interface *ifp;
538 char *name;
paul718e3742002-12-13 20:15:29 +0000539
540 ifi = NLMSG_DATA (h);
541
542 if (h->nlmsg_type != RTM_NEWLINK)
543 return 0;
544
545 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
546 if (len < 0)
547 return -1;
548
549 /* Looking up interface name. */
550 memset (tb, 0, sizeof tb);
551 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
paulc15cb242005-01-24 09:05:27 +0000552
paul1e193152005-02-14 23:53:05 +0000553#ifdef IFLA_WIRELESS
paulc15cb242005-01-24 09:05:27 +0000554 /* check for wireless messages to ignore */
555 if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
556 {
557 if (IS_ZEBRA_DEBUG_KERNEL)
558 zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__);
559 return 0;
560 }
paul1e193152005-02-14 23:53:05 +0000561#endif /* IFLA_WIRELESS */
paulc15cb242005-01-24 09:05:27 +0000562
paul718e3742002-12-13 20:15:29 +0000563 if (tb[IFLA_IFNAME] == NULL)
564 return -1;
paul7021c422003-07-15 12:52:22 +0000565 name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
paul718e3742002-12-13 20:15:29 +0000566
567 /* Add interface. */
Feng Lu758fb8f2014-07-03 18:23:09 +0800568 ifp = if_get_by_name_vrf (name, vrf_id);
ajsd2fc8892005-04-02 18:38:43 +0000569 set_ifindex(ifp, ifi->ifi_index);
paul718e3742002-12-13 20:15:29 +0000570 ifp->flags = ifi->ifi_flags & 0x0000fffff;
Stephen Hemminger4308abb2008-12-01 14:19:38 -0800571 ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]);
Brett Cipherydb19c852013-10-03 13:48:54 +0000572 ifp->metric = 0;
paul718e3742002-12-13 20:15:29 +0000573
574 /* Hardware type and address. */
Timo Teräs954c7d62016-01-15 17:36:33 +0200575 ifp->ll_type = netlink_to_zebra_link_type (ifi->ifi_type);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700576 netlink_interface_update_hw_addr (tb, ifp);
paul718e3742002-12-13 20:15:29 +0000577
578 if_add_update (ifp);
579
580 return 0;
581}
582
583/* Lookup interface IPv4/IPv6 address. */
Stephen Hemminger6072b242008-08-14 16:52:26 +0100584static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800585netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h,
586 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000587{
588 int len;
589 struct ifaddrmsg *ifa;
paul7021c422003-07-15 12:52:22 +0000590 struct rtattr *tb[IFA_MAX + 1];
paul718e3742002-12-13 20:15:29 +0000591 struct interface *ifp;
Andrew J. Schorre4529632006-12-12 19:18:21 +0000592 void *addr;
593 void *broad;
paul718e3742002-12-13 20:15:29 +0000594 u_char flags = 0;
595 char *label = NULL;
596
597 ifa = NLMSG_DATA (h);
598
paul7021c422003-07-15 12:52:22 +0000599 if (ifa->ifa_family != AF_INET
paul718e3742002-12-13 20:15:29 +0000600#ifdef HAVE_IPV6
601 && ifa->ifa_family != AF_INET6
602#endif /* HAVE_IPV6 */
paul7021c422003-07-15 12:52:22 +0000603 )
paul718e3742002-12-13 20:15:29 +0000604 return 0;
605
606 if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
607 return 0;
608
paul7021c422003-07-15 12:52:22 +0000609 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifaddrmsg));
paul718e3742002-12-13 20:15:29 +0000610 if (len < 0)
611 return -1;
612
613 memset (tb, 0, sizeof tb);
614 netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len);
615
Feng Lu758fb8f2014-07-03 18:23:09 +0800616 ifp = if_lookup_by_index_vrf (ifa->ifa_index, vrf_id);
paul718e3742002-12-13 20:15:29 +0000617 if (ifp == NULL)
618 {
Feng Lu758fb8f2014-07-03 18:23:09 +0800619 zlog_err ("netlink_interface_addr can't find interface by index %d vrf %u",
620 ifa->ifa_index, vrf_id);
paul718e3742002-12-13 20:15:29 +0000621 return -1;
622 }
623
paul7021c422003-07-15 12:52:22 +0000624 if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */
paul718e3742002-12-13 20:15:29 +0000625 {
paul00df0c12002-12-13 21:07:36 +0000626 char buf[BUFSIZ];
Feng Lu758fb8f2014-07-03 18:23:09 +0800627 zlog_debug ("netlink_interface_addr %s %s vrf %u:",
628 lookup (nlmsg_str, h->nlmsg_type), ifp->name, vrf_id);
paul718e3742002-12-13 20:15:29 +0000629 if (tb[IFA_LOCAL])
hasso206d8052005-04-09 16:38:51 +0000630 zlog_debug (" IFA_LOCAL %s/%d",
631 inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]),
632 buf, BUFSIZ), ifa->ifa_prefixlen);
paul718e3742002-12-13 20:15:29 +0000633 if (tb[IFA_ADDRESS])
hasso206d8052005-04-09 16:38:51 +0000634 zlog_debug (" IFA_ADDRESS %s/%d",
635 inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_ADDRESS]),
636 buf, BUFSIZ), ifa->ifa_prefixlen);
paul718e3742002-12-13 20:15:29 +0000637 if (tb[IFA_BROADCAST])
hasso206d8052005-04-09 16:38:51 +0000638 zlog_debug (" IFA_BROADCAST %s/%d",
639 inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_BROADCAST]),
640 buf, BUFSIZ), ifa->ifa_prefixlen);
paul00df0c12002-12-13 21:07:36 +0000641 if (tb[IFA_LABEL] && strcmp (ifp->name, RTA_DATA (tb[IFA_LABEL])))
ajsb6178002004-12-07 21:12:56 +0000642 zlog_debug (" IFA_LABEL %s", (char *)RTA_DATA (tb[IFA_LABEL]));
pauld34b8992006-01-17 18:03:04 +0000643
644 if (tb[IFA_CACHEINFO])
645 {
646 struct ifa_cacheinfo *ci = RTA_DATA (tb[IFA_CACHEINFO]);
647 zlog_debug (" IFA_CACHEINFO pref %d, valid %d",
648 ci->ifa_prefered, ci->ifa_valid);
649 }
paul718e3742002-12-13 20:15:29 +0000650 }
paul31a476c2003-09-29 19:54:53 +0000651
Andrew J. Schorre4529632006-12-12 19:18:21 +0000652 /* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */
653 if (tb[IFA_LOCAL] == NULL)
654 tb[IFA_LOCAL] = tb[IFA_ADDRESS];
paul31a476c2003-09-29 19:54:53 +0000655 if (tb[IFA_ADDRESS] == NULL)
656 tb[IFA_ADDRESS] = tb[IFA_LOCAL];
657
Andrew J. Schorre4529632006-12-12 19:18:21 +0000658 /* local interface address */
659 addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL);
660
661 /* is there a peer address? */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000662 if (tb[IFA_ADDRESS] &&
vize068fd772007-08-10 06:25:20 +0000663 memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_ADDRESS])))
paul7021c422003-07-15 12:52:22 +0000664 {
Andrew J. Schorre4529632006-12-12 19:18:21 +0000665 broad = RTA_DATA(tb[IFA_ADDRESS]);
666 SET_FLAG (flags, ZEBRA_IFA_PEER);
paul7021c422003-07-15 12:52:22 +0000667 }
paul31a476c2003-09-29 19:54:53 +0000668 else
Andrew J. Schorre4529632006-12-12 19:18:21 +0000669 /* seeking a broadcast address */
670 broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST]) : NULL);
paul00df0c12002-12-13 21:07:36 +0000671
Paul Jakma27b47252006-07-02 16:38:54 +0000672 /* addr is primary key, SOL if we don't have one */
673 if (addr == NULL)
674 {
675 zlog_debug ("%s: NULL address", __func__);
676 return -1;
677 }
678
paul718e3742002-12-13 20:15:29 +0000679 /* Flags. */
680 if (ifa->ifa_flags & IFA_F_SECONDARY)
681 SET_FLAG (flags, ZEBRA_IFA_SECONDARY);
682
683 /* Label */
684 if (tb[IFA_LABEL])
685 label = (char *) RTA_DATA (tb[IFA_LABEL]);
686
687 if (ifp && label && strcmp (ifp->name, label) == 0)
688 label = NULL;
689
690 /* Register interface address to the interface. */
691 if (ifa->ifa_family == AF_INET)
692 {
paul7021c422003-07-15 12:52:22 +0000693 if (h->nlmsg_type == RTM_NEWADDR)
694 connected_add_ipv4 (ifp, flags,
695 (struct in_addr *) addr, ifa->ifa_prefixlen,
696 (struct in_addr *) broad, label);
697 else
698 connected_delete_ipv4 (ifp, flags,
699 (struct in_addr *) addr, ifa->ifa_prefixlen,
paul0752ef02005-11-03 12:35:21 +0000700 (struct in_addr *) broad);
paul718e3742002-12-13 20:15:29 +0000701 }
702#ifdef HAVE_IPV6
703 if (ifa->ifa_family == AF_INET6)
704 {
705 if (h->nlmsg_type == RTM_NEWADDR)
Andrew J. Schorre4529632006-12-12 19:18:21 +0000706 connected_add_ipv6 (ifp, flags,
paul7021c422003-07-15 12:52:22 +0000707 (struct in6_addr *) addr, ifa->ifa_prefixlen,
paul0752ef02005-11-03 12:35:21 +0000708 (struct in6_addr *) broad, label);
paul718e3742002-12-13 20:15:29 +0000709 else
paul7021c422003-07-15 12:52:22 +0000710 connected_delete_ipv6 (ifp,
711 (struct in6_addr *) addr, ifa->ifa_prefixlen,
712 (struct in6_addr *) broad);
paul718e3742002-12-13 20:15:29 +0000713 }
paul7021c422003-07-15 12:52:22 +0000714#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +0000715
716 return 0;
717}
718
719/* Looking up routing table by netlink interface. */
Stephen Hemminger6072b242008-08-14 16:52:26 +0100720static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800721netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
722 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000723{
724 int len;
725 struct rtmsg *rtm;
paul7021c422003-07-15 12:52:22 +0000726 struct rtattr *tb[RTA_MAX + 1];
paul718e3742002-12-13 20:15:29 +0000727 u_char flags = 0;
paul7021c422003-07-15 12:52:22 +0000728
729 char anyaddr[16] = { 0 };
paul718e3742002-12-13 20:15:29 +0000730
731 int index;
732 int table;
Timo Teräsb11f3b52015-11-02 16:50:07 +0200733 u_int32_t mtu = 0;
hasso34195bf2004-04-06 12:07:06 +0000734
paul718e3742002-12-13 20:15:29 +0000735 void *dest;
736 void *gate;
Paul Jakma7514fb72007-05-02 16:05:35 +0000737 void *src;
paul718e3742002-12-13 20:15:29 +0000738
739 rtm = NLMSG_DATA (h);
740
741 if (h->nlmsg_type != RTM_NEWROUTE)
742 return 0;
743 if (rtm->rtm_type != RTN_UNICAST)
744 return 0;
745
746 table = rtm->rtm_table;
paul7021c422003-07-15 12:52:22 +0000747#if 0 /* we weed them out later in rib_weed_tables () */
paulb21b19c2003-06-15 01:28:29 +0000748 if (table != RT_TABLE_MAIN && table != zebrad.rtm_table_default)
paul718e3742002-12-13 20:15:29 +0000749 return 0;
750#endif
751
paul7021c422003-07-15 12:52:22 +0000752 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
paul718e3742002-12-13 20:15:29 +0000753 if (len < 0)
754 return -1;
755
756 memset (tb, 0, sizeof tb);
757 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
758
759 if (rtm->rtm_flags & RTM_F_CLONED)
760 return 0;
761 if (rtm->rtm_protocol == RTPROT_REDIRECT)
762 return 0;
763 if (rtm->rtm_protocol == RTPROT_KERNEL)
764 return 0;
765
766 if (rtm->rtm_src_len != 0)
767 return 0;
768
769 /* Route which inserted by Zebra. */
770 if (rtm->rtm_protocol == RTPROT_ZEBRA)
771 flags |= ZEBRA_FLAG_SELFROUTE;
paul7021c422003-07-15 12:52:22 +0000772
paul718e3742002-12-13 20:15:29 +0000773 index = 0;
774 dest = NULL;
775 gate = NULL;
Paul Jakma7514fb72007-05-02 16:05:35 +0000776 src = NULL;
paul718e3742002-12-13 20:15:29 +0000777
778 if (tb[RTA_OIF])
779 index = *(int *) RTA_DATA (tb[RTA_OIF]);
780
781 if (tb[RTA_DST])
782 dest = RTA_DATA (tb[RTA_DST]);
783 else
784 dest = anyaddr;
785
Paul Jakma7514fb72007-05-02 16:05:35 +0000786 if (tb[RTA_PREFSRC])
787 src = RTA_DATA (tb[RTA_PREFSRC]);
788
paul718e3742002-12-13 20:15:29 +0000789 if (tb[RTA_GATEWAY])
790 gate = RTA_DATA (tb[RTA_GATEWAY]);
791
Timo Teräsb11f3b52015-11-02 16:50:07 +0200792 if (tb[RTA_METRICS])
793 {
794 struct rtattr *mxrta[RTAX_MAX+1];
795
796 memset (mxrta, 0, sizeof mxrta);
797 netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),
798 RTA_PAYLOAD(tb[RTA_METRICS]));
799
800 if (mxrta[RTAX_MTU])
801 mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]);
802 }
803
paul718e3742002-12-13 20:15:29 +0000804 if (rtm->rtm_family == AF_INET)
805 {
806 struct prefix_ipv4 p;
807 p.family = AF_INET;
808 memcpy (&p.prefix, dest, 4);
809 p.prefixlen = rtm->rtm_dst_len;
810
Josh Bailey26e2ae32012-03-22 01:09:21 -0700811 if (!tb[RTA_MULTIPATH])
812 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index,
Timo Teräs4d3ae712016-01-15 17:36:32 +0200813 vrf_id, table, 0, mtu, 0, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700814 else
815 {
816 /* This is a multipath route */
817
818 struct rib *rib;
819 struct rtnexthop *rtnh =
820 (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
821
822 len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
823
824 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
825 rib->type = ZEBRA_ROUTE_KERNEL;
826 rib->distance = 0;
827 rib->flags = flags;
Timo Teräs4d3ae712016-01-15 17:36:32 +0200828 rib->metric = 0;
Timo Teräsb11f3b52015-11-02 16:50:07 +0200829 rib->mtu = mtu;
Feng Lu758fb8f2014-07-03 18:23:09 +0800830 rib->vrf_id = vrf_id;
Josh Bailey26e2ae32012-03-22 01:09:21 -0700831 rib->table = table;
832 rib->nexthop_num = 0;
833 rib->uptime = time (NULL);
834
835 for (;;)
836 {
837 if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
838 break;
839
Josh Bailey26e2ae32012-03-22 01:09:21 -0700840 index = rtnh->rtnh_ifindex;
841 gate = 0;
842 if (rtnh->rtnh_len > sizeof (*rtnh))
843 {
844 memset (tb, 0, sizeof (tb));
845 netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
846 rtnh->rtnh_len - sizeof (*rtnh));
847 if (tb[RTA_GATEWAY])
848 gate = RTA_DATA (tb[RTA_GATEWAY]);
849 }
850
851 if (gate)
852 {
853 if (index)
854 nexthop_ipv4_ifindex_add (rib, gate, src, index);
855 else
856 nexthop_ipv4_add (rib, gate, src);
857 }
858 else
859 nexthop_ifindex_add (rib, index);
860
861 len -= NLMSG_ALIGN(rtnh->rtnh_len);
862 rtnh = RTNH_NEXT(rtnh);
863 }
864
865 if (rib->nexthop_num == 0)
866 XFREE (MTYPE_RIB, rib);
867 else
Avneesh Sachdev14d2bba2012-04-11 23:51:08 -0700868 rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700869 }
paul718e3742002-12-13 20:15:29 +0000870 }
871#ifdef HAVE_IPV6
872 if (rtm->rtm_family == AF_INET6)
873 {
874 struct prefix_ipv6 p;
875 p.family = AF_INET6;
876 memcpy (&p.prefix, dest, 16);
877 p.prefixlen = rtm->rtm_dst_len;
878
Feng Lu758fb8f2014-07-03 18:23:09 +0800879 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, vrf_id,
Timo Teräs4d3ae712016-01-15 17:36:32 +0200880 table, 0, mtu, 0, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000881 }
882#endif /* HAVE_IPV6 */
883
884 return 0;
885}
886
Stephen Hemminger1423c802008-08-14 17:59:25 +0100887static const struct message rtproto_str[] = {
paul718e3742002-12-13 20:15:29 +0000888 {RTPROT_REDIRECT, "redirect"},
889 {RTPROT_KERNEL, "kernel"},
890 {RTPROT_BOOT, "boot"},
891 {RTPROT_STATIC, "static"},
892 {RTPROT_GATED, "GateD"},
893 {RTPROT_RA, "router advertisement"},
894 {RTPROT_MRT, "MRT"},
895 {RTPROT_ZEBRA, "Zebra"},
896#ifdef RTPROT_BIRD
897 {RTPROT_BIRD, "BIRD"},
898#endif /* RTPROT_BIRD */
899 {0, NULL}
900};
901
902/* Routing information change from the kernel. */
Stephen Hemminger6072b242008-08-14 16:52:26 +0100903static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800904netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
905 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000906{
907 int len;
908 struct rtmsg *rtm;
paul7021c422003-07-15 12:52:22 +0000909 struct rtattr *tb[RTA_MAX + 1];
910
911 char anyaddr[16] = { 0 };
paul718e3742002-12-13 20:15:29 +0000912
913 int index;
914 int table;
Timo Teräsb11f3b52015-11-02 16:50:07 +0200915 u_int32_t mtu = 0;
Dmitry Popov83d16142011-09-11 13:48:25 +0400916
paul718e3742002-12-13 20:15:29 +0000917 void *dest;
918 void *gate;
Paul Jakma7514fb72007-05-02 16:05:35 +0000919 void *src;
paul718e3742002-12-13 20:15:29 +0000920
921 rtm = NLMSG_DATA (h);
922
paul7021c422003-07-15 12:52:22 +0000923 if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
paul718e3742002-12-13 20:15:29 +0000924 {
925 /* If this is not route add/delete message print warning. */
Feng Lu758fb8f2014-07-03 18:23:09 +0800926 zlog_warn ("Kernel message: %d vrf %u\n", h->nlmsg_type, vrf_id);
paul718e3742002-12-13 20:15:29 +0000927 return 0;
928 }
929
930 /* Connected route. */
931 if (IS_ZEBRA_DEBUG_KERNEL)
Feng Lu758fb8f2014-07-03 18:23:09 +0800932 zlog_debug ("%s %s %s proto %s vrf %u",
paul7021c422003-07-15 12:52:22 +0000933 h->nlmsg_type ==
934 RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
935 rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",
936 rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast",
Feng Lu758fb8f2014-07-03 18:23:09 +0800937 lookup (rtproto_str, rtm->rtm_protocol),
938 vrf_id);
paul718e3742002-12-13 20:15:29 +0000939
940 if (rtm->rtm_type != RTN_UNICAST)
941 {
942 return 0;
943 }
944
945 table = rtm->rtm_table;
paulb21b19c2003-06-15 01:28:29 +0000946 if (table != RT_TABLE_MAIN && table != zebrad.rtm_table_default)
paul718e3742002-12-13 20:15:29 +0000947 {
948 return 0;
949 }
950
paul7021c422003-07-15 12:52:22 +0000951 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
paul718e3742002-12-13 20:15:29 +0000952 if (len < 0)
953 return -1;
954
955 memset (tb, 0, sizeof tb);
956 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
957
958 if (rtm->rtm_flags & RTM_F_CLONED)
959 return 0;
960 if (rtm->rtm_protocol == RTPROT_REDIRECT)
961 return 0;
962 if (rtm->rtm_protocol == RTPROT_KERNEL)
963 return 0;
964
965 if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)
966 return 0;
967
968 if (rtm->rtm_src_len != 0)
969 {
Feng Lu758fb8f2014-07-03 18:23:09 +0800970 zlog_warn ("netlink_route_change(): no src len, vrf %u", vrf_id);
paul718e3742002-12-13 20:15:29 +0000971 return 0;
972 }
paul7021c422003-07-15 12:52:22 +0000973
paul718e3742002-12-13 20:15:29 +0000974 index = 0;
975 dest = NULL;
976 gate = NULL;
Paul Jakma7514fb72007-05-02 16:05:35 +0000977 src = NULL;
paul718e3742002-12-13 20:15:29 +0000978
979 if (tb[RTA_OIF])
980 index = *(int *) RTA_DATA (tb[RTA_OIF]);
981
982 if (tb[RTA_DST])
983 dest = RTA_DATA (tb[RTA_DST]);
984 else
985 dest = anyaddr;
986
987 if (tb[RTA_GATEWAY])
988 gate = RTA_DATA (tb[RTA_GATEWAY]);
989
Paul Jakma7514fb72007-05-02 16:05:35 +0000990 if (tb[RTA_PREFSRC])
991 src = RTA_DATA (tb[RTA_PREFSRC]);
992
Timo Teräsb11f3b52015-11-02 16:50:07 +0200993 if (h->nlmsg_type == RTM_NEWROUTE)
994 {
Timo Teräsb11f3b52015-11-02 16:50:07 +0200995 if (tb[RTA_METRICS])
996 {
997 struct rtattr *mxrta[RTAX_MAX+1];
998
999 memset (mxrta, 0, sizeof mxrta);
1000 netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),
1001 RTA_PAYLOAD(tb[RTA_METRICS]));
1002
1003 if (mxrta[RTAX_MTU])
1004 mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]);
1005 }
1006 }
Josh Bailey26e2ae32012-03-22 01:09:21 -07001007
paul718e3742002-12-13 20:15:29 +00001008 if (rtm->rtm_family == AF_INET)
1009 {
1010 struct prefix_ipv4 p;
1011 p.family = AF_INET;
1012 memcpy (&p.prefix, dest, 4);
1013 p.prefixlen = rtm->rtm_dst_len;
1014
1015 if (IS_ZEBRA_DEBUG_KERNEL)
paul7021c422003-07-15 12:52:22 +00001016 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001017 char buf[PREFIX_STRLEN];
Feng Lu758fb8f2014-07-03 18:23:09 +08001018 zlog_debug ("%s %s vrf %u",
Timo Teräsbe6335d2015-05-23 11:08:41 +03001019 h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
Feng Lu758fb8f2014-07-03 18:23:09 +08001020 prefix2str (&p, buf, sizeof(buf)), vrf_id);
paul7021c422003-07-15 12:52:22 +00001021 }
paul718e3742002-12-13 20:15:29 +00001022
1023 if (h->nlmsg_type == RTM_NEWROUTE)
Josh Bailey26e2ae32012-03-22 01:09:21 -07001024 {
1025 if (!tb[RTA_MULTIPATH])
Feng Lu758fb8f2014-07-03 18:23:09 +08001026 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, vrf_id,
Timo Teräs4d3ae712016-01-15 17:36:32 +02001027 table, 0, mtu, 0, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -07001028 else
1029 {
1030 /* This is a multipath route */
1031
1032 struct rib *rib;
1033 struct rtnexthop *rtnh =
1034 (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
1035
1036 len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
1037
1038 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1039 rib->type = ZEBRA_ROUTE_KERNEL;
1040 rib->distance = 0;
1041 rib->flags = 0;
Timo Teräs4d3ae712016-01-15 17:36:32 +02001042 rib->metric = 0;
Timo Teräsb11f3b52015-11-02 16:50:07 +02001043 rib->mtu = mtu;
Feng Lu758fb8f2014-07-03 18:23:09 +08001044 rib->vrf_id = vrf_id;
Josh Bailey26e2ae32012-03-22 01:09:21 -07001045 rib->table = table;
1046 rib->nexthop_num = 0;
1047 rib->uptime = time (NULL);
1048
1049 for (;;)
1050 {
1051 if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
1052 break;
1053
Josh Bailey26e2ae32012-03-22 01:09:21 -07001054 index = rtnh->rtnh_ifindex;
1055 gate = 0;
1056 if (rtnh->rtnh_len > sizeof (*rtnh))
1057 {
1058 memset (tb, 0, sizeof (tb));
1059 netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
1060 rtnh->rtnh_len - sizeof (*rtnh));
1061 if (tb[RTA_GATEWAY])
1062 gate = RTA_DATA (tb[RTA_GATEWAY]);
1063 }
1064
1065 if (gate)
1066 {
1067 if (index)
1068 nexthop_ipv4_ifindex_add (rib, gate, src, index);
1069 else
1070 nexthop_ipv4_add (rib, gate, src);
1071 }
1072 else
1073 nexthop_ifindex_add (rib, index);
1074
1075 len -= NLMSG_ALIGN(rtnh->rtnh_len);
1076 rtnh = RTNH_NEXT(rtnh);
1077 }
1078
1079 if (rib->nexthop_num == 0)
1080 XFREE (MTYPE_RIB, rib);
1081 else
Avneesh Sachdev14d2bba2012-04-11 23:51:08 -07001082 rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -07001083 }
1084 }
paul718e3742002-12-13 20:15:29 +00001085 else
Feng Lu758fb8f2014-07-03 18:23:09 +08001086 rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, vrf_id,
Feng Lu0d0686f2015-05-22 11:40:02 +02001087 SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001088 }
1089
1090#ifdef HAVE_IPV6
1091 if (rtm->rtm_family == AF_INET6)
1092 {
1093 struct prefix_ipv6 p;
paul718e3742002-12-13 20:15:29 +00001094
1095 p.family = AF_INET6;
1096 memcpy (&p.prefix, dest, 16);
1097 p.prefixlen = rtm->rtm_dst_len;
1098
1099 if (IS_ZEBRA_DEBUG_KERNEL)
paul7021c422003-07-15 12:52:22 +00001100 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001101 char buf[PREFIX_STRLEN];
Feng Lu758fb8f2014-07-03 18:23:09 +08001102 zlog_debug ("%s %s vrf %u",
Timo Teräsbe6335d2015-05-23 11:08:41 +03001103 h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
Feng Lu758fb8f2014-07-03 18:23:09 +08001104 prefix2str (&p, buf, sizeof(buf)), vrf_id);
paul7021c422003-07-15 12:52:22 +00001105 }
paul718e3742002-12-13 20:15:29 +00001106
1107 if (h->nlmsg_type == RTM_NEWROUTE)
Feng Lu758fb8f2014-07-03 18:23:09 +08001108 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, vrf_id, table,
Timo Teräs4d3ae712016-01-15 17:36:32 +02001109 0, mtu, 0, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001110 else
Feng Lu758fb8f2014-07-03 18:23:09 +08001111 rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, vrf_id,
Feng Lu0d0686f2015-05-22 11:40:02 +02001112 SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001113 }
1114#endif /* HAVE_IPV6 */
1115
1116 return 0;
1117}
1118
Stephen Hemminger6072b242008-08-14 16:52:26 +01001119static int
Feng Lu758fb8f2014-07-03 18:23:09 +08001120netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
1121 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001122{
1123 int len;
1124 struct ifinfomsg *ifi;
paul7021c422003-07-15 12:52:22 +00001125 struct rtattr *tb[IFLA_MAX + 1];
paul718e3742002-12-13 20:15:29 +00001126 struct interface *ifp;
1127 char *name;
1128
1129 ifi = NLMSG_DATA (h);
1130
paul7021c422003-07-15 12:52:22 +00001131 if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
paul718e3742002-12-13 20:15:29 +00001132 {
1133 /* If this is not link add/delete message so print warning. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001134 zlog_warn ("netlink_link_change: wrong kernel message %d vrf %u\n",
1135 h->nlmsg_type, vrf_id);
paul718e3742002-12-13 20:15:29 +00001136 return 0;
1137 }
1138
1139 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
1140 if (len < 0)
1141 return -1;
1142
1143 /* Looking up interface name. */
1144 memset (tb, 0, sizeof tb);
1145 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
paulc15cb242005-01-24 09:05:27 +00001146
paul1e193152005-02-14 23:53:05 +00001147#ifdef IFLA_WIRELESS
paulc15cb242005-01-24 09:05:27 +00001148 /* check for wireless messages to ignore */
1149 if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
1150 {
1151 if (IS_ZEBRA_DEBUG_KERNEL)
Feng Lu758fb8f2014-07-03 18:23:09 +08001152 zlog_debug ("%s: ignoring IFLA_WIRELESS message, vrf %u", __func__,
1153 vrf_id);
paulc15cb242005-01-24 09:05:27 +00001154 return 0;
1155 }
paul1e193152005-02-14 23:53:05 +00001156#endif /* IFLA_WIRELESS */
paulc15cb242005-01-24 09:05:27 +00001157
paul718e3742002-12-13 20:15:29 +00001158 if (tb[IFLA_IFNAME] == NULL)
1159 return -1;
paul7021c422003-07-15 12:52:22 +00001160 name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
paul718e3742002-12-13 20:15:29 +00001161
1162 /* Add interface. */
1163 if (h->nlmsg_type == RTM_NEWLINK)
1164 {
Feng Lu758fb8f2014-07-03 18:23:09 +08001165 ifp = if_lookup_by_name_vrf (name, vrf_id);
paul718e3742002-12-13 20:15:29 +00001166
paul7021c422003-07-15 12:52:22 +00001167 if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1168 {
1169 if (ifp == NULL)
Feng Lu758fb8f2014-07-03 18:23:09 +08001170 ifp = if_get_by_name_vrf (name, vrf_id);
paul718e3742002-12-13 20:15:29 +00001171
ajsd2fc8892005-04-02 18:38:43 +00001172 set_ifindex(ifp, ifi->ifi_index);
paul7021c422003-07-15 12:52:22 +00001173 ifp->flags = ifi->ifi_flags & 0x0000fffff;
paul44145db2004-05-09 11:00:23 +00001174 ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
Brett Cipherydb19c852013-10-03 13:48:54 +00001175 ifp->metric = 0;
paul718e3742002-12-13 20:15:29 +00001176
Josh Bailey26e2ae32012-03-22 01:09:21 -07001177 netlink_interface_update_hw_addr (tb, ifp);
1178
paul7021c422003-07-15 12:52:22 +00001179 /* If new link is added. */
1180 if_add_update (ifp);
1181 }
paul718e3742002-12-13 20:15:29 +00001182 else
paul7021c422003-07-15 12:52:22 +00001183 {
1184 /* Interface status change. */
ajsd2fc8892005-04-02 18:38:43 +00001185 set_ifindex(ifp, ifi->ifi_index);
paul44145db2004-05-09 11:00:23 +00001186 ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
Brett Cipherydb19c852013-10-03 13:48:54 +00001187 ifp->metric = 0;
paul718e3742002-12-13 20:15:29 +00001188
Josh Bailey26e2ae32012-03-22 01:09:21 -07001189 netlink_interface_update_hw_addr (tb, ifp);
1190
paul7021c422003-07-15 12:52:22 +00001191 if (if_is_operative (ifp))
1192 {
1193 ifp->flags = ifi->ifi_flags & 0x0000fffff;
1194 if (!if_is_operative (ifp))
1195 if_down (ifp);
ajsa608bbf2005-03-29 17:03:49 +00001196 else
1197 /* Must notify client daemons of new interface status. */
1198 zebra_interface_up_update (ifp);
paul7021c422003-07-15 12:52:22 +00001199 }
1200 else
1201 {
1202 ifp->flags = ifi->ifi_flags & 0x0000fffff;
1203 if (if_is_operative (ifp))
1204 if_up (ifp);
1205 }
1206 }
paul718e3742002-12-13 20:15:29 +00001207 }
1208 else
1209 {
1210 /* RTM_DELLINK. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001211 ifp = if_lookup_by_name_vrf (name, vrf_id);
paul718e3742002-12-13 20:15:29 +00001212
1213 if (ifp == NULL)
paul7021c422003-07-15 12:52:22 +00001214 {
Feng Lu758fb8f2014-07-03 18:23:09 +08001215 zlog_warn ("interface %s vrf %u is deleted but can't find",
1216 name, vrf_id);
paul7021c422003-07-15 12:52:22 +00001217 return 0;
1218 }
1219
paul718e3742002-12-13 20:15:29 +00001220 if_delete_update (ifp);
1221 }
1222
1223 return 0;
1224}
1225
Stephen Hemminger6072b242008-08-14 16:52:26 +01001226static int
Feng Lu758fb8f2014-07-03 18:23:09 +08001227netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h,
1228 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001229{
Stephen Hemminger3d265b42008-08-16 17:30:39 +01001230 /* JF: Ignore messages that aren't from the kernel */
1231 if ( snl->nl_pid != 0 )
1232 {
1233 zlog ( NULL, LOG_ERR, "Ignoring message from pid %u", snl->nl_pid );
1234 return 0;
1235 }
1236
paul718e3742002-12-13 20:15:29 +00001237 switch (h->nlmsg_type)
1238 {
1239 case RTM_NEWROUTE:
Feng Lu758fb8f2014-07-03 18:23:09 +08001240 return netlink_route_change (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001241 break;
1242 case RTM_DELROUTE:
Feng Lu758fb8f2014-07-03 18:23:09 +08001243 return netlink_route_change (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001244 break;
1245 case RTM_NEWLINK:
Feng Lu758fb8f2014-07-03 18:23:09 +08001246 return netlink_link_change (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001247 break;
1248 case RTM_DELLINK:
Feng Lu758fb8f2014-07-03 18:23:09 +08001249 return netlink_link_change (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001250 break;
1251 case RTM_NEWADDR:
Feng Lu758fb8f2014-07-03 18:23:09 +08001252 return netlink_interface_addr (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001253 break;
1254 case RTM_DELADDR:
Feng Lu758fb8f2014-07-03 18:23:09 +08001255 return netlink_interface_addr (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001256 break;
1257 default:
Feng Lu758fb8f2014-07-03 18:23:09 +08001258 zlog_warn ("Unknown netlink nlmsg_type %d vrf %u\n", h->nlmsg_type,
1259 vrf_id);
paul718e3742002-12-13 20:15:29 +00001260 break;
1261 }
1262 return 0;
1263}
1264
1265/* Interface lookup by netlink socket. */
1266int
Feng Lu758fb8f2014-07-03 18:23:09 +08001267interface_lookup_netlink (struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001268{
1269 int ret;
paul7021c422003-07-15 12:52:22 +00001270
paul718e3742002-12-13 20:15:29 +00001271 /* Get interface information. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001272 ret = netlink_request (AF_PACKET, RTM_GETLINK, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001273 if (ret < 0)
1274 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001275 ret = netlink_parse_info (netlink_interface, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001276 if (ret < 0)
1277 return ret;
1278
1279 /* Get IPv4 address of the interfaces. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001280 ret = netlink_request (AF_INET, RTM_GETADDR, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001281 if (ret < 0)
1282 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001283 ret = netlink_parse_info (netlink_interface_addr, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001284 if (ret < 0)
1285 return ret;
1286
1287#ifdef HAVE_IPV6
1288 /* Get IPv6 address of the interfaces. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001289 ret = netlink_request (AF_INET6, RTM_GETADDR, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001290 if (ret < 0)
1291 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001292 ret = netlink_parse_info (netlink_interface_addr, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001293 if (ret < 0)
1294 return ret;
1295#endif /* HAVE_IPV6 */
1296
1297 return 0;
1298}
1299
1300/* Routing table read function using netlink interface. Only called
1301 bootstrap time. */
1302int
Feng Lu758fb8f2014-07-03 18:23:09 +08001303netlink_route_read (struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001304{
1305 int ret;
paul7021c422003-07-15 12:52:22 +00001306
paul718e3742002-12-13 20:15:29 +00001307 /* Get IPv4 routing table. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001308 ret = netlink_request (AF_INET, RTM_GETROUTE, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001309 if (ret < 0)
1310 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001311 ret = netlink_parse_info (netlink_routing_table, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001312 if (ret < 0)
1313 return ret;
1314
1315#ifdef HAVE_IPV6
1316 /* Get IPv6 routing table. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001317 ret = netlink_request (AF_INET6, RTM_GETROUTE, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001318 if (ret < 0)
1319 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001320 ret = netlink_parse_info (netlink_routing_table, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001321 if (ret < 0)
1322 return ret;
1323#endif /* HAVE_IPV6 */
1324
1325 return 0;
1326}
1327
1328/* Utility function comes from iproute2.
1329 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001330int
Paul Jakma7aa9dce2014-09-19 14:42:23 +01001331addattr_l (struct nlmsghdr *n, size_t maxlen, int type, void *data, int alen)
paul718e3742002-12-13 20:15:29 +00001332{
Paul Jakma7aa9dce2014-09-19 14:42:23 +01001333 size_t len;
paul718e3742002-12-13 20:15:29 +00001334 struct rtattr *rta;
1335
paul7021c422003-07-15 12:52:22 +00001336 len = RTA_LENGTH (alen);
paul718e3742002-12-13 20:15:29 +00001337
paul7021c422003-07-15 12:52:22 +00001338 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
paul718e3742002-12-13 20:15:29 +00001339 return -1;
1340
paul7021c422003-07-15 12:52:22 +00001341 rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
paul718e3742002-12-13 20:15:29 +00001342 rta->rta_type = type;
1343 rta->rta_len = len;
paul7021c422003-07-15 12:52:22 +00001344 memcpy (RTA_DATA (rta), data, alen);
paul718e3742002-12-13 20:15:29 +00001345 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1346
1347 return 0;
1348}
1349
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001350int
paul718e3742002-12-13 20:15:29 +00001351rta_addattr_l (struct rtattr *rta, int maxlen, int type, void *data, int alen)
1352{
1353 int len;
1354 struct rtattr *subrta;
1355
paul7021c422003-07-15 12:52:22 +00001356 len = RTA_LENGTH (alen);
paul718e3742002-12-13 20:15:29 +00001357
paul7021c422003-07-15 12:52:22 +00001358 if (RTA_ALIGN (rta->rta_len) + len > maxlen)
paul718e3742002-12-13 20:15:29 +00001359 return -1;
1360
paul7021c422003-07-15 12:52:22 +00001361 subrta = (struct rtattr *) (((char *) rta) + RTA_ALIGN (rta->rta_len));
paul718e3742002-12-13 20:15:29 +00001362 subrta->rta_type = type;
1363 subrta->rta_len = len;
paul7021c422003-07-15 12:52:22 +00001364 memcpy (RTA_DATA (subrta), data, alen);
paul718e3742002-12-13 20:15:29 +00001365 rta->rta_len = NLMSG_ALIGN (rta->rta_len) + len;
1366
1367 return 0;
1368}
1369
1370/* Utility function comes from iproute2.
1371 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001372int
Paul Jakma7aa9dce2014-09-19 14:42:23 +01001373addattr32 (struct nlmsghdr *n, size_t maxlen, int type, int data)
paul718e3742002-12-13 20:15:29 +00001374{
Paul Jakma7aa9dce2014-09-19 14:42:23 +01001375 size_t len;
paul718e3742002-12-13 20:15:29 +00001376 struct rtattr *rta;
paul7021c422003-07-15 12:52:22 +00001377
1378 len = RTA_LENGTH (4);
1379
paul718e3742002-12-13 20:15:29 +00001380 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
1381 return -1;
1382
paul7021c422003-07-15 12:52:22 +00001383 rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
paul718e3742002-12-13 20:15:29 +00001384 rta->rta_type = type;
1385 rta->rta_len = len;
paul7021c422003-07-15 12:52:22 +00001386 memcpy (RTA_DATA (rta), &data, 4);
paul718e3742002-12-13 20:15:29 +00001387 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1388
1389 return 0;
1390}
1391
1392static int
Feng Lu758fb8f2014-07-03 18:23:09 +08001393netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h,
1394 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001395{
Feng Lu758fb8f2014-07-03 18:23:09 +08001396 zlog_warn ("netlink_talk: ignoring message type 0x%04x vrf %u", h->nlmsg_type,
1397 vrf_id);
paul718e3742002-12-13 20:15:29 +00001398 return 0;
1399}
1400
1401/* sendmsg() to netlink socket then recvmsg(). */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001402static int
Feng Lu758fb8f2014-07-03 18:23:09 +08001403netlink_talk (struct nlmsghdr *n, struct nlsock *nl, struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001404{
1405 int status;
1406 struct sockaddr_nl snl;
Timo Teräsc299ed72014-07-29 09:41:55 +00001407 struct iovec iov = {
1408 .iov_base = (void *) n,
1409 .iov_len = n->nlmsg_len
1410 };
1411 struct msghdr msg = {
1412 .msg_name = (void *) &snl,
1413 .msg_namelen = sizeof snl,
1414 .msg_iov = &iov,
1415 .msg_iovlen = 1,
1416 };
ajs4be019d2005-01-29 16:12:41 +00001417 int save_errno;
paul7021c422003-07-15 12:52:22 +00001418
paul718e3742002-12-13 20:15:29 +00001419 memset (&snl, 0, sizeof snl);
1420 snl.nl_family = AF_NETLINK;
paul7021c422003-07-15 12:52:22 +00001421
hassob7ed1ec2005-03-31 20:13:49 +00001422 n->nlmsg_seq = ++nl->seq;
paul718e3742002-12-13 20:15:29 +00001423
1424 /* Request an acknowledgement by setting NLM_F_ACK */
1425 n->nlmsg_flags |= NLM_F_ACK;
paul7021c422003-07-15 12:52:22 +00001426
1427 if (IS_ZEBRA_DEBUG_KERNEL)
hassob7ed1ec2005-03-31 20:13:49 +00001428 zlog_debug ("netlink_talk: %s type %s(%u), seq=%u", nl->name,
paul7021c422003-07-15 12:52:22 +00001429 lookup (nlmsg_str, n->nlmsg_type), n->nlmsg_type,
1430 n->nlmsg_seq);
paul718e3742002-12-13 20:15:29 +00001431
1432 /* Send message to netlink interface. */
paul7021c422003-07-15 12:52:22 +00001433 if (zserv_privs.change (ZPRIVS_RAISE))
1434 zlog (NULL, LOG_ERR, "Can't raise privileges");
paul718e3742002-12-13 20:15:29 +00001435 status = sendmsg (nl->sock, &msg, 0);
ajs4be019d2005-01-29 16:12:41 +00001436 save_errno = errno;
paul7021c422003-07-15 12:52:22 +00001437 if (zserv_privs.change (ZPRIVS_LOWER))
1438 zlog (NULL, LOG_ERR, "Can't lower privileges");
1439
paul718e3742002-12-13 20:15:29 +00001440 if (status < 0)
1441 {
1442 zlog (NULL, LOG_ERR, "netlink_talk sendmsg() error: %s",
ajs4be019d2005-01-29 16:12:41 +00001443 safe_strerror (save_errno));
paul718e3742002-12-13 20:15:29 +00001444 return -1;
1445 }
paul7021c422003-07-15 12:52:22 +00001446
paul718e3742002-12-13 20:15:29 +00001447
1448 /*
1449 * Get reply from netlink socket.
1450 * The reply should either be an acknowlegement or an error.
1451 */
Feng Lu758fb8f2014-07-03 18:23:09 +08001452 return netlink_parse_info (netlink_talk_filter, nl, zvrf);
paul718e3742002-12-13 20:15:29 +00001453}
1454
Christian Frankefa713d92013-07-05 15:35:37 +00001455/* This function takes a nexthop as argument and adds
1456 * the appropriate netlink attributes to an existing
1457 * netlink message.
1458 *
1459 * @param routedesc: Human readable description of route type
1460 * (direct/recursive, single-/multipath)
1461 * @param bytelen: Length of addresses in bytes.
1462 * @param nexthop: Nexthop information
1463 * @param nlmsg: nlmsghdr structure to fill in.
1464 * @param req_size: The size allocated for the message.
1465 */
1466static void
1467_netlink_route_build_singlepath(
1468 const char *routedesc,
1469 int bytelen,
1470 struct nexthop *nexthop,
1471 struct nlmsghdr *nlmsg,
Christian Frankee8d3d292013-07-05 15:35:39 +00001472 struct rtmsg *rtmsg,
Christian Frankefa713d92013-07-05 15:35:37 +00001473 size_t req_size)
1474{
Christian Frankee8d3d292013-07-05 15:35:39 +00001475 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
1476 rtmsg->rtm_flags |= RTNH_F_ONLINK;
Christian Frankefa713d92013-07-05 15:35:37 +00001477 if (nexthop->type == NEXTHOP_TYPE_IPV4
1478 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1479 {
1480 addattr_l (nlmsg, req_size, RTA_GATEWAY,
1481 &nexthop->gate.ipv4, bytelen);
1482 if (nexthop->src.ipv4.s_addr)
1483 addattr_l (nlmsg, req_size, RTA_PREFSRC,
1484 &nexthop->src.ipv4, bytelen);
1485
1486 if (IS_ZEBRA_DEBUG_KERNEL)
1487 zlog_debug("netlink_route_multipath() (%s): "
1488 "nexthop via %s if %u",
1489 routedesc,
1490 inet_ntoa (nexthop->gate.ipv4),
1491 nexthop->ifindex);
1492 }
1493#ifdef HAVE_IPV6
1494 if (nexthop->type == NEXTHOP_TYPE_IPV6
1495 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1496 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1497 {
1498 addattr_l (nlmsg, req_size, RTA_GATEWAY,
1499 &nexthop->gate.ipv6, bytelen);
1500
1501 if (IS_ZEBRA_DEBUG_KERNEL)
1502 zlog_debug("netlink_route_multipath() (%s): "
1503 "nexthop via %s if %u",
1504 routedesc,
1505 inet6_ntoa (nexthop->gate.ipv6),
1506 nexthop->ifindex);
1507 }
1508#endif /* HAVE_IPV6 */
1509 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1510 || nexthop->type == NEXTHOP_TYPE_IFNAME
1511 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1512 {
1513 addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
1514
1515 if (nexthop->src.ipv4.s_addr)
1516 addattr_l (nlmsg, req_size, RTA_PREFSRC,
1517 &nexthop->src.ipv4, bytelen);
1518
1519 if (IS_ZEBRA_DEBUG_KERNEL)
1520 zlog_debug("netlink_route_multipath() (%s): "
1521 "nexthop via if %u", routedesc, nexthop->ifindex);
1522 }
1523
1524 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
1525 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
1526 {
1527 addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
1528
1529 if (IS_ZEBRA_DEBUG_KERNEL)
1530 zlog_debug("netlink_route_multipath() (%s): "
1531 "nexthop via if %u", routedesc, nexthop->ifindex);
1532 }
1533}
1534
1535/* This function takes a nexthop as argument and
1536 * appends to the given rtattr/rtnexthop pair the
1537 * representation of the nexthop. If the nexthop
1538 * defines a preferred source, the src parameter
1539 * will be modified to point to that src, otherwise
1540 * it will be kept unmodified.
1541 *
1542 * @param routedesc: Human readable description of route type
1543 * (direct/recursive, single-/multipath)
1544 * @param bytelen: Length of addresses in bytes.
1545 * @param nexthop: Nexthop information
1546 * @param rta: rtnetlink attribute structure
1547 * @param rtnh: pointer to an rtnetlink nexthop structure
1548 * @param src: pointer pointing to a location where
1549 * the prefsrc should be stored.
1550 */
1551static void
1552_netlink_route_build_multipath(
1553 const char *routedesc,
1554 int bytelen,
1555 struct nexthop *nexthop,
1556 struct rtattr *rta,
1557 struct rtnexthop *rtnh,
1558 union g_addr **src
1559 )
1560{
1561 rtnh->rtnh_len = sizeof (*rtnh);
1562 rtnh->rtnh_flags = 0;
1563 rtnh->rtnh_hops = 0;
1564 rta->rta_len += rtnh->rtnh_len;
1565
Christian Frankee8d3d292013-07-05 15:35:39 +00001566 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
1567 rtnh->rtnh_flags |= RTNH_F_ONLINK;
1568
Christian Frankefa713d92013-07-05 15:35:37 +00001569 if (nexthop->type == NEXTHOP_TYPE_IPV4
1570 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1571 {
1572 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
1573 &nexthop->gate.ipv4, bytelen);
Lu Feng621e2aa2014-07-11 07:52:15 +00001574 rtnh->rtnh_len += sizeof (struct rtattr) + bytelen;
Christian Frankefa713d92013-07-05 15:35:37 +00001575
1576 if (nexthop->src.ipv4.s_addr)
1577 *src = &nexthop->src;
1578
1579 if (IS_ZEBRA_DEBUG_KERNEL)
1580 zlog_debug("netlink_route_multipath() (%s): "
1581 "nexthop via %s if %u",
1582 routedesc,
1583 inet_ntoa (nexthop->gate.ipv4),
1584 nexthop->ifindex);
1585 }
1586#ifdef HAVE_IPV6
1587 if (nexthop->type == NEXTHOP_TYPE_IPV6
1588 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1589 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1590 {
1591 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
1592 &nexthop->gate.ipv6, bytelen);
Lu Feng621e2aa2014-07-11 07:52:15 +00001593 rtnh->rtnh_len += sizeof (struct rtattr) + bytelen;
Christian Frankefa713d92013-07-05 15:35:37 +00001594
1595 if (IS_ZEBRA_DEBUG_KERNEL)
1596 zlog_debug("netlink_route_multipath() (%s): "
1597 "nexthop via %s if %u",
1598 routedesc,
1599 inet6_ntoa (nexthop->gate.ipv6),
1600 nexthop->ifindex);
1601 }
1602#endif /* HAVE_IPV6 */
1603 /* ifindex */
1604 if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1605 || nexthop->type == NEXTHOP_TYPE_IFINDEX
1606 || nexthop->type == NEXTHOP_TYPE_IFNAME)
1607 {
1608 rtnh->rtnh_ifindex = nexthop->ifindex;
1609 if (nexthop->src.ipv4.s_addr)
1610 *src = &nexthop->src;
1611 if (IS_ZEBRA_DEBUG_KERNEL)
1612 zlog_debug("netlink_route_multipath() (%s): "
1613 "nexthop via if %u", routedesc, nexthop->ifindex);
1614 }
1615 else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1616 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1617 {
1618 rtnh->rtnh_ifindex = nexthop->ifindex;
1619
1620 if (IS_ZEBRA_DEBUG_KERNEL)
1621 zlog_debug("netlink_route_multipath() (%s): "
1622 "nexthop via if %u", routedesc, nexthop->ifindex);
1623 }
1624 else
1625 {
1626 rtnh->rtnh_ifindex = 0;
1627 }
1628}
1629
1630/* Log debug information for netlink_route_multipath
1631 * if debug logging is enabled.
1632 *
1633 * @param cmd: Netlink command which is to be processed
1634 * @param p: Prefix for which the change is due
1635 * @param nexthop: Nexthop which is currently processed
1636 * @param routedesc: Semantic annotation for nexthop
1637 * (recursive, multipath, etc.)
1638 * @param family: Address family which the change concerns
1639 */
1640static void
1641_netlink_route_debug(
1642 int cmd,
1643 struct prefix *p,
1644 struct nexthop *nexthop,
1645 const char *routedesc,
Feng Lu758fb8f2014-07-03 18:23:09 +08001646 int family,
1647 struct zebra_vrf *zvrf)
Christian Frankefa713d92013-07-05 15:35:37 +00001648{
1649 if (IS_ZEBRA_DEBUG_KERNEL)
1650 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001651 char buf[PREFIX_STRLEN];
Feng Lu758fb8f2014-07-03 18:23:09 +08001652 zlog_debug ("netlink_route_multipath() (%s): %s %s vrf %u type %s",
Christian Frankefa713d92013-07-05 15:35:37 +00001653 routedesc,
1654 lookup (nlmsg_str, cmd),
Timo Teräsbe6335d2015-05-23 11:08:41 +03001655 prefix2str (p, buf, sizeof(buf)),
Kaloyan Kovachev8c56b442015-06-15 17:08:48 +03001656 zvrf->vrf_id,
Timo Teräsbe6335d2015-05-23 11:08:41 +03001657 nexthop_type_to_str (nexthop->type));
Christian Frankefa713d92013-07-05 15:35:37 +00001658 }
1659}
1660
paul718e3742002-12-13 20:15:29 +00001661/* Routing table change via netlink interface. */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001662static int
Timo Teräs0abf6792016-01-15 17:36:29 +02001663netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001664{
1665 int bytelen;
1666 struct sockaddr_nl snl;
Christian Frankefa713d92013-07-05 15:35:37 +00001667 struct nexthop *nexthop = NULL, *tnexthop;
1668 int recursing;
1669 int nexthop_num;
paul718e3742002-12-13 20:15:29 +00001670 int discard;
Timo Teräs0abf6792016-01-15 17:36:29 +02001671 int family = PREFIX_FAMILY(p);
Christian Frankefa713d92013-07-05 15:35:37 +00001672 const char *routedesc;
paul718e3742002-12-13 20:15:29 +00001673
paul7021c422003-07-15 12:52:22 +00001674 struct
paul718e3742002-12-13 20:15:29 +00001675 {
1676 struct nlmsghdr n;
1677 struct rtmsg r;
JR Rivers3cadc0c2012-04-01 12:16:31 -07001678 char buf[NL_PKT_BUF_SIZE];
paul718e3742002-12-13 20:15:29 +00001679 } req;
1680
Feng Lu758fb8f2014-07-03 18:23:09 +08001681 struct zebra_vrf *zvrf = vrf_info_lookup (rib->vrf_id);
1682
Jorge Boncompte [DTI2]a4c06de2012-04-20 14:28:40 +02001683 memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
paul718e3742002-12-13 20:15:29 +00001684
1685 bytelen = (family == AF_INET ? 4 : 16);
1686
1687 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
Timo Teräs0abf6792016-01-15 17:36:29 +02001688 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REPLACE | NLM_F_REQUEST;
paul718e3742002-12-13 20:15:29 +00001689 req.n.nlmsg_type = cmd;
1690 req.r.rtm_family = family;
1691 req.r.rtm_table = rib->table;
1692 req.r.rtm_dst_len = p->prefixlen;
Timo Teräs40da2212008-08-13 17:37:14 +01001693 req.r.rtm_protocol = RTPROT_ZEBRA;
Timo Teräs82a66352016-01-15 17:36:30 +02001694 req.r.rtm_scope = RT_SCOPE_LINK;
paul718e3742002-12-13 20:15:29 +00001695
paul7021c422003-07-15 12:52:22 +00001696 if ((rib->flags & ZEBRA_FLAG_BLACKHOLE) || (rib->flags & ZEBRA_FLAG_REJECT))
paul718e3742002-12-13 20:15:29 +00001697 discard = 1;
1698 else
1699 discard = 0;
1700
paul7021c422003-07-15 12:52:22 +00001701 if (cmd == RTM_NEWROUTE)
paul718e3742002-12-13 20:15:29 +00001702 {
paul7021c422003-07-15 12:52:22 +00001703 if (discard)
paul595db7f2003-05-25 21:35:06 +00001704 {
1705 if (rib->flags & ZEBRA_FLAG_BLACKHOLE)
1706 req.r.rtm_type = RTN_BLACKHOLE;
1707 else if (rib->flags & ZEBRA_FLAG_REJECT)
1708 req.r.rtm_type = RTN_UNREACHABLE;
paul7021c422003-07-15 12:52:22 +00001709 else
1710 assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
1711 }
paul595db7f2003-05-25 21:35:06 +00001712 else
paul7021c422003-07-15 12:52:22 +00001713 req.r.rtm_type = RTN_UNICAST;
paul718e3742002-12-13 20:15:29 +00001714 }
1715
1716 addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
1717
1718 /* Metric. */
Timo Teräs4d3ae712016-01-15 17:36:32 +02001719 addattr32 (&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC);
paul718e3742002-12-13 20:15:29 +00001720
Timo Teräsb11f3b52015-11-02 16:50:07 +02001721 if (rib->mtu || rib->nexthop_mtu)
1722 {
1723 char buf[NL_PKT_BUF_SIZE];
1724 struct rtattr *rta = (void *) buf;
1725 u_int32_t mtu = rib->mtu;
1726 if (!mtu || (rib->nexthop_mtu && rib->nexthop_mtu < mtu))
1727 mtu = rib->nexthop_mtu;
1728 rta->rta_type = RTA_METRICS;
1729 rta->rta_len = RTA_LENGTH(0);
1730 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTAX_MTU, &mtu, sizeof mtu);
1731 addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA (rta),
1732 RTA_PAYLOAD (rta));
1733 }
1734
paul718e3742002-12-13 20:15:29 +00001735 if (discard)
1736 {
1737 if (cmd == RTM_NEWROUTE)
Christian Frankefa713d92013-07-05 15:35:37 +00001738 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1739 {
1740 /* We shouldn't encounter recursive nexthops on discard routes,
1741 * but it is probably better to handle that case correctly anyway.
1742 */
1743 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1744 continue;
1745 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1746 }
paul718e3742002-12-13 20:15:29 +00001747 goto skip;
1748 }
1749
Christian Frankefa713d92013-07-05 15:35:37 +00001750 /* Count overall nexthops so we can decide whether to use singlepath
1751 * or multipath case. */
1752 nexthop_num = 0;
1753 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001754 {
Christian Frankefa713d92013-07-05 15:35:37 +00001755 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1756 continue;
1757 if (cmd == RTM_NEWROUTE && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1758 continue;
1759 if (cmd == RTM_DELROUTE && !CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1760 continue;
1761
Timo Teräs82a66352016-01-15 17:36:30 +02001762 if (nexthop->type != NEXTHOP_TYPE_IFINDEX &&
1763 nexthop->type != NEXTHOP_TYPE_IFNAME)
1764 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1765
Christian Frankefa713d92013-07-05 15:35:37 +00001766 nexthop_num++;
1767 }
1768
1769 /* Singlepath case. */
1770 if (nexthop_num == 1 || MULTIPATH_NUM == 1)
1771 {
1772 nexthop_num = 0;
1773 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul7021c422003-07-15 12:52:22 +00001774 {
Christian Frankefa713d92013-07-05 15:35:37 +00001775 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1776 continue;
paul5ec90d22003-06-19 01:41:37 +00001777
paul7021c422003-07-15 12:52:22 +00001778 if ((cmd == RTM_NEWROUTE
1779 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1780 || (cmd == RTM_DELROUTE
1781 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1782 {
Christian Frankefa713d92013-07-05 15:35:37 +00001783 routedesc = recursing ? "recursive, 1 hop" : "single hop";
paul5ec90d22003-06-19 01:41:37 +00001784
Feng Lu758fb8f2014-07-03 18:23:09 +08001785 _netlink_route_debug(cmd, p, nexthop, routedesc, family, zvrf);
Christian Frankefa713d92013-07-05 15:35:37 +00001786 _netlink_route_build_singlepath(routedesc, bytelen,
Christian Frankee8d3d292013-07-05 15:35:39 +00001787 nexthop, &req.n, &req.r,
1788 sizeof req);
paul718e3742002-12-13 20:15:29 +00001789
paul7021c422003-07-15 12:52:22 +00001790 if (cmd == RTM_NEWROUTE)
1791 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
paul718e3742002-12-13 20:15:29 +00001792
paul7021c422003-07-15 12:52:22 +00001793 nexthop_num++;
1794 break;
1795 }
1796 }
paul718e3742002-12-13 20:15:29 +00001797 }
1798 else
1799 {
JR Rivers3cadc0c2012-04-01 12:16:31 -07001800 char buf[NL_PKT_BUF_SIZE];
paul718e3742002-12-13 20:15:29 +00001801 struct rtattr *rta = (void *) buf;
1802 struct rtnexthop *rtnh;
Paul Jakma7514fb72007-05-02 16:05:35 +00001803 union g_addr *src = NULL;
paul718e3742002-12-13 20:15:29 +00001804
1805 rta->rta_type = RTA_MULTIPATH;
paul7021c422003-07-15 12:52:22 +00001806 rta->rta_len = RTA_LENGTH (0);
1807 rtnh = RTA_DATA (rta);
paul718e3742002-12-13 20:15:29 +00001808
1809 nexthop_num = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001810 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul7021c422003-07-15 12:52:22 +00001811 {
Christian Frankefa713d92013-07-05 15:35:37 +00001812 if (MULTIPATH_NUM != 0 && nexthop_num >= MULTIPATH_NUM)
1813 break;
1814
1815 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1816 continue;
1817
paul7021c422003-07-15 12:52:22 +00001818 if ((cmd == RTM_NEWROUTE
1819 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1820 || (cmd == RTM_DELROUTE
1821 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1822 {
Christian Frankefa713d92013-07-05 15:35:37 +00001823 routedesc = recursing ? "recursive, multihop" : "multihop";
paul7021c422003-07-15 12:52:22 +00001824 nexthop_num++;
paul718e3742002-12-13 20:15:29 +00001825
Christian Frankefa713d92013-07-05 15:35:37 +00001826 _netlink_route_debug(cmd, p, nexthop,
Feng Lu758fb8f2014-07-03 18:23:09 +08001827 routedesc, family, zvrf);
Christian Frankefa713d92013-07-05 15:35:37 +00001828 _netlink_route_build_multipath(routedesc, bytelen,
1829 nexthop, rta, rtnh, &src);
paul7021c422003-07-15 12:52:22 +00001830 rtnh = RTNH_NEXT (rtnh);
paul718e3742002-12-13 20:15:29 +00001831
paul7021c422003-07-15 12:52:22 +00001832 if (cmd == RTM_NEWROUTE)
1833 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1834 }
1835 }
Paul Jakma7514fb72007-05-02 16:05:35 +00001836 if (src)
1837 addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src->ipv4, bytelen);
paul718e3742002-12-13 20:15:29 +00001838
1839 if (rta->rta_len > RTA_LENGTH (0))
JR Rivers3cadc0c2012-04-01 12:16:31 -07001840 addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta),
paul7021c422003-07-15 12:52:22 +00001841 RTA_PAYLOAD (rta));
paul718e3742002-12-13 20:15:29 +00001842 }
1843
1844 /* If there is no useful nexthop then return. */
1845 if (nexthop_num == 0)
1846 {
1847 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +00001848 zlog_debug ("netlink_route_multipath(): No useful nexthop.");
paul718e3742002-12-13 20:15:29 +00001849 return 0;
1850 }
1851
paul7021c422003-07-15 12:52:22 +00001852skip:
paul718e3742002-12-13 20:15:29 +00001853
1854 /* Destination netlink address. */
1855 memset (&snl, 0, sizeof snl);
1856 snl.nl_family = AF_NETLINK;
1857
paul718e3742002-12-13 20:15:29 +00001858 /* Talk to netlink socket. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001859 return netlink_talk (&req.n, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001860}
1861
1862int
Timo Teräs0abf6792016-01-15 17:36:29 +02001863kernel_route_rib (struct prefix *p, struct rib *old, struct rib *new)
paul718e3742002-12-13 20:15:29 +00001864{
Timo Teräs0abf6792016-01-15 17:36:29 +02001865 if (!old && new)
1866 return netlink_route_multipath (RTM_NEWROUTE, p, new);
1867 if (old && !new)
1868 return netlink_route_multipath (RTM_DELROUTE, p, old);
paul718e3742002-12-13 20:15:29 +00001869
Timo Teräs4d3ae712016-01-15 17:36:32 +02001870 /* Replace, can be done atomically if metric does not change;
1871 * netlink uses [prefix, tos, priority] to identify prefix.
1872 * Now metric is not sent to kernel, so we can just do atomic replace. */
1873 return netlink_route_multipath (RTM_NEWROUTE, p, new);
paul718e3742002-12-13 20:15:29 +00001874}
David Lamparter6b0655a2014-06-04 06:53:35 +02001875
paul718e3742002-12-13 20:15:29 +00001876/* Interface address modification. */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001877static int
paul718e3742002-12-13 20:15:29 +00001878netlink_address (int cmd, int family, struct interface *ifp,
paul7021c422003-07-15 12:52:22 +00001879 struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001880{
1881 int bytelen;
1882 struct prefix *p;
1883
paul7021c422003-07-15 12:52:22 +00001884 struct
paul718e3742002-12-13 20:15:29 +00001885 {
1886 struct nlmsghdr n;
1887 struct ifaddrmsg ifa;
JR Rivers3cadc0c2012-04-01 12:16:31 -07001888 char buf[NL_PKT_BUF_SIZE];
paul718e3742002-12-13 20:15:29 +00001889 } req;
1890
Feng Lu758fb8f2014-07-03 18:23:09 +08001891 struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
1892
paul718e3742002-12-13 20:15:29 +00001893 p = ifc->address;
Jorge Boncompte [DTI2]a4c06de2012-04-20 14:28:40 +02001894 memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
paul718e3742002-12-13 20:15:29 +00001895
1896 bytelen = (family == AF_INET ? 4 : 16);
1897
paul7021c422003-07-15 12:52:22 +00001898 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg));
paul718e3742002-12-13 20:15:29 +00001899 req.n.nlmsg_flags = NLM_F_REQUEST;
1900 req.n.nlmsg_type = cmd;
1901 req.ifa.ifa_family = family;
1902
1903 req.ifa.ifa_index = ifp->ifindex;
1904 req.ifa.ifa_prefixlen = p->prefixlen;
1905
1906 addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen);
1907
1908 if (family == AF_INET && cmd == RTM_NEWADDR)
1909 {
Andrew J. Schorre4529632006-12-12 19:18:21 +00001910 if (!CONNECTED_PEER(ifc) && ifc->destination)
paul7021c422003-07-15 12:52:22 +00001911 {
1912 p = ifc->destination;
1913 addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix,
1914 bytelen);
1915 }
paul718e3742002-12-13 20:15:29 +00001916 }
1917
1918 if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
1919 SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY);
paul7021c422003-07-15 12:52:22 +00001920
paul718e3742002-12-13 20:15:29 +00001921 if (ifc->label)
1922 addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label,
paul7021c422003-07-15 12:52:22 +00001923 strlen (ifc->label) + 1);
paul718e3742002-12-13 20:15:29 +00001924
Feng Lu758fb8f2014-07-03 18:23:09 +08001925 return netlink_talk (&req.n, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001926}
1927
1928int
1929kernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc)
1930{
1931 return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc);
1932}
1933
1934int
1935kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc)
1936{
1937 return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc);
1938}
1939
paul718e3742002-12-13 20:15:29 +00001940
1941extern struct thread_master *master;
1942
1943/* Kernel route reflection. */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001944static int
paul718e3742002-12-13 20:15:29 +00001945kernel_read (struct thread *thread)
1946{
Feng Lu758fb8f2014-07-03 18:23:09 +08001947 struct zebra_vrf *zvrf = (struct zebra_vrf *)THREAD_ARG (thread);
1948 netlink_parse_info (netlink_information_fetch, &zvrf->netlink, zvrf);
1949 zvrf->t_netlink = thread_add_read (zebrad.master, kernel_read, zvrf,
1950 zvrf->netlink.sock);
paul718e3742002-12-13 20:15:29 +00001951
1952 return 0;
1953}
1954
Stephen Hemminger3d265b42008-08-16 17:30:39 +01001955/* Filter out messages from self that occur on listener socket,
1956 caused by our actions on the command socket
1957 */
1958static void netlink_install_filter (int sock, __u32 pid)
Paul Jakma768a27e2008-05-29 18:23:08 +00001959{
Paul Jakma768a27e2008-05-29 18:23:08 +00001960 struct sock_filter filter[] = {
Stephen Hemminger3d265b42008-08-16 17:30:39 +01001961 /* 0: ldh [4] */
1962 BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)),
1963 /* 1: jeq 0x18 jt 3 jf 6 */
1964 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 1, 0),
1965 /* 2: jeq 0x19 jt 3 jf 6 */
1966 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 0, 3),
1967 /* 3: ldw [12] */
1968 BPF_STMT(BPF_LD|BPF_ABS|BPF_W, offsetof(struct nlmsghdr, nlmsg_pid)),
1969 /* 4: jeq XX jt 5 jf 6 */
1970 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htonl(pid), 0, 1),
1971 /* 5: ret 0 (skip) */
1972 BPF_STMT(BPF_RET|BPF_K, 0),
1973 /* 6: ret 0xffff (keep) */
1974 BPF_STMT(BPF_RET|BPF_K, 0xffff),
Paul Jakma768a27e2008-05-29 18:23:08 +00001975 };
1976
1977 struct sock_fprog prog = {
Balaji.G837d16c2012-09-26 14:09:10 +05301978 .len = array_size(filter),
Paul Jakma768a27e2008-05-29 18:23:08 +00001979 .filter = filter,
1980 };
1981
1982 if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)) < 0)
1983 zlog_warn ("Can't install socket filter: %s\n", safe_strerror(errno));
1984}
1985
paul718e3742002-12-13 20:15:29 +00001986/* Exported interface function. This function simply calls
1987 netlink_socket (). */
1988void
Feng Lu758fb8f2014-07-03 18:23:09 +08001989kernel_init (struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001990{
1991 unsigned long groups;
1992
paul7021c422003-07-15 12:52:22 +00001993 groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR;
paul718e3742002-12-13 20:15:29 +00001994#ifdef HAVE_IPV6
paul7021c422003-07-15 12:52:22 +00001995 groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR;
paul718e3742002-12-13 20:15:29 +00001996#endif /* HAVE_IPV6 */
Feng Lu758fb8f2014-07-03 18:23:09 +08001997 netlink_socket (&zvrf->netlink, groups, zvrf->vrf_id);
1998 netlink_socket (&zvrf->netlink_cmd, 0, zvrf->vrf_id);
paul718e3742002-12-13 20:15:29 +00001999
2000 /* Register kernel socket. */
Feng Lu758fb8f2014-07-03 18:23:09 +08002001 if (zvrf->netlink.sock > 0)
Paul Jakma768a27e2008-05-29 18:23:08 +00002002 {
Stephen Hemminger4cde9312008-08-16 17:51:27 +01002003 /* Only want non-blocking on the netlink event socket */
Feng Lu758fb8f2014-07-03 18:23:09 +08002004 if (fcntl (zvrf->netlink.sock, F_SETFL, O_NONBLOCK) < 0)
2005 zlog_err ("Can't set %s socket flags: %s", zvrf->netlink.name,
2006 safe_strerror (errno));
Stephen Hemminger4cde9312008-08-16 17:51:27 +01002007
Stephen Hemminger30afea32008-08-16 18:25:47 +01002008 /* Set receive buffer size if it's set from command line */
2009 if (nl_rcvbufsize)
Feng Lu758fb8f2014-07-03 18:23:09 +08002010 netlink_recvbuf (&zvrf->netlink, nl_rcvbufsize);
Stephen Hemminger30afea32008-08-16 18:25:47 +01002011
Feng Lu758fb8f2014-07-03 18:23:09 +08002012 netlink_install_filter (zvrf->netlink.sock, zvrf->netlink_cmd.snl.nl_pid);
2013 zvrf->t_netlink = thread_add_read (zebrad.master, kernel_read, zvrf,
2014 zvrf->netlink.sock);
2015 }
2016}
2017
2018void
2019kernel_terminate (struct zebra_vrf *zvrf)
2020{
2021 THREAD_READ_OFF (zvrf->t_netlink);
2022
2023 if (zvrf->netlink.sock >= 0)
2024 {
2025 close (zvrf->netlink.sock);
2026 zvrf->netlink.sock = -1;
2027 }
2028
2029 if (zvrf->netlink_cmd.sock >= 0)
2030 {
2031 close (zvrf->netlink_cmd.sock);
2032 zvrf->netlink_cmd.sock = -1;
Paul Jakma768a27e2008-05-29 18:23:08 +00002033 }
paul718e3742002-12-13 20:15:29 +00002034}
Avneesh Sachdev78deec42012-11-13 22:48:56 +00002035
2036/*
2037 * nl_msg_type_to_str
2038 */
2039const char *
2040nl_msg_type_to_str (uint16_t msg_type)
2041{
2042 return lookup (nlmsg_str, msg_type);
2043}
2044
2045/*
2046 * nl_rtproto_to_str
2047 */
2048const char *
2049nl_rtproto_to_str (u_char rtproto)
2050{
2051 return lookup (rtproto_str, rtproto);
2052}