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 */