blob: 930271d0a6b65d335077369b81d9b0121ab55922 [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>
23
24/* Hack for GNU libc version 2. */
25#ifndef MSG_TRUNC
26#define MSG_TRUNC 0x20
27#endif /* MSG_TRUNC */
28
29#include "linklist.h"
30#include "if.h"
31#include "log.h"
32#include "prefix.h"
33#include "connected.h"
34#include "table.h"
Josh Bailey26e2ae32012-03-22 01:09:21 -070035#include "memory.h"
paul718e3742002-12-13 20:15:29 +000036#include "rib.h"
paule04ab742003-01-17 23:47:00 +000037#include "thread.h"
pauledd7c242003-06-04 13:59:38 +000038#include "privs.h"
Feng Lu0d0686f2015-05-22 11:40:02 +020039#include "vrf.h"
paul718e3742002-12-13 20:15:29 +000040
41#include "zebra/zserv.h"
paul6621ca82005-11-23 13:02:08 +000042#include "zebra/rt.h"
paul718e3742002-12-13 20:15:29 +000043#include "zebra/redistribute.h"
44#include "zebra/interface.h"
45#include "zebra/debug.h"
46
Avneesh Sachdev78deec42012-11-13 22:48:56 +000047#include "rt_netlink.h"
JR Rivers3cadc0c2012-04-01 12:16:31 -070048
Stephen Hemminger1423c802008-08-14 17:59:25 +010049static const struct message nlmsg_str[] = {
paul718e3742002-12-13 20:15:29 +000050 {RTM_NEWROUTE, "RTM_NEWROUTE"},
51 {RTM_DELROUTE, "RTM_DELROUTE"},
52 {RTM_GETROUTE, "RTM_GETROUTE"},
53 {RTM_NEWLINK, "RTM_NEWLINK"},
54 {RTM_DELLINK, "RTM_DELLINK"},
55 {RTM_GETLINK, "RTM_GETLINK"},
56 {RTM_NEWADDR, "RTM_NEWADDR"},
57 {RTM_DELADDR, "RTM_DELADDR"},
58 {RTM_GETADDR, "RTM_GETADDR"},
paul7021c422003-07-15 12:52:22 +000059 {0, NULL}
paul718e3742002-12-13 20:15:29 +000060};
61
paulb21b19c2003-06-15 01:28:29 +000062extern struct zebra_t zebrad;
paul718e3742002-12-13 20:15:29 +000063
pauledd7c242003-06-04 13:59:38 +000064extern struct zebra_privs_t zserv_privs;
65
hassoc34b6b52004-08-31 13:41:49 +000066extern u_int32_t nl_rcvbufsize;
67
ajsd2fc8892005-04-02 18:38:43 +000068/* Note: on netlink systems, there should be a 1-to-1 mapping between interface
69 names and ifindex values. */
70static void
71set_ifindex(struct interface *ifp, unsigned int ifi_index)
72{
73 struct interface *oifp;
74
75 if (((oifp = if_lookup_by_index(ifi_index)) != NULL) && (oifp != ifp))
76 {
77 if (ifi_index == IFINDEX_INTERNAL)
78 zlog_err("Netlink is setting interface %s ifindex to reserved "
79 "internal value %u", ifp->name, ifi_index);
80 else
81 {
82 if (IS_ZEBRA_DEBUG_KERNEL)
83 zlog_debug("interface index %d was renamed from %s to %s",
84 ifi_index, oifp->name, ifp->name);
85 if (if_is_up(oifp))
86 zlog_err("interface rename detected on up interface: index %d "
87 "was renamed from %s to %s, results are uncertain!",
88 ifi_index, oifp->name, ifp->name);
89 if_delete_update(oifp);
90 }
91 }
92 ifp->ifindex = ifi_index;
93}
94
Ulrich Weberf1ef81b2013-01-22 10:39:18 +000095#ifndef SO_RCVBUFFORCE
96#define SO_RCVBUFFORCE (33)
97#endif
98
Stephen Hemminger30afea32008-08-16 18:25:47 +010099static int
100netlink_recvbuf (struct nlsock *nl, uint32_t newsize)
101{
102 u_int32_t oldsize;
103 socklen_t newlen = sizeof(newsize);
104 socklen_t oldlen = sizeof(oldsize);
105 int ret;
106
107 ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &oldsize, &oldlen);
108 if (ret < 0)
109 {
110 zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name,
111 safe_strerror (errno));
112 return -1;
113 }
114
Ulrich Weberf1ef81b2013-01-22 10:39:18 +0000115 /* Try force option (linux >= 2.6.14) and fall back to normal set */
116 if ( zserv_privs.change (ZPRIVS_RAISE) )
117 zlog_err ("routing_socket: Can't raise privileges");
118 ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUFFORCE, &nl_rcvbufsize,
Stephen Hemminger30afea32008-08-16 18:25:47 +0100119 sizeof(nl_rcvbufsize));
Ulrich Weberf1ef81b2013-01-22 10:39:18 +0000120 if ( zserv_privs.change (ZPRIVS_LOWER) )
121 zlog_err ("routing_socket: Can't lower privileges");
122 if (ret < 0)
123 ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &nl_rcvbufsize,
124 sizeof(nl_rcvbufsize));
Stephen Hemminger30afea32008-08-16 18:25:47 +0100125 if (ret < 0)
126 {
127 zlog (NULL, LOG_ERR, "Can't set %s receive buffer size: %s", nl->name,
128 safe_strerror (errno));
129 return -1;
130 }
131
132 ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &newsize, &newlen);
133 if (ret < 0)
134 {
135 zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name,
136 safe_strerror (errno));
137 return -1;
138 }
139
140 zlog (NULL, LOG_INFO,
141 "Setting netlink socket receive buffer size: %u -> %u",
142 oldsize, newsize);
143 return 0;
144}
145
paul718e3742002-12-13 20:15:29 +0000146/* Make socket for Linux netlink interface. */
147static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800148netlink_socket (struct nlsock *nl, unsigned long groups, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000149{
150 int ret;
151 struct sockaddr_nl snl;
152 int sock;
153 int namelen;
ajs4be019d2005-01-29 16:12:41 +0000154 int save_errno;
paul718e3742002-12-13 20:15:29 +0000155
Michal Sekletar8e998b12014-05-16 14:13:43 +0000156 if (zserv_privs.change (ZPRIVS_RAISE))
157 {
158 zlog (NULL, LOG_ERR, "Can't raise privileges");
159 return -1;
160 }
161
Feng Lu758fb8f2014-07-03 18:23:09 +0800162 sock = vrf_socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE, vrf_id);
paul718e3742002-12-13 20:15:29 +0000163 if (sock < 0)
164 {
165 zlog (NULL, LOG_ERR, "Can't open %s socket: %s", nl->name,
ajs6099b3b2004-11-20 02:06:59 +0000166 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000167 return -1;
168 }
169
paul718e3742002-12-13 20:15:29 +0000170 memset (&snl, 0, sizeof snl);
171 snl.nl_family = AF_NETLINK;
172 snl.nl_groups = groups;
173
174 /* Bind the socket to the netlink structure for anything. */
175 ret = bind (sock, (struct sockaddr *) &snl, sizeof snl);
ajs4be019d2005-01-29 16:12:41 +0000176 save_errno = errno;
hasso55e7ecd2004-08-06 08:41:56 +0000177 if (zserv_privs.change (ZPRIVS_LOWER))
178 zlog (NULL, LOG_ERR, "Can't lower privileges");
179
paul718e3742002-12-13 20:15:29 +0000180 if (ret < 0)
181 {
paul7021c422003-07-15 12:52:22 +0000182 zlog (NULL, LOG_ERR, "Can't bind %s socket to group 0x%x: %s",
ajs4be019d2005-01-29 16:12:41 +0000183 nl->name, snl.nl_groups, safe_strerror (save_errno));
paul718e3742002-12-13 20:15:29 +0000184 close (sock);
185 return -1;
186 }
paul7021c422003-07-15 12:52:22 +0000187
paul718e3742002-12-13 20:15:29 +0000188 /* multiple netlink sockets will have different nl_pid */
189 namelen = sizeof snl;
hassoc9e52be2004-09-26 16:09:34 +0000190 ret = getsockname (sock, (struct sockaddr *) &snl, (socklen_t *) &namelen);
paul718e3742002-12-13 20:15:29 +0000191 if (ret < 0 || namelen != sizeof snl)
192 {
193 zlog (NULL, LOG_ERR, "Can't get %s socket name: %s", nl->name,
ajs6099b3b2004-11-20 02:06:59 +0000194 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000195 close (sock);
196 return -1;
197 }
198
199 nl->snl = snl;
200 nl->sock = sock;
201 return ret;
202}
203
204/* Get type specified information from netlink. */
205static int
206netlink_request (int family, int type, struct nlsock *nl)
207{
208 int ret;
209 struct sockaddr_nl snl;
ajs4be019d2005-01-29 16:12:41 +0000210 int save_errno;
paul718e3742002-12-13 20:15:29 +0000211
212 struct
213 {
214 struct nlmsghdr nlh;
215 struct rtgenmsg g;
216 } req;
217
218
219 /* Check netlink socket. */
220 if (nl->sock < 0)
221 {
222 zlog (NULL, LOG_ERR, "%s socket isn't active.", nl->name);
223 return -1;
224 }
225
226 memset (&snl, 0, sizeof snl);
227 snl.nl_family = AF_NETLINK;
228
ajsc05612b2005-10-01 16:36:54 +0000229 memset (&req, 0, sizeof req);
paul718e3742002-12-13 20:15:29 +0000230 req.nlh.nlmsg_len = sizeof req;
231 req.nlh.nlmsg_type = type;
232 req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
Stephen Hemminger3d265b42008-08-16 17:30:39 +0100233 req.nlh.nlmsg_pid = nl->snl.nl_pid;
paul718e3742002-12-13 20:15:29 +0000234 req.nlh.nlmsg_seq = ++nl->seq;
235 req.g.rtgen_family = family;
pauledd7c242003-06-04 13:59:38 +0000236
237 /* linux appears to check capabilities on every message
238 * have to raise caps for every message sent
239 */
paul7021c422003-07-15 12:52:22 +0000240 if (zserv_privs.change (ZPRIVS_RAISE))
pauledd7c242003-06-04 13:59:38 +0000241 {
242 zlog (NULL, LOG_ERR, "Can't raise privileges");
243 return -1;
244 }
paul7021c422003-07-15 12:52:22 +0000245
246 ret = sendto (nl->sock, (void *) &req, sizeof req, 0,
247 (struct sockaddr *) &snl, sizeof snl);
ajs4be019d2005-01-29 16:12:41 +0000248 save_errno = errno;
paul7021c422003-07-15 12:52:22 +0000249
250 if (zserv_privs.change (ZPRIVS_LOWER))
251 zlog (NULL, LOG_ERR, "Can't lower privileges");
252
paul718e3742002-12-13 20:15:29 +0000253 if (ret < 0)
paul7021c422003-07-15 12:52:22 +0000254 {
255 zlog (NULL, LOG_ERR, "%s sendto failed: %s", nl->name,
ajs4be019d2005-01-29 16:12:41 +0000256 safe_strerror (save_errno));
paul718e3742002-12-13 20:15:29 +0000257 return -1;
258 }
pauledd7c242003-06-04 13:59:38 +0000259
paul718e3742002-12-13 20:15:29 +0000260 return 0;
261}
262
263/* Receive message from netlink interface and pass those information
264 to the given function. */
265static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800266netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *,
267 vrf_id_t),
268 struct nlsock *nl, struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +0000269{
270 int status;
271 int ret = 0;
272 int error;
273
274 while (1)
275 {
JR Rivers3cadc0c2012-04-01 12:16:31 -0700276 char buf[NL_PKT_BUF_SIZE];
Timo Teräsc299ed72014-07-29 09:41:55 +0000277 struct iovec iov = {
278 .iov_base = buf,
279 .iov_len = sizeof buf
280 };
paul718e3742002-12-13 20:15:29 +0000281 struct sockaddr_nl snl;
Timo Teräsc299ed72014-07-29 09:41:55 +0000282 struct msghdr msg = {
283 .msg_name = (void *) &snl,
284 .msg_namelen = sizeof snl,
285 .msg_iov = &iov,
286 .msg_iovlen = 1
287 };
paul718e3742002-12-13 20:15:29 +0000288 struct nlmsghdr *h;
paul7021c422003-07-15 12:52:22 +0000289
paul718e3742002-12-13 20:15:29 +0000290 status = recvmsg (nl->sock, &msg, 0);
paul718e3742002-12-13 20:15:29 +0000291 if (status < 0)
paul7021c422003-07-15 12:52:22 +0000292 {
Stephen Hemminger4c699472008-08-17 17:01:44 +0100293 if (errno == EINTR)
paul7021c422003-07-15 12:52:22 +0000294 continue;
Stephen Hemminger4c699472008-08-17 17:01:44 +0100295 if (errno == EWOULDBLOCK || errno == EAGAIN)
paul7021c422003-07-15 12:52:22 +0000296 break;
ajs4be019d2005-01-29 16:12:41 +0000297 zlog (NULL, LOG_ERR, "%s recvmsg overrun: %s",
Stephen Hemminger4c699472008-08-17 17:01:44 +0100298 nl->name, safe_strerror(errno));
paul7021c422003-07-15 12:52:22 +0000299 continue;
300 }
paul718e3742002-12-13 20:15:29 +0000301
302 if (status == 0)
paul7021c422003-07-15 12:52:22 +0000303 {
304 zlog (NULL, LOG_ERR, "%s EOF", nl->name);
305 return -1;
306 }
paul718e3742002-12-13 20:15:29 +0000307
308 if (msg.msg_namelen != sizeof snl)
paul7021c422003-07-15 12:52:22 +0000309 {
310 zlog (NULL, LOG_ERR, "%s sender address length error: length %d",
311 nl->name, msg.msg_namelen);
312 return -1;
313 }
paulb84d3a12003-11-17 10:31:01 +0000314
hasso206d8052005-04-09 16:38:51 +0000315 for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, (unsigned int) status);
paul7021c422003-07-15 12:52:22 +0000316 h = NLMSG_NEXT (h, status))
317 {
318 /* Finish of reading. */
319 if (h->nlmsg_type == NLMSG_DONE)
320 return ret;
paul718e3742002-12-13 20:15:29 +0000321
paul7021c422003-07-15 12:52:22 +0000322 /* Error handling. */
323 if (h->nlmsg_type == NLMSG_ERROR)
324 {
325 struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h);
Stephen Hemminger898987e2008-08-17 16:56:15 +0100326 int errnum = err->error;
327 int msg_type = err->msg.nlmsg_type;
paul7021c422003-07-15 12:52:22 +0000328
paul718e3742002-12-13 20:15:29 +0000329 /* If the error field is zero, then this is an ACK */
paul7021c422003-07-15 12:52:22 +0000330 if (err->error == 0)
paul718e3742002-12-13 20:15:29 +0000331 {
paul7021c422003-07-15 12:52:22 +0000332 if (IS_ZEBRA_DEBUG_KERNEL)
333 {
hasso1ada8192005-06-12 11:28:18 +0000334 zlog_debug ("%s: %s ACK: type=%s(%u), seq=%u, pid=%u",
paul7021c422003-07-15 12:52:22 +0000335 __FUNCTION__, nl->name,
336 lookup (nlmsg_str, err->msg.nlmsg_type),
337 err->msg.nlmsg_type, err->msg.nlmsg_seq,
338 err->msg.nlmsg_pid);
paul718e3742002-12-13 20:15:29 +0000339 }
paul7021c422003-07-15 12:52:22 +0000340
341 /* return if not a multipart message, otherwise continue */
342 if (!(h->nlmsg_flags & NLM_F_MULTI))
343 {
344 return 0;
paul718e3742002-12-13 20:15:29 +0000345 }
paul7021c422003-07-15 12:52:22 +0000346 continue;
paul718e3742002-12-13 20:15:29 +0000347 }
paul7021c422003-07-15 12:52:22 +0000348
paul718e3742002-12-13 20:15:29 +0000349 if (h->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr)))
paul7021c422003-07-15 12:52:22 +0000350 {
351 zlog (NULL, LOG_ERR, "%s error: message truncated",
352 nl->name);
353 return -1;
354 }
pauld753e9e2003-01-22 19:45:50 +0000355
Stephen Hemminger898987e2008-08-17 16:56:15 +0100356 /* Deal with errors that occur because of races in link handling */
Feng Lu758fb8f2014-07-03 18:23:09 +0800357 if (nl == &zvrf->netlink_cmd
Stephen Hemminger898987e2008-08-17 16:56:15 +0100358 && ((msg_type == RTM_DELROUTE &&
359 (-errnum == ENODEV || -errnum == ESRCH))
360 || (msg_type == RTM_NEWROUTE && -errnum == EEXIST)))
361 {
362 if (IS_ZEBRA_DEBUG_KERNEL)
363 zlog_debug ("%s: error: %s type=%s(%u), seq=%u, pid=%u",
364 nl->name, safe_strerror (-errnum),
365 lookup (nlmsg_str, msg_type),
366 msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid);
367 return 0;
368 }
paul718e3742002-12-13 20:15:29 +0000369
Stephen Hemminger898987e2008-08-17 16:56:15 +0100370 zlog_err ("%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);
paul7021c422003-07-15 12:52:22 +0000374 return -1;
375 }
paul718e3742002-12-13 20:15:29 +0000376
paul7021c422003-07-15 12:52:22 +0000377 /* OK we got netlink message. */
378 if (IS_ZEBRA_DEBUG_KERNEL)
hasso1ada8192005-06-12 11:28:18 +0000379 zlog_debug ("netlink_parse_info: %s type %s(%u), seq=%u, pid=%u",
paul7021c422003-07-15 12:52:22 +0000380 nl->name,
381 lookup (nlmsg_str, h->nlmsg_type), h->nlmsg_type,
382 h->nlmsg_seq, h->nlmsg_pid);
383
Christian Franke599da952013-01-24 14:04:43 +0000384 /* skip unsolicited messages originating from command socket
385 * linux sets the originators port-id for {NEW|DEL}ADDR messages,
386 * so this has to be checked here. */
Feng Lu758fb8f2014-07-03 18:23:09 +0800387 if (nl != &zvrf->netlink_cmd
388 && h->nlmsg_pid == zvrf->netlink_cmd.snl.nl_pid
Christian Franke599da952013-01-24 14:04:43 +0000389 && (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR))
paul7021c422003-07-15 12:52:22 +0000390 {
391 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000392 zlog_debug ("netlink_parse_info: %s packet comes from %s",
Feng Lu758fb8f2014-07-03 18:23:09 +0800393 zvrf->netlink_cmd.name, nl->name);
paul7021c422003-07-15 12:52:22 +0000394 continue;
395 }
396
Feng Lu758fb8f2014-07-03 18:23:09 +0800397 error = (*filter) (&snl, h, zvrf->vrf_id);
paul7021c422003-07-15 12:52:22 +0000398 if (error < 0)
399 {
400 zlog (NULL, LOG_ERR, "%s filter function error", nl->name);
401 ret = error;
402 }
403 }
paul718e3742002-12-13 20:15:29 +0000404
405 /* After error care. */
406 if (msg.msg_flags & MSG_TRUNC)
paul7021c422003-07-15 12:52:22 +0000407 {
408 zlog (NULL, LOG_ERR, "%s error: message truncated", nl->name);
409 continue;
410 }
paul718e3742002-12-13 20:15:29 +0000411 if (status)
paul7021c422003-07-15 12:52:22 +0000412 {
413 zlog (NULL, LOG_ERR, "%s error: data remnant size %d", nl->name,
414 status);
415 return -1;
416 }
paul718e3742002-12-13 20:15:29 +0000417 }
418 return ret;
419}
420
421/* Utility function for parse rtattr. */
422static void
paul7021c422003-07-15 12:52:22 +0000423netlink_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta,
424 int len)
paul718e3742002-12-13 20:15:29 +0000425{
paul7021c422003-07-15 12:52:22 +0000426 while (RTA_OK (rta, len))
paul718e3742002-12-13 20:15:29 +0000427 {
428 if (rta->rta_type <= max)
paul7021c422003-07-15 12:52:22 +0000429 tb[rta->rta_type] = rta;
430 rta = RTA_NEXT (rta, len);
paul718e3742002-12-13 20:15:29 +0000431 }
432}
433
Josh Bailey26e2ae32012-03-22 01:09:21 -0700434/* Utility function to parse hardware link-layer address and update ifp */
435static void
436netlink_interface_update_hw_addr (struct rtattr **tb, struct interface *ifp)
437{
438 int i;
439
440 if (tb[IFLA_ADDRESS])
441 {
442 int hw_addr_len;
443
444 hw_addr_len = RTA_PAYLOAD (tb[IFLA_ADDRESS]);
445
446 if (hw_addr_len > INTERFACE_HWADDR_MAX)
447 zlog_warn ("Hardware address is too large: %d", hw_addr_len);
448 else
449 {
450 ifp->hw_addr_len = hw_addr_len;
451 memcpy (ifp->hw_addr, RTA_DATA (tb[IFLA_ADDRESS]), hw_addr_len);
452
453 for (i = 0; i < hw_addr_len; i++)
454 if (ifp->hw_addr[i] != 0)
455 break;
456
457 if (i == hw_addr_len)
458 ifp->hw_addr_len = 0;
459 else
460 ifp->hw_addr_len = hw_addr_len;
461 }
462 }
463}
464
paul718e3742002-12-13 20:15:29 +0000465/* Called from interface_lookup_netlink(). This function is only used
466 during bootstrap. */
Stephen Hemminger6072b242008-08-14 16:52:26 +0100467static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800468netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h,
469 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000470{
471 int len;
472 struct ifinfomsg *ifi;
473 struct rtattr *tb[IFLA_MAX + 1];
474 struct interface *ifp;
475 char *name;
paul718e3742002-12-13 20:15:29 +0000476
477 ifi = NLMSG_DATA (h);
478
479 if (h->nlmsg_type != RTM_NEWLINK)
480 return 0;
481
482 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
483 if (len < 0)
484 return -1;
485
486 /* Looking up interface name. */
487 memset (tb, 0, sizeof tb);
488 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
paulc15cb242005-01-24 09:05:27 +0000489
paul1e193152005-02-14 23:53:05 +0000490#ifdef IFLA_WIRELESS
paulc15cb242005-01-24 09:05:27 +0000491 /* check for wireless messages to ignore */
492 if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
493 {
494 if (IS_ZEBRA_DEBUG_KERNEL)
495 zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__);
496 return 0;
497 }
paul1e193152005-02-14 23:53:05 +0000498#endif /* IFLA_WIRELESS */
paulc15cb242005-01-24 09:05:27 +0000499
paul718e3742002-12-13 20:15:29 +0000500 if (tb[IFLA_IFNAME] == NULL)
501 return -1;
paul7021c422003-07-15 12:52:22 +0000502 name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
paul718e3742002-12-13 20:15:29 +0000503
504 /* Add interface. */
Feng Lu758fb8f2014-07-03 18:23:09 +0800505 ifp = if_get_by_name_vrf (name, vrf_id);
ajsd2fc8892005-04-02 18:38:43 +0000506 set_ifindex(ifp, ifi->ifi_index);
paul718e3742002-12-13 20:15:29 +0000507 ifp->flags = ifi->ifi_flags & 0x0000fffff;
Stephen Hemminger4308abb2008-12-01 14:19:38 -0800508 ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]);
Brett Cipherydb19c852013-10-03 13:48:54 +0000509 ifp->metric = 0;
paul718e3742002-12-13 20:15:29 +0000510
511 /* Hardware type and address. */
512 ifp->hw_type = ifi->ifi_type;
Josh Bailey26e2ae32012-03-22 01:09:21 -0700513 netlink_interface_update_hw_addr (tb, ifp);
paul718e3742002-12-13 20:15:29 +0000514
515 if_add_update (ifp);
516
517 return 0;
518}
519
520/* Lookup interface IPv4/IPv6 address. */
Stephen Hemminger6072b242008-08-14 16:52:26 +0100521static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800522netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h,
523 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000524{
525 int len;
526 struct ifaddrmsg *ifa;
paul7021c422003-07-15 12:52:22 +0000527 struct rtattr *tb[IFA_MAX + 1];
paul718e3742002-12-13 20:15:29 +0000528 struct interface *ifp;
Andrew J. Schorre4529632006-12-12 19:18:21 +0000529 void *addr;
530 void *broad;
paul718e3742002-12-13 20:15:29 +0000531 u_char flags = 0;
532 char *label = NULL;
533
534 ifa = NLMSG_DATA (h);
535
paul7021c422003-07-15 12:52:22 +0000536 if (ifa->ifa_family != AF_INET
paul718e3742002-12-13 20:15:29 +0000537#ifdef HAVE_IPV6
538 && ifa->ifa_family != AF_INET6
539#endif /* HAVE_IPV6 */
paul7021c422003-07-15 12:52:22 +0000540 )
paul718e3742002-12-13 20:15:29 +0000541 return 0;
542
543 if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
544 return 0;
545
paul7021c422003-07-15 12:52:22 +0000546 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifaddrmsg));
paul718e3742002-12-13 20:15:29 +0000547 if (len < 0)
548 return -1;
549
550 memset (tb, 0, sizeof tb);
551 netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len);
552
Feng Lu758fb8f2014-07-03 18:23:09 +0800553 ifp = if_lookup_by_index_vrf (ifa->ifa_index, vrf_id);
paul718e3742002-12-13 20:15:29 +0000554 if (ifp == NULL)
555 {
Feng Lu758fb8f2014-07-03 18:23:09 +0800556 zlog_err ("netlink_interface_addr can't find interface by index %d vrf %u",
557 ifa->ifa_index, vrf_id);
paul718e3742002-12-13 20:15:29 +0000558 return -1;
559 }
560
paul7021c422003-07-15 12:52:22 +0000561 if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */
paul718e3742002-12-13 20:15:29 +0000562 {
paul00df0c12002-12-13 21:07:36 +0000563 char buf[BUFSIZ];
Feng Lu758fb8f2014-07-03 18:23:09 +0800564 zlog_debug ("netlink_interface_addr %s %s vrf %u:",
565 lookup (nlmsg_str, h->nlmsg_type), ifp->name, vrf_id);
paul718e3742002-12-13 20:15:29 +0000566 if (tb[IFA_LOCAL])
hasso206d8052005-04-09 16:38:51 +0000567 zlog_debug (" IFA_LOCAL %s/%d",
568 inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]),
569 buf, BUFSIZ), ifa->ifa_prefixlen);
paul718e3742002-12-13 20:15:29 +0000570 if (tb[IFA_ADDRESS])
hasso206d8052005-04-09 16:38:51 +0000571 zlog_debug (" IFA_ADDRESS %s/%d",
572 inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_ADDRESS]),
573 buf, BUFSIZ), ifa->ifa_prefixlen);
paul718e3742002-12-13 20:15:29 +0000574 if (tb[IFA_BROADCAST])
hasso206d8052005-04-09 16:38:51 +0000575 zlog_debug (" IFA_BROADCAST %s/%d",
576 inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_BROADCAST]),
577 buf, BUFSIZ), ifa->ifa_prefixlen);
paul00df0c12002-12-13 21:07:36 +0000578 if (tb[IFA_LABEL] && strcmp (ifp->name, RTA_DATA (tb[IFA_LABEL])))
ajsb6178002004-12-07 21:12:56 +0000579 zlog_debug (" IFA_LABEL %s", (char *)RTA_DATA (tb[IFA_LABEL]));
pauld34b8992006-01-17 18:03:04 +0000580
581 if (tb[IFA_CACHEINFO])
582 {
583 struct ifa_cacheinfo *ci = RTA_DATA (tb[IFA_CACHEINFO]);
584 zlog_debug (" IFA_CACHEINFO pref %d, valid %d",
585 ci->ifa_prefered, ci->ifa_valid);
586 }
paul718e3742002-12-13 20:15:29 +0000587 }
paul31a476c2003-09-29 19:54:53 +0000588
Andrew J. Schorre4529632006-12-12 19:18:21 +0000589 /* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */
590 if (tb[IFA_LOCAL] == NULL)
591 tb[IFA_LOCAL] = tb[IFA_ADDRESS];
paul31a476c2003-09-29 19:54:53 +0000592 if (tb[IFA_ADDRESS] == NULL)
593 tb[IFA_ADDRESS] = tb[IFA_LOCAL];
594
Andrew J. Schorre4529632006-12-12 19:18:21 +0000595 /* local interface address */
596 addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL);
597
598 /* is there a peer address? */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000599 if (tb[IFA_ADDRESS] &&
vize068fd772007-08-10 06:25:20 +0000600 memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_ADDRESS])))
paul7021c422003-07-15 12:52:22 +0000601 {
Andrew J. Schorre4529632006-12-12 19:18:21 +0000602 broad = RTA_DATA(tb[IFA_ADDRESS]);
603 SET_FLAG (flags, ZEBRA_IFA_PEER);
paul7021c422003-07-15 12:52:22 +0000604 }
paul31a476c2003-09-29 19:54:53 +0000605 else
Andrew J. Schorre4529632006-12-12 19:18:21 +0000606 /* seeking a broadcast address */
607 broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST]) : NULL);
paul00df0c12002-12-13 21:07:36 +0000608
Paul Jakma27b47252006-07-02 16:38:54 +0000609 /* addr is primary key, SOL if we don't have one */
610 if (addr == NULL)
611 {
612 zlog_debug ("%s: NULL address", __func__);
613 return -1;
614 }
615
paul718e3742002-12-13 20:15:29 +0000616 /* Flags. */
617 if (ifa->ifa_flags & IFA_F_SECONDARY)
618 SET_FLAG (flags, ZEBRA_IFA_SECONDARY);
619
620 /* Label */
621 if (tb[IFA_LABEL])
622 label = (char *) RTA_DATA (tb[IFA_LABEL]);
623
624 if (ifp && label && strcmp (ifp->name, label) == 0)
625 label = NULL;
626
627 /* Register interface address to the interface. */
628 if (ifa->ifa_family == AF_INET)
629 {
paul7021c422003-07-15 12:52:22 +0000630 if (h->nlmsg_type == RTM_NEWADDR)
631 connected_add_ipv4 (ifp, flags,
632 (struct in_addr *) addr, ifa->ifa_prefixlen,
633 (struct in_addr *) broad, label);
634 else
635 connected_delete_ipv4 (ifp, flags,
636 (struct in_addr *) addr, ifa->ifa_prefixlen,
paul0752ef02005-11-03 12:35:21 +0000637 (struct in_addr *) broad);
paul718e3742002-12-13 20:15:29 +0000638 }
639#ifdef HAVE_IPV6
640 if (ifa->ifa_family == AF_INET6)
641 {
642 if (h->nlmsg_type == RTM_NEWADDR)
Andrew J. Schorre4529632006-12-12 19:18:21 +0000643 connected_add_ipv6 (ifp, flags,
paul7021c422003-07-15 12:52:22 +0000644 (struct in6_addr *) addr, ifa->ifa_prefixlen,
paul0752ef02005-11-03 12:35:21 +0000645 (struct in6_addr *) broad, label);
paul718e3742002-12-13 20:15:29 +0000646 else
paul7021c422003-07-15 12:52:22 +0000647 connected_delete_ipv6 (ifp,
648 (struct in6_addr *) addr, ifa->ifa_prefixlen,
649 (struct in6_addr *) broad);
paul718e3742002-12-13 20:15:29 +0000650 }
paul7021c422003-07-15 12:52:22 +0000651#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +0000652
653 return 0;
654}
655
656/* Looking up routing table by netlink interface. */
Stephen Hemminger6072b242008-08-14 16:52:26 +0100657static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800658netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
659 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000660{
661 int len;
662 struct rtmsg *rtm;
paul7021c422003-07-15 12:52:22 +0000663 struct rtattr *tb[RTA_MAX + 1];
paul718e3742002-12-13 20:15:29 +0000664 u_char flags = 0;
paul7021c422003-07-15 12:52:22 +0000665
666 char anyaddr[16] = { 0 };
paul718e3742002-12-13 20:15:29 +0000667
668 int index;
669 int table;
Timo Teräsb11f3b52015-11-02 16:50:07 +0200670 u_int32_t mtu = 0;
hasso34195bf2004-04-06 12:07:06 +0000671
paul718e3742002-12-13 20:15:29 +0000672 void *dest;
673 void *gate;
Paul Jakma7514fb72007-05-02 16:05:35 +0000674 void *src;
paul718e3742002-12-13 20:15:29 +0000675
676 rtm = NLMSG_DATA (h);
677
678 if (h->nlmsg_type != RTM_NEWROUTE)
679 return 0;
680 if (rtm->rtm_type != RTN_UNICAST)
681 return 0;
682
683 table = rtm->rtm_table;
paul7021c422003-07-15 12:52:22 +0000684#if 0 /* we weed them out later in rib_weed_tables () */
paulb21b19c2003-06-15 01:28:29 +0000685 if (table != RT_TABLE_MAIN && table != zebrad.rtm_table_default)
paul718e3742002-12-13 20:15:29 +0000686 return 0;
687#endif
688
paul7021c422003-07-15 12:52:22 +0000689 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
paul718e3742002-12-13 20:15:29 +0000690 if (len < 0)
691 return -1;
692
693 memset (tb, 0, sizeof tb);
694 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
695
696 if (rtm->rtm_flags & RTM_F_CLONED)
697 return 0;
698 if (rtm->rtm_protocol == RTPROT_REDIRECT)
699 return 0;
700 if (rtm->rtm_protocol == RTPROT_KERNEL)
701 return 0;
702
703 if (rtm->rtm_src_len != 0)
704 return 0;
705
706 /* Route which inserted by Zebra. */
707 if (rtm->rtm_protocol == RTPROT_ZEBRA)
708 flags |= ZEBRA_FLAG_SELFROUTE;
paul7021c422003-07-15 12:52:22 +0000709
paul718e3742002-12-13 20:15:29 +0000710 index = 0;
711 dest = NULL;
712 gate = NULL;
Paul Jakma7514fb72007-05-02 16:05:35 +0000713 src = NULL;
paul718e3742002-12-13 20:15:29 +0000714
715 if (tb[RTA_OIF])
716 index = *(int *) RTA_DATA (tb[RTA_OIF]);
717
718 if (tb[RTA_DST])
719 dest = RTA_DATA (tb[RTA_DST]);
720 else
721 dest = anyaddr;
722
Paul Jakma7514fb72007-05-02 16:05:35 +0000723 if (tb[RTA_PREFSRC])
724 src = RTA_DATA (tb[RTA_PREFSRC]);
725
paul718e3742002-12-13 20:15:29 +0000726 if (tb[RTA_GATEWAY])
727 gate = RTA_DATA (tb[RTA_GATEWAY]);
728
Timo Teräsb11f3b52015-11-02 16:50:07 +0200729 if (tb[RTA_METRICS])
730 {
731 struct rtattr *mxrta[RTAX_MAX+1];
732
733 memset (mxrta, 0, sizeof mxrta);
734 netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),
735 RTA_PAYLOAD(tb[RTA_METRICS]));
736
737 if (mxrta[RTAX_MTU])
738 mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]);
739 }
740
paul718e3742002-12-13 20:15:29 +0000741 if (rtm->rtm_family == AF_INET)
742 {
743 struct prefix_ipv4 p;
744 p.family = AF_INET;
745 memcpy (&p.prefix, dest, 4);
746 p.prefixlen = rtm->rtm_dst_len;
747
Josh Bailey26e2ae32012-03-22 01:09:21 -0700748 if (!tb[RTA_MULTIPATH])
749 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index,
Timo Teräs4d3ae712016-01-15 17:36:32 +0200750 vrf_id, table, 0, mtu, 0, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700751 else
752 {
753 /* This is a multipath route */
754
755 struct rib *rib;
756 struct rtnexthop *rtnh =
757 (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
758
759 len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
760
761 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
762 rib->type = ZEBRA_ROUTE_KERNEL;
763 rib->distance = 0;
764 rib->flags = flags;
Timo Teräs4d3ae712016-01-15 17:36:32 +0200765 rib->metric = 0;
Timo Teräsb11f3b52015-11-02 16:50:07 +0200766 rib->mtu = mtu;
Feng Lu758fb8f2014-07-03 18:23:09 +0800767 rib->vrf_id = vrf_id;
Josh Bailey26e2ae32012-03-22 01:09:21 -0700768 rib->table = table;
769 rib->nexthop_num = 0;
770 rib->uptime = time (NULL);
771
772 for (;;)
773 {
774 if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
775 break;
776
Josh Bailey26e2ae32012-03-22 01:09:21 -0700777 index = rtnh->rtnh_ifindex;
778 gate = 0;
779 if (rtnh->rtnh_len > sizeof (*rtnh))
780 {
781 memset (tb, 0, sizeof (tb));
782 netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
783 rtnh->rtnh_len - sizeof (*rtnh));
784 if (tb[RTA_GATEWAY])
785 gate = RTA_DATA (tb[RTA_GATEWAY]);
786 }
787
788 if (gate)
789 {
790 if (index)
791 nexthop_ipv4_ifindex_add (rib, gate, src, index);
792 else
793 nexthop_ipv4_add (rib, gate, src);
794 }
795 else
796 nexthop_ifindex_add (rib, index);
797
798 len -= NLMSG_ALIGN(rtnh->rtnh_len);
799 rtnh = RTNH_NEXT(rtnh);
800 }
801
802 if (rib->nexthop_num == 0)
803 XFREE (MTYPE_RIB, rib);
804 else
Avneesh Sachdev14d2bba2012-04-11 23:51:08 -0700805 rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700806 }
paul718e3742002-12-13 20:15:29 +0000807 }
808#ifdef HAVE_IPV6
809 if (rtm->rtm_family == AF_INET6)
810 {
811 struct prefix_ipv6 p;
812 p.family = AF_INET6;
813 memcpy (&p.prefix, dest, 16);
814 p.prefixlen = rtm->rtm_dst_len;
815
Feng Lu758fb8f2014-07-03 18:23:09 +0800816 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, vrf_id,
Timo Teräs4d3ae712016-01-15 17:36:32 +0200817 table, 0, mtu, 0, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000818 }
819#endif /* HAVE_IPV6 */
820
821 return 0;
822}
823
Stephen Hemminger1423c802008-08-14 17:59:25 +0100824static const struct message rtproto_str[] = {
paul718e3742002-12-13 20:15:29 +0000825 {RTPROT_REDIRECT, "redirect"},
826 {RTPROT_KERNEL, "kernel"},
827 {RTPROT_BOOT, "boot"},
828 {RTPROT_STATIC, "static"},
829 {RTPROT_GATED, "GateD"},
830 {RTPROT_RA, "router advertisement"},
831 {RTPROT_MRT, "MRT"},
832 {RTPROT_ZEBRA, "Zebra"},
833#ifdef RTPROT_BIRD
834 {RTPROT_BIRD, "BIRD"},
835#endif /* RTPROT_BIRD */
836 {0, NULL}
837};
838
839/* Routing information change from the kernel. */
Stephen Hemminger6072b242008-08-14 16:52:26 +0100840static int
Feng Lu758fb8f2014-07-03 18:23:09 +0800841netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
842 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000843{
844 int len;
845 struct rtmsg *rtm;
paul7021c422003-07-15 12:52:22 +0000846 struct rtattr *tb[RTA_MAX + 1];
847
848 char anyaddr[16] = { 0 };
paul718e3742002-12-13 20:15:29 +0000849
850 int index;
851 int table;
Timo Teräsb11f3b52015-11-02 16:50:07 +0200852 u_int32_t mtu = 0;
Dmitry Popov83d16142011-09-11 13:48:25 +0400853
paul718e3742002-12-13 20:15:29 +0000854 void *dest;
855 void *gate;
Paul Jakma7514fb72007-05-02 16:05:35 +0000856 void *src;
paul718e3742002-12-13 20:15:29 +0000857
858 rtm = NLMSG_DATA (h);
859
paul7021c422003-07-15 12:52:22 +0000860 if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
paul718e3742002-12-13 20:15:29 +0000861 {
862 /* If this is not route add/delete message print warning. */
Feng Lu758fb8f2014-07-03 18:23:09 +0800863 zlog_warn ("Kernel message: %d vrf %u\n", h->nlmsg_type, vrf_id);
paul718e3742002-12-13 20:15:29 +0000864 return 0;
865 }
866
867 /* Connected route. */
868 if (IS_ZEBRA_DEBUG_KERNEL)
Feng Lu758fb8f2014-07-03 18:23:09 +0800869 zlog_debug ("%s %s %s proto %s vrf %u",
paul7021c422003-07-15 12:52:22 +0000870 h->nlmsg_type ==
871 RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
872 rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",
873 rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast",
Feng Lu758fb8f2014-07-03 18:23:09 +0800874 lookup (rtproto_str, rtm->rtm_protocol),
875 vrf_id);
paul718e3742002-12-13 20:15:29 +0000876
877 if (rtm->rtm_type != RTN_UNICAST)
878 {
879 return 0;
880 }
881
882 table = rtm->rtm_table;
paulb21b19c2003-06-15 01:28:29 +0000883 if (table != RT_TABLE_MAIN && table != zebrad.rtm_table_default)
paul718e3742002-12-13 20:15:29 +0000884 {
885 return 0;
886 }
887
paul7021c422003-07-15 12:52:22 +0000888 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
paul718e3742002-12-13 20:15:29 +0000889 if (len < 0)
890 return -1;
891
892 memset (tb, 0, sizeof tb);
893 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
894
895 if (rtm->rtm_flags & RTM_F_CLONED)
896 return 0;
897 if (rtm->rtm_protocol == RTPROT_REDIRECT)
898 return 0;
899 if (rtm->rtm_protocol == RTPROT_KERNEL)
900 return 0;
901
902 if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)
903 return 0;
904
905 if (rtm->rtm_src_len != 0)
906 {
Feng Lu758fb8f2014-07-03 18:23:09 +0800907 zlog_warn ("netlink_route_change(): no src len, vrf %u", vrf_id);
paul718e3742002-12-13 20:15:29 +0000908 return 0;
909 }
paul7021c422003-07-15 12:52:22 +0000910
paul718e3742002-12-13 20:15:29 +0000911 index = 0;
912 dest = NULL;
913 gate = NULL;
Paul Jakma7514fb72007-05-02 16:05:35 +0000914 src = NULL;
paul718e3742002-12-13 20:15:29 +0000915
916 if (tb[RTA_OIF])
917 index = *(int *) RTA_DATA (tb[RTA_OIF]);
918
919 if (tb[RTA_DST])
920 dest = RTA_DATA (tb[RTA_DST]);
921 else
922 dest = anyaddr;
923
924 if (tb[RTA_GATEWAY])
925 gate = RTA_DATA (tb[RTA_GATEWAY]);
926
Paul Jakma7514fb72007-05-02 16:05:35 +0000927 if (tb[RTA_PREFSRC])
928 src = RTA_DATA (tb[RTA_PREFSRC]);
929
Timo Teräsb11f3b52015-11-02 16:50:07 +0200930 if (h->nlmsg_type == RTM_NEWROUTE)
931 {
Timo Teräsb11f3b52015-11-02 16:50:07 +0200932 if (tb[RTA_METRICS])
933 {
934 struct rtattr *mxrta[RTAX_MAX+1];
935
936 memset (mxrta, 0, sizeof mxrta);
937 netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),
938 RTA_PAYLOAD(tb[RTA_METRICS]));
939
940 if (mxrta[RTAX_MTU])
941 mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]);
942 }
943 }
Josh Bailey26e2ae32012-03-22 01:09:21 -0700944
paul718e3742002-12-13 20:15:29 +0000945 if (rtm->rtm_family == AF_INET)
946 {
947 struct prefix_ipv4 p;
948 p.family = AF_INET;
949 memcpy (&p.prefix, dest, 4);
950 p.prefixlen = rtm->rtm_dst_len;
951
952 if (IS_ZEBRA_DEBUG_KERNEL)
paul7021c422003-07-15 12:52:22 +0000953 {
Timo Teräsbe6335d2015-05-23 11:08:41 +0300954 char buf[PREFIX_STRLEN];
Feng Lu758fb8f2014-07-03 18:23:09 +0800955 zlog_debug ("%s %s vrf %u",
Timo Teräsbe6335d2015-05-23 11:08:41 +0300956 h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
Feng Lu758fb8f2014-07-03 18:23:09 +0800957 prefix2str (&p, buf, sizeof(buf)), vrf_id);
paul7021c422003-07-15 12:52:22 +0000958 }
paul718e3742002-12-13 20:15:29 +0000959
960 if (h->nlmsg_type == RTM_NEWROUTE)
Josh Bailey26e2ae32012-03-22 01:09:21 -0700961 {
962 if (!tb[RTA_MULTIPATH])
Feng Lu758fb8f2014-07-03 18:23:09 +0800963 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, vrf_id,
Timo Teräs4d3ae712016-01-15 17:36:32 +0200964 table, 0, mtu, 0, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700965 else
966 {
967 /* This is a multipath route */
968
969 struct rib *rib;
970 struct rtnexthop *rtnh =
971 (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
972
973 len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
974
975 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
976 rib->type = ZEBRA_ROUTE_KERNEL;
977 rib->distance = 0;
978 rib->flags = 0;
Timo Teräs4d3ae712016-01-15 17:36:32 +0200979 rib->metric = 0;
Timo Teräsb11f3b52015-11-02 16:50:07 +0200980 rib->mtu = mtu;
Feng Lu758fb8f2014-07-03 18:23:09 +0800981 rib->vrf_id = vrf_id;
Josh Bailey26e2ae32012-03-22 01:09:21 -0700982 rib->table = table;
983 rib->nexthop_num = 0;
984 rib->uptime = time (NULL);
985
986 for (;;)
987 {
988 if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
989 break;
990
Josh Bailey26e2ae32012-03-22 01:09:21 -0700991 index = rtnh->rtnh_ifindex;
992 gate = 0;
993 if (rtnh->rtnh_len > sizeof (*rtnh))
994 {
995 memset (tb, 0, sizeof (tb));
996 netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
997 rtnh->rtnh_len - sizeof (*rtnh));
998 if (tb[RTA_GATEWAY])
999 gate = RTA_DATA (tb[RTA_GATEWAY]);
1000 }
1001
1002 if (gate)
1003 {
1004 if (index)
1005 nexthop_ipv4_ifindex_add (rib, gate, src, index);
1006 else
1007 nexthop_ipv4_add (rib, gate, src);
1008 }
1009 else
1010 nexthop_ifindex_add (rib, index);
1011
1012 len -= NLMSG_ALIGN(rtnh->rtnh_len);
1013 rtnh = RTNH_NEXT(rtnh);
1014 }
1015
1016 if (rib->nexthop_num == 0)
1017 XFREE (MTYPE_RIB, rib);
1018 else
Avneesh Sachdev14d2bba2012-04-11 23:51:08 -07001019 rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -07001020 }
1021 }
paul718e3742002-12-13 20:15:29 +00001022 else
Feng Lu758fb8f2014-07-03 18:23:09 +08001023 rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, vrf_id,
Feng Lu0d0686f2015-05-22 11:40:02 +02001024 SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001025 }
1026
1027#ifdef HAVE_IPV6
1028 if (rtm->rtm_family == AF_INET6)
1029 {
1030 struct prefix_ipv6 p;
paul718e3742002-12-13 20:15:29 +00001031
1032 p.family = AF_INET6;
1033 memcpy (&p.prefix, dest, 16);
1034 p.prefixlen = rtm->rtm_dst_len;
1035
1036 if (IS_ZEBRA_DEBUG_KERNEL)
paul7021c422003-07-15 12:52:22 +00001037 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001038 char buf[PREFIX_STRLEN];
Feng Lu758fb8f2014-07-03 18:23:09 +08001039 zlog_debug ("%s %s vrf %u",
Timo Teräsbe6335d2015-05-23 11:08:41 +03001040 h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
Feng Lu758fb8f2014-07-03 18:23:09 +08001041 prefix2str (&p, buf, sizeof(buf)), vrf_id);
paul7021c422003-07-15 12:52:22 +00001042 }
paul718e3742002-12-13 20:15:29 +00001043
1044 if (h->nlmsg_type == RTM_NEWROUTE)
Feng Lu758fb8f2014-07-03 18:23:09 +08001045 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, vrf_id, table,
Timo Teräs4d3ae712016-01-15 17:36:32 +02001046 0, mtu, 0, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001047 else
Feng Lu758fb8f2014-07-03 18:23:09 +08001048 rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, vrf_id,
Feng Lu0d0686f2015-05-22 11:40:02 +02001049 SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001050 }
1051#endif /* HAVE_IPV6 */
1052
1053 return 0;
1054}
1055
Stephen Hemminger6072b242008-08-14 16:52:26 +01001056static int
Feng Lu758fb8f2014-07-03 18:23:09 +08001057netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
1058 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001059{
1060 int len;
1061 struct ifinfomsg *ifi;
paul7021c422003-07-15 12:52:22 +00001062 struct rtattr *tb[IFLA_MAX + 1];
paul718e3742002-12-13 20:15:29 +00001063 struct interface *ifp;
1064 char *name;
1065
1066 ifi = NLMSG_DATA (h);
1067
paul7021c422003-07-15 12:52:22 +00001068 if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
paul718e3742002-12-13 20:15:29 +00001069 {
1070 /* If this is not link add/delete message so print warning. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001071 zlog_warn ("netlink_link_change: wrong kernel message %d vrf %u\n",
1072 h->nlmsg_type, vrf_id);
paul718e3742002-12-13 20:15:29 +00001073 return 0;
1074 }
1075
1076 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
1077 if (len < 0)
1078 return -1;
1079
1080 /* Looking up interface name. */
1081 memset (tb, 0, sizeof tb);
1082 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
paulc15cb242005-01-24 09:05:27 +00001083
paul1e193152005-02-14 23:53:05 +00001084#ifdef IFLA_WIRELESS
paulc15cb242005-01-24 09:05:27 +00001085 /* check for wireless messages to ignore */
1086 if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
1087 {
1088 if (IS_ZEBRA_DEBUG_KERNEL)
Feng Lu758fb8f2014-07-03 18:23:09 +08001089 zlog_debug ("%s: ignoring IFLA_WIRELESS message, vrf %u", __func__,
1090 vrf_id);
paulc15cb242005-01-24 09:05:27 +00001091 return 0;
1092 }
paul1e193152005-02-14 23:53:05 +00001093#endif /* IFLA_WIRELESS */
paulc15cb242005-01-24 09:05:27 +00001094
paul718e3742002-12-13 20:15:29 +00001095 if (tb[IFLA_IFNAME] == NULL)
1096 return -1;
paul7021c422003-07-15 12:52:22 +00001097 name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
paul718e3742002-12-13 20:15:29 +00001098
1099 /* Add interface. */
1100 if (h->nlmsg_type == RTM_NEWLINK)
1101 {
Feng Lu758fb8f2014-07-03 18:23:09 +08001102 ifp = if_lookup_by_name_vrf (name, vrf_id);
paul718e3742002-12-13 20:15:29 +00001103
paul7021c422003-07-15 12:52:22 +00001104 if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1105 {
1106 if (ifp == NULL)
Feng Lu758fb8f2014-07-03 18:23:09 +08001107 ifp = if_get_by_name_vrf (name, vrf_id);
paul718e3742002-12-13 20:15:29 +00001108
ajsd2fc8892005-04-02 18:38:43 +00001109 set_ifindex(ifp, ifi->ifi_index);
paul7021c422003-07-15 12:52:22 +00001110 ifp->flags = ifi->ifi_flags & 0x0000fffff;
paul44145db2004-05-09 11:00:23 +00001111 ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
Brett Cipherydb19c852013-10-03 13:48:54 +00001112 ifp->metric = 0;
paul718e3742002-12-13 20:15:29 +00001113
Josh Bailey26e2ae32012-03-22 01:09:21 -07001114 netlink_interface_update_hw_addr (tb, ifp);
1115
paul7021c422003-07-15 12:52:22 +00001116 /* If new link is added. */
1117 if_add_update (ifp);
1118 }
paul718e3742002-12-13 20:15:29 +00001119 else
paul7021c422003-07-15 12:52:22 +00001120 {
1121 /* Interface status change. */
ajsd2fc8892005-04-02 18:38:43 +00001122 set_ifindex(ifp, ifi->ifi_index);
paul44145db2004-05-09 11:00:23 +00001123 ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
Brett Cipherydb19c852013-10-03 13:48:54 +00001124 ifp->metric = 0;
paul718e3742002-12-13 20:15:29 +00001125
Josh Bailey26e2ae32012-03-22 01:09:21 -07001126 netlink_interface_update_hw_addr (tb, ifp);
1127
paul7021c422003-07-15 12:52:22 +00001128 if (if_is_operative (ifp))
1129 {
1130 ifp->flags = ifi->ifi_flags & 0x0000fffff;
1131 if (!if_is_operative (ifp))
1132 if_down (ifp);
ajsa608bbf2005-03-29 17:03:49 +00001133 else
1134 /* Must notify client daemons of new interface status. */
1135 zebra_interface_up_update (ifp);
paul7021c422003-07-15 12:52:22 +00001136 }
1137 else
1138 {
1139 ifp->flags = ifi->ifi_flags & 0x0000fffff;
1140 if (if_is_operative (ifp))
1141 if_up (ifp);
1142 }
1143 }
paul718e3742002-12-13 20:15:29 +00001144 }
1145 else
1146 {
1147 /* RTM_DELLINK. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001148 ifp = if_lookup_by_name_vrf (name, vrf_id);
paul718e3742002-12-13 20:15:29 +00001149
1150 if (ifp == NULL)
paul7021c422003-07-15 12:52:22 +00001151 {
Feng Lu758fb8f2014-07-03 18:23:09 +08001152 zlog_warn ("interface %s vrf %u is deleted but can't find",
1153 name, vrf_id);
paul7021c422003-07-15 12:52:22 +00001154 return 0;
1155 }
1156
paul718e3742002-12-13 20:15:29 +00001157 if_delete_update (ifp);
1158 }
1159
1160 return 0;
1161}
1162
Stephen Hemminger6072b242008-08-14 16:52:26 +01001163static int
Feng Lu758fb8f2014-07-03 18:23:09 +08001164netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h,
1165 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001166{
Stephen Hemminger3d265b42008-08-16 17:30:39 +01001167 /* JF: Ignore messages that aren't from the kernel */
1168 if ( snl->nl_pid != 0 )
1169 {
1170 zlog ( NULL, LOG_ERR, "Ignoring message from pid %u", snl->nl_pid );
1171 return 0;
1172 }
1173
paul718e3742002-12-13 20:15:29 +00001174 switch (h->nlmsg_type)
1175 {
1176 case RTM_NEWROUTE:
Feng Lu758fb8f2014-07-03 18:23:09 +08001177 return netlink_route_change (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001178 break;
1179 case RTM_DELROUTE:
Feng Lu758fb8f2014-07-03 18:23:09 +08001180 return netlink_route_change (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001181 break;
1182 case RTM_NEWLINK:
Feng Lu758fb8f2014-07-03 18:23:09 +08001183 return netlink_link_change (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001184 break;
1185 case RTM_DELLINK:
Feng Lu758fb8f2014-07-03 18:23:09 +08001186 return netlink_link_change (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001187 break;
1188 case RTM_NEWADDR:
Feng Lu758fb8f2014-07-03 18:23:09 +08001189 return netlink_interface_addr (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001190 break;
1191 case RTM_DELADDR:
Feng Lu758fb8f2014-07-03 18:23:09 +08001192 return netlink_interface_addr (snl, h, vrf_id);
paul718e3742002-12-13 20:15:29 +00001193 break;
1194 default:
Feng Lu758fb8f2014-07-03 18:23:09 +08001195 zlog_warn ("Unknown netlink nlmsg_type %d vrf %u\n", h->nlmsg_type,
1196 vrf_id);
paul718e3742002-12-13 20:15:29 +00001197 break;
1198 }
1199 return 0;
1200}
1201
1202/* Interface lookup by netlink socket. */
1203int
Feng Lu758fb8f2014-07-03 18:23:09 +08001204interface_lookup_netlink (struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001205{
1206 int ret;
paul7021c422003-07-15 12:52:22 +00001207
paul718e3742002-12-13 20:15:29 +00001208 /* Get interface information. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001209 ret = netlink_request (AF_PACKET, RTM_GETLINK, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001210 if (ret < 0)
1211 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001212 ret = netlink_parse_info (netlink_interface, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001213 if (ret < 0)
1214 return ret;
1215
1216 /* Get IPv4 address of the interfaces. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001217 ret = netlink_request (AF_INET, RTM_GETADDR, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001218 if (ret < 0)
1219 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001220 ret = netlink_parse_info (netlink_interface_addr, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001221 if (ret < 0)
1222 return ret;
1223
1224#ifdef HAVE_IPV6
1225 /* Get IPv6 address of the interfaces. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001226 ret = netlink_request (AF_INET6, RTM_GETADDR, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001227 if (ret < 0)
1228 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001229 ret = netlink_parse_info (netlink_interface_addr, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001230 if (ret < 0)
1231 return ret;
1232#endif /* HAVE_IPV6 */
1233
1234 return 0;
1235}
1236
1237/* Routing table read function using netlink interface. Only called
1238 bootstrap time. */
1239int
Feng Lu758fb8f2014-07-03 18:23:09 +08001240netlink_route_read (struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001241{
1242 int ret;
paul7021c422003-07-15 12:52:22 +00001243
paul718e3742002-12-13 20:15:29 +00001244 /* Get IPv4 routing table. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001245 ret = netlink_request (AF_INET, RTM_GETROUTE, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001246 if (ret < 0)
1247 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001248 ret = netlink_parse_info (netlink_routing_table, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001249 if (ret < 0)
1250 return ret;
1251
1252#ifdef HAVE_IPV6
1253 /* Get IPv6 routing table. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001254 ret = netlink_request (AF_INET6, RTM_GETROUTE, &zvrf->netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001255 if (ret < 0)
1256 return ret;
Feng Lu758fb8f2014-07-03 18:23:09 +08001257 ret = netlink_parse_info (netlink_routing_table, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001258 if (ret < 0)
1259 return ret;
1260#endif /* HAVE_IPV6 */
1261
1262 return 0;
1263}
1264
1265/* Utility function comes from iproute2.
1266 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001267int
Paul Jakma7aa9dce2014-09-19 14:42:23 +01001268addattr_l (struct nlmsghdr *n, size_t maxlen, int type, void *data, int alen)
paul718e3742002-12-13 20:15:29 +00001269{
Paul Jakma7aa9dce2014-09-19 14:42:23 +01001270 size_t len;
paul718e3742002-12-13 20:15:29 +00001271 struct rtattr *rta;
1272
paul7021c422003-07-15 12:52:22 +00001273 len = RTA_LENGTH (alen);
paul718e3742002-12-13 20:15:29 +00001274
paul7021c422003-07-15 12:52:22 +00001275 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
paul718e3742002-12-13 20:15:29 +00001276 return -1;
1277
paul7021c422003-07-15 12:52:22 +00001278 rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
paul718e3742002-12-13 20:15:29 +00001279 rta->rta_type = type;
1280 rta->rta_len = len;
paul7021c422003-07-15 12:52:22 +00001281 memcpy (RTA_DATA (rta), data, alen);
paul718e3742002-12-13 20:15:29 +00001282 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1283
1284 return 0;
1285}
1286
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001287int
paul718e3742002-12-13 20:15:29 +00001288rta_addattr_l (struct rtattr *rta, int maxlen, int type, void *data, int alen)
1289{
1290 int len;
1291 struct rtattr *subrta;
1292
paul7021c422003-07-15 12:52:22 +00001293 len = RTA_LENGTH (alen);
paul718e3742002-12-13 20:15:29 +00001294
paul7021c422003-07-15 12:52:22 +00001295 if (RTA_ALIGN (rta->rta_len) + len > maxlen)
paul718e3742002-12-13 20:15:29 +00001296 return -1;
1297
paul7021c422003-07-15 12:52:22 +00001298 subrta = (struct rtattr *) (((char *) rta) + RTA_ALIGN (rta->rta_len));
paul718e3742002-12-13 20:15:29 +00001299 subrta->rta_type = type;
1300 subrta->rta_len = len;
paul7021c422003-07-15 12:52:22 +00001301 memcpy (RTA_DATA (subrta), data, alen);
paul718e3742002-12-13 20:15:29 +00001302 rta->rta_len = NLMSG_ALIGN (rta->rta_len) + len;
1303
1304 return 0;
1305}
1306
1307/* Utility function comes from iproute2.
1308 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001309int
Paul Jakma7aa9dce2014-09-19 14:42:23 +01001310addattr32 (struct nlmsghdr *n, size_t maxlen, int type, int data)
paul718e3742002-12-13 20:15:29 +00001311{
Paul Jakma7aa9dce2014-09-19 14:42:23 +01001312 size_t len;
paul718e3742002-12-13 20:15:29 +00001313 struct rtattr *rta;
paul7021c422003-07-15 12:52:22 +00001314
1315 len = RTA_LENGTH (4);
1316
paul718e3742002-12-13 20:15:29 +00001317 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
1318 return -1;
1319
paul7021c422003-07-15 12:52:22 +00001320 rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
paul718e3742002-12-13 20:15:29 +00001321 rta->rta_type = type;
1322 rta->rta_len = len;
paul7021c422003-07-15 12:52:22 +00001323 memcpy (RTA_DATA (rta), &data, 4);
paul718e3742002-12-13 20:15:29 +00001324 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1325
1326 return 0;
1327}
1328
1329static int
Feng Lu758fb8f2014-07-03 18:23:09 +08001330netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h,
1331 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001332{
Feng Lu758fb8f2014-07-03 18:23:09 +08001333 zlog_warn ("netlink_talk: ignoring message type 0x%04x vrf %u", h->nlmsg_type,
1334 vrf_id);
paul718e3742002-12-13 20:15:29 +00001335 return 0;
1336}
1337
1338/* sendmsg() to netlink socket then recvmsg(). */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001339static int
Feng Lu758fb8f2014-07-03 18:23:09 +08001340netlink_talk (struct nlmsghdr *n, struct nlsock *nl, struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001341{
1342 int status;
1343 struct sockaddr_nl snl;
Timo Teräsc299ed72014-07-29 09:41:55 +00001344 struct iovec iov = {
1345 .iov_base = (void *) n,
1346 .iov_len = n->nlmsg_len
1347 };
1348 struct msghdr msg = {
1349 .msg_name = (void *) &snl,
1350 .msg_namelen = sizeof snl,
1351 .msg_iov = &iov,
1352 .msg_iovlen = 1,
1353 };
ajs4be019d2005-01-29 16:12:41 +00001354 int save_errno;
paul7021c422003-07-15 12:52:22 +00001355
paul718e3742002-12-13 20:15:29 +00001356 memset (&snl, 0, sizeof snl);
1357 snl.nl_family = AF_NETLINK;
paul7021c422003-07-15 12:52:22 +00001358
hassob7ed1ec2005-03-31 20:13:49 +00001359 n->nlmsg_seq = ++nl->seq;
paul718e3742002-12-13 20:15:29 +00001360
1361 /* Request an acknowledgement by setting NLM_F_ACK */
1362 n->nlmsg_flags |= NLM_F_ACK;
paul7021c422003-07-15 12:52:22 +00001363
1364 if (IS_ZEBRA_DEBUG_KERNEL)
hassob7ed1ec2005-03-31 20:13:49 +00001365 zlog_debug ("netlink_talk: %s type %s(%u), seq=%u", nl->name,
paul7021c422003-07-15 12:52:22 +00001366 lookup (nlmsg_str, n->nlmsg_type), n->nlmsg_type,
1367 n->nlmsg_seq);
paul718e3742002-12-13 20:15:29 +00001368
1369 /* Send message to netlink interface. */
paul7021c422003-07-15 12:52:22 +00001370 if (zserv_privs.change (ZPRIVS_RAISE))
1371 zlog (NULL, LOG_ERR, "Can't raise privileges");
paul718e3742002-12-13 20:15:29 +00001372 status = sendmsg (nl->sock, &msg, 0);
ajs4be019d2005-01-29 16:12:41 +00001373 save_errno = errno;
paul7021c422003-07-15 12:52:22 +00001374 if (zserv_privs.change (ZPRIVS_LOWER))
1375 zlog (NULL, LOG_ERR, "Can't lower privileges");
1376
paul718e3742002-12-13 20:15:29 +00001377 if (status < 0)
1378 {
1379 zlog (NULL, LOG_ERR, "netlink_talk sendmsg() error: %s",
ajs4be019d2005-01-29 16:12:41 +00001380 safe_strerror (save_errno));
paul718e3742002-12-13 20:15:29 +00001381 return -1;
1382 }
paul7021c422003-07-15 12:52:22 +00001383
paul718e3742002-12-13 20:15:29 +00001384
1385 /*
1386 * Get reply from netlink socket.
1387 * The reply should either be an acknowlegement or an error.
1388 */
Feng Lu758fb8f2014-07-03 18:23:09 +08001389 return netlink_parse_info (netlink_talk_filter, nl, zvrf);
paul718e3742002-12-13 20:15:29 +00001390}
1391
Christian Frankefa713d92013-07-05 15:35:37 +00001392/* This function takes a nexthop as argument and adds
1393 * the appropriate netlink attributes to an existing
1394 * netlink message.
1395 *
1396 * @param routedesc: Human readable description of route type
1397 * (direct/recursive, single-/multipath)
1398 * @param bytelen: Length of addresses in bytes.
1399 * @param nexthop: Nexthop information
1400 * @param nlmsg: nlmsghdr structure to fill in.
1401 * @param req_size: The size allocated for the message.
1402 */
1403static void
1404_netlink_route_build_singlepath(
1405 const char *routedesc,
1406 int bytelen,
1407 struct nexthop *nexthop,
1408 struct nlmsghdr *nlmsg,
Christian Frankee8d3d292013-07-05 15:35:39 +00001409 struct rtmsg *rtmsg,
Christian Frankefa713d92013-07-05 15:35:37 +00001410 size_t req_size)
1411{
Christian Frankee8d3d292013-07-05 15:35:39 +00001412 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
1413 rtmsg->rtm_flags |= RTNH_F_ONLINK;
Christian Frankefa713d92013-07-05 15:35:37 +00001414 if (nexthop->type == NEXTHOP_TYPE_IPV4
1415 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1416 {
1417 addattr_l (nlmsg, req_size, RTA_GATEWAY,
1418 &nexthop->gate.ipv4, bytelen);
1419 if (nexthop->src.ipv4.s_addr)
1420 addattr_l (nlmsg, req_size, RTA_PREFSRC,
1421 &nexthop->src.ipv4, bytelen);
1422
1423 if (IS_ZEBRA_DEBUG_KERNEL)
1424 zlog_debug("netlink_route_multipath() (%s): "
1425 "nexthop via %s if %u",
1426 routedesc,
1427 inet_ntoa (nexthop->gate.ipv4),
1428 nexthop->ifindex);
1429 }
1430#ifdef HAVE_IPV6
1431 if (nexthop->type == NEXTHOP_TYPE_IPV6
1432 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1433 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1434 {
1435 addattr_l (nlmsg, req_size, RTA_GATEWAY,
1436 &nexthop->gate.ipv6, bytelen);
1437
1438 if (IS_ZEBRA_DEBUG_KERNEL)
1439 zlog_debug("netlink_route_multipath() (%s): "
1440 "nexthop via %s if %u",
1441 routedesc,
1442 inet6_ntoa (nexthop->gate.ipv6),
1443 nexthop->ifindex);
1444 }
1445#endif /* HAVE_IPV6 */
1446 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1447 || nexthop->type == NEXTHOP_TYPE_IFNAME
1448 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1449 {
1450 addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
1451
1452 if (nexthop->src.ipv4.s_addr)
1453 addattr_l (nlmsg, req_size, RTA_PREFSRC,
1454 &nexthop->src.ipv4, bytelen);
1455
1456 if (IS_ZEBRA_DEBUG_KERNEL)
1457 zlog_debug("netlink_route_multipath() (%s): "
1458 "nexthop via if %u", routedesc, nexthop->ifindex);
1459 }
1460
1461 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
1462 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
1463 {
1464 addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
1465
1466 if (IS_ZEBRA_DEBUG_KERNEL)
1467 zlog_debug("netlink_route_multipath() (%s): "
1468 "nexthop via if %u", routedesc, nexthop->ifindex);
1469 }
1470}
1471
1472/* This function takes a nexthop as argument and
1473 * appends to the given rtattr/rtnexthop pair the
1474 * representation of the nexthop. If the nexthop
1475 * defines a preferred source, the src parameter
1476 * will be modified to point to that src, otherwise
1477 * it will be kept unmodified.
1478 *
1479 * @param routedesc: Human readable description of route type
1480 * (direct/recursive, single-/multipath)
1481 * @param bytelen: Length of addresses in bytes.
1482 * @param nexthop: Nexthop information
1483 * @param rta: rtnetlink attribute structure
1484 * @param rtnh: pointer to an rtnetlink nexthop structure
1485 * @param src: pointer pointing to a location where
1486 * the prefsrc should be stored.
1487 */
1488static void
1489_netlink_route_build_multipath(
1490 const char *routedesc,
1491 int bytelen,
1492 struct nexthop *nexthop,
1493 struct rtattr *rta,
1494 struct rtnexthop *rtnh,
1495 union g_addr **src
1496 )
1497{
1498 rtnh->rtnh_len = sizeof (*rtnh);
1499 rtnh->rtnh_flags = 0;
1500 rtnh->rtnh_hops = 0;
1501 rta->rta_len += rtnh->rtnh_len;
1502
Christian Frankee8d3d292013-07-05 15:35:39 +00001503 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
1504 rtnh->rtnh_flags |= RTNH_F_ONLINK;
1505
Christian Frankefa713d92013-07-05 15:35:37 +00001506 if (nexthop->type == NEXTHOP_TYPE_IPV4
1507 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1508 {
1509 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
1510 &nexthop->gate.ipv4, bytelen);
Lu Feng621e2aa2014-07-11 07:52:15 +00001511 rtnh->rtnh_len += sizeof (struct rtattr) + bytelen;
Christian Frankefa713d92013-07-05 15:35:37 +00001512
1513 if (nexthop->src.ipv4.s_addr)
1514 *src = &nexthop->src;
1515
1516 if (IS_ZEBRA_DEBUG_KERNEL)
1517 zlog_debug("netlink_route_multipath() (%s): "
1518 "nexthop via %s if %u",
1519 routedesc,
1520 inet_ntoa (nexthop->gate.ipv4),
1521 nexthop->ifindex);
1522 }
1523#ifdef HAVE_IPV6
1524 if (nexthop->type == NEXTHOP_TYPE_IPV6
1525 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1526 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1527 {
1528 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
1529 &nexthop->gate.ipv6, bytelen);
Lu Feng621e2aa2014-07-11 07:52:15 +00001530 rtnh->rtnh_len += sizeof (struct rtattr) + bytelen;
Christian Frankefa713d92013-07-05 15:35:37 +00001531
1532 if (IS_ZEBRA_DEBUG_KERNEL)
1533 zlog_debug("netlink_route_multipath() (%s): "
1534 "nexthop via %s if %u",
1535 routedesc,
1536 inet6_ntoa (nexthop->gate.ipv6),
1537 nexthop->ifindex);
1538 }
1539#endif /* HAVE_IPV6 */
1540 /* ifindex */
1541 if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1542 || nexthop->type == NEXTHOP_TYPE_IFINDEX
1543 || nexthop->type == NEXTHOP_TYPE_IFNAME)
1544 {
1545 rtnh->rtnh_ifindex = nexthop->ifindex;
1546 if (nexthop->src.ipv4.s_addr)
1547 *src = &nexthop->src;
1548 if (IS_ZEBRA_DEBUG_KERNEL)
1549 zlog_debug("netlink_route_multipath() (%s): "
1550 "nexthop via if %u", routedesc, nexthop->ifindex);
1551 }
1552 else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1553 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1554 {
1555 rtnh->rtnh_ifindex = nexthop->ifindex;
1556
1557 if (IS_ZEBRA_DEBUG_KERNEL)
1558 zlog_debug("netlink_route_multipath() (%s): "
1559 "nexthop via if %u", routedesc, nexthop->ifindex);
1560 }
1561 else
1562 {
1563 rtnh->rtnh_ifindex = 0;
1564 }
1565}
1566
1567/* Log debug information for netlink_route_multipath
1568 * if debug logging is enabled.
1569 *
1570 * @param cmd: Netlink command which is to be processed
1571 * @param p: Prefix for which the change is due
1572 * @param nexthop: Nexthop which is currently processed
1573 * @param routedesc: Semantic annotation for nexthop
1574 * (recursive, multipath, etc.)
1575 * @param family: Address family which the change concerns
1576 */
1577static void
1578_netlink_route_debug(
1579 int cmd,
1580 struct prefix *p,
1581 struct nexthop *nexthop,
1582 const char *routedesc,
Feng Lu758fb8f2014-07-03 18:23:09 +08001583 int family,
1584 struct zebra_vrf *zvrf)
Christian Frankefa713d92013-07-05 15:35:37 +00001585{
1586 if (IS_ZEBRA_DEBUG_KERNEL)
1587 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001588 char buf[PREFIX_STRLEN];
Feng Lu758fb8f2014-07-03 18:23:09 +08001589 zlog_debug ("netlink_route_multipath() (%s): %s %s vrf %u type %s",
Christian Frankefa713d92013-07-05 15:35:37 +00001590 routedesc,
1591 lookup (nlmsg_str, cmd),
Timo Teräsbe6335d2015-05-23 11:08:41 +03001592 prefix2str (p, buf, sizeof(buf)),
Kaloyan Kovachev8c56b442015-06-15 17:08:48 +03001593 zvrf->vrf_id,
Timo Teräsbe6335d2015-05-23 11:08:41 +03001594 nexthop_type_to_str (nexthop->type));
Christian Frankefa713d92013-07-05 15:35:37 +00001595 }
1596}
1597
paul718e3742002-12-13 20:15:29 +00001598/* Routing table change via netlink interface. */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001599static int
Timo Teräs0abf6792016-01-15 17:36:29 +02001600netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib)
paul718e3742002-12-13 20:15:29 +00001601{
1602 int bytelen;
1603 struct sockaddr_nl snl;
Christian Frankefa713d92013-07-05 15:35:37 +00001604 struct nexthop *nexthop = NULL, *tnexthop;
1605 int recursing;
1606 int nexthop_num;
paul718e3742002-12-13 20:15:29 +00001607 int discard;
Timo Teräs0abf6792016-01-15 17:36:29 +02001608 int family = PREFIX_FAMILY(p);
Christian Frankefa713d92013-07-05 15:35:37 +00001609 const char *routedesc;
paul718e3742002-12-13 20:15:29 +00001610
paul7021c422003-07-15 12:52:22 +00001611 struct
paul718e3742002-12-13 20:15:29 +00001612 {
1613 struct nlmsghdr n;
1614 struct rtmsg r;
JR Rivers3cadc0c2012-04-01 12:16:31 -07001615 char buf[NL_PKT_BUF_SIZE];
paul718e3742002-12-13 20:15:29 +00001616 } req;
1617
Feng Lu758fb8f2014-07-03 18:23:09 +08001618 struct zebra_vrf *zvrf = vrf_info_lookup (rib->vrf_id);
1619
Jorge Boncompte [DTI2]a4c06de2012-04-20 14:28:40 +02001620 memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
paul718e3742002-12-13 20:15:29 +00001621
1622 bytelen = (family == AF_INET ? 4 : 16);
1623
1624 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
Timo Teräs0abf6792016-01-15 17:36:29 +02001625 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REPLACE | NLM_F_REQUEST;
paul718e3742002-12-13 20:15:29 +00001626 req.n.nlmsg_type = cmd;
1627 req.r.rtm_family = family;
1628 req.r.rtm_table = rib->table;
1629 req.r.rtm_dst_len = p->prefixlen;
Timo Teräs40da2212008-08-13 17:37:14 +01001630 req.r.rtm_protocol = RTPROT_ZEBRA;
Timo Teräs82a66352016-01-15 17:36:30 +02001631 req.r.rtm_scope = RT_SCOPE_LINK;
paul718e3742002-12-13 20:15:29 +00001632
paul7021c422003-07-15 12:52:22 +00001633 if ((rib->flags & ZEBRA_FLAG_BLACKHOLE) || (rib->flags & ZEBRA_FLAG_REJECT))
paul718e3742002-12-13 20:15:29 +00001634 discard = 1;
1635 else
1636 discard = 0;
1637
paul7021c422003-07-15 12:52:22 +00001638 if (cmd == RTM_NEWROUTE)
paul718e3742002-12-13 20:15:29 +00001639 {
paul7021c422003-07-15 12:52:22 +00001640 if (discard)
paul595db7f2003-05-25 21:35:06 +00001641 {
1642 if (rib->flags & ZEBRA_FLAG_BLACKHOLE)
1643 req.r.rtm_type = RTN_BLACKHOLE;
1644 else if (rib->flags & ZEBRA_FLAG_REJECT)
1645 req.r.rtm_type = RTN_UNREACHABLE;
paul7021c422003-07-15 12:52:22 +00001646 else
1647 assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
1648 }
paul595db7f2003-05-25 21:35:06 +00001649 else
paul7021c422003-07-15 12:52:22 +00001650 req.r.rtm_type = RTN_UNICAST;
paul718e3742002-12-13 20:15:29 +00001651 }
1652
1653 addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
1654
1655 /* Metric. */
Timo Teräs4d3ae712016-01-15 17:36:32 +02001656 addattr32 (&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC);
paul718e3742002-12-13 20:15:29 +00001657
Timo Teräsb11f3b52015-11-02 16:50:07 +02001658 if (rib->mtu || rib->nexthop_mtu)
1659 {
1660 char buf[NL_PKT_BUF_SIZE];
1661 struct rtattr *rta = (void *) buf;
1662 u_int32_t mtu = rib->mtu;
1663 if (!mtu || (rib->nexthop_mtu && rib->nexthop_mtu < mtu))
1664 mtu = rib->nexthop_mtu;
1665 rta->rta_type = RTA_METRICS;
1666 rta->rta_len = RTA_LENGTH(0);
1667 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTAX_MTU, &mtu, sizeof mtu);
1668 addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA (rta),
1669 RTA_PAYLOAD (rta));
1670 }
1671
paul718e3742002-12-13 20:15:29 +00001672 if (discard)
1673 {
1674 if (cmd == RTM_NEWROUTE)
Christian Frankefa713d92013-07-05 15:35:37 +00001675 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1676 {
1677 /* We shouldn't encounter recursive nexthops on discard routes,
1678 * but it is probably better to handle that case correctly anyway.
1679 */
1680 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1681 continue;
1682 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1683 }
paul718e3742002-12-13 20:15:29 +00001684 goto skip;
1685 }
1686
Christian Frankefa713d92013-07-05 15:35:37 +00001687 /* Count overall nexthops so we can decide whether to use singlepath
1688 * or multipath case. */
1689 nexthop_num = 0;
1690 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul718e3742002-12-13 20:15:29 +00001691 {
Christian Frankefa713d92013-07-05 15:35:37 +00001692 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1693 continue;
1694 if (cmd == RTM_NEWROUTE && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1695 continue;
1696 if (cmd == RTM_DELROUTE && !CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1697 continue;
1698
Timo Teräs82a66352016-01-15 17:36:30 +02001699 if (nexthop->type != NEXTHOP_TYPE_IFINDEX &&
1700 nexthop->type != NEXTHOP_TYPE_IFNAME)
1701 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1702
Christian Frankefa713d92013-07-05 15:35:37 +00001703 nexthop_num++;
1704 }
1705
1706 /* Singlepath case. */
1707 if (nexthop_num == 1 || MULTIPATH_NUM == 1)
1708 {
1709 nexthop_num = 0;
1710 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul7021c422003-07-15 12:52:22 +00001711 {
Christian Frankefa713d92013-07-05 15:35:37 +00001712 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1713 continue;
paul5ec90d22003-06-19 01:41:37 +00001714
paul7021c422003-07-15 12:52:22 +00001715 if ((cmd == RTM_NEWROUTE
1716 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1717 || (cmd == RTM_DELROUTE
1718 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1719 {
Christian Frankefa713d92013-07-05 15:35:37 +00001720 routedesc = recursing ? "recursive, 1 hop" : "single hop";
paul5ec90d22003-06-19 01:41:37 +00001721
Feng Lu758fb8f2014-07-03 18:23:09 +08001722 _netlink_route_debug(cmd, p, nexthop, routedesc, family, zvrf);
Christian Frankefa713d92013-07-05 15:35:37 +00001723 _netlink_route_build_singlepath(routedesc, bytelen,
Christian Frankee8d3d292013-07-05 15:35:39 +00001724 nexthop, &req.n, &req.r,
1725 sizeof req);
paul718e3742002-12-13 20:15:29 +00001726
paul7021c422003-07-15 12:52:22 +00001727 if (cmd == RTM_NEWROUTE)
1728 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
paul718e3742002-12-13 20:15:29 +00001729
paul7021c422003-07-15 12:52:22 +00001730 nexthop_num++;
1731 break;
1732 }
1733 }
paul718e3742002-12-13 20:15:29 +00001734 }
1735 else
1736 {
JR Rivers3cadc0c2012-04-01 12:16:31 -07001737 char buf[NL_PKT_BUF_SIZE];
paul718e3742002-12-13 20:15:29 +00001738 struct rtattr *rta = (void *) buf;
1739 struct rtnexthop *rtnh;
Paul Jakma7514fb72007-05-02 16:05:35 +00001740 union g_addr *src = NULL;
paul718e3742002-12-13 20:15:29 +00001741
1742 rta->rta_type = RTA_MULTIPATH;
paul7021c422003-07-15 12:52:22 +00001743 rta->rta_len = RTA_LENGTH (0);
1744 rtnh = RTA_DATA (rta);
paul718e3742002-12-13 20:15:29 +00001745
1746 nexthop_num = 0;
Christian Frankefa713d92013-07-05 15:35:37 +00001747 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
paul7021c422003-07-15 12:52:22 +00001748 {
Christian Frankefa713d92013-07-05 15:35:37 +00001749 if (MULTIPATH_NUM != 0 && nexthop_num >= MULTIPATH_NUM)
1750 break;
1751
1752 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1753 continue;
1754
paul7021c422003-07-15 12:52:22 +00001755 if ((cmd == RTM_NEWROUTE
1756 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1757 || (cmd == RTM_DELROUTE
1758 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1759 {
Christian Frankefa713d92013-07-05 15:35:37 +00001760 routedesc = recursing ? "recursive, multihop" : "multihop";
paul7021c422003-07-15 12:52:22 +00001761 nexthop_num++;
paul718e3742002-12-13 20:15:29 +00001762
Christian Frankefa713d92013-07-05 15:35:37 +00001763 _netlink_route_debug(cmd, p, nexthop,
Feng Lu758fb8f2014-07-03 18:23:09 +08001764 routedesc, family, zvrf);
Christian Frankefa713d92013-07-05 15:35:37 +00001765 _netlink_route_build_multipath(routedesc, bytelen,
1766 nexthop, rta, rtnh, &src);
paul7021c422003-07-15 12:52:22 +00001767 rtnh = RTNH_NEXT (rtnh);
paul718e3742002-12-13 20:15:29 +00001768
paul7021c422003-07-15 12:52:22 +00001769 if (cmd == RTM_NEWROUTE)
1770 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1771 }
1772 }
Paul Jakma7514fb72007-05-02 16:05:35 +00001773 if (src)
1774 addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src->ipv4, bytelen);
paul718e3742002-12-13 20:15:29 +00001775
1776 if (rta->rta_len > RTA_LENGTH (0))
JR Rivers3cadc0c2012-04-01 12:16:31 -07001777 addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta),
paul7021c422003-07-15 12:52:22 +00001778 RTA_PAYLOAD (rta));
paul718e3742002-12-13 20:15:29 +00001779 }
1780
1781 /* If there is no useful nexthop then return. */
1782 if (nexthop_num == 0)
1783 {
1784 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +00001785 zlog_debug ("netlink_route_multipath(): No useful nexthop.");
paul718e3742002-12-13 20:15:29 +00001786 return 0;
1787 }
1788
paul7021c422003-07-15 12:52:22 +00001789skip:
paul718e3742002-12-13 20:15:29 +00001790
1791 /* Destination netlink address. */
1792 memset (&snl, 0, sizeof snl);
1793 snl.nl_family = AF_NETLINK;
1794
paul718e3742002-12-13 20:15:29 +00001795 /* Talk to netlink socket. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001796 return netlink_talk (&req.n, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001797}
1798
1799int
Timo Teräs0abf6792016-01-15 17:36:29 +02001800kernel_route_rib (struct prefix *p, struct rib *old, struct rib *new)
paul718e3742002-12-13 20:15:29 +00001801{
Timo Teräs0abf6792016-01-15 17:36:29 +02001802 if (!old && new)
1803 return netlink_route_multipath (RTM_NEWROUTE, p, new);
1804 if (old && !new)
1805 return netlink_route_multipath (RTM_DELROUTE, p, old);
paul718e3742002-12-13 20:15:29 +00001806
Timo Teräs4d3ae712016-01-15 17:36:32 +02001807 /* Replace, can be done atomically if metric does not change;
1808 * netlink uses [prefix, tos, priority] to identify prefix.
1809 * Now metric is not sent to kernel, so we can just do atomic replace. */
1810 return netlink_route_multipath (RTM_NEWROUTE, p, new);
paul718e3742002-12-13 20:15:29 +00001811}
David Lamparter6b0655a2014-06-04 06:53:35 +02001812
paul718e3742002-12-13 20:15:29 +00001813/* Interface address modification. */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001814static int
paul718e3742002-12-13 20:15:29 +00001815netlink_address (int cmd, int family, struct interface *ifp,
paul7021c422003-07-15 12:52:22 +00001816 struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001817{
1818 int bytelen;
1819 struct prefix *p;
1820
paul7021c422003-07-15 12:52:22 +00001821 struct
paul718e3742002-12-13 20:15:29 +00001822 {
1823 struct nlmsghdr n;
1824 struct ifaddrmsg ifa;
JR Rivers3cadc0c2012-04-01 12:16:31 -07001825 char buf[NL_PKT_BUF_SIZE];
paul718e3742002-12-13 20:15:29 +00001826 } req;
1827
Feng Lu758fb8f2014-07-03 18:23:09 +08001828 struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
1829
paul718e3742002-12-13 20:15:29 +00001830 p = ifc->address;
Jorge Boncompte [DTI2]a4c06de2012-04-20 14:28:40 +02001831 memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
paul718e3742002-12-13 20:15:29 +00001832
1833 bytelen = (family == AF_INET ? 4 : 16);
1834
paul7021c422003-07-15 12:52:22 +00001835 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg));
paul718e3742002-12-13 20:15:29 +00001836 req.n.nlmsg_flags = NLM_F_REQUEST;
1837 req.n.nlmsg_type = cmd;
1838 req.ifa.ifa_family = family;
1839
1840 req.ifa.ifa_index = ifp->ifindex;
1841 req.ifa.ifa_prefixlen = p->prefixlen;
1842
1843 addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen);
1844
1845 if (family == AF_INET && cmd == RTM_NEWADDR)
1846 {
Andrew J. Schorre4529632006-12-12 19:18:21 +00001847 if (!CONNECTED_PEER(ifc) && ifc->destination)
paul7021c422003-07-15 12:52:22 +00001848 {
1849 p = ifc->destination;
1850 addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix,
1851 bytelen);
1852 }
paul718e3742002-12-13 20:15:29 +00001853 }
1854
1855 if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
1856 SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY);
paul7021c422003-07-15 12:52:22 +00001857
paul718e3742002-12-13 20:15:29 +00001858 if (ifc->label)
1859 addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label,
paul7021c422003-07-15 12:52:22 +00001860 strlen (ifc->label) + 1);
paul718e3742002-12-13 20:15:29 +00001861
Feng Lu758fb8f2014-07-03 18:23:09 +08001862 return netlink_talk (&req.n, &zvrf->netlink_cmd, zvrf);
paul718e3742002-12-13 20:15:29 +00001863}
1864
1865int
1866kernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc)
1867{
1868 return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc);
1869}
1870
1871int
1872kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc)
1873{
1874 return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc);
1875}
1876
paul718e3742002-12-13 20:15:29 +00001877
1878extern struct thread_master *master;
1879
1880/* Kernel route reflection. */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001881static int
paul718e3742002-12-13 20:15:29 +00001882kernel_read (struct thread *thread)
1883{
Feng Lu758fb8f2014-07-03 18:23:09 +08001884 struct zebra_vrf *zvrf = (struct zebra_vrf *)THREAD_ARG (thread);
1885 netlink_parse_info (netlink_information_fetch, &zvrf->netlink, zvrf);
1886 zvrf->t_netlink = thread_add_read (zebrad.master, kernel_read, zvrf,
1887 zvrf->netlink.sock);
paul718e3742002-12-13 20:15:29 +00001888
1889 return 0;
1890}
1891
Stephen Hemminger3d265b42008-08-16 17:30:39 +01001892/* Filter out messages from self that occur on listener socket,
1893 caused by our actions on the command socket
1894 */
1895static void netlink_install_filter (int sock, __u32 pid)
Paul Jakma768a27e2008-05-29 18:23:08 +00001896{
Paul Jakma768a27e2008-05-29 18:23:08 +00001897 struct sock_filter filter[] = {
Stephen Hemminger3d265b42008-08-16 17:30:39 +01001898 /* 0: ldh [4] */
1899 BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)),
1900 /* 1: jeq 0x18 jt 3 jf 6 */
1901 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 1, 0),
1902 /* 2: jeq 0x19 jt 3 jf 6 */
1903 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 0, 3),
1904 /* 3: ldw [12] */
1905 BPF_STMT(BPF_LD|BPF_ABS|BPF_W, offsetof(struct nlmsghdr, nlmsg_pid)),
1906 /* 4: jeq XX jt 5 jf 6 */
1907 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htonl(pid), 0, 1),
1908 /* 5: ret 0 (skip) */
1909 BPF_STMT(BPF_RET|BPF_K, 0),
1910 /* 6: ret 0xffff (keep) */
1911 BPF_STMT(BPF_RET|BPF_K, 0xffff),
Paul Jakma768a27e2008-05-29 18:23:08 +00001912 };
1913
1914 struct sock_fprog prog = {
Balaji.G837d16c2012-09-26 14:09:10 +05301915 .len = array_size(filter),
Paul Jakma768a27e2008-05-29 18:23:08 +00001916 .filter = filter,
1917 };
1918
1919 if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)) < 0)
1920 zlog_warn ("Can't install socket filter: %s\n", safe_strerror(errno));
1921}
1922
paul718e3742002-12-13 20:15:29 +00001923/* Exported interface function. This function simply calls
1924 netlink_socket (). */
1925void
Feng Lu758fb8f2014-07-03 18:23:09 +08001926kernel_init (struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001927{
1928 unsigned long groups;
1929
paul7021c422003-07-15 12:52:22 +00001930 groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR;
paul718e3742002-12-13 20:15:29 +00001931#ifdef HAVE_IPV6
paul7021c422003-07-15 12:52:22 +00001932 groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR;
paul718e3742002-12-13 20:15:29 +00001933#endif /* HAVE_IPV6 */
Feng Lu758fb8f2014-07-03 18:23:09 +08001934 netlink_socket (&zvrf->netlink, groups, zvrf->vrf_id);
1935 netlink_socket (&zvrf->netlink_cmd, 0, zvrf->vrf_id);
paul718e3742002-12-13 20:15:29 +00001936
1937 /* Register kernel socket. */
Feng Lu758fb8f2014-07-03 18:23:09 +08001938 if (zvrf->netlink.sock > 0)
Paul Jakma768a27e2008-05-29 18:23:08 +00001939 {
Stephen Hemminger4cde9312008-08-16 17:51:27 +01001940 /* Only want non-blocking on the netlink event socket */
Feng Lu758fb8f2014-07-03 18:23:09 +08001941 if (fcntl (zvrf->netlink.sock, F_SETFL, O_NONBLOCK) < 0)
1942 zlog_err ("Can't set %s socket flags: %s", zvrf->netlink.name,
1943 safe_strerror (errno));
Stephen Hemminger4cde9312008-08-16 17:51:27 +01001944
Stephen Hemminger30afea32008-08-16 18:25:47 +01001945 /* Set receive buffer size if it's set from command line */
1946 if (nl_rcvbufsize)
Feng Lu758fb8f2014-07-03 18:23:09 +08001947 netlink_recvbuf (&zvrf->netlink, nl_rcvbufsize);
Stephen Hemminger30afea32008-08-16 18:25:47 +01001948
Feng Lu758fb8f2014-07-03 18:23:09 +08001949 netlink_install_filter (zvrf->netlink.sock, zvrf->netlink_cmd.snl.nl_pid);
1950 zvrf->t_netlink = thread_add_read (zebrad.master, kernel_read, zvrf,
1951 zvrf->netlink.sock);
1952 }
1953}
1954
1955void
1956kernel_terminate (struct zebra_vrf *zvrf)
1957{
1958 THREAD_READ_OFF (zvrf->t_netlink);
1959
1960 if (zvrf->netlink.sock >= 0)
1961 {
1962 close (zvrf->netlink.sock);
1963 zvrf->netlink.sock = -1;
1964 }
1965
1966 if (zvrf->netlink_cmd.sock >= 0)
1967 {
1968 close (zvrf->netlink_cmd.sock);
1969 zvrf->netlink_cmd.sock = -1;
Paul Jakma768a27e2008-05-29 18:23:08 +00001970 }
paul718e3742002-12-13 20:15:29 +00001971}
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001972
1973/*
1974 * nl_msg_type_to_str
1975 */
1976const char *
1977nl_msg_type_to_str (uint16_t msg_type)
1978{
1979 return lookup (nlmsg_str, msg_type);
1980}
1981
1982/*
1983 * nl_rtproto_to_str
1984 */
1985const char *
1986nl_rtproto_to_str (u_char rtproto)
1987{
1988 return lookup (rtproto_str, rtproto);
1989}