int route_get(route_t *r, struct route_entry *entry) { if (route_msg(r, RTM_GET, &entry->route_dst, &entry->route_gw) < 0) return (-1); return (0); }
int route_get(route_t *r, struct route_entry *entry) { if (route_msg(r, RTM_GET, entry->intf_name, &entry->route_dst, &entry->route_gw) < 0) return (-1); entry->intf_name[0] = '\0'; entry->metric = 0; return (0); }
int route_add(route_t *r, const struct route_entry *entry) { struct route_entry rtent; memcpy(&rtent, entry, sizeof(rtent)); if (route_msg(r, RTM_ADD, &rtent.route_dst, &rtent.route_gw) < 0) return (-1); return (0); }
/* Route manipulation */ static int route_ctrl(int ctrl, struct rtentry *rt) { int s; /* Open a raw socket to the kernel */ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0 || ioctl(s, ctrl, rt) < 0) route_msg("%s: %s", __FUNCTION__, strerror(errno)); else errno = 0; close(s); return errno; }
/* * this thread listens to incoming_wdp list * and then routs messages to proper wapbox */ static void wdp_to_wapboxes(void *arg) { List *route_info; AddrPar *ap; Boxc *conn; Msg *msg; int i; gwlist_add_producer(flow_threads); gwlist_add_producer(wapbox_list); route_info = gwlist_create(); while(bb_status != BB_DEAD) { gwlist_consume(suspended); /* block here if suspended */ if ((msg = gwlist_consume(incoming_wdp)) == NULL) break; gw_assert(msg_type(msg) == wdp_datagram); conn = route_msg(route_info, msg); if (conn == NULL) { warning(0, "Cannot route message, discard it"); msg_destroy(msg); continue; } gwlist_produce(conn->incoming, msg); } debug("bb", 0, "wdp_to_wapboxes: destroying lists"); while((ap = gwlist_extract_first(route_info)) != NULL) ap_destroy(ap); gw_assert(gwlist_len(route_info) == 0); gwlist_destroy(route_info, NULL); gwlist_lock(wapbox_list); for(i=0; i < gwlist_len(wapbox_list); i++) { conn = gwlist_get(wapbox_list, i); gwlist_remove_producer(conn->incoming); conn->alive = 0; } gwlist_unlock(wapbox_list); gwlist_remove_producer(wapbox_list); gwlist_remove_producer(flow_threads); }
int route_delete(route_t *r, const struct route_entry *entry) { struct route_entry rtent; memcpy(&rtent, entry, sizeof(rtent)); if (route_get(r, &rtent) < 0) return (-1); if (route_msg(r, RTM_DELETE, &rtent.route_dst, &rtent.route_gw) < 0) return (-1); return (0); }
static int route_add(const struct in_addr inetaddr, struct rtentry *rt) { char buf[256], dev[64], rdev[64]; u_int32_t dest, mask, gateway, flags, bestmask = 0; int metric; FILE *f = fopen("/proc/net/route", "r"); if (f == NULL) { route_msg("%s: /proc/net/route: %s", strerror(errno), __FUNCTION__); return -1; } rt->rt_gateway.sa_family = 0; while (fgets(buf, sizeof(buf), f)) { if (sscanf(buf, "%63s %x %x %x %*s %*s %d %x", dev, &dest, &gateway, &flags, &metric, &mask) != 6) continue; if ((flags & RTF_UP) == (RTF_UP) && (inetaddr.s_addr & mask) == dest && (dest || strncmp(dev, "ppp", 3)) /* avoid default via pppX to avoid on-demand loops*/) { if ((mask | bestmask) == bestmask && rt->rt_gateway.sa_family) continue; bestmask = mask; sin_addr(&rt->rt_gateway).s_addr = gateway; rt->rt_gateway.sa_family = AF_INET; rt->rt_flags = flags; rt->rt_metric = metric; strncpy(rdev, dev, sizeof(rdev)); if (mask == INADDR_BROADCAST) break; } } fclose(f); /* check for no route */ if (rt->rt_gateway.sa_family != AF_INET) { /* route_msg("%s: no route to host", __FUNCTION__); */ return -1; } /* check for existing route to this host, * add if missing based on the existing routes */ if (rt->rt_flags & RTF_HOST) { /* route_msg("%s: not adding existing route", __FUNCTION__); */ return -1; } sin_addr(&rt->rt_dst) = inetaddr; rt->rt_dst.sa_family = AF_INET; sin_addr(&rt->rt_genmask).s_addr = INADDR_BROADCAST; rt->rt_genmask.sa_family = AF_INET; rt->rt_flags &= RTF_GATEWAY; rt->rt_flags |= RTF_UP | RTF_HOST; rt->rt_metric++; rt->rt_dev = strdup(rdev); if (!rt->rt_dev) { /* route_msg("%s: no memory", __FUNCTION__); */ return -1; } if (!route_ctrl(SIOCADDRT, rt)) return 0; free(rt->rt_dev), rt->rt_dev = NULL; return -1; }