From f6fb6bee2c29f31d13d0b0288f4f680b6b56e9ba Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 3 May 2011 00:53:40 +0200 Subject: [PATCH] add routes/gateway support --- config/network | 1 + interface-ip.c | 20 ++++++++++++++++++++ interface.c | 1 + interface.h | 4 ++++ proto-static.c | 41 +++++++++++++++++++++++++++-------------- system-dummy.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ system.h | 3 +++ 7 files changed, 108 insertions(+), 14 deletions(-) diff --git a/config/network b/config/network index 1f803a0..fa8ef38 100644 --- a/config/network +++ b/config/network @@ -31,4 +31,5 @@ config interface lan2 option proto static option ipaddr 192.168.1.1 option netmask 255.255.255.0 + option gateway 192.168.1.2 diff --git a/interface-ip.c b/interface-ip.c index 51f23ef..6c673c6 100644 --- a/interface-ip.c +++ b/interface-ip.c @@ -46,3 +46,23 @@ void interface_del_ctx_addr(struct interface *iface, void *ctx) interface_del_address(iface, addr); } } + +int interface_add_route(struct interface *iface, struct device_route *route) +{ + list_add(&route->list, &iface->routes); + return system_add_route(iface->l3_iface->dev, route); +} + +void interface_del_route(struct interface *iface, struct device_route *route) +{ + list_del(&route->list); + system_del_route(iface->l3_iface->dev, route); +} + +void interface_del_all_routes(struct interface *iface) +{ + struct device_route *route, *tmp; + + list_for_each_entry_safe(route, tmp, &iface->routes, list) + interface_del_route(iface, route); +} diff --git a/interface.c b/interface.c index 0a53151..dd303ef 100644 --- a/interface.c +++ b/interface.c @@ -104,6 +104,7 @@ __set_interface_down(struct interface *iface, bool force) iface->state = IFS_TEARDOWN; interface_event(iface, IFEV_DOWN); + interface_del_all_routes(iface); interface_proto_event(iface->proto, PROTO_CMD_TEARDOWN, force); } diff --git a/interface.h b/interface.h index 2d13b48..480f759 100644 --- a/interface.h +++ b/interface.h @@ -77,6 +77,10 @@ int interface_add_address(struct interface *iface, struct device_addr *addr); void interface_del_address(struct interface *iface, struct device_addr *addr); void interface_del_ctx_addr(struct interface *iface, void *ctx); +int interface_add_route(struct interface *iface, struct device_route *route); +void interface_del_route(struct interface *iface, struct device_route *route); +void interface_del_all_routes(struct interface *iface); + void start_pending_interfaces(void); #endif diff --git a/proto-static.c b/proto-static.c index 53e0ec8..3c251f4 100644 --- a/proto-static.c +++ b/proto-static.c @@ -93,6 +93,27 @@ parse_address_option(struct static_proto_state *state, struct uci_option *o, boo return n_addr; } +static bool +parse_gateway_option(struct static_proto_state *state, struct uci_option *o, bool v6) +{ + struct device_route *route; + const char *str = o->v.string; + int af = v6 ? AF_INET6 : AF_INET; + + route = calloc(1, sizeof(*route)); + if (!inet_pton(af, str, &route->nexthop)) { + interface_add_error(state->iface, "proto-static", + "INVALID_GATEWAY", &str, 1); + free(route); + return false; + } + route->mask = 0; + route->flags = DEVADDR_DEVICE | (v6 ? DEVADDR_INET6 : DEVADDR_INET4); + interface_add_route(state->iface, route); + + return true; +} + enum { OPT_IPADDR, OPT_IP6ADDR, @@ -144,23 +165,15 @@ static_proto_setup(struct static_proto_state *state) if (n_v4 < 0 || n_v6 < 0) goto out; -#if 0 - if (ps.n_v4 && tb[OPT_GATEWAY]) { - if (!inet_pton(AF_INET, tb[OPT_GATEWAY]->v.string, &ps.ipv4gw)) { - error = "INVALID_GATEWAY"; - goto error; - } - ps.flags |= STATIC_F_IPV4GW; + if (n_v4 && tb[OPT_GATEWAY]) { + if (!parse_gateway_option(state, tb[OPT_GATEWAY], false)) + goto out; } - if (ps.n_v6 && tb[OPT_IP6GW]) { - if (!inet_pton(AF_INET6, tb[OPT_IP6GW]->v.string, &ps.ipv6gw)) { - error = "INVALID_GATEWAY"; - goto error; - } - ps.flags |= STATIC_F_IPV6GW; + if (n_v6 && tb[OPT_IP6GW]) { + if (!parse_gateway_option(state, tb[OPT_IP6GW], true)) + goto out; } -#endif return true; diff --git a/system-dummy.c b/system-dummy.c index 2d391df..f24f686 100644 --- a/system-dummy.c +++ b/system-dummy.c @@ -89,3 +89,55 @@ int system_del_address(struct device *dev, struct device_addr *addr) return 0; } + +int system_add_route(struct device *dev, struct device_route *route) +{ + uint8_t *a1 = (uint8_t *) &route->addr.in; + uint8_t *a2 = (uint8_t *) &route->nexthop.in; + char addr[40], gw[40] = "", devstr[64] = ""; + + if ((route->flags & DEVADDR_FAMILY) != DEVADDR_INET4) + return -1; + + if (!route->mask) + sprintf(addr, "default"); + else + sprintf(addr, "%d.%d.%d.%d/%d", + a1[0], a1[1], a1[2], a1[3], route->mask); + + if (memcmp(a2, "\x00\x00\x00\x00", 4) != 0) + sprintf(gw, " gw %d.%d.%d.%d", + a2[0], a2[1], a2[2], a2[3]); + + if (route->flags & DEVADDR_DEVICE) + sprintf(devstr, " dev %s", dev->ifname); + + DPRINTF("route add %s%s%s\n", addr, gw, devstr); + return 0; +} + +int system_del_route(struct device *dev, struct device_route *route) +{ + uint8_t *a1 = (uint8_t *) &route->addr.in; + uint8_t *a2 = (uint8_t *) &route->nexthop.in; + char addr[40], gw[40] = "", devstr[64] = ""; + + if ((route->flags & DEVADDR_FAMILY) != DEVADDR_INET4) + return -1; + + if (!route->mask) + sprintf(addr, "default"); + else + sprintf(addr, "%d.%d.%d.%d/%d", + a1[0], a1[1], a1[2], a1[3], route->mask); + + if (memcmp(a2, "\x00\x00\x00\x00", 4) != 0) + sprintf(gw, " gw %d.%d.%d.%d", + a2[0], a2[1], a2[2], a2[3]); + + if (route->flags & DEVADDR_DEVICE) + sprintf(devstr, " dev %s", dev->ifname); + + DPRINTF("route del %s%s%s\n", addr, gw, devstr); + return 0; +} diff --git a/system.h b/system.h index 3364151..835a49d 100644 --- a/system.h +++ b/system.h @@ -19,4 +19,7 @@ int system_if_check(struct device *dev); int system_add_address(struct device *dev, struct device_addr *addr); int system_del_address(struct device *dev, struct device_addr *addr); +int system_add_route(struct device *dev, struct device_route *route); +int system_del_route(struct device *dev, struct device_route *route); + #endif -- 2.11.0