static int route_del(struct rtentry *rt) { if (rt->rt_dev) { route_ctrl(SIOCDELRT, rt); free(rt->rt_dev), rt->rt_dev = NULL; } return 0; }
static int route_del(struct rtentry *rt) { if (rt->rt_dev) { route_ctrl(SIOCDELRT, rt); free(rt->rt_dev), rt->rt_dev = NULL; } memset(rt, 0, sizeof(*rt)); 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; }
/* static */ int route_add(const struct in_addr inetaddr, int any_dgw, struct rtentry *rt) { char buf[256], dev[64], rdev[64]; u_int32_t dest, mask, gateway, flags, bestmask = 0; u_int32_t metric, metric_min = UINT_MAX; FILE *fp = fopen("/proc/net/route", "r"); if (!fp) { /* route_msg("%s: /proc/net/route: %s", strerror(errno), __FUNCTION__); */ return -1; } rt->rt_gateway.sa_family = 0; while (fgets(buf, sizeof(buf), fp)) { 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) continue; if (!any_dgw) { /* use only physical WAN/MAN interface */ if (strncmp(dev, "eth", 3) != 0 && strncmp(dev, "apcli", 5) != 0 && strncmp(dev, "wwan", 4) != 0 && strncmp(dev, "weth", 4) != 0) continue; if ( (inetaddr.s_addr & mask) == dest && gateway ) { 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 = (dest) ? metric : 0; strncpy(rdev, dev, sizeof(rdev)); if (mask == INADDR_BROADCAST) break; } } else { /* skip lo and LAN */ if (strcmp(dev, "lo") == 0 || strcmp(dev, "br0") == 0) continue; if ( !dest && !mask && gateway && metric < metric_min ) { metric_min = metric; sin_addr(&rt->rt_gateway).s_addr = gateway; rt->rt_gateway.sa_family = AF_INET; rt->rt_flags = flags; rt->rt_metric = 0; strncpy(rdev, dev, sizeof(rdev)); } } } fclose(fp); /* 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); memset(rt, 0, sizeof(*rt)); return -1; }
int route_add(const struct in_addr inetaddr, struct rtentry *rt) { char buf[256], dev[64]; int metric, flags; u_int32_t dest, mask; FILE *f = fopen("/proc/net/route", "r"); if (f == NULL) { l2tp_log (LOG_ERR, "/proc/net/route: %s", strerror(errno)); return -1; } while (fgets(buf, sizeof(buf), f)) { if (sscanf(buf, "%63s %x %x %X %*s %*s %d %x", dev, &dest, &sin_addr(&rt->rt_gateway).s_addr, &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*/) { rt->rt_metric = metric + 1; rt->rt_gateway.sa_family = AF_INET; break; } } fclose(f); /* check for no route */ if (rt->rt_gateway.sa_family != AF_INET) { /* l2tp_log (LOG_ERR, "route_add: no route to host"); */ return -1; } /* check for existing route to this host, add if missing based on the existing routes */ if (flags & RTF_HOST) { /* l2tp_log (LOG_ERR, "route_add: not adding existing route"); */ 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_UP | RTF_HOST; if (flags & RTF_GATEWAY) rt->rt_flags |= RTF_GATEWAY; rt->rt_metric++; rt->rt_dev = strdup(dev); if (!rt->rt_dev) { l2tp_log (LOG_ERR, "route_add: no memory"); return -1; } if (!route_ctrl(SIOCADDRT, rt)) return 0; free(rt->rt_dev); rt->rt_dev = NULL; return -1; }