3 * The olsr.org Optimized Link-State Routing daemon(olsrd)
4 * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of olsr.org, olsrd nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
34 * Visit http://www.olsr.org for more information.
36 * If you find this software useful feel free to make a donation
37 * to the project. For more information see the website or contact
38 * the copyright holders.
42 #include "kernel_routes.h"
45 #include "process_routes.h"
51 #include <net/if_dl.h>
54 #include <net/ifaddrs.h>
55 #include <wrn/coreip/net/route.h>
57 #define OLSR_PID taskIdSelf ()
58 #else /* _WRS_KERNEL */
60 #define OLSR_PID getpid ()
61 #endif /* _WRS_KERNEL */
63 static unsigned int seq = 0;
66 * Sends an add or delete message via the routing socket.
67 * The message consists of:
68 * - a header i.e. struct rt_msghdr
69 * - 0-8 socket address structures
72 add_del_route(const struct rt_entry *rt, int add)
74 struct rt_msghdr *rtm; /* message to send to the routing socket */
75 unsigned char buff[512];
76 unsigned char *walker; /* points within the buffer */
77 struct sockaddr_in sin4; /* internet style sockaddr */
78 struct sockaddr_dl *sdl; /* link level sockaddr */
79 struct ifaddrs *addrs;
80 struct ifaddrs *awalker;
81 const struct rt_nexthop *nexthop;
82 union olsr_ip_addr mask; /* netmask as ip address */
83 int sin_size, sdl_size; /* payload of the message */
84 int len; /* message size written to routing socket */
87 OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));
89 OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));
92 memset(buff, 0, sizeof(buff));
93 memset(&sin4, 0, sizeof(sin4));
95 sin4.sin_len = sizeof(sin4);
96 sin4.sin_family = AF_INET;
98 sin_size = 1 + ((sizeof(struct sockaddr_in) - 1) | (sizeof(long) - 1));
99 sdl_size = 1 + ((sizeof(struct sockaddr_dl) - 1) | (sizeof(long) - 1));
101 /**********************************************************************
102 * FILL THE ROUTING MESSAGE HEADER
103 **********************************************************************/
105 /* position header to the beginning of the buffer */
106 rtm = (struct rt_msghdr *)buff;
108 rtm->rtm_version = RTM_VERSION;
109 rtm->rtm_type = add ? RTM_ADD : RTM_DELETE;
110 rtm->rtm_index = 0; /* is ignored in outgoing messages */
111 rtm->rtm_flags = olsr_rt_flags(rt, add);
112 rtm->rtm_pid = OLSR_PID;
113 rtm->rtm_seq = ++seq;
115 /* walk to the end of the header */
116 walker = buff + sizeof(struct rt_msghdr);
118 /**********************************************************************
119 * SET DESTINATION OF THE ROUTE
120 **********************************************************************/
124 * vxWorks: change proto or tos
126 OLSR_PRINTF(8, "\t- Setting Protocol: 0\n");
127 ((struct sockaddr_rt *)(&sin4))->srt_proto = 0;
128 OLSR_PRINTF(8, "\t- Setting TOS: 0\n");
129 ((struct sockaddr_rt *)(&sin4))->srt_tos = 0;
130 #endif /* _WRS_KERNEL */
132 sin4.sin_addr = rt->rt_dst.prefix.v4;
133 memcpy(walker, &sin4, sizeof(sin4));
135 rtm->rtm_addrs = RTA_DST;
137 /**********************************************************************
138 * SET GATEWAY OF THE ROUTE
139 **********************************************************************/
143 * vxWorks: Route with no gateway is deleted
146 #endif /* _WRS_KERNEL */
147 nexthop = olsr_get_nh(rt);
148 if (0 != (rtm->rtm_flags & RTF_GATEWAY)) {
149 sin4.sin_addr = nexthop->gateway.v4;
150 memcpy(walker, &sin4, sizeof(sin4));
152 rtm->rtm_addrs |= RTA_GATEWAY;
156 * Host is directly reachable, so add
157 * the output interface MAC address.
159 if (getifaddrs(&addrs)) {
160 fprintf(stderr, "\ngetifaddrs() failed\n");
164 for (awalker = addrs; awalker != NULL; awalker = awalker->ifa_next)
165 if (awalker->ifa_addr->sa_family == AF_LINK && strcmp(awalker->ifa_name, if_ifwithindex_name(nexthop->iif_index)) == 0)
168 if (awalker == NULL) {
169 fprintf(stderr, "\nInterface %s not found\n", if_ifwithindex_name(nexthop->iif_index));
174 /* sdl is "struct sockaddr_dl" */
175 sdl = (struct sockaddr_dl *)awalker->ifa_addr;
176 memcpy(walker, sdl, sdl->sdl_len);
178 rtm->rtm_addrs |= RTA_GATEWAY;
180 rtm->rtm_flags |= RTF_CLONING;
181 #endif /* RTF_CLONING */
183 rtm->rtm_flags &= ~RTF_HOST;
184 #endif /* _WRS_KERNEL */
189 #endif /* _WRS_KERNEL */
191 /**********************************************************************
193 **********************************************************************/
195 if (0 == (rtm->rtm_flags & RTF_HOST)) {
196 olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len);
197 sin4.sin_addr = mask.v4;
198 memcpy(walker, &sin4, sizeof(sin4));
200 rtm->rtm_addrs |= RTA_NETMASK;
203 /**********************************************************************
204 * WRITE CONFIGURATION MESSAGE TO THE ROUTING SOCKET
205 **********************************************************************/
207 rtm->rtm_msglen = (unsigned short)(walker - buff);
208 len = write(olsr_cnf->rts, buff, rtm->rtm_msglen);
209 if (0 != rtm->rtm_errno || len < rtm->rtm_msglen) {
210 fprintf(stderr, "\nCannot write to routing socket: (rtm_errno= 0x%x) (last error message: %s)\n",
211 rtm->rtm_errno,strerror(errno));
213 fprintf(stderr, " Failed on Adding %s\n", olsr_rtp_to_string(rt->rt_best));
215 fprintf(stderr, " Failed on Deleting %s\n",olsr_rt_to_string(rt));
222 olsr_ioctl_add_route(const struct rt_entry *rt)
224 return add_del_route(rt, 1);
228 olsr_ioctl_del_route(const struct rt_entry *rt)
230 return add_del_route(rt, 0);
234 add_del_route6(const struct rt_entry *rt, int add)
236 struct rt_msghdr *rtm;
237 unsigned char buff[512];
238 unsigned char *walker;
239 struct sockaddr_in6 sin6;
240 struct sockaddr_dl sdl;
241 const struct rt_nexthop *nexthop;
242 int sin_size, sdl_size;
246 OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));
248 OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));
251 memset(buff, 0, sizeof(buff));
252 memset(&sin6, 0, sizeof(sin6));
253 memset(&sdl, 0, sizeof(sdl));
255 sin6.sin6_len = sizeof(sin6);
256 sin6.sin6_family = AF_INET6;
257 sdl.sdl_len = sizeof(sdl);
258 sdl.sdl_family = AF_LINK;
260 sin_size = 1 + ((sizeof(struct sockaddr_in6) - 1) | (sizeof(long) - 1));
261 sdl_size = 1 + ((sizeof(struct sockaddr_dl) - 1) | (sizeof(long) - 1));
263 /**********************************************************************
264 * FILL THE ROUTING MESSAGE HEADER
265 **********************************************************************/
267 /* position header to the beginning of the buffer */
268 rtm = (struct rt_msghdr *)buff;
269 rtm->rtm_version = RTM_VERSION;
270 rtm->rtm_type = (add != 0) ? RTM_ADD : RTM_DELETE;
272 rtm->rtm_flags = olsr_rt_flags(rt, add);
273 rtm->rtm_pid = OLSR_PID;
274 rtm->rtm_seq = ++seq;
276 /* walk to the end of the header */
277 walker = buff + sizeof(struct rt_msghdr);
279 /**********************************************************************
280 * SET DESTINATION OF THE ROUTE
281 **********************************************************************/
283 memcpy(&sin6.sin6_addr.s6_addr, &rt->rt_dst.prefix.v6, sizeof(struct in6_addr));
284 memcpy(walker, &sin6, sizeof(sin6));
286 rtm->rtm_addrs = RTA_DST;
288 /**********************************************************************
289 * SET GATEWAY OF THE ROUTE
290 **********************************************************************/
292 nexthop = olsr_get_nh(rt);
293 if (0 != (rtm->rtm_flags & RTF_GATEWAY)) {
294 memcpy(&sin6.sin6_addr.s6_addr, &nexthop->gateway.v6, sizeof(struct in6_addr));
295 memset(&sin6.sin6_addr.s6_addr, 0, 8);
296 sin6.sin6_addr.s6_addr[0] = 0xfe;
297 sin6.sin6_addr.s6_addr[1] = 0x80;
298 sin6.sin6_scope_id = nexthop->iif_index;
300 *(u_int16_t *) & sin6.sin6_addr.s6_addr[2] = htons(sin6.sin6_scope_id);
301 sin6.sin6_scope_id = 0;
302 #endif /* __KAME__ */
303 memcpy(walker, &sin6, sizeof(sin6));
305 rtm->rtm_addrs |= RTA_GATEWAY;
309 * Host is directly reachable, so add
310 * the output interface MAC address.
312 memcpy(&sin6.sin6_addr.s6_addr, &rt->rt_dst.prefix.v6, sizeof(struct in6_addr));
313 memset(&sin6.sin6_addr.s6_addr, 0, 8);
314 sin6.sin6_addr.s6_addr[0] = 0xfe;
315 sin6.sin6_addr.s6_addr[1] = 0x80;
316 sin6.sin6_scope_id = nexthop->iif_index;
318 *(u_int16_t *) & sin6.sin6_addr.s6_addr[2] = htons(sin6.sin6_scope_id);
319 sin6.sin6_scope_id = 0;
320 #endif /* __KAME__ */
321 memcpy(walker, &sin6, sizeof(sin6));
323 rtm->rtm_addrs |= RTA_GATEWAY;
324 rtm->rtm_flags |= RTF_GATEWAY;
327 /**********************************************************************
329 **********************************************************************/
331 if (0 == (rtm->rtm_flags & RTF_HOST)) {
332 olsr_prefix_to_netmask((union olsr_ip_addr *)&sin6.sin6_addr, rt->rt_dst.prefix_len);
333 memcpy(walker, &sin6, sizeof(sin6));
335 rtm->rtm_addrs |= RTA_NETMASK;
338 /**********************************************************************
339 * WRITE CONFIGURATION MESSAGE TO THE ROUTING SOCKET
340 **********************************************************************/
342 rtm->rtm_msglen = (unsigned short)(walker - buff);
343 len = write(olsr_cnf->rts, buff, rtm->rtm_msglen);
344 if (len < 0 && !(errno == EEXIST || errno == ESRCH)) {
345 fprintf(stderr, "cannot write to routing socket: %s\n", strerror(errno));
349 * If we get an EEXIST error while adding, delete and retry.
351 if (len < 0 && errno == EEXIST && rtm->rtm_type == RTM_ADD) {
352 struct rt_msghdr *drtm;
353 unsigned char dbuff[512];
355 memset(dbuff, 0, sizeof(dbuff));
356 drtm = (struct rt_msghdr *)dbuff;
357 drtm->rtm_version = RTM_VERSION;
358 drtm->rtm_type = RTM_DELETE;
360 drtm->rtm_flags = olsr_rt_flags(rt, add);
361 drtm->rtm_seq = ++seq;
363 walker = dbuff + sizeof(struct rt_msghdr);
364 memcpy(&sin6.sin6_addr.s6_addr, &rt->rt_dst.prefix.v6, sizeof(struct in6_addr));
365 memcpy(walker, &sin6, sizeof(sin6));
367 drtm->rtm_addrs = RTA_DST;
368 drtm->rtm_msglen = (unsigned short)(walker - dbuff);
369 len = write(olsr_cnf->rts, dbuff, drtm->rtm_msglen);
371 fprintf(stderr, "cannot delete route: %s\n", strerror(errno));
373 rtm->rtm_seq = ++seq;
374 len = write(olsr_cnf->rts, buff, rtm->rtm_msglen);
376 fprintf(stderr, "still cannot add route: %s\n", strerror(errno));
383 olsr_ioctl_add_route6(const struct rt_entry *rt)
385 return add_del_route6(rt, 1);
389 olsr_ioctl_del_route6(const struct rt_entry *rt)
391 return add_del_route6(rt, 0);
397 * indent-tabs-mode: nil