Tomato 1.28
[tomato.git] / release / src / router / zebra / zebra / rt_socket.c
blobcd2f26ca861b5333d27e1ead170e594d2c87d3ea
1 /*
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
10 * later version.
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
20 * 02111-1307, USA.
23 #include <zebra.h>
25 #include "if.h"
26 #include "prefix.h"
27 #include "sockunion.h"
28 #include "log.h"
29 #include "str.h"
31 #include "zebra/debug.h"
32 #include "zebra/rib.h"
34 int
35 rtm_write (int message,
36 union sockunion *dest,
37 union sockunion *mask,
38 union sockunion *gate,
39 unsigned int index,
40 int zebra_flags,
41 int metric);
43 /* Adjust netmask socket length. Return value is a adjusted sin_len
44 value. */
45 int
46 sin_masklen (struct in_addr mask)
48 char *p, *lim;
49 int len;
50 struct sockaddr_in sin;
52 if (mask.s_addr == 0)
53 return sizeof (long);
55 sin.sin_addr = mask;
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)
62 len--;
63 return len;
66 /* Interface between zebra message and rtm message. */
67 int
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;
74 int nexthop_num = 0;
75 unsigned int ifindex = 0;
76 int gate = 0;
77 int error;
79 memset (&sin_dest, 0, sizeof (struct sockaddr_in));
80 sin_dest.sin_family = AF_INET;
81 #ifdef HAVE_SIN_LEN
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;
90 #ifdef HAVE_SIN_LEN
91 sin_gate.sin_len = sizeof (struct sockaddr_in);
92 #endif /* HAVE_SIN_LEN */
94 /* Make gateway. */
95 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
97 gate = 0;
99 if ((cmd == RTM_ADD
100 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
101 || (cmd == RTM_DELETE
102 #if 0
103 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
104 #endif
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;
113 gate = 1;
115 if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
116 || nexthop->rtype == NEXTHOP_TYPE_IFNAME
117 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
118 ifindex = nexthop->rifindex;
120 else
122 if (nexthop->type == NEXTHOP_TYPE_IPV4 ||
123 nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
125 sin_gate.sin_addr = nexthop->gate.ipv4;
126 gate = 1;
128 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
129 || nexthop->type == NEXTHOP_TYPE_IFNAME
130 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
131 ifindex = nexthop->ifindex;
134 if (cmd == RTM_ADD)
135 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
137 if (gate && p->prefixlen == 32)
138 mask = NULL;
139 else
141 masklen2ip (p->prefixlen, &sin_mask.sin_addr);
142 sin_mask.sin_family = AF_UNSPEC;
143 #ifdef HAVE_SIN_LEN
144 sin_mask.sin_len = sin_masklen (sin_mask.sin_addr);
145 #endif /* HAVE_SIN_LEN */
146 mask = &sin_mask;
150 error = rtm_write (cmd,
151 (union sockunion *)&sin_dest,
152 (union sockunion *)mask,
153 gate ? (union sockunion *)&sin_gate : NULL,
154 ifindex,
155 rib->flags,
156 rib->metric);
158 #if 0
159 if (error)
161 zlog_info ("kernel_rtm_ipv4(): nexthop %d add error=%d.",
162 nexthop_num, error);
164 #endif
166 nexthop_num++;
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.");
174 return 0;
177 return 0; /*XXX*/
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);
192 #ifdef HAVE_IPV6
194 /* Calculate sin6_len value for netmask socket value. */
196 sin6_masklen (struct in6_addr mask)
198 struct sockaddr_in6 sin6;
199 char *p, *lim;
200 int len;
202 #if defined (INRIA)
203 if (IN_ANYADDR6 (mask))
204 return sizeof (long);
205 #else /* ! INRIA */
206 if (IN6_IS_ADDR_UNSPECIFIED (&mask))
207 return sizeof (long);
208 #endif /* ! INRIA */
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)
217 len--;
219 return len;
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;
232 #ifdef SIN6_LEN
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;
240 #ifdef SIN6_LEN
241 sin_gate.sin6_len = sizeof (struct sockaddr_in6);
242 #endif /* SIN6_LEN */
244 sin_dest.sin6_addr = dest->prefix;
246 if (gate)
247 memcpy (&sin_gate.sin6_addr, gate, sizeof (struct in6_addr));
249 /* Under kame set interface index to link local address. */
250 #ifdef KAME
252 #define SET_IN6_LINKLOCAL_IFINDEX(a, i) \
253 do { \
254 (a).s6_addr[2] = ((i) >> 8) & 0xff; \
255 (a).s6_addr[3] = (i) & 0xff; \
256 } while (0)
258 if (gate && IN6_IS_ADDR_LINKLOCAL(gate))
259 SET_IN6_LINKLOCAL_IFINDEX (sin_gate.sin6_addr, index);
260 #endif /* KAME */
262 if (gate && dest->prefixlen == 128)
263 mask = NULL;
264 else
266 masklen2ip6 (dest->prefixlen, &sin_mask.sin6_addr);
267 sin_mask.sin6_family = AF_UNSPEC;
268 #ifdef SIN6_LEN
269 sin_mask.sin6_len = sin6_masklen (sin_mask.sin6_addr);
270 #endif /* SIN6_LEN */
271 mask = &sin_mask;
274 return rtm_write (message,
275 (union sockunion *) &sin_dest,
276 (union sockunion *) mask,
277 gate ? (union sockunion *)&sin_gate : NULL,
278 index,
279 flags,
283 /* Interface between zebra message and rtm message. */
285 kernel_rtm_ipv6_multipath (int cmd, struct prefix *p, struct rib *rib,
286 int family)
288 struct sockaddr_in6 *mask;
289 struct sockaddr_in6 sin_dest, sin_mask, sin_gate;
290 struct nexthop *nexthop;
291 int nexthop_num = 0;
292 unsigned int ifindex = 0;
293 int gate = 0;
294 int error;
296 memset (&sin_dest, 0, sizeof (struct sockaddr_in6));
297 sin_dest.sin6_family = AF_INET6;
298 #ifdef SIN6_LEN
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;
307 #ifdef HAVE_SIN_LEN
308 sin_gate.sin6_len = sizeof (struct sockaddr_in6);
309 #endif /* HAVE_SIN_LEN */
311 /* Make gateway. */
312 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
314 gate = 0;
316 if ((cmd == RTM_ADD
317 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
318 || (cmd == RTM_DELETE
319 #if 0
320 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
321 #endif
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;
331 gate = 1;
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;
339 else
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;
346 gate = 1;
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;
355 if (cmd == RTM_ADD)
356 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
359 /* Under kame set interface index to link local address. */
360 #ifdef KAME
362 #define SET_IN6_LINKLOCAL_IFINDEX(a, i) \
363 do { \
364 (a).s6_addr[2] = ((i) >> 8) & 0xff; \
365 (a).s6_addr[3] = (i) & 0xff; \
366 } while (0)
368 if (gate && IN6_IS_ADDR_LINKLOCAL(&sin_gate.sin6_addr))
369 SET_IN6_LINKLOCAL_IFINDEX (sin_gate.sin6_addr, ifindex);
370 #endif /* KAME */
372 if (gate && p->prefixlen == 128)
373 mask = NULL;
374 else
376 masklen2ip6 (p->prefixlen, &sin_mask.sin6_addr);
377 sin_mask.sin6_family = AF_UNSPEC;
378 #ifdef SIN6_LEN
379 sin_mask.sin6_len = sin6_masklen (sin_mask.sin6_addr);
380 #endif /* SIN6_LEN */
381 mask = &sin_mask;
384 error = rtm_write (cmd,
385 (union sockunion *) &sin_dest,
386 (union sockunion *) mask,
387 gate ? (union sockunion *)&sin_gate : NULL,
388 ifindex,
389 rib->flags,
390 rib->metric);
392 #if 0
393 if (error)
395 zlog_info ("kernel_rtm_ipv6_multipath(): nexthop %d add error=%d.",
396 nexthop_num, error);
398 #endif
400 nexthop_num++;
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.");
408 return 0;
411 return 0; /*XXX*/
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 */