blob: b3b2aab5d0c19cf0c509a1cd5a0f5eafdc41708d [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"
35#include "rib.h"
paule04ab742003-01-17 23:47:00 +000036#include "thread.h"
pauledd7c242003-06-04 13:59:38 +000037#include "privs.h"
paul718e3742002-12-13 20:15:29 +000038
39#include "zebra/zserv.h"
40#include "zebra/redistribute.h"
41#include "zebra/interface.h"
42#include "zebra/debug.h"
43
44/* Socket interface to kernel */
45struct nlsock
46{
47 int sock;
48 int seq;
49 struct sockaddr_nl snl;
hassofce954f2004-10-07 20:29:24 +000050 const char *name;
paul7021c422003-07-15 12:52:22 +000051} netlink = { -1, 0, {0}, "netlink-listen"}, /* kernel messages */
52 netlink_cmd = { -1, 0, {0}, "netlink-cmd"}, /* command channel */
53 netlink_addr = { -1, 0, {0}, "netlink-addr"}; /* address channel */
paul718e3742002-12-13 20:15:29 +000054
paul7021c422003-07-15 12:52:22 +000055struct message nlmsg_str[] = {
paul718e3742002-12-13 20:15:29 +000056 {RTM_NEWROUTE, "RTM_NEWROUTE"},
57 {RTM_DELROUTE, "RTM_DELROUTE"},
58 {RTM_GETROUTE, "RTM_GETROUTE"},
59 {RTM_NEWLINK, "RTM_NEWLINK"},
60 {RTM_DELLINK, "RTM_DELLINK"},
61 {RTM_GETLINK, "RTM_GETLINK"},
62 {RTM_NEWADDR, "RTM_NEWADDR"},
63 {RTM_DELADDR, "RTM_DELADDR"},
64 {RTM_GETADDR, "RTM_GETADDR"},
paul7021c422003-07-15 12:52:22 +000065 {0, NULL}
paul718e3742002-12-13 20:15:29 +000066};
67
hassofce954f2004-10-07 20:29:24 +000068const char *nexthop_types_desc[] =
paul7021c422003-07-15 12:52:22 +000069{
70 "none",
71 "Directly connected",
72 "Interface route",
73 "IPv4 nexthop",
74 "IPv4 nexthop with ifindex",
75 "IPv4 nexthop with ifname",
76 "IPv6 nexthop"
77 "IPv6 nexthop with ifindex",
78 "IPv6 nexthop with ifname",
79 "Null0 nexthop",
80};
81
82
paulb21b19c2003-06-15 01:28:29 +000083extern struct zebra_t zebrad;
paul718e3742002-12-13 20:15:29 +000084
pauledd7c242003-06-04 13:59:38 +000085extern struct zebra_privs_t zserv_privs;
86
hassoc34b6b52004-08-31 13:41:49 +000087extern u_int32_t nl_rcvbufsize;
88
ajsd2fc8892005-04-02 18:38:43 +000089/* Note: on netlink systems, there should be a 1-to-1 mapping between interface
90 names and ifindex values. */
91static void
92set_ifindex(struct interface *ifp, unsigned int ifi_index)
93{
94 struct interface *oifp;
95
96 if (((oifp = if_lookup_by_index(ifi_index)) != NULL) && (oifp != ifp))
97 {
98 if (ifi_index == IFINDEX_INTERNAL)
99 zlog_err("Netlink is setting interface %s ifindex to reserved "
100 "internal value %u", ifp->name, ifi_index);
101 else
102 {
103 if (IS_ZEBRA_DEBUG_KERNEL)
104 zlog_debug("interface index %d was renamed from %s to %s",
105 ifi_index, oifp->name, ifp->name);
106 if (if_is_up(oifp))
107 zlog_err("interface rename detected on up interface: index %d "
108 "was renamed from %s to %s, results are uncertain!",
109 ifi_index, oifp->name, ifp->name);
110 if_delete_update(oifp);
111 }
112 }
113 ifp->ifindex = ifi_index;
114}
115
paul718e3742002-12-13 20:15:29 +0000116/* Make socket for Linux netlink interface. */
117static int
118netlink_socket (struct nlsock *nl, unsigned long groups)
119{
120 int ret;
121 struct sockaddr_nl snl;
122 int sock;
123 int namelen;
ajs4be019d2005-01-29 16:12:41 +0000124 int save_errno;
paul718e3742002-12-13 20:15:29 +0000125
126 sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
127 if (sock < 0)
128 {
129 zlog (NULL, LOG_ERR, "Can't open %s socket: %s", nl->name,
ajs6099b3b2004-11-20 02:06:59 +0000130 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000131 return -1;
132 }
133
134 ret = fcntl (sock, F_SETFL, O_NONBLOCK);
135 if (ret < 0)
136 {
137 zlog (NULL, LOG_ERR, "Can't set %s socket flags: %s", nl->name,
ajs6099b3b2004-11-20 02:06:59 +0000138 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000139 close (sock);
140 return -1;
141 }
paul7021c422003-07-15 12:52:22 +0000142
hassoc34b6b52004-08-31 13:41:49 +0000143 /* Set receive buffer size if it's set from command line */
144 if (nl_rcvbufsize)
145 {
146 u_int32_t oldsize, oldlen;
147 u_int32_t newsize, newlen;
148
149 oldlen = sizeof(oldsize);
150 newlen = sizeof(newsize);
151
152 ret = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &oldsize, &oldlen);
153 if (ret < 0)
154 {
155 zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name,
ajs6099b3b2004-11-20 02:06:59 +0000156 safe_strerror (errno));
hassoc34b6b52004-08-31 13:41:49 +0000157 close (sock);
158 return -1;
159 }
160
161 ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &nl_rcvbufsize,
162 sizeof(nl_rcvbufsize));
163 if (ret < 0)
164 {
165 zlog (NULL, LOG_ERR, "Can't set %s receive buffer size: %s", nl->name,
ajs6099b3b2004-11-20 02:06:59 +0000166 safe_strerror (errno));
hassoc34b6b52004-08-31 13:41:49 +0000167 close (sock);
168 return -1;
169 }
170
171 ret = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &newsize, &newlen);
172 if (ret < 0)
173 {
174 zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name,
ajs6099b3b2004-11-20 02:06:59 +0000175 safe_strerror (errno));
hassoc34b6b52004-08-31 13:41:49 +0000176 close (sock);
177 return -1;
178 }
179
180 zlog (NULL, LOG_INFO,
181 "Setting netlink socket receive buffer size: %u -> %u",
182 oldsize, newsize);
183 }
184
paul718e3742002-12-13 20:15:29 +0000185 memset (&snl, 0, sizeof snl);
186 snl.nl_family = AF_NETLINK;
187 snl.nl_groups = groups;
188
189 /* Bind the socket to the netlink structure for anything. */
paul7021c422003-07-15 12:52:22 +0000190 if (zserv_privs.change (ZPRIVS_RAISE))
191 {
192 zlog (NULL, LOG_ERR, "Can't raise privileges");
193 return -1;
194 }
pauledd7c242003-06-04 13:59:38 +0000195
paul718e3742002-12-13 20:15:29 +0000196 ret = bind (sock, (struct sockaddr *) &snl, sizeof snl);
ajs4be019d2005-01-29 16:12:41 +0000197 save_errno = errno;
hasso55e7ecd2004-08-06 08:41:56 +0000198 if (zserv_privs.change (ZPRIVS_LOWER))
199 zlog (NULL, LOG_ERR, "Can't lower privileges");
200
paul718e3742002-12-13 20:15:29 +0000201 if (ret < 0)
202 {
paul7021c422003-07-15 12:52:22 +0000203 zlog (NULL, LOG_ERR, "Can't bind %s socket to group 0x%x: %s",
ajs4be019d2005-01-29 16:12:41 +0000204 nl->name, snl.nl_groups, safe_strerror (save_errno));
paul718e3742002-12-13 20:15:29 +0000205 close (sock);
206 return -1;
207 }
paul7021c422003-07-15 12:52:22 +0000208
paul718e3742002-12-13 20:15:29 +0000209 /* multiple netlink sockets will have different nl_pid */
210 namelen = sizeof snl;
hassoc9e52be2004-09-26 16:09:34 +0000211 ret = getsockname (sock, (struct sockaddr *) &snl, (socklen_t *) &namelen);
paul718e3742002-12-13 20:15:29 +0000212 if (ret < 0 || namelen != sizeof snl)
213 {
214 zlog (NULL, LOG_ERR, "Can't get %s socket name: %s", nl->name,
ajs6099b3b2004-11-20 02:06:59 +0000215 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000216 close (sock);
217 return -1;
218 }
219
220 nl->snl = snl;
221 nl->sock = sock;
222 return ret;
223}
224
paul7021c422003-07-15 12:52:22 +0000225int
226set_netlink_blocking (struct nlsock *nl, int *flags)
paul5f37d862003-04-19 00:11:28 +0000227{
228
229 /* Change socket flags for blocking I/O. */
paul7021c422003-07-15 12:52:22 +0000230 if ((*flags = fcntl (nl->sock, F_GETFL, 0)) < 0)
paul5f37d862003-04-19 00:11:28 +0000231 {
paul7021c422003-07-15 12:52:22 +0000232 zlog (NULL, LOG_ERR, "%s:%i F_GETFL error: %s",
ajs6099b3b2004-11-20 02:06:59 +0000233 __FUNCTION__, __LINE__, safe_strerror (errno));
paul5f37d862003-04-19 00:11:28 +0000234 return -1;
235 }
236 *flags &= ~O_NONBLOCK;
paul7021c422003-07-15 12:52:22 +0000237 if (fcntl (nl->sock, F_SETFL, *flags) < 0)
paul5f37d862003-04-19 00:11:28 +0000238 {
paul7021c422003-07-15 12:52:22 +0000239 zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",
ajs6099b3b2004-11-20 02:06:59 +0000240 __FUNCTION__, __LINE__, safe_strerror (errno));
paul5f37d862003-04-19 00:11:28 +0000241 return -1;
242 }
243 return 0;
244}
245
paul7021c422003-07-15 12:52:22 +0000246int
247set_netlink_nonblocking (struct nlsock *nl, int *flags)
248{
paul5f37d862003-04-19 00:11:28 +0000249 /* Restore socket flags for nonblocking I/O */
250 *flags |= O_NONBLOCK;
paul7021c422003-07-15 12:52:22 +0000251 if (fcntl (nl->sock, F_SETFL, *flags) < 0)
paul5f37d862003-04-19 00:11:28 +0000252 {
paul7021c422003-07-15 12:52:22 +0000253 zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",
ajs6099b3b2004-11-20 02:06:59 +0000254 __FUNCTION__, __LINE__, safe_strerror (errno));
paul5f37d862003-04-19 00:11:28 +0000255 return -1;
256 }
257 return 0;
258}
259
paul718e3742002-12-13 20:15:29 +0000260/* Get type specified information from netlink. */
261static int
262netlink_request (int family, int type, struct nlsock *nl)
263{
264 int ret;
265 struct sockaddr_nl snl;
ajs4be019d2005-01-29 16:12:41 +0000266 int save_errno;
paul718e3742002-12-13 20:15:29 +0000267
268 struct
269 {
270 struct nlmsghdr nlh;
271 struct rtgenmsg g;
272 } req;
273
274
275 /* Check netlink socket. */
276 if (nl->sock < 0)
277 {
278 zlog (NULL, LOG_ERR, "%s socket isn't active.", nl->name);
279 return -1;
280 }
281
282 memset (&snl, 0, sizeof snl);
283 snl.nl_family = AF_NETLINK;
284
285 req.nlh.nlmsg_len = sizeof req;
286 req.nlh.nlmsg_type = type;
287 req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
288 req.nlh.nlmsg_pid = 0;
289 req.nlh.nlmsg_seq = ++nl->seq;
290 req.g.rtgen_family = family;
pauledd7c242003-06-04 13:59:38 +0000291
292 /* linux appears to check capabilities on every message
293 * have to raise caps for every message sent
294 */
paul7021c422003-07-15 12:52:22 +0000295 if (zserv_privs.change (ZPRIVS_RAISE))
pauledd7c242003-06-04 13:59:38 +0000296 {
297 zlog (NULL, LOG_ERR, "Can't raise privileges");
298 return -1;
299 }
paul7021c422003-07-15 12:52:22 +0000300
301 ret = sendto (nl->sock, (void *) &req, sizeof req, 0,
302 (struct sockaddr *) &snl, sizeof snl);
ajs4be019d2005-01-29 16:12:41 +0000303 save_errno = errno;
paul7021c422003-07-15 12:52:22 +0000304
305 if (zserv_privs.change (ZPRIVS_LOWER))
306 zlog (NULL, LOG_ERR, "Can't lower privileges");
307
paul718e3742002-12-13 20:15:29 +0000308 if (ret < 0)
paul7021c422003-07-15 12:52:22 +0000309 {
310 zlog (NULL, LOG_ERR, "%s sendto failed: %s", nl->name,
ajs4be019d2005-01-29 16:12:41 +0000311 safe_strerror (save_errno));
paul718e3742002-12-13 20:15:29 +0000312 return -1;
313 }
pauledd7c242003-06-04 13:59:38 +0000314
paul718e3742002-12-13 20:15:29 +0000315 return 0;
316}
317
318/* Receive message from netlink interface and pass those information
319 to the given function. */
320static int
321netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *),
paul7021c422003-07-15 12:52:22 +0000322 struct nlsock *nl)
paul718e3742002-12-13 20:15:29 +0000323{
324 int status;
325 int ret = 0;
326 int error;
327
328 while (1)
329 {
330 char buf[4096];
331 struct iovec iov = { buf, sizeof buf };
332 struct sockaddr_nl snl;
paul7021c422003-07-15 12:52:22 +0000333 struct msghdr msg = { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 };
paul718e3742002-12-13 20:15:29 +0000334 struct nlmsghdr *h;
ajs4be019d2005-01-29 16:12:41 +0000335 int save_errno;
paul718e3742002-12-13 20:15:29 +0000336
paul7021c422003-07-15 12:52:22 +0000337 if (zserv_privs.change (ZPRIVS_RAISE))
pauledd7c242003-06-04 13:59:38 +0000338 zlog (NULL, LOG_ERR, "Can't raise privileges");
paul7021c422003-07-15 12:52:22 +0000339
paul718e3742002-12-13 20:15:29 +0000340 status = recvmsg (nl->sock, &msg, 0);
ajs4be019d2005-01-29 16:12:41 +0000341 save_errno = errno;
paul7021c422003-07-15 12:52:22 +0000342
343 if (zserv_privs.change (ZPRIVS_LOWER))
pauledd7c242003-06-04 13:59:38 +0000344 zlog (NULL, LOG_ERR, "Can't lower privileges");
paul718e3742002-12-13 20:15:29 +0000345
346 if (status < 0)
paul7021c422003-07-15 12:52:22 +0000347 {
ajs4be019d2005-01-29 16:12:41 +0000348 if (save_errno == EINTR)
paul7021c422003-07-15 12:52:22 +0000349 continue;
ajs4be019d2005-01-29 16:12:41 +0000350 if (save_errno == EWOULDBLOCK || save_errno == EAGAIN)
paul7021c422003-07-15 12:52:22 +0000351 break;
ajs4be019d2005-01-29 16:12:41 +0000352 zlog (NULL, LOG_ERR, "%s recvmsg overrun: %s",
353 nl->name, safe_strerror(save_errno));
paul7021c422003-07-15 12:52:22 +0000354 continue;
355 }
paul718e3742002-12-13 20:15:29 +0000356
357 if (status == 0)
paul7021c422003-07-15 12:52:22 +0000358 {
359 zlog (NULL, LOG_ERR, "%s EOF", nl->name);
360 return -1;
361 }
paul718e3742002-12-13 20:15:29 +0000362
363 if (msg.msg_namelen != sizeof snl)
paul7021c422003-07-15 12:52:22 +0000364 {
365 zlog (NULL, LOG_ERR, "%s sender address length error: length %d",
366 nl->name, msg.msg_namelen);
367 return -1;
368 }
paulb84d3a12003-11-17 10:31:01 +0000369
370 /* JF: Ignore messages that aren't from the kernel */
371 if ( snl.nl_pid != 0 )
372 {
373 zlog ( NULL, LOG_ERR, "Ignoring message from pid %u", snl.nl_pid );
374 continue;
375 }
paul718e3742002-12-13 20:15:29 +0000376
paul7021c422003-07-15 12:52:22 +0000377 for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, status);
378 h = NLMSG_NEXT (h, status))
379 {
380 /* Finish of reading. */
381 if (h->nlmsg_type == NLMSG_DONE)
382 return ret;
paul718e3742002-12-13 20:15:29 +0000383
paul7021c422003-07-15 12:52:22 +0000384 /* Error handling. */
385 if (h->nlmsg_type == NLMSG_ERROR)
386 {
387 struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h);
388
paul718e3742002-12-13 20:15:29 +0000389 /* If the error field is zero, then this is an ACK */
paul7021c422003-07-15 12:52:22 +0000390 if (err->error == 0)
paul718e3742002-12-13 20:15:29 +0000391 {
paul7021c422003-07-15 12:52:22 +0000392 if (IS_ZEBRA_DEBUG_KERNEL)
393 {
ajsb6178002004-12-07 21:12:56 +0000394 zlog_debug ("%s: %s ACK: type=%s(%u), seq=%u, pid=%d",
paul7021c422003-07-15 12:52:22 +0000395 __FUNCTION__, nl->name,
396 lookup (nlmsg_str, err->msg.nlmsg_type),
397 err->msg.nlmsg_type, err->msg.nlmsg_seq,
398 err->msg.nlmsg_pid);
paul718e3742002-12-13 20:15:29 +0000399 }
paul7021c422003-07-15 12:52:22 +0000400
401 /* return if not a multipart message, otherwise continue */
402 if (!(h->nlmsg_flags & NLM_F_MULTI))
403 {
404 return 0;
paul718e3742002-12-13 20:15:29 +0000405 }
paul7021c422003-07-15 12:52:22 +0000406 continue;
paul718e3742002-12-13 20:15:29 +0000407 }
paul7021c422003-07-15 12:52:22 +0000408
paul718e3742002-12-13 20:15:29 +0000409 if (h->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr)))
paul7021c422003-07-15 12:52:22 +0000410 {
411 zlog (NULL, LOG_ERR, "%s error: message truncated",
412 nl->name);
413 return -1;
414 }
pauld753e9e2003-01-22 19:45:50 +0000415
paul7021c422003-07-15 12:52:22 +0000416 /* Deal with Error Noise - MAG */
417 {
418 int loglvl = LOG_ERR;
419 int errnum = err->error;
420 int msg_type = err->msg.nlmsg_type;
paul718e3742002-12-13 20:15:29 +0000421
paul7021c422003-07-15 12:52:22 +0000422 if (nl == &netlink_cmd
423 && (-errnum == ENODEV || -errnum == ESRCH)
424 && (msg_type == RTM_NEWROUTE || msg_type == RTM_DELROUTE))
425 loglvl = LOG_DEBUG;
paul718e3742002-12-13 20:15:29 +0000426
paul7021c422003-07-15 12:52:22 +0000427 zlog (NULL, loglvl, "%s error: %s, type=%s(%u), "
428 "seq=%u, pid=%d",
ajs6099b3b2004-11-20 02:06:59 +0000429 nl->name, safe_strerror (-errnum),
paul7021c422003-07-15 12:52:22 +0000430 lookup (nlmsg_str, msg_type),
431 msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid);
432 }
433 /*
434 ret = -1;
435 continue;
436 */
437 return -1;
438 }
paul718e3742002-12-13 20:15:29 +0000439
paul7021c422003-07-15 12:52:22 +0000440 /* OK we got netlink message. */
441 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000442 zlog_debug ("netlink_parse_info: %s type %s(%u), seq=%u, pid=%d",
paul7021c422003-07-15 12:52:22 +0000443 nl->name,
444 lookup (nlmsg_str, h->nlmsg_type), h->nlmsg_type,
445 h->nlmsg_seq, h->nlmsg_pid);
446
447 /* skip unsolicited messages originating from command socket */
448 if (nl != &netlink_cmd && h->nlmsg_pid == netlink_cmd.snl.nl_pid)
449 {
450 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000451 zlog_debug ("netlink_parse_info: %s packet comes from %s",
paul7021c422003-07-15 12:52:22 +0000452 nl->name, netlink_cmd.name);
453 continue;
454 }
455
456 error = (*filter) (&snl, h);
457 if (error < 0)
458 {
459 zlog (NULL, LOG_ERR, "%s filter function error", nl->name);
460 ret = error;
461 }
462 }
paul718e3742002-12-13 20:15:29 +0000463
464 /* After error care. */
465 if (msg.msg_flags & MSG_TRUNC)
paul7021c422003-07-15 12:52:22 +0000466 {
467 zlog (NULL, LOG_ERR, "%s error: message truncated", nl->name);
468 continue;
469 }
paul718e3742002-12-13 20:15:29 +0000470 if (status)
paul7021c422003-07-15 12:52:22 +0000471 {
472 zlog (NULL, LOG_ERR, "%s error: data remnant size %d", nl->name,
473 status);
474 return -1;
475 }
paul718e3742002-12-13 20:15:29 +0000476 }
477 return ret;
478}
479
480/* Utility function for parse rtattr. */
481static void
paul7021c422003-07-15 12:52:22 +0000482netlink_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta,
483 int len)
paul718e3742002-12-13 20:15:29 +0000484{
paul7021c422003-07-15 12:52:22 +0000485 while (RTA_OK (rta, len))
paul718e3742002-12-13 20:15:29 +0000486 {
487 if (rta->rta_type <= max)
paul7021c422003-07-15 12:52:22 +0000488 tb[rta->rta_type] = rta;
489 rta = RTA_NEXT (rta, len);
paul718e3742002-12-13 20:15:29 +0000490 }
491}
492
493/* Called from interface_lookup_netlink(). This function is only used
494 during bootstrap. */
495int
496netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h)
497{
498 int len;
499 struct ifinfomsg *ifi;
500 struct rtattr *tb[IFLA_MAX + 1];
501 struct interface *ifp;
502 char *name;
503 int i;
504
505 ifi = NLMSG_DATA (h);
506
507 if (h->nlmsg_type != RTM_NEWLINK)
508 return 0;
509
510 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
511 if (len < 0)
512 return -1;
513
514 /* Looking up interface name. */
515 memset (tb, 0, sizeof tb);
516 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
paulc15cb242005-01-24 09:05:27 +0000517
paul1e193152005-02-14 23:53:05 +0000518#ifdef IFLA_WIRELESS
paulc15cb242005-01-24 09:05:27 +0000519 /* check for wireless messages to ignore */
520 if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
521 {
522 if (IS_ZEBRA_DEBUG_KERNEL)
523 zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__);
524 return 0;
525 }
paul1e193152005-02-14 23:53:05 +0000526#endif /* IFLA_WIRELESS */
paulc15cb242005-01-24 09:05:27 +0000527
paul718e3742002-12-13 20:15:29 +0000528 if (tb[IFLA_IFNAME] == NULL)
529 return -1;
paul7021c422003-07-15 12:52:22 +0000530 name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
paul718e3742002-12-13 20:15:29 +0000531
532 /* Add interface. */
533 ifp = if_get_by_name (name);
ajsd2fc8892005-04-02 18:38:43 +0000534 set_ifindex(ifp, ifi->ifi_index);
paul718e3742002-12-13 20:15:29 +0000535 ifp->flags = ifi->ifi_flags & 0x0000fffff;
paul44145db2004-05-09 11:00:23 +0000536 ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
paul718e3742002-12-13 20:15:29 +0000537 ifp->metric = 1;
538
539 /* Hardware type and address. */
540 ifp->hw_type = ifi->ifi_type;
541
542 if (tb[IFLA_ADDRESS])
543 {
544 int hw_addr_len;
545
paul7021c422003-07-15 12:52:22 +0000546 hw_addr_len = RTA_PAYLOAD (tb[IFLA_ADDRESS]);
paul718e3742002-12-13 20:15:29 +0000547
548 if (hw_addr_len > INTERFACE_HWADDR_MAX)
paul7021c422003-07-15 12:52:22 +0000549 zlog_warn ("Hardware address is too large: %d", hw_addr_len);
paul718e3742002-12-13 20:15:29 +0000550 else
paul7021c422003-07-15 12:52:22 +0000551 {
552 ifp->hw_addr_len = hw_addr_len;
553 memcpy (ifp->hw_addr, RTA_DATA (tb[IFLA_ADDRESS]), hw_addr_len);
paul718e3742002-12-13 20:15:29 +0000554
paul7021c422003-07-15 12:52:22 +0000555 for (i = 0; i < hw_addr_len; i++)
556 if (ifp->hw_addr[i] != 0)
557 break;
paul718e3742002-12-13 20:15:29 +0000558
paul7021c422003-07-15 12:52:22 +0000559 if (i == hw_addr_len)
560 ifp->hw_addr_len = 0;
561 else
562 ifp->hw_addr_len = hw_addr_len;
563 }
paul718e3742002-12-13 20:15:29 +0000564 }
565
566 if_add_update (ifp);
567
568 return 0;
569}
570
571/* Lookup interface IPv4/IPv6 address. */
572int
573netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
574{
575 int len;
576 struct ifaddrmsg *ifa;
paul7021c422003-07-15 12:52:22 +0000577 struct rtattr *tb[IFA_MAX + 1];
paul718e3742002-12-13 20:15:29 +0000578 struct interface *ifp;
579 void *addr = NULL;
580 void *broad = NULL;
581 u_char flags = 0;
582 char *label = NULL;
583
584 ifa = NLMSG_DATA (h);
585
paul7021c422003-07-15 12:52:22 +0000586 if (ifa->ifa_family != AF_INET
paul718e3742002-12-13 20:15:29 +0000587#ifdef HAVE_IPV6
588 && ifa->ifa_family != AF_INET6
589#endif /* HAVE_IPV6 */
paul7021c422003-07-15 12:52:22 +0000590 )
paul718e3742002-12-13 20:15:29 +0000591 return 0;
592
593 if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
594 return 0;
595
paul7021c422003-07-15 12:52:22 +0000596 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifaddrmsg));
paul718e3742002-12-13 20:15:29 +0000597 if (len < 0)
598 return -1;
599
600 memset (tb, 0, sizeof tb);
601 netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len);
602
603 ifp = if_lookup_by_index (ifa->ifa_index);
604 if (ifp == NULL)
605 {
606 zlog_err ("netlink_interface_addr can't find interface by index %d",
paul7021c422003-07-15 12:52:22 +0000607 ifa->ifa_index);
paul718e3742002-12-13 20:15:29 +0000608 return -1;
609 }
610
paul7021c422003-07-15 12:52:22 +0000611 if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */
paul718e3742002-12-13 20:15:29 +0000612 {
paul00df0c12002-12-13 21:07:36 +0000613 char buf[BUFSIZ];
ajsb6178002004-12-07 21:12:56 +0000614 zlog_debug ("netlink_interface_addr %s %s/%d:",
paul7021c422003-07-15 12:52:22 +0000615 lookup (nlmsg_str, h->nlmsg_type),
616 ifp->name, ifa->ifa_prefixlen);
paul718e3742002-12-13 20:15:29 +0000617 if (tb[IFA_LOCAL])
ajsb6178002004-12-07 21:12:56 +0000618 zlog_debug (" IFA_LOCAL %s", inet_ntop (ifa->ifa_family,
paul7021c422003-07-15 12:52:22 +0000619 RTA_DATA (tb[IFA_LOCAL]),
620 buf, BUFSIZ));
paul718e3742002-12-13 20:15:29 +0000621 if (tb[IFA_ADDRESS])
ajsb6178002004-12-07 21:12:56 +0000622 zlog_debug (" IFA_ADDRESS %s", inet_ntop (ifa->ifa_family,
paul7021c422003-07-15 12:52:22 +0000623 RTA_DATA (tb
624 [IFA_ADDRESS]),
625 buf, BUFSIZ));
paul718e3742002-12-13 20:15:29 +0000626 if (tb[IFA_BROADCAST])
ajsb6178002004-12-07 21:12:56 +0000627 zlog_debug (" IFA_BROADCAST %s", inet_ntop (ifa->ifa_family,
paul7021c422003-07-15 12:52:22 +0000628 RTA_DATA (tb
629 [IFA_BROADCAST]),
630 buf, BUFSIZ));
paul00df0c12002-12-13 21:07:36 +0000631 if (tb[IFA_LABEL] && strcmp (ifp->name, RTA_DATA (tb[IFA_LABEL])))
ajsb6178002004-12-07 21:12:56 +0000632 zlog_debug (" IFA_LABEL %s", (char *)RTA_DATA (tb[IFA_LABEL]));
paul718e3742002-12-13 20:15:29 +0000633 }
paul31a476c2003-09-29 19:54:53 +0000634
635 if (tb[IFA_ADDRESS] == NULL)
636 tb[IFA_ADDRESS] = tb[IFA_LOCAL];
637
638 if (ifp->flags & IFF_POINTOPOINT)
paul7021c422003-07-15 12:52:22 +0000639 {
paul31a476c2003-09-29 19:54:53 +0000640 if (tb[IFA_LOCAL])
641 {
642 addr = RTA_DATA (tb[IFA_LOCAL]);
hasso3fb9cd62004-10-19 19:44:43 +0000643 if (tb[IFA_ADDRESS] &&
644 memcmp(RTA_DATA(tb[IFA_ADDRESS]),RTA_DATA(tb[IFA_LOCAL]),4))
645 /* if IFA_ADDRESS != IFA_LOCAL, then it's the peer address */
paul31a476c2003-09-29 19:54:53 +0000646 broad = RTA_DATA (tb[IFA_ADDRESS]);
647 else
648 broad = NULL;
649 }
650 else
651 {
652 if (tb[IFA_ADDRESS])
653 addr = RTA_DATA (tb[IFA_ADDRESS]);
654 else
655 addr = NULL;
656 }
paul7021c422003-07-15 12:52:22 +0000657 }
paul31a476c2003-09-29 19:54:53 +0000658 else
paul7021c422003-07-15 12:52:22 +0000659 {
paul31a476c2003-09-29 19:54:53 +0000660 if (tb[IFA_ADDRESS])
661 addr = RTA_DATA (tb[IFA_ADDRESS]);
662 else
663 addr = NULL;
664
665 if (tb[IFA_BROADCAST])
666 broad = RTA_DATA(tb[IFA_BROADCAST]);
667 else
668 broad = NULL;
paul7021c422003-07-15 12:52:22 +0000669 }
paul00df0c12002-12-13 21:07:36 +0000670
paul718e3742002-12-13 20:15:29 +0000671 /* Flags. */
672 if (ifa->ifa_flags & IFA_F_SECONDARY)
673 SET_FLAG (flags, ZEBRA_IFA_SECONDARY);
674
675 /* Label */
676 if (tb[IFA_LABEL])
677 label = (char *) RTA_DATA (tb[IFA_LABEL]);
678
679 if (ifp && label && strcmp (ifp->name, label) == 0)
680 label = NULL;
681
682 /* Register interface address to the interface. */
683 if (ifa->ifa_family == AF_INET)
684 {
paul7021c422003-07-15 12:52:22 +0000685 if (h->nlmsg_type == RTM_NEWADDR)
686 connected_add_ipv4 (ifp, flags,
687 (struct in_addr *) addr, ifa->ifa_prefixlen,
688 (struct in_addr *) broad, label);
689 else
690 connected_delete_ipv4 (ifp, flags,
691 (struct in_addr *) addr, ifa->ifa_prefixlen,
692 (struct in_addr *) broad, label);
paul718e3742002-12-13 20:15:29 +0000693 }
694#ifdef HAVE_IPV6
695 if (ifa->ifa_family == AF_INET6)
696 {
697 if (h->nlmsg_type == RTM_NEWADDR)
paul7021c422003-07-15 12:52:22 +0000698 connected_add_ipv6 (ifp,
699 (struct in6_addr *) addr, ifa->ifa_prefixlen,
700 (struct in6_addr *) broad);
paul718e3742002-12-13 20:15:29 +0000701 else
paul7021c422003-07-15 12:52:22 +0000702 connected_delete_ipv6 (ifp,
703 (struct in6_addr *) addr, ifa->ifa_prefixlen,
704 (struct in6_addr *) broad);
paul718e3742002-12-13 20:15:29 +0000705 }
paul7021c422003-07-15 12:52:22 +0000706#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +0000707
708 return 0;
709}
710
711/* Looking up routing table by netlink interface. */
712int
713netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
714{
715 int len;
716 struct rtmsg *rtm;
paul7021c422003-07-15 12:52:22 +0000717 struct rtattr *tb[RTA_MAX + 1];
paul718e3742002-12-13 20:15:29 +0000718 u_char flags = 0;
paul7021c422003-07-15 12:52:22 +0000719
720 char anyaddr[16] = { 0 };
paul718e3742002-12-13 20:15:29 +0000721
722 int index;
723 int table;
hasso34195bf2004-04-06 12:07:06 +0000724 int metric;
725
paul718e3742002-12-13 20:15:29 +0000726 void *dest;
727 void *gate;
728
729 rtm = NLMSG_DATA (h);
730
731 if (h->nlmsg_type != RTM_NEWROUTE)
732 return 0;
733 if (rtm->rtm_type != RTN_UNICAST)
734 return 0;
735
736 table = rtm->rtm_table;
paul7021c422003-07-15 12:52:22 +0000737#if 0 /* we weed them out later in rib_weed_tables () */
paulb21b19c2003-06-15 01:28:29 +0000738 if (table != RT_TABLE_MAIN && table != zebrad.rtm_table_default)
paul718e3742002-12-13 20:15:29 +0000739 return 0;
740#endif
741
paul7021c422003-07-15 12:52:22 +0000742 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
paul718e3742002-12-13 20:15:29 +0000743 if (len < 0)
744 return -1;
745
746 memset (tb, 0, sizeof tb);
747 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
748
749 if (rtm->rtm_flags & RTM_F_CLONED)
750 return 0;
751 if (rtm->rtm_protocol == RTPROT_REDIRECT)
752 return 0;
753 if (rtm->rtm_protocol == RTPROT_KERNEL)
754 return 0;
755
756 if (rtm->rtm_src_len != 0)
757 return 0;
758
759 /* Route which inserted by Zebra. */
760 if (rtm->rtm_protocol == RTPROT_ZEBRA)
761 flags |= ZEBRA_FLAG_SELFROUTE;
paul7021c422003-07-15 12:52:22 +0000762
paul718e3742002-12-13 20:15:29 +0000763 index = 0;
hasso34195bf2004-04-06 12:07:06 +0000764 metric = 0;
paul718e3742002-12-13 20:15:29 +0000765 dest = NULL;
766 gate = NULL;
767
768 if (tb[RTA_OIF])
769 index = *(int *) RTA_DATA (tb[RTA_OIF]);
770
771 if (tb[RTA_DST])
772 dest = RTA_DATA (tb[RTA_DST]);
773 else
774 dest = anyaddr;
775
776 /* Multipath treatment is needed. */
777 if (tb[RTA_GATEWAY])
778 gate = RTA_DATA (tb[RTA_GATEWAY]);
779
hasso34195bf2004-04-06 12:07:06 +0000780 if (tb[RTA_PRIORITY])
781 metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
782
paul718e3742002-12-13 20:15:29 +0000783 if (rtm->rtm_family == AF_INET)
784 {
785 struct prefix_ipv4 p;
786 p.family = AF_INET;
787 memcpy (&p.prefix, dest, 4);
788 p.prefixlen = rtm->rtm_dst_len;
789
hasso34195bf2004-04-06 12:07:06 +0000790 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table, metric, 0);
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
800 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table);
801 }
802#endif /* HAVE_IPV6 */
803
804 return 0;
805}
806
paul7021c422003-07-15 12:52:22 +0000807struct message rtproto_str[] = {
paul718e3742002-12-13 20:15:29 +0000808 {RTPROT_REDIRECT, "redirect"},
809 {RTPROT_KERNEL, "kernel"},
810 {RTPROT_BOOT, "boot"},
811 {RTPROT_STATIC, "static"},
812 {RTPROT_GATED, "GateD"},
813 {RTPROT_RA, "router advertisement"},
814 {RTPROT_MRT, "MRT"},
815 {RTPROT_ZEBRA, "Zebra"},
816#ifdef RTPROT_BIRD
817 {RTPROT_BIRD, "BIRD"},
818#endif /* RTPROT_BIRD */
819 {0, NULL}
820};
821
822/* Routing information change from the kernel. */
823int
824netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
825{
826 int len;
827 struct rtmsg *rtm;
paul7021c422003-07-15 12:52:22 +0000828 struct rtattr *tb[RTA_MAX + 1];
829
830 char anyaddr[16] = { 0 };
paul718e3742002-12-13 20:15:29 +0000831
832 int index;
833 int table;
834 void *dest;
835 void *gate;
836
837 rtm = NLMSG_DATA (h);
838
paul7021c422003-07-15 12:52:22 +0000839 if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
paul718e3742002-12-13 20:15:29 +0000840 {
841 /* If this is not route add/delete message print warning. */
842 zlog_warn ("Kernel message: %d\n", h->nlmsg_type);
843 return 0;
844 }
845
846 /* Connected route. */
847 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +0000848 zlog_debug ("%s %s %s proto %s",
paul7021c422003-07-15 12:52:22 +0000849 h->nlmsg_type ==
850 RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
851 rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",
852 rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast",
853 lookup (rtproto_str, rtm->rtm_protocol));
paul718e3742002-12-13 20:15:29 +0000854
855 if (rtm->rtm_type != RTN_UNICAST)
856 {
857 return 0;
858 }
859
860 table = rtm->rtm_table;
paulb21b19c2003-06-15 01:28:29 +0000861 if (table != RT_TABLE_MAIN && table != zebrad.rtm_table_default)
paul718e3742002-12-13 20:15:29 +0000862 {
863 return 0;
864 }
865
paul7021c422003-07-15 12:52:22 +0000866 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
paul718e3742002-12-13 20:15:29 +0000867 if (len < 0)
868 return -1;
869
870 memset (tb, 0, sizeof tb);
871 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
872
873 if (rtm->rtm_flags & RTM_F_CLONED)
874 return 0;
875 if (rtm->rtm_protocol == RTPROT_REDIRECT)
876 return 0;
877 if (rtm->rtm_protocol == RTPROT_KERNEL)
878 return 0;
879
880 if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)
881 return 0;
882
883 if (rtm->rtm_src_len != 0)
884 {
885 zlog_warn ("netlink_route_change(): no src len");
886 return 0;
887 }
paul7021c422003-07-15 12:52:22 +0000888
paul718e3742002-12-13 20:15:29 +0000889 index = 0;
890 dest = NULL;
891 gate = NULL;
892
893 if (tb[RTA_OIF])
894 index = *(int *) RTA_DATA (tb[RTA_OIF]);
895
896 if (tb[RTA_DST])
897 dest = RTA_DATA (tb[RTA_DST]);
898 else
899 dest = anyaddr;
900
901 if (tb[RTA_GATEWAY])
902 gate = RTA_DATA (tb[RTA_GATEWAY]);
903
904 if (rtm->rtm_family == AF_INET)
905 {
906 struct prefix_ipv4 p;
907 p.family = AF_INET;
908 memcpy (&p.prefix, dest, 4);
909 p.prefixlen = rtm->rtm_dst_len;
910
911 if (IS_ZEBRA_DEBUG_KERNEL)
paul7021c422003-07-15 12:52:22 +0000912 {
913 if (h->nlmsg_type == RTM_NEWROUTE)
ajsb6178002004-12-07 21:12:56 +0000914 zlog_debug ("RTM_NEWROUTE %s/%d",
paul7021c422003-07-15 12:52:22 +0000915 inet_ntoa (p.prefix), p.prefixlen);
916 else
ajsb6178002004-12-07 21:12:56 +0000917 zlog_debug ("RTM_DELROUTE %s/%d",
paul7021c422003-07-15 12:52:22 +0000918 inet_ntoa (p.prefix), p.prefixlen);
919 }
paul718e3742002-12-13 20:15:29 +0000920
921 if (h->nlmsg_type == RTM_NEWROUTE)
paul7021c422003-07-15 12:52:22 +0000922 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, 0, 0);
paul718e3742002-12-13 20:15:29 +0000923 else
paul7021c422003-07-15 12:52:22 +0000924 rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table);
paul718e3742002-12-13 20:15:29 +0000925 }
926
927#ifdef HAVE_IPV6
928 if (rtm->rtm_family == AF_INET6)
929 {
930 struct prefix_ipv6 p;
931 char buf[BUFSIZ];
932
933 p.family = AF_INET6;
934 memcpy (&p.prefix, dest, 16);
935 p.prefixlen = rtm->rtm_dst_len;
936
937 if (IS_ZEBRA_DEBUG_KERNEL)
paul7021c422003-07-15 12:52:22 +0000938 {
939 if (h->nlmsg_type == RTM_NEWROUTE)
ajsb6178002004-12-07 21:12:56 +0000940 zlog_debug ("RTM_NEWROUTE %s/%d",
paul7021c422003-07-15 12:52:22 +0000941 inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
942 p.prefixlen);
943 else
ajsb6178002004-12-07 21:12:56 +0000944 zlog_debug ("RTM_DELROUTE %s/%d",
paul7021c422003-07-15 12:52:22 +0000945 inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
946 p.prefixlen);
947 }
paul718e3742002-12-13 20:15:29 +0000948
949 if (h->nlmsg_type == RTM_NEWROUTE)
paul7021c422003-07-15 12:52:22 +0000950 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);
paul718e3742002-12-13 20:15:29 +0000951 else
paul7021c422003-07-15 12:52:22 +0000952 rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);
paul718e3742002-12-13 20:15:29 +0000953 }
954#endif /* HAVE_IPV6 */
955
956 return 0;
957}
958
959int
960netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
961{
962 int len;
963 struct ifinfomsg *ifi;
paul7021c422003-07-15 12:52:22 +0000964 struct rtattr *tb[IFLA_MAX + 1];
paul718e3742002-12-13 20:15:29 +0000965 struct interface *ifp;
966 char *name;
967
968 ifi = NLMSG_DATA (h);
969
paul7021c422003-07-15 12:52:22 +0000970 if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
paul718e3742002-12-13 20:15:29 +0000971 {
972 /* If this is not link add/delete message so print warning. */
973 zlog_warn ("netlink_link_change: wrong kernel message %d\n",
paul7021c422003-07-15 12:52:22 +0000974 h->nlmsg_type);
paul718e3742002-12-13 20:15:29 +0000975 return 0;
976 }
977
978 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
979 if (len < 0)
980 return -1;
981
982 /* Looking up interface name. */
983 memset (tb, 0, sizeof tb);
984 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
paulc15cb242005-01-24 09:05:27 +0000985
paul1e193152005-02-14 23:53:05 +0000986#ifdef IFLA_WIRELESS
paulc15cb242005-01-24 09:05:27 +0000987 /* check for wireless messages to ignore */
988 if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
989 {
990 if (IS_ZEBRA_DEBUG_KERNEL)
991 zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__);
992 return 0;
993 }
paul1e193152005-02-14 23:53:05 +0000994#endif /* IFLA_WIRELESS */
paulc15cb242005-01-24 09:05:27 +0000995
paul718e3742002-12-13 20:15:29 +0000996 if (tb[IFLA_IFNAME] == NULL)
997 return -1;
paul7021c422003-07-15 12:52:22 +0000998 name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
paul718e3742002-12-13 20:15:29 +0000999
1000 /* Add interface. */
1001 if (h->nlmsg_type == RTM_NEWLINK)
1002 {
1003 ifp = if_lookup_by_name (name);
1004
paul7021c422003-07-15 12:52:22 +00001005 if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1006 {
1007 if (ifp == NULL)
1008 ifp = if_get_by_name (name);
paul718e3742002-12-13 20:15:29 +00001009
ajsd2fc8892005-04-02 18:38:43 +00001010 set_ifindex(ifp, ifi->ifi_index);
paul7021c422003-07-15 12:52:22 +00001011 ifp->flags = ifi->ifi_flags & 0x0000fffff;
paul44145db2004-05-09 11:00:23 +00001012 ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
paul7021c422003-07-15 12:52:22 +00001013 ifp->metric = 1;
paul718e3742002-12-13 20:15:29 +00001014
paul7021c422003-07-15 12:52:22 +00001015 /* If new link is added. */
1016 if_add_update (ifp);
1017 }
paul718e3742002-12-13 20:15:29 +00001018 else
paul7021c422003-07-15 12:52:22 +00001019 {
1020 /* Interface status change. */
ajsd2fc8892005-04-02 18:38:43 +00001021 set_ifindex(ifp, ifi->ifi_index);
paul44145db2004-05-09 11:00:23 +00001022 ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
paul7021c422003-07-15 12:52:22 +00001023 ifp->metric = 1;
paul718e3742002-12-13 20:15:29 +00001024
paul7021c422003-07-15 12:52:22 +00001025 if (if_is_operative (ifp))
1026 {
1027 ifp->flags = ifi->ifi_flags & 0x0000fffff;
1028 if (!if_is_operative (ifp))
1029 if_down (ifp);
ajsa608bbf2005-03-29 17:03:49 +00001030 else
1031 /* Must notify client daemons of new interface status. */
1032 zebra_interface_up_update (ifp);
paul7021c422003-07-15 12:52:22 +00001033 }
1034 else
1035 {
1036 ifp->flags = ifi->ifi_flags & 0x0000fffff;
1037 if (if_is_operative (ifp))
1038 if_up (ifp);
1039 }
1040 }
paul718e3742002-12-13 20:15:29 +00001041 }
1042 else
1043 {
1044 /* RTM_DELLINK. */
1045 ifp = if_lookup_by_name (name);
1046
1047 if (ifp == NULL)
paul7021c422003-07-15 12:52:22 +00001048 {
1049 zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find",
paul718e3742002-12-13 20:15:29 +00001050 name);
paul7021c422003-07-15 12:52:22 +00001051 return 0;
1052 }
1053
paul718e3742002-12-13 20:15:29 +00001054 if_delete_update (ifp);
1055 }
1056
1057 return 0;
1058}
1059
1060int
1061netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h)
1062{
1063 switch (h->nlmsg_type)
1064 {
1065 case RTM_NEWROUTE:
1066 return netlink_route_change (snl, h);
1067 break;
1068 case RTM_DELROUTE:
1069 return netlink_route_change (snl, h);
1070 break;
1071 case RTM_NEWLINK:
1072 return netlink_link_change (snl, h);
1073 break;
1074 case RTM_DELLINK:
1075 return netlink_link_change (snl, h);
1076 break;
1077 case RTM_NEWADDR:
1078 return netlink_interface_addr (snl, h);
1079 break;
1080 case RTM_DELADDR:
1081 return netlink_interface_addr (snl, h);
1082 break;
1083 default:
1084 zlog_warn ("Unknown netlink nlmsg_type %d\n", h->nlmsg_type);
1085 break;
1086 }
1087 return 0;
1088}
1089
1090/* Interface lookup by netlink socket. */
1091int
1092interface_lookup_netlink ()
1093{
1094 int ret;
paul5f37d862003-04-19 00:11:28 +00001095 int flags;
1096 int snb_ret;
paul7021c422003-07-15 12:52:22 +00001097
paul5f37d862003-04-19 00:11:28 +00001098 /*
1099 * Change netlink socket flags to blocking to ensure we get
1100 * a reply via nelink_parse_info
paul7021c422003-07-15 12:52:22 +00001101 */
1102 snb_ret = set_netlink_blocking (&netlink_cmd, &flags);
1103 if (snb_ret < 0)
1104 zlog (NULL, LOG_WARNING,
1105 "%s:%i Warning: Could not set netlink socket to blocking.",
1106 __FUNCTION__, __LINE__);
1107
paul718e3742002-12-13 20:15:29 +00001108 /* Get interface information. */
1109 ret = netlink_request (AF_PACKET, RTM_GETLINK, &netlink_cmd);
1110 if (ret < 0)
1111 return ret;
1112 ret = netlink_parse_info (netlink_interface, &netlink_cmd);
1113 if (ret < 0)
1114 return ret;
1115
1116 /* Get IPv4 address of the interfaces. */
1117 ret = netlink_request (AF_INET, RTM_GETADDR, &netlink_cmd);
1118 if (ret < 0)
1119 return ret;
1120 ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
1121 if (ret < 0)
1122 return ret;
1123
1124#ifdef HAVE_IPV6
1125 /* Get IPv6 address of the interfaces. */
1126 ret = netlink_request (AF_INET6, RTM_GETADDR, &netlink_cmd);
1127 if (ret < 0)
1128 return ret;
1129 ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
1130 if (ret < 0)
1131 return ret;
1132#endif /* HAVE_IPV6 */
1133
paul7021c422003-07-15 12:52:22 +00001134 /* restore socket flags */
1135 if (snb_ret == 0)
1136 set_netlink_nonblocking (&netlink_cmd, &flags);
paul718e3742002-12-13 20:15:29 +00001137 return 0;
1138}
1139
1140/* Routing table read function using netlink interface. Only called
1141 bootstrap time. */
1142int
1143netlink_route_read ()
1144{
1145 int ret;
paul5f37d862003-04-19 00:11:28 +00001146 int flags;
1147 int snb_ret;
paul7021c422003-07-15 12:52:22 +00001148
paul5f37d862003-04-19 00:11:28 +00001149 /*
1150 * Change netlink socket flags to blocking to ensure we get
1151 * a reply via nelink_parse_info
paul7021c422003-07-15 12:52:22 +00001152 */
1153 snb_ret = set_netlink_blocking (&netlink_cmd, &flags);
1154 if (snb_ret < 0)
1155 zlog (NULL, LOG_WARNING,
1156 "%s:%i Warning: Could not set netlink socket to blocking.",
1157 __FUNCTION__, __LINE__);
1158
paul718e3742002-12-13 20:15:29 +00001159 /* Get IPv4 routing table. */
1160 ret = netlink_request (AF_INET, RTM_GETROUTE, &netlink_cmd);
1161 if (ret < 0)
1162 return ret;
1163 ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
1164 if (ret < 0)
1165 return ret;
1166
1167#ifdef HAVE_IPV6
1168 /* Get IPv6 routing table. */
1169 ret = netlink_request (AF_INET6, RTM_GETROUTE, &netlink_cmd);
1170 if (ret < 0)
1171 return ret;
1172 ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
1173 if (ret < 0)
1174 return ret;
1175#endif /* HAVE_IPV6 */
1176
paul5f37d862003-04-19 00:11:28 +00001177 /* restore flags */
paul7021c422003-07-15 12:52:22 +00001178 if (snb_ret == 0)
1179 set_netlink_nonblocking (&netlink_cmd, &flags);
paul718e3742002-12-13 20:15:29 +00001180 return 0;
1181}
1182
1183/* Utility function comes from iproute2.
1184 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
1185int
1186addattr_l (struct nlmsghdr *n, int maxlen, int type, void *data, int alen)
1187{
1188 int len;
1189 struct rtattr *rta;
1190
paul7021c422003-07-15 12:52:22 +00001191 len = RTA_LENGTH (alen);
paul718e3742002-12-13 20:15:29 +00001192
paul7021c422003-07-15 12:52:22 +00001193 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
paul718e3742002-12-13 20:15:29 +00001194 return -1;
1195
paul7021c422003-07-15 12:52:22 +00001196 rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
paul718e3742002-12-13 20:15:29 +00001197 rta->rta_type = type;
1198 rta->rta_len = len;
paul7021c422003-07-15 12:52:22 +00001199 memcpy (RTA_DATA (rta), data, alen);
paul718e3742002-12-13 20:15:29 +00001200 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1201
1202 return 0;
1203}
1204
1205int
1206rta_addattr_l (struct rtattr *rta, int maxlen, int type, void *data, int alen)
1207{
1208 int len;
1209 struct rtattr *subrta;
1210
paul7021c422003-07-15 12:52:22 +00001211 len = RTA_LENGTH (alen);
paul718e3742002-12-13 20:15:29 +00001212
paul7021c422003-07-15 12:52:22 +00001213 if (RTA_ALIGN (rta->rta_len) + len > maxlen)
paul718e3742002-12-13 20:15:29 +00001214 return -1;
1215
paul7021c422003-07-15 12:52:22 +00001216 subrta = (struct rtattr *) (((char *) rta) + RTA_ALIGN (rta->rta_len));
paul718e3742002-12-13 20:15:29 +00001217 subrta->rta_type = type;
1218 subrta->rta_len = len;
paul7021c422003-07-15 12:52:22 +00001219 memcpy (RTA_DATA (subrta), data, alen);
paul718e3742002-12-13 20:15:29 +00001220 rta->rta_len = NLMSG_ALIGN (rta->rta_len) + len;
1221
1222 return 0;
1223}
1224
1225/* Utility function comes from iproute2.
1226 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
1227int
1228addattr32 (struct nlmsghdr *n, int maxlen, int type, int data)
1229{
1230 int len;
1231 struct rtattr *rta;
paul7021c422003-07-15 12:52:22 +00001232
1233 len = RTA_LENGTH (4);
1234
paul718e3742002-12-13 20:15:29 +00001235 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
1236 return -1;
1237
paul7021c422003-07-15 12:52:22 +00001238 rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
paul718e3742002-12-13 20:15:29 +00001239 rta->rta_type = type;
1240 rta->rta_len = len;
paul7021c422003-07-15 12:52:22 +00001241 memcpy (RTA_DATA (rta), &data, 4);
paul718e3742002-12-13 20:15:29 +00001242 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1243
1244 return 0;
1245}
1246
1247static int
1248netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h)
1249{
hassob7ed1ec2005-03-31 20:13:49 +00001250 zlog_warn ("netlink_talk: ignoring message type 0x%04x", h->nlmsg_type);
paul718e3742002-12-13 20:15:29 +00001251 return 0;
1252}
1253
1254/* sendmsg() to netlink socket then recvmsg(). */
1255int
1256netlink_talk (struct nlmsghdr *n, struct nlsock *nl)
1257{
1258 int status;
1259 struct sockaddr_nl snl;
paul7021c422003-07-15 12:52:22 +00001260 struct iovec iov = { (void *) n, n->nlmsg_len };
1261 struct msghdr msg = { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 };
paul718e3742002-12-13 20:15:29 +00001262 int flags = 0;
paul5f37d862003-04-19 00:11:28 +00001263 int snb_ret;
ajs4be019d2005-01-29 16:12:41 +00001264 int save_errno;
paul7021c422003-07-15 12:52:22 +00001265
paul718e3742002-12-13 20:15:29 +00001266 memset (&snl, 0, sizeof snl);
1267 snl.nl_family = AF_NETLINK;
paul7021c422003-07-15 12:52:22 +00001268
hassob7ed1ec2005-03-31 20:13:49 +00001269 n->nlmsg_seq = ++nl->seq;
paul718e3742002-12-13 20:15:29 +00001270
1271 /* Request an acknowledgement by setting NLM_F_ACK */
1272 n->nlmsg_flags |= NLM_F_ACK;
paul7021c422003-07-15 12:52:22 +00001273
1274 if (IS_ZEBRA_DEBUG_KERNEL)
hassob7ed1ec2005-03-31 20:13:49 +00001275 zlog_debug ("netlink_talk: %s type %s(%u), seq=%u", nl->name,
paul7021c422003-07-15 12:52:22 +00001276 lookup (nlmsg_str, n->nlmsg_type), n->nlmsg_type,
1277 n->nlmsg_seq);
paul718e3742002-12-13 20:15:29 +00001278
1279 /* Send message to netlink interface. */
paul7021c422003-07-15 12:52:22 +00001280 if (zserv_privs.change (ZPRIVS_RAISE))
1281 zlog (NULL, LOG_ERR, "Can't raise privileges");
paul718e3742002-12-13 20:15:29 +00001282 status = sendmsg (nl->sock, &msg, 0);
ajs4be019d2005-01-29 16:12:41 +00001283 save_errno = errno;
paul7021c422003-07-15 12:52:22 +00001284 if (zserv_privs.change (ZPRIVS_LOWER))
1285 zlog (NULL, LOG_ERR, "Can't lower privileges");
1286
paul718e3742002-12-13 20:15:29 +00001287 if (status < 0)
1288 {
1289 zlog (NULL, LOG_ERR, "netlink_talk sendmsg() error: %s",
ajs4be019d2005-01-29 16:12:41 +00001290 safe_strerror (save_errno));
paul718e3742002-12-13 20:15:29 +00001291 return -1;
1292 }
paul7021c422003-07-15 12:52:22 +00001293
paul718e3742002-12-13 20:15:29 +00001294 /*
1295 * Change socket flags for blocking I/O.
1296 * This ensures we wait for a reply in netlink_parse_info().
1297 */
paul7021c422003-07-15 12:52:22 +00001298 snb_ret = set_netlink_blocking (nl, &flags);
1299 if (snb_ret < 0)
1300 zlog (NULL, LOG_WARNING,
1301 "%s:%i Warning: Could not set netlink socket to blocking.",
1302 __FUNCTION__, __LINE__);
paul718e3742002-12-13 20:15:29 +00001303
1304 /*
1305 * Get reply from netlink socket.
1306 * The reply should either be an acknowlegement or an error.
1307 */
1308 status = netlink_parse_info (netlink_talk_filter, nl);
paul7021c422003-07-15 12:52:22 +00001309
paul718e3742002-12-13 20:15:29 +00001310 /* Restore socket flags for nonblocking I/O */
paul7021c422003-07-15 12:52:22 +00001311 if (snb_ret == 0)
1312 set_netlink_nonblocking (nl, &flags);
1313
paul718e3742002-12-13 20:15:29 +00001314 return status;
1315}
1316
1317/* Routing table change via netlink interface. */
1318int
1319netlink_route (int cmd, int family, void *dest, int length, void *gate,
paul7021c422003-07-15 12:52:22 +00001320 int index, int zebra_flags, int table)
paul718e3742002-12-13 20:15:29 +00001321{
1322 int ret;
1323 int bytelen;
1324 struct sockaddr_nl snl;
1325 int discard;
1326
paul7021c422003-07-15 12:52:22 +00001327 struct
paul718e3742002-12-13 20:15:29 +00001328 {
1329 struct nlmsghdr n;
1330 struct rtmsg r;
1331 char buf[1024];
1332 } req;
1333
1334 memset (&req, 0, sizeof req);
1335
1336 bytelen = (family == AF_INET ? 4 : 16);
1337
1338 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1339 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1340 req.n.nlmsg_type = cmd;
1341 req.r.rtm_family = family;
1342 req.r.rtm_table = table;
1343 req.r.rtm_dst_len = length;
1344
hasso81dfcaa2003-05-25 19:21:25 +00001345 if ((zebra_flags & ZEBRA_FLAG_BLACKHOLE)
1346 || (zebra_flags & ZEBRA_FLAG_REJECT))
paul718e3742002-12-13 20:15:29 +00001347 discard = 1;
1348 else
1349 discard = 0;
1350
paul7021c422003-07-15 12:52:22 +00001351 if (cmd == RTM_NEWROUTE)
paul718e3742002-12-13 20:15:29 +00001352 {
1353 req.r.rtm_protocol = RTPROT_ZEBRA;
1354 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1355
paul7021c422003-07-15 12:52:22 +00001356 if (discard)
paul595db7f2003-05-25 21:35:06 +00001357 {
1358 if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
1359 req.r.rtm_type = RTN_BLACKHOLE;
1360 else if (zebra_flags & ZEBRA_FLAG_REJECT)
1361 req.r.rtm_type = RTN_UNREACHABLE;
paul7021c422003-07-15 12:52:22 +00001362 else
1363 assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
1364 }
paul595db7f2003-05-25 21:35:06 +00001365 else
paul7021c422003-07-15 12:52:22 +00001366 req.r.rtm_type = RTN_UNICAST;
paul718e3742002-12-13 20:15:29 +00001367 }
1368
1369 if (dest)
1370 addattr_l (&req.n, sizeof req, RTA_DST, dest, bytelen);
1371
paul7021c422003-07-15 12:52:22 +00001372 if (!discard)
paul718e3742002-12-13 20:15:29 +00001373 {
1374 if (gate)
paul7021c422003-07-15 12:52:22 +00001375 addattr_l (&req.n, sizeof req, RTA_GATEWAY, gate, bytelen);
paul718e3742002-12-13 20:15:29 +00001376 if (index > 0)
paul7021c422003-07-15 12:52:22 +00001377 addattr32 (&req.n, sizeof req, RTA_OIF, index);
paul718e3742002-12-13 20:15:29 +00001378 }
1379
1380 /* Destination netlink address. */
1381 memset (&snl, 0, sizeof snl);
1382 snl.nl_family = AF_NETLINK;
1383
1384 /* Talk to netlink socket. */
hassob7ed1ec2005-03-31 20:13:49 +00001385 ret = netlink_talk (&req.n, &netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001386 if (ret < 0)
1387 return -1;
1388
1389 return 0;
1390}
1391
1392/* Routing table change via netlink interface. */
1393int
1394netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
paul7021c422003-07-15 12:52:22 +00001395 int family)
paul718e3742002-12-13 20:15:29 +00001396{
1397 int bytelen;
1398 struct sockaddr_nl snl;
1399 struct nexthop *nexthop = NULL;
1400 int nexthop_num = 0;
paul718e3742002-12-13 20:15:29 +00001401 int discard;
1402
paul7021c422003-07-15 12:52:22 +00001403 struct
paul718e3742002-12-13 20:15:29 +00001404 {
1405 struct nlmsghdr n;
1406 struct rtmsg r;
1407 char buf[1024];
1408 } req;
1409
1410 memset (&req, 0, sizeof req);
1411
1412 bytelen = (family == AF_INET ? 4 : 16);
1413
1414 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1415 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1416 req.n.nlmsg_type = cmd;
1417 req.r.rtm_family = family;
1418 req.r.rtm_table = rib->table;
1419 req.r.rtm_dst_len = p->prefixlen;
1420
paul7021c422003-07-15 12:52:22 +00001421 if ((rib->flags & ZEBRA_FLAG_BLACKHOLE) || (rib->flags & ZEBRA_FLAG_REJECT))
paul718e3742002-12-13 20:15:29 +00001422 discard = 1;
1423 else
1424 discard = 0;
1425
paul7021c422003-07-15 12:52:22 +00001426 if (cmd == RTM_NEWROUTE)
paul718e3742002-12-13 20:15:29 +00001427 {
1428 req.r.rtm_protocol = RTPROT_ZEBRA;
1429 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1430
paul7021c422003-07-15 12:52:22 +00001431 if (discard)
paul595db7f2003-05-25 21:35:06 +00001432 {
1433 if (rib->flags & ZEBRA_FLAG_BLACKHOLE)
1434 req.r.rtm_type = RTN_BLACKHOLE;
1435 else if (rib->flags & ZEBRA_FLAG_REJECT)
1436 req.r.rtm_type = RTN_UNREACHABLE;
paul7021c422003-07-15 12:52:22 +00001437 else
1438 assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
1439 }
paul595db7f2003-05-25 21:35:06 +00001440 else
paul7021c422003-07-15 12:52:22 +00001441 req.r.rtm_type = RTN_UNICAST;
paul718e3742002-12-13 20:15:29 +00001442 }
1443
1444 addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
1445
1446 /* Metric. */
1447 addattr32 (&req.n, sizeof req, RTA_PRIORITY, rib->metric);
1448
1449 if (discard)
1450 {
1451 if (cmd == RTM_NEWROUTE)
paul7021c422003-07-15 12:52:22 +00001452 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1453 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
paul718e3742002-12-13 20:15:29 +00001454 goto skip;
1455 }
1456
1457 /* Multipath case. */
1458 if (rib->nexthop_active_num == 1 || MULTIPATH_NUM == 1)
1459 {
1460 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
paul7021c422003-07-15 12:52:22 +00001461 {
paul5ec90d22003-06-19 01:41:37 +00001462
paul7021c422003-07-15 12:52:22 +00001463 if ((cmd == RTM_NEWROUTE
1464 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1465 || (cmd == RTM_DELROUTE
1466 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1467 {
paul5ec90d22003-06-19 01:41:37 +00001468
paul7021c422003-07-15 12:52:22 +00001469 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1470 {
1471 if (IS_ZEBRA_DEBUG_KERNEL)
1472 {
ajsb6178002004-12-07 21:12:56 +00001473 zlog_debug
paul7021c422003-07-15 12:52:22 +00001474 ("netlink_route_multipath() (recursive, 1 hop): "
1475 "%s %s/%d via %s if %u, type %s",
1476 lookup (nlmsg_str, cmd), inet_ntoa (p->u.prefix4),
1477 p->prefixlen, inet_ntoa (nexthop->rgate.ipv4),
1478 nexthop->rifindex,
1479 nexthop_types_desc[nexthop->rtype]);
1480 }
paul5ec90d22003-06-19 01:41:37 +00001481
paul7021c422003-07-15 12:52:22 +00001482 if (nexthop->rtype == NEXTHOP_TYPE_IPV4
1483 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
1484 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1485 &nexthop->rgate.ipv4, bytelen);
paul718e3742002-12-13 20:15:29 +00001486#ifdef HAVE_IPV6
paul7021c422003-07-15 12:52:22 +00001487 if (nexthop->rtype == NEXTHOP_TYPE_IPV6
1488 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1489 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1490 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1491 &nexthop->rgate.ipv6, bytelen);
paul718e3742002-12-13 20:15:29 +00001492#endif /* HAVE_IPV6 */
paul7021c422003-07-15 12:52:22 +00001493 if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
1494 || nexthop->rtype == NEXTHOP_TYPE_IFNAME
1495 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
1496 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1497 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1498 addattr32 (&req.n, sizeof req, RTA_OIF,
1499 nexthop->rifindex);
1500 }
1501 else
1502 {
1503 if (IS_ZEBRA_DEBUG_KERNEL)
1504 {
ajsb6178002004-12-07 21:12:56 +00001505 zlog_debug
paul7021c422003-07-15 12:52:22 +00001506 ("netlink_route_multipath(): (single hop)"
1507 "%s %s/%d via %s if %u, type %s",
1508 lookup (nlmsg_str, cmd), inet_ntoa (p->u.prefix4),
1509 p->prefixlen, inet_ntoa (nexthop->gate.ipv4),
1510 nexthop->ifindex,
1511 nexthop_types_desc[nexthop->type]);
1512 }
paul5ec90d22003-06-19 01:41:37 +00001513
paul7021c422003-07-15 12:52:22 +00001514 if (nexthop->type == NEXTHOP_TYPE_IPV4
1515 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1516 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1517 &nexthop->gate.ipv4, bytelen);
paul718e3742002-12-13 20:15:29 +00001518#ifdef HAVE_IPV6
paul7021c422003-07-15 12:52:22 +00001519 if (nexthop->type == NEXTHOP_TYPE_IPV6
1520 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1521 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1522 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1523 &nexthop->gate.ipv6, bytelen);
paul718e3742002-12-13 20:15:29 +00001524#endif /* HAVE_IPV6 */
paul7021c422003-07-15 12:52:22 +00001525 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1526 || nexthop->type == NEXTHOP_TYPE_IFNAME
1527 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1528 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
1529 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
1530 addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->ifindex);
1531 }
paul718e3742002-12-13 20:15:29 +00001532
paul7021c422003-07-15 12:52:22 +00001533 if (cmd == RTM_NEWROUTE)
1534 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
paul718e3742002-12-13 20:15:29 +00001535
paul7021c422003-07-15 12:52:22 +00001536 nexthop_num++;
1537 break;
1538 }
1539 }
paul718e3742002-12-13 20:15:29 +00001540 }
1541 else
1542 {
1543 char buf[1024];
1544 struct rtattr *rta = (void *) buf;
1545 struct rtnexthop *rtnh;
1546
1547 rta->rta_type = RTA_MULTIPATH;
paul7021c422003-07-15 12:52:22 +00001548 rta->rta_len = RTA_LENGTH (0);
1549 rtnh = RTA_DATA (rta);
paul718e3742002-12-13 20:15:29 +00001550
1551 nexthop_num = 0;
1552 for (nexthop = rib->nexthop;
paul7021c422003-07-15 12:52:22 +00001553 nexthop && (MULTIPATH_NUM == 0 || nexthop_num < MULTIPATH_NUM);
1554 nexthop = nexthop->next)
1555 {
1556 if ((cmd == RTM_NEWROUTE
1557 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1558 || (cmd == RTM_DELROUTE
1559 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1560 {
1561 nexthop_num++;
paul718e3742002-12-13 20:15:29 +00001562
paul7021c422003-07-15 12:52:22 +00001563 rtnh->rtnh_len = sizeof (*rtnh);
1564 rtnh->rtnh_flags = 0;
1565 rtnh->rtnh_hops = 0;
1566 rta->rta_len += rtnh->rtnh_len;
paul718e3742002-12-13 20:15:29 +00001567
paul7021c422003-07-15 12:52:22 +00001568 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1569 {
1570 if (IS_ZEBRA_DEBUG_KERNEL)
1571 {
ajsb6178002004-12-07 21:12:56 +00001572 zlog_debug ("netlink_route_multipath() "
paul7021c422003-07-15 12:52:22 +00001573 "(recursive, multihop): "
1574 "%s %s/%d via %s if %u, type %s",
1575 lookup (nlmsg_str, cmd), inet_ntoa (p->u.prefix4),
1576 p->prefixlen, inet_ntoa (nexthop->rgate.ipv4),
1577 nexthop->rifindex,
1578 nexthop_types_desc[nexthop->type]);
1579 }
1580 if (nexthop->rtype == NEXTHOP_TYPE_IPV4
1581 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
1582 {
1583 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1584 &nexthop->rgate.ipv4, bytelen);
1585 rtnh->rtnh_len += sizeof (struct rtattr) + 4;
1586 }
paul718e3742002-12-13 20:15:29 +00001587#ifdef HAVE_IPV6
paul7021c422003-07-15 12:52:22 +00001588 if (nexthop->rtype == NEXTHOP_TYPE_IPV6
1589 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME
1590 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX)
1591 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1592 &nexthop->rgate.ipv6, bytelen);
paul718e3742002-12-13 20:15:29 +00001593#endif /* HAVE_IPV6 */
paul7021c422003-07-15 12:52:22 +00001594 /* ifindex */
1595 if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
1596 || nexthop->rtype == NEXTHOP_TYPE_IFNAME
1597 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
1598 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1599 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1600 rtnh->rtnh_ifindex = nexthop->rifindex;
1601 else
1602 rtnh->rtnh_ifindex = 0;
1603 }
1604 else
1605 {
1606 if (IS_ZEBRA_DEBUG_KERNEL)
1607 {
ajsb6178002004-12-07 21:12:56 +00001608 zlog_debug ("netlink_route_multipath() "
paul7021c422003-07-15 12:52:22 +00001609 "(multihop): "
1610 "%s %s/%d via %s if %u, type %s",
1611 lookup (nlmsg_str, cmd), inet_ntoa (p->u.prefix4),
1612 p->prefixlen, inet_ntoa (nexthop->rgate.ipv4),
1613 nexthop->rifindex,
1614 nexthop_types_desc[nexthop->type]);
1615 }
1616 if (nexthop->type == NEXTHOP_TYPE_IPV4
1617 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1618 {
1619 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1620 &nexthop->gate.ipv4, bytelen);
1621 rtnh->rtnh_len += sizeof (struct rtattr) + 4;
1622 }
paul718e3742002-12-13 20:15:29 +00001623#ifdef HAVE_IPV6
paul7021c422003-07-15 12:52:22 +00001624 if (nexthop->type == NEXTHOP_TYPE_IPV6
1625 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1626 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1627 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1628 &nexthop->gate.ipv6, bytelen);
paul718e3742002-12-13 20:15:29 +00001629#endif /* HAVE_IPV6 */
paul7021c422003-07-15 12:52:22 +00001630 /* ifindex */
1631 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1632 || nexthop->type == NEXTHOP_TYPE_IFNAME
1633 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1634 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1635 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1636 rtnh->rtnh_ifindex = nexthop->ifindex;
1637 else
1638 rtnh->rtnh_ifindex = 0;
1639 }
1640 rtnh = RTNH_NEXT (rtnh);
paul718e3742002-12-13 20:15:29 +00001641
paul7021c422003-07-15 12:52:22 +00001642 if (cmd == RTM_NEWROUTE)
1643 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1644 }
1645 }
paul718e3742002-12-13 20:15:29 +00001646
1647 if (rta->rta_len > RTA_LENGTH (0))
paul7021c422003-07-15 12:52:22 +00001648 addattr_l (&req.n, 1024, RTA_MULTIPATH, RTA_DATA (rta),
1649 RTA_PAYLOAD (rta));
paul718e3742002-12-13 20:15:29 +00001650 }
1651
1652 /* If there is no useful nexthop then return. */
1653 if (nexthop_num == 0)
1654 {
1655 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +00001656 zlog_debug ("netlink_route_multipath(): No useful nexthop.");
paul718e3742002-12-13 20:15:29 +00001657 return 0;
1658 }
1659
paul7021c422003-07-15 12:52:22 +00001660skip:
paul718e3742002-12-13 20:15:29 +00001661
1662 /* Destination netlink address. */
1663 memset (&snl, 0, sizeof snl);
1664 snl.nl_family = AF_NETLINK;
1665
paul718e3742002-12-13 20:15:29 +00001666 /* Talk to netlink socket. */
hassob7ed1ec2005-03-31 20:13:49 +00001667 return netlink_talk (&req.n, &netlink_cmd);
paul718e3742002-12-13 20:15:29 +00001668}
1669
1670int
1671kernel_add_ipv4 (struct prefix *p, struct rib *rib)
1672{
1673 return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET);
1674}
1675
1676int
1677kernel_delete_ipv4 (struct prefix *p, struct rib *rib)
1678{
1679 return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET);
1680}
1681
1682#ifdef HAVE_IPV6
1683int
1684kernel_add_ipv6 (struct prefix *p, struct rib *rib)
1685{
1686 return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET6);
1687}
1688
1689int
1690kernel_delete_ipv6 (struct prefix *p, struct rib *rib)
1691{
1692 return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET6);
1693}
1694
1695/* Delete IPv6 route from the kernel. */
1696int
1697kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate,
paul7021c422003-07-15 12:52:22 +00001698 int index, int flags, int table)
paul718e3742002-12-13 20:15:29 +00001699{
paul7021c422003-07-15 12:52:22 +00001700 return netlink_route (RTM_DELROUTE, AF_INET6, &dest->prefix,
1701 dest->prefixlen, gate, index, flags, table);
paul718e3742002-12-13 20:15:29 +00001702}
1703#endif /* HAVE_IPV6 */
1704
1705/* Interface address modification. */
1706int
1707netlink_address (int cmd, int family, struct interface *ifp,
paul7021c422003-07-15 12:52:22 +00001708 struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001709{
1710 int bytelen;
1711 struct prefix *p;
1712
paul7021c422003-07-15 12:52:22 +00001713 struct
paul718e3742002-12-13 20:15:29 +00001714 {
1715 struct nlmsghdr n;
1716 struct ifaddrmsg ifa;
1717 char buf[1024];
1718 } req;
1719
1720 p = ifc->address;
1721 memset (&req, 0, sizeof req);
1722
1723 bytelen = (family == AF_INET ? 4 : 16);
1724
paul7021c422003-07-15 12:52:22 +00001725 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg));
paul718e3742002-12-13 20:15:29 +00001726 req.n.nlmsg_flags = NLM_F_REQUEST;
1727 req.n.nlmsg_type = cmd;
1728 req.ifa.ifa_family = family;
1729
1730 req.ifa.ifa_index = ifp->ifindex;
1731 req.ifa.ifa_prefixlen = p->prefixlen;
1732
1733 addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen);
1734
1735 if (family == AF_INET && cmd == RTM_NEWADDR)
1736 {
1737 if (if_is_broadcast (ifp) && ifc->destination)
paul7021c422003-07-15 12:52:22 +00001738 {
1739 p = ifc->destination;
1740 addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix,
1741 bytelen);
1742 }
paul718e3742002-12-13 20:15:29 +00001743 }
1744
1745 if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
1746 SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY);
paul7021c422003-07-15 12:52:22 +00001747
paul718e3742002-12-13 20:15:29 +00001748 if (ifc->label)
1749 addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label,
paul7021c422003-07-15 12:52:22 +00001750 strlen (ifc->label) + 1);
paul718e3742002-12-13 20:15:29 +00001751
1752 return netlink_talk (&req.n, &netlink_cmd);
1753}
1754
1755int
1756kernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc)
1757{
1758 return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc);
1759}
1760
1761int
1762kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc)
1763{
1764 return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc);
1765}
1766
paul718e3742002-12-13 20:15:29 +00001767
1768extern struct thread_master *master;
1769
1770/* Kernel route reflection. */
1771int
1772kernel_read (struct thread *thread)
1773{
1774 int ret;
1775 int sock;
1776
1777 sock = THREAD_FD (thread);
1778 ret = netlink_parse_info (netlink_information_fetch, &netlink);
paulb21b19c2003-06-15 01:28:29 +00001779 thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock);
paul718e3742002-12-13 20:15:29 +00001780
1781 return 0;
1782}
1783
1784/* Exported interface function. This function simply calls
1785 netlink_socket (). */
1786void
1787kernel_init ()
1788{
1789 unsigned long groups;
1790
paul7021c422003-07-15 12:52:22 +00001791 groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR;
paul718e3742002-12-13 20:15:29 +00001792#ifdef HAVE_IPV6
paul7021c422003-07-15 12:52:22 +00001793 groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR;
paul718e3742002-12-13 20:15:29 +00001794#endif /* HAVE_IPV6 */
1795 netlink_socket (&netlink, groups);
1796 netlink_socket (&netlink_cmd, 0);
1797
1798 /* Register kernel socket. */
1799 if (netlink.sock > 0)
paulb21b19c2003-06-15 01:28:29 +00001800 thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock);
paul718e3742002-12-13 20:15:29 +00001801}