blob: bab170371f58f0c61bf295263c6c3995ff9fe342 [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"
paul718e3742002-12-13 20:15:29 +000039
40#include "zebra/zserv.h"
paul6621ca82005-11-23 13:02:08 +000041#include "zebra/rt.h"
paul718e3742002-12-13 20:15:29 +000042#include "zebra/redistribute.h"
43#include "zebra/interface.h"
44#include "zebra/debug.h"
45
Avneesh Sachdev78deec42012-11-13 22:48:56 +000046#include "rt_netlink.h"
JR Rivers3cadc0c2012-04-01 12:16:31 -070047
paul718e3742002-12-13 20:15:29 +000048/* Socket interface to kernel */
49struct nlsock
50{
51 int sock;
52 int seq;
53 struct sockaddr_nl snl;
hassofce954f2004-10-07 20:29:24 +000054 const char *name;
paul7021c422003-07-15 12:52:22 +000055} netlink = { -1, 0, {0}, "netlink-listen"}, /* kernel messages */
hasso1ada8192005-06-12 11:28:18 +000056 netlink_cmd = { -1, 0, {0}, "netlink-cmd"}; /* command channel */
paul718e3742002-12-13 20:15:29 +000057
Stephen Hemminger1423c802008-08-14 17:59:25 +010058static const struct message nlmsg_str[] = {
paul718e3742002-12-13 20:15:29 +000059 {RTM_NEWROUTE, "RTM_NEWROUTE"},
60 {RTM_DELROUTE, "RTM_DELROUTE"},
61 {RTM_GETROUTE, "RTM_GETROUTE"},
62 {RTM_NEWLINK, "RTM_NEWLINK"},
63 {RTM_DELLINK, "RTM_DELLINK"},
64 {RTM_GETLINK, "RTM_GETLINK"},
65 {RTM_NEWADDR, "RTM_NEWADDR"},
66 {RTM_DELADDR, "RTM_DELADDR"},
67 {RTM_GETADDR, "RTM_GETADDR"},
paul7021c422003-07-15 12:52:22 +000068 {0, NULL}
paul718e3742002-12-13 20:15:29 +000069};
70
paulb21b19c2003-06-15 01:28:29 +000071extern struct zebra_t zebrad;
paul718e3742002-12-13 20:15:29 +000072
pauledd7c242003-06-04 13:59:38 +000073extern struct zebra_privs_t zserv_privs;
74
hassoc34b6b52004-08-31 13:41:49 +000075extern u_int32_t nl_rcvbufsize;
76
ajsd2fc8892005-04-02 18:38:43 +000077/* Note: on netlink systems, there should be a 1-to-1 mapping between interface
78 names and ifindex values. */
79static void
80set_ifindex(struct interface *ifp, unsigned int ifi_index)
81{
82 struct interface *oifp;
83
84 if (((oifp = if_lookup_by_index(ifi_index)) != NULL) && (oifp != ifp))
85 {
86 if (ifi_index == IFINDEX_INTERNAL)
87 zlog_err("Netlink is setting interface %s ifindex to reserved "
88 "internal value %u", ifp->name, ifi_index);
89 else
90 {
91 if (IS_ZEBRA_DEBUG_KERNEL)
92 zlog_debug("interface index %d was renamed from %s to %s",
93 ifi_index, oifp->name, ifp->name);
94 if (if_is_up(oifp))
95 zlog_err("interface rename detected on up interface: index %d "
96 "was renamed from %s to %s, results are uncertain!",
97 ifi_index, oifp->name, ifp->name);
98 if_delete_update(oifp);
99 }
100 }
101 ifp->ifindex = ifi_index;
102}
103
Ulrich Weberf1ef81b2013-01-22 10:39:18 +0000104#ifndef SO_RCVBUFFORCE
105#define SO_RCVBUFFORCE (33)
106#endif
107
Stephen Hemminger30afea32008-08-16 18:25:47 +0100108static int
109netlink_recvbuf (struct nlsock *nl, uint32_t newsize)
110{
111 u_int32_t oldsize;
112 socklen_t newlen = sizeof(newsize);
113 socklen_t oldlen = sizeof(oldsize);
114 int ret;
115
116 ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &oldsize, &oldlen);
117 if (ret < 0)
118 {
119 zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name,
120 safe_strerror (errno));
121 return -1;
122 }
123
Ulrich Weberf1ef81b2013-01-22 10:39:18 +0000124 /* Try force option (linux >= 2.6.14) and fall back to normal set */
125 if ( zserv_privs.change (ZPRIVS_RAISE) )
126 zlog_err ("routing_socket: Can't raise privileges");
127 ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUFFORCE, &nl_rcvbufsize,
Stephen Hemminger30afea32008-08-16 18:25:47 +0100128 sizeof(nl_rcvbufsize));
Ulrich Weberf1ef81b2013-01-22 10:39:18 +0000129 if ( zserv_privs.change (ZPRIVS_LOWER) )
130 zlog_err ("routing_socket: Can't lower privileges");
131 if (ret < 0)
132 ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &nl_rcvbufsize,
133 sizeof(nl_rcvbufsize));
Stephen Hemminger30afea32008-08-16 18:25:47 +0100134 if (ret < 0)
135 {
136 zlog (NULL, LOG_ERR, "Can't set %s receive buffer size: %s", nl->name,
137 safe_strerror (errno));
138 return -1;
139 }
140
141 ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &newsize, &newlen);
142 if (ret < 0)
143 {
144 zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name,
145 safe_strerror (errno));
146 return -1;
147 }
148
149 zlog (NULL, LOG_INFO,
150 "Setting netlink socket receive buffer size: %u -> %u",
151 oldsize, newsize);
152 return 0;
153}
154
paul718e3742002-12-13 20:15:29 +0000155/* Make socket for Linux netlink interface. */
156static int
157netlink_socket (struct nlsock *nl, unsigned long groups)
158{
159 int ret;
160 struct sockaddr_nl snl;
161 int sock;
162 int namelen;
ajs4be019d2005-01-29 16:12:41 +0000163 int save_errno;
paul718e3742002-12-13 20:15:29 +0000164
165 sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
166 if (sock < 0)
167 {
168 zlog (NULL, LOG_ERR, "Can't open %s socket: %s", nl->name,
ajs6099b3b2004-11-20 02:06:59 +0000169 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000170 return -1;
171 }
172
paul718e3742002-12-13 20:15:29 +0000173 memset (&snl, 0, sizeof snl);
174 snl.nl_family = AF_NETLINK;
175 snl.nl_groups = groups;
176
177 /* Bind the socket to the netlink structure for anything. */
paul7021c422003-07-15 12:52:22 +0000178 if (zserv_privs.change (ZPRIVS_RAISE))
179 {
180 zlog (NULL, LOG_ERR, "Can't raise privileges");
181 return -1;
182 }
pauledd7c242003-06-04 13:59:38 +0000183
paul718e3742002-12-13 20:15:29 +0000184 ret = bind (sock, (struct sockaddr *) &snl, sizeof snl);
ajs4be019d2005-01-29 16:12:41 +0000185 save_errno = errno;
hasso55e7ecd2004-08-06 08:41:56 +0000186 if (zserv_privs.change (ZPRIVS_LOWER))
187 zlog (NULL, LOG_ERR, "Can't lower privileges");
188
paul718e3742002-12-13 20:15:29 +0000189 if (ret < 0)
190 {
paul7021c422003-07-15 12:52:22 +0000191 zlog (NULL, LOG_ERR, "Can't bind %s socket to group 0x%x: %s",
ajs4be019d2005-01-29 16:12:41 +0000192 nl->name, snl.nl_groups, safe_strerror (save_errno));
paul718e3742002-12-13 20:15:29 +0000193 close (sock);
194 return -1;
195 }
paul7021c422003-07-15 12:52:22 +0000196
paul718e3742002-12-13 20:15:29 +0000197 /* multiple netlink sockets will have different nl_pid */
198 namelen = sizeof snl;
hassoc9e52be2004-09-26 16:09:34 +0000199 ret = getsockname (sock, (struct sockaddr *) &snl, (socklen_t *) &namelen);
paul718e3742002-12-13 20:15:29 +0000200 if (ret < 0 || namelen != sizeof snl)
201 {
202 zlog (NULL, LOG_ERR, "Can't get %s socket name: %s", nl->name,
ajs6099b3b2004-11-20 02:06:59 +0000203 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000204 close (sock);
205 return -1;
206 }
207
208 nl->snl = snl;
209 nl->sock = sock;
210 return ret;
211}
212
213/* Get type specified information from netlink. */
214static int
215netlink_request (int family, int type, struct nlsock *nl)
216{
217 int ret;
218 struct sockaddr_nl snl;
ajs4be019d2005-01-29 16:12:41 +0000219 int save_errno;
paul718e3742002-12-13 20:15:29 +0000220
221 struct
222 {
223 struct nlmsghdr nlh;
224 struct rtgenmsg g;
225 } req;
226
227
228 /* Check netlink socket. */
229 if (nl->sock < 0)
230 {
231 zlog (NULL, LOG_ERR, "%s socket isn't active.", nl->name);
232 return -1;
233 }
234
235 memset (&snl, 0, sizeof snl);
236 snl.nl_family = AF_NETLINK;
237
ajsc05612b2005-10-01 16:36:54 +0000238 memset (&req, 0, sizeof req);
paul718e3742002-12-13 20:15:29 +0000239 req.nlh.nlmsg_len = sizeof req;
240 req.nlh.nlmsg_type = type;
241 req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
Stephen Hemminger3d265b42008-08-16 17:30:39 +0100242 req.nlh.nlmsg_pid = nl->snl.nl_pid;
paul718e3742002-12-13 20:15:29 +0000243 req.nlh.nlmsg_seq = ++nl->seq;
244 req.g.rtgen_family = family;
pauledd7c242003-06-04 13:59:38 +0000245
246 /* linux appears to check capabilities on every message
247 * have to raise caps for every message sent
248 */
paul7021c422003-07-15 12:52:22 +0000249 if (zserv_privs.change (ZPRIVS_RAISE))
pauledd7c242003-06-04 13:59:38 +0000250 {
251 zlog (NULL, LOG_ERR, "Can't raise privileges");
252 return -1;
253 }
paul7021c422003-07-15 12:52:22 +0000254
255 ret = sendto (nl->sock, (void *) &req, sizeof req, 0,
256 (struct sockaddr *) &snl, sizeof snl);
ajs4be019d2005-01-29 16:12:41 +0000257 save_errno = errno;
paul7021c422003-07-15 12:52:22 +0000258
259 if (zserv_privs.change (ZPRIVS_LOWER))
260 zlog (NULL, LOG_ERR, "Can't lower privileges");
261
paul718e3742002-12-13 20:15:29 +0000262 if (ret < 0)
paul7021c422003-07-15 12:52:22 +0000263 {
264 zlog (NULL, LOG_ERR, "%s sendto failed: %s", nl->name,
ajs4be019d2005-01-29 16:12:41 +0000265 safe_strerror (save_errno));
paul718e3742002-12-13 20:15:29 +0000266 return -1;
267 }
pauledd7c242003-06-04 13:59:38 +0000268
paul718e3742002-12-13 20:15:29 +0000269 return 0;
270}
271
272/* Receive message from netlink interface and pass those information
273 to the given function. */
274static int
275netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *),
paul7021c422003-07-15 12:52:22 +0000276 struct nlsock *nl)
paul718e3742002-12-13 20:15:29 +0000277{
278 int status;
279 int ret = 0;
280 int error;
281
282 while (1)
283 {
JR Rivers3cadc0c2012-04-01 12:16:31 -0700284 char buf[NL_PKT_BUF_SIZE];
paul718e3742002-12-13 20:15:29 +0000285 struct iovec iov = { buf, sizeof buf };
286 struct sockaddr_nl snl;
paul7021c422003-07-15 12:52:22 +0000287 struct msghdr msg = { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 };
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 */
357 if (nl == &netlink_cmd
358 && ((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
384 /* skip unsolicited messages originating from command socket */
385 if (nl != &netlink_cmd && h->nlmsg_pid == netlink_cmd.snl.nl_pid)
386 {
387 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000388 zlog_debug ("netlink_parse_info: %s packet comes from %s",
hasso1ada8192005-06-12 11:28:18 +0000389 netlink_cmd.name, nl->name);
paul7021c422003-07-15 12:52:22 +0000390 continue;
391 }
392
393 error = (*filter) (&snl, h);
394 if (error < 0)
395 {
396 zlog (NULL, LOG_ERR, "%s filter function error", nl->name);
397 ret = error;
398 }
399 }
paul718e3742002-12-13 20:15:29 +0000400
401 /* After error care. */
402 if (msg.msg_flags & MSG_TRUNC)
paul7021c422003-07-15 12:52:22 +0000403 {
404 zlog (NULL, LOG_ERR, "%s error: message truncated", nl->name);
405 continue;
406 }
paul718e3742002-12-13 20:15:29 +0000407 if (status)
paul7021c422003-07-15 12:52:22 +0000408 {
409 zlog (NULL, LOG_ERR, "%s error: data remnant size %d", nl->name,
410 status);
411 return -1;
412 }
paul718e3742002-12-13 20:15:29 +0000413 }
414 return ret;
415}
416
417/* Utility function for parse rtattr. */
418static void
paul7021c422003-07-15 12:52:22 +0000419netlink_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta,
420 int len)
paul718e3742002-12-13 20:15:29 +0000421{
paul7021c422003-07-15 12:52:22 +0000422 while (RTA_OK (rta, len))
paul718e3742002-12-13 20:15:29 +0000423 {
424 if (rta->rta_type <= max)
paul7021c422003-07-15 12:52:22 +0000425 tb[rta->rta_type] = rta;
426 rta = RTA_NEXT (rta, len);
paul718e3742002-12-13 20:15:29 +0000427 }
428}
429
Josh Bailey26e2ae32012-03-22 01:09:21 -0700430/* Utility function to parse hardware link-layer address and update ifp */
431static void
432netlink_interface_update_hw_addr (struct rtattr **tb, struct interface *ifp)
433{
434 int i;
435
436 if (tb[IFLA_ADDRESS])
437 {
438 int hw_addr_len;
439
440 hw_addr_len = RTA_PAYLOAD (tb[IFLA_ADDRESS]);
441
442 if (hw_addr_len > INTERFACE_HWADDR_MAX)
443 zlog_warn ("Hardware address is too large: %d", hw_addr_len);
444 else
445 {
446 ifp->hw_addr_len = hw_addr_len;
447 memcpy (ifp->hw_addr, RTA_DATA (tb[IFLA_ADDRESS]), hw_addr_len);
448
449 for (i = 0; i < hw_addr_len; i++)
450 if (ifp->hw_addr[i] != 0)
451 break;
452
453 if (i == hw_addr_len)
454 ifp->hw_addr_len = 0;
455 else
456 ifp->hw_addr_len = hw_addr_len;
457 }
458 }
459}
460
paul718e3742002-12-13 20:15:29 +0000461/* Called from interface_lookup_netlink(). This function is only used
462 during bootstrap. */
Stephen Hemminger6072b242008-08-14 16:52:26 +0100463static int
paul718e3742002-12-13 20:15:29 +0000464netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h)
465{
466 int len;
467 struct ifinfomsg *ifi;
468 struct rtattr *tb[IFLA_MAX + 1];
469 struct interface *ifp;
470 char *name;
paul718e3742002-12-13 20:15:29 +0000471
472 ifi = NLMSG_DATA (h);
473
474 if (h->nlmsg_type != RTM_NEWLINK)
475 return 0;
476
477 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
478 if (len < 0)
479 return -1;
480
481 /* Looking up interface name. */
482 memset (tb, 0, sizeof tb);
483 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
paulc15cb242005-01-24 09:05:27 +0000484
paul1e193152005-02-14 23:53:05 +0000485#ifdef IFLA_WIRELESS
paulc15cb242005-01-24 09:05:27 +0000486 /* check for wireless messages to ignore */
487 if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
488 {
489 if (IS_ZEBRA_DEBUG_KERNEL)
490 zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__);
491 return 0;
492 }
paul1e193152005-02-14 23:53:05 +0000493#endif /* IFLA_WIRELESS */
paulc15cb242005-01-24 09:05:27 +0000494
paul718e3742002-12-13 20:15:29 +0000495 if (tb[IFLA_IFNAME] == NULL)
496 return -1;
paul7021c422003-07-15 12:52:22 +0000497 name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
paul718e3742002-12-13 20:15:29 +0000498
499 /* Add interface. */
500 ifp = if_get_by_name (name);
ajsd2fc8892005-04-02 18:38:43 +0000501 set_ifindex(ifp, ifi->ifi_index);
paul718e3742002-12-13 20:15:29 +0000502 ifp->flags = ifi->ifi_flags & 0x0000fffff;
Stephen Hemminger4308abb2008-12-01 14:19:38 -0800503 ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]);
paul718e3742002-12-13 20:15:29 +0000504 ifp->metric = 1;
505
506 /* Hardware type and address. */
507 ifp->hw_type = ifi->ifi_type;
Josh Bailey26e2ae32012-03-22 01:09:21 -0700508 netlink_interface_update_hw_addr (tb, ifp);
paul718e3742002-12-13 20:15:29 +0000509
510 if_add_update (ifp);
511
512 return 0;
513}
514
515/* Lookup interface IPv4/IPv6 address. */
Stephen Hemminger6072b242008-08-14 16:52:26 +0100516static int
paul718e3742002-12-13 20:15:29 +0000517netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
518{
519 int len;
520 struct ifaddrmsg *ifa;
paul7021c422003-07-15 12:52:22 +0000521 struct rtattr *tb[IFA_MAX + 1];
paul718e3742002-12-13 20:15:29 +0000522 struct interface *ifp;
Andrew J. Schorre4529632006-12-12 19:18:21 +0000523 void *addr;
524 void *broad;
paul718e3742002-12-13 20:15:29 +0000525 u_char flags = 0;
526 char *label = NULL;
527
528 ifa = NLMSG_DATA (h);
529
paul7021c422003-07-15 12:52:22 +0000530 if (ifa->ifa_family != AF_INET
paul718e3742002-12-13 20:15:29 +0000531#ifdef HAVE_IPV6
532 && ifa->ifa_family != AF_INET6
533#endif /* HAVE_IPV6 */
paul7021c422003-07-15 12:52:22 +0000534 )
paul718e3742002-12-13 20:15:29 +0000535 return 0;
536
537 if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
538 return 0;
539
paul7021c422003-07-15 12:52:22 +0000540 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifaddrmsg));
paul718e3742002-12-13 20:15:29 +0000541 if (len < 0)
542 return -1;
543
544 memset (tb, 0, sizeof tb);
545 netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len);
546
547 ifp = if_lookup_by_index (ifa->ifa_index);
548 if (ifp == NULL)
549 {
550 zlog_err ("netlink_interface_addr can't find interface by index %d",
paul7021c422003-07-15 12:52:22 +0000551 ifa->ifa_index);
paul718e3742002-12-13 20:15:29 +0000552 return -1;
553 }
554
paul7021c422003-07-15 12:52:22 +0000555 if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */
paul718e3742002-12-13 20:15:29 +0000556 {
paul00df0c12002-12-13 21:07:36 +0000557 char buf[BUFSIZ];
hasso206d8052005-04-09 16:38:51 +0000558 zlog_debug ("netlink_interface_addr %s %s:",
559 lookup (nlmsg_str, h->nlmsg_type), ifp->name);
paul718e3742002-12-13 20:15:29 +0000560 if (tb[IFA_LOCAL])
hasso206d8052005-04-09 16:38:51 +0000561 zlog_debug (" IFA_LOCAL %s/%d",
562 inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]),
563 buf, BUFSIZ), ifa->ifa_prefixlen);
paul718e3742002-12-13 20:15:29 +0000564 if (tb[IFA_ADDRESS])
hasso206d8052005-04-09 16:38:51 +0000565 zlog_debug (" IFA_ADDRESS %s/%d",
566 inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_ADDRESS]),
567 buf, BUFSIZ), ifa->ifa_prefixlen);
paul718e3742002-12-13 20:15:29 +0000568 if (tb[IFA_BROADCAST])
hasso206d8052005-04-09 16:38:51 +0000569 zlog_debug (" IFA_BROADCAST %s/%d",
570 inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_BROADCAST]),
571 buf, BUFSIZ), ifa->ifa_prefixlen);
paul00df0c12002-12-13 21:07:36 +0000572 if (tb[IFA_LABEL] && strcmp (ifp->name, RTA_DATA (tb[IFA_LABEL])))
ajsb6178002004-12-07 21:12:56 +0000573 zlog_debug (" IFA_LABEL %s", (char *)RTA_DATA (tb[IFA_LABEL]));
pauld34b8992006-01-17 18:03:04 +0000574
575 if (tb[IFA_CACHEINFO])
576 {
577 struct ifa_cacheinfo *ci = RTA_DATA (tb[IFA_CACHEINFO]);
578 zlog_debug (" IFA_CACHEINFO pref %d, valid %d",
579 ci->ifa_prefered, ci->ifa_valid);
580 }
paul718e3742002-12-13 20:15:29 +0000581 }
paul31a476c2003-09-29 19:54:53 +0000582
Andrew J. Schorre4529632006-12-12 19:18:21 +0000583 /* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */
584 if (tb[IFA_LOCAL] == NULL)
585 tb[IFA_LOCAL] = tb[IFA_ADDRESS];
paul31a476c2003-09-29 19:54:53 +0000586 if (tb[IFA_ADDRESS] == NULL)
587 tb[IFA_ADDRESS] = tb[IFA_LOCAL];
588
Andrew J. Schorre4529632006-12-12 19:18:21 +0000589 /* local interface address */
590 addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL);
591
592 /* is there a peer address? */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000593 if (tb[IFA_ADDRESS] &&
vize068fd772007-08-10 06:25:20 +0000594 memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_ADDRESS])))
paul7021c422003-07-15 12:52:22 +0000595 {
Andrew J. Schorre4529632006-12-12 19:18:21 +0000596 broad = RTA_DATA(tb[IFA_ADDRESS]);
597 SET_FLAG (flags, ZEBRA_IFA_PEER);
paul7021c422003-07-15 12:52:22 +0000598 }
paul31a476c2003-09-29 19:54:53 +0000599 else
Andrew J. Schorre4529632006-12-12 19:18:21 +0000600 /* seeking a broadcast address */
601 broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST]) : NULL);
paul00df0c12002-12-13 21:07:36 +0000602
Paul Jakma27b47252006-07-02 16:38:54 +0000603 /* addr is primary key, SOL if we don't have one */
604 if (addr == NULL)
605 {
606 zlog_debug ("%s: NULL address", __func__);
607 return -1;
608 }
609
paul718e3742002-12-13 20:15:29 +0000610 /* Flags. */
611 if (ifa->ifa_flags & IFA_F_SECONDARY)
612 SET_FLAG (flags, ZEBRA_IFA_SECONDARY);
613
614 /* Label */
615 if (tb[IFA_LABEL])
616 label = (char *) RTA_DATA (tb[IFA_LABEL]);
617
618 if (ifp && label && strcmp (ifp->name, label) == 0)
619 label = NULL;
620
621 /* Register interface address to the interface. */
622 if (ifa->ifa_family == AF_INET)
623 {
paul7021c422003-07-15 12:52:22 +0000624 if (h->nlmsg_type == RTM_NEWADDR)
625 connected_add_ipv4 (ifp, flags,
626 (struct in_addr *) addr, ifa->ifa_prefixlen,
627 (struct in_addr *) broad, label);
628 else
629 connected_delete_ipv4 (ifp, flags,
630 (struct in_addr *) addr, ifa->ifa_prefixlen,
paul0752ef02005-11-03 12:35:21 +0000631 (struct in_addr *) broad);
paul718e3742002-12-13 20:15:29 +0000632 }
633#ifdef HAVE_IPV6
634 if (ifa->ifa_family == AF_INET6)
635 {
636 if (h->nlmsg_type == RTM_NEWADDR)
Andrew J. Schorre4529632006-12-12 19:18:21 +0000637 connected_add_ipv6 (ifp, flags,
paul7021c422003-07-15 12:52:22 +0000638 (struct in6_addr *) addr, ifa->ifa_prefixlen,
paul0752ef02005-11-03 12:35:21 +0000639 (struct in6_addr *) broad, label);
paul718e3742002-12-13 20:15:29 +0000640 else
paul7021c422003-07-15 12:52:22 +0000641 connected_delete_ipv6 (ifp,
642 (struct in6_addr *) addr, ifa->ifa_prefixlen,
643 (struct in6_addr *) broad);
paul718e3742002-12-13 20:15:29 +0000644 }
paul7021c422003-07-15 12:52:22 +0000645#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +0000646
647 return 0;
648}
649
650/* Looking up routing table by netlink interface. */
Stephen Hemminger6072b242008-08-14 16:52:26 +0100651static int
paul718e3742002-12-13 20:15:29 +0000652netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
653{
654 int len;
655 struct rtmsg *rtm;
paul7021c422003-07-15 12:52:22 +0000656 struct rtattr *tb[RTA_MAX + 1];
paul718e3742002-12-13 20:15:29 +0000657 u_char flags = 0;
paul7021c422003-07-15 12:52:22 +0000658
659 char anyaddr[16] = { 0 };
paul718e3742002-12-13 20:15:29 +0000660
661 int index;
662 int table;
hasso34195bf2004-04-06 12:07:06 +0000663 int metric;
664
paul718e3742002-12-13 20:15:29 +0000665 void *dest;
666 void *gate;
Paul Jakma7514fb72007-05-02 16:05:35 +0000667 void *src;
paul718e3742002-12-13 20:15:29 +0000668
669 rtm = NLMSG_DATA (h);
670
671 if (h->nlmsg_type != RTM_NEWROUTE)
672 return 0;
673 if (rtm->rtm_type != RTN_UNICAST)
674 return 0;
675
676 table = rtm->rtm_table;
paul7021c422003-07-15 12:52:22 +0000677#if 0 /* we weed them out later in rib_weed_tables () */
paulb21b19c2003-06-15 01:28:29 +0000678 if (table != RT_TABLE_MAIN && table != zebrad.rtm_table_default)
paul718e3742002-12-13 20:15:29 +0000679 return 0;
680#endif
681
paul7021c422003-07-15 12:52:22 +0000682 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
paul718e3742002-12-13 20:15:29 +0000683 if (len < 0)
684 return -1;
685
686 memset (tb, 0, sizeof tb);
687 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
688
689 if (rtm->rtm_flags & RTM_F_CLONED)
690 return 0;
691 if (rtm->rtm_protocol == RTPROT_REDIRECT)
692 return 0;
693 if (rtm->rtm_protocol == RTPROT_KERNEL)
694 return 0;
695
696 if (rtm->rtm_src_len != 0)
697 return 0;
698
699 /* Route which inserted by Zebra. */
700 if (rtm->rtm_protocol == RTPROT_ZEBRA)
701 flags |= ZEBRA_FLAG_SELFROUTE;
paul7021c422003-07-15 12:52:22 +0000702
paul718e3742002-12-13 20:15:29 +0000703 index = 0;
hasso34195bf2004-04-06 12:07:06 +0000704 metric = 0;
paul718e3742002-12-13 20:15:29 +0000705 dest = NULL;
706 gate = NULL;
Paul Jakma7514fb72007-05-02 16:05:35 +0000707 src = NULL;
paul718e3742002-12-13 20:15:29 +0000708
709 if (tb[RTA_OIF])
710 index = *(int *) RTA_DATA (tb[RTA_OIF]);
711
712 if (tb[RTA_DST])
713 dest = RTA_DATA (tb[RTA_DST]);
714 else
715 dest = anyaddr;
716
Paul Jakma7514fb72007-05-02 16:05:35 +0000717 if (tb[RTA_PREFSRC])
718 src = RTA_DATA (tb[RTA_PREFSRC]);
719
paul718e3742002-12-13 20:15:29 +0000720 if (tb[RTA_GATEWAY])
721 gate = RTA_DATA (tb[RTA_GATEWAY]);
722
hasso34195bf2004-04-06 12:07:06 +0000723 if (tb[RTA_PRIORITY])
724 metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
725
paul718e3742002-12-13 20:15:29 +0000726 if (rtm->rtm_family == AF_INET)
727 {
728 struct prefix_ipv4 p;
729 p.family = AF_INET;
730 memcpy (&p.prefix, dest, 4);
731 p.prefixlen = rtm->rtm_dst_len;
732
Josh Bailey26e2ae32012-03-22 01:09:21 -0700733 if (!tb[RTA_MULTIPATH])
734 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index,
Avneesh Sachdev14d2bba2012-04-11 23:51:08 -0700735 table, metric, 0, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700736 else
737 {
738 /* This is a multipath route */
739
740 struct rib *rib;
741 struct rtnexthop *rtnh =
742 (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
743
744 len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
745
746 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
747 rib->type = ZEBRA_ROUTE_KERNEL;
748 rib->distance = 0;
749 rib->flags = flags;
750 rib->metric = metric;
751 rib->table = table;
752 rib->nexthop_num = 0;
753 rib->uptime = time (NULL);
754
755 for (;;)
756 {
757 if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
758 break;
759
760 rib->nexthop_num++;
761 index = rtnh->rtnh_ifindex;
762 gate = 0;
763 if (rtnh->rtnh_len > sizeof (*rtnh))
764 {
765 memset (tb, 0, sizeof (tb));
766 netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
767 rtnh->rtnh_len - sizeof (*rtnh));
768 if (tb[RTA_GATEWAY])
769 gate = RTA_DATA (tb[RTA_GATEWAY]);
770 }
771
772 if (gate)
773 {
774 if (index)
775 nexthop_ipv4_ifindex_add (rib, gate, src, index);
776 else
777 nexthop_ipv4_add (rib, gate, src);
778 }
779 else
780 nexthop_ifindex_add (rib, index);
781
782 len -= NLMSG_ALIGN(rtnh->rtnh_len);
783 rtnh = RTNH_NEXT(rtnh);
784 }
785
786 if (rib->nexthop_num == 0)
787 XFREE (MTYPE_RIB, rib);
788 else
Avneesh Sachdev14d2bba2012-04-11 23:51:08 -0700789 rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700790 }
paul718e3742002-12-13 20:15:29 +0000791 }
792#ifdef HAVE_IPV6
793 if (rtm->rtm_family == AF_INET6)
794 {
795 struct prefix_ipv6 p;
796 p.family = AF_INET6;
797 memcpy (&p.prefix, dest, 16);
798 p.prefixlen = rtm->rtm_dst_len;
799
hassobe61c4e2005-08-27 06:05:47 +0000800 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table,
G.Balajif768f362011-11-26 22:10:39 +0400801 metric, 0, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000802 }
803#endif /* HAVE_IPV6 */
804
805 return 0;
806}
807
Stephen Hemminger1423c802008-08-14 17:59:25 +0100808static const struct message rtproto_str[] = {
paul718e3742002-12-13 20:15:29 +0000809 {RTPROT_REDIRECT, "redirect"},
810 {RTPROT_KERNEL, "kernel"},
811 {RTPROT_BOOT, "boot"},
812 {RTPROT_STATIC, "static"},
813 {RTPROT_GATED, "GateD"},
814 {RTPROT_RA, "router advertisement"},
815 {RTPROT_MRT, "MRT"},
816 {RTPROT_ZEBRA, "Zebra"},
817#ifdef RTPROT_BIRD
818 {RTPROT_BIRD, "BIRD"},
819#endif /* RTPROT_BIRD */
820 {0, NULL}
821};
822
823/* Routing information change from the kernel. */
Stephen Hemminger6072b242008-08-14 16:52:26 +0100824static int
paul718e3742002-12-13 20:15:29 +0000825netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
826{
827 int len;
828 struct rtmsg *rtm;
paul7021c422003-07-15 12:52:22 +0000829 struct rtattr *tb[RTA_MAX + 1];
830
831 char anyaddr[16] = { 0 };
paul718e3742002-12-13 20:15:29 +0000832
833 int index;
834 int table;
Josh Bailey26e2ae32012-03-22 01:09:21 -0700835 int metric;
Dmitry Popov83d16142011-09-11 13:48:25 +0400836
paul718e3742002-12-13 20:15:29 +0000837 void *dest;
838 void *gate;
Paul Jakma7514fb72007-05-02 16:05:35 +0000839 void *src;
paul718e3742002-12-13 20:15:29 +0000840
841 rtm = NLMSG_DATA (h);
842
paul7021c422003-07-15 12:52:22 +0000843 if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
paul718e3742002-12-13 20:15:29 +0000844 {
845 /* If this is not route add/delete message print warning. */
846 zlog_warn ("Kernel message: %d\n", h->nlmsg_type);
847 return 0;
848 }
849
850 /* Connected route. */
851 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000852 zlog_debug ("%s %s %s proto %s",
paul7021c422003-07-15 12:52:22 +0000853 h->nlmsg_type ==
854 RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
855 rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",
856 rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast",
857 lookup (rtproto_str, rtm->rtm_protocol));
paul718e3742002-12-13 20:15:29 +0000858
859 if (rtm->rtm_type != RTN_UNICAST)
860 {
861 return 0;
862 }
863
864 table = rtm->rtm_table;
paulb21b19c2003-06-15 01:28:29 +0000865 if (table != RT_TABLE_MAIN && table != zebrad.rtm_table_default)
paul718e3742002-12-13 20:15:29 +0000866 {
867 return 0;
868 }
869
paul7021c422003-07-15 12:52:22 +0000870 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
paul718e3742002-12-13 20:15:29 +0000871 if (len < 0)
872 return -1;
873
874 memset (tb, 0, sizeof tb);
875 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
876
877 if (rtm->rtm_flags & RTM_F_CLONED)
878 return 0;
879 if (rtm->rtm_protocol == RTPROT_REDIRECT)
880 return 0;
881 if (rtm->rtm_protocol == RTPROT_KERNEL)
882 return 0;
883
884 if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)
885 return 0;
886
887 if (rtm->rtm_src_len != 0)
888 {
889 zlog_warn ("netlink_route_change(): no src len");
890 return 0;
891 }
paul7021c422003-07-15 12:52:22 +0000892
paul718e3742002-12-13 20:15:29 +0000893 index = 0;
Josh Bailey26e2ae32012-03-22 01:09:21 -0700894 metric = 0;
paul718e3742002-12-13 20:15:29 +0000895 dest = NULL;
896 gate = NULL;
Paul Jakma7514fb72007-05-02 16:05:35 +0000897 src = NULL;
paul718e3742002-12-13 20:15:29 +0000898
899 if (tb[RTA_OIF])
900 index = *(int *) RTA_DATA (tb[RTA_OIF]);
901
902 if (tb[RTA_DST])
903 dest = RTA_DATA (tb[RTA_DST]);
904 else
905 dest = anyaddr;
906
907 if (tb[RTA_GATEWAY])
908 gate = RTA_DATA (tb[RTA_GATEWAY]);
909
Paul Jakma7514fb72007-05-02 16:05:35 +0000910 if (tb[RTA_PREFSRC])
911 src = RTA_DATA (tb[RTA_PREFSRC]);
912
Dmitry Popov83d16142011-09-11 13:48:25 +0400913 if (h->nlmsg_type == RTM_NEWROUTE && tb[RTA_PRIORITY])
Josh Bailey26e2ae32012-03-22 01:09:21 -0700914 metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
915
paul718e3742002-12-13 20:15:29 +0000916 if (rtm->rtm_family == AF_INET)
917 {
918 struct prefix_ipv4 p;
919 p.family = AF_INET;
920 memcpy (&p.prefix, dest, 4);
921 p.prefixlen = rtm->rtm_dst_len;
922
923 if (IS_ZEBRA_DEBUG_KERNEL)
paul7021c422003-07-15 12:52:22 +0000924 {
925 if (h->nlmsg_type == RTM_NEWROUTE)
ajsb6178002004-12-07 21:12:56 +0000926 zlog_debug ("RTM_NEWROUTE %s/%d",
paul7021c422003-07-15 12:52:22 +0000927 inet_ntoa (p.prefix), p.prefixlen);
928 else
ajsb6178002004-12-07 21:12:56 +0000929 zlog_debug ("RTM_DELROUTE %s/%d",
paul7021c422003-07-15 12:52:22 +0000930 inet_ntoa (p.prefix), p.prefixlen);
931 }
paul718e3742002-12-13 20:15:29 +0000932
933 if (h->nlmsg_type == RTM_NEWROUTE)
Josh Bailey26e2ae32012-03-22 01:09:21 -0700934 {
935 if (!tb[RTA_MULTIPATH])
936 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table,
Avneesh Sachdev14d2bba2012-04-11 23:51:08 -0700937 metric, 0, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700938 else
939 {
940 /* This is a multipath route */
941
942 struct rib *rib;
943 struct rtnexthop *rtnh =
944 (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
945
946 len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
947
948 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
949 rib->type = ZEBRA_ROUTE_KERNEL;
950 rib->distance = 0;
951 rib->flags = 0;
952 rib->metric = metric;
953 rib->table = table;
954 rib->nexthop_num = 0;
955 rib->uptime = time (NULL);
956
957 for (;;)
958 {
959 if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
960 break;
961
962 rib->nexthop_num++;
963 index = rtnh->rtnh_ifindex;
964 gate = 0;
965 if (rtnh->rtnh_len > sizeof (*rtnh))
966 {
967 memset (tb, 0, sizeof (tb));
968 netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
969 rtnh->rtnh_len - sizeof (*rtnh));
970 if (tb[RTA_GATEWAY])
971 gate = RTA_DATA (tb[RTA_GATEWAY]);
972 }
973
974 if (gate)
975 {
976 if (index)
977 nexthop_ipv4_ifindex_add (rib, gate, src, index);
978 else
979 nexthop_ipv4_add (rib, gate, src);
980 }
981 else
982 nexthop_ifindex_add (rib, index);
983
984 len -= NLMSG_ALIGN(rtnh->rtnh_len);
985 rtnh = RTNH_NEXT(rtnh);
986 }
987
988 if (rib->nexthop_num == 0)
989 XFREE (MTYPE_RIB, rib);
990 else
Avneesh Sachdev14d2bba2012-04-11 23:51:08 -0700991 rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST);
Josh Bailey26e2ae32012-03-22 01:09:21 -0700992 }
993 }
paul718e3742002-12-13 20:15:29 +0000994 else
G.Balajicddf3912011-11-26 21:59:32 +0400995 rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000996 }
997
998#ifdef HAVE_IPV6
999 if (rtm->rtm_family == AF_INET6)
1000 {
1001 struct prefix_ipv6 p;
1002 char buf[BUFSIZ];
1003
1004 p.family = AF_INET6;
1005 memcpy (&p.prefix, dest, 16);
1006 p.prefixlen = rtm->rtm_dst_len;
1007
1008 if (IS_ZEBRA_DEBUG_KERNEL)
paul7021c422003-07-15 12:52:22 +00001009 {
1010 if (h->nlmsg_type == RTM_NEWROUTE)
ajsb6178002004-12-07 21:12:56 +00001011 zlog_debug ("RTM_NEWROUTE %s/%d",
paul7021c422003-07-15 12:52:22 +00001012 inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
1013 p.prefixlen);
1014 else
ajsb6178002004-12-07 21:12:56 +00001015 zlog_debug ("RTM_DELROUTE %s/%d",
paul7021c422003-07-15 12:52:22 +00001016 inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
1017 p.prefixlen);
1018 }
paul718e3742002-12-13 20:15:29 +00001019
1020 if (h->nlmsg_type == RTM_NEWROUTE)
G.Balajif768f362011-11-26 22:10:39 +04001021 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, metric, 0, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001022 else
G.Balajif768f362011-11-26 22:10:39 +04001023 rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001024 }
1025#endif /* HAVE_IPV6 */
1026
1027 return 0;
1028}
1029
Stephen Hemminger6072b242008-08-14 16:52:26 +01001030static int
paul718e3742002-12-13 20:15:29 +00001031netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
1032{
1033 int len;
1034 struct ifinfomsg *ifi;
paul7021c422003-07-15 12:52:22 +00001035 struct rtattr *tb[IFLA_MAX + 1];
paul718e3742002-12-13 20:15:29 +00001036 struct interface *ifp;
1037 char *name;
1038
1039 ifi = NLMSG_DATA (h);
1040
paul7021c422003-07-15 12:52:22 +00001041 if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
paul718e3742002-12-13 20:15:29 +00001042 {
1043 /* If this is not link add/delete message so print warning. */
1044 zlog_warn ("netlink_link_change: wrong kernel message %d\n",
paul7021c422003-07-15 12:52:22 +00001045 h->nlmsg_type);
paul718e3742002-12-13 20:15:29 +00001046 return 0;
1047 }
1048
1049 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
1050 if (len < 0)
1051 return -1;
1052
1053 /* Looking up interface name. */
1054 memset (tb, 0, sizeof tb);
1055 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
paulc15cb242005-01-24 09:05:27 +00001056
paul1e193152005-02-14 23:53:05 +00001057#ifdef IFLA_WIRELESS
paulc15cb242005-01-24 09:05:27 +00001058 /* check for wireless messages to ignore */
1059 if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
1060 {
1061 if (IS_ZEBRA_DEBUG_KERNEL)
1062 zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__);
1063 return 0;
1064 }
paul1e193152005-02-14 23:53:05 +00001065#endif /* IFLA_WIRELESS */
paulc15cb242005-01-24 09:05:27 +00001066
paul718e3742002-12-13 20:15:29 +00001067 if (tb[IFLA_IFNAME] == NULL)
1068 return -1;
paul7021c422003-07-15 12:52:22 +00001069 name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
paul718e3742002-12-13 20:15:29 +00001070
1071 /* Add interface. */
1072 if (h->nlmsg_type == RTM_NEWLINK)
1073 {
1074 ifp = if_lookup_by_name (name);
1075
paul7021c422003-07-15 12:52:22 +00001076 if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1077 {
1078 if (ifp == NULL)
1079 ifp = if_get_by_name (name);
paul718e3742002-12-13 20:15:29 +00001080
ajsd2fc8892005-04-02 18:38:43 +00001081 set_ifindex(ifp, ifi->ifi_index);
paul7021c422003-07-15 12:52:22 +00001082 ifp->flags = ifi->ifi_flags & 0x0000fffff;
paul44145db2004-05-09 11:00:23 +00001083 ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
paul7021c422003-07-15 12:52:22 +00001084 ifp->metric = 1;
paul718e3742002-12-13 20:15:29 +00001085
Josh Bailey26e2ae32012-03-22 01:09:21 -07001086 netlink_interface_update_hw_addr (tb, ifp);
1087
paul7021c422003-07-15 12:52:22 +00001088 /* If new link is added. */
1089 if_add_update (ifp);
1090 }
paul718e3742002-12-13 20:15:29 +00001091 else
paul7021c422003-07-15 12:52:22 +00001092 {
1093 /* Interface status change. */
ajsd2fc8892005-04-02 18:38:43 +00001094 set_ifindex(ifp, ifi->ifi_index);
paul44145db2004-05-09 11:00:23 +00001095 ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
paul7021c422003-07-15 12:52:22 +00001096 ifp->metric = 1;
paul718e3742002-12-13 20:15:29 +00001097
Josh Bailey26e2ae32012-03-22 01:09:21 -07001098 netlink_interface_update_hw_addr (tb, ifp);
1099
paul7021c422003-07-15 12:52:22 +00001100 if (if_is_operative (ifp))
1101 {
1102 ifp->flags = ifi->ifi_flags & 0x0000fffff;
1103 if (!if_is_operative (ifp))
1104 if_down (ifp);
ajsa608bbf2005-03-29 17:03:49 +00001105 else
1106 /* Must notify client daemons of new interface status. */
1107 zebra_interface_up_update (ifp);
paul7021c422003-07-15 12:52:22 +00001108 }
1109 else
1110 {
1111 ifp->flags = ifi->ifi_flags & 0x0000fffff;
1112 if (if_is_operative (ifp))
1113 if_up (ifp);
1114 }
1115 }
paul718e3742002-12-13 20:15:29 +00001116 }
1117 else
1118 {
1119 /* RTM_DELLINK. */
1120 ifp = if_lookup_by_name (name);
1121
1122 if (ifp == NULL)
paul7021c422003-07-15 12:52:22 +00001123 {
1124 zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find",
paul718e3742002-12-13 20:15:29 +00001125 name);
paul7021c422003-07-15 12:52:22 +00001126 return 0;
1127 }
1128
paul718e3742002-12-13 20:15:29 +00001129 if_delete_update (ifp);
1130 }
1131
1132 return 0;
1133}
1134
Stephen Hemminger6072b242008-08-14 16:52:26 +01001135static int
paul718e3742002-12-13 20:15:29 +00001136netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h)
1137{
Stephen Hemminger3d265b42008-08-16 17:30:39 +01001138 /* JF: Ignore messages that aren't from the kernel */
1139 if ( snl->nl_pid != 0 )
1140 {
1141 zlog ( NULL, LOG_ERR, "Ignoring message from pid %u", snl->nl_pid );
1142 return 0;
1143 }
1144
paul718e3742002-12-13 20:15:29 +00001145 switch (h->nlmsg_type)
1146 {
1147 case RTM_NEWROUTE:
1148 return netlink_route_change (snl, h);
1149 break;
1150 case RTM_DELROUTE:
1151 return netlink_route_change (snl, h);
1152 break;
1153 case RTM_NEWLINK:
1154 return netlink_link_change (snl, h);
1155 break;
1156 case RTM_DELLINK:
1157 return netlink_link_change (snl, h);
1158 break;
1159 case RTM_NEWADDR:
1160 return netlink_interface_addr (snl, h);
1161 break;
1162 case RTM_DELADDR:
1163 return netlink_interface_addr (snl, h);
1164 break;
1165 default:
1166 zlog_warn ("Unknown netlink nlmsg_type %d\n", h->nlmsg_type);
1167 break;
1168 }
1169 return 0;
1170}
1171
1172/* Interface lookup by netlink socket. */
1173int
paul6621ca82005-11-23 13:02:08 +00001174interface_lookup_netlink (void)
paul718e3742002-12-13 20:15:29 +00001175{
1176 int ret;
paul7021c422003-07-15 12:52:22 +00001177
paul718e3742002-12-13 20:15:29 +00001178 /* Get interface information. */
1179 ret = netlink_request (AF_PACKET, RTM_GETLINK, &netlink_cmd);
1180 if (ret < 0)
1181 return ret;
1182 ret = netlink_parse_info (netlink_interface, &netlink_cmd);
1183 if (ret < 0)
1184 return ret;
1185
1186 /* Get IPv4 address of the interfaces. */
1187 ret = netlink_request (AF_INET, RTM_GETADDR, &netlink_cmd);
1188 if (ret < 0)
1189 return ret;
1190 ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
1191 if (ret < 0)
1192 return ret;
1193
1194#ifdef HAVE_IPV6
1195 /* Get IPv6 address of the interfaces. */
1196 ret = netlink_request (AF_INET6, RTM_GETADDR, &netlink_cmd);
1197 if (ret < 0)
1198 return ret;
1199 ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
1200 if (ret < 0)
1201 return ret;
1202#endif /* HAVE_IPV6 */
1203
1204 return 0;
1205}
1206
1207/* Routing table read function using netlink interface. Only called
1208 bootstrap time. */
1209int
paul6621ca82005-11-23 13:02:08 +00001210netlink_route_read (void)
paul718e3742002-12-13 20:15:29 +00001211{
1212 int ret;
paul7021c422003-07-15 12:52:22 +00001213
paul718e3742002-12-13 20:15:29 +00001214 /* Get IPv4 routing table. */
1215 ret = netlink_request (AF_INET, RTM_GETROUTE, &netlink_cmd);
1216 if (ret < 0)
1217 return ret;
1218 ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
1219 if (ret < 0)
1220 return ret;
1221
1222#ifdef HAVE_IPV6
1223 /* Get IPv6 routing table. */
1224 ret = netlink_request (AF_INET6, RTM_GETROUTE, &netlink_cmd);
1225 if (ret < 0)
1226 return ret;
1227 ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
1228 if (ret < 0)
1229 return ret;
1230#endif /* HAVE_IPV6 */
1231
1232 return 0;
1233}
1234
1235/* Utility function comes from iproute2.
1236 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001237int
paul718e3742002-12-13 20:15:29 +00001238addattr_l (struct nlmsghdr *n, int maxlen, int type, void *data, int alen)
1239{
1240 int len;
1241 struct rtattr *rta;
1242
paul7021c422003-07-15 12:52:22 +00001243 len = RTA_LENGTH (alen);
paul718e3742002-12-13 20:15:29 +00001244
paul7021c422003-07-15 12:52:22 +00001245 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
paul718e3742002-12-13 20:15:29 +00001246 return -1;
1247
paul7021c422003-07-15 12:52:22 +00001248 rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
paul718e3742002-12-13 20:15:29 +00001249 rta->rta_type = type;
1250 rta->rta_len = len;
paul7021c422003-07-15 12:52:22 +00001251 memcpy (RTA_DATA (rta), data, alen);
paul718e3742002-12-13 20:15:29 +00001252 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1253
1254 return 0;
1255}
1256
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001257int
paul718e3742002-12-13 20:15:29 +00001258rta_addattr_l (struct rtattr *rta, int maxlen, int type, void *data, int alen)
1259{
1260 int len;
1261 struct rtattr *subrta;
1262
paul7021c422003-07-15 12:52:22 +00001263 len = RTA_LENGTH (alen);
paul718e3742002-12-13 20:15:29 +00001264
paul7021c422003-07-15 12:52:22 +00001265 if (RTA_ALIGN (rta->rta_len) + len > maxlen)
paul718e3742002-12-13 20:15:29 +00001266 return -1;
1267
paul7021c422003-07-15 12:52:22 +00001268 subrta = (struct rtattr *) (((char *) rta) + RTA_ALIGN (rta->rta_len));
paul718e3742002-12-13 20:15:29 +00001269 subrta->rta_type = type;
1270 subrta->rta_len = len;
paul7021c422003-07-15 12:52:22 +00001271 memcpy (RTA_DATA (subrta), data, alen);
paul718e3742002-12-13 20:15:29 +00001272 rta->rta_len = NLMSG_ALIGN (rta->rta_len) + len;
1273
1274 return 0;
1275}
1276
1277/* Utility function comes from iproute2.
1278 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001279int
paul718e3742002-12-13 20:15:29 +00001280addattr32 (struct nlmsghdr *n, int maxlen, int type, int data)
1281{
1282 int len;
1283 struct rtattr *rta;
paul7021c422003-07-15 12:52:22 +00001284
1285 len = RTA_LENGTH (4);
1286
paul718e3742002-12-13 20:15:29 +00001287 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
1288 return -1;
1289
paul7021c422003-07-15 12:52:22 +00001290 rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
paul718e3742002-12-13 20:15:29 +00001291 rta->rta_type = type;
1292 rta->rta_len = len;
paul7021c422003-07-15 12:52:22 +00001293 memcpy (RTA_DATA (rta), &data, 4);
paul718e3742002-12-13 20:15:29 +00001294 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1295
1296 return 0;
1297}
1298
1299static int
1300netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h)
1301{
hassob7ed1ec2005-03-31 20:13:49 +00001302 zlog_warn ("netlink_talk: ignoring message type 0x%04x", h->nlmsg_type);
paul718e3742002-12-13 20:15:29 +00001303 return 0;
1304}
1305
1306/* sendmsg() to netlink socket then recvmsg(). */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001307static int
paul718e3742002-12-13 20:15:29 +00001308netlink_talk (struct nlmsghdr *n, struct nlsock *nl)
1309{
1310 int status;
1311 struct sockaddr_nl snl;
paul7021c422003-07-15 12:52:22 +00001312 struct iovec iov = { (void *) n, n->nlmsg_len };
1313 struct msghdr msg = { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 };
ajs4be019d2005-01-29 16:12:41 +00001314 int save_errno;
paul7021c422003-07-15 12:52:22 +00001315
paul718e3742002-12-13 20:15:29 +00001316 memset (&snl, 0, sizeof snl);
1317 snl.nl_family = AF_NETLINK;
paul7021c422003-07-15 12:52:22 +00001318
hassob7ed1ec2005-03-31 20:13:49 +00001319 n->nlmsg_seq = ++nl->seq;
paul718e3742002-12-13 20:15:29 +00001320
1321 /* Request an acknowledgement by setting NLM_F_ACK */
1322 n->nlmsg_flags |= NLM_F_ACK;
paul7021c422003-07-15 12:52:22 +00001323
1324 if (IS_ZEBRA_DEBUG_KERNEL)
hassob7ed1ec2005-03-31 20:13:49 +00001325 zlog_debug ("netlink_talk: %s type %s(%u), seq=%u", nl->name,
paul7021c422003-07-15 12:52:22 +00001326 lookup (nlmsg_str, n->nlmsg_type), n->nlmsg_type,
1327 n->nlmsg_seq);
paul718e3742002-12-13 20:15:29 +00001328
1329 /* Send message to netlink interface. */
paul7021c422003-07-15 12:52:22 +00001330 if (zserv_privs.change (ZPRIVS_RAISE))
1331 zlog (NULL, LOG_ERR, "Can't raise privileges");
paul718e3742002-12-13 20:15:29 +00001332 status = sendmsg (nl->sock, &msg, 0);
ajs4be019d2005-01-29 16:12:41 +00001333 save_errno = errno;
paul7021c422003-07-15 12:52:22 +00001334 if (zserv_privs.change (ZPRIVS_LOWER))
1335 zlog (NULL, LOG_ERR, "Can't lower privileges");
1336
paul718e3742002-12-13 20:15:29 +00001337 if (status < 0)
1338 {
1339 zlog (NULL, LOG_ERR, "netlink_talk sendmsg() error: %s",
ajs4be019d2005-01-29 16:12:41 +00001340 safe_strerror (save_errno));
paul718e3742002-12-13 20:15:29 +00001341 return -1;
1342 }
paul7021c422003-07-15 12:52:22 +00001343
paul718e3742002-12-13 20:15:29 +00001344
1345 /*
1346 * Get reply from netlink socket.
1347 * The reply should either be an acknowlegement or an error.
1348 */
Stephen Hemminger4cde9312008-08-16 17:51:27 +01001349 return netlink_parse_info (netlink_talk_filter, nl);
paul718e3742002-12-13 20:15:29 +00001350}
1351
1352/* Routing table change via netlink interface. */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001353static int
paul718e3742002-12-13 20:15:29 +00001354netlink_route (int cmd, int family, void *dest, int length, void *gate,
paul7021c422003-07-15 12:52:22 +00001355 int index, int zebra_flags, int table)
paul718e3742002-12-13 20:15:29 +00001356{
1357 int ret;
1358 int bytelen;
1359 struct sockaddr_nl snl;
1360 int discard;
1361
paul7021c422003-07-15 12:52:22 +00001362 struct
paul718e3742002-12-13 20:15:29 +00001363 {
1364 struct nlmsghdr n;
1365 struct rtmsg r;
JR Rivers3cadc0c2012-04-01 12:16:31 -07001366 char buf[NL_PKT_BUF_SIZE];
paul718e3742002-12-13 20:15:29 +00001367 } req;
1368
Jorge Boncompte [DTI2]a4c06de2012-04-20 14:28:40 +02001369 memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
paul718e3742002-12-13 20:15:29 +00001370
1371 bytelen = (family == AF_INET ? 4 : 16);
1372
1373 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1374 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1375 req.n.nlmsg_type = cmd;
1376 req.r.rtm_family = family;
1377 req.r.rtm_table = table;
1378 req.r.rtm_dst_len = length;
Timo Teräs40da2212008-08-13 17:37:14 +01001379 req.r.rtm_protocol = RTPROT_ZEBRA;
1380 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
paul718e3742002-12-13 20:15:29 +00001381
hasso81dfcaa2003-05-25 19:21:25 +00001382 if ((zebra_flags & ZEBRA_FLAG_BLACKHOLE)
1383 || (zebra_flags & ZEBRA_FLAG_REJECT))
paul718e3742002-12-13 20:15:29 +00001384 discard = 1;
1385 else
1386 discard = 0;
1387
paul7021c422003-07-15 12:52:22 +00001388 if (cmd == RTM_NEWROUTE)
paul718e3742002-12-13 20:15:29 +00001389 {
paul7021c422003-07-15 12:52:22 +00001390 if (discard)
paul595db7f2003-05-25 21:35:06 +00001391 {
1392 if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
1393 req.r.rtm_type = RTN_BLACKHOLE;
1394 else if (zebra_flags & ZEBRA_FLAG_REJECT)
1395 req.r.rtm_type = RTN_UNREACHABLE;
paul7021c422003-07-15 12:52:22 +00001396 else
1397 assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
1398 }
paul595db7f2003-05-25 21:35:06 +00001399 else
paul7021c422003-07-15 12:52:22 +00001400 req.r.rtm_type = RTN_UNICAST;
paul718e3742002-12-13 20:15:29 +00001401 }
1402
1403 if (dest)
1404 addattr_l (&req.n, sizeof req, RTA_DST, dest, bytelen);
1405
paul7021c422003-07-15 12:52:22 +00001406 if (!discard)
paul718e3742002-12-13 20:15:29 +00001407 {
1408 if (gate)
paul7021c422003-07-15 12:52:22 +00001409 addattr_l (&req.n, sizeof req, RTA_GATEWAY, gate, bytelen);
paul718e3742002-12-13 20:15:29 +00001410 if (index > 0)
paul7021c422003-07-15 12:52:22 +00001411 addattr32 (&req.n, sizeof req, RTA_OIF, index);
paul718e3742002-12-13 20:15:29 +00001412 }
1413
1414 /* Destination netlink address. */
1415 memset (&snl, 0, sizeof snl);
1416 snl.nl_family = AF_NETLINK;
1417
1418 /* Talk to netlink socket. */
hassob7ed1ec2005-03-31 20:13:49 +00001419 ret = netlink_talk (&req.n, &netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001420 if (ret < 0)
1421 return -1;
1422
1423 return 0;
1424}
1425
1426/* Routing table change via netlink interface. */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001427static int
paul718e3742002-12-13 20:15:29 +00001428netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
paul7021c422003-07-15 12:52:22 +00001429 int family)
paul718e3742002-12-13 20:15:29 +00001430{
1431 int bytelen;
1432 struct sockaddr_nl snl;
1433 struct nexthop *nexthop = NULL;
1434 int nexthop_num = 0;
paul718e3742002-12-13 20:15:29 +00001435 int discard;
1436
paul7021c422003-07-15 12:52:22 +00001437 struct
paul718e3742002-12-13 20:15:29 +00001438 {
1439 struct nlmsghdr n;
1440 struct rtmsg r;
JR Rivers3cadc0c2012-04-01 12:16:31 -07001441 char buf[NL_PKT_BUF_SIZE];
paul718e3742002-12-13 20:15:29 +00001442 } req;
1443
Jorge Boncompte [DTI2]a4c06de2012-04-20 14:28:40 +02001444 memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
paul718e3742002-12-13 20:15:29 +00001445
1446 bytelen = (family == AF_INET ? 4 : 16);
1447
1448 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1449 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1450 req.n.nlmsg_type = cmd;
1451 req.r.rtm_family = family;
1452 req.r.rtm_table = rib->table;
1453 req.r.rtm_dst_len = p->prefixlen;
Timo Teräs40da2212008-08-13 17:37:14 +01001454 req.r.rtm_protocol = RTPROT_ZEBRA;
1455 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
paul718e3742002-12-13 20:15:29 +00001456
paul7021c422003-07-15 12:52:22 +00001457 if ((rib->flags & ZEBRA_FLAG_BLACKHOLE) || (rib->flags & ZEBRA_FLAG_REJECT))
paul718e3742002-12-13 20:15:29 +00001458 discard = 1;
1459 else
1460 discard = 0;
1461
paul7021c422003-07-15 12:52:22 +00001462 if (cmd == RTM_NEWROUTE)
paul718e3742002-12-13 20:15:29 +00001463 {
paul7021c422003-07-15 12:52:22 +00001464 if (discard)
paul595db7f2003-05-25 21:35:06 +00001465 {
1466 if (rib->flags & ZEBRA_FLAG_BLACKHOLE)
1467 req.r.rtm_type = RTN_BLACKHOLE;
1468 else if (rib->flags & ZEBRA_FLAG_REJECT)
1469 req.r.rtm_type = RTN_UNREACHABLE;
paul7021c422003-07-15 12:52:22 +00001470 else
1471 assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
1472 }
paul595db7f2003-05-25 21:35:06 +00001473 else
paul7021c422003-07-15 12:52:22 +00001474 req.r.rtm_type = RTN_UNICAST;
paul718e3742002-12-13 20:15:29 +00001475 }
1476
1477 addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
1478
1479 /* Metric. */
1480 addattr32 (&req.n, sizeof req, RTA_PRIORITY, rib->metric);
1481
1482 if (discard)
1483 {
1484 if (cmd == RTM_NEWROUTE)
paul7021c422003-07-15 12:52:22 +00001485 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1486 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
paul718e3742002-12-13 20:15:29 +00001487 goto skip;
1488 }
1489
1490 /* Multipath case. */
1491 if (rib->nexthop_active_num == 1 || MULTIPATH_NUM == 1)
1492 {
1493 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
paul7021c422003-07-15 12:52:22 +00001494 {
paul5ec90d22003-06-19 01:41:37 +00001495
paul7021c422003-07-15 12:52:22 +00001496 if ((cmd == RTM_NEWROUTE
1497 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1498 || (cmd == RTM_DELROUTE
1499 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1500 {
paul5ec90d22003-06-19 01:41:37 +00001501
paul7021c422003-07-15 12:52:22 +00001502 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1503 {
1504 if (IS_ZEBRA_DEBUG_KERNEL)
1505 {
ajsb6178002004-12-07 21:12:56 +00001506 zlog_debug
paul7021c422003-07-15 12:52:22 +00001507 ("netlink_route_multipath() (recursive, 1 hop): "
hasso206d8052005-04-09 16:38:51 +00001508 "%s %s/%d, type %s", lookup (nlmsg_str, cmd),
hasso1ada8192005-06-12 11:28:18 +00001509#ifdef HAVE_IPV6
hasso206d8052005-04-09 16:38:51 +00001510 (family == AF_INET) ? inet_ntoa (p->u.prefix4) :
hasso1ada8192005-06-12 11:28:18 +00001511 inet6_ntoa (p->u.prefix6),
1512#else
1513 inet_ntoa (p->u.prefix4),
1514#endif /* HAVE_IPV6 */
1515
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001516 p->prefixlen, nexthop_type_to_str (nexthop->rtype));
paul7021c422003-07-15 12:52:22 +00001517 }
paul5ec90d22003-06-19 01:41:37 +00001518
paul7021c422003-07-15 12:52:22 +00001519 if (nexthop->rtype == NEXTHOP_TYPE_IPV4
1520 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
hasso206d8052005-04-09 16:38:51 +00001521 {
1522 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1523 &nexthop->rgate.ipv4, bytelen);
Paul Jakma7514fb72007-05-02 16:05:35 +00001524 if (nexthop->src.ipv4.s_addr)
1525 addattr_l(&req.n, sizeof req, RTA_PREFSRC,
1526 &nexthop->src.ipv4, bytelen);
hasso206d8052005-04-09 16:38:51 +00001527 if (IS_ZEBRA_DEBUG_KERNEL)
1528 zlog_debug("netlink_route_multipath() (recursive, "
1529 "1 hop): nexthop via %s if %u",
1530 inet_ntoa (nexthop->rgate.ipv4),
1531 nexthop->rifindex);
1532 }
paul718e3742002-12-13 20:15:29 +00001533#ifdef HAVE_IPV6
paul7021c422003-07-15 12:52:22 +00001534 if (nexthop->rtype == NEXTHOP_TYPE_IPV6
1535 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1536 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
hasso206d8052005-04-09 16:38:51 +00001537 {
1538 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1539 &nexthop->rgate.ipv6, bytelen);
1540
1541 if (IS_ZEBRA_DEBUG_KERNEL)
1542 zlog_debug("netlink_route_multipath() (recursive, "
1543 "1 hop): nexthop via %s if %u",
1544 inet6_ntoa (nexthop->rgate.ipv6),
1545 nexthop->rifindex);
1546 }
paul718e3742002-12-13 20:15:29 +00001547#endif /* HAVE_IPV6 */
paul7021c422003-07-15 12:52:22 +00001548 if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
1549 || nexthop->rtype == NEXTHOP_TYPE_IFNAME
1550 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
1551 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1552 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
hasso206d8052005-04-09 16:38:51 +00001553 {
1554 addattr32 (&req.n, sizeof req, RTA_OIF,
1555 nexthop->rifindex);
Paul Jakma7514fb72007-05-02 16:05:35 +00001556 if ((nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
1557 || nexthop->rtype == NEXTHOP_TYPE_IFINDEX)
1558 && nexthop->src.ipv4.s_addr)
1559 addattr_l (&req.n, sizeof req, RTA_PREFSRC,
1560 &nexthop->src.ipv4, bytelen);
hasso206d8052005-04-09 16:38:51 +00001561
1562 if (IS_ZEBRA_DEBUG_KERNEL)
1563 zlog_debug("netlink_route_multipath() (recursive, "
1564 "1 hop): nexthop via if %u",
1565 nexthop->rifindex);
1566 }
paul7021c422003-07-15 12:52:22 +00001567 }
1568 else
1569 {
1570 if (IS_ZEBRA_DEBUG_KERNEL)
1571 {
ajsb6178002004-12-07 21:12:56 +00001572 zlog_debug
hasso206d8052005-04-09 16:38:51 +00001573 ("netlink_route_multipath() (single hop): "
1574 "%s %s/%d, type %s", lookup (nlmsg_str, cmd),
hasso1ada8192005-06-12 11:28:18 +00001575#ifdef HAVE_IPV6
hasso206d8052005-04-09 16:38:51 +00001576 (family == AF_INET) ? inet_ntoa (p->u.prefix4) :
hasso1ada8192005-06-12 11:28:18 +00001577 inet6_ntoa (p->u.prefix6),
1578#else
1579 inet_ntoa (p->u.prefix4),
1580#endif /* HAVE_IPV6 */
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001581 p->prefixlen, nexthop_type_to_str (nexthop->type));
paul7021c422003-07-15 12:52:22 +00001582 }
paul5ec90d22003-06-19 01:41:37 +00001583
paul7021c422003-07-15 12:52:22 +00001584 if (nexthop->type == NEXTHOP_TYPE_IPV4
1585 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
hasso206d8052005-04-09 16:38:51 +00001586 {
1587 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1588 &nexthop->gate.ipv4, bytelen);
Paul Jakma7514fb72007-05-02 16:05:35 +00001589 if (nexthop->src.ipv4.s_addr)
1590 addattr_l (&req.n, sizeof req, RTA_PREFSRC,
1591 &nexthop->src.ipv4, bytelen);
hasso206d8052005-04-09 16:38:51 +00001592
1593 if (IS_ZEBRA_DEBUG_KERNEL)
1594 zlog_debug("netlink_route_multipath() (single hop): "
1595 "nexthop via %s if %u",
1596 inet_ntoa (nexthop->gate.ipv4),
1597 nexthop->ifindex);
1598 }
paul718e3742002-12-13 20:15:29 +00001599#ifdef HAVE_IPV6
paul7021c422003-07-15 12:52:22 +00001600 if (nexthop->type == NEXTHOP_TYPE_IPV6
1601 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1602 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
hasso206d8052005-04-09 16:38:51 +00001603 {
1604 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1605 &nexthop->gate.ipv6, bytelen);
1606
1607 if (IS_ZEBRA_DEBUG_KERNEL)
1608 zlog_debug("netlink_route_multipath() (single hop): "
1609 "nexthop via %s if %u",
1610 inet6_ntoa (nexthop->gate.ipv6),
1611 nexthop->ifindex);
1612 }
paul718e3742002-12-13 20:15:29 +00001613#endif /* HAVE_IPV6 */
paul7021c422003-07-15 12:52:22 +00001614 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1615 || nexthop->type == NEXTHOP_TYPE_IFNAME
Paul Jakma7514fb72007-05-02 16:05:35 +00001616 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1617 {
1618 addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->ifindex);
1619
1620 if (nexthop->src.ipv4.s_addr)
1621 addattr_l (&req.n, sizeof req, RTA_PREFSRC,
1622 &nexthop->src.ipv4, bytelen);
1623
1624 if (IS_ZEBRA_DEBUG_KERNEL)
1625 zlog_debug("netlink_route_multipath() (single hop): "
1626 "nexthop via if %u", nexthop->ifindex);
1627 }
1628 else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
paul7021c422003-07-15 12:52:22 +00001629 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
hasso206d8052005-04-09 16:38:51 +00001630 {
1631 addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->ifindex);
1632
1633 if (IS_ZEBRA_DEBUG_KERNEL)
1634 zlog_debug("netlink_route_multipath() (single hop): "
1635 "nexthop via if %u", nexthop->ifindex);
1636 }
paul7021c422003-07-15 12:52:22 +00001637 }
paul718e3742002-12-13 20:15:29 +00001638
paul7021c422003-07-15 12:52:22 +00001639 if (cmd == RTM_NEWROUTE)
1640 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
paul718e3742002-12-13 20:15:29 +00001641
paul7021c422003-07-15 12:52:22 +00001642 nexthop_num++;
1643 break;
1644 }
1645 }
paul718e3742002-12-13 20:15:29 +00001646 }
1647 else
1648 {
JR Rivers3cadc0c2012-04-01 12:16:31 -07001649 char buf[NL_PKT_BUF_SIZE];
paul718e3742002-12-13 20:15:29 +00001650 struct rtattr *rta = (void *) buf;
1651 struct rtnexthop *rtnh;
Paul Jakma7514fb72007-05-02 16:05:35 +00001652 union g_addr *src = NULL;
paul718e3742002-12-13 20:15:29 +00001653
1654 rta->rta_type = RTA_MULTIPATH;
paul7021c422003-07-15 12:52:22 +00001655 rta->rta_len = RTA_LENGTH (0);
1656 rtnh = RTA_DATA (rta);
paul718e3742002-12-13 20:15:29 +00001657
1658 nexthop_num = 0;
1659 for (nexthop = rib->nexthop;
paul7021c422003-07-15 12:52:22 +00001660 nexthop && (MULTIPATH_NUM == 0 || nexthop_num < MULTIPATH_NUM);
1661 nexthop = nexthop->next)
1662 {
1663 if ((cmd == RTM_NEWROUTE
1664 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1665 || (cmd == RTM_DELROUTE
1666 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1667 {
1668 nexthop_num++;
paul718e3742002-12-13 20:15:29 +00001669
paul7021c422003-07-15 12:52:22 +00001670 rtnh->rtnh_len = sizeof (*rtnh);
1671 rtnh->rtnh_flags = 0;
1672 rtnh->rtnh_hops = 0;
1673 rta->rta_len += rtnh->rtnh_len;
paul718e3742002-12-13 20:15:29 +00001674
paul7021c422003-07-15 12:52:22 +00001675 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1676 {
1677 if (IS_ZEBRA_DEBUG_KERNEL)
1678 {
ajsb6178002004-12-07 21:12:56 +00001679 zlog_debug ("netlink_route_multipath() "
hasso206d8052005-04-09 16:38:51 +00001680 "(recursive, multihop): %s %s/%d type %s",
hasso1ada8192005-06-12 11:28:18 +00001681 lookup (nlmsg_str, cmd),
1682#ifdef HAVE_IPV6
1683 (family == AF_INET) ? inet_ntoa (p->u.prefix4) :
1684 inet6_ntoa (p->u.prefix6),
1685#else
1686 inet_ntoa (p->u.prefix4),
1687#endif /* HAVE_IPV6 */
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001688 p->prefixlen, nexthop_type_to_str (nexthop->rtype));
paul7021c422003-07-15 12:52:22 +00001689 }
1690 if (nexthop->rtype == NEXTHOP_TYPE_IPV4
1691 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
1692 {
JR Rivers3cadc0c2012-04-01 12:16:31 -07001693 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
paul7021c422003-07-15 12:52:22 +00001694 &nexthop->rgate.ipv4, bytelen);
1695 rtnh->rtnh_len += sizeof (struct rtattr) + 4;
hasso206d8052005-04-09 16:38:51 +00001696
Paul Jakma7514fb72007-05-02 16:05:35 +00001697 if (nexthop->src.ipv4.s_addr)
1698 src = &nexthop->src;
1699
hasso206d8052005-04-09 16:38:51 +00001700 if (IS_ZEBRA_DEBUG_KERNEL)
1701 zlog_debug("netlink_route_multipath() (recursive, "
1702 "multihop): nexthop via %s if %u",
1703 inet_ntoa (nexthop->rgate.ipv4),
1704 nexthop->rifindex);
paul7021c422003-07-15 12:52:22 +00001705 }
paul718e3742002-12-13 20:15:29 +00001706#ifdef HAVE_IPV6
paul7021c422003-07-15 12:52:22 +00001707 if (nexthop->rtype == NEXTHOP_TYPE_IPV6
1708 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME
1709 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX)
hasso206d8052005-04-09 16:38:51 +00001710 {
JR Rivers3cadc0c2012-04-01 12:16:31 -07001711 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
hasso206d8052005-04-09 16:38:51 +00001712 &nexthop->rgate.ipv6, bytelen);
1713
1714 if (IS_ZEBRA_DEBUG_KERNEL)
1715 zlog_debug("netlink_route_multipath() (recursive, "
1716 "multihop): nexthop via %s if %u",
1717 inet6_ntoa (nexthop->rgate.ipv6),
1718 nexthop->rifindex);
1719 }
paul718e3742002-12-13 20:15:29 +00001720#endif /* HAVE_IPV6 */
paul7021c422003-07-15 12:52:22 +00001721 /* ifindex */
Paul Jakma7514fb72007-05-02 16:05:35 +00001722 if (nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
1723 || nexthop->rtype == NEXTHOP_TYPE_IFINDEX
1724 || nexthop->rtype == NEXTHOP_TYPE_IFNAME)
1725 {
1726 rtnh->rtnh_ifindex = nexthop->rifindex;
1727 if (nexthop->src.ipv4.s_addr)
1728 src = &nexthop->src;
1729
1730 if (IS_ZEBRA_DEBUG_KERNEL)
1731 zlog_debug("netlink_route_multipath() (recursive, "
1732 "multihop): nexthop via if %u",
1733 nexthop->rifindex);
1734 }
1735 else if (nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
paul7021c422003-07-15 12:52:22 +00001736 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
hasso206d8052005-04-09 16:38:51 +00001737 {
1738 rtnh->rtnh_ifindex = nexthop->rifindex;
1739
1740 if (IS_ZEBRA_DEBUG_KERNEL)
1741 zlog_debug("netlink_route_multipath() (recursive, "
1742 "multihop): nexthop via if %u",
1743 nexthop->rifindex);
1744 }
paul7021c422003-07-15 12:52:22 +00001745 else
hasso206d8052005-04-09 16:38:51 +00001746 {
1747 rtnh->rtnh_ifindex = 0;
1748 }
paul7021c422003-07-15 12:52:22 +00001749 }
1750 else
1751 {
1752 if (IS_ZEBRA_DEBUG_KERNEL)
1753 {
hasso206d8052005-04-09 16:38:51 +00001754 zlog_debug ("netlink_route_multipath() (multihop): "
1755 "%s %s/%d, type %s", lookup (nlmsg_str, cmd),
hasso1ada8192005-06-12 11:28:18 +00001756#ifdef HAVE_IPV6
hasso206d8052005-04-09 16:38:51 +00001757 (family == AF_INET) ? inet_ntoa (p->u.prefix4) :
hasso1ada8192005-06-12 11:28:18 +00001758 inet6_ntoa (p->u.prefix6),
1759#else
1760 inet_ntoa (p->u.prefix4),
1761#endif /* HAVE_IPV6 */
Avneesh Sachdev78deec42012-11-13 22:48:56 +00001762 p->prefixlen, nexthop_type_to_str (nexthop->type));
paul7021c422003-07-15 12:52:22 +00001763 }
1764 if (nexthop->type == NEXTHOP_TYPE_IPV4
1765 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1766 {
JR Rivers3cadc0c2012-04-01 12:16:31 -07001767 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
hasso206d8052005-04-09 16:38:51 +00001768 &nexthop->gate.ipv4, bytelen);
1769 rtnh->rtnh_len += sizeof (struct rtattr) + 4;
1770
Paul Jakma7514fb72007-05-02 16:05:35 +00001771 if (nexthop->src.ipv4.s_addr)
1772 src = &nexthop->src;
1773
hasso206d8052005-04-09 16:38:51 +00001774 if (IS_ZEBRA_DEBUG_KERNEL)
1775 zlog_debug("netlink_route_multipath() (multihop): "
1776 "nexthop via %s if %u",
1777 inet_ntoa (nexthop->gate.ipv4),
1778 nexthop->ifindex);
paul7021c422003-07-15 12:52:22 +00001779 }
paul718e3742002-12-13 20:15:29 +00001780#ifdef HAVE_IPV6
paul7021c422003-07-15 12:52:22 +00001781 if (nexthop->type == NEXTHOP_TYPE_IPV6
1782 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1783 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
hasso206d8052005-04-09 16:38:51 +00001784 {
JR Rivers3cadc0c2012-04-01 12:16:31 -07001785 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
hasso206d8052005-04-09 16:38:51 +00001786 &nexthop->gate.ipv6, bytelen);
1787
1788 if (IS_ZEBRA_DEBUG_KERNEL)
1789 zlog_debug("netlink_route_multipath() (multihop): "
1790 "nexthop via %s if %u",
1791 inet6_ntoa (nexthop->gate.ipv6),
1792 nexthop->ifindex);
1793 }
paul718e3742002-12-13 20:15:29 +00001794#endif /* HAVE_IPV6 */
paul7021c422003-07-15 12:52:22 +00001795 /* ifindex */
Paul Jakma7514fb72007-05-02 16:05:35 +00001796 if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1797 || nexthop->type == NEXTHOP_TYPE_IFINDEX
1798 || nexthop->type == NEXTHOP_TYPE_IFNAME)
1799 {
1800 rtnh->rtnh_ifindex = nexthop->ifindex;
1801 if (nexthop->src.ipv4.s_addr)
1802 src = &nexthop->src;
1803 if (IS_ZEBRA_DEBUG_KERNEL)
1804 zlog_debug("netlink_route_multipath() (multihop): "
1805 "nexthop via if %u", nexthop->ifindex);
1806 }
1807 else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
paul7021c422003-07-15 12:52:22 +00001808 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
hasso206d8052005-04-09 16:38:51 +00001809 {
1810 rtnh->rtnh_ifindex = nexthop->ifindex;
1811
1812 if (IS_ZEBRA_DEBUG_KERNEL)
1813 zlog_debug("netlink_route_multipath() (multihop): "
1814 "nexthop via if %u", nexthop->ifindex);
1815 }
paul7021c422003-07-15 12:52:22 +00001816 else
hasso206d8052005-04-09 16:38:51 +00001817 {
1818 rtnh->rtnh_ifindex = 0;
1819 }
paul7021c422003-07-15 12:52:22 +00001820 }
1821 rtnh = RTNH_NEXT (rtnh);
paul718e3742002-12-13 20:15:29 +00001822
paul7021c422003-07-15 12:52:22 +00001823 if (cmd == RTM_NEWROUTE)
1824 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1825 }
1826 }
Paul Jakma7514fb72007-05-02 16:05:35 +00001827 if (src)
1828 addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src->ipv4, bytelen);
paul718e3742002-12-13 20:15:29 +00001829
1830 if (rta->rta_len > RTA_LENGTH (0))
JR Rivers3cadc0c2012-04-01 12:16:31 -07001831 addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta),
paul7021c422003-07-15 12:52:22 +00001832 RTA_PAYLOAD (rta));
paul718e3742002-12-13 20:15:29 +00001833 }
1834
1835 /* If there is no useful nexthop then return. */
1836 if (nexthop_num == 0)
1837 {
1838 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +00001839 zlog_debug ("netlink_route_multipath(): No useful nexthop.");
paul718e3742002-12-13 20:15:29 +00001840 return 0;
1841 }
1842
paul7021c422003-07-15 12:52:22 +00001843skip:
paul718e3742002-12-13 20:15:29 +00001844
1845 /* Destination netlink address. */
1846 memset (&snl, 0, sizeof snl);
1847 snl.nl_family = AF_NETLINK;
1848
paul718e3742002-12-13 20:15:29 +00001849 /* Talk to netlink socket. */
hassob7ed1ec2005-03-31 20:13:49 +00001850 return netlink_talk (&req.n, &netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001851}
1852
1853int
1854kernel_add_ipv4 (struct prefix *p, struct rib *rib)
1855{
1856 return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET);
1857}
1858
1859int
1860kernel_delete_ipv4 (struct prefix *p, struct rib *rib)
1861{
1862 return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET);
1863}
1864
1865#ifdef HAVE_IPV6
1866int
1867kernel_add_ipv6 (struct prefix *p, struct rib *rib)
1868{
1869 return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET6);
1870}
1871
1872int
1873kernel_delete_ipv6 (struct prefix *p, struct rib *rib)
1874{
1875 return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET6);
1876}
1877
1878/* Delete IPv6 route from the kernel. */
1879int
1880kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate,
paul6621ca82005-11-23 13:02:08 +00001881 unsigned int index, int flags, int table)
paul718e3742002-12-13 20:15:29 +00001882{
paul7021c422003-07-15 12:52:22 +00001883 return netlink_route (RTM_DELROUTE, AF_INET6, &dest->prefix,
1884 dest->prefixlen, gate, index, flags, table);
paul718e3742002-12-13 20:15:29 +00001885}
1886#endif /* HAVE_IPV6 */
1887
1888/* Interface address modification. */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001889static int
paul718e3742002-12-13 20:15:29 +00001890netlink_address (int cmd, int family, struct interface *ifp,
paul7021c422003-07-15 12:52:22 +00001891 struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001892{
1893 int bytelen;
1894 struct prefix *p;
1895
paul7021c422003-07-15 12:52:22 +00001896 struct
paul718e3742002-12-13 20:15:29 +00001897 {
1898 struct nlmsghdr n;
1899 struct ifaddrmsg ifa;
JR Rivers3cadc0c2012-04-01 12:16:31 -07001900 char buf[NL_PKT_BUF_SIZE];
paul718e3742002-12-13 20:15:29 +00001901 } req;
1902
1903 p = ifc->address;
Jorge Boncompte [DTI2]a4c06de2012-04-20 14:28:40 +02001904 memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
paul718e3742002-12-13 20:15:29 +00001905
1906 bytelen = (family == AF_INET ? 4 : 16);
1907
paul7021c422003-07-15 12:52:22 +00001908 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg));
paul718e3742002-12-13 20:15:29 +00001909 req.n.nlmsg_flags = NLM_F_REQUEST;
1910 req.n.nlmsg_type = cmd;
1911 req.ifa.ifa_family = family;
1912
1913 req.ifa.ifa_index = ifp->ifindex;
1914 req.ifa.ifa_prefixlen = p->prefixlen;
1915
1916 addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen);
1917
1918 if (family == AF_INET && cmd == RTM_NEWADDR)
1919 {
Andrew J. Schorre4529632006-12-12 19:18:21 +00001920 if (!CONNECTED_PEER(ifc) && ifc->destination)
paul7021c422003-07-15 12:52:22 +00001921 {
1922 p = ifc->destination;
1923 addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix,
1924 bytelen);
1925 }
paul718e3742002-12-13 20:15:29 +00001926 }
1927
1928 if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
1929 SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY);
paul7021c422003-07-15 12:52:22 +00001930
paul718e3742002-12-13 20:15:29 +00001931 if (ifc->label)
1932 addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label,
paul7021c422003-07-15 12:52:22 +00001933 strlen (ifc->label) + 1);
paul718e3742002-12-13 20:15:29 +00001934
1935 return netlink_talk (&req.n, &netlink_cmd);
1936}
1937
1938int
1939kernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc)
1940{
1941 return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc);
1942}
1943
1944int
1945kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc)
1946{
1947 return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc);
1948}
1949
paul718e3742002-12-13 20:15:29 +00001950
1951extern struct thread_master *master;
1952
1953/* Kernel route reflection. */
Stephen Hemminger6072b242008-08-14 16:52:26 +01001954static int
paul718e3742002-12-13 20:15:29 +00001955kernel_read (struct thread *thread)
1956{
Stephen Hemminger9206f9e2011-12-18 19:43:40 +04001957 netlink_parse_info (netlink_information_fetch, &netlink);
paulb21b19c2003-06-15 01:28:29 +00001958 thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock);
paul718e3742002-12-13 20:15:29 +00001959
1960 return 0;
1961}
1962
Stephen Hemminger3d265b42008-08-16 17:30:39 +01001963/* Filter out messages from self that occur on listener socket,
1964 caused by our actions on the command socket
1965 */
1966static void netlink_install_filter (int sock, __u32 pid)
Paul Jakma768a27e2008-05-29 18:23:08 +00001967{
Paul Jakma768a27e2008-05-29 18:23:08 +00001968 struct sock_filter filter[] = {
Stephen Hemminger3d265b42008-08-16 17:30:39 +01001969 /* 0: ldh [4] */
1970 BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)),
1971 /* 1: jeq 0x18 jt 3 jf 6 */
1972 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 1, 0),
1973 /* 2: jeq 0x19 jt 3 jf 6 */
1974 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 0, 3),
1975 /* 3: ldw [12] */
1976 BPF_STMT(BPF_LD|BPF_ABS|BPF_W, offsetof(struct nlmsghdr, nlmsg_pid)),
1977 /* 4: jeq XX jt 5 jf 6 */
1978 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htonl(pid), 0, 1),
1979 /* 5: ret 0 (skip) */
1980 BPF_STMT(BPF_RET|BPF_K, 0),
1981 /* 6: ret 0xffff (keep) */
1982 BPF_STMT(BPF_RET|BPF_K, 0xffff),
Paul Jakma768a27e2008-05-29 18:23:08 +00001983 };
1984
1985 struct sock_fprog prog = {
Balaji.G837d16c2012-09-26 14:09:10 +05301986 .len = array_size(filter),
Paul Jakma768a27e2008-05-29 18:23:08 +00001987 .filter = filter,
1988 };
1989
1990 if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)) < 0)
1991 zlog_warn ("Can't install socket filter: %s\n", safe_strerror(errno));
1992}
1993
paul718e3742002-12-13 20:15:29 +00001994/* Exported interface function. This function simply calls
1995 netlink_socket (). */
1996void
paul6621ca82005-11-23 13:02:08 +00001997kernel_init (void)
paul718e3742002-12-13 20:15:29 +00001998{
1999 unsigned long groups;
2000
paul7021c422003-07-15 12:52:22 +00002001 groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR;
paul718e3742002-12-13 20:15:29 +00002002#ifdef HAVE_IPV6
paul7021c422003-07-15 12:52:22 +00002003 groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR;
paul718e3742002-12-13 20:15:29 +00002004#endif /* HAVE_IPV6 */
2005 netlink_socket (&netlink, groups);
2006 netlink_socket (&netlink_cmd, 0);
2007
2008 /* Register kernel socket. */
2009 if (netlink.sock > 0)
Paul Jakma768a27e2008-05-29 18:23:08 +00002010 {
Stephen Hemminger4cde9312008-08-16 17:51:27 +01002011 /* Only want non-blocking on the netlink event socket */
2012 if (fcntl (netlink.sock, F_SETFL, O_NONBLOCK) < 0)
2013 zlog (NULL, LOG_ERR, "Can't set %s socket flags: %s", netlink.name,
2014 safe_strerror (errno));
2015
Stephen Hemminger30afea32008-08-16 18:25:47 +01002016 /* Set receive buffer size if it's set from command line */
2017 if (nl_rcvbufsize)
2018 netlink_recvbuf (&netlink, nl_rcvbufsize);
2019
Stephen Hemminger3d265b42008-08-16 17:30:39 +01002020 netlink_install_filter (netlink.sock, netlink_cmd.snl.nl_pid);
Paul Jakma768a27e2008-05-29 18:23:08 +00002021 thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock);
2022 }
paul718e3742002-12-13 20:15:29 +00002023}
Avneesh Sachdev78deec42012-11-13 22:48:56 +00002024
2025/*
2026 * nl_msg_type_to_str
2027 */
2028const char *
2029nl_msg_type_to_str (uint16_t msg_type)
2030{
2031 return lookup (nlmsg_str, msg_type);
2032}
2033
2034/*
2035 * nl_rtproto_to_str
2036 */
2037const char *
2038nl_rtproto_to_str (u_char rtproto)
2039{
2040 return lookup (rtproto_str, rtproto);
2041}