2 * The olsr.org Optimized Link-State Routing daemon(olsrd)
3 * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
16 * * Neither the name of olsr.org, olsrd nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
33 * Visit http://www.olsr.org for more information.
35 * If you find this software useful feel free to make a donation
36 * to the project. For more information see the website or contact
37 * the copyright holders.
39 * $Id: kernel_routes.c,v 1.8 2006/12/12 11:20:53 kattemat Exp $
43 #include "kernel_routes.h"
47 #include <net/if_dl.h>
50 static unsigned int seq = 0;
52 static int add_del_route(struct rt_entry *dest, int add)
54 struct rt_msghdr *rtm;
55 unsigned char buff[512];
56 unsigned char *walker;
57 struct sockaddr_in sin;
58 struct sockaddr_dl *sdl;
59 struct ifaddrs *addrs;
60 struct ifaddrs *awalker;
63 char Str1[16], Str2[16], Str3[16];
66 inet_ntop(AF_INET, &dest->rt_dst.v4, Str1, 16);
67 inet_ntop(AF_INET, &dest->rt_mask.v4, Str2, 16);
68 inet_ntop(AF_INET, &dest->rt_router.v4, Str3, 16);
70 OLSR_PRINTF(1, "%s IPv4 route to %s/%s via %s.\n",
71 (add != 0) ? "Adding" : "Removing", Str1, Str2, Str3)
73 memset(buff, 0, sizeof (buff));
74 memset(&sin, 0, sizeof (sin));
76 sin.sin_len = sizeof (sin);
77 sin.sin_family = AF_INET;
79 step = 1 + ((sizeof (struct sockaddr_in) - 1) | 3);
80 step2 = 1 + ((sizeof (struct sockaddr_dl) - 1) | 3);
82 rtm = (struct rt_msghdr *)buff;
84 flags = dest->rt_flags;
86 // the host is directly reachable, so use cloning and a /32 net
87 // routing table entry
89 if ((flags & RTF_GATEWAY) == 0)
95 rtm->rtm_version = RTM_VERSION;
96 rtm->rtm_type = (add != 0) ? RTM_ADD : RTM_DELETE;
98 rtm->rtm_flags = flags;
99 rtm->rtm_addrs = RTA_DST | RTA_NETMASK | RTA_GATEWAY;
100 rtm->rtm_seq = ++seq;
102 walker = buff + sizeof (struct rt_msghdr);
104 sin.sin_addr.s_addr = dest->rt_dst.v4;
106 memcpy(walker, &sin, sizeof (sin));
109 if ((flags & RTF_GATEWAY) != 0)
111 sin.sin_addr.s_addr = dest->rt_router.v4;
113 memcpy(walker, &sin, sizeof (sin));
117 // the host is directly reachable, so add the output interface's
122 if (getifaddrs(&addrs))
124 fprintf(stderr, "getifaddrs() failed\n");
128 for (awalker = addrs; awalker != NULL; awalker = awalker->ifa_next)
129 if (awalker->ifa_addr->sa_family == AF_LINK &&
130 strcmp(awalker->ifa_name, dest->rt_if->int_name) == 0)
135 fprintf(stderr, "interface %s not found\n", dest->rt_if->int_name);
140 sdl = (struct sockaddr_dl *)awalker->ifa_addr;
142 memcpy(walker, sdl, sdl->sdl_len);
148 sin.sin_addr.s_addr = dest->rt_mask.v4;
150 memcpy(walker, &sin, sizeof (sin));
153 rtm->rtm_msglen = (unsigned short)(walker - buff);
155 len = write(olsr_cnf->rts, buff, rtm->rtm_msglen);
157 if (len < rtm->rtm_msglen)
158 fprintf(stderr, "cannot write to routing socket: %s\n", strerror(errno));
163 int olsr_ioctl_add_route(struct rt_entry *dest)
165 return add_del_route(dest, 1);
168 int olsr_ioctl_del_route(struct rt_entry *dest)
170 return add_del_route(dest, 0);
173 static int add_del_route6(struct rt_entry *dest, int add)
175 struct rt_msghdr *rtm;
176 unsigned char buff[512];
177 unsigned char *walker;
178 struct sockaddr_in6 sin6;
179 struct sockaddr_dl sdl;
182 char Str1[40], Str2[40];
184 inet_ntop(AF_INET6, &dest->rt_dst.v6, Str1, 40);
185 inet_ntop(AF_INET6, &dest->rt_router.v6, Str2, 40);
187 OLSR_PRINTF(1, "%s IPv6 route to %s/%d via %s.\n",
188 (add != 0) ? "Adding" : "Removing", Str1, dest->rt_mask.v6, Str2)
190 memset(buff, 0, sizeof (buff));
191 memset(&sin6, 0, sizeof (sin6));
192 memset(&sdl, 0, sizeof (sdl));
194 sin6.sin6_len = sizeof (sin6);
195 sin6.sin6_family = AF_INET6;
196 sdl.sdl_len = sizeof (sdl);
197 sdl.sdl_family = AF_LINK;
199 step = 1 + ((sizeof (struct sockaddr_in6) - 1) | 3);
200 step_dl = 1 + ((sizeof (struct sockaddr_dl) - 1) | 3);
202 rtm = (struct rt_msghdr *)buff;
203 rtm->rtm_version = RTM_VERSION;
204 rtm->rtm_type = (add != 0) ? RTM_ADD : RTM_DELETE;
206 rtm->rtm_flags = dest->rt_flags;
207 rtm->rtm_addrs = RTA_DST | RTA_GATEWAY;
208 rtm->rtm_seq = ++seq;
210 walker = buff + sizeof (struct rt_msghdr);
212 memcpy(&sin6.sin6_addr.s6_addr, &dest->rt_dst.v6, sizeof(struct in6_addr));
214 memcpy(walker, &sin6, sizeof (sin6));
217 if ((rtm->rtm_flags & RTF_GATEWAY) != 0)
219 memcpy(&sin6.sin6_addr.s6_addr, &dest->rt_router.v6, sizeof(struct in6_addr));
221 memcpy(walker, &sin6, sizeof (sin6));
225 // the host is directly reachable, so add the output interface's address
229 memcpy(&sin6.sin6_addr.s6_addr, &dest->rt_if->int6_addr.sin6_addr.s6_addr,
230 sizeof(struct in6_addr));
232 memcpy(walker, &sin6, sizeof (sin6));
234 rtm->rtm_flags |= RTF_LLINFO;
237 if ((rtm->rtm_flags & RTF_HOST) == 0)
239 olsr_prefix_to_netmask((union olsr_ip_addr *)&sin6.sin6_addr, dest->rt_mask.v6);
240 memcpy(walker, &sin6, sizeof (sin6));
242 rtm->rtm_addrs |= RTA_NETMASK;
245 if ((rtm->rtm_flags & RTF_GATEWAY) != 0)
247 strcpy(&sdl.sdl_data[0], dest->rt_if->int_name);
248 sdl.sdl_nlen = (u_char)strlen(dest->rt_if->int_name);
249 memcpy(walker, &sdl, sizeof (sdl));
251 rtm->rtm_addrs |= RTA_IFP;
254 rtm->rtm_msglen = (unsigned short)(walker - buff);
256 len = write(rts, buff, rtm->rtm_msglen);
258 if (len < rtm->rtm_msglen)
259 fprintf(stderr, "cannot write to routing socket: %s\n", strerror(errno));
264 int olsr_ioctl_add_route6(struct rt_entry *dest)
266 return add_del_route6(dest, 1);
269 int olsr_ioctl_del_route6(struct rt_entry *dest)
271 return add_del_route6(dest, 0);