const char * olsr_ip_prefix_to_string(const struct olsr_ip_prefix *prefix) { /* We need for IPv6 an IP address + '/' + prefix and for IPv4 an IP address + '/' + a netmask */ static char buf[MAX(INET6_ADDRSTRLEN + 1 + 3, INET_ADDRSTRLEN + 1 + INET_ADDRSTRLEN)]; const char *rv; if (olsr_cnf->ip_version == AF_INET) { /* IPv4 */ int len; union olsr_ip_addr netmask; rv = inet_ntop(AF_INET, &prefix->prefix.v4, buf, sizeof(buf)); len = strlen(buf); buf[len++] = '/'; olsr_prefix_to_netmask(&netmask, prefix->prefix_len); inet_ntop(AF_INET, &netmask.v4, buf + len, sizeof(buf) - len); } else { /* IPv6 */ int len; rv = inet_ntop(AF_INET6, &prefix->prefix.v6, buf, sizeof(buf)); len = strlen(buf); buf[len++] = '/'; snprintf(buf + len, sizeof(buf) - len, "%d", prefix->prefix_len); } return rv; }
/** * 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; }
/* * Remove a route from the kernel * @param destination the route to remove * @return negative on error */ int os_route_del_rtentry(const struct rt_entry *rt, int ip_version) { MIB_IPFORWARDROW Row; union olsr_ip_addr mask; unsigned long Res; struct interface *iface = rt->rt_nexthop.interface; if (AF_INET != ip_version) { /* * Not implemented */ return -1; } OLSR_DEBUG(LOG_NETWORKING, "KERN: Deleting %s\n", olsr_rt_to_string(rt)); memset(&Row, 0, sizeof(Row)); Row.dwForwardDest = rt->rt_dst.prefix.v4.s_addr; if (!olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len)) { return -1; } Row.dwForwardMask = mask.v4.s_addr; Row.dwForwardPolicy = 0; Row.dwForwardNextHop = rt->rt_nexthop.gateway.v4.s_addr; Row.dwForwardIfIndex = iface->if_index; // MIB_IPROUTE_TYPE_DIRECT and MIB_IPROUTE_TYPE_INDIRECT Row.dwForwardType = (rt->rt_dst.prefix.v4.s_addr == rt->rt_nexthop.gateway.v4.s_addr) ? 3 : 4; Row.dwForwardProto = 3; // MIB_IPPROTO_NETMGMT Row.dwForwardAge = INFINITE; Row.dwForwardNextHopAS = 0; Row.dwForwardMetric1 = olsr_fib_metric(&rt->rt_metric); Row.dwForwardMetric2 = -1; Row.dwForwardMetric3 = -1; Row.dwForwardMetric4 = -1; Row.dwForwardMetric5 = -1; Res = DeleteIpForwardEntry(&Row); if (Res != NO_ERROR) { OLSR_WARN(LOG_NETWORKING, "DeleteIpForwardEntry() = %08lx, %s", Res, win32_strerror(Res)); // XXX - report error in a different way errno = Res; return -1; } return 0; }
/** *Remove a route from the kernel * *@param destination the route to remove * *@return negative on error */ int olsr_ioctl_del_route(const struct rt_entry *rt) { struct rtentry kernel_route; union olsr_ip_addr mask; int rslt; OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt)); 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 (rt->rt_dst.prefix.v4.s_addr != rt->rt_nexthop.gateway.v4.s_addr) { ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr = rt->rt_nexthop.gateway.v4; } if (!olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len)) { return -1; } else { ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr = mask.v4; } kernel_route.rt_flags = olsr_rt_flags(rt); kernel_route.rt_metric = olsr_fib_metric(&rt->rt_metric); /* * Set interface */ kernel_route.rt_dev = NULL; if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCDELRT, &kernel_route)) >= 0) { /* * Send IPC route update message */ ipc_route_send_rtentry(&rt->rt_dst.prefix, NULL, 0, 0, NULL); } return rslt; }
/** *IP version 4 * *@param ifp the interface to send on *@return nada */ static bool serialize_hna4(struct interface *ifp) { uint16_t remainsize, curr_size, needsize; /* preserve existing data in output buffer */ union olsr_message *m; struct hnapair *pair; struct ip_prefix_list *h; /* No hna nets */ if (ifp == NULL) { return false; } if (olsr_cnf->ip_version != AF_INET) { return false; } h = olsr_cnf->hna_entries; if (h == NULL) { return false; } remainsize = net_outbuffer_bytes_left(ifp); curr_size = OLSR_HNA_IPV4_HDRSIZE; /* calculate size needed for HNA */ needsize = curr_size; while (h) { needsize += olsr_cnf->ipsize*2; h = h->next; } h = olsr_cnf->hna_entries; /* Send pending packet if not room in buffer */ if (needsize > remainsize) { net_output(ifp); remainsize = net_outbuffer_bytes_left(ifp); } check_buffspace(curr_size, remainsize, "HNA"); m = (union olsr_message *)msg_buffer; /* Fill header */ m->v4.originator = olsr_cnf->main_addr.v4.s_addr; m->v4.hopcnt = 0; m->v4.ttl = MAX_TTL; m->v4.olsr_msgtype = HNA_MESSAGE; m->v4.olsr_vtime = ifp->valtimes.hna; pair = m->v4.message.hna.hna_net; for (; h != NULL; h = h->next) { union olsr_ip_addr ip_addr; if ((curr_size + (2 * olsr_cnf->ipsize)) > remainsize) { /* Only add HNA message if it contains data */ if (curr_size > OLSR_HNA_IPV4_HDRSIZE) { #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize); #endif m->v4.seqno = htons(get_msg_seqno()); m->v4.olsr_msgsize = htons(curr_size); net_outbuffer_push(ifp, msg_buffer, curr_size); curr_size = OLSR_HNA_IPV4_HDRSIZE; pair = m->v4.message.hna.hna_net; } net_output(ifp); remainsize = net_outbuffer_bytes_left(ifp); check_buffspace(curr_size + (2 * olsr_cnf->ipsize), remainsize, "HNA2"); } #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "\tNet: %s\n", olsr_ip_prefix_to_string(&h->net)); #endif olsr_prefix_to_netmask(&ip_addr, h->net.prefix_len); #ifdef linux if (olsr_cnf->smart_gw_active && is_prefix_inetgw(&h->net)) { /* this is the default route, overwrite it with the smart gateway */ olsr_modifiy_inetgw_netmask(&ip_addr, h->net.prefix_len); } #endif pair->addr = h->net.prefix.v4.s_addr; pair->netmask = ip_addr.v4.s_addr; pair++; curr_size += (2 * olsr_cnf->ipsize); } m->v4.seqno = htons(get_msg_seqno()); m->v4.olsr_msgsize = htons(curr_size); net_outbuffer_push(ifp, msg_buffer, curr_size); //printf("Sending HNA (%d bytes)...\n", outputsize); return false; }
void olsrd_print_cnf(struct olsrd_config *cnf) { struct ip_prefix_list *h = cnf->hna_entries; struct olsr_if *in = cnf->interfaces; struct plugin_entry *pe = cnf->plugins; struct ip_prefix_list *ie = cnf->ipc_nets; printf(" *** olsrd configuration ***\n"); printf("Debug Level : %d\n", cnf->debug_level); if (cnf->ip_version == AF_INET6) printf("IpVersion : 6\n"); else printf("IpVersion : 4\n"); if (cnf->allow_no_interfaces) printf("No interfaces : ALLOWED\n"); else printf("No interfaces : NOT ALLOWED\n"); printf("TOS : 0x%02x\n", cnf->tos); printf("OlsrPort : 0x%03x\n", cnf->olsrport); printf("RtTable : %u\n", cnf->rt_table); printf("RtTableDefault : %u\n", cnf->rt_table_default); printf("RtTableTunnel : %u\n", cnf->rt_table_tunnel); if (cnf->willingness_auto) printf("Willingness : AUTO\n"); else printf("Willingness : %d\n", cnf->willingness); printf("IPC connections : %d\n", cnf->ipc_connections); while (ie) { struct ipaddr_str strbuf; if (ie->net.prefix_len == olsr_cnf->maxplen) { printf("\tHost %s\n", olsr_ip_to_string(&strbuf, &ie->net.prefix)); } else { printf("\tNet %s/%d\n", olsr_ip_to_string(&strbuf, &ie->net.prefix), ie->net.prefix_len); } ie = ie->next; } printf("Pollrate : %0.2f\n", cnf->pollrate); printf("NIC ChangPollrate: %0.2f\n", cnf->nic_chgs_pollrate); printf("TC redundancy : %d\n", cnf->tc_redundancy); printf("MPR coverage : %d\n", cnf->mpr_coverage); printf("LQ level : %d\n", cnf->lq_level); printf("LQ fish eye : %d\n", cnf->lq_fish); printf("LQ aging factor : %f\n", cnf->lq_aging); printf("LQ algorithm name: %s\n", cnf->lq_algorithm ? cnf->lq_algorithm : "default"); printf("NAT threshold : %f\n", cnf->lq_nat_thresh); printf("Clear screen : %s\n", cnf->clear_screen ? "yes" : "no"); printf("Use niit : %s\n", cnf->use_niit ? "yes" : "no"); printf("Smart Gateway : %s\n", cnf->smart_gw_active ? "yes" : "no"); printf("SmGw. Allow NAT : %s\n", cnf->smart_gw_allow_nat ? "yes" : "no"); printf("Smart Gw. Uplink : %s\n", GW_UPLINK_TXT[cnf->smart_gw_type]); printf("SmGw. Uplink NAT : %s\n", cnf->smart_gw_uplink_nat ? "yes" : "no"); printf("Smart Gw. speed : %d kbit/s up, %d kbit/s down\n", cnf->smart_gw_uplink, cnf->smart_gw_downlink); if (olsr_cnf->smart_gw_prefix.prefix_len == 0) { printf("# Smart Gw. prefix : ::/0\n"); } else { printf("Smart Gw. prefix : %s\n", olsr_ip_prefix_to_string(&cnf->smart_gw_prefix)); } /* Interfaces */ if (in) { /*print interface default config*/ printf(" InterfaceDefaults: \n"); olsrd_print_interface_cnf(cnf->interface_defaults, cnf->interface_defaults, true); while (in) { if (cnf->interface_defaults!=in->cnf) { printf(" dev: \"%s\"\n", in->name); olsrd_print_interface_cnf(in->cnf, in->cnfi, false); } in = in->next; } } /* Plugins */ if (pe) { printf("Plugins:\n"); while (pe) { printf("\tName: \"%s\"\n", pe->name); pe = pe->next; } } /* Hysteresis */ if (cnf->use_hysteresis) { printf("Using hysteresis:\n"); printf("\tScaling : %0.2f\n", cnf->hysteresis_param.scaling); printf("\tThr high/low : %0.2f/%0.2f\n", cnf->hysteresis_param.thr_high, cnf->hysteresis_param.thr_low); } else { printf("Not using hysteresis\n"); } /* HNA IPv4 and IPv6 */ if (h) { printf("HNA%d entries:\n", cnf->ip_version == AF_INET ? 4 : 6); while (h) { struct ipaddr_str buf; printf("\t%s/", olsr_ip_to_string(&buf, &h->net.prefix)); if (cnf->ip_version == AF_INET) { union olsr_ip_addr ip; olsr_prefix_to_netmask(&ip, h->net.prefix_len); printf("%s\n", olsr_ip_to_string(&buf, &ip)); } else { printf("%d\n", h->net.prefix_len); } h = h->next; } } }
/* * 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; }
static int add_del_route6(const struct rt_entry *rt, int add) { struct rt_msghdr *rtm; unsigned char buff[512]; unsigned char *walker; struct sockaddr_in6 sin6; struct sockaddr_dl sdl; const struct rt_nexthop *nexthop; int sin_size, sdl_size; int len; 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(&sin6, 0, sizeof(sin6)); memset(&sdl, 0, sizeof(sdl)); sin6.sin6_len = sizeof(sin6); sin6.sin6_family = AF_INET6; sdl.sdl_len = sizeof(sdl); sdl.sdl_family = AF_LINK; sin_size = 1 + ((sizeof(struct sockaddr_in6) - 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 != 0) ? RTM_ADD : RTM_DELETE; rtm->rtm_index = 0; 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 **********************************************************************/ memcpy(&sin6.sin6_addr.s6_addr, &rt->rt_dst.prefix.v6, sizeof(struct in6_addr)); memcpy(walker, &sin6, sizeof(sin6)); walker += sin_size; rtm->rtm_addrs = RTA_DST; /********************************************************************** * SET GATEWAY OF THE ROUTE **********************************************************************/ nexthop = olsr_get_nh(rt); if (0 != (rtm->rtm_flags & RTF_GATEWAY)) { memcpy(&sin6.sin6_addr.s6_addr, &nexthop->gateway.v6, sizeof(struct in6_addr)); memset(&sin6.sin6_addr.s6_addr, 0, 8); sin6.sin6_addr.s6_addr[0] = 0xfe; sin6.sin6_addr.s6_addr[1] = 0x80; sin6.sin6_scope_id = nexthop->iif_index; #ifdef __KAME__ *(u_int16_t *) & sin6.sin6_addr.s6_addr[2] = htons(sin6.sin6_scope_id); sin6.sin6_scope_id = 0; #endif memcpy(walker, &sin6, sizeof(sin6)); walker += sin_size; rtm->rtm_addrs |= RTA_GATEWAY; } else { /* * Host is directly reachable, so add * the output interface MAC address. */ memcpy(&sin6.sin6_addr.s6_addr, &rt->rt_dst.prefix.v6, sizeof(struct in6_addr)); memset(&sin6.sin6_addr.s6_addr, 0, 8); sin6.sin6_addr.s6_addr[0] = 0xfe; sin6.sin6_addr.s6_addr[1] = 0x80; sin6.sin6_scope_id = nexthop->iif_index; #ifdef __KAME__ *(u_int16_t *) & sin6.sin6_addr.s6_addr[2] = htons(sin6.sin6_scope_id); sin6.sin6_scope_id = 0; #endif memcpy(walker, &sin6, sizeof(sin6)); walker += sin_size; rtm->rtm_addrs |= RTA_GATEWAY; rtm->rtm_flags |= RTF_GATEWAY; } /********************************************************************** * SET NETMASK **********************************************************************/ if (0 == (rtm->rtm_flags & RTF_HOST)) { olsr_prefix_to_netmask((union olsr_ip_addr *)&sin6.sin6_addr, rt->rt_dst.prefix_len); memcpy(walker, &sin6, sizeof(sin6)); 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 (len < 0 && !(errno == EEXIST || errno == ESRCH)) { fprintf(stderr, "cannot write to routing socket: %s\n", strerror(errno)); } /* * If we get an EEXIST error while adding, delete and retry. */ if (len < 0 && errno == EEXIST && rtm->rtm_type == RTM_ADD) { struct rt_msghdr *drtm; unsigned char dbuff[512]; memset(dbuff, 0, sizeof(dbuff)); drtm = (struct rt_msghdr *)dbuff; drtm->rtm_version = RTM_VERSION; drtm->rtm_type = RTM_DELETE; drtm->rtm_index = 0; drtm->rtm_flags = olsr_rt_flags(rt); drtm->rtm_seq = ++seq; walker = dbuff + sizeof(struct rt_msghdr); memcpy(&sin6.sin6_addr.s6_addr, &rt->rt_dst.prefix.v6, sizeof(struct in6_addr)); memcpy(walker, &sin6, sizeof(sin6)); walker += sin_size; drtm->rtm_addrs = RTA_DST; drtm->rtm_msglen = (unsigned short)(walker - dbuff); len = write(olsr_cnf->rts, dbuff, drtm->rtm_msglen); if (len < 0) { fprintf(stderr, "cannot delete route: %s\n", strerror(errno)); } rtm->rtm_seq = ++seq; len = write(olsr_cnf->rts, buff, rtm->rtm_msglen); if (len < 0) { fprintf(stderr, "still cannot add route: %s\n", strerror(errno)); } } return 0; }