blob: e151462350a748bc27fffd1374c9f5e14f5abc24 [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;
50 char *name;
51} 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 */
54
55struct message nlmsg_str[] =
56{
57 {RTM_NEWROUTE, "RTM_NEWROUTE"},
58 {RTM_DELROUTE, "RTM_DELROUTE"},
59 {RTM_GETROUTE, "RTM_GETROUTE"},
60 {RTM_NEWLINK, "RTM_NEWLINK"},
61 {RTM_DELLINK, "RTM_DELLINK"},
62 {RTM_GETLINK, "RTM_GETLINK"},
63 {RTM_NEWADDR, "RTM_NEWADDR"},
64 {RTM_DELADDR, "RTM_DELADDR"},
65 {RTM_GETADDR, "RTM_GETADDR"},
66 {0, NULL}
67};
68
69extern int rtm_table_default;
70
pauledd7c242003-06-04 13:59:38 +000071extern struct zebra_privs_t zserv_privs;
72
paul718e3742002-12-13 20:15:29 +000073/* Make socket for Linux netlink interface. */
74static int
75netlink_socket (struct nlsock *nl, unsigned long groups)
76{
77 int ret;
78 struct sockaddr_nl snl;
79 int sock;
80 int namelen;
81
82 sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
83 if (sock < 0)
84 {
85 zlog (NULL, LOG_ERR, "Can't open %s socket: %s", nl->name,
86 strerror (errno));
87 return -1;
88 }
89
90 ret = fcntl (sock, F_SETFL, O_NONBLOCK);
91 if (ret < 0)
92 {
93 zlog (NULL, LOG_ERR, "Can't set %s socket flags: %s", nl->name,
94 strerror (errno));
95 close (sock);
96 return -1;
97 }
98
99 memset (&snl, 0, sizeof snl);
100 snl.nl_family = AF_NETLINK;
101 snl.nl_groups = groups;
102
103 /* Bind the socket to the netlink structure for anything. */
pauledd7c242003-06-04 13:59:38 +0000104 if ( zserv_privs.change(ZPRIVS_RAISE) )
105 {
106 zlog (NULL, LOG_ERR, "Can't raise privileges");
107 return -1;
108 }
109
paul718e3742002-12-13 20:15:29 +0000110 ret = bind (sock, (struct sockaddr *) &snl, sizeof snl);
111 if (ret < 0)
112 {
pauledd7c242003-06-04 13:59:38 +0000113 if ( zserv_privs.change(ZPRIVS_LOWER) )
114 zlog (NULL, LOG_ERR, "Can't lower privileges");
paul718e3742002-12-13 20:15:29 +0000115 zlog (NULL, LOG_ERR, "Can't bind %s socket to group 0x%x: %s",
116 nl->name, snl.nl_groups, strerror (errno));
117 close (sock);
118 return -1;
119 }
pauledd7c242003-06-04 13:59:38 +0000120
121 if ( zserv_privs.change(ZPRIVS_LOWER) )
122 zlog (NULL, LOG_ERR, "Can't lower privileges");
paul718e3742002-12-13 20:15:29 +0000123
124 /* multiple netlink sockets will have different nl_pid */
125 namelen = sizeof snl;
126 ret = getsockname (sock, (struct sockaddr *) &snl, &namelen);
127 if (ret < 0 || namelen != sizeof snl)
128 {
129 zlog (NULL, LOG_ERR, "Can't get %s socket name: %s", nl->name,
130 strerror (errno));
131 close (sock);
132 return -1;
133 }
134
135 nl->snl = snl;
136 nl->sock = sock;
137 return ret;
138}
139
paul5f37d862003-04-19 00:11:28 +0000140int set_netlink_blocking(struct nlsock *nl, int *flags)
141{
142
143 /* Change socket flags for blocking I/O. */
144 if((*flags = fcntl(nl->sock, F_GETFL, 0)) < 0)
145 {
146 zlog (NULL, LOG_ERR, "%s:%i F_GETFL error: %s",
147 __FUNCTION__, __LINE__, strerror (errno));
148 return -1;
149 }
150 *flags &= ~O_NONBLOCK;
151 if(fcntl(nl->sock, F_SETFL, *flags) < 0)
152 {
153 zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",
154 __FUNCTION__, __LINE__, strerror (errno));
155 return -1;
156 }
157 return 0;
158}
159
160int set_netlink_nonblocking(struct nlsock *nl, int *flags)
161{
162 /* Restore socket flags for nonblocking I/O */
163 *flags |= O_NONBLOCK;
164 if(fcntl(nl->sock, F_SETFL, *flags) < 0)
165 {
166 zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",
167 __FUNCTION__, __LINE__, strerror (errno));
168 return -1;
169 }
170 return 0;
171}
172
paul718e3742002-12-13 20:15:29 +0000173/* Get type specified information from netlink. */
174static int
175netlink_request (int family, int type, struct nlsock *nl)
176{
177 int ret;
178 struct sockaddr_nl snl;
179
180 struct
181 {
182 struct nlmsghdr nlh;
183 struct rtgenmsg g;
184 } req;
185
186
187 /* Check netlink socket. */
188 if (nl->sock < 0)
189 {
190 zlog (NULL, LOG_ERR, "%s socket isn't active.", nl->name);
191 return -1;
192 }
193
194 memset (&snl, 0, sizeof snl);
195 snl.nl_family = AF_NETLINK;
196
197 req.nlh.nlmsg_len = sizeof req;
198 req.nlh.nlmsg_type = type;
199 req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
200 req.nlh.nlmsg_pid = 0;
201 req.nlh.nlmsg_seq = ++nl->seq;
202 req.g.rtgen_family = family;
pauledd7c242003-06-04 13:59:38 +0000203
204 /* linux appears to check capabilities on every message
205 * have to raise caps for every message sent
206 */
207 if ( zserv_privs.change(ZPRIVS_RAISE) )
208 {
209 zlog (NULL, LOG_ERR, "Can't raise privileges");
210 return -1;
211 }
paul718e3742002-12-13 20:15:29 +0000212
213 ret = sendto (nl->sock, (void*) &req, sizeof req, 0,
214 (struct sockaddr*) &snl, sizeof snl);
pauledd7c242003-06-04 13:59:38 +0000215
216 if ( zserv_privs.change(ZPRIVS_LOWER) )
217 zlog (NULL, LOG_ERR, "Can't lower privileges");
218
paul718e3742002-12-13 20:15:29 +0000219 if (ret < 0)
pauledd7c242003-06-04 13:59:38 +0000220 {
paul718e3742002-12-13 20:15:29 +0000221 zlog (NULL, LOG_ERR, "%s sendto failed: %s", nl->name, strerror (errno));
222 return -1;
223 }
pauledd7c242003-06-04 13:59:38 +0000224
paul718e3742002-12-13 20:15:29 +0000225 return 0;
226}
227
228/* Receive message from netlink interface and pass those information
229 to the given function. */
230static int
231netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *),
232 struct nlsock *nl)
233{
234 int status;
235 int ret = 0;
236 int error;
237
238 while (1)
239 {
240 char buf[4096];
241 struct iovec iov = { buf, sizeof buf };
242 struct sockaddr_nl snl;
243 struct msghdr msg = { (void*)&snl, sizeof snl, &iov, 1, NULL, 0, 0};
244 struct nlmsghdr *h;
245
pauledd7c242003-06-04 13:59:38 +0000246 if ( zserv_privs.change(ZPRIVS_RAISE) )
247 zlog (NULL, LOG_ERR, "Can't raise privileges");
248
paul718e3742002-12-13 20:15:29 +0000249 status = recvmsg (nl->sock, &msg, 0);
pauledd7c242003-06-04 13:59:38 +0000250
251 if ( zserv_privs.change(ZPRIVS_LOWER) )
252 zlog (NULL, LOG_ERR, "Can't lower privileges");
paul718e3742002-12-13 20:15:29 +0000253
254 if (status < 0)
255 {
256 if (errno == EINTR)
257 continue;
258 if (errno == EWOULDBLOCK || errno == EAGAIN)
259 break;
260 zlog (NULL, LOG_ERR, "%s recvmsg overrun", nl->name);
261 continue;
262 }
263
264 if (status == 0)
265 {
266 zlog (NULL, LOG_ERR, "%s EOF", nl->name);
267 return -1;
268 }
269
270 if (msg.msg_namelen != sizeof snl)
271 {
272 zlog (NULL, LOG_ERR, "%s sender address length error: length %d",
273 nl->name, msg.msg_namelen);
274 return -1;
275 }
276
277 for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, status);
278 h = NLMSG_NEXT (h, status))
279 {
280 /* Finish of reading. */
281 if (h->nlmsg_type == NLMSG_DONE)
282 return ret;
283
284 /* Error handling. */
285 if (h->nlmsg_type == NLMSG_ERROR)
286 {
287 struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h);
288
289 /* If the error field is zero, then this is an ACK */
290 if (err->error == 0)
291 {
292 if (IS_ZEBRA_DEBUG_KERNEL)
293 {
294 zlog_info("%s: %s ACK: type=%s(%u), seq=%u, pid=%d",
295 __FUNCTION__, nl->name,
296 lookup (nlmsg_str, err->msg.nlmsg_type),
297 err->msg.nlmsg_type, err->msg.nlmsg_seq,
298 err->msg.nlmsg_pid);
299 }
300
301 /* return if not a multipart message, otherwise continue */
302 if(!(h->nlmsg_flags & NLM_F_MULTI))
303 {
304 return 0;
305 }
306 continue;
307 }
308
309 if (h->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr)))
310 {
311 zlog (NULL, LOG_ERR, "%s error: message truncated",
312 nl->name);
313 return -1;
314 }
pauld753e9e2003-01-22 19:45:50 +0000315
316 /* Deal with Error Noise - MAG*/
317 {
318 int loglvl = LOG_ERR;
319 int errnum = err->error;
320 int msg_type = err->msg.nlmsg_type;
321
322 if (nl == &netlink_cmd
323 && (-errnum == ENODEV || -errnum == ESRCH)
324 && (msg_type == RTM_NEWROUTE
325 || msg_type == RTM_DELROUTE))
326 loglvl = LOG_DEBUG;
327
328 zlog (NULL, loglvl, "%s error: %s, type=%s(%u), "
329 "seq=%u, pid=%d",
330 nl->name, strerror (-errnum),
331 lookup (nlmsg_str, msg_type),
332 msg_type, err->msg.nlmsg_seq,
paul718e3742002-12-13 20:15:29 +0000333 err->msg.nlmsg_pid);
pauld753e9e2003-01-22 19:45:50 +0000334 }
paul718e3742002-12-13 20:15:29 +0000335 /*
336 ret = -1;
337 continue;
338 */
339 return -1;
340 }
341
342 /* OK we got netlink message. */
343 if (IS_ZEBRA_DEBUG_KERNEL)
344 zlog_info ("netlink_parse_info: %s type %s(%u), seq=%u, pid=%d",
345 nl->name,
346 lookup (nlmsg_str, h->nlmsg_type), h->nlmsg_type,
347 h->nlmsg_seq, h->nlmsg_pid);
348
349 /* skip unsolicited messages originating from command socket */
350 if (nl != &netlink_cmd && h->nlmsg_pid == netlink_cmd.snl.nl_pid)
351 {
352 if (IS_ZEBRA_DEBUG_KERNEL)
353 zlog_info ("netlink_parse_info: %s packet comes from %s",
354 nl->name, netlink_cmd.name);
355 continue;
356 }
357
358 error = (*filter) (&snl, h);
359 if (error < 0)
360 {
361 zlog (NULL, LOG_ERR, "%s filter function error", nl->name);
362 ret = error;
363 }
364 }
365
366 /* After error care. */
367 if (msg.msg_flags & MSG_TRUNC)
368 {
369 zlog (NULL, LOG_ERR, "%s error: message truncated", nl->name);
370 continue;
371 }
372 if (status)
373 {
374 zlog (NULL, LOG_ERR, "%s error: data remnant size %d", nl->name,
375 status);
376 return -1;
377 }
378 }
379 return ret;
380}
381
382/* Utility function for parse rtattr. */
383static void
384netlink_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta, int len)
385{
386 while (RTA_OK(rta, len))
387 {
388 if (rta->rta_type <= max)
389 tb[rta->rta_type] = rta;
390 rta = RTA_NEXT(rta,len);
391 }
392}
393
394/* Called from interface_lookup_netlink(). This function is only used
395 during bootstrap. */
396int
397netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h)
398{
399 int len;
400 struct ifinfomsg *ifi;
401 struct rtattr *tb[IFLA_MAX + 1];
402 struct interface *ifp;
403 char *name;
404 int i;
405
406 ifi = NLMSG_DATA (h);
407
408 if (h->nlmsg_type != RTM_NEWLINK)
409 return 0;
410
411 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
412 if (len < 0)
413 return -1;
414
415 /* Looking up interface name. */
416 memset (tb, 0, sizeof tb);
417 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
418 if (tb[IFLA_IFNAME] == NULL)
419 return -1;
420 name = (char *)RTA_DATA(tb[IFLA_IFNAME]);
421
422 /* Add interface. */
423 ifp = if_get_by_name (name);
424
425 ifp->ifindex = ifi->ifi_index;
426 ifp->flags = ifi->ifi_flags & 0x0000fffff;
427 ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);
428 ifp->metric = 1;
429
430 /* Hardware type and address. */
431 ifp->hw_type = ifi->ifi_type;
432
433 if (tb[IFLA_ADDRESS])
434 {
435 int hw_addr_len;
436
437 hw_addr_len = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
438
439 if (hw_addr_len > INTERFACE_HWADDR_MAX)
440 zlog_warn ("Hardware address is too large: %d", hw_addr_len);
441 else
442 {
443 ifp->hw_addr_len = hw_addr_len;
444 memcpy (ifp->hw_addr, RTA_DATA(tb[IFLA_ADDRESS]), hw_addr_len);
445
446 for (i = 0; i < hw_addr_len; i++)
447 if (ifp->hw_addr[i] != 0)
448 break;
449
450 if (i == hw_addr_len)
451 ifp->hw_addr_len = 0;
452 else
453 ifp->hw_addr_len = hw_addr_len;
454 }
455 }
456
457 if_add_update (ifp);
458
459 return 0;
460}
461
462/* Lookup interface IPv4/IPv6 address. */
463int
464netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
465{
466 int len;
467 struct ifaddrmsg *ifa;
468 struct rtattr *tb [IFA_MAX + 1];
469 struct interface *ifp;
470 void *addr = NULL;
471 void *broad = NULL;
472 u_char flags = 0;
473 char *label = NULL;
paul00df0c12002-12-13 21:07:36 +0000474 int peeronly = 0;
paul718e3742002-12-13 20:15:29 +0000475
476 ifa = NLMSG_DATA (h);
477
478 if (ifa->ifa_family != AF_INET
479#ifdef HAVE_IPV6
480 && ifa->ifa_family != AF_INET6
481#endif /* HAVE_IPV6 */
482 )
483 return 0;
484
485 if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
486 return 0;
487
488 len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct ifaddrmsg));
489 if (len < 0)
490 return -1;
491
492 memset (tb, 0, sizeof tb);
493 netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len);
494
495 ifp = if_lookup_by_index (ifa->ifa_index);
496 if (ifp == NULL)
497 {
498 zlog_err ("netlink_interface_addr can't find interface by index %d",
499 ifa->ifa_index);
500 return -1;
501 }
502
paul00df0c12002-12-13 21:07:36 +0000503 if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */
paul718e3742002-12-13 20:15:29 +0000504 {
paul00df0c12002-12-13 21:07:36 +0000505 char buf[BUFSIZ];
506 zlog_info ("netlink_interface_addr %s %s/%d:",
507 lookup (nlmsg_str, h->nlmsg_type),
508 ifp->name, ifa->ifa_prefixlen);
paul718e3742002-12-13 20:15:29 +0000509 if (tb[IFA_LOCAL])
paul00df0c12002-12-13 21:07:36 +0000510 zlog_info (" IFA_LOCAL %s", inet_ntop (ifa->ifa_family,
511 RTA_DATA (tb[IFA_LOCAL]), buf, BUFSIZ));
paul718e3742002-12-13 20:15:29 +0000512 if (tb[IFA_ADDRESS])
paul00df0c12002-12-13 21:07:36 +0000513 zlog_info (" IFA_ADDRESS %s", inet_ntop (ifa->ifa_family,
514 RTA_DATA (tb[IFA_ADDRESS]), buf, BUFSIZ));
paul718e3742002-12-13 20:15:29 +0000515 if (tb[IFA_BROADCAST])
paul00df0c12002-12-13 21:07:36 +0000516 zlog_info (" IFA_BROADCAST %s", inet_ntop (ifa->ifa_family,
517 RTA_DATA (tb[IFA_BROADCAST]), buf, BUFSIZ));
518 if (tb[IFA_LABEL] && strcmp (ifp->name, RTA_DATA (tb[IFA_LABEL])))
519 zlog_info (" IFA_LABEL %s", RTA_DATA (tb[IFA_LABEL]));
paul718e3742002-12-13 20:15:29 +0000520 }
521
paul00df0c12002-12-13 21:07:36 +0000522 /* peer or broadcast network? */
523 if (ifa->ifa_family == AF_INET)
524 peeronly = if_is_pointopoint (ifp) ||
525 ifa->ifa_prefixlen >= IPV4_MAX_PREFIXLEN - 1;
526#ifdef HAVE_IPV6
paul8fdcfde2003-01-19 20:52:55 +0000527 if (ifa->ifa_family == AF_INET6) {
paul00df0c12002-12-13 21:07:36 +0000528 peeronly = if_is_pointopoint (ifp) ||
529 ifa->ifa_prefixlen >= IPV6_MAX_PREFIXLEN - 1;
paul8fdcfde2003-01-19 20:52:55 +0000530 }
paul00df0c12002-12-13 21:07:36 +0000531#endif /* HAVE_IPV6*/
paul8fdcfde2003-01-19 20:52:55 +0000532 if (!(tb[IFA_LOCAL] && tb[IFA_ADDRESS])) {
533 /* FIXME: IPv6 Appears to have only IFA_ADDRESS */
534 peeronly=0;
535 }
paul00df0c12002-12-13 21:07:36 +0000536
537 /* network. prefixlen applies to IFA_ADDRESS rather than IFA_LOCAL */
538 if (tb[IFA_ADDRESS] && !peeronly)
539 addr = RTA_DATA (tb[IFA_ADDRESS]);
540 else if (tb[IFA_LOCAL])
541 addr = RTA_DATA (tb[IFA_LOCAL]);
542 else
543 addr = NULL;
544
545 /* broadcast/peer */
546 if (tb[IFA_BROADCAST])
547 broad = RTA_DATA (tb[IFA_BROADCAST]);
548 else if (tb[IFA_ADDRESS] && peeronly)
549 broad = RTA_DATA (tb[IFA_ADDRESS]); /* peer address specified */
550 else
551 broad = NULL;
552
paul718e3742002-12-13 20:15:29 +0000553 /* Flags. */
554 if (ifa->ifa_flags & IFA_F_SECONDARY)
555 SET_FLAG (flags, ZEBRA_IFA_SECONDARY);
556
557 /* Label */
558 if (tb[IFA_LABEL])
559 label = (char *) RTA_DATA (tb[IFA_LABEL]);
560
561 if (ifp && label && strcmp (ifp->name, label) == 0)
562 label = NULL;
563
564 /* Register interface address to the interface. */
565 if (ifa->ifa_family == AF_INET)
566 {
567 if (h->nlmsg_type == RTM_NEWADDR)
568 connected_add_ipv4 (ifp, flags,
569 (struct in_addr *) addr, ifa->ifa_prefixlen,
570 (struct in_addr *) broad, label);
571 else
572 connected_delete_ipv4 (ifp, flags,
573 (struct in_addr *) addr, ifa->ifa_prefixlen,
574 (struct in_addr *) broad, label);
575 }
576#ifdef HAVE_IPV6
577 if (ifa->ifa_family == AF_INET6)
578 {
579 if (h->nlmsg_type == RTM_NEWADDR)
580 connected_add_ipv6 (ifp,
581 (struct in6_addr *) addr, ifa->ifa_prefixlen,
582 (struct in6_addr *) broad);
583 else
584 connected_delete_ipv6 (ifp,
585 (struct in6_addr *) addr, ifa->ifa_prefixlen,
586 (struct in6_addr *) broad);
587 }
588#endif /* HAVE_IPV6*/
589
590 return 0;
591}
592
593/* Looking up routing table by netlink interface. */
594int
595netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
596{
597 int len;
598 struct rtmsg *rtm;
599 struct rtattr *tb [RTA_MAX + 1];
600 u_char flags = 0;
601
602 char anyaddr[16] = {0};
603
604 int index;
605 int table;
606 void *dest;
607 void *gate;
608
609 rtm = NLMSG_DATA (h);
610
611 if (h->nlmsg_type != RTM_NEWROUTE)
612 return 0;
613 if (rtm->rtm_type != RTN_UNICAST)
614 return 0;
615
616 table = rtm->rtm_table;
617#if 0 /* we weed them out later in rib_weed_tables () */
618 if (table != RT_TABLE_MAIN && table != rtm_table_default)
619 return 0;
620#endif
621
622 len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct rtmsg));
623 if (len < 0)
624 return -1;
625
626 memset (tb, 0, sizeof tb);
627 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
628
629 if (rtm->rtm_flags & RTM_F_CLONED)
630 return 0;
631 if (rtm->rtm_protocol == RTPROT_REDIRECT)
632 return 0;
633 if (rtm->rtm_protocol == RTPROT_KERNEL)
634 return 0;
635
636 if (rtm->rtm_src_len != 0)
637 return 0;
638
639 /* Route which inserted by Zebra. */
640 if (rtm->rtm_protocol == RTPROT_ZEBRA)
641 flags |= ZEBRA_FLAG_SELFROUTE;
642
643 index = 0;
644 dest = NULL;
645 gate = NULL;
646
647 if (tb[RTA_OIF])
648 index = *(int *) RTA_DATA (tb[RTA_OIF]);
649
650 if (tb[RTA_DST])
651 dest = RTA_DATA (tb[RTA_DST]);
652 else
653 dest = anyaddr;
654
655 /* Multipath treatment is needed. */
656 if (tb[RTA_GATEWAY])
657 gate = RTA_DATA (tb[RTA_GATEWAY]);
658
659 if (rtm->rtm_family == AF_INET)
660 {
661 struct prefix_ipv4 p;
662 p.family = AF_INET;
663 memcpy (&p.prefix, dest, 4);
664 p.prefixlen = rtm->rtm_dst_len;
665
666 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table, 0, 0);
667 }
668#ifdef HAVE_IPV6
669 if (rtm->rtm_family == AF_INET6)
670 {
671 struct prefix_ipv6 p;
672 p.family = AF_INET6;
673 memcpy (&p.prefix, dest, 16);
674 p.prefixlen = rtm->rtm_dst_len;
675
676 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table);
677 }
678#endif /* HAVE_IPV6 */
679
680 return 0;
681}
682
683struct message rtproto_str [] =
684{
685 {RTPROT_REDIRECT, "redirect"},
686 {RTPROT_KERNEL, "kernel"},
687 {RTPROT_BOOT, "boot"},
688 {RTPROT_STATIC, "static"},
689 {RTPROT_GATED, "GateD"},
690 {RTPROT_RA, "router advertisement"},
691 {RTPROT_MRT, "MRT"},
692 {RTPROT_ZEBRA, "Zebra"},
693#ifdef RTPROT_BIRD
694 {RTPROT_BIRD, "BIRD"},
695#endif /* RTPROT_BIRD */
696 {0, NULL}
697};
698
699/* Routing information change from the kernel. */
700int
701netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
702{
703 int len;
704 struct rtmsg *rtm;
705 struct rtattr *tb [RTA_MAX + 1];
706
707 char anyaddr[16] = {0};
708
709 int index;
710 int table;
711 void *dest;
712 void *gate;
713
714 rtm = NLMSG_DATA (h);
715
716 if (! (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
717 {
718 /* If this is not route add/delete message print warning. */
719 zlog_warn ("Kernel message: %d\n", h->nlmsg_type);
720 return 0;
721 }
722
723 /* Connected route. */
724 if (IS_ZEBRA_DEBUG_KERNEL)
725 zlog_info ("%s %s %s proto %s",
726 h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
727 rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",
728 rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast",
729 lookup (rtproto_str, rtm->rtm_protocol));
730
731 if (rtm->rtm_type != RTN_UNICAST)
732 {
733 return 0;
734 }
735
736 table = rtm->rtm_table;
737 if (table != RT_TABLE_MAIN && table != rtm_table_default)
738 {
739 return 0;
740 }
741
742 len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct rtmsg));
743 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_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)
757 return 0;
758
759 if (rtm->rtm_src_len != 0)
760 {
761 zlog_warn ("netlink_route_change(): no src len");
762 return 0;
763 }
764
765 index = 0;
766 dest = NULL;
767 gate = NULL;
768
769 if (tb[RTA_OIF])
770 index = *(int *) RTA_DATA (tb[RTA_OIF]);
771
772 if (tb[RTA_DST])
773 dest = RTA_DATA (tb[RTA_DST]);
774 else
775 dest = anyaddr;
776
777 if (tb[RTA_GATEWAY])
778 gate = RTA_DATA (tb[RTA_GATEWAY]);
779
780 if (rtm->rtm_family == AF_INET)
781 {
782 struct prefix_ipv4 p;
783 p.family = AF_INET;
784 memcpy (&p.prefix, dest, 4);
785 p.prefixlen = rtm->rtm_dst_len;
786
787 if (IS_ZEBRA_DEBUG_KERNEL)
788 {
789 if (h->nlmsg_type == RTM_NEWROUTE)
790 zlog_info ("RTM_NEWROUTE %s/%d",
791 inet_ntoa (p.prefix), p.prefixlen);
792 else
793 zlog_info ("RTM_DELROUTE %s/%d",
794 inet_ntoa (p.prefix), p.prefixlen);
795 }
796
797 if (h->nlmsg_type == RTM_NEWROUTE)
798 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, 0, 0);
799 else
800 rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table);
801 }
802
803#ifdef HAVE_IPV6
804 if (rtm->rtm_family == AF_INET6)
805 {
806 struct prefix_ipv6 p;
807 char buf[BUFSIZ];
808
809 p.family = AF_INET6;
810 memcpy (&p.prefix, dest, 16);
811 p.prefixlen = rtm->rtm_dst_len;
812
813 if (IS_ZEBRA_DEBUG_KERNEL)
814 {
815 if (h->nlmsg_type == RTM_NEWROUTE)
816 zlog_info ("RTM_NEWROUTE %s/%d",
817 inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
818 p.prefixlen);
819 else
820 zlog_info ("RTM_DELROUTE %s/%d",
821 inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
822 p.prefixlen);
823 }
824
825 if (h->nlmsg_type == RTM_NEWROUTE)
826 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);
827 else
828 rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);
829 }
830#endif /* HAVE_IPV6 */
831
832 return 0;
833}
834
835int
836netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
837{
838 int len;
839 struct ifinfomsg *ifi;
840 struct rtattr *tb [IFLA_MAX + 1];
841 struct interface *ifp;
842 char *name;
843
844 ifi = NLMSG_DATA (h);
845
846 if (! (h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
847 {
848 /* If this is not link add/delete message so print warning. */
849 zlog_warn ("netlink_link_change: wrong kernel message %d\n",
850 h->nlmsg_type);
851 return 0;
852 }
853
854 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
855 if (len < 0)
856 return -1;
857
858 /* Looking up interface name. */
859 memset (tb, 0, sizeof tb);
860 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
861 if (tb[IFLA_IFNAME] == NULL)
862 return -1;
863 name = (char *)RTA_DATA(tb[IFLA_IFNAME]);
864
865 /* Add interface. */
866 if (h->nlmsg_type == RTM_NEWLINK)
867 {
868 ifp = if_lookup_by_name (name);
869
870 if (ifp == NULL || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
871 {
872 if (ifp == NULL)
873 ifp = if_get_by_name (name);
874
875 ifp->ifindex = ifi->ifi_index;
876 ifp->flags = ifi->ifi_flags & 0x0000fffff;
877 ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);
878 ifp->metric = 1;
879
880 /* If new link is added. */
881 if_add_update(ifp);
882 }
883 else
884 {
885 /* Interface status change. */
886 ifp->ifindex = ifi->ifi_index;
887 ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);
888 ifp->metric = 1;
889
paul2e3b2e42002-12-13 21:03:13 +0000890 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000891 {
892 ifp->flags = ifi->ifi_flags & 0x0000fffff;
paul2e3b2e42002-12-13 21:03:13 +0000893 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000894 if_down (ifp);
895 }
896 else
897 {
898 ifp->flags = ifi->ifi_flags & 0x0000fffff;
paul2e3b2e42002-12-13 21:03:13 +0000899 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000900 if_up (ifp);
901 }
902 }
903 }
904 else
905 {
906 /* RTM_DELLINK. */
907 ifp = if_lookup_by_name (name);
908
909 if (ifp == NULL)
910 {
911 zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find",
912 name);
913 return 0;
914 }
915
916 if_delete_update (ifp);
917 }
918
919 return 0;
920}
921
922int
923netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h)
924{
925 switch (h->nlmsg_type)
926 {
927 case RTM_NEWROUTE:
928 return netlink_route_change (snl, h);
929 break;
930 case RTM_DELROUTE:
931 return netlink_route_change (snl, h);
932 break;
933 case RTM_NEWLINK:
934 return netlink_link_change (snl, h);
935 break;
936 case RTM_DELLINK:
937 return netlink_link_change (snl, h);
938 break;
939 case RTM_NEWADDR:
940 return netlink_interface_addr (snl, h);
941 break;
942 case RTM_DELADDR:
943 return netlink_interface_addr (snl, h);
944 break;
945 default:
946 zlog_warn ("Unknown netlink nlmsg_type %d\n", h->nlmsg_type);
947 break;
948 }
949 return 0;
950}
951
952/* Interface lookup by netlink socket. */
953int
954interface_lookup_netlink ()
955{
956 int ret;
paul5f37d862003-04-19 00:11:28 +0000957 int flags;
958 int snb_ret;
959
960 /*
961 * Change netlink socket flags to blocking to ensure we get
962 * a reply via nelink_parse_info
963 */
964 snb_ret = set_netlink_blocking(&netlink_cmd, &flags);
965 if(snb_ret < 0)
966 zlog (NULL, LOG_WARNING,
967 "%s:%i Warning: Could not set netlink socket to blocking.",
968 __FUNCTION__, __LINE__);
969
paul718e3742002-12-13 20:15:29 +0000970 /* Get interface information. */
971 ret = netlink_request (AF_PACKET, RTM_GETLINK, &netlink_cmd);
972 if (ret < 0)
973 return ret;
974 ret = netlink_parse_info (netlink_interface, &netlink_cmd);
975 if (ret < 0)
976 return ret;
977
978 /* Get IPv4 address of the interfaces. */
979 ret = netlink_request (AF_INET, RTM_GETADDR, &netlink_cmd);
980 if (ret < 0)
981 return ret;
982 ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
983 if (ret < 0)
984 return ret;
985
986#ifdef HAVE_IPV6
987 /* Get IPv6 address of the interfaces. */
988 ret = netlink_request (AF_INET6, RTM_GETADDR, &netlink_cmd);
989 if (ret < 0)
990 return ret;
991 ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
992 if (ret < 0)
993 return ret;
994#endif /* HAVE_IPV6 */
995
paul5f37d862003-04-19 00:11:28 +0000996 /* restore socket flags */
997 if(snb_ret == 0)
998 set_netlink_nonblocking(&netlink_cmd, &flags);
paul718e3742002-12-13 20:15:29 +0000999 return 0;
1000}
1001
1002/* Routing table read function using netlink interface. Only called
1003 bootstrap time. */
1004int
1005netlink_route_read ()
1006{
1007 int ret;
paul5f37d862003-04-19 00:11:28 +00001008 int flags;
1009 int snb_ret;
1010
1011 /*
1012 * Change netlink socket flags to blocking to ensure we get
1013 * a reply via nelink_parse_info
1014 */
1015 snb_ret = set_netlink_blocking(&netlink_cmd, &flags);
1016 if(snb_ret < 0)
1017 zlog (NULL, LOG_WARNING,
1018 "%s:%i Warning: Could not set netlink socket to blocking.",
1019 __FUNCTION__, __LINE__);
1020
paul718e3742002-12-13 20:15:29 +00001021 /* Get IPv4 routing table. */
1022 ret = netlink_request (AF_INET, RTM_GETROUTE, &netlink_cmd);
1023 if (ret < 0)
1024 return ret;
1025 ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
1026 if (ret < 0)
1027 return ret;
1028
1029#ifdef HAVE_IPV6
1030 /* Get IPv6 routing table. */
1031 ret = netlink_request (AF_INET6, RTM_GETROUTE, &netlink_cmd);
1032 if (ret < 0)
1033 return ret;
1034 ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
1035 if (ret < 0)
1036 return ret;
1037#endif /* HAVE_IPV6 */
1038
paul5f37d862003-04-19 00:11:28 +00001039 /* restore flags */
1040 if(snb_ret == 0)
1041 set_netlink_nonblocking(&netlink_cmd, &flags);
paul718e3742002-12-13 20:15:29 +00001042 return 0;
1043}
1044
1045/* Utility function comes from iproute2.
1046 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
1047int
1048addattr_l (struct nlmsghdr *n, int maxlen, int type, void *data, int alen)
1049{
1050 int len;
1051 struct rtattr *rta;
1052
1053 len = RTA_LENGTH(alen);
1054
1055 if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)
1056 return -1;
1057
1058 rta = (struct rtattr*) (((char*)n) + NLMSG_ALIGN (n->nlmsg_len));
1059 rta->rta_type = type;
1060 rta->rta_len = len;
1061 memcpy (RTA_DATA(rta), data, alen);
1062 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1063
1064 return 0;
1065}
1066
1067int
1068rta_addattr_l (struct rtattr *rta, int maxlen, int type, void *data, int alen)
1069{
1070 int len;
1071 struct rtattr *subrta;
1072
1073 len = RTA_LENGTH(alen);
1074
1075 if (RTA_ALIGN(rta->rta_len) + len > maxlen)
1076 return -1;
1077
1078 subrta = (struct rtattr*) (((char*)rta) + RTA_ALIGN (rta->rta_len));
1079 subrta->rta_type = type;
1080 subrta->rta_len = len;
1081 memcpy (RTA_DATA(subrta), data, alen);
1082 rta->rta_len = NLMSG_ALIGN (rta->rta_len) + len;
1083
1084 return 0;
1085}
1086
1087/* Utility function comes from iproute2.
1088 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
1089int
1090addattr32 (struct nlmsghdr *n, int maxlen, int type, int data)
1091{
1092 int len;
1093 struct rtattr *rta;
1094
1095 len = RTA_LENGTH(4);
1096
1097 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
1098 return -1;
1099
1100 rta = (struct rtattr*) (((char*)n) + NLMSG_ALIGN (n->nlmsg_len));
1101 rta->rta_type = type;
1102 rta->rta_len = len;
1103 memcpy (RTA_DATA(rta), &data, 4);
1104 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1105
1106 return 0;
1107}
1108
1109static int
1110netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h)
1111{
1112 zlog_warn ("netlink_talk: ignoring message type 0x%04x", h->nlmsg_type);
1113 return 0;
1114}
1115
1116/* sendmsg() to netlink socket then recvmsg(). */
1117int
1118netlink_talk (struct nlmsghdr *n, struct nlsock *nl)
1119{
1120 int status;
1121 struct sockaddr_nl snl;
1122 struct iovec iov = { (void*) n, n->nlmsg_len };
1123 struct msghdr msg = {(void*) &snl, sizeof snl, &iov, 1, NULL, 0, 0};
1124 int flags = 0;
paul5f37d862003-04-19 00:11:28 +00001125 int snb_ret;
paul718e3742002-12-13 20:15:29 +00001126
1127 memset (&snl, 0, sizeof snl);
1128 snl.nl_family = AF_NETLINK;
1129
1130 n->nlmsg_seq = ++netlink_cmd.seq;
1131
1132 /* Request an acknowledgement by setting NLM_F_ACK */
1133 n->nlmsg_flags |= NLM_F_ACK;
1134
1135 if (IS_ZEBRA_DEBUG_KERNEL)
1136 zlog_info ("netlink_talk: %s type %s(%u), seq=%u", netlink_cmd.name,
1137 lookup (nlmsg_str, n->nlmsg_type), n->nlmsg_type,
1138 n->nlmsg_seq);
1139
1140 /* Send message to netlink interface. */
pauledd7c242003-06-04 13:59:38 +00001141 if ( zserv_privs.change(ZPRIVS_RAISE) )
1142 zlog (NULL, LOG_ERR, "Can't raise privileges");
paul718e3742002-12-13 20:15:29 +00001143 status = sendmsg (nl->sock, &msg, 0);
pauledd7c242003-06-04 13:59:38 +00001144 if ( zserv_privs.change(ZPRIVS_LOWER) )
1145 zlog (NULL, LOG_ERR, "Can't lower privileges");
1146
paul718e3742002-12-13 20:15:29 +00001147 if (status < 0)
1148 {
1149 zlog (NULL, LOG_ERR, "netlink_talk sendmsg() error: %s",
1150 strerror (errno));
1151 return -1;
1152 }
1153
1154 /*
1155 * Change socket flags for blocking I/O.
1156 * This ensures we wait for a reply in netlink_parse_info().
1157 */
paul5f37d862003-04-19 00:11:28 +00001158 snb_ret = set_netlink_blocking(nl, &flags);
1159 if(snb_ret < 0)
1160 zlog (NULL, LOG_WARNING,
1161 "%s:%i Warning: Could not set netlink socket to blocking.",
1162 __FUNCTION__, __LINE__);
paul718e3742002-12-13 20:15:29 +00001163
1164 /*
1165 * Get reply from netlink socket.
1166 * The reply should either be an acknowlegement or an error.
1167 */
1168 status = netlink_parse_info (netlink_talk_filter, nl);
1169
1170 /* Restore socket flags for nonblocking I/O */
paul5f37d862003-04-19 00:11:28 +00001171 if(snb_ret == 0)
1172 set_netlink_nonblocking(nl, &flags);
paul718e3742002-12-13 20:15:29 +00001173
1174 return status;
1175}
1176
1177/* Routing table change via netlink interface. */
1178int
1179netlink_route (int cmd, int family, void *dest, int length, void *gate,
1180 int index, int zebra_flags, int table)
1181{
1182 int ret;
1183 int bytelen;
1184 struct sockaddr_nl snl;
1185 int discard;
1186
1187 struct
1188 {
1189 struct nlmsghdr n;
1190 struct rtmsg r;
1191 char buf[1024];
1192 } req;
1193
1194 memset (&req, 0, sizeof req);
1195
1196 bytelen = (family == AF_INET ? 4 : 16);
1197
1198 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1199 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1200 req.n.nlmsg_type = cmd;
1201 req.r.rtm_family = family;
1202 req.r.rtm_table = table;
1203 req.r.rtm_dst_len = length;
1204
hasso81dfcaa2003-05-25 19:21:25 +00001205 if ((zebra_flags & ZEBRA_FLAG_BLACKHOLE)
1206 || (zebra_flags & ZEBRA_FLAG_REJECT))
paul718e3742002-12-13 20:15:29 +00001207 discard = 1;
1208 else
1209 discard = 0;
1210
1211 if (cmd == RTM_NEWROUTE)
1212 {
1213 req.r.rtm_protocol = RTPROT_ZEBRA;
1214 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1215
paul595db7f2003-05-25 21:35:06 +00001216 if (discard)
1217 {
1218 if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
1219 req.r.rtm_type = RTN_BLACKHOLE;
1220 else if (zebra_flags & ZEBRA_FLAG_REJECT)
1221 req.r.rtm_type = RTN_UNREACHABLE;
1222 else assert(RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
1223 }
1224 else
1225 req.r.rtm_type = RTN_UNICAST;
paul718e3742002-12-13 20:15:29 +00001226 }
1227
1228 if (dest)
1229 addattr_l (&req.n, sizeof req, RTA_DST, dest, bytelen);
1230
1231 if (! discard)
1232 {
1233 if (gate)
1234 addattr_l (&req.n, sizeof req, RTA_GATEWAY, gate, bytelen);
1235 if (index > 0)
1236 addattr32 (&req.n, sizeof req, RTA_OIF, index);
1237 }
1238
1239 /* Destination netlink address. */
1240 memset (&snl, 0, sizeof snl);
1241 snl.nl_family = AF_NETLINK;
1242
1243 /* Talk to netlink socket. */
1244 ret = netlink_talk (&req.n, &netlink);
1245 if (ret < 0)
1246 return -1;
1247
1248 return 0;
1249}
1250
1251/* Routing table change via netlink interface. */
1252int
1253netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
1254 int family)
1255{
1256 int bytelen;
1257 struct sockaddr_nl snl;
1258 struct nexthop *nexthop = NULL;
1259 int nexthop_num = 0;
1260 struct nlsock *nl;
1261 int discard;
1262
1263 struct
1264 {
1265 struct nlmsghdr n;
1266 struct rtmsg r;
1267 char buf[1024];
1268 } req;
1269
1270 memset (&req, 0, sizeof req);
1271
1272 bytelen = (family == AF_INET ? 4 : 16);
1273
1274 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1275 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1276 req.n.nlmsg_type = cmd;
1277 req.r.rtm_family = family;
1278 req.r.rtm_table = rib->table;
1279 req.r.rtm_dst_len = p->prefixlen;
1280
paul13766da2003-02-07 14:46:23 +00001281#ifdef RTM_F_EQUALIZE
1282 req.r.rtm_flags |= RTM_F_EQUALIZE;
1283#endif /* RTM_F_EQUALIZE */
1284
hasso81dfcaa2003-05-25 19:21:25 +00001285 if ((rib->flags & ZEBRA_FLAG_BLACKHOLE)
1286 || (rib->flags & ZEBRA_FLAG_REJECT))
paul718e3742002-12-13 20:15:29 +00001287 discard = 1;
1288 else
1289 discard = 0;
1290
1291 if (cmd == RTM_NEWROUTE)
1292 {
1293 req.r.rtm_protocol = RTPROT_ZEBRA;
1294 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1295
paul595db7f2003-05-25 21:35:06 +00001296 if (discard)
1297 {
1298 if (rib->flags & ZEBRA_FLAG_BLACKHOLE)
1299 req.r.rtm_type = RTN_BLACKHOLE;
1300 else if (rib->flags & ZEBRA_FLAG_REJECT)
1301 req.r.rtm_type = RTN_UNREACHABLE;
1302 else assert(RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
1303 }
1304 else
1305 req.r.rtm_type = RTN_UNICAST;
paul718e3742002-12-13 20:15:29 +00001306 }
1307
1308 addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
1309
1310 /* Metric. */
1311 addattr32 (&req.n, sizeof req, RTA_PRIORITY, rib->metric);
1312
1313 if (discard)
1314 {
1315 if (cmd == RTM_NEWROUTE)
1316 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1317 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1318 goto skip;
1319 }
1320
1321 /* Multipath case. */
1322 if (rib->nexthop_active_num == 1 || MULTIPATH_NUM == 1)
1323 {
1324 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1325 {
1326 if ((cmd == RTM_NEWROUTE
1327 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1328 || (cmd == RTM_DELROUTE
1329 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1330 {
1331 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1332 {
1333 if (nexthop->rtype == NEXTHOP_TYPE_IPV4
1334 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
1335 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1336 &nexthop->rgate.ipv4, bytelen);
1337#ifdef HAVE_IPV6
1338 if (nexthop->rtype == NEXTHOP_TYPE_IPV6
1339 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1340 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1341 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1342 &nexthop->rgate.ipv6, bytelen);
1343#endif /* HAVE_IPV6 */
1344 if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
1345 || nexthop->rtype == NEXTHOP_TYPE_IFNAME
1346 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
1347 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1348 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1349 addattr32 (&req.n, sizeof req, RTA_OIF,
1350 nexthop->rifindex);
1351 }
1352 else
1353 {
1354 if (nexthop->type == NEXTHOP_TYPE_IPV4
1355 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1356 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1357 &nexthop->gate.ipv4, bytelen);
1358#ifdef HAVE_IPV6
1359 if (nexthop->type == NEXTHOP_TYPE_IPV6
1360 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1361 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1362 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1363 &nexthop->gate.ipv6, bytelen);
1364#endif /* HAVE_IPV6 */
1365 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1366 || nexthop->type == NEXTHOP_TYPE_IFNAME
1367 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1368 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
1369 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
1370 addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->ifindex);
1371 }
1372
1373 if (cmd == RTM_NEWROUTE)
1374 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1375
1376 nexthop_num++;
1377 break;
1378 }
1379 }
1380 }
1381 else
1382 {
1383 char buf[1024];
1384 struct rtattr *rta = (void *) buf;
1385 struct rtnexthop *rtnh;
1386
1387 rta->rta_type = RTA_MULTIPATH;
1388 rta->rta_len = RTA_LENGTH(0);
1389 rtnh = RTA_DATA(rta);
1390
1391 nexthop_num = 0;
1392 for (nexthop = rib->nexthop;
1393 nexthop && (MULTIPATH_NUM == 0 || nexthop_num < MULTIPATH_NUM);
1394 nexthop = nexthop->next)
1395 {
1396 if ((cmd == RTM_NEWROUTE
1397 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1398 || (cmd == RTM_DELROUTE
1399 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1400 {
1401 nexthop_num++;
1402
1403 rtnh->rtnh_len = sizeof (*rtnh);
1404 rtnh->rtnh_flags = 0;
1405 rtnh->rtnh_hops = 0;
1406 rta->rta_len += rtnh->rtnh_len;
1407
1408 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1409 {
1410 if (nexthop->rtype == NEXTHOP_TYPE_IPV4
1411 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
1412 {
1413 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1414 &nexthop->rgate.ipv4, bytelen);
1415 rtnh->rtnh_len += sizeof (struct rtattr) + 4;
1416 }
1417#ifdef HAVE_IPV6
1418 if (nexthop->rtype == NEXTHOP_TYPE_IPV6
1419 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME
1420 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX)
1421 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1422 &nexthop->rgate.ipv6, bytelen);
1423#endif /* HAVE_IPV6 */
1424 /* ifindex */
1425 if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
1426 || nexthop->rtype == NEXTHOP_TYPE_IFNAME
1427 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
1428 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1429 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1430 rtnh->rtnh_ifindex = nexthop->rifindex;
1431 else
1432 rtnh->rtnh_ifindex = 0;
1433 }
1434 else
1435 {
1436 if (nexthop->type == NEXTHOP_TYPE_IPV4
1437 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1438 {
1439 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1440 &nexthop->gate.ipv4, bytelen);
1441 rtnh->rtnh_len += sizeof (struct rtattr) + 4;
1442 }
1443#ifdef HAVE_IPV6
1444 if (nexthop->type == NEXTHOP_TYPE_IPV6
1445 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1446 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1447 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1448 &nexthop->gate.ipv6, bytelen);
1449#endif /* HAVE_IPV6 */
1450 /* ifindex */
1451 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1452 || nexthop->type == NEXTHOP_TYPE_IFNAME
1453 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1454 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1455 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1456 rtnh->rtnh_ifindex = nexthop->ifindex;
1457 else
1458 rtnh->rtnh_ifindex = 0;
1459 }
1460 rtnh = RTNH_NEXT(rtnh);
1461
1462 if (cmd == RTM_NEWROUTE)
1463 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1464 }
1465 }
1466
1467 if (rta->rta_len > RTA_LENGTH (0))
1468 addattr_l (&req.n, 1024, RTA_MULTIPATH, RTA_DATA(rta),
1469 RTA_PAYLOAD(rta));
1470 }
1471
1472 /* If there is no useful nexthop then return. */
1473 if (nexthop_num == 0)
1474 {
1475 if (IS_ZEBRA_DEBUG_KERNEL)
1476 zlog_info ("netlink_route_multipath(): No useful nexthop.");
1477 return 0;
1478 }
1479
1480 skip:
1481
1482 /* Destination netlink address. */
1483 memset (&snl, 0, sizeof snl);
1484 snl.nl_family = AF_NETLINK;
1485
1486 if (family == AF_INET)
1487 nl = &netlink_cmd;
1488 else
1489 nl = &netlink;
1490
1491 /* Talk to netlink socket. */
1492 return netlink_talk (&req.n, nl);
1493}
1494
1495int
1496kernel_add_ipv4 (struct prefix *p, struct rib *rib)
1497{
1498 return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET);
1499}
1500
1501int
1502kernel_delete_ipv4 (struct prefix *p, struct rib *rib)
1503{
1504 return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET);
1505}
1506
1507#ifdef HAVE_IPV6
1508int
1509kernel_add_ipv6 (struct prefix *p, struct rib *rib)
1510{
1511 return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET6);
1512}
1513
1514int
1515kernel_delete_ipv6 (struct prefix *p, struct rib *rib)
1516{
1517 return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET6);
1518}
1519
1520/* Delete IPv6 route from the kernel. */
1521int
1522kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate,
1523 int index, int flags, int table)
1524{
1525 return netlink_route (RTM_DELROUTE, AF_INET6, &dest->prefix, dest->prefixlen,
1526 gate, index, flags, table);
1527}
1528#endif /* HAVE_IPV6 */
1529
1530/* Interface address modification. */
1531int
1532netlink_address (int cmd, int family, struct interface *ifp,
1533 struct connected *ifc)
1534{
1535 int bytelen;
1536 struct prefix *p;
1537
1538 struct
1539 {
1540 struct nlmsghdr n;
1541 struct ifaddrmsg ifa;
1542 char buf[1024];
1543 } req;
1544
1545 p = ifc->address;
1546 memset (&req, 0, sizeof req);
1547
1548 bytelen = (family == AF_INET ? 4 : 16);
1549
1550 req.n.nlmsg_len = NLMSG_LENGTH (sizeof(struct ifaddrmsg));
1551 req.n.nlmsg_flags = NLM_F_REQUEST;
1552 req.n.nlmsg_type = cmd;
1553 req.ifa.ifa_family = family;
1554
1555 req.ifa.ifa_index = ifp->ifindex;
1556 req.ifa.ifa_prefixlen = p->prefixlen;
1557
1558 addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen);
1559
1560 if (family == AF_INET && cmd == RTM_NEWADDR)
1561 {
1562 if (if_is_broadcast (ifp) && ifc->destination)
1563 {
1564 p = ifc->destination;
1565 addattr_l(&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix, bytelen);
1566 }
1567 }
1568
1569 if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
1570 SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY);
1571
1572 if (ifc->label)
1573 addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label,
1574 strlen (ifc->label) + 1);
1575
1576 return netlink_talk (&req.n, &netlink_cmd);
1577}
1578
1579int
1580kernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc)
1581{
1582 return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc);
1583}
1584
1585int
1586kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc)
1587{
1588 return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc);
1589}
1590
paul718e3742002-12-13 20:15:29 +00001591
1592extern struct thread_master *master;
1593
1594/* Kernel route reflection. */
1595int
1596kernel_read (struct thread *thread)
1597{
1598 int ret;
1599 int sock;
1600
1601 sock = THREAD_FD (thread);
1602 ret = netlink_parse_info (netlink_information_fetch, &netlink);
1603 thread_add_read (master, kernel_read, NULL, netlink.sock);
1604
1605 return 0;
1606}
1607
1608/* Exported interface function. This function simply calls
1609 netlink_socket (). */
1610void
1611kernel_init ()
1612{
1613 unsigned long groups;
1614
1615 groups = RTMGRP_LINK|RTMGRP_IPV4_ROUTE|RTMGRP_IPV4_IFADDR;
1616#ifdef HAVE_IPV6
1617 groups |= RTMGRP_IPV6_ROUTE|RTMGRP_IPV6_IFADDR;
1618#endif /* HAVE_IPV6 */
1619 netlink_socket (&netlink, groups);
1620 netlink_socket (&netlink_cmd, 0);
1621
1622 /* Register kernel socket. */
1623 if (netlink.sock > 0)
1624 thread_add_read (master, kernel_read, NULL, netlink.sock);
1625}