2 * Kernel routing table updates by routing socket.
3 * Copyright (C) 1997, 98 Kunihiro Ishiguro
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 #include "sockunion.h"
31 #include "zebra/debug.h"
32 #include "zebra/rib.h"
35 rtm_write (int message
,
36 union sockunion
*dest
,
37 union sockunion
*mask
,
38 union sockunion
*gate
,
43 /* Adjust netmask socket length. Return value is a adjusted sin_len
46 sin_masklen (struct in_addr mask
)
50 struct sockaddr_in sin
;
56 len
= sizeof (struct sockaddr_in
);
58 lim
= (char *) &sin
.sin_addr
;
59 p
= lim
+ sizeof (sin
.sin_addr
);
61 while (*--p
== 0 && p
>= lim
)
66 /* Interface between zebra message and rtm message. */
68 kernel_rtm_ipv4 (int cmd
, struct prefix
*p
, struct rib
*rib
, int family
)
71 struct sockaddr_in
*mask
;
72 struct sockaddr_in sin_dest
, sin_mask
, sin_gate
;
73 struct nexthop
*nexthop
;
75 unsigned int ifindex
= 0;
79 memset (&sin_dest
, 0, sizeof (struct sockaddr_in
));
80 sin_dest
.sin_family
= AF_INET
;
82 sin_dest
.sin_len
= sizeof (struct sockaddr_in
);
83 #endif /* HAVE_SIN_LEN */
84 sin_dest
.sin_addr
= p
->u
.prefix4
;
86 memset (&sin_mask
, 0, sizeof (struct sockaddr_in
));
88 memset (&sin_gate
, 0, sizeof (struct sockaddr_in
));
89 sin_gate
.sin_family
= AF_INET
;
91 sin_gate
.sin_len
= sizeof (struct sockaddr_in
);
92 #endif /* HAVE_SIN_LEN */
95 for (nexthop
= rib
->nexthop
; nexthop
; nexthop
= nexthop
->next
)
100 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
101 || (cmd
== RTM_DELETE
103 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
)
107 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
109 if (nexthop
->rtype
== NEXTHOP_TYPE_IPV4
||
110 nexthop
->rtype
== NEXTHOP_TYPE_IPV4_IFINDEX
)
112 sin_gate
.sin_addr
= nexthop
->rgate
.ipv4
;
115 if (nexthop
->rtype
== NEXTHOP_TYPE_IFINDEX
116 || nexthop
->rtype
== NEXTHOP_TYPE_IFNAME
117 || nexthop
->rtype
== NEXTHOP_TYPE_IPV4_IFINDEX
)
118 ifindex
= nexthop
->rifindex
;
122 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
||
123 nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
125 sin_gate
.sin_addr
= nexthop
->gate
.ipv4
;
128 if (nexthop
->type
== NEXTHOP_TYPE_IFINDEX
129 || nexthop
->type
== NEXTHOP_TYPE_IFNAME
130 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
131 ifindex
= nexthop
->ifindex
;
135 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
137 if (gate
&& p
->prefixlen
== 32)
141 masklen2ip (p
->prefixlen
, &sin_mask
.sin_addr
);
142 sin_mask
.sin_family
= AF_UNSPEC
;
144 sin_mask
.sin_len
= sin_masklen (sin_mask
.sin_addr
);
145 #endif /* HAVE_SIN_LEN */
150 error
= rtm_write (cmd
,
151 (union sockunion
*)&sin_dest
,
152 (union sockunion
*)mask
,
153 gate
? (union sockunion
*)&sin_gate
: NULL
,
161 zlog_info ("kernel_rtm_ipv4(): nexthop %d add error=%d.",
169 /* If there is no useful nexthop then return. */
170 if (nexthop_num
== 0)
172 if (IS_ZEBRA_DEBUG_KERNEL
)
173 zlog_info ("kernel_rtm_ipv4(): No useful nexthop.");
181 kernel_add_ipv4 (struct prefix
*p
, struct rib
*rib
)
183 return kernel_rtm_ipv4 (RTM_ADD
, p
, rib
, AF_INET
);
187 kernel_delete_ipv4 (struct prefix
*p
, struct rib
*rib
)
189 return kernel_rtm_ipv4 (RTM_DELETE
, p
, rib
, AF_INET
);
194 /* Calculate sin6_len value for netmask socket value. */
196 sin6_masklen (struct in6_addr mask
)
198 struct sockaddr_in6 sin6
;
203 if (IN_ANYADDR6 (mask
))
204 return sizeof (long);
206 if (IN6_IS_ADDR_UNSPECIFIED (&mask
))
207 return sizeof (long);
210 sin6
.sin6_addr
= mask
;
211 len
= sizeof (struct sockaddr_in6
);
213 lim
= (char *) & sin6
.sin6_addr
;
214 p
= lim
+ sizeof (sin6
.sin6_addr
);
216 while (*--p
== 0 && p
>= lim
)
222 /* Interface between zebra message and rtm message. */
224 kernel_rtm_ipv6 (int message
, struct prefix_ipv6
*dest
,
225 struct in6_addr
*gate
, int index
, int flags
)
227 struct sockaddr_in6
*mask
;
228 struct sockaddr_in6 sin_dest
, sin_mask
, sin_gate
;
230 memset (&sin_dest
, 0, sizeof (struct sockaddr_in6
));
231 sin_dest
.sin6_family
= AF_INET6
;
233 sin_dest
.sin6_len
= sizeof (struct sockaddr_in6
);
234 #endif /* SIN6_LEN */
236 memset (&sin_mask
, 0, sizeof (struct sockaddr_in6
));
238 memset (&sin_gate
, 0, sizeof (struct sockaddr_in6
));
239 sin_gate
.sin6_family
= AF_INET6
;
241 sin_gate
.sin6_len
= sizeof (struct sockaddr_in6
);
242 #endif /* SIN6_LEN */
244 sin_dest
.sin6_addr
= dest
->prefix
;
247 memcpy (&sin_gate
.sin6_addr
, gate
, sizeof (struct in6_addr
));
249 /* Under kame set interface index to link local address. */
252 #define SET_IN6_LINKLOCAL_IFINDEX(a, i) \
254 (a).s6_addr[2] = ((i) >> 8) & 0xff; \
255 (a).s6_addr[3] = (i) & 0xff; \
258 if (gate
&& IN6_IS_ADDR_LINKLOCAL(gate
))
259 SET_IN6_LINKLOCAL_IFINDEX (sin_gate
.sin6_addr
, index
);
262 if (gate
&& dest
->prefixlen
== 128)
266 masklen2ip6 (dest
->prefixlen
, &sin_mask
.sin6_addr
);
267 sin_mask
.sin6_family
= AF_UNSPEC
;
269 sin_mask
.sin6_len
= sin6_masklen (sin_mask
.sin6_addr
);
270 #endif /* SIN6_LEN */
274 return rtm_write (message
,
275 (union sockunion
*) &sin_dest
,
276 (union sockunion
*) mask
,
277 gate
? (union sockunion
*)&sin_gate
: NULL
,
283 /* Interface between zebra message and rtm message. */
285 kernel_rtm_ipv6_multipath (int cmd
, struct prefix
*p
, struct rib
*rib
,
288 struct sockaddr_in6
*mask
;
289 struct sockaddr_in6 sin_dest
, sin_mask
, sin_gate
;
290 struct nexthop
*nexthop
;
292 unsigned int ifindex
= 0;
296 memset (&sin_dest
, 0, sizeof (struct sockaddr_in6
));
297 sin_dest
.sin6_family
= AF_INET6
;
299 sin_dest
.sin6_len
= sizeof (struct sockaddr_in6
);
300 #endif /* SIN6_LEN */
301 sin_dest
.sin6_addr
= p
->u
.prefix6
;
303 memset (&sin_mask
, 0, sizeof (struct sockaddr_in6
));
305 memset (&sin_gate
, 0, sizeof (struct sockaddr_in6
));
306 sin_gate
.sin6_family
= AF_INET6
;
308 sin_gate
.sin6_len
= sizeof (struct sockaddr_in6
);
309 #endif /* HAVE_SIN_LEN */
312 for (nexthop
= rib
->nexthop
; nexthop
; nexthop
= nexthop
->next
)
317 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
318 || (cmd
== RTM_DELETE
320 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
)
324 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
326 if (nexthop
->rtype
== NEXTHOP_TYPE_IPV6
327 || nexthop
->rtype
== NEXTHOP_TYPE_IPV6_IFNAME
328 || nexthop
->rtype
== NEXTHOP_TYPE_IPV6_IFINDEX
)
330 sin_gate
.sin6_addr
= nexthop
->rgate
.ipv6
;
333 if (nexthop
->rtype
== NEXTHOP_TYPE_IFINDEX
334 || nexthop
->rtype
== NEXTHOP_TYPE_IFNAME
335 || nexthop
->rtype
== NEXTHOP_TYPE_IPV6_IFNAME
336 || nexthop
->rtype
== NEXTHOP_TYPE_IPV6_IFINDEX
)
337 ifindex
= nexthop
->rifindex
;
341 if (nexthop
->type
== NEXTHOP_TYPE_IPV6
342 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFNAME
343 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
345 sin_gate
.sin6_addr
= nexthop
->gate
.ipv6
;
348 if (nexthop
->type
== NEXTHOP_TYPE_IFINDEX
349 || nexthop
->type
== NEXTHOP_TYPE_IFNAME
350 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFNAME
351 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
352 ifindex
= nexthop
->ifindex
;
356 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
359 /* Under kame set interface index to link local address. */
362 #define SET_IN6_LINKLOCAL_IFINDEX(a, i) \
364 (a).s6_addr[2] = ((i) >> 8) & 0xff; \
365 (a).s6_addr[3] = (i) & 0xff; \
368 if (gate
&& IN6_IS_ADDR_LINKLOCAL(&sin_gate
.sin6_addr
))
369 SET_IN6_LINKLOCAL_IFINDEX (sin_gate
.sin6_addr
, ifindex
);
372 if (gate
&& p
->prefixlen
== 128)
376 masklen2ip6 (p
->prefixlen
, &sin_mask
.sin6_addr
);
377 sin_mask
.sin6_family
= AF_UNSPEC
;
379 sin_mask
.sin6_len
= sin6_masklen (sin_mask
.sin6_addr
);
380 #endif /* SIN6_LEN */
384 error
= rtm_write (cmd
,
385 (union sockunion
*) &sin_dest
,
386 (union sockunion
*) mask
,
387 gate
? (union sockunion
*)&sin_gate
: NULL
,
395 zlog_info ("kernel_rtm_ipv6_multipath(): nexthop %d add error=%d.",
403 /* If there is no useful nexthop then return. */
404 if (nexthop_num
== 0)
406 if (IS_ZEBRA_DEBUG_KERNEL
)
407 zlog_info ("kernel_rtm_ipv6_multipath(): No useful nexthop.");
415 kernel_add_ipv6 (struct prefix
*p
, struct rib
*rib
)
417 return kernel_rtm_ipv6_multipath (RTM_ADD
, p
, rib
, AF_INET6
);
421 kernel_delete_ipv6 (struct prefix
*p
, struct rib
*rib
)
423 return kernel_rtm_ipv6_multipath (RTM_DELETE
, p
, rib
, AF_INET6
);
426 /* Delete IPv6 route from the kernel. */
428 kernel_delete_ipv6_old (struct prefix_ipv6
*dest
, struct in6_addr
*gate
,
429 int index
, int flags
, int table
)
431 return kernel_rtm_ipv6 (RTM_DELETE
, dest
, gate
, index
, flags
);
433 #endif /* HAVE_IPV6 */