add routes/gateway support
authorFelix Fietkau <nbd@openwrt.org>
Mon, 2 May 2011 22:53:40 +0000 (00:53 +0200)
committerFelix Fietkau <nbd@openwrt.org>
Mon, 2 May 2011 22:53:40 +0000 (00:53 +0200)
config/network
interface-ip.c
interface.c
interface.h
proto-static.c
system-dummy.c
system.h

index 1f803a0..fa8ef38 100644 (file)
@@ -31,4 +31,5 @@ config interface lan2
        option proto    static
        option ipaddr   192.168.1.1
        option netmask  255.255.255.0
        option proto    static
        option ipaddr   192.168.1.1
        option netmask  255.255.255.0
+       option gateway  192.168.1.2
 
 
index 51f23ef..6c673c6 100644 (file)
@@ -46,3 +46,23 @@ void interface_del_ctx_addr(struct interface *iface, void *ctx)
                interface_del_address(iface, addr);
        }
 }
                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);
+}
index 0a53151..dd303ef 100644 (file)
@@ -104,6 +104,7 @@ __set_interface_down(struct interface *iface, bool force)
        iface->state = IFS_TEARDOWN;
        interface_event(iface, IFEV_DOWN);
 
        iface->state = IFS_TEARDOWN;
        interface_event(iface, IFEV_DOWN);
 
+       interface_del_all_routes(iface);
        interface_proto_event(iface->proto, PROTO_CMD_TEARDOWN, force);
 }
 
        interface_proto_event(iface->proto, PROTO_CMD_TEARDOWN, force);
 }
 
index 2d13b48..480f759 100644 (file)
@@ -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);
 
 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
 void start_pending_interfaces(void);
 
 #endif
index 53e0ec8..3c251f4 100644 (file)
@@ -93,6 +93,27 @@ parse_address_option(struct static_proto_state *state, struct uci_option *o, boo
        return n_addr;
 }
 
        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,
 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 (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;
 
 
        return true;
 
index 2d391df..f24f686 100644 (file)
@@ -89,3 +89,55 @@ int system_del_address(struct device *dev, struct device_addr *addr)
 
        return 0;
 }
 
        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;
+}
index 3364151..835a49d 100644 (file)
--- 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_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
 #endif