static void
clear_if_addr(union if_addr *a, int mask)
{
- int m_bytes = (mask + 7) / 8;
+ size_t m_bytes = (mask + 7) / 8;
uint8_t m_clear = (1 << (m_bytes * 8 - mask)) - 1;
uint8_t *p = (uint8_t *) a;
}
struct interface *
-interface_ip_add_target_route(union if_addr *addr, bool v6, struct interface *iface)
+interface_ip_add_target_route(union if_addr *addr, bool v6, struct interface *iface,
+ bool exclude)
{
struct device_route *route, *r_next = NULL;
bool defaultroute_target = false;
union if_addr addr_zero;
int addrsize = v6 ? sizeof(addr->in6) : sizeof(addr->in);
+ struct interface *exclude_iface = NULL;
+
+ if (exclude) {
+ exclude_iface = iface;
+ iface = NULL;
+ }
memset(&addr_zero, 0, sizeof(addr_zero));
if (memcmp(&addr_zero, addr, addrsize) == 0)
interface_ip_find_route_target(iface, addr, v6, &r_next);
} else {
vlist_for_each_element(&interfaces, iface, node) {
+ if (iface == exclude_iface)
+ continue;
+
/* look for locally addressable target first */
if (interface_ip_find_addr_target(iface, addr, v6))
return iface;
}
static void
-interface_update_proto_route(struct vlist_tree *tree,
- struct vlist_node *node_new,
- struct vlist_node *node_old)
+__interface_update_route(struct interface_ip_settings *ip,
+ struct vlist_node *node_new,
+ struct vlist_node *node_old)
{
- struct interface_ip_settings *ip;
- struct interface *iface;
+ struct interface *iface = ip->iface;
struct device *dev;
struct device_route *route_old, *route_new;
bool keep = false;
- ip = container_of(tree, struct interface_ip_settings, route);
- iface = ip->iface;
dev = iface->l3_dev.dev;
if (!node_new || !node_old)
}
}
+static void
+interface_update_proto_route(struct vlist_tree *tree,
+ struct vlist_node *node_new,
+ struct vlist_node *node_old)
+{
+ struct interface_ip_settings *ip;
+
+ ip = container_of(tree, struct interface_ip_settings, route);
+ __interface_update_route(ip, node_new, node_old);
+}
+
static void
interface_update_host_route(struct vlist_tree *tree,
struct vlist_node *node_new,
struct vlist_node *node_old)
{
struct interface *iface;
- struct device *dev;
- struct device_route *route_old, *route_new;
iface = container_of(tree, struct interface, host_routes);
- dev = iface->l3_dev.dev;
-
- route_old = container_of(node_old, struct device_route, node);
- route_new = container_of(node_new, struct device_route, node);
-
- if (node_old) {
- system_del_route(dev, route_old);
- free(route_old);
- }
-
- if (node_new) {
- if (system_add_route(dev, route_new))
- route_new->failed = true;
- }
+ __interface_update_route(&iface->proto_ip, node_new, node_old);
}
static void
void
interface_write_resolv_conf(const char *jail)
{
- size_t plen = (jail ? strlen(jail) + 1 : 0 ) + strlen(resolv_conf) + 1;
+ size_t plen = (jail ? strlen(jail) + 1 : 0 ) +
+ (strlen(resolv_conf) >= strlen(DEFAULT_RESOLV_CONF) ?
+ strlen(resolv_conf) : strlen(DEFAULT_RESOLV_CONF) ) + 1;
char *path = alloca(plen);
char *dpath = alloca(plen);
char *tmppath = alloca(plen + 4);
}
}
+static void
+interface_ip_set_route_enabled(struct interface_ip_settings *ip,
+ struct device_route *route, bool enabled)
+{
+ struct device *dev = ip->iface->l3_dev.dev;
+
+ if (route->flags & DEVADDR_EXTERNAL)
+ return;
+
+ if (!enable_route(ip, route))
+ enabled = false;
+
+ if (route->enabled == enabled)
+ return;
+
+ if (enabled) {
+ interface_set_route_info(ip->iface, route);
+
+ if (system_add_route(dev, route))
+ route->failed = true;
+ } else
+ system_del_route(dev, route);
+
+ route->enabled = enabled;
+}
+
void interface_ip_set_enabled(struct interface_ip_settings *ip, bool enabled)
{
struct device_addr *addr;
addr->enabled = enabled;
}
- vlist_for_each_element(&ip->route, route, node) {
- bool _enabled = enabled;
-
- if (route->flags & DEVADDR_EXTERNAL)
- continue;
-
- if (!enable_route(ip, route))
- _enabled = false;
- if (route->enabled == _enabled)
- continue;
-
- if (_enabled) {
- interface_set_route_info(ip->iface, route);
-
- if (system_add_route(dev, route))
- route->failed = true;
- } else
- system_del_route(dev, route);
-
- route->enabled = _enabled;
- }
+ vlist_for_each_element(&ip->route, route, node)
+ interface_ip_set_route_enabled(ip, route, enabled);
+ if (ip == &iface->proto_ip)
+ vlist_for_each_element(&iface->host_routes, route, node)
+ interface_ip_set_route_enabled(ip, route, enabled);
vlist_for_each_element(&ip->neighbor, neighbor, node) {
if (neighbor->enabled == enabled)
if (ip->iface->policy_rules_set != enabled &&
ip->iface->l3_dev.dev) {
- set_ip_lo_policy(enabled, true, ip->iface);
+ if (ip->iface->l3_dev.dev->settings.ipv6) {
+ set_ip_lo_policy(enabled, true, ip->iface);
+ set_ip_source_policy(enabled, true, IPRULE_PRIORITY_REJECT + ip->iface->l3_dev.dev->ifindex,
+ NULL, 0, 0, ip->iface, "failed_policy", true);
+ }
set_ip_lo_policy(enabled, false, ip->iface);
- set_ip_source_policy(enabled, true, IPRULE_PRIORITY_REJECT + ip->iface->l3_dev.dev->ifindex,
- NULL, 0, 0, ip->iface, "failed_policy", true);
ip->iface->policy_rules_set = enabled;
}
}