]> git.proxmox.com Git - mirror_frr.git/blame - zebra/kernel_socket.c
move changelog section up higher.
[mirror_frr.git] / zebra / kernel_socket.c
CommitLineData
718e3744 1/* Kernel communication using routing socket.
2 * Copyright (C) 1999 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#include "if.h"
25#include "prefix.h"
26#include "sockunion.h"
27#include "connected.h"
28#include "memory.h"
29#include "ioctl.h"
30#include "log.h"
31#include "str.h"
32#include "table.h"
33#include "rib.h"
edd7c245 34#include "privs.h"
718e3744 35
36#include "zebra/interface.h"
37#include "zebra/zserv.h"
38#include "zebra/debug.h"
39
edd7c245 40extern struct zebra_privs_t zserv_privs;
9bcdb638 41extern struct zebra_t zebrad;
edd7c245 42
718e3744 43/* Socket length roundup function. */
44#define ROUNDUP(a) \
45 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
46
47/* And this macro is wrapper for handling sa_len. */
30be8028 48#if defined(HAVE_SA_LEN)
718e3744 49#define WRAPUP(X) ROUNDUP(((struct sockaddr *)(X))->sa_len)
30be8028 50#elif defined(HAVE_IPV6)
3e95a074 51#define WRAPUP(X) \
30be8028 52 do { \
3e95a074 53 (((struct sockaddr *)(X))->sa_family == AF_INET ? \
54 ROUNDUP(sizeof(struct sockaddr_in)):\
55 (((struct sockaddr *)(X))->sa_family == AF_INET6 ? \
56 ROUNDUP(sizeof(struct sockaddr_in6)) : \
57 (((struct sockaddr *)(X))->sa_family == AF_LINK ? \
30be8028 58 ROUNDUP(sizeof(struct sockaddr_dl)) : sizeof(struct sockaddr)))) \
59 } while (0)
60#else /* HAVE_IPV6 */
61#define WRAPUP(X) \
62 (((struct sockaddr *)(X))->sa_family == AF_INET ? \
63 ROUNDUP(sizeof(struct sockaddr_in)):\
64 (((struct sockaddr *)(X))->sa_family == AF_LINK ? \
65 ROUNDUP(sizeof(struct sockaddr_dl)) : sizeof(struct sockaddr)))
718e3744 66#endif /* HAVE_SA_LEN */
67
68/* Routing socket message types. */
69struct message rtm_type_str[] =
70{
71 {RTM_ADD, "RTM_ADD"},
72 {RTM_DELETE, "RTM_DELETE"},
73 {RTM_CHANGE, "RTM_CHANGE"},
74 {RTM_GET, "RTM_GET"},
75 {RTM_LOSING, "RTM_LOSING"},
76 {RTM_REDIRECT, "RTM_REDIRECT"},
77 {RTM_MISS, "RTM_MISS"},
78 {RTM_LOCK, "RTM_LOCK"},
79 {RTM_OLDADD, "RTM_OLDADD"},
80 {RTM_OLDDEL, "RTM_OLDDEL"},
81 {RTM_RESOLVE, "RTM_RESOLVE"},
82 {RTM_NEWADDR, "RTM_NEWADDR"},
83 {RTM_DELADDR, "RTM_DELADDR"},
84 {RTM_IFINFO, "RTM_IFINFO"},
85#ifdef RTM_OIFINFO
86 {RTM_OIFINFO, "RTM_OIFINFO"},
87#endif /* RTM_OIFINFO */
88#ifdef RTM_NEWMADDR
89 {RTM_NEWMADDR, "RTM_NEWMADDR"},
90#endif /* RTM_NEWMADDR */
91#ifdef RTM_DELMADDR
92 {RTM_DELMADDR, "RTM_DELMADDR"},
93#endif /* RTM_DELMADDR */
94#ifdef RTM_IFANNOUNCE
95 {RTM_IFANNOUNCE, "RTM_IFANNOUNCE"},
96#endif /* RTM_IFANNOUNCE */
97 {0, NULL}
98};
99
100struct message rtm_flag_str[] =
101{
102 {RTF_UP, "UP"},
103 {RTF_GATEWAY, "GATEWAY"},
104 {RTF_HOST, "HOST"},
105 {RTF_REJECT, "REJECT"},
106 {RTF_DYNAMIC, "DYNAMIC"},
107 {RTF_MODIFIED, "MODIFIED"},
108 {RTF_DONE, "DONE"},
109#ifdef RTF_MASK
110 {RTF_MASK, "MASK"},
111#endif /* RTF_MASK */
112 {RTF_CLONING, "CLONING"},
113 {RTF_XRESOLVE, "XRESOLVE"},
114 {RTF_LLINFO, "LLINFO"},
115 {RTF_STATIC, "STATIC"},
116 {RTF_BLACKHOLE, "BLACKHOLE"},
117 {RTF_PROTO1, "PROTO1"},
118 {RTF_PROTO2, "PROTO2"},
119#ifdef RTF_PRCLONING
120 {RTF_PRCLONING, "PRCLONING"},
121#endif /* RTF_PRCLONING */
122#ifdef RTF_WASCLONED
123 {RTF_WASCLONED, "WASCLONED"},
124#endif /* RTF_WASCLONED */
125#ifdef RTF_PROTO3
126 {RTF_PROTO3, "PROTO3"},
127#endif /* RTF_PROTO3 */
128#ifdef RTF_PINNED
129 {RTF_PINNED, "PINNED"},
130#endif /* RTF_PINNED */
131#ifdef RTF_LOCAL
132 {RTF_LOCAL, "LOCAL"},
133#endif /* RTF_LOCAL */
134#ifdef RTF_BROADCAST
135 {RTF_BROADCAST, "BROADCAST"},
136#endif /* RTF_BROADCAST */
137#ifdef RTF_MULTICAST
138 {RTF_MULTICAST, "MULTICAST"},
139#endif /* RTF_MULTICAST */
140 {0, NULL}
141};
142
143/* Kernel routing update socket. */
144int routing_sock = -1;
145
146/* Yes I'm checking ugly routing socket behavior. */
147/* #define DEBUG */
148
149/* Supported address family check. */
150static int
151af_check (int family)
152{
153 if (family == AF_INET)
154 return 1;
155#ifdef HAVE_IPV6
156 if (family == AF_INET6)
157 return 1;
158#endif /* HAVE_IPV6 */
159 return 0;
160}
161\f
162/* Dump routing table flag for debug purpose. */
163void
164rtm_flag_dump (int flag)
165{
166 struct message *mes;
167 static char buf[BUFSIZ];
168
81dfcaa2 169 buf[0] = '0';
718e3744 170 for (mes = rtm_flag_str; mes->key != 0; mes++)
171 {
172 if (mes->key & flag)
173 {
174 strlcat (buf, mes->str, BUFSIZ);
175 strlcat (buf, " ", BUFSIZ);
176 }
177 }
178 zlog_info ("Kernel: %s", buf);
179}
180
181#ifdef RTM_IFANNOUNCE
182/* Interface adding function */
183int
184ifan_read (struct if_announcemsghdr *ifan)
185{
186 struct interface *ifp;
187
188 ifp = if_lookup_by_index (ifan->ifan_index);
189 if (ifp == NULL && ifan->ifan_what == IFAN_ARRIVAL)
190 {
191 /* Create Interface */
192 ifp = if_get_by_name (ifan->ifan_name);
193 ifp->ifindex = ifan->ifan_index;
194
195 if_add_update (ifp);
196 }
197 else if (ifp != NULL && ifan->ifan_what == IFAN_DEPARTURE)
198 {
199 if_delete_update (ifp);
200 if_delete (ifp);
201 }
202
203 if_get_flags (ifp);
204 if_get_mtu (ifp);
205 if_get_metric (ifp);
206
207 if (IS_ZEBRA_DEBUG_KERNEL)
208 zlog_info ("interface %s index %d", ifp->name, ifp->ifindex);
209
210 return 0;
211}
212#endif /* RTM_IFANNOUNCE */
213
da26e3b6 214/*
215 * Handle struct if_msghdr obtained from reading routing socket or
216 * sysctl (from interface_list). There may or may not be sockaddrs
217 * present after the header.
218 */
718e3744 219int
220ifm_read (struct if_msghdr *ifm)
221{
3e95a074 222 struct interface *ifp = NULL;
718e3744 223 struct sockaddr_dl *sdl = NULL;
3e95a074 224 char ifname[IFNAMSIZ];
225
da26e3b6 226 /* paranoia: sanity check structure */
227 if (ifm->ifm_msglen < sizeof(struct if_msghdr))
228 {
229 zlog_err ("ifm_read: ifm->ifm_msglen %d too short\n",
230 ifm->ifm_msglen);
231 return -1;
232 }
233
234 /*
235 * Check for a sockaddr_dl following the message.
236 */
3e95a074 237#ifdef SUNOS_5
238 int i;
239 struct sockaddr *sa;
240 u_char *cp = (u_char *)(ifm + 1);
718e3744 241
3e95a074 242 /*
243 * if_msghdr_t on 64 bit kernels in Solaris 9 and earlier versions
244 * is 12 bytes larger than the 32 bit version, so make adjustment
245 * here.
246 */
247 sa = (struct sockaddr *)cp;
248 if (sa->sa_family == AF_UNSPEC)
249 cp = cp + 12;
250
251 for (i = 1; i != 0; i <<= 1)
252 {
253 if (i & ifm->ifm_addrs)
254 {
255 sa = (struct sockaddr *)cp;
256 cp += WRAPUP(sa);
257 if (i & RTA_IFP)
258 {
259 sdl = (struct sockaddr_dl *)sa;
260 break;
261 }
262 }
263 }
da26e3b6 264 /*
265 * After here, If RTA_IFP was set in ifm_addrs, sdl should point to
266 * the sockaddr_dl.
267 */
3e95a074 268#else
da26e3b6 269 /* sockaddrs_present? */
270 if (ifm->ifm_addrs)
271 {
272 if (ifm->ifm_addrs == RTA_IFP)
273 {
274 /* just the one we want */
275 sdl = (struct sockaddr_dl *)(ifm + 1);
276 }
277 else
278 {
279 /*
280 * Not strictly an error, but more complicated parsing than
281 * is implemented is required to handle this case.
282 */
283 zlog_err ("ifm_read: addrs %x != RTA_IFP (unhandled, ignoring)\n",
284 ifm->ifm_addrs);
285 return -1;
286 }
287 }
288 /*
289 * Past here, either ifm_addrs == 0 or ifm_addrs == RTA_IFP and sdl
290 * points to a RTA_IFP sockaddr.
291 */
3e95a074 292#endif
718e3744 293
da26e3b6 294 /* Check that sdl, if present, is actually a sockaddr_dl before use. */
295 if (sdl != NULL)
296 switch (sdl->sdl_family)
297 {
298 case AF_LINK:
299 /* Standard AF for link-layer address sockaddrs. */
300 case AF_DLI:
301 /*
302 * XXX Comment in NetBSD net/if_dl.h says AF_DLI, but this
303 * seems wrong. Accept it for now.
304 */
305 break;
306
307 default:
308 zlog_err ("ifm_read: sockaddr_dl bad AF %d\n",
309 sdl->sdl_family);
310 return -1;
311 }
312
3e95a074 313 /*
da26e3b6 314 * Look up on ifindex. This is useful if this is an up/down
315 * notification for an interface of which we are already aware.
316 * (This happens on NetBSD 1.6.2, for example.)
3e95a074 317 */
da26e3b6 318 if (ifp == NULL)
319 ifp = if_lookup_by_index (ifm->ifm_index);
320
da26e3b6 321 /*
322 * If lookup by index was unsuccessful and we have a name, try
323 * looking up by name. Interfaces specified in the configuration
324 * file for which the ifindex has not been determined will have
325 * ifindex == -1, and such interfaces are found by this search, and
326 * then their ifindex values can be filled in.
327 */
cb42c035 328 if (ifp == NULL && sdl != NULL)
3e95a074 329 {
da26e3b6 330 /*
331 * paranoia: sanity check name length. nlen does not include
332 * trailing zero, but IFNAMSIZ max length does.
333 */
334 if (sdl->sdl_nlen >= IFNAMSIZ)
335 {
336 zlog_err ("ifm_read: illegal sdl_nlen %d\n", sdl->sdl_nlen);
337 return -1;
338 }
339
30be8028 340 memcpy (ifname, sdl->sdl_data, sdl->sdl_nlen);
3e95a074 341 ifname[sdl->sdl_nlen] = '\0';
342 ifp = if_lookup_by_name (ifname);
343 }
718e3744 344
da26e3b6 345 /*
346 * If ifp does not exist or has an invalid index (-1), create or
347 * fill in an interface.
348 */
3e95a074 349 if ((ifp == NULL) || (ifp->ifindex == -1))
718e3744 350 {
351 /* Check interface's address.*/
352 if (! (ifm->ifm_addrs & RTA_IFP))
353 {
da26e3b6 354 zlog_warn ("Interface index %d (new) missing RTA_IFP sockaddr\n",
718e3744 355 ifm->ifm_index);
356 return -1;
357 }
358
da26e3b6 359 /*
360 * paranoia: sdl-finding code above guarantees that sdl is
361 * non-NULL and valid if RTA_IFP is set in ifm_addrs, so this
362 * check is in theory not necessary.
363 */
364 if (sdl == NULL)
365 {
366 zlog_warn ("ifm_read: no sockaddr_dl present");
367 return -1;
368 }
369
3e95a074 370 if (ifp == NULL)
371 ifp = if_create (sdl->sdl_data, sdl->sdl_nlen);
718e3744 372
718e3744 373 ifp->ifindex = ifm->ifm_index;
374 ifp->flags = ifm->ifm_flags;
375#if defined(__bsdi__)
376 if_kvm_get_mtu (ifp);
377#else
378 if_get_mtu (ifp);
379#endif /* __bsdi__ */
380 if_get_metric (ifp);
381
382 /* Fetch hardware address. */
383 if (sdl->sdl_family != AF_LINK)
384 {
385 zlog_warn ("sockaddr_dl->sdl_family is not AF_LINK");
386 return -1;
387 }
da26e3b6 388 /* XXX sockaddr_dl can be larger than base structure */
718e3744 389 memcpy (&ifp->sdl, sdl, sizeof (struct sockaddr_dl));
390
391 if_add_update (ifp);
392 }
393 else
da26e3b6 394 /*
395 * Interface structure exists. Adjust stored flags from
396 * notification. If interface has up->down or down->up
397 * transition, call state change routines (to adjust routes,
398 * notify routing daemons, etc.). (Other flag changes are stored
399 * but apparently do not trigger action.)
400 */
718e3744 401 {
718e3744 402 if (if_is_up (ifp))
403 {
404 ifp->flags = ifm->ifm_flags;
405 if (! if_is_up (ifp))
406 if_down (ifp);
407 }
408 else
409 {
410 ifp->flags = ifm->ifm_flags;
411 if (if_is_up (ifp))
412 if_up (ifp);
413 }
414 }
415
416#ifdef HAVE_NET_RT_IFLIST
417 ifp->stats = ifm->ifm_data;
418#endif /* HAVE_NET_RT_IFLIST */
419
420 if (IS_ZEBRA_DEBUG_KERNEL)
421 zlog_info ("interface %s index %d", ifp->name, ifp->ifindex);
422
423 return 0;
424}
425\f
426/* Address read from struct ifa_msghdr. */
427void
428ifam_read_mesg (struct ifa_msghdr *ifm,
429 union sockunion *addr,
430 union sockunion *mask,
431 union sockunion *dest)
432{
433 caddr_t pnt, end;
434
435 pnt = (caddr_t)(ifm + 1);
436 end = ((caddr_t)ifm) + ifm->ifam_msglen;
437
438#define IFAMADDRGET(X,R) \
439 if (ifm->ifam_addrs & (R)) \
440 { \
441 int len = WRAPUP(pnt); \
442 if (((X) != NULL) && af_check (((struct sockaddr *)pnt)->sa_family)) \
443 memcpy ((caddr_t)(X), pnt, len); \
444 pnt += len; \
445 }
446#define IFAMMASKGET(X,R) \
447 if (ifm->ifam_addrs & (R)) \
448 { \
449 int len = WRAPUP(pnt); \
450 if ((X) != NULL) \
451 memcpy ((caddr_t)(X), pnt, len); \
452 pnt += len; \
453 }
454
455 /* Be sure structure is cleared */
456 memset (mask, 0, sizeof (union sockunion));
457 memset (addr, 0, sizeof (union sockunion));
458 memset (dest, 0, sizeof (union sockunion));
459
460 /* We fetch each socket variable into sockunion. */
461 IFAMADDRGET (NULL, RTA_DST);
462 IFAMADDRGET (NULL, RTA_GATEWAY);
463 IFAMMASKGET (mask, RTA_NETMASK);
464 IFAMADDRGET (NULL, RTA_GENMASK);
465 IFAMADDRGET (NULL, RTA_IFP);
466 IFAMADDRGET (addr, RTA_IFA);
467 IFAMADDRGET (NULL, RTA_AUTHOR);
468 IFAMADDRGET (dest, RTA_BRD);
469
470 /* Assert read up end point matches to end point */
471 if (pnt != end)
472 zlog_warn ("ifam_read() does't read all socket data");
473}
474
475/* Interface's address information get. */
476int
477ifam_read (struct ifa_msghdr *ifam)
478{
479 struct interface *ifp;
480 union sockunion addr, mask, gate;
481
482 /* Check does this interface exist or not. */
483 ifp = if_lookup_by_index (ifam->ifam_index);
484 if (ifp == NULL)
485 {
486 zlog_warn ("no interface for index %d", ifam->ifam_index);
487 return -1;
488 }
489
490 /* Allocate and read address information. */
491 ifam_read_mesg (ifam, &addr, &mask, &gate);
492
493 /* Check interface flag for implicit up of the interface. */
494 if_refresh (ifp);
495
496 /* Add connected address. */
497 switch (sockunion_family (&addr))
498 {
499 case AF_INET:
500 if (ifam->ifam_type == RTM_NEWADDR)
501 connected_add_ipv4 (ifp, 0, &addr.sin.sin_addr,
502 ip_masklen (mask.sin.sin_addr),
503 &gate.sin.sin_addr, NULL);
504 else
505 connected_delete_ipv4 (ifp, 0, &addr.sin.sin_addr,
506 ip_masklen (mask.sin.sin_addr),
507 &gate.sin.sin_addr, NULL);
508 break;
509#ifdef HAVE_IPV6
510 case AF_INET6:
511 /* Unset interface index from link-local address when IPv6 stack
512 is KAME. */
513 if (IN6_IS_ADDR_LINKLOCAL (&addr.sin6.sin6_addr))
514 SET_IN6_LINKLOCAL_IFINDEX (addr.sin6.sin6_addr, 0);
515
516 if (ifam->ifam_type == RTM_NEWADDR)
517 connected_add_ipv6 (ifp,
518 &addr.sin6.sin6_addr,
519 ip6_masklen (mask.sin6.sin6_addr),
520 &gate.sin6.sin6_addr);
521 else
522 connected_delete_ipv6 (ifp,
523 &addr.sin6.sin6_addr,
524 ip6_masklen (mask.sin6.sin6_addr),
525 &gate.sin6.sin6_addr);
526 break;
527#endif /* HAVE_IPV6 */
528 default:
529 /* Unsupported family silently ignore... */
530 break;
531 }
532 return 0;
533}
534\f
535/* Interface function for reading kernel routing table information. */
536int
537rtm_read_mesg (struct rt_msghdr *rtm,
538 union sockunion *dest,
539 union sockunion *mask,
540 union sockunion *gate)
541{
542 caddr_t pnt, end;
543
544 /* Pnt points out socket data start point. */
545 pnt = (caddr_t)(rtm + 1);
546 end = ((caddr_t)rtm) + rtm->rtm_msglen;
547
548 /* rt_msghdr version check. */
549 if (rtm->rtm_version != RTM_VERSION)
550 zlog (NULL, LOG_WARNING,
551 "Routing message version different %d should be %d."
552 "This may cause problem\n", rtm->rtm_version, RTM_VERSION);
553
554#define RTMADDRGET(X,R) \
555 if (rtm->rtm_addrs & (R)) \
556 { \
557 int len = WRAPUP (pnt); \
558 if (((X) != NULL) && af_check (((struct sockaddr *)pnt)->sa_family)) \
559 memcpy ((caddr_t)(X), pnt, len); \
560 pnt += len; \
561 }
562#define RTMMASKGET(X,R) \
563 if (rtm->rtm_addrs & (R)) \
564 { \
565 int len = WRAPUP (pnt); \
566 if ((X) != NULL) \
567 memcpy ((caddr_t)(X), pnt, len); \
568 pnt += len; \
569 }
570
571 /* Be sure structure is cleared */
572 memset (dest, 0, sizeof (union sockunion));
573 memset (gate, 0, sizeof (union sockunion));
574 memset (mask, 0, sizeof (union sockunion));
575
576 /* We fetch each socket variable into sockunion. */
577 RTMADDRGET (dest, RTA_DST);
578 RTMADDRGET (gate, RTA_GATEWAY);
579 RTMMASKGET (mask, RTA_NETMASK);
580 RTMADDRGET (NULL, RTA_GENMASK);
581 RTMADDRGET (NULL, RTA_IFP);
582 RTMADDRGET (NULL, RTA_IFA);
583 RTMADDRGET (NULL, RTA_AUTHOR);
584 RTMADDRGET (NULL, RTA_BRD);
585
586 /* If there is netmask information set it's family same as
587 destination family*/
588 if (rtm->rtm_addrs & RTA_NETMASK)
589 mask->sa.sa_family = dest->sa.sa_family;
590
591 /* Assert read up to the end of pointer. */
592 if (pnt != end)
593 zlog (NULL, LOG_WARNING, "rtm_read() does't read all socket data.");
594
595 return rtm->rtm_flags;
596}
597
598void
599rtm_read (struct rt_msghdr *rtm)
600{
601 int flags;
602 u_char zebra_flags;
603 union sockunion dest, mask, gate;
604
605 zebra_flags = 0;
606
607 /* Discard self send message. */
608 if (rtm->rtm_type != RTM_GET
609 && (rtm->rtm_pid == pid || rtm->rtm_pid == old_pid))
610 return;
611
612 /* Read destination and netmask and gateway from rtm message
613 structure. */
614 flags = rtm_read_mesg (rtm, &dest, &mask, &gate);
615
616#ifdef RTF_CLONED /*bsdi, netbsd 1.6*/
617 if (flags & RTF_CLONED)
618 return;
619#endif
620#ifdef RTF_WASCLONED /*freebsd*/
621 if (flags & RTF_WASCLONED)
622 return;
623#endif
624
625 if ((rtm->rtm_type == RTM_ADD) && ! (flags & RTF_UP))
626 return;
627
628 /* This is connected route. */
629 if (! (flags & RTF_GATEWAY))
630 return;
631
632 if (flags & RTF_PROTO1)
633 SET_FLAG (zebra_flags, ZEBRA_FLAG_SELFROUTE);
634
635 /* This is persistent route. */
636 if (flags & RTF_STATIC)
637 SET_FLAG (zebra_flags, ZEBRA_FLAG_STATIC);
638
81dfcaa2 639 /* This is a reject or blackhole route */
640 if (flags & RTF_REJECT)
641 SET_FLAG (zebra_flags, ZEBRA_FLAG_REJECT);
642 if (flags & RTF_BLACKHOLE)
643 SET_FLAG (zebra_flags, ZEBRA_FLAG_BLACKHOLE);
644
718e3744 645 if (dest.sa.sa_family == AF_INET)
646 {
647 struct prefix_ipv4 p;
648
649 p.family = AF_INET;
650 p.prefix = dest.sin.sin_addr;
651 if (flags & RTF_HOST)
652 p.prefixlen = IPV4_MAX_PREFIXLEN;
653 else
654 p.prefixlen = ip_masklen (mask.sin.sin_addr);
655
656 if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD)
657 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags,
658 &p, &gate.sin.sin_addr, 0, 0, 0, 0);
659 else
660 rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags,
661 &p, &gate.sin.sin_addr, 0, 0);
662 }
663#ifdef HAVE_IPV6
664 if (dest.sa.sa_family == AF_INET6)
665 {
666 struct prefix_ipv6 p;
667 unsigned int ifindex = 0;
668
669 p.family = AF_INET6;
670 p.prefix = dest.sin6.sin6_addr;
671 if (flags & RTF_HOST)
672 p.prefixlen = IPV6_MAX_PREFIXLEN;
673 else
674 p.prefixlen = ip6_masklen (mask.sin6.sin6_addr);
675
676#ifdef KAME
677 if (IN6_IS_ADDR_LINKLOCAL (&gate.sin6.sin6_addr))
678 {
679 ifindex = IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr);
680 SET_IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr, 0);
681 }
682#endif /* KAME */
683
684 if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD)
685 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags,
686 &p, &gate.sin6.sin6_addr, ifindex, 0);
687 else
688 rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags,
689 &p, &gate.sin6.sin6_addr, ifindex, 0);
690 }
691#endif /* HAVE_IPV6 */
692}
693
694/* Interface function for the kernel routing table updates. Support
695 for RTM_CHANGE will be needed. */
696int
697rtm_write (int message,
698 union sockunion *dest,
699 union sockunion *mask,
700 union sockunion *gate,
701 unsigned int index,
702 int zebra_flags,
703 int metric)
704{
705 int ret;
706 caddr_t pnt;
707 struct interface *ifp;
708 struct sockaddr_in tmp_gate;
709#ifdef HAVE_IPV6
710 struct sockaddr_in6 tmp_gate6;
711#endif /* HAVE_IPV6 */
712
713 /* Sequencial number of routing message. */
714 static int msg_seq = 0;
715
716 /* Struct of rt_msghdr and buffer for storing socket's data. */
717 struct
718 {
719 struct rt_msghdr rtm;
720 char buf[512];
721 } msg;
722
723 memset (&tmp_gate, 0, sizeof (struct sockaddr_in));
724 tmp_gate.sin_family = AF_INET;
725#ifdef HAVE_SIN_LEN
726 tmp_gate.sin_len = sizeof (struct sockaddr_in);
727#endif /* HAVE_SIN_LEN */
728
729#ifdef HAVE_IPV6
730 memset (&tmp_gate6, 0, sizeof (struct sockaddr_in6));
731 tmp_gate6.sin6_family = AF_INET6;
732#ifdef SIN6_LEN
733 tmp_gate6.sin6_len = sizeof (struct sockaddr_in6);
734#endif /* SIN6_LEN */
735#endif /* HAVE_IPV6 */
736
737 if (routing_sock < 0)
738 return ZEBRA_ERR_EPERM;
739
740 /* Clear and set rt_msghdr values */
741 memset (&msg, 0, sizeof (struct rt_msghdr));
742 msg.rtm.rtm_version = RTM_VERSION;
743 msg.rtm.rtm_type = message;
744 msg.rtm.rtm_seq = msg_seq++;
745 msg.rtm.rtm_addrs = RTA_DST;
746 msg.rtm.rtm_addrs |= RTA_GATEWAY;
747 msg.rtm.rtm_flags = RTF_UP;
748 msg.rtm.rtm_index = index;
749
750 if (metric != 0)
751 {
752 msg.rtm.rtm_rmx.rmx_hopcount = metric;
753 msg.rtm.rtm_inits |= RTV_HOPCOUNT;
754 }
755
756 ifp = if_lookup_by_index (index);
757
758 if (gate && message == RTM_ADD)
759 msg.rtm.rtm_flags |= RTF_GATEWAY;
760
761 if (! gate && message == RTM_ADD && ifp &&
762 (ifp->flags & IFF_POINTOPOINT) == 0)
763 msg.rtm.rtm_flags |= RTF_CLONING;
764
765 /* If no protocol specific gateway is specified, use link
766 address for gateway. */
767 if (! gate)
768 {
769 if (!ifp)
770 {
771 zlog_warn ("no gateway found for interface index %d", index);
772 return -1;
773 }
774 gate = (union sockunion *) & ifp->sdl;
775 }
776
777 if (mask)
778 msg.rtm.rtm_addrs |= RTA_NETMASK;
779 else if (message == RTM_ADD)
780 msg.rtm.rtm_flags |= RTF_HOST;
781
782 /* Tagging route with flags */
783 msg.rtm.rtm_flags |= (RTF_PROTO1);
784
785 /* Additional flags. */
786 if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
787 msg.rtm.rtm_flags |= RTF_BLACKHOLE;
81dfcaa2 788 if (zebra_flags & ZEBRA_FLAG_REJECT)
789 msg.rtm.rtm_flags |= RTF_REJECT;
790
718e3744 791
792#ifdef HAVE_SIN_LEN
793#define SOCKADDRSET(X,R) \
794 if (msg.rtm.rtm_addrs & (R)) \
795 { \
796 int len = ROUNDUP ((X)->sa.sa_len); \
797 memcpy (pnt, (caddr_t)(X), len); \
798 pnt += len; \
799 }
800#else
801#define SOCKADDRSET(X,R) \
802 if (msg.rtm.rtm_addrs & (R)) \
803 { \
804 int len = ROUNDUP (sizeof((X)->sa)); \
805 memcpy (pnt, (caddr_t)(X), len); \
806 pnt += len; \
807 }
808#endif /* HAVE_SIN_LEN */
809
810 pnt = (caddr_t) msg.buf;
811
812 /* Write each socket data into rtm message buffer */
813 SOCKADDRSET (dest, RTA_DST);
814 SOCKADDRSET (gate, RTA_GATEWAY);
815 SOCKADDRSET (mask, RTA_NETMASK);
816
817 msg.rtm.rtm_msglen = pnt - (caddr_t) &msg;
818
819 ret = write (routing_sock, &msg, msg.rtm.rtm_msglen);
820
821 if (ret != msg.rtm.rtm_msglen)
822 {
823 if (errno == EEXIST)
824 return ZEBRA_ERR_RTEXIST;
825 if (errno == ENETUNREACH)
826 return ZEBRA_ERR_RTUNREACH;
827
828 zlog_warn ("write : %s (%d)", strerror (errno), errno);
829 return -1;
830 }
831 return 0;
832}
833
834\f
835#include "thread.h"
836#include "zebra/zserv.h"
837
718e3744 838/* For debug purpose. */
839void
840rtmsg_debug (struct rt_msghdr *rtm)
841{
842 char *type = "Unknown";
843 struct message *mes;
844
845 for (mes = rtm_type_str; mes->str; mes++)
846 if (mes->key == rtm->rtm_type)
847 {
848 type = mes->str;
849 break;
850 }
851
852 zlog_info ("Kernel: Len: %d Type: %s", rtm->rtm_msglen, type);
853 rtm_flag_dump (rtm->rtm_flags);
854 zlog_info ("Kernel: message seq %d", rtm->rtm_seq);
855 zlog_info ("Kernel: pid %d", rtm->rtm_pid);
856}
857
858/* This is pretty gross, better suggestions welcome -- mhandler */
859#ifndef RTAX_MAX
860#ifdef RTA_NUMBITS
861#define RTAX_MAX RTA_NUMBITS
862#else
863#define RTAX_MAX 8
864#endif /* RTA_NUMBITS */
865#endif /* RTAX_MAX */
866
867/* Kernel routing table and interface updates via routing socket. */
868int
869kernel_read (struct thread *thread)
870{
871 int sock;
872 int nbytes;
873 struct rt_msghdr *rtm;
874
875 union
876 {
877 /* Routing information. */
878 struct
879 {
880 struct rt_msghdr rtm;
881 struct sockaddr addr[RTAX_MAX];
882 } r;
883
884 /* Interface information. */
885 struct
886 {
887 struct if_msghdr ifm;
888 struct sockaddr addr[RTAX_MAX];
889 } im;
890
891 /* Interface address information. */
892 struct
893 {
894 struct ifa_msghdr ifa;
895 struct sockaddr addr[RTAX_MAX];
896 } ia;
897
898#ifdef RTM_IFANNOUNCE
899 /* Interface arrival/departure */
900 struct
901 {
902 struct if_announcemsghdr ifan;
903 struct sockaddr addr[RTAX_MAX];
904 } ian;
905#endif /* RTM_IFANNOUNCE */
906
907 } buf;
908
909 /* Fetch routing socket. */
910 sock = THREAD_FD (thread);
911
912 nbytes= read (sock, &buf, sizeof buf);
913
914 if (nbytes <= 0)
915 {
916 if (nbytes < 0 && errno != EWOULDBLOCK && errno != EAGAIN)
917 zlog_warn ("routing socket error: %s", strerror (errno));
918 return 0;
919 }
920
9bcdb638 921 thread_add_read (zebrad.master, kernel_read, NULL, sock);
718e3744 922
726f9b2b 923 if (IS_ZEBRA_DEBUG_KERNEL)
924 rtmsg_debug (&buf.r.rtm);
718e3744 925
926 rtm = &buf.r.rtm;
927
da26e3b6 928 if (rtm->rtm_msglen != nbytes)
929 {
930 zlog_warn ("kernel_read: rtm->rtm_msglen %d, nbytes %d, type %d\n",
931 rtm->rtm_msglen, nbytes, rtm->rtm_type);
932 return -1;
933 }
934
718e3744 935 switch (rtm->rtm_type)
936 {
937 case RTM_ADD:
938 case RTM_DELETE:
939 rtm_read (rtm);
940 break;
941 case RTM_IFINFO:
942 ifm_read (&buf.im.ifm);
943 break;
944 case RTM_NEWADDR:
945 case RTM_DELADDR:
946 ifam_read (&buf.ia.ifa);
947 break;
948#ifdef RTM_IFANNOUNCE
949 case RTM_IFANNOUNCE:
950 ifan_read (&buf.ian.ifan);
951 break;
952#endif /* RTM_IFANNOUNCE */
953 default:
726f9b2b 954 if (IS_ZEBRA_DEBUG_KERNEL)
955 zlog_info("Unprocessed RTM_type: %d", rtm->rtm_type);
718e3744 956 break;
957 }
958 return 0;
959}
960
961/* Make routing socket. */
962void
963routing_socket ()
964{
edd7c245 965 if ( zserv_privs.change (ZPRIVS_RAISE) )
966 zlog_err ("routing_socket: Can't raise privileges");
967
718e3744 968 routing_sock = socket (AF_ROUTE, SOCK_RAW, 0);
969
970 if (routing_sock < 0)
971 {
edd7c245 972 if ( zserv_privs.change (ZPRIVS_LOWER) )
973 zlog_err ("routing_socket: Can't lower privileges");
718e3744 974 zlog_warn ("Can't init kernel routing socket");
975 return;
976 }
977
978 if (fcntl (routing_sock, F_SETFL, O_NONBLOCK) < 0)
979 zlog_warn ("Can't set O_NONBLOCK to routing socket");
edd7c245 980 if ( zserv_privs.change (ZPRIVS_LOWER) )
981 zlog_err ("routing_socket: Can't lower privileges");
718e3744 982
983 /* kernel_read needs rewrite. */
9bcdb638 984 thread_add_read (zebrad.master, kernel_read, NULL, routing_sock);
718e3744 985}
986
987/* Exported interface function. This function simply calls
988 routing_socket (). */
989void
990kernel_init ()
991{
992 routing_socket ();
993}