1 /* Kernel communication using routing socket.
2 * Copyright (C) 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
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
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.
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
26 #include "sockunion.h"
27 #include "connected.h"
36 #include "zebra/interface.h"
37 #include "zebra/zserv.h"
38 #include "zebra/debug.h"
40 extern struct zebra_privs_t zserv_privs
;
41 extern struct zebra_t zebrad
;
44 * Given a sockaddr length, round it up to include pad bytes following
45 * it. Assumes the kernel pads to sizeof(long).
47 * XXX: why is ROUNDUP(0) sizeof(long)? 0 is an illegal sockaddr
48 * length anyway (< sizeof (struct sockaddr)), so this shouldn't
52 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
55 * Given a pointer (sockaddr or void *), return the number of bytes
56 * taken up by the sockaddr and any padding needed for alignment.
58 #if defined(HAVE_SA_LEN)
59 #define SAROUNDUP(X) ROUNDUP(((struct sockaddr *)(X))->sa_len)
60 #elif defined(HAVE_IPV6)
62 * One would hope all fixed-size structure definitions are aligned,
63 * but round them up nonetheless.
65 #define SAROUNDUP(X) \
66 (((struct sockaddr *)(X))->sa_family == AF_INET ? \
67 ROUNDUP(sizeof(struct sockaddr_in)):\
68 (((struct sockaddr *)(X))->sa_family == AF_INET6 ? \
69 ROUNDUP(sizeof(struct sockaddr_in6)) : \
70 (((struct sockaddr *)(X))->sa_family == AF_LINK ? \
71 ROUNDUP(sizeof(struct sockaddr_dl)) : sizeof(struct sockaddr))))
73 #define SAROUNDUP(X) \
74 (((struct sockaddr *)(X))->sa_family == AF_INET ? \
75 ROUNDUP(sizeof(struct sockaddr_in)):\
76 (((struct sockaddr *)(X))->sa_family == AF_LINK ? \
77 ROUNDUP(sizeof(struct sockaddr_dl)) : sizeof(struct sockaddr)))
78 #endif /* HAVE_SA_LEN */
80 /* Routing socket message types. */
81 struct message rtm_type_str
[] =
84 {RTM_DELETE
, "RTM_DELETE"},
85 {RTM_CHANGE
, "RTM_CHANGE"},
87 {RTM_LOSING
, "RTM_LOSING"},
88 {RTM_REDIRECT
, "RTM_REDIRECT"},
89 {RTM_MISS
, "RTM_MISS"},
90 {RTM_LOCK
, "RTM_LOCK"},
91 {RTM_OLDADD
, "RTM_OLDADD"},
92 {RTM_OLDDEL
, "RTM_OLDDEL"},
93 {RTM_RESOLVE
, "RTM_RESOLVE"},
94 {RTM_NEWADDR
, "RTM_NEWADDR"},
95 {RTM_DELADDR
, "RTM_DELADDR"},
96 {RTM_IFINFO
, "RTM_IFINFO"},
98 {RTM_OIFINFO
, "RTM_OIFINFO"},
99 #endif /* RTM_OIFINFO */
101 {RTM_NEWMADDR
, "RTM_NEWMADDR"},
102 #endif /* RTM_NEWMADDR */
104 {RTM_DELMADDR
, "RTM_DELMADDR"},
105 #endif /* RTM_DELMADDR */
106 #ifdef RTM_IFANNOUNCE
107 {RTM_IFANNOUNCE
, "RTM_IFANNOUNCE"},
108 #endif /* RTM_IFANNOUNCE */
112 struct message rtm_flag_str
[] =
115 {RTF_GATEWAY
, "GATEWAY"},
117 {RTF_REJECT
, "REJECT"},
118 {RTF_DYNAMIC
, "DYNAMIC"},
119 {RTF_MODIFIED
, "MODIFIED"},
123 #endif /* RTF_MASK */
124 {RTF_CLONING
, "CLONING"},
125 {RTF_XRESOLVE
, "XRESOLVE"},
126 {RTF_LLINFO
, "LLINFO"},
127 {RTF_STATIC
, "STATIC"},
128 {RTF_BLACKHOLE
, "BLACKHOLE"},
129 {RTF_PROTO1
, "PROTO1"},
130 {RTF_PROTO2
, "PROTO2"},
132 {RTF_PRCLONING
, "PRCLONING"},
133 #endif /* RTF_PRCLONING */
135 {RTF_WASCLONED
, "WASCLONED"},
136 #endif /* RTF_WASCLONED */
138 {RTF_PROTO3
, "PROTO3"},
139 #endif /* RTF_PROTO3 */
141 {RTF_PINNED
, "PINNED"},
142 #endif /* RTF_PINNED */
144 {RTF_LOCAL
, "LOCAL"},
145 #endif /* RTF_LOCAL */
147 {RTF_BROADCAST
, "BROADCAST"},
148 #endif /* RTF_BROADCAST */
150 {RTF_MULTICAST
, "MULTICAST"},
151 #endif /* RTF_MULTICAST */
155 /* Kernel routing update socket. */
156 int routing_sock
= -1;
158 /* Yes I'm checking ugly routing socket behavior. */
161 /* Supported address family check. */
163 af_check (int family
)
165 if (family
== AF_INET
)
168 if (family
== AF_INET6
)
170 #endif /* HAVE_IPV6 */
174 /* Dump routing table flag for debug purpose. */
176 rtm_flag_dump (int flag
)
179 static char buf
[BUFSIZ
];
182 for (mes
= rtm_flag_str
; mes
->key
!= 0; mes
++)
186 strlcat (buf
, mes
->str
, BUFSIZ
);
187 strlcat (buf
, " ", BUFSIZ
);
190 zlog_debug ("Kernel: %s", buf
);
193 #ifdef RTM_IFANNOUNCE
194 /* Interface adding function */
196 ifan_read (struct if_announcemsghdr
*ifan
)
198 struct interface
*ifp
;
200 ifp
= if_lookup_by_index (ifan
->ifan_index
);
201 if (ifp
== NULL
&& ifan
->ifan_what
== IFAN_ARRIVAL
)
203 /* Create Interface */
204 ifp
= if_get_by_name (ifan
->ifan_name
);
205 ifp
->ifindex
= ifan
->ifan_index
;
209 else if (ifp
!= NULL
&& ifan
->ifan_what
== IFAN_DEPARTURE
)
211 if_delete_update (ifp
);
219 if (IS_ZEBRA_DEBUG_KERNEL
)
220 zlog_debug ("interface %s index %d", ifp
->name
, ifp
->ifindex
);
224 #endif /* RTM_IFANNOUNCE */
227 * Handle struct if_msghdr obtained from reading routing socket or
228 * sysctl (from interface_list). There may or may not be sockaddrs
229 * present after the header.
232 ifm_read (struct if_msghdr
*ifm
)
234 struct interface
*ifp
= NULL
;
235 struct sockaddr_dl
*sdl
= NULL
;
238 char ifname
[IFNAMSIZ
];
240 /* paranoia: sanity check structure */
241 if (ifm
->ifm_msglen
< sizeof(struct if_msghdr
))
243 zlog_err ("ifm_read: ifm->ifm_msglen %d too short\n",
249 * Check for a sockaddr_dl following the message. First, point to
250 * where a socakddr might be if one follows the message.
252 cp
= (void *)(ifm
+ 1);
256 * XXX This behavior should be narrowed to only the kernel versions
257 * for which the structures returned do not match the headers.
259 * if_msghdr_t on 64 bit kernels in Solaris 9 and earlier versions
260 * is 12 bytes larger than the 32 bit version.
262 if (((struct sockaddr
*) cp
)->sa_family
== AF_UNSPEC
)
267 * Check for each sockaddr in turn, advancing over it. After this
268 * loop, sdl should point to a sockaddr_dl iff one was present.
270 for (i
= 1; i
!= 0; i
<<= 1)
272 if (i
& ifm
->ifm_addrs
)
276 sdl
= (struct sockaddr_dl
*)cp
;
279 /* XXX warning: pointer of type `void *' used in arithmetic */
284 /* Ensure that sdl, if present, is actually a sockaddr_dl. */
285 if (sdl
!= NULL
&& sdl
->sdl_family
!= AF_LINK
)
287 zlog_err ("ifm_read: sockaddr_dl bad AF %d\n",
293 * Look up on ifindex first, because ifindices are the primary
294 * handle for interfaces across the user/kernel boundary. (Some
295 * messages, such as up/down status changes on NetBSD, do not
296 * include a sockaddr_dl).
298 ifp
= if_lookup_by_index (ifm
->ifm_index
);
301 * If lookup by index was unsuccessful and we have a name, try
302 * looking up by name. Interfaces specified in the configuration
303 * file for which the ifindex has not been determined will have
304 * ifindex == IFINDEX_INTERNAL, and such interfaces are found by this search,
305 * and then their ifindex values can be filled in.
307 if (ifp
== NULL
&& sdl
!= NULL
)
310 * paranoia: sanity check name length. nlen does not include
311 * trailing zero, but IFNAMSIZ max length does.
313 if (sdl
->sdl_nlen
>= IFNAMSIZ
)
315 zlog_err ("ifm_read: illegal sdl_nlen %d\n", sdl
->sdl_nlen
);
319 memcpy (ifname
, sdl
->sdl_data
, sdl
->sdl_nlen
);
320 ifname
[sdl
->sdl_nlen
] = '\0';
321 ifp
= if_lookup_by_name (ifname
);
325 * If ifp does not exist or has an invalid index (IFINDEX_INTERNAL), create or
326 * fill in an interface.
328 if ((ifp
== NULL
) || (ifp
->ifindex
== IFINDEX_INTERNAL
))
331 * To create or fill in an interface, a sockaddr_dl (via
332 * RTA_IFP) is required.
336 zlog_warn ("Interface index %d (new) missing RTA_IFP sockaddr_dl\n",
342 /* Interface that zebra was not previously aware of, so create. */
343 ifp
= if_create (sdl
->sdl_data
, sdl
->sdl_nlen
);
346 * Fill in newly created interface structure, or larval
347 * structure with ifindex IFINDEX_INTERNAL.
349 ifp
->ifindex
= ifm
->ifm_index
;
350 ifp
->flags
= ifm
->ifm_flags
;
351 #if defined(__bsdi__)
352 if_kvm_get_mtu (ifp
);
355 #endif /* __bsdi__ */
359 * XXX sockaddr_dl contents can be larger than the structure
360 * definition, so the user of the stored structure must be
361 * careful not to read off the end.
363 memcpy (&ifp
->sdl
, sdl
, sizeof (struct sockaddr_dl
));
369 * Interface structure exists. Adjust stored flags from
370 * notification. If interface has up->down or down->up
371 * transition, call state change routines (to adjust routes,
372 * notify routing daemons, etc.). (Other flag changes are stored
373 * but apparently do not trigger action.)
378 ifp
->flags
= ifm
->ifm_flags
;
379 if (! if_is_up (ifp
))
384 ifp
->flags
= ifm
->ifm_flags
;
390 #ifdef HAVE_NET_RT_IFLIST
391 ifp
->stats
= ifm
->ifm_data
;
392 #endif /* HAVE_NET_RT_IFLIST */
394 if (IS_ZEBRA_DEBUG_KERNEL
)
395 zlog_debug ("interface %s index %d", ifp
->name
, ifp
->ifindex
);
400 /* Address read from struct ifa_msghdr. */
402 ifam_read_mesg (struct ifa_msghdr
*ifm
,
403 union sockunion
*addr
,
404 union sockunion
*mask
,
405 union sockunion
*dest
)
409 pnt
= (caddr_t
)(ifm
+ 1);
410 end
= ((caddr_t
)ifm
) + ifm
->ifam_msglen
;
412 #define IFAMADDRGET(X,R) \
413 if (ifm->ifam_addrs & (R)) \
415 int len = SAROUNDUP(pnt); \
416 if (((X) != NULL) && af_check (((struct sockaddr *)pnt)->sa_family)) \
417 memcpy ((caddr_t)(X), pnt, len); \
420 #define IFAMMASKGET(X,R) \
421 if (ifm->ifam_addrs & (R)) \
423 int len = SAROUNDUP(pnt); \
425 memcpy ((caddr_t)(X), pnt, len); \
429 /* Be sure structure is cleared */
430 memset (mask
, 0, sizeof (union sockunion
));
431 memset (addr
, 0, sizeof (union sockunion
));
432 memset (dest
, 0, sizeof (union sockunion
));
434 /* We fetch each socket variable into sockunion. */
435 IFAMADDRGET (NULL
, RTA_DST
);
436 IFAMADDRGET (NULL
, RTA_GATEWAY
);
437 IFAMMASKGET (mask
, RTA_NETMASK
);
438 IFAMADDRGET (NULL
, RTA_GENMASK
);
439 IFAMADDRGET (NULL
, RTA_IFP
);
440 IFAMADDRGET (addr
, RTA_IFA
);
441 IFAMADDRGET (NULL
, RTA_AUTHOR
);
442 IFAMADDRGET (dest
, RTA_BRD
);
444 /* Assert read up end point matches to end point */
446 zlog_warn ("ifam_read() does't read all socket data");
449 /* Interface's address information get. */
451 ifam_read (struct ifa_msghdr
*ifam
)
453 struct interface
*ifp
;
454 union sockunion addr
, mask
, gate
;
456 /* Check does this interface exist or not. */
457 ifp
= if_lookup_by_index (ifam
->ifam_index
);
460 zlog_warn ("no interface for index %d", ifam
->ifam_index
);
464 /* Allocate and read address information. */
465 ifam_read_mesg (ifam
, &addr
, &mask
, &gate
);
467 /* Check interface flag for implicit up of the interface. */
470 /* Add connected address. */
471 switch (sockunion_family (&addr
))
474 if (ifam
->ifam_type
== RTM_NEWADDR
)
475 connected_add_ipv4 (ifp
, 0, &addr
.sin
.sin_addr
,
476 ip_masklen (mask
.sin
.sin_addr
),
477 &gate
.sin
.sin_addr
, NULL
);
479 connected_delete_ipv4 (ifp
, 0, &addr
.sin
.sin_addr
,
480 ip_masklen (mask
.sin
.sin_addr
),
481 &gate
.sin
.sin_addr
, NULL
);
485 /* Unset interface index from link-local address when IPv6 stack
487 if (IN6_IS_ADDR_LINKLOCAL (&addr
.sin6
.sin6_addr
))
488 SET_IN6_LINKLOCAL_IFINDEX (addr
.sin6
.sin6_addr
, 0);
490 if (ifam
->ifam_type
== RTM_NEWADDR
)
491 connected_add_ipv6 (ifp
,
492 &addr
.sin6
.sin6_addr
,
493 ip6_masklen (mask
.sin6
.sin6_addr
),
494 &gate
.sin6
.sin6_addr
);
496 connected_delete_ipv6 (ifp
,
497 &addr
.sin6
.sin6_addr
,
498 ip6_masklen (mask
.sin6
.sin6_addr
),
499 &gate
.sin6
.sin6_addr
);
501 #endif /* HAVE_IPV6 */
503 /* Unsupported family silently ignore... */
509 /* Interface function for reading kernel routing table information. */
511 rtm_read_mesg (struct rt_msghdr
*rtm
,
512 union sockunion
*dest
,
513 union sockunion
*mask
,
514 union sockunion
*gate
)
518 /* Pnt points out socket data start point. */
519 pnt
= (caddr_t
)(rtm
+ 1);
520 end
= ((caddr_t
)rtm
) + rtm
->rtm_msglen
;
522 /* rt_msghdr version check. */
523 if (rtm
->rtm_version
!= RTM_VERSION
)
524 zlog (NULL
, LOG_WARNING
,
525 "Routing message version different %d should be %d."
526 "This may cause problem\n", rtm
->rtm_version
, RTM_VERSION
);
528 #define RTMADDRGET(X,R) \
529 if (rtm->rtm_addrs & (R)) \
531 int len = SAROUNDUP (pnt); \
532 if (((X) != NULL) && af_check (((struct sockaddr *)pnt)->sa_family)) \
533 memcpy ((caddr_t)(X), pnt, len); \
536 #define RTMMASKGET(X,R) \
537 if (rtm->rtm_addrs & (R)) \
539 int len = SAROUNDUP (pnt); \
541 memcpy ((caddr_t)(X), pnt, len); \
545 /* Be sure structure is cleared */
546 memset (dest
, 0, sizeof (union sockunion
));
547 memset (gate
, 0, sizeof (union sockunion
));
548 memset (mask
, 0, sizeof (union sockunion
));
550 /* We fetch each socket variable into sockunion. */
551 RTMADDRGET (dest
, RTA_DST
);
552 RTMADDRGET (gate
, RTA_GATEWAY
);
553 RTMMASKGET (mask
, RTA_NETMASK
);
554 RTMADDRGET (NULL
, RTA_GENMASK
);
555 RTMADDRGET (NULL
, RTA_IFP
);
556 RTMADDRGET (NULL
, RTA_IFA
);
557 RTMADDRGET (NULL
, RTA_AUTHOR
);
558 RTMADDRGET (NULL
, RTA_BRD
);
560 /* If there is netmask information set it's family same as
562 if (rtm
->rtm_addrs
& RTA_NETMASK
)
563 mask
->sa
.sa_family
= dest
->sa
.sa_family
;
565 /* Assert read up to the end of pointer. */
567 zlog (NULL
, LOG_WARNING
, "rtm_read() does't read all socket data.");
569 return rtm
->rtm_flags
;
573 rtm_read (struct rt_msghdr
*rtm
)
577 union sockunion dest
, mask
, gate
;
581 /* Discard self send message. */
582 if (rtm
->rtm_type
!= RTM_GET
583 && (rtm
->rtm_pid
== pid
|| rtm
->rtm_pid
== old_pid
))
586 /* Read destination and netmask and gateway from rtm message
588 flags
= rtm_read_mesg (rtm
, &dest
, &mask
, &gate
);
590 #ifdef RTF_CLONED /*bsdi, netbsd 1.6*/
591 if (flags
& RTF_CLONED
)
594 #ifdef RTF_WASCLONED /*freebsd*/
595 if (flags
& RTF_WASCLONED
)
599 if ((rtm
->rtm_type
== RTM_ADD
) && ! (flags
& RTF_UP
))
602 /* This is connected route. */
603 if (! (flags
& RTF_GATEWAY
))
606 if (flags
& RTF_PROTO1
)
607 SET_FLAG (zebra_flags
, ZEBRA_FLAG_SELFROUTE
);
609 /* This is persistent route. */
610 if (flags
& RTF_STATIC
)
611 SET_FLAG (zebra_flags
, ZEBRA_FLAG_STATIC
);
613 /* This is a reject or blackhole route */
614 if (flags
& RTF_REJECT
)
615 SET_FLAG (zebra_flags
, ZEBRA_FLAG_REJECT
);
616 if (flags
& RTF_BLACKHOLE
)
617 SET_FLAG (zebra_flags
, ZEBRA_FLAG_BLACKHOLE
);
619 if (dest
.sa
.sa_family
== AF_INET
)
621 struct prefix_ipv4 p
;
624 p
.prefix
= dest
.sin
.sin_addr
;
625 if (flags
& RTF_HOST
)
626 p
.prefixlen
= IPV4_MAX_PREFIXLEN
;
628 p
.prefixlen
= ip_masklen (mask
.sin
.sin_addr
);
630 if (rtm
->rtm_type
== RTM_GET
|| rtm
->rtm_type
== RTM_ADD
)
631 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL
, zebra_flags
,
632 &p
, &gate
.sin
.sin_addr
, 0, 0, 0, 0);
634 rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL
, zebra_flags
,
635 &p
, &gate
.sin
.sin_addr
, 0, 0);
638 if (dest
.sa
.sa_family
== AF_INET6
)
640 struct prefix_ipv6 p
;
641 unsigned int ifindex
= 0;
644 p
.prefix
= dest
.sin6
.sin6_addr
;
645 if (flags
& RTF_HOST
)
646 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
648 p
.prefixlen
= ip6_masklen (mask
.sin6
.sin6_addr
);
651 if (IN6_IS_ADDR_LINKLOCAL (&gate
.sin6
.sin6_addr
))
653 ifindex
= IN6_LINKLOCAL_IFINDEX (gate
.sin6
.sin6_addr
);
654 SET_IN6_LINKLOCAL_IFINDEX (gate
.sin6
.sin6_addr
, 0);
658 if (rtm
->rtm_type
== RTM_GET
|| rtm
->rtm_type
== RTM_ADD
)
659 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL
, zebra_flags
,
660 &p
, &gate
.sin6
.sin6_addr
, ifindex
, 0);
662 rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL
, zebra_flags
,
663 &p
, &gate
.sin6
.sin6_addr
, ifindex
, 0);
665 #endif /* HAVE_IPV6 */
668 /* Interface function for the kernel routing table updates. Support
669 for RTM_CHANGE will be needed. */
671 rtm_write (int message
,
672 union sockunion
*dest
,
673 union sockunion
*mask
,
674 union sockunion
*gate
,
681 struct interface
*ifp
;
682 struct sockaddr_in tmp_gate
;
684 struct sockaddr_in6 tmp_gate6
;
685 #endif /* HAVE_IPV6 */
687 /* Sequencial number of routing message. */
688 static int msg_seq
= 0;
690 /* Struct of rt_msghdr and buffer for storing socket's data. */
693 struct rt_msghdr rtm
;
697 memset (&tmp_gate
, 0, sizeof (struct sockaddr_in
));
698 tmp_gate
.sin_family
= AF_INET
;
700 tmp_gate
.sin_len
= sizeof (struct sockaddr_in
);
701 #endif /* HAVE_SIN_LEN */
704 memset (&tmp_gate6
, 0, sizeof (struct sockaddr_in6
));
705 tmp_gate6
.sin6_family
= AF_INET6
;
707 tmp_gate6
.sin6_len
= sizeof (struct sockaddr_in6
);
708 #endif /* SIN6_LEN */
709 #endif /* HAVE_IPV6 */
711 if (routing_sock
< 0)
712 return ZEBRA_ERR_EPERM
;
714 /* Clear and set rt_msghdr values */
715 memset (&msg
, 0, sizeof (struct rt_msghdr
));
716 msg
.rtm
.rtm_version
= RTM_VERSION
;
717 msg
.rtm
.rtm_type
= message
;
718 msg
.rtm
.rtm_seq
= msg_seq
++;
719 msg
.rtm
.rtm_addrs
= RTA_DST
;
720 msg
.rtm
.rtm_addrs
|= RTA_GATEWAY
;
721 msg
.rtm
.rtm_flags
= RTF_UP
;
722 msg
.rtm
.rtm_index
= index
;
726 msg
.rtm
.rtm_rmx
.rmx_hopcount
= metric
;
727 msg
.rtm
.rtm_inits
|= RTV_HOPCOUNT
;
730 ifp
= if_lookup_by_index (index
);
732 if (gate
&& message
== RTM_ADD
)
733 msg
.rtm
.rtm_flags
|= RTF_GATEWAY
;
735 if (! gate
&& message
== RTM_ADD
&& ifp
&&
736 (ifp
->flags
& IFF_POINTOPOINT
) == 0)
737 msg
.rtm
.rtm_flags
|= RTF_CLONING
;
739 /* If no protocol specific gateway is specified, use link
740 address for gateway. */
745 zlog_warn ("no gateway found for interface index %d", index
);
748 gate
= (union sockunion
*) & ifp
->sdl
;
752 msg
.rtm
.rtm_addrs
|= RTA_NETMASK
;
753 else if (message
== RTM_ADD
)
754 msg
.rtm
.rtm_flags
|= RTF_HOST
;
756 /* Tagging route with flags */
757 msg
.rtm
.rtm_flags
|= (RTF_PROTO1
);
759 /* Additional flags. */
760 if (zebra_flags
& ZEBRA_FLAG_BLACKHOLE
)
761 msg
.rtm
.rtm_flags
|= RTF_BLACKHOLE
;
762 if (zebra_flags
& ZEBRA_FLAG_REJECT
)
763 msg
.rtm
.rtm_flags
|= RTF_REJECT
;
767 #define SOCKADDRSET(X,R) \
768 if (msg.rtm.rtm_addrs & (R)) \
770 int len = ROUNDUP ((X)->sa.sa_len); \
771 memcpy (pnt, (caddr_t)(X), len); \
775 #define SOCKADDRSET(X,R) \
776 if (msg.rtm.rtm_addrs & (R)) \
778 int len = ROUNDUP (sizeof((X)->sa)); \
779 memcpy (pnt, (caddr_t)(X), len); \
782 #endif /* HAVE_SIN_LEN */
784 pnt
= (caddr_t
) msg
.buf
;
786 /* Write each socket data into rtm message buffer */
787 SOCKADDRSET (dest
, RTA_DST
);
788 SOCKADDRSET (gate
, RTA_GATEWAY
);
789 SOCKADDRSET (mask
, RTA_NETMASK
);
791 msg
.rtm
.rtm_msglen
= pnt
- (caddr_t
) &msg
;
793 ret
= write (routing_sock
, &msg
, msg
.rtm
.rtm_msglen
);
795 if (ret
!= msg
.rtm
.rtm_msglen
)
798 return ZEBRA_ERR_RTEXIST
;
799 if (errno
== ENETUNREACH
)
800 return ZEBRA_ERR_RTUNREACH
;
802 zlog_warn ("write : %s (%d)", safe_strerror (errno
), errno
);
810 #include "zebra/zserv.h"
812 /* For debug purpose. */
814 rtmsg_debug (struct rt_msghdr
*rtm
)
816 const char *type
= "Unknown";
819 for (mes
= rtm_type_str
; mes
->str
; mes
++)
820 if (mes
->key
== rtm
->rtm_type
)
826 zlog_debug ("Kernel: Len: %d Type: %s", rtm
->rtm_msglen
, type
);
827 rtm_flag_dump (rtm
->rtm_flags
);
828 zlog_debug ("Kernel: message seq %d", rtm
->rtm_seq
);
829 zlog_debug ("Kernel: pid %d", rtm
->rtm_pid
);
832 /* This is pretty gross, better suggestions welcome -- mhandler */
835 #define RTAX_MAX RTA_NUMBITS
838 #endif /* RTA_NUMBITS */
839 #endif /* RTAX_MAX */
841 /* Kernel routing table and interface updates via routing socket. */
843 kernel_read (struct thread
*thread
)
847 struct rt_msghdr
*rtm
;
850 * This must be big enough for any message the kernel might send.
851 * Rather than determining how many sockaddrs of what size might be
852 * in each particular message, just use RTAX_MAX of sockaddr_storage
853 * for each. Note that the sockaddrs must be after each message
854 * definition, or rather after whichever happens to be the largest,
855 * since the buffer needs to be big enough for a message and the
856 * sockaddrs together.
860 /* Routing information. */
863 struct rt_msghdr rtm
;
864 struct sockaddr_storage addr
[RTAX_MAX
];
867 /* Interface information. */
870 struct if_msghdr ifm
;
871 struct sockaddr_storage addr
[RTAX_MAX
];
874 /* Interface address information. */
877 struct ifa_msghdr ifa
;
878 struct sockaddr_storage addr
[RTAX_MAX
];
881 #ifdef RTM_IFANNOUNCE
882 /* Interface arrival/departure */
885 struct if_announcemsghdr ifan
;
886 struct sockaddr_storage addr
[RTAX_MAX
];
888 #endif /* RTM_IFANNOUNCE */
892 /* Fetch routing socket. */
893 sock
= THREAD_FD (thread
);
895 nbytes
= read (sock
, &buf
, sizeof buf
);
899 if (nbytes
< 0 && errno
!= EWOULDBLOCK
&& errno
!= EAGAIN
)
900 zlog_warn ("routing socket error: %s", safe_strerror (errno
));
904 thread_add_read (zebrad
.master
, kernel_read
, NULL
, sock
);
906 if (IS_ZEBRA_DEBUG_KERNEL
)
907 rtmsg_debug (&buf
.r
.rtm
);
912 * Ensure that we didn't drop any data, so that processing routines
913 * can assume they have the whole message.
915 if (rtm
->rtm_msglen
!= nbytes
)
917 zlog_warn ("kernel_read: rtm->rtm_msglen %d, nbytes %d, type %d\n",
918 rtm
->rtm_msglen
, nbytes
, rtm
->rtm_type
);
922 switch (rtm
->rtm_type
)
929 ifm_read (&buf
.im
.ifm
);
933 ifam_read (&buf
.ia
.ifa
);
935 #ifdef RTM_IFANNOUNCE
937 ifan_read (&buf
.ian
.ifan
);
939 #endif /* RTM_IFANNOUNCE */
941 if (IS_ZEBRA_DEBUG_KERNEL
)
942 zlog_debug("Unprocessed RTM_type: %d", rtm
->rtm_type
);
948 /* Make routing socket. */
952 if ( zserv_privs
.change (ZPRIVS_RAISE
) )
953 zlog_err ("routing_socket: Can't raise privileges");
955 routing_sock
= socket (AF_ROUTE
, SOCK_RAW
, 0);
957 if (routing_sock
< 0)
959 if ( zserv_privs
.change (ZPRIVS_LOWER
) )
960 zlog_err ("routing_socket: Can't lower privileges");
961 zlog_warn ("Can't init kernel routing socket");
965 /* XXX: Socket should be NONBLOCK, however as we currently
966 * discard failed writes, this will lead to inconsistencies.
967 * For now, socket must be blocking.
969 /*if (fcntl (routing_sock, F_SETFL, O_NONBLOCK) < 0)
970 zlog_warn ("Can't set O_NONBLOCK to routing socket");*/
972 if ( zserv_privs
.change (ZPRIVS_LOWER
) )
973 zlog_err ("routing_socket: Can't lower privileges");
975 /* kernel_read needs rewrite. */
976 thread_add_read (zebrad
.master
, kernel_read
, NULL
, routing_sock
);
979 /* Exported interface function. This function simply calls
980 routing_socket (). */