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