00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "kernel_routes.h"
00043 #include "olsr.h"
00044 #include "defs.h"
00045 #include "process_routes.h"
00046 #include "net_olsr.h"
00047 #include "ipcalc.h"
00048
00049 #include <errno.h>
00050 #include <unistd.h>
00051 #include <net/if_dl.h>
00052
00053 #ifdef _WRS_KERNEL
00054 #include <net/ifaddrs.h>
00055 #include <wrn/coreip/net/route.h>
00056 #include <m2Lib.h>
00057 #define OLSR_PID taskIdSelf ()
00058 #else
00059 #include <ifaddrs.h>
00060 #define OLSR_PID getpid ()
00061 #endif
00062
00063 static unsigned int seq = 0;
00064
00065
00066
00067
00068
00069
00070
00071 static int
00072 add_del_route(const struct rt_entry *rt, int add)
00073 {
00074 struct rt_msghdr *rtm;
00075 unsigned char buff[512];
00076 unsigned char *walker;
00077 struct sockaddr_in sin4;
00078 struct sockaddr_dl *sdl;
00079 struct ifaddrs *addrs;
00080 struct ifaddrs *awalker;
00081 const struct rt_nexthop *nexthop;
00082 union olsr_ip_addr mask;
00083 int sin_size, sdl_size;
00084 int len;
00085
00086 if (add) {
00087 OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));
00088 } else {
00089 OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));
00090 }
00091
00092 memset(buff, 0, sizeof(buff));
00093 memset(&sin4, 0, sizeof(sin4));
00094
00095 sin4.sin_len = sizeof(sin4);
00096 sin4.sin_family = AF_INET;
00097
00098 sin_size = 1 + ((sizeof(struct sockaddr_in) - 1) | (sizeof(long) - 1));
00099 sdl_size = 1 + ((sizeof(struct sockaddr_dl) - 1) | (sizeof(long) - 1));
00100
00101
00102
00103
00104
00105
00106 rtm = (struct rt_msghdr *)buff;
00107
00108 rtm->rtm_version = RTM_VERSION;
00109 rtm->rtm_type = add ? RTM_ADD : RTM_DELETE;
00110 rtm->rtm_index = 0;
00111 rtm->rtm_flags = olsr_rt_flags(rt);
00112 rtm->rtm_pid = OLSR_PID;
00113 rtm->rtm_seq = ++seq;
00114
00115
00116 walker = buff + sizeof(struct rt_msghdr);
00117
00118
00119
00120
00121
00122 #ifdef _WRS_KERNEL
00123
00124
00125
00126 OLSR_PRINTF(8, "\t- Setting Protocol: 0\n");
00127 ((struct sockaddr_rt *)(&sin4))->srt_proto = 0;
00128 OLSR_PRINTF(8, "\t- Setting TOS: 0\n");
00129 ((struct sockaddr_rt *)(&sin4))->srt_tos = 0;
00130 #endif
00131
00132 sin4.sin_addr = rt->rt_dst.prefix.v4;
00133 memcpy(walker, &sin4, sizeof(sin4));
00134 walker += sin_size;
00135 rtm->rtm_addrs = RTA_DST;
00136
00137
00138
00139
00140
00141 #ifdef _WRS_KERNEL
00142
00143
00144
00145 if (add) {
00146 #endif
00147 nexthop = olsr_get_nh(rt);
00148 if (0 != (rtm->rtm_flags & RTF_GATEWAY)) {
00149 sin4.sin_addr = nexthop->gateway.v4;
00150 memcpy(walker, &sin4, sizeof(sin4));
00151 walker += sin_size;
00152 rtm->rtm_addrs |= RTA_GATEWAY;
00153 }
00154 else {
00155
00156
00157
00158
00159 if (getifaddrs(&addrs)) {
00160 fprintf(stderr, "\ngetifaddrs() failed\n");
00161 return -1;
00162 }
00163
00164 for (awalker = addrs; awalker != NULL; awalker = awalker->ifa_next)
00165 if (awalker->ifa_addr->sa_family == AF_LINK && strcmp(awalker->ifa_name, if_ifwithindex_name(nexthop->iif_index)) == 0)
00166 break;
00167
00168 if (awalker == NULL) {
00169 fprintf(stderr, "\nInterface %s not found\n", if_ifwithindex_name(nexthop->iif_index));
00170 freeifaddrs(addrs);
00171 return -1;
00172 }
00173
00174
00175 sdl = (struct sockaddr_dl *)awalker->ifa_addr;
00176 memcpy(walker, sdl, sdl->sdl_len);
00177 walker += sdl_size;
00178 rtm->rtm_addrs |= RTA_GATEWAY;
00179 #ifdef RTF_CLONING
00180 rtm->rtm_flags |= RTF_CLONING;
00181 #endif
00182 #ifndef _WRS_KERNEL
00183 rtm->rtm_flags &= ~RTF_HOST;
00184 #endif
00185 freeifaddrs(addrs);
00186 }
00187 #ifdef _WRS_KERNEL
00188 }
00189 #endif
00190
00191
00192
00193
00194
00195 if (0 == (rtm->rtm_flags & RTF_HOST)) {
00196 olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len);
00197 sin4.sin_addr = mask.v4;
00198 memcpy(walker, &sin4, sizeof(sin4));
00199 walker += sin_size;
00200 rtm->rtm_addrs |= RTA_NETMASK;
00201 }
00202
00203
00204
00205
00206
00207 rtm->rtm_msglen = (unsigned short)(walker - buff);
00208 len = write(olsr_cnf->rts, buff, rtm->rtm_msglen);
00209 if (0 != rtm->rtm_errno || len < rtm->rtm_msglen) {
00210 fprintf(stderr, "\nCannot write to routing socket: (rtm_errno= 0x%x) (last error message: %s)\n", rtm->rtm_errno,
00211 strerror(errno));
00212 }
00213 return 0;
00214 }
00215
00216 int
00217 olsr_ioctl_add_route(const struct rt_entry *rt)
00218 {
00219 return add_del_route(rt, 1);
00220 }
00221
00222 int
00223 olsr_ioctl_del_route(const struct rt_entry *rt)
00224 {
00225 return add_del_route(rt, 0);
00226 }
00227
00228 static int
00229 add_del_route6(const struct rt_entry *rt, int add)
00230 {
00231 struct rt_msghdr *rtm;
00232 unsigned char buff[512];
00233 unsigned char *walker;
00234 struct sockaddr_in6 sin6;
00235 struct sockaddr_dl sdl;
00236 const struct rt_nexthop *nexthop;
00237 int sin_size, sdl_size;
00238 int len;
00239
00240 if (add) {
00241 OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));
00242 } else {
00243 OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));
00244 }
00245
00246 memset(buff, 0, sizeof(buff));
00247 memset(&sin6, 0, sizeof(sin6));
00248 memset(&sdl, 0, sizeof(sdl));
00249
00250 sin6.sin6_len = sizeof(sin6);
00251 sin6.sin6_family = AF_INET6;
00252 sdl.sdl_len = sizeof(sdl);
00253 sdl.sdl_family = AF_LINK;
00254
00255 sin_size = 1 + ((sizeof(struct sockaddr_in6) - 1) | (sizeof(long) - 1));
00256 sdl_size = 1 + ((sizeof(struct sockaddr_dl) - 1) | (sizeof(long) - 1));
00257
00258
00259
00260
00261
00262
00263 rtm = (struct rt_msghdr *)buff;
00264 rtm->rtm_version = RTM_VERSION;
00265 rtm->rtm_type = (add != 0) ? RTM_ADD : RTM_DELETE;
00266 rtm->rtm_index = 0;
00267 rtm->rtm_flags = olsr_rt_flags(rt);
00268 rtm->rtm_pid = OLSR_PID;
00269 rtm->rtm_seq = ++seq;
00270
00271
00272 walker = buff + sizeof(struct rt_msghdr);
00273
00274
00275
00276
00277
00278 memcpy(&sin6.sin6_addr.s6_addr, &rt->rt_dst.prefix.v6, sizeof(struct in6_addr));
00279 memcpy(walker, &sin6, sizeof(sin6));
00280 walker += sin_size;
00281 rtm->rtm_addrs = RTA_DST;
00282
00283
00284
00285
00286
00287 nexthop = olsr_get_nh(rt);
00288 if (0 != (rtm->rtm_flags & RTF_GATEWAY)) {
00289 memcpy(&sin6.sin6_addr.s6_addr, &nexthop->gateway.v6, sizeof(struct in6_addr));
00290 memset(&sin6.sin6_addr.s6_addr, 0, 8);
00291 sin6.sin6_addr.s6_addr[0] = 0xfe;
00292 sin6.sin6_addr.s6_addr[1] = 0x80;
00293 sin6.sin6_scope_id = nexthop->iif_index;
00294 #ifdef __KAME__
00295 *(u_int16_t *) & sin6.sin6_addr.s6_addr[2] = htons(sin6.sin6_scope_id);
00296 sin6.sin6_scope_id = 0;
00297 #endif
00298 memcpy(walker, &sin6, sizeof(sin6));
00299 walker += sin_size;
00300 rtm->rtm_addrs |= RTA_GATEWAY;
00301 }
00302 else {
00303
00304
00305
00306
00307 memcpy(&sin6.sin6_addr.s6_addr, &rt->rt_dst.prefix.v6, sizeof(struct in6_addr));
00308 memset(&sin6.sin6_addr.s6_addr, 0, 8);
00309 sin6.sin6_addr.s6_addr[0] = 0xfe;
00310 sin6.sin6_addr.s6_addr[1] = 0x80;
00311 sin6.sin6_scope_id = nexthop->iif_index;
00312 #ifdef __KAME__
00313 *(u_int16_t *) & sin6.sin6_addr.s6_addr[2] = htons(sin6.sin6_scope_id);
00314 sin6.sin6_scope_id = 0;
00315 #endif
00316 memcpy(walker, &sin6, sizeof(sin6));
00317 walker += sin_size;
00318 rtm->rtm_addrs |= RTA_GATEWAY;
00319 rtm->rtm_flags |= RTF_GATEWAY;
00320 }
00321
00322
00323
00324
00325
00326 if (0 == (rtm->rtm_flags & RTF_HOST)) {
00327 olsr_prefix_to_netmask((union olsr_ip_addr *)&sin6.sin6_addr, rt->rt_dst.prefix_len);
00328 memcpy(walker, &sin6, sizeof(sin6));
00329 walker += sin_size;
00330 rtm->rtm_addrs |= RTA_NETMASK;
00331 }
00332
00333
00334
00335
00336
00337 rtm->rtm_msglen = (unsigned short)(walker - buff);
00338 len = write(olsr_cnf->rts, buff, rtm->rtm_msglen);
00339 if (len < 0 && !(errno == EEXIST || errno == ESRCH)) {
00340 fprintf(stderr, "cannot write to routing socket: %s\n", strerror(errno));
00341 }
00342
00343
00344
00345
00346 if (len < 0 && errno == EEXIST && rtm->rtm_type == RTM_ADD) {
00347 struct rt_msghdr *drtm;
00348 unsigned char dbuff[512];
00349
00350 memset(dbuff, 0, sizeof(dbuff));
00351 drtm = (struct rt_msghdr *)dbuff;
00352 drtm->rtm_version = RTM_VERSION;
00353 drtm->rtm_type = RTM_DELETE;
00354 drtm->rtm_index = 0;
00355 drtm->rtm_flags = olsr_rt_flags(rt);
00356 drtm->rtm_seq = ++seq;
00357
00358 walker = dbuff + sizeof(struct rt_msghdr);
00359 memcpy(&sin6.sin6_addr.s6_addr, &rt->rt_dst.prefix.v6, sizeof(struct in6_addr));
00360 memcpy(walker, &sin6, sizeof(sin6));
00361 walker += sin_size;
00362 drtm->rtm_addrs = RTA_DST;
00363 drtm->rtm_msglen = (unsigned short)(walker - dbuff);
00364 len = write(olsr_cnf->rts, dbuff, drtm->rtm_msglen);
00365 if (len < 0) {
00366 fprintf(stderr, "cannot delete route: %s\n", strerror(errno));
00367 }
00368 rtm->rtm_seq = ++seq;
00369 len = write(olsr_cnf->rts, buff, rtm->rtm_msglen);
00370 if (len < 0) {
00371 fprintf(stderr, "still cannot add route: %s\n", strerror(errno));
00372 }
00373 }
00374 return 0;
00375 }
00376
00377 int
00378 olsr_ioctl_add_route6(const struct rt_entry *rt)
00379 {
00380 return add_del_route6(rt, 1);
00381 }
00382
00383 int
00384 olsr_ioctl_del_route6(const struct rt_entry *rt)
00385 {
00386 return add_del_route6(rt, 0);
00387 }
00388
00389
00390
00391
00392
00393
00394