/** * Insert a route in the kernel routing table * * @param destination the route to add * * @return negative on error */ int olsr_ioctl_add_route(const struct rt_entry *rt) { char if_name[IFNAMSIZ]; struct rtentry kernel_route; union olsr_ip_addr mask; int rslt; OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best)); memset(&kernel_route, 0, sizeof(struct rtentry)); ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family = AF_INET; ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family = AF_INET; ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family = AF_INET; ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr = rt->rt_dst.prefix.v4; if (!olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len)) { return -1; } ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr = mask.v4; if (rt->rt_dst.prefix.v4.s_addr != rt->rt_best->rtp_nexthop.gateway.v4.s_addr) { ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr = rt->rt_best->rtp_nexthop.gateway.v4; } kernel_route.rt_flags = olsr_rt_flags(rt); kernel_route.rt_metric = olsr_fib_metric(&rt->rt_best->rtp_metric); /* * Set interface */ strcpy(if_name, if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index)); kernel_route.rt_dev = if_name; /* delete existing default route before ? */ if ((olsr_cnf->del_gws) && (rt->rt_dst.prefix.v4.s_addr == INADDR_ANY) && (rt->rt_dst.prefix_len == INADDR_ANY)) { delete_all_inet_gws(); olsr_cnf->del_gws = false; } if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCADDRT, &kernel_route)) >= 0) { /* * Send IPC route update message */ ipc_route_send_rtentry(&rt->rt_dst.prefix, &rt->rt_best->rtp_nexthop.gateway, rt->rt_best->rtp_metric.hops, 1, if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index)); } return rslt; }
/** *Insert a route in the kernel routing table * *@param destination the route to add * *@return negative on error */ int olsr_ioctl_add_route6(const struct rt_entry *rt) { struct in6_rtmsg kernel_route; int rslt; OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best)); memset(&kernel_route, 0, sizeof(struct in6_rtmsg)); kernel_route.rtmsg_dst = rt->rt_dst.prefix.v6; kernel_route.rtmsg_dst_len = rt->rt_dst.prefix_len; kernel_route.rtmsg_gateway = rt->rt_best->rtp_nexthop.gateway.v6; kernel_route.rtmsg_flags = olsr_rt_flags(rt); kernel_route.rtmsg_metric = olsr_fib_metric(&rt->rt_best->rtp_metric); /* * set interface */ kernel_route.rtmsg_ifindex = rt->rt_best->rtp_nexthop.iif_index; /* XXX delete 0/0 route before ? */ if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCADDRT, &kernel_route)) >= 0) { /* * Send IPC route update message */ ipc_route_send_rtentry(&rt->rt_dst.prefix, &rt->rt_best->rtp_nexthop.gateway, rt->rt_best->rtp_metric.hops, 1, if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index)); } return rslt; }
/** * Print the routingtree to STDOUT * */ void olsr_print_routing_table(struct avl_tree *tree) { #ifndef NODEBUG /* The whole function makes no sense without it. */ struct avl_node *rt_tree_node; struct lqtextbuffer lqbuffer; OLSR_PRINTF(6, "ROUTING TABLE\n"); for (rt_tree_node = avl_walk_first(tree); rt_tree_node != NULL; rt_tree_node = avl_walk_next(rt_tree_node)) { struct avl_node *rtp_tree_node; struct ipaddr_str prefixstr, origstr, gwstr; struct rt_entry *rt = rt_tree2rt(rt_tree_node); /* first the route entry */ OLSR_PRINTF(6, "%s/%u, via %s, best-originator %s\n", olsr_ip_to_string(&prefixstr, &rt->rt_dst.prefix), rt->rt_dst.prefix_len, olsr_ip_to_string(&origstr, &rt->rt_nexthop.gateway), olsr_ip_to_string(&gwstr, &rt->rt_best->rtp_originator)); /* walk the per-originator path tree of routes */ for (rtp_tree_node = avl_walk_first(&rt->rt_path_tree); rtp_tree_node != NULL; rtp_tree_node = avl_walk_next(rtp_tree_node)) { struct rt_path *rtp = rtp_tree2rtp(rtp_tree_node); OLSR_PRINTF(6, "\tfrom %s, cost %s, metric %u, via %s, %s, v %u\n", olsr_ip_to_string(&origstr, &rtp->rtp_originator), get_linkcost_text(rtp->rtp_metric.cost, true, &lqbuffer), rtp->rtp_metric.hops, olsr_ip_to_string(&gwstr, &rtp-> rtp_nexthop. gateway), if_ifwithindex_name(rt->rt_nexthop.iif_index), rtp->rtp_version); } } #endif /* NODEBUG */ tree = NULL; /* squelch compiler warnings */ }
int iterRouteTabNext(char *buff, int len) { struct avl_node *rt_tree_node; if (iterRouteTab == NULL) return -1; snprintf(buff, len, "destination~%s~gateway~%s~interface~%s~metric~%d~", rawIpAddrToString(&iterRouteTab->rt_dst.prefix, ipAddrLen), rawIpAddrToString(&iterRouteTab->rt_best->rtp_nexthop.gateway, ipAddrLen), if_ifwithindex_name(iterRouteTab->rt_best->rtp_nexthop.iif_index), iterRouteTab->rt_best->rtp_metric.hops); rt_tree_node = avl_walk_next(&iterRouteTab->rt_tree_node); if (rt_tree_node) { iterRouteTab = rt_tree2rt(rt_tree_node); } else { iterRouteTab = NULL; } return 0; }
/* * Sends an add or delete message via the routing socket. * The message consists of: * - a header i.e. struct rt_msghdr * - 0-8 socket address structures */ static int add_del_route(const struct rt_entry *rt, int add) { struct rt_msghdr *rtm; /* message to send to the routing socket */ unsigned char buff[512]; unsigned char *walker; /* points within the buffer */ struct sockaddr_in sin4; /* internet style sockaddr */ struct sockaddr_dl *sdl; /* link level sockaddr */ struct ifaddrs *addrs; struct ifaddrs *awalker; const struct rt_nexthop *nexthop; union olsr_ip_addr mask; /* netmask as ip address */ int sin_size, sdl_size; /* payload of the message */ int len; /* message size written to routing socket */ if (add) { OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best)); } else { OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt)); } memset(buff, 0, sizeof(buff)); memset(&sin4, 0, sizeof(sin4)); sin4.sin_len = sizeof(sin4); sin4.sin_family = AF_INET; sin_size = 1 + ((sizeof(struct sockaddr_in) - 1) | (sizeof(long) - 1)); sdl_size = 1 + ((sizeof(struct sockaddr_dl) - 1) | (sizeof(long) - 1)); /********************************************************************** * FILL THE ROUTING MESSAGE HEADER **********************************************************************/ /* position header to the beginning of the buffer */ rtm = (struct rt_msghdr *)buff; rtm->rtm_version = RTM_VERSION; rtm->rtm_type = add ? RTM_ADD : RTM_DELETE; rtm->rtm_index = 0; /* is ignored in outgoing messages */ rtm->rtm_flags = olsr_rt_flags(rt); rtm->rtm_pid = OLSR_PID; rtm->rtm_seq = ++seq; /* walk to the end of the header */ walker = buff + sizeof(struct rt_msghdr); /********************************************************************** * SET DESTINATION OF THE ROUTE **********************************************************************/ #ifdef _WRS_KERNEL /* * vxWorks: change proto or tos */ OLSR_PRINTF(8, "\t- Setting Protocol: 0\n"); ((struct sockaddr_rt *)(&sin4))->srt_proto = 0; OLSR_PRINTF(8, "\t- Setting TOS: 0\n"); ((struct sockaddr_rt *)(&sin4))->srt_tos = 0; #endif sin4.sin_addr = rt->rt_dst.prefix.v4; memcpy(walker, &sin4, sizeof(sin4)); walker += sin_size; rtm->rtm_addrs = RTA_DST; /********************************************************************** * SET GATEWAY OF THE ROUTE **********************************************************************/ #ifdef _WRS_KERNEL /* * vxWorks: Route with no gateway is deleted */ if (add) { #endif nexthop = olsr_get_nh(rt); if (0 != (rtm->rtm_flags & RTF_GATEWAY)) { sin4.sin_addr = nexthop->gateway.v4; memcpy(walker, &sin4, sizeof(sin4)); walker += sin_size; rtm->rtm_addrs |= RTA_GATEWAY; } else { /* * Host is directly reachable, so add * the output interface MAC address. */ if (getifaddrs(&addrs)) { fprintf(stderr, "\ngetifaddrs() failed\n"); return -1; } for (awalker = addrs; awalker != NULL; awalker = awalker->ifa_next) if (awalker->ifa_addr->sa_family == AF_LINK && strcmp(awalker->ifa_name, if_ifwithindex_name(nexthop->iif_index)) == 0) break; if (awalker == NULL) { fprintf(stderr, "\nInterface %s not found\n", if_ifwithindex_name(nexthop->iif_index)); freeifaddrs(addrs); return -1; } /* sdl is "struct sockaddr_dl" */ sdl = (struct sockaddr_dl *)awalker->ifa_addr; memcpy(walker, sdl, sdl->sdl_len); walker += sdl_size; rtm->rtm_addrs |= RTA_GATEWAY; #ifdef RTF_CLONING rtm->rtm_flags |= RTF_CLONING; #endif #ifndef _WRS_KERNEL rtm->rtm_flags &= ~RTF_HOST; #endif freeifaddrs(addrs); } #ifdef _WRS_KERNEL } #endif /********************************************************************** * SET NETMASK **********************************************************************/ if (0 == (rtm->rtm_flags & RTF_HOST)) { olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len); sin4.sin_addr = mask.v4; memcpy(walker, &sin4, sizeof(sin4)); walker += sin_size; rtm->rtm_addrs |= RTA_NETMASK; } /********************************************************************** * WRITE CONFIGURATION MESSAGE TO THE ROUTING SOCKET **********************************************************************/ rtm->rtm_msglen = (unsigned short)(walker - buff); len = write(olsr_cnf->rts, buff, rtm->rtm_msglen); if (0 != rtm->rtm_errno || len < rtm->rtm_msglen) { fprintf(stderr, "\nCannot write to routing socket: (rtm_errno= 0x%x) (last error message: %s)\n", rtm->rtm_errno,strerror(errno)); if (add) { fprintf(stderr, " Failed on Adding %s\n", olsr_rtp_to_string(rt->rt_best)); } else { fprintf(stderr, " Failed on Deleting %s\n",olsr_rt_to_string(rt)); } } return 0; }