X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=interface-ip.c;h=d5488efafbe18fbd32d5d602262601484f5d2046;hb=aaa5a702b7ff4b6b086cf24a2c3caa34d7cb1fe2;hp=0558b6c7aac9ed7caab0b1e87840837e53766973;hpb=575b1fe1bc8f15e65d89a0905e1640277c17fadc;p=project%2Fnetifd.git diff --git a/interface-ip.c b/interface-ip.c index 0558b6c..d5488ef 100644 --- a/interface-ip.c +++ b/interface-ip.c @@ -141,14 +141,19 @@ interface_ip_add_target_route(union if_addr *addr, bool v6) { struct interface *iface; struct device_route *route, *r_next = NULL; + bool defaultroute_target = false; + int addrsize = v6 ? sizeof(addr->in6) : sizeof(addr->in); route = calloc(1, sizeof(*route)); if (!route) - return false; + return NULL; route->flags = v6 ? DEVADDR_INET6 : DEVADDR_INET4; route->mask = v6 ? 128 : 32; - memcpy(&route->addr, addr, v6 ? sizeof(addr->in6) : sizeof(addr->in)); + if (memcmp(&route->addr, addr, addrsize) == 0) + defaultroute_target = true; + else + memcpy(&route->addr, addr, addrsize); vlist_for_each_element(&interfaces, iface, node) { /* look for locally addressable target first */ @@ -160,8 +165,10 @@ interface_ip_add_target_route(union if_addr *addr, bool v6) interface_ip_find_route_target(iface, addr, v6, &r_next); } - if (!r_next) + if (!r_next) { + free(route); return NULL; + } iface = r_next->iface; memcpy(&route->nexthop, &r_next->nexthop, sizeof(route->nexthop)); @@ -170,7 +177,10 @@ interface_ip_add_target_route(union if_addr *addr, bool v6) done: route->iface = iface; - vlist_add(&iface->host_routes, &route->node, &route->flags); + if (defaultroute_target) + free(route); + else + vlist_add(&iface->host_routes, &route->node, &route->flags); return iface; } @@ -210,7 +220,7 @@ interface_ip_add_route(struct interface *iface, struct blob_attr *attr, bool v6) } if ((cur = tb[ROUTE_TARGET]) != NULL) { - if (!inet_pton(af, blobmsg_data(cur), &route->addr)) { + if (!parse_ip_and_netmask(af, blobmsg_data(cur), &route->addr, &route->mask)) { DPRINTF("Failed to parse route target: %s\n", (char *) blobmsg_data(cur)); goto error; } @@ -228,8 +238,10 @@ interface_ip_add_route(struct interface *iface, struct blob_attr *attr, bool v6) route->flags |= DEVROUTE_METRIC; } - if ((cur = tb[ROUTE_MTU]) != NULL) + if ((cur = tb[ROUTE_MTU]) != NULL) { route->mtu = blobmsg_get_u32(cur); + route->flags |= DEVROUTE_MTU; + } vlist_add(&ip->route, &route->node, &route->flags); return; @@ -252,6 +264,31 @@ route_cmp(const void *k1, const void *k2, void *ptr) offsetof(struct device_route, flags)); } +static void +interface_handle_subnet_route(struct interface *iface, struct device_addr *addr, bool add) +{ + struct device *dev = iface->l3_dev.dev; + struct device_route route; + + memset(&route, 0, sizeof(route)); + route.iface = iface; + route.flags = addr->flags; + route.mask = addr->mask; + memcpy(&route.addr, &addr->addr, sizeof(route.addr)); + clear_if_addr(&route.addr, route.mask); + + if (add) { + route.flags |= DEVADDR_KERNEL; + system_del_route(dev, &route); + + route.flags &= ~DEVADDR_KERNEL; + route.metric = iface->metric; + system_add_route(dev, &route); + } else { + system_del_route(dev, &route); + } +} + static void interface_update_proto_addr(struct vlist_tree *tree, struct vlist_node *node_new, @@ -262,7 +299,6 @@ interface_update_proto_addr(struct vlist_tree *tree, struct device *dev; struct device_addr *a_new = NULL, *a_old = NULL; bool keep = false; - struct device_route *route; ip = container_of(tree, struct interface_ip_settings, addr); iface = ip->iface; @@ -278,7 +314,7 @@ interface_update_proto_addr(struct vlist_tree *tree, uint32_t *a = (uint32_t *) &a_new->addr; mask >>= a_new->mask; - a_new->broadcast = *a | mask; + a_new->broadcast = *a | htonl(mask); } } @@ -297,8 +333,10 @@ interface_update_proto_addr(struct vlist_tree *tree, } if (node_old) { - if (!(a_old->flags & DEVADDR_EXTERNAL) && a_old->enabled && !keep) + if (!(a_old->flags & DEVADDR_EXTERNAL) && a_old->enabled && !keep) { + interface_handle_subnet_route(iface, a_old, false); system_del_address(dev, a_old); + } free(a_old); } @@ -307,24 +345,9 @@ interface_update_proto_addr(struct vlist_tree *tree, if (!(a_new->flags & DEVADDR_EXTERNAL) && !keep) { system_add_address(dev, a_new); if (iface->metric) - goto replace_route; + interface_handle_subnet_route(iface, a_new, true); } } - return; - -replace_route: - route = calloc(1, sizeof(*route)); - route->iface = iface; - route->flags = a_new->flags | DEVADDR_KERNEL; - route->mask = a_new->mask; - memcpy(&route->addr, &a_new->addr, sizeof(route->addr)); - clear_if_addr(&route->addr, route->mask); - - system_del_route(dev, route); - - route->flags &= ~DEVADDR_KERNEL; - route->metric = iface->metric; - vlist_add(&ip->route, &route->node, &route->flags); } static bool @@ -407,6 +430,9 @@ interface_add_dns_server(struct interface_ip_settings *ip, const char *str) struct dns_server *s; s = calloc(1, sizeof(*s)); + if (!s) + return; + s->af = AF_INET; if (inet_pton(s->af, str, &s->addr.in)) goto add;