blob: ba03498cc9dfc1f42fe334640772aa6ecbf64bec [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* 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"
pauledd7c242003-06-04 13:59:38 +000034#include "privs.h"
Feng Lu0d0686f2015-05-22 11:40:02 +020035#include "vrf.h"
paul718e3742002-12-13 20:15:29 +000036
37#include "zebra/interface.h"
38#include "zebra/zserv.h"
39#include "zebra/debug.h"
paulec1a4282005-11-24 15:15:17 +000040#include "zebra/kernel_socket.h"
Feng Lu758fb8f2014-07-03 18:23:09 +080041#include "zebra/rib.h"
paul718e3742002-12-13 20:15:29 +000042
pauledd7c242003-06-04 13:59:38 +000043extern struct zebra_privs_t zserv_privs;
paul9bcdb632003-07-08 08:09:45 +000044extern struct zebra_t zebrad;
pauledd7c242003-06-04 13:59:38 +000045
gdt4bfbea82004-01-06 01:13:05 +000046/*
Greg Troxel273b1bd2014-12-02 14:51:49 -050047 * Historically, the BSD routing socket has aligned data following a
48 * struct sockaddr to sizeof(long), which was 4 bytes on some
49 * platforms, and 8 bytes on others. NetBSD 6 changed the routing
50 * socket to align to sizeof(uint64_t), which is 8 bytes. OS X
51 * appears to align to sizeof(int), which is 4 bytes.
gdt4bfbea82004-01-06 01:13:05 +000052 *
Greg Troxel273b1bd2014-12-02 14:51:49 -050053 * Alignment of zero-sized sockaddrs is nonsensical, but historically
54 * BSD defines RT_ROUNDUP(0) to be the alignment interval (rather than
55 * 0). We follow this practice without questioning it, but it is a
56 * bug if quagga calls ROUNDUP with 0.
gdt4bfbea82004-01-06 01:13:05 +000057 */
Greg Troxel273b1bd2014-12-02 14:51:49 -050058
59/*
60 * Because of these varying conventions, the only sane approach is for
61 * the <net/route.h> header to define some flavor of ROUNDUP macro.
62 */
David Lamparter7e923222015-03-03 21:04:20 +010063
64#if defined(SA_SIZE)
65/* SAROUNDUP is the only thing we need, and SA_SIZE provides that */
66#define SAROUNDUP(a) SA_SIZE(a)
67#else /* !SA_SIZE */
68
Greg Troxel273b1bd2014-12-02 14:51:49 -050069#if defined(RT_ROUNDUP)
70#define ROUNDUP(a) RT_ROUNDUP(a)
71#endif /* defined(RT_ROUNDUP) */
72
David Lampartera2b50312015-09-15 19:35:41 -070073#if defined(SUNOS_5)
74/* Solaris has struct sockaddr_in[6] definitions at 16 / 32 bytes size,
75 * so the whole concept doesn't really apply. */
76#define ROUNDUP(a) (a)
77#endif
78
Greg Troxel273b1bd2014-12-02 14:51:49 -050079/*
80 * If ROUNDUP has not yet been defined in terms of platform-provided
81 * defines, attempt to cope with heuristics.
82 */
83#if !defined(ROUNDUP)
84
85/*
86 * It's a bug for a platform not to define rounding/alignment for
87 * sockaddrs on the routing socket. This warning really is
88 * intentional, to provoke filing bug reports with operating systems
89 * that don't define RT_ROUNDUP or equivalent.
90 */
91#warning "net/route.h does not define RT_ROUNDUP; making unwarranted assumptions!"
92
93/* OS X (Xcode as of 2014-12) is known not to define RT_ROUNDUP */
Doug VanLeuven3b33de62012-10-10 22:10:14 +000094#ifdef __APPLE__
Greg Troxel273b1bd2014-12-02 14:51:49 -050095#define ROUNDUP_TYPE int
Greg Troxel941789e2015-03-23 15:16:29 -040096#else
97#define ROUNDUP_TYPE long
Doug VanLeuven3b33de62012-10-10 22:10:14 +000098#endif
paul718e3742002-12-13 20:15:29 +000099
Greg Troxel273b1bd2014-12-02 14:51:49 -0500100#define ROUNDUP(a) \
101 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(ROUNDUP_TYPE) - 1))) : sizeof(ROUNDUP_TYPE))
102
103#endif /* defined(ROUNDUP) */
104
gdt4bfbea82004-01-06 01:13:05 +0000105/*
106 * Given a pointer (sockaddr or void *), return the number of bytes
107 * taken up by the sockaddr and any padding needed for alignment.
108 */
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000109#if defined(HAVE_STRUCT_SOCKADDR_SA_LEN)
gdt4bfbea82004-01-06 01:13:05 +0000110#define SAROUNDUP(X) ROUNDUP(((struct sockaddr *)(X))->sa_len)
paul30be8022003-10-22 02:51:38 +0000111#elif defined(HAVE_IPV6)
gdt4bfbea82004-01-06 01:13:05 +0000112/*
113 * One would hope all fixed-size structure definitions are aligned,
114 * but round them up nonetheless.
115 */
116#define SAROUNDUP(X) \
paul3e95a072003-09-24 00:05:45 +0000117 (((struct sockaddr *)(X))->sa_family == AF_INET ? \
118 ROUNDUP(sizeof(struct sockaddr_in)):\
119 (((struct sockaddr *)(X))->sa_family == AF_INET6 ? \
120 ROUNDUP(sizeof(struct sockaddr_in6)) : \
121 (((struct sockaddr *)(X))->sa_family == AF_LINK ? \
paulc50ae8b2004-05-11 11:31:07 +0000122 ROUNDUP(sizeof(struct sockaddr_dl)) : sizeof(struct sockaddr))))
paul30be8022003-10-22 02:51:38 +0000123#else /* HAVE_IPV6 */
gdt4bfbea82004-01-06 01:13:05 +0000124#define SAROUNDUP(X) \
paul30be8022003-10-22 02:51:38 +0000125 (((struct sockaddr *)(X))->sa_family == AF_INET ? \
126 ROUNDUP(sizeof(struct sockaddr_in)):\
127 (((struct sockaddr *)(X))->sa_family == AF_LINK ? \
128 ROUNDUP(sizeof(struct sockaddr_dl)) : sizeof(struct sockaddr)))
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000129#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
paul718e3742002-12-13 20:15:29 +0000130
David Lamparter7e923222015-03-03 21:04:20 +0100131#endif /* !SA_SIZE */
132
Doug VanLeuvena05df8f2012-10-10 16:11:36 -0700133/*
134 * We use a call to an inline function to copy (PNT) to (DEST)
135 * 1. Calculating the length of the copy requires an #ifdef to determine
136 * if sa_len is a field and can't be used directly inside a #define
137 * 2. So the compiler doesn't complain when DEST is NULL, which is only true
138 * when we are skipping the copy and incrementing to the next SA
paulec1a4282005-11-24 15:15:17 +0000139 */
David Lamparter3e9e2c92015-04-10 09:14:58 +0200140static inline void
Doug VanLeuvena05df8f2012-10-10 16:11:36 -0700141rta_copy (union sockunion *dest, caddr_t src) {
142 int len;
David Lamparterda1b7ea2015-09-15 20:36:20 -0700143 if (!dest)
144 return;
Doug VanLeuvena05df8f2012-10-10 16:11:36 -0700145#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
146 len = (((struct sockaddr *)src)->sa_len > sizeof (*dest)) ?
147 sizeof (*dest) : ((struct sockaddr *)src)->sa_len ;
148#else
149 len = (SAROUNDUP (src) > sizeof (*dest)) ?
150 sizeof (*dest) : SAROUNDUP (src) ;
151#endif
152 memcpy (dest, src, len);
153}
154
paul62debbb2005-06-14 14:07:07 +0000155#define RTA_ADDR_GET(DEST, RTA, RTMADDRS, PNT) \
156 if ((RTMADDRS) & (RTA)) \
157 { \
158 int len = SAROUNDUP ((PNT)); \
David Lamparterda1b7ea2015-09-15 20:36:20 -0700159 if (af_check (((struct sockaddr *)(PNT))->sa_family)) \
Doug VanLeuvena05df8f2012-10-10 16:11:36 -0700160 rta_copy((DEST), (PNT)); \
paul62debbb2005-06-14 14:07:07 +0000161 (PNT) += len; \
162 }
163#define RTA_ATTR_GET(DEST, RTA, RTMADDRS, PNT) \
164 if ((RTMADDRS) & (RTA)) \
165 { \
166 int len = SAROUNDUP ((PNT)); \
David Lamparterda1b7ea2015-09-15 20:36:20 -0700167 rta_copy((DEST), (PNT)); \
paul62debbb2005-06-14 14:07:07 +0000168 (PNT) += len; \
169 }
170
paul6fe70d12005-11-12 22:55:10 +0000171#define RTA_NAME_GET(DEST, RTA, RTMADDRS, PNT, LEN) \
172 if ((RTMADDRS) & (RTA)) \
173 { \
paulec1a4282005-11-24 15:15:17 +0000174 u_char *pdest = (u_char *) (DEST); \
paul6fe70d12005-11-12 22:55:10 +0000175 int len = SAROUNDUP ((PNT)); \
176 struct sockaddr_dl *sdl = (struct sockaddr_dl *)(PNT); \
177 if (IS_ZEBRA_DEBUG_KERNEL) \
178 zlog_debug ("%s: RTA_SDL_GET nlen %d, alen %d", \
179 __func__, sdl->sdl_nlen, sdl->sdl_alen); \
180 if ( ((DEST) != NULL) && (sdl->sdl_family == AF_LINK) \
181 && (sdl->sdl_nlen < IFNAMSIZ) && (sdl->sdl_nlen <= len) ) \
182 { \
paulec1a4282005-11-24 15:15:17 +0000183 memcpy (pdest, sdl->sdl_data, sdl->sdl_nlen); \
184 pdest[sdl->sdl_nlen] = '\0'; \
paul6fe70d12005-11-12 22:55:10 +0000185 (LEN) = sdl->sdl_nlen; \
186 } \
187 (PNT) += len; \
188 } \
189 else \
190 { \
191 (LEN) = 0; \
192 }
paul718e3742002-12-13 20:15:29 +0000193/* Routing socket message types. */
Stephen Hemminger1423c802008-08-14 17:59:25 +0100194const struct message rtm_type_str[] =
paul718e3742002-12-13 20:15:29 +0000195{
196 {RTM_ADD, "RTM_ADD"},
197 {RTM_DELETE, "RTM_DELETE"},
198 {RTM_CHANGE, "RTM_CHANGE"},
199 {RTM_GET, "RTM_GET"},
200 {RTM_LOSING, "RTM_LOSING"},
201 {RTM_REDIRECT, "RTM_REDIRECT"},
202 {RTM_MISS, "RTM_MISS"},
203 {RTM_LOCK, "RTM_LOCK"},
Greg Troxel9458b812006-09-13 12:13:08 +0000204#ifdef OLDADD
paul718e3742002-12-13 20:15:29 +0000205 {RTM_OLDADD, "RTM_OLDADD"},
Greg Troxel9458b812006-09-13 12:13:08 +0000206#endif /* RTM_OLDADD */
207#ifdef RTM_OLDDEL
paul718e3742002-12-13 20:15:29 +0000208 {RTM_OLDDEL, "RTM_OLDDEL"},
Greg Troxel9458b812006-09-13 12:13:08 +0000209#endif /* RTM_OLDDEL */
paul718e3742002-12-13 20:15:29 +0000210 {RTM_RESOLVE, "RTM_RESOLVE"},
211 {RTM_NEWADDR, "RTM_NEWADDR"},
212 {RTM_DELADDR, "RTM_DELADDR"},
213 {RTM_IFINFO, "RTM_IFINFO"},
214#ifdef RTM_OIFINFO
215 {RTM_OIFINFO, "RTM_OIFINFO"},
216#endif /* RTM_OIFINFO */
217#ifdef RTM_NEWMADDR
218 {RTM_NEWMADDR, "RTM_NEWMADDR"},
219#endif /* RTM_NEWMADDR */
220#ifdef RTM_DELMADDR
221 {RTM_DELMADDR, "RTM_DELMADDR"},
222#endif /* RTM_DELMADDR */
223#ifdef RTM_IFANNOUNCE
224 {RTM_IFANNOUNCE, "RTM_IFANNOUNCE"},
225#endif /* RTM_IFANNOUNCE */
226 {0, NULL}
227};
228
Stephen Hemmingerce0db9c2009-05-15 10:47:04 -0700229static const struct message rtm_flag_str[] =
paul718e3742002-12-13 20:15:29 +0000230{
231 {RTF_UP, "UP"},
232 {RTF_GATEWAY, "GATEWAY"},
233 {RTF_HOST, "HOST"},
234 {RTF_REJECT, "REJECT"},
235 {RTF_DYNAMIC, "DYNAMIC"},
236 {RTF_MODIFIED, "MODIFIED"},
237 {RTF_DONE, "DONE"},
238#ifdef RTF_MASK
239 {RTF_MASK, "MASK"},
240#endif /* RTF_MASK */
David Warde6f148e2009-12-03 21:43:11 +0300241#ifdef RTF_CLONING
paul718e3742002-12-13 20:15:29 +0000242 {RTF_CLONING, "CLONING"},
David Warde6f148e2009-12-03 21:43:11 +0300243#endif /* RTF_CLONING */
paul718e3742002-12-13 20:15:29 +0000244 {RTF_XRESOLVE, "XRESOLVE"},
Lou Bergerb05c6ca2016-01-12 13:41:44 -0500245#ifdef RTF_LLINFO
paul718e3742002-12-13 20:15:29 +0000246 {RTF_LLINFO, "LLINFO"},
Lou Bergerb05c6ca2016-01-12 13:41:44 -0500247#endif /* RTF_LLINFO */
paul718e3742002-12-13 20:15:29 +0000248 {RTF_STATIC, "STATIC"},
249 {RTF_BLACKHOLE, "BLACKHOLE"},
paul6fe70d12005-11-12 22:55:10 +0000250#ifdef RTF_PRIVATE
251 {RTF_PRIVATE, "PRIVATE"},
252#endif /* RTF_PRIVATE */
paul718e3742002-12-13 20:15:29 +0000253 {RTF_PROTO1, "PROTO1"},
254 {RTF_PROTO2, "PROTO2"},
255#ifdef RTF_PRCLONING
256 {RTF_PRCLONING, "PRCLONING"},
257#endif /* RTF_PRCLONING */
258#ifdef RTF_WASCLONED
259 {RTF_WASCLONED, "WASCLONED"},
260#endif /* RTF_WASCLONED */
261#ifdef RTF_PROTO3
262 {RTF_PROTO3, "PROTO3"},
263#endif /* RTF_PROTO3 */
264#ifdef RTF_PINNED
265 {RTF_PINNED, "PINNED"},
266#endif /* RTF_PINNED */
267#ifdef RTF_LOCAL
268 {RTF_LOCAL, "LOCAL"},
269#endif /* RTF_LOCAL */
270#ifdef RTF_BROADCAST
271 {RTF_BROADCAST, "BROADCAST"},
272#endif /* RTF_BROADCAST */
273#ifdef RTF_MULTICAST
274 {RTF_MULTICAST, "MULTICAST"},
275#endif /* RTF_MULTICAST */
paul6fe70d12005-11-12 22:55:10 +0000276#ifdef RTF_MULTIRT
277 {RTF_MULTIRT, "MULTIRT"},
278#endif /* RTF_MULTIRT */
279#ifdef RTF_SETSRC
280 {RTF_SETSRC, "SETSRC"},
281#endif /* RTF_SETSRC */
paul718e3742002-12-13 20:15:29 +0000282 {0, NULL}
283};
284
285/* Kernel routing update socket. */
286int routing_sock = -1;
287
288/* Yes I'm checking ugly routing socket behavior. */
289/* #define DEBUG */
290
291/* Supported address family check. */
David Lamparter3e9e2c92015-04-10 09:14:58 +0200292static inline int
paul718e3742002-12-13 20:15:29 +0000293af_check (int family)
294{
295 if (family == AF_INET)
296 return 1;
297#ifdef HAVE_IPV6
298 if (family == AF_INET6)
299 return 1;
300#endif /* HAVE_IPV6 */
301 return 0;
302}
David Lamparter6b0655a2014-06-04 06:53:35 +0200303
paul718e3742002-12-13 20:15:29 +0000304/* Dump routing table flag for debug purpose. */
ajsb6178002004-12-07 21:12:56 +0000305static void
paul718e3742002-12-13 20:15:29 +0000306rtm_flag_dump (int flag)
307{
Tom Goff80b2a942009-12-03 14:53:15 +0300308 const struct message *mes;
paul718e3742002-12-13 20:15:29 +0000309 static char buf[BUFSIZ];
310
gdtcced60d2004-07-13 16:45:54 +0000311 buf[0] = '\0';
paul718e3742002-12-13 20:15:29 +0000312 for (mes = rtm_flag_str; mes->key != 0; mes++)
313 {
314 if (mes->key & flag)
315 {
316 strlcat (buf, mes->str, BUFSIZ);
317 strlcat (buf, " ", BUFSIZ);
318 }
319 }
ajsb6178002004-12-07 21:12:56 +0000320 zlog_debug ("Kernel: %s", buf);
paul718e3742002-12-13 20:15:29 +0000321}
322
323#ifdef RTM_IFANNOUNCE
324/* Interface adding function */
paul6621ca82005-11-23 13:02:08 +0000325static int
paul718e3742002-12-13 20:15:29 +0000326ifan_read (struct if_announcemsghdr *ifan)
327{
328 struct interface *ifp;
paul6fe70d12005-11-12 22:55:10 +0000329
paul718e3742002-12-13 20:15:29 +0000330 ifp = if_lookup_by_index (ifan->ifan_index);
paul6fe70d12005-11-12 22:55:10 +0000331
332 if (ifp)
333 assert ( (ifp->ifindex == ifan->ifan_index)
334 || (ifp->ifindex == IFINDEX_INTERNAL) );
335
paulec1a4282005-11-24 15:15:17 +0000336 if ( (ifp == NULL)
337 || ((ifp->ifindex == IFINDEX_INTERNAL)
338 && (ifan->ifan_what == IFAN_ARRIVAL)) )
paul718e3742002-12-13 20:15:29 +0000339 {
paul6fe70d12005-11-12 22:55:10 +0000340 if (IS_ZEBRA_DEBUG_KERNEL)
341 zlog_debug ("%s: creating interface for ifindex %d, name %s",
342 __func__, ifan->ifan_index, ifan->ifan_name);
343
paul718e3742002-12-13 20:15:29 +0000344 /* Create Interface */
ajs08dbfb62005-04-03 03:40:52 +0000345 ifp = if_get_by_name_len(ifan->ifan_name,
346 strnlen(ifan->ifan_name,
347 sizeof(ifan->ifan_name)));
paul718e3742002-12-13 20:15:29 +0000348 ifp->ifindex = ifan->ifan_index;
349
Ingo Flaschberger1db65fa2011-04-17 18:28:20 +0000350 if_get_metric (ifp);
paul718e3742002-12-13 20:15:29 +0000351 if_add_update (ifp);
352 }
353 else if (ifp != NULL && ifan->ifan_what == IFAN_DEPARTURE)
paul6eb88272005-07-29 14:36:00 +0000354 if_delete_update (ifp);
paul718e3742002-12-13 20:15:29 +0000355
356 if_get_flags (ifp);
357 if_get_mtu (ifp);
358 if_get_metric (ifp);
359
360 if (IS_ZEBRA_DEBUG_KERNEL)
paul6fe70d12005-11-12 22:55:10 +0000361 zlog_debug ("%s: interface %s index %d",
362 __func__, ifan->ifan_name, ifan->ifan_index);
paul718e3742002-12-13 20:15:29 +0000363
364 return 0;
365}
366#endif /* RTM_IFANNOUNCE */
367
Doug VanLeuven9234b382012-10-10 16:12:32 -0700368#ifdef HAVE_BSD_IFI_LINK_STATE
Andrew J. Schorrc543a172008-01-10 15:24:32 +0000369/* BSD link detect translation */
370static void
371bsd_linkdetect_translate (struct if_msghdr *ifm)
372{
Andrew J. Schorr55edb0d2008-01-11 15:57:13 +0000373 if ((ifm->ifm_data.ifi_link_state >= LINK_STATE_UP) ||
374 (ifm->ifm_data.ifi_link_state == LINK_STATE_UNKNOWN))
Andrew J. Schorrc543a172008-01-10 15:24:32 +0000375 SET_FLAG(ifm->ifm_flags, IFF_RUNNING);
376 else
377 UNSET_FLAG(ifm->ifm_flags, IFF_RUNNING);
378}
Doug VanLeuven9234b382012-10-10 16:12:32 -0700379#endif /* HAVE_BSD_IFI_LINK_STATE */
Andrew J. Schorrc543a172008-01-10 15:24:32 +0000380
gdtda26e3b2004-01-05 17:20:59 +0000381/*
382 * Handle struct if_msghdr obtained from reading routing socket or
383 * sysctl (from interface_list). There may or may not be sockaddrs
384 * present after the header.
385 */
paulec1a4282005-11-24 15:15:17 +0000386int
paul718e3742002-12-13 20:15:29 +0000387ifm_read (struct if_msghdr *ifm)
388{
paul3e95a072003-09-24 00:05:45 +0000389 struct interface *ifp = NULL;
Tom Goffa34eb362009-11-25 20:36:06 +0000390 struct sockaddr_dl *sdl;
paul6fe70d12005-11-12 22:55:10 +0000391 char ifname[IFNAMSIZ];
392 short ifnlen = 0;
Doug VanLeuvena05df8f2012-10-10 16:11:36 -0700393 caddr_t cp;
paul6fe70d12005-11-12 22:55:10 +0000394
395 /* terminate ifname at head (for strnlen) and tail (for safety) */
396 ifname[IFNAMSIZ - 1] = '\0';
397
gdtda26e3b2004-01-05 17:20:59 +0000398 /* paranoia: sanity check structure */
399 if (ifm->ifm_msglen < sizeof(struct if_msghdr))
400 {
401 zlog_err ("ifm_read: ifm->ifm_msglen %d too short\n",
402 ifm->ifm_msglen);
403 return -1;
404 }
405
406 /*
gdt4bfbea82004-01-06 01:13:05 +0000407 * Check for a sockaddr_dl following the message. First, point to
408 * where a socakddr might be if one follows the message.
gdtda26e3b2004-01-05 17:20:59 +0000409 */
gdt4bfbea82004-01-06 01:13:05 +0000410 cp = (void *)(ifm + 1);
411
paul3e95a072003-09-24 00:05:45 +0000412#ifdef SUNOS_5
paul3e95a072003-09-24 00:05:45 +0000413 /*
gdt4bfbea82004-01-06 01:13:05 +0000414 * XXX This behavior should be narrowed to only the kernel versions
415 * for which the structures returned do not match the headers.
416 *
paul3e95a072003-09-24 00:05:45 +0000417 * if_msghdr_t on 64 bit kernels in Solaris 9 and earlier versions
gdt4bfbea82004-01-06 01:13:05 +0000418 * is 12 bytes larger than the 32 bit version.
paul3e95a072003-09-24 00:05:45 +0000419 */
gdt4bfbea82004-01-06 01:13:05 +0000420 if (((struct sockaddr *) cp)->sa_family == AF_UNSPEC)
paul3e95a072003-09-24 00:05:45 +0000421 cp = cp + 12;
paul3e95a072003-09-24 00:05:45 +0000422#endif
paul718e3742002-12-13 20:15:29 +0000423
paul6fe70d12005-11-12 22:55:10 +0000424 RTA_ADDR_GET (NULL, RTA_DST, ifm->ifm_addrs, cp);
425 RTA_ADDR_GET (NULL, RTA_GATEWAY, ifm->ifm_addrs, cp);
426 RTA_ATTR_GET (NULL, RTA_NETMASK, ifm->ifm_addrs, cp);
427 RTA_ADDR_GET (NULL, RTA_GENMASK, ifm->ifm_addrs, cp);
Tom Goffa34eb362009-11-25 20:36:06 +0000428 sdl = (struct sockaddr_dl *)cp;
paul6fe70d12005-11-12 22:55:10 +0000429 RTA_NAME_GET (ifname, RTA_IFP, ifm->ifm_addrs, cp, ifnlen);
430 RTA_ADDR_GET (NULL, RTA_IFA, ifm->ifm_addrs, cp);
431 RTA_ADDR_GET (NULL, RTA_AUTHOR, ifm->ifm_addrs, cp);
432 RTA_ADDR_GET (NULL, RTA_BRD, ifm->ifm_addrs, cp);
433
434 if (IS_ZEBRA_DEBUG_KERNEL)
435 zlog_debug ("%s: sdl ifname %s", __func__, (ifnlen ? ifname : "(nil)"));
436
gdt4bfbea82004-01-06 01:13:05 +0000437 /*
paul6fe70d12005-11-12 22:55:10 +0000438 * Look up on ifindex first, because ifindices are the primary handle for
439 * interfaces across the user/kernel boundary, for most systems. (Some
440 * messages, such as up/down status changes on NetBSD, do not include a
441 * sockaddr_dl).
gdt4bfbea82004-01-06 01:13:05 +0000442 */
paul6fe70d12005-11-12 22:55:10 +0000443 if ( (ifp = if_lookup_by_index (ifm->ifm_index)) != NULL )
gdt4bfbea82004-01-06 01:13:05 +0000444 {
paul6fe70d12005-11-12 22:55:10 +0000445 /* we have an ifp, verify that the name matches as some systems,
446 * eg Solaris, have a 1:many association of ifindex:ifname
447 * if they dont match, we dont have the correct ifp and should
448 * set it back to NULL to let next check do lookup by name
449 */
450 if (ifnlen && (strncmp (ifp->name, ifname, IFNAMSIZ) != 0) )
gdt4bfbea82004-01-06 01:13:05 +0000451 {
paul6fe70d12005-11-12 22:55:10 +0000452 if (IS_ZEBRA_DEBUG_KERNEL)
453 zlog_debug ("%s: ifp name %s doesnt match sdl name %s",
454 __func__, ifp->name, ifname);
455 ifp = NULL;
gdt4bfbea82004-01-06 01:13:05 +0000456 }
457 }
paul6fe70d12005-11-12 22:55:10 +0000458
gdtda26e3b2004-01-05 17:20:59 +0000459 /*
paul6fe70d12005-11-12 22:55:10 +0000460 * If we dont have an ifp, try looking up by name. Particularly as some
461 * systems (Solaris) have a 1:many mapping of ifindex:ifname - the ifname
462 * is therefore our unique handle to that interface.
463 *
464 * Interfaces specified in the configuration file for which the ifindex
465 * has not been determined will have ifindex == IFINDEX_INTERNAL, and such
466 * interfaces are found by this search, and then their ifindex values can
467 * be filled in.
gdtda26e3b2004-01-05 17:20:59 +0000468 */
paul6fe70d12005-11-12 22:55:10 +0000469 if ( (ifp == NULL) && ifnlen)
470 ifp = if_lookup_by_name (ifname);
paul718e3742002-12-13 20:15:29 +0000471
gdtda26e3b2004-01-05 17:20:59 +0000472 /*
paul6fe70d12005-11-12 22:55:10 +0000473 * If ifp still does not exist or has an invalid index (IFINDEX_INTERNAL),
474 * create or fill in an interface.
gdtda26e3b2004-01-05 17:20:59 +0000475 */
ajsd2fc8892005-04-02 18:38:43 +0000476 if ((ifp == NULL) || (ifp->ifindex == IFINDEX_INTERNAL))
paul718e3742002-12-13 20:15:29 +0000477 {
gdt4bfbea82004-01-06 01:13:05 +0000478 /*
479 * To create or fill in an interface, a sockaddr_dl (via
480 * RTA_IFP) is required.
481 */
paul6fe70d12005-11-12 22:55:10 +0000482 if (!ifnlen)
paul718e3742002-12-13 20:15:29 +0000483 {
paul6fe70d12005-11-12 22:55:10 +0000484 zlog_warn ("Interface index %d (new) missing ifname\n",
paul718e3742002-12-13 20:15:29 +0000485 ifm->ifm_index);
486 return -1;
487 }
paul5c78b3d2006-01-25 04:31:40 +0000488
489#ifndef RTM_IFANNOUNCE
490 /* Down->Down interface should be ignored here.
491 * See further comment below.
492 */
493 if (!CHECK_FLAG (ifm->ifm_flags, IFF_UP))
494 return 0;
495#endif /* !RTM_IFANNOUNCE */
paul6fe70d12005-11-12 22:55:10 +0000496
paul3e95a072003-09-24 00:05:45 +0000497 if (ifp == NULL)
paul6fe70d12005-11-12 22:55:10 +0000498 {
499 /* Interface that zebra was not previously aware of, so create. */
500 ifp = if_create (ifname, ifnlen);
501 if (IS_ZEBRA_DEBUG_KERNEL)
502 zlog_debug ("%s: creating ifp for ifindex %d",
503 __func__, ifm->ifm_index);
504 }
paul718e3742002-12-13 20:15:29 +0000505
paul6fe70d12005-11-12 22:55:10 +0000506 if (IS_ZEBRA_DEBUG_KERNEL)
507 zlog_debug ("%s: updated/created ifp, ifname %s, ifindex %d",
508 __func__, ifp->name, ifp->ifindex);
gdt4bfbea82004-01-06 01:13:05 +0000509 /*
510 * Fill in newly created interface structure, or larval
ajsd2fc8892005-04-02 18:38:43 +0000511 * structure with ifindex IFINDEX_INTERNAL.
gdt4bfbea82004-01-06 01:13:05 +0000512 */
paul718e3742002-12-13 20:15:29 +0000513 ifp->ifindex = ifm->ifm_index;
Andrew J. Schorrc543a172008-01-10 15:24:32 +0000514
Doug VanLeuven9234b382012-10-10 16:12:32 -0700515#ifdef HAVE_BSD_IFI_LINK_STATE /* translate BSD kernel msg for link-state */
Andrew J. Schorrc543a172008-01-10 15:24:32 +0000516 bsd_linkdetect_translate(ifm);
Doug VanLeuven9234b382012-10-10 16:12:32 -0700517#endif /* HAVE_BSD_IFI_LINK_STATE */
Andrew J. Schorrc543a172008-01-10 15:24:32 +0000518
paul5c78b3d2006-01-25 04:31:40 +0000519 if_flags_update (ifp, ifm->ifm_flags);
paul718e3742002-12-13 20:15:29 +0000520#if defined(__bsdi__)
521 if_kvm_get_mtu (ifp);
522#else
523 if_get_mtu (ifp);
524#endif /* __bsdi__ */
525 if_get_metric (ifp);
526
Tom Goffa34eb362009-11-25 20:36:06 +0000527 /*
528 * XXX sockaddr_dl contents can be larger than the structure
David Lamparterca3ccd82012-09-26 14:52:39 +0200529 * definition. There are 2 big families here:
530 * - BSD has sdl_len + sdl_data[16] + overruns sdl_data
531 * we MUST use sdl_len here or we'll truncate data.
532 * - Solaris has no sdl_len, but sdl_data[244]
533 * presumably, it's not going to run past that, so sizeof()
534 * is fine here.
Tom Goffa34eb362009-11-25 20:36:06 +0000535 * a nonzero ifnlen from RTA_NAME_GET() means sdl is valid
536 */
537 if (ifnlen)
David Lamparterca3ccd82012-09-26 14:52:39 +0200538 {
539#ifdef HAVE_STRUCT_SOCKADDR_DL_SDL_LEN
540 memcpy (&ifp->sdl, sdl, sdl->sdl_len);
541#else
Tom Goffa34eb362009-11-25 20:36:06 +0000542 memcpy (&ifp->sdl, sdl, sizeof (struct sockaddr_dl));
David Lamparterca3ccd82012-09-26 14:52:39 +0200543#endif /* HAVE_STRUCT_SOCKADDR_DL_SDL_LEN */
544 }
Tom Goffa34eb362009-11-25 20:36:06 +0000545
paul718e3742002-12-13 20:15:29 +0000546 if_add_update (ifp);
547 }
548 else
gdtda26e3b2004-01-05 17:20:59 +0000549 /*
550 * Interface structure exists. Adjust stored flags from
551 * notification. If interface has up->down or down->up
552 * transition, call state change routines (to adjust routes,
553 * notify routing daemons, etc.). (Other flag changes are stored
554 * but apparently do not trigger action.)
555 */
paul718e3742002-12-13 20:15:29 +0000556 {
paul6fe70d12005-11-12 22:55:10 +0000557 if (ifp->ifindex != ifm->ifm_index)
558 {
559 zlog_warn ("%s: index mismatch, ifname %s, ifp index %d, "
560 "ifm index %d",
561 __func__, ifp->name, ifp->ifindex, ifm->ifm_index);
562 return -1;
563 }
564
Doug VanLeuven9234b382012-10-10 16:12:32 -0700565#ifdef HAVE_BSD_IFI_LINK_STATE /* translate BSD kernel msg for link-state */
Andrew J. Schorrc543a172008-01-10 15:24:32 +0000566 bsd_linkdetect_translate(ifm);
Doug VanLeuven9234b382012-10-10 16:12:32 -0700567#endif /* HAVE_BSD_IFI_LINK_STATE */
Andrew J. Schorrc543a172008-01-10 15:24:32 +0000568
paul5c78b3d2006-01-25 04:31:40 +0000569 /* update flags and handle operative->inoperative transition, if any */
570 if_flags_update (ifp, ifm->ifm_flags);
571
paul6eb88272005-07-29 14:36:00 +0000572#ifndef RTM_IFANNOUNCE
paul5c78b3d2006-01-25 04:31:40 +0000573 if (!if_is_up (ifp))
574 {
575 /* No RTM_IFANNOUNCE on this platform, so we can never
576 * distinguish between ~IFF_UP and delete. We must presume
577 * it has been deleted.
578 * Eg, Solaris will not notify us of unplumb.
579 *
580 * XXX: Fixme - this should be runtime detected
581 * So that a binary compiled on a system with IFANNOUNCE
582 * will still behave correctly if run on a platform without
583 */
584 if_delete_update (ifp);
585 }
paul6eb88272005-07-29 14:36:00 +0000586#endif /* RTM_IFANNOUNCE */
Denis Ovsienko1ba27562007-08-21 16:15:39 +0000587 if (if_is_up (ifp))
588 {
589#if defined(__bsdi__)
590 if_kvm_get_mtu (ifp);
591#else
592 if_get_mtu (ifp);
593#endif /* __bsdi__ */
594 if_get_metric (ifp);
595 }
paul718e3742002-12-13 20:15:29 +0000596 }
paul5c78b3d2006-01-25 04:31:40 +0000597
paul718e3742002-12-13 20:15:29 +0000598#ifdef HAVE_NET_RT_IFLIST
599 ifp->stats = ifm->ifm_data;
600#endif /* HAVE_NET_RT_IFLIST */
601
602 if (IS_ZEBRA_DEBUG_KERNEL)
paul6fe70d12005-11-12 22:55:10 +0000603 zlog_debug ("%s: interface %s index %d",
604 __func__, ifp->name, ifp->ifindex);
paul718e3742002-12-13 20:15:29 +0000605
606 return 0;
607}
David Lamparter6b0655a2014-06-04 06:53:35 +0200608
paul718e3742002-12-13 20:15:29 +0000609/* Address read from struct ifa_msghdr. */
paul6621ca82005-11-23 13:02:08 +0000610static void
paul718e3742002-12-13 20:15:29 +0000611ifam_read_mesg (struct ifa_msghdr *ifm,
612 union sockunion *addr,
613 union sockunion *mask,
paul6fe70d12005-11-12 22:55:10 +0000614 union sockunion *brd,
615 char *ifname,
616 short *ifnlen)
paul718e3742002-12-13 20:15:29 +0000617{
618 caddr_t pnt, end;
Andrew J. Schorr7ab62c52007-05-17 15:00:41 +0000619 union sockunion dst;
620 union sockunion gateway;
paul718e3742002-12-13 20:15:29 +0000621
622 pnt = (caddr_t)(ifm + 1);
623 end = ((caddr_t)ifm) + ifm->ifam_msglen;
624
paul718e3742002-12-13 20:15:29 +0000625 /* Be sure structure is cleared */
626 memset (mask, 0, sizeof (union sockunion));
627 memset (addr, 0, sizeof (union sockunion));
paul6621ca82005-11-23 13:02:08 +0000628 memset (brd, 0, sizeof (union sockunion));
Andrew J. Schorr7ab62c52007-05-17 15:00:41 +0000629 memset (&dst, 0, sizeof (union sockunion));
630 memset (&gateway, 0, sizeof (union sockunion));
paul718e3742002-12-13 20:15:29 +0000631
632 /* We fetch each socket variable into sockunion. */
Andrew J. Schorr7ab62c52007-05-17 15:00:41 +0000633 RTA_ADDR_GET (&dst, RTA_DST, ifm->ifam_addrs, pnt);
634 RTA_ADDR_GET (&gateway, RTA_GATEWAY, ifm->ifam_addrs, pnt);
paul62debbb2005-06-14 14:07:07 +0000635 RTA_ATTR_GET (mask, RTA_NETMASK, ifm->ifam_addrs, pnt);
636 RTA_ADDR_GET (NULL, RTA_GENMASK, ifm->ifam_addrs, pnt);
paul6fe70d12005-11-12 22:55:10 +0000637 RTA_NAME_GET (ifname, RTA_IFP, ifm->ifam_addrs, pnt, *ifnlen);
paul62debbb2005-06-14 14:07:07 +0000638 RTA_ADDR_GET (addr, RTA_IFA, ifm->ifam_addrs, pnt);
639 RTA_ADDR_GET (NULL, RTA_AUTHOR, ifm->ifam_addrs, pnt);
paul6fe70d12005-11-12 22:55:10 +0000640 RTA_ADDR_GET (brd, RTA_BRD, ifm->ifam_addrs, pnt);
paul718e3742002-12-13 20:15:29 +0000641
paul6fe70d12005-11-12 22:55:10 +0000642 if (IS_ZEBRA_DEBUG_KERNEL)
Andrew J. Schorr55196042006-05-17 15:04:59 +0000643 {
Timo Teräsbe6335d2015-05-23 11:08:41 +0300644 int family = sockunion_family(addr);
645 switch (family)
Andrew J. Schorr55196042006-05-17 15:04:59 +0000646 {
647 case AF_INET:
Timo Teräsbe6335d2015-05-23 11:08:41 +0300648#ifdef HAVE_IPV6
649 case AF_INET6:
650#endif
Andrew J. Schorr55196042006-05-17 15:04:59 +0000651 {
Timo Teräsbe6335d2015-05-23 11:08:41 +0300652 char buf[4][INET6_ADDRSTRLEN];
Andrew J. Schorr55196042006-05-17 15:04:59 +0000653 zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x, "
Andrew J. Schorr7ab62c52007-05-17 15:00:41 +0000654 "ifam_flags 0x%x, addr %s/%d broad %s dst %s "
655 "gateway %s",
656 __func__, ifm->ifam_index,
Andrew J. Schorr55196042006-05-17 15:04:59 +0000657 (ifnlen ? ifname : "(nil)"), ifm->ifam_addrs,
Andrew J. Schorr7ab62c52007-05-17 15:00:41 +0000658 ifm->ifam_flags,
Timo Teräsbe6335d2015-05-23 11:08:41 +0300659 inet_ntop(family,&addr->sin.sin_addr,
Andrew J. Schorr55196042006-05-17 15:04:59 +0000660 buf[0],sizeof(buf[0])),
661 ip_masklen(mask->sin.sin_addr),
Timo Teräsbe6335d2015-05-23 11:08:41 +0300662 inet_ntop(family,&brd->sin.sin_addr,
Andrew J. Schorr7ab62c52007-05-17 15:00:41 +0000663 buf[1],sizeof(buf[1])),
Timo Teräsbe6335d2015-05-23 11:08:41 +0300664 inet_ntop(family,&dst.sin.sin_addr,
Andrew J. Schorr7ab62c52007-05-17 15:00:41 +0000665 buf[2],sizeof(buf[2])),
Timo Teräsbe6335d2015-05-23 11:08:41 +0300666 inet_ntop(family,&gateway.sin.sin_addr,
Andrew J. Schorr7ab62c52007-05-17 15:00:41 +0000667 buf[3],sizeof(buf[3])));
Andrew J. Schorr55196042006-05-17 15:04:59 +0000668 }
669 break;
Andrew J. Schorr55196042006-05-17 15:04:59 +0000670 default:
671 zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x",
672 __func__, ifm->ifam_index,
673 (ifnlen ? ifname : "(nil)"), ifm->ifam_addrs);
674 break;
675 }
676 }
Andrew J. Schorr7ab62c52007-05-17 15:00:41 +0000677
paul718e3742002-12-13 20:15:29 +0000678 /* Assert read up end point matches to end point */
679 if (pnt != end)
Denis Ovsienko85a2ebf2011-12-05 19:36:06 +0400680 zlog_warn ("ifam_read() doesn't read all socket data");
paul718e3742002-12-13 20:15:29 +0000681}
682
683/* Interface's address information get. */
paulec1a4282005-11-24 15:15:17 +0000684int
paul718e3742002-12-13 20:15:29 +0000685ifam_read (struct ifa_msghdr *ifam)
686{
paul6fe70d12005-11-12 22:55:10 +0000687 struct interface *ifp = NULL;
paul0752ef02005-11-03 12:35:21 +0000688 union sockunion addr, mask, brd;
paul6fe70d12005-11-12 22:55:10 +0000689 char ifname[INTERFACE_NAMSIZ];
690 short ifnlen = 0;
691 char isalias = 0;
Andrew J. Schorr7ab62c52007-05-17 15:00:41 +0000692 int flags = 0;
paul6fe70d12005-11-12 22:55:10 +0000693
694 ifname[0] = ifname[INTERFACE_NAMSIZ - 1] = '\0';
695
696 /* Allocate and read address information. */
697 ifam_read_mesg (ifam, &addr, &mask, &brd, ifname, &ifnlen);
698
699 if ((ifp = if_lookup_by_index(ifam->ifam_index)) == NULL)
paul718e3742002-12-13 20:15:29 +0000700 {
paul6fe70d12005-11-12 22:55:10 +0000701 zlog_warn ("%s: no interface for ifname %s, index %d",
702 __func__, ifname, ifam->ifam_index);
paul718e3742002-12-13 20:15:29 +0000703 return -1;
704 }
paul6fe70d12005-11-12 22:55:10 +0000705
706 if (ifnlen && strncmp (ifp->name, ifname, INTERFACE_NAMSIZ))
707 isalias = 1;
708
Andrew J. Schorr7ab62c52007-05-17 15:00:41 +0000709 /* N.B. The info in ifa_msghdr does not tell us whether the RTA_BRD
710 field contains a broadcast address or a peer address, so we are forced to
711 rely upon the interface type. */
712 if (if_is_pointopoint(ifp))
713 SET_FLAG(flags, ZEBRA_IFA_PEER);
714
Paul Jakma65022082007-03-06 13:43:05 +0000715#if 0
716 /* it might seem cute to grab the interface metric here, however
717 * we're processing an address update message, and so some systems
718 * (e.g. FBSD) dont bother to fill in ifam_metric. Disabled, but left
719 * in deliberately, as comment.
720 */
pauld34b8992006-01-17 18:03:04 +0000721 ifp->metric = ifam->ifam_metric;
Paul Jakma65022082007-03-06 13:43:05 +0000722#endif
723
paul718e3742002-12-13 20:15:29 +0000724 /* Add connected address. */
725 switch (sockunion_family (&addr))
726 {
727 case AF_INET:
728 if (ifam->ifam_type == RTM_NEWADDR)
Andrew J. Schorr7ab62c52007-05-17 15:00:41 +0000729 connected_add_ipv4 (ifp, flags, &addr.sin.sin_addr,
paul718e3742002-12-13 20:15:29 +0000730 ip_masklen (mask.sin.sin_addr),
pauld34b8992006-01-17 18:03:04 +0000731 &brd.sin.sin_addr,
732 (isalias ? ifname : NULL));
paul718e3742002-12-13 20:15:29 +0000733 else
Andrew J. Schorr7ab62c52007-05-17 15:00:41 +0000734 connected_delete_ipv4 (ifp, flags, &addr.sin.sin_addr,
paul718e3742002-12-13 20:15:29 +0000735 ip_masklen (mask.sin.sin_addr),
paul0752ef02005-11-03 12:35:21 +0000736 &brd.sin.sin_addr);
paul718e3742002-12-13 20:15:29 +0000737 break;
738#ifdef HAVE_IPV6
739 case AF_INET6:
740 /* Unset interface index from link-local address when IPv6 stack
741 is KAME. */
742 if (IN6_IS_ADDR_LINKLOCAL (&addr.sin6.sin6_addr))
David Lamparterda1b7ea2015-09-15 20:36:20 -0700743 {
744 SET_IN6_LINKLOCAL_IFINDEX (addr.sin6.sin6_addr, 0);
745 }
paul718e3742002-12-13 20:15:29 +0000746
747 if (ifam->ifam_type == RTM_NEWADDR)
Andrew J. Schorr7ab62c52007-05-17 15:00:41 +0000748 connected_add_ipv6 (ifp, flags, &addr.sin6.sin6_addr,
paul718e3742002-12-13 20:15:29 +0000749 ip6_masklen (mask.sin6.sin6_addr),
pauld34b8992006-01-17 18:03:04 +0000750 &brd.sin6.sin6_addr,
751 (isalias ? ifname : NULL));
paul718e3742002-12-13 20:15:29 +0000752 else
753 connected_delete_ipv6 (ifp,
754 &addr.sin6.sin6_addr,
755 ip6_masklen (mask.sin6.sin6_addr),
paul0752ef02005-11-03 12:35:21 +0000756 &brd.sin6.sin6_addr);
paul718e3742002-12-13 20:15:29 +0000757 break;
758#endif /* HAVE_IPV6 */
759 default:
760 /* Unsupported family silently ignore... */
761 break;
762 }
paul5c78b3d2006-01-25 04:31:40 +0000763
764 /* Check interface flag for implicit up of the interface. */
765 if_refresh (ifp);
766
767#ifdef SUNOS_5
768 /* In addition to lacking IFANNOUNCE, on SUNOS IFF_UP is strange.
769 * See comments for SUNOS_5 in interface.c::if_flags_mangle.
770 *
771 * Here we take care of case where the real IFF_UP was previously
772 * unset (as kept in struct zebra_if.primary_state) and the mangled
773 * IFF_UP (ie IFF_UP set || listcount(connected) has now transitioned
774 * to unset due to the lost non-primary address having DELADDR'd.
775 *
776 * we must delete the interface, because in between here and next
777 * event for this interface-name the administrator could unplumb
778 * and replumb the interface.
779 */
780 if (!if_is_up (ifp))
781 if_delete_update (ifp);
782#endif /* SUNOS_5 */
783
paul718e3742002-12-13 20:15:29 +0000784 return 0;
785}
David Lamparter6b0655a2014-06-04 06:53:35 +0200786
paul718e3742002-12-13 20:15:29 +0000787/* Interface function for reading kernel routing table information. */
paul6621ca82005-11-23 13:02:08 +0000788static int
paul718e3742002-12-13 20:15:29 +0000789rtm_read_mesg (struct rt_msghdr *rtm,
790 union sockunion *dest,
791 union sockunion *mask,
paul6fe70d12005-11-12 22:55:10 +0000792 union sockunion *gate,
793 char *ifname,
794 short *ifnlen)
paul718e3742002-12-13 20:15:29 +0000795{
796 caddr_t pnt, end;
797
798 /* Pnt points out socket data start point. */
799 pnt = (caddr_t)(rtm + 1);
800 end = ((caddr_t)rtm) + rtm->rtm_msglen;
801
802 /* rt_msghdr version check. */
803 if (rtm->rtm_version != RTM_VERSION)
804 zlog (NULL, LOG_WARNING,
805 "Routing message version different %d should be %d."
806 "This may cause problem\n", rtm->rtm_version, RTM_VERSION);
paul62debbb2005-06-14 14:07:07 +0000807
paul718e3742002-12-13 20:15:29 +0000808 /* Be sure structure is cleared */
809 memset (dest, 0, sizeof (union sockunion));
810 memset (gate, 0, sizeof (union sockunion));
811 memset (mask, 0, sizeof (union sockunion));
812
813 /* We fetch each socket variable into sockunion. */
paul62debbb2005-06-14 14:07:07 +0000814 RTA_ADDR_GET (dest, RTA_DST, rtm->rtm_addrs, pnt);
815 RTA_ADDR_GET (gate, RTA_GATEWAY, rtm->rtm_addrs, pnt);
816 RTA_ATTR_GET (mask, RTA_NETMASK, rtm->rtm_addrs, pnt);
817 RTA_ADDR_GET (NULL, RTA_GENMASK, rtm->rtm_addrs, pnt);
paul6fe70d12005-11-12 22:55:10 +0000818 RTA_NAME_GET (ifname, RTA_IFP, rtm->rtm_addrs, pnt, *ifnlen);
paul62debbb2005-06-14 14:07:07 +0000819 RTA_ADDR_GET (NULL, RTA_IFA, rtm->rtm_addrs, pnt);
820 RTA_ADDR_GET (NULL, RTA_AUTHOR, rtm->rtm_addrs, pnt);
821 RTA_ADDR_GET (NULL, RTA_BRD, rtm->rtm_addrs, pnt);
paul718e3742002-12-13 20:15:29 +0000822
823 /* If there is netmask information set it's family same as
824 destination family*/
825 if (rtm->rtm_addrs & RTA_NETMASK)
826 mask->sa.sa_family = dest->sa.sa_family;
827
828 /* Assert read up to the end of pointer. */
829 if (pnt != end)
Denis Ovsienko85a2ebf2011-12-05 19:36:06 +0400830 zlog (NULL, LOG_WARNING, "rtm_read() doesn't read all socket data.");
paul718e3742002-12-13 20:15:29 +0000831
832 return rtm->rtm_flags;
833}
834
paulec1a4282005-11-24 15:15:17 +0000835void
paul718e3742002-12-13 20:15:29 +0000836rtm_read (struct rt_msghdr *rtm)
837{
838 int flags;
839 u_char zebra_flags;
840 union sockunion dest, mask, gate;
paul6fe70d12005-11-12 22:55:10 +0000841 char ifname[INTERFACE_NAMSIZ + 1];
842 short ifnlen = 0;
paul718e3742002-12-13 20:15:29 +0000843
844 zebra_flags = 0;
845
paul718e3742002-12-13 20:15:29 +0000846 /* Read destination and netmask and gateway from rtm message
847 structure. */
paul6fe70d12005-11-12 22:55:10 +0000848 flags = rtm_read_mesg (rtm, &dest, &mask, &gate, ifname, &ifnlen);
Denis Ovsienko6da59802007-08-17 14:16:30 +0000849 if (!(flags & RTF_DONE))
850 return;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000851 if (IS_ZEBRA_DEBUG_KERNEL)
852 zlog_debug ("%s: got rtm of type %d (%s)", __func__, rtm->rtm_type,
Denis Ovsienko2d844522007-09-14 11:31:55 +0000853 lookup (rtm_type_str, rtm->rtm_type));
paul718e3742002-12-13 20:15:29 +0000854
855#ifdef RTF_CLONED /*bsdi, netbsd 1.6*/
856 if (flags & RTF_CLONED)
857 return;
858#endif
859#ifdef RTF_WASCLONED /*freebsd*/
860 if (flags & RTF_WASCLONED)
861 return;
862#endif
863
Timo Teräs0abf6792016-01-15 17:36:29 +0200864 if ((rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) && ! (flags & RTF_UP))
paul718e3742002-12-13 20:15:29 +0000865 return;
866
867 /* This is connected route. */
868 if (! (flags & RTF_GATEWAY))
869 return;
870
871 if (flags & RTF_PROTO1)
872 SET_FLAG (zebra_flags, ZEBRA_FLAG_SELFROUTE);
873
874 /* This is persistent route. */
875 if (flags & RTF_STATIC)
876 SET_FLAG (zebra_flags, ZEBRA_FLAG_STATIC);
877
hasso81dfcaa2003-05-25 19:21:25 +0000878 /* This is a reject or blackhole route */
879 if (flags & RTF_REJECT)
880 SET_FLAG (zebra_flags, ZEBRA_FLAG_REJECT);
881 if (flags & RTF_BLACKHOLE)
882 SET_FLAG (zebra_flags, ZEBRA_FLAG_BLACKHOLE);
883
paul718e3742002-12-13 20:15:29 +0000884 if (dest.sa.sa_family == AF_INET)
885 {
886 struct prefix_ipv4 p;
887
888 p.family = AF_INET;
889 p.prefix = dest.sin.sin_addr;
890 if (flags & RTF_HOST)
891 p.prefixlen = IPV4_MAX_PREFIXLEN;
892 else
893 p.prefixlen = ip_masklen (mask.sin.sin_addr);
paulca162182005-09-12 16:58:52 +0000894
Denis Ovsienkodc958242007-08-13 16:03:06 +0000895 /* Catch self originated messages and match them against our current RIB.
896 * At the same time, ignore unconfirmed messages, they should be tracked
897 * by rtm_write() and kernel_rtm_ipv4().
898 */
Denis Ovsienko96934e62007-09-14 14:56:28 +0000899 if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid)
Denis Ovsienkodc958242007-08-13 16:03:06 +0000900 {
Timo Teräsbe6335d2015-05-23 11:08:41 +0300901 char buf[PREFIX_STRLEN], gate_buf[INET_ADDRSTRLEN];
Denis Ovsienkodc958242007-08-13 16:03:06 +0000902 int ret;
Denis Ovsienkodc958242007-08-13 16:03:06 +0000903 if (! IS_ZEBRA_DEBUG_RIB)
904 return;
Feng Lu0d0686f2015-05-22 11:40:02 +0200905 ret = rib_lookup_ipv4_route (&p, &gate, VRF_DEFAULT);
Timo Teräsbe6335d2015-05-23 11:08:41 +0300906 prefix2str (&p, buf, sizeof(buf));
Denis Ovsienkodc958242007-08-13 16:03:06 +0000907 switch (rtm->rtm_type)
908 {
909 case RTM_ADD:
910 case RTM_GET:
911 case RTM_CHANGE:
912 /* The kernel notifies us about a new route in FIB created by us.
913 Do we have a correspondent entry in our RIB? */
914 switch (ret)
915 {
916 case ZEBRA_RIB_NOTFOUND:
Timo Teräsbe6335d2015-05-23 11:08:41 +0300917 zlog_debug ("%s: %s %s: desync: RR isn't yet in RIB, while already in FIB",
918 __func__, lookup (rtm_type_str, rtm->rtm_type), buf);
Denis Ovsienkodc958242007-08-13 16:03:06 +0000919 break;
920 case ZEBRA_RIB_FOUND_CONNECTED:
921 case ZEBRA_RIB_FOUND_NOGATE:
922 inet_ntop (AF_INET, &gate.sin.sin_addr, gate_buf, INET_ADDRSTRLEN);
Timo Teräsbe6335d2015-05-23 11:08:41 +0300923 zlog_debug ("%s: %s %s: desync: RR is in RIB, but gate differs (ours is %s)",
924 __func__, lookup (rtm_type_str, rtm->rtm_type), buf, gate_buf);
Denis Ovsienkodc958242007-08-13 16:03:06 +0000925 break;
926 case ZEBRA_RIB_FOUND_EXACT: /* RIB RR == FIB RR */
Timo Teräsbe6335d2015-05-23 11:08:41 +0300927 zlog_debug ("%s: %s %s: done Ok",
928 __func__, lookup (rtm_type_str, rtm->rtm_type), buf);
Denis Ovsienkodc958242007-08-13 16:03:06 +0000929 rib_lookup_and_dump (&p);
930 return;
931 break;
932 }
933 break;
934 case RTM_DELETE:
935 /* The kernel notifies us about a route deleted by us. Do we still
936 have it in the RIB? Do we have anything instead? */
937 switch (ret)
938 {
939 case ZEBRA_RIB_FOUND_EXACT:
Timo Teräsbe6335d2015-05-23 11:08:41 +0300940 zlog_debug ("%s: %s %s: desync: RR is still in RIB, while already not in FIB",
941 __func__, lookup (rtm_type_str, rtm->rtm_type), buf);
Denis Ovsienkodc958242007-08-13 16:03:06 +0000942 rib_lookup_and_dump (&p);
943 break;
944 case ZEBRA_RIB_FOUND_CONNECTED:
945 case ZEBRA_RIB_FOUND_NOGATE:
Timo Teräsbe6335d2015-05-23 11:08:41 +0300946 zlog_debug ("%s: %s %s: desync: RR is still in RIB, plus gate differs",
947 __func__, lookup (rtm_type_str, rtm->rtm_type), buf);
Denis Ovsienkodc958242007-08-13 16:03:06 +0000948 rib_lookup_and_dump (&p);
949 break;
950 case ZEBRA_RIB_NOTFOUND: /* RIB RR == FIB RR */
Timo Teräsbe6335d2015-05-23 11:08:41 +0300951 zlog_debug ("%s: %s %s: done Ok",
952 __func__, lookup (rtm_type_str, rtm->rtm_type), buf);
Denis Ovsienkodc958242007-08-13 16:03:06 +0000953 rib_lookup_and_dump (&p);
954 return;
955 break;
956 }
957 break;
958 default:
Timo Teräsbe6335d2015-05-23 11:08:41 +0300959 zlog_debug ("%s: %s: warning: loopback RTM of type %s received",
960 __func__, buf, lookup (rtm_type_str, rtm->rtm_type));
Denis Ovsienkodc958242007-08-13 16:03:06 +0000961 }
962 return;
963 }
964
paulca162182005-09-12 16:58:52 +0000965 /* Change, delete the old prefix, we have no further information
966 * to specify the route really
967 */
968 if (rtm->rtm_type == RTM_CHANGE)
969 rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p,
Feng Lu0d0686f2015-05-22 11:40:02 +0200970 NULL, 0, VRF_DEFAULT, SAFI_UNICAST);
paulca162182005-09-12 16:58:52 +0000971
972 if (rtm->rtm_type == RTM_GET
973 || rtm->rtm_type == RTM_ADD
974 || rtm->rtm_type == RTM_CHANGE)
Feng Lu0d0686f2015-05-22 11:40:02 +0200975 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin.sin_addr,
Timo Teräsb11f3b52015-11-02 16:50:07 +0200976 NULL, 0, VRF_DEFAULT, 0, 0, 0, 0, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000977 else
Feng Lu0d0686f2015-05-22 11:40:02 +0200978 rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p,
979 &gate.sin.sin_addr, 0, VRF_DEFAULT, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000980 }
981#ifdef HAVE_IPV6
982 if (dest.sa.sa_family == AF_INET6)
983 {
Denis Ovsienko5619f562007-10-24 13:13:21 +0000984 /* One day we might have a debug section here like one in the
985 * IPv4 case above. Just ignore own messages at the moment.
986 */
987 if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid)
988 return;
paul718e3742002-12-13 20:15:29 +0000989 struct prefix_ipv6 p;
990 unsigned int ifindex = 0;
991
992 p.family = AF_INET6;
993 p.prefix = dest.sin6.sin6_addr;
994 if (flags & RTF_HOST)
995 p.prefixlen = IPV6_MAX_PREFIXLEN;
996 else
997 p.prefixlen = ip6_masklen (mask.sin6.sin6_addr);
998
999#ifdef KAME
1000 if (IN6_IS_ADDR_LINKLOCAL (&gate.sin6.sin6_addr))
1001 {
1002 ifindex = IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr);
1003 SET_IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr, 0);
1004 }
1005#endif /* KAME */
1006
paulca162182005-09-12 16:58:52 +00001007 /* CHANGE: delete the old prefix, we have no further information
1008 * to specify the route really
1009 */
1010 if (rtm->rtm_type == RTM_CHANGE)
paul6621ca82005-11-23 13:02:08 +00001011 rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p,
Feng Lu0d0686f2015-05-22 11:40:02 +02001012 NULL, 0, VRF_DEFAULT, SAFI_UNICAST);
paulca162182005-09-12 16:58:52 +00001013
1014 if (rtm->rtm_type == RTM_GET
1015 || rtm->rtm_type == RTM_ADD
1016 || rtm->rtm_type == RTM_CHANGE)
Feng Lu0d0686f2015-05-22 11:40:02 +02001017 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin6.sin6_addr,
Timo Teräsb11f3b52015-11-02 16:50:07 +02001018 ifindex, VRF_DEFAULT, RT_TABLE_MAIN, 0, 0, 0, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001019 else
Feng Lu0d0686f2015-05-22 11:40:02 +02001020 rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p,
1021 &gate.sin6.sin6_addr, ifindex,
1022 VRF_DEFAULT, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +00001023 }
1024#endif /* HAVE_IPV6 */
1025}
1026
1027/* Interface function for the kernel routing table updates. Support
paul6621ca82005-11-23 13:02:08 +00001028 * for RTM_CHANGE will be needed.
1029 * Exported only for rt_socket.c
1030 */
paul718e3742002-12-13 20:15:29 +00001031int
1032rtm_write (int message,
1033 union sockunion *dest,
1034 union sockunion *mask,
1035 union sockunion *gate,
1036 unsigned int index,
1037 int zebra_flags,
1038 int metric)
1039{
1040 int ret;
1041 caddr_t pnt;
1042 struct interface *ifp;
paul718e3742002-12-13 20:15:29 +00001043
1044 /* Sequencial number of routing message. */
1045 static int msg_seq = 0;
1046
1047 /* Struct of rt_msghdr and buffer for storing socket's data. */
1048 struct
1049 {
1050 struct rt_msghdr rtm;
1051 char buf[512];
1052 } msg;
1053
paul718e3742002-12-13 20:15:29 +00001054 if (routing_sock < 0)
1055 return ZEBRA_ERR_EPERM;
1056
1057 /* Clear and set rt_msghdr values */
1058 memset (&msg, 0, sizeof (struct rt_msghdr));
1059 msg.rtm.rtm_version = RTM_VERSION;
1060 msg.rtm.rtm_type = message;
1061 msg.rtm.rtm_seq = msg_seq++;
1062 msg.rtm.rtm_addrs = RTA_DST;
1063 msg.rtm.rtm_addrs |= RTA_GATEWAY;
1064 msg.rtm.rtm_flags = RTF_UP;
1065 msg.rtm.rtm_index = index;
1066
1067 if (metric != 0)
1068 {
1069 msg.rtm.rtm_rmx.rmx_hopcount = metric;
1070 msg.rtm.rtm_inits |= RTV_HOPCOUNT;
1071 }
1072
1073 ifp = if_lookup_by_index (index);
1074
Timo Teräs0abf6792016-01-15 17:36:29 +02001075 if (gate && (message == RTM_ADD || message == RTM_CHANGE))
paul718e3742002-12-13 20:15:29 +00001076 msg.rtm.rtm_flags |= RTF_GATEWAY;
1077
David Warde6f148e2009-12-03 21:43:11 +03001078 /* When RTF_CLONING is unavailable on BSD, should we set some
1079 * other flag instead?
1080 */
1081#ifdef RTF_CLONING
Timo Teräs0abf6792016-01-15 17:36:29 +02001082 if (! gate && (message == RTM_ADD || message == RTM_CHANGE) && ifp &&
paul718e3742002-12-13 20:15:29 +00001083 (ifp->flags & IFF_POINTOPOINT) == 0)
1084 msg.rtm.rtm_flags |= RTF_CLONING;
David Warde6f148e2009-12-03 21:43:11 +03001085#endif /* RTF_CLONING */
paul718e3742002-12-13 20:15:29 +00001086
1087 /* If no protocol specific gateway is specified, use link
1088 address for gateway. */
1089 if (! gate)
1090 {
1091 if (!ifp)
1092 {
Denis Ovsienkodc958242007-08-13 16:03:06 +00001093 char dest_buf[INET_ADDRSTRLEN] = "NULL", mask_buf[INET_ADDRSTRLEN] = "255.255.255.255";
1094 if (dest)
1095 inet_ntop (AF_INET, &dest->sin.sin_addr, dest_buf, INET_ADDRSTRLEN);
1096 if (mask)
1097 inet_ntop (AF_INET, &mask->sin.sin_addr, mask_buf, INET_ADDRSTRLEN);
1098 zlog_warn ("%s: %s/%s: gate == NULL and no gateway found for ifindex %d",
1099 __func__, dest_buf, mask_buf, index);
paul718e3742002-12-13 20:15:29 +00001100 return -1;
1101 }
1102 gate = (union sockunion *) & ifp->sdl;
1103 }
1104
1105 if (mask)
1106 msg.rtm.rtm_addrs |= RTA_NETMASK;
Timo Teräs0abf6792016-01-15 17:36:29 +02001107 else if (message == RTM_ADD || message == RTM_CHANGE)
paul718e3742002-12-13 20:15:29 +00001108 msg.rtm.rtm_flags |= RTF_HOST;
1109
1110 /* Tagging route with flags */
1111 msg.rtm.rtm_flags |= (RTF_PROTO1);
1112
1113 /* Additional flags. */
1114 if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
1115 msg.rtm.rtm_flags |= RTF_BLACKHOLE;
hasso81dfcaa2003-05-25 19:21:25 +00001116 if (zebra_flags & ZEBRA_FLAG_REJECT)
1117 msg.rtm.rtm_flags |= RTF_REJECT;
1118
paul718e3742002-12-13 20:15:29 +00001119
paul718e3742002-12-13 20:15:29 +00001120#define SOCKADDRSET(X,R) \
1121 if (msg.rtm.rtm_addrs & (R)) \
1122 { \
paul6fe70d12005-11-12 22:55:10 +00001123 int len = SAROUNDUP (X); \
paul718e3742002-12-13 20:15:29 +00001124 memcpy (pnt, (caddr_t)(X), len); \
1125 pnt += len; \
1126 }
paul718e3742002-12-13 20:15:29 +00001127
1128 pnt = (caddr_t) msg.buf;
1129
1130 /* Write each socket data into rtm message buffer */
1131 SOCKADDRSET (dest, RTA_DST);
1132 SOCKADDRSET (gate, RTA_GATEWAY);
1133 SOCKADDRSET (mask, RTA_NETMASK);
1134
1135 msg.rtm.rtm_msglen = pnt - (caddr_t) &msg;
1136
1137 ret = write (routing_sock, &msg, msg.rtm.rtm_msglen);
1138
1139 if (ret != msg.rtm.rtm_msglen)
1140 {
1141 if (errno == EEXIST)
1142 return ZEBRA_ERR_RTEXIST;
1143 if (errno == ENETUNREACH)
1144 return ZEBRA_ERR_RTUNREACH;
Denis Ovsienkodc958242007-08-13 16:03:06 +00001145 if (errno == ESRCH)
1146 return ZEBRA_ERR_RTNOEXIST;
paul718e3742002-12-13 20:15:29 +00001147
Denis Ovsienkodc958242007-08-13 16:03:06 +00001148 zlog_warn ("%s: write : %s (%d)", __func__, safe_strerror (errno), errno);
1149 return ZEBRA_ERR_KERNEL;
paul718e3742002-12-13 20:15:29 +00001150 }
Denis Ovsienkodc958242007-08-13 16:03:06 +00001151 return ZEBRA_ERR_NOERROR;
paul718e3742002-12-13 20:15:29 +00001152}
1153
David Lamparter6b0655a2014-06-04 06:53:35 +02001154
paul718e3742002-12-13 20:15:29 +00001155#include "thread.h"
1156#include "zebra/zserv.h"
1157
paul718e3742002-12-13 20:15:29 +00001158/* For debug purpose. */
ajsb6178002004-12-07 21:12:56 +00001159static void
paul718e3742002-12-13 20:15:29 +00001160rtmsg_debug (struct rt_msghdr *rtm)
1161{
Denis Ovsienko2d844522007-09-14 11:31:55 +00001162 zlog_debug ("Kernel: Len: %d Type: %s", rtm->rtm_msglen, lookup (rtm_type_str, rtm->rtm_type));
paul718e3742002-12-13 20:15:29 +00001163 rtm_flag_dump (rtm->rtm_flags);
ajsb6178002004-12-07 21:12:56 +00001164 zlog_debug ("Kernel: message seq %d", rtm->rtm_seq);
David Lamparterda1b7ea2015-09-15 20:36:20 -07001165 zlog_debug ("Kernel: pid %lld, rtm_addrs 0x%x",
1166 (long long)rtm->rtm_pid, rtm->rtm_addrs);
paul718e3742002-12-13 20:15:29 +00001167}
1168
1169/* This is pretty gross, better suggestions welcome -- mhandler */
1170#ifndef RTAX_MAX
1171#ifdef RTA_NUMBITS
1172#define RTAX_MAX RTA_NUMBITS
1173#else
1174#define RTAX_MAX 8
1175#endif /* RTA_NUMBITS */
1176#endif /* RTAX_MAX */
1177
1178/* Kernel routing table and interface updates via routing socket. */
paul6621ca82005-11-23 13:02:08 +00001179static int
paul718e3742002-12-13 20:15:29 +00001180kernel_read (struct thread *thread)
1181{
1182 int sock;
1183 int nbytes;
1184 struct rt_msghdr *rtm;
1185
gdtdbee01f2004-01-06 00:36:51 +00001186 /*
1187 * This must be big enough for any message the kernel might send.
gdtb27900b2004-01-08 15:44:29 +00001188 * Rather than determining how many sockaddrs of what size might be
1189 * in each particular message, just use RTAX_MAX of sockaddr_storage
1190 * for each. Note that the sockaddrs must be after each message
1191 * definition, or rather after whichever happens to be the largest,
1192 * since the buffer needs to be big enough for a message and the
1193 * sockaddrs together.
gdtdbee01f2004-01-06 00:36:51 +00001194 */
paul718e3742002-12-13 20:15:29 +00001195 union
1196 {
1197 /* Routing information. */
1198 struct
1199 {
1200 struct rt_msghdr rtm;
gdtb27900b2004-01-08 15:44:29 +00001201 struct sockaddr_storage addr[RTAX_MAX];
paul718e3742002-12-13 20:15:29 +00001202 } r;
1203
1204 /* Interface information. */
1205 struct
1206 {
1207 struct if_msghdr ifm;
gdtb27900b2004-01-08 15:44:29 +00001208 struct sockaddr_storage addr[RTAX_MAX];
paul718e3742002-12-13 20:15:29 +00001209 } im;
1210
1211 /* Interface address information. */
1212 struct
1213 {
1214 struct ifa_msghdr ifa;
gdtb27900b2004-01-08 15:44:29 +00001215 struct sockaddr_storage addr[RTAX_MAX];
paul718e3742002-12-13 20:15:29 +00001216 } ia;
1217
1218#ifdef RTM_IFANNOUNCE
1219 /* Interface arrival/departure */
1220 struct
1221 {
1222 struct if_announcemsghdr ifan;
gdtb27900b2004-01-08 15:44:29 +00001223 struct sockaddr_storage addr[RTAX_MAX];
paul718e3742002-12-13 20:15:29 +00001224 } ian;
1225#endif /* RTM_IFANNOUNCE */
1226
1227 } buf;
1228
1229 /* Fetch routing socket. */
1230 sock = THREAD_FD (thread);
1231
1232 nbytes= read (sock, &buf, sizeof buf);
1233
1234 if (nbytes <= 0)
1235 {
1236 if (nbytes < 0 && errno != EWOULDBLOCK && errno != EAGAIN)
ajs6099b3b2004-11-20 02:06:59 +00001237 zlog_warn ("routing socket error: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001238 return 0;
1239 }
1240
paul9bcdb632003-07-08 08:09:45 +00001241 thread_add_read (zebrad.master, kernel_read, NULL, sock);
paul718e3742002-12-13 20:15:29 +00001242
hasso726f9b22003-05-25 21:04:54 +00001243 if (IS_ZEBRA_DEBUG_KERNEL)
1244 rtmsg_debug (&buf.r.rtm);
paul718e3742002-12-13 20:15:29 +00001245
1246 rtm = &buf.r.rtm;
1247
gdtb27900b2004-01-08 15:44:29 +00001248 /*
1249 * Ensure that we didn't drop any data, so that processing routines
1250 * can assume they have the whole message.
1251 */
gdtda26e3b2004-01-05 17:20:59 +00001252 if (rtm->rtm_msglen != nbytes)
1253 {
1254 zlog_warn ("kernel_read: rtm->rtm_msglen %d, nbytes %d, type %d\n",
1255 rtm->rtm_msglen, nbytes, rtm->rtm_type);
1256 return -1;
1257 }
1258
paul718e3742002-12-13 20:15:29 +00001259 switch (rtm->rtm_type)
1260 {
1261 case RTM_ADD:
1262 case RTM_DELETE:
paulca162182005-09-12 16:58:52 +00001263 case RTM_CHANGE:
paul718e3742002-12-13 20:15:29 +00001264 rtm_read (rtm);
1265 break;
1266 case RTM_IFINFO:
1267 ifm_read (&buf.im.ifm);
1268 break;
1269 case RTM_NEWADDR:
1270 case RTM_DELADDR:
1271 ifam_read (&buf.ia.ifa);
1272 break;
1273#ifdef RTM_IFANNOUNCE
1274 case RTM_IFANNOUNCE:
1275 ifan_read (&buf.ian.ifan);
1276 break;
1277#endif /* RTM_IFANNOUNCE */
1278 default:
hasso726f9b22003-05-25 21:04:54 +00001279 if (IS_ZEBRA_DEBUG_KERNEL)
ajsb6178002004-12-07 21:12:56 +00001280 zlog_debug("Unprocessed RTM_type: %d", rtm->rtm_type);
paul718e3742002-12-13 20:15:29 +00001281 break;
1282 }
1283 return 0;
1284}
1285
1286/* Make routing socket. */
paul6621ca82005-11-23 13:02:08 +00001287static void
Feng Lu758fb8f2014-07-03 18:23:09 +08001288routing_socket (struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001289{
Feng Lu758fb8f2014-07-03 18:23:09 +08001290 if (zvrf->vrf_id != VRF_DEFAULT)
1291 return;
1292
pauledd7c242003-06-04 13:59:38 +00001293 if ( zserv_privs.change (ZPRIVS_RAISE) )
1294 zlog_err ("routing_socket: Can't raise privileges");
1295
paul718e3742002-12-13 20:15:29 +00001296 routing_sock = socket (AF_ROUTE, SOCK_RAW, 0);
1297
1298 if (routing_sock < 0)
1299 {
pauledd7c242003-06-04 13:59:38 +00001300 if ( zserv_privs.change (ZPRIVS_LOWER) )
1301 zlog_err ("routing_socket: Can't lower privileges");
paul718e3742002-12-13 20:15:29 +00001302 zlog_warn ("Can't init kernel routing socket");
1303 return;
1304 }
1305
paul865b8522005-01-05 08:30:35 +00001306 /* XXX: Socket should be NONBLOCK, however as we currently
1307 * discard failed writes, this will lead to inconsistencies.
1308 * For now, socket must be blocking.
1309 */
1310 /*if (fcntl (routing_sock, F_SETFL, O_NONBLOCK) < 0)
1311 zlog_warn ("Can't set O_NONBLOCK to routing socket");*/
1312
pauledd7c242003-06-04 13:59:38 +00001313 if ( zserv_privs.change (ZPRIVS_LOWER) )
1314 zlog_err ("routing_socket: Can't lower privileges");
paul718e3742002-12-13 20:15:29 +00001315
1316 /* kernel_read needs rewrite. */
paul9bcdb632003-07-08 08:09:45 +00001317 thread_add_read (zebrad.master, kernel_read, NULL, routing_sock);
paul718e3742002-12-13 20:15:29 +00001318}
1319
1320/* Exported interface function. This function simply calls
1321 routing_socket (). */
1322void
Feng Lu758fb8f2014-07-03 18:23:09 +08001323kernel_init (struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001324{
Feng Lu758fb8f2014-07-03 18:23:09 +08001325 routing_socket (zvrf);
1326}
1327
1328void
1329kernel_terminate (struct zebra_vrf *zvrf)
1330{
1331 return;
paul718e3742002-12-13 20:15:29 +00001332}