Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions interface-event.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ run_cmd(const char *ifname, const char *device, enum interface_event event,
setenv("IFUPDATE_PREFIXES", "1", 1);
if (updated & IUF_DATA)
setenv("IFUPDATE_DATA", "1", 1);
if (updated & IUF_POLICY)
setenv("IFUPDATE_POLICY", "1", 1);
}

argv[0] = hotplug_cmd_path;
Expand Down
29 changes: 29 additions & 0 deletions interface-ip.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,33 @@ static int set_ip_lo_policy(bool add, bool v6, struct interface *iface)
return (add) ? system_add_iprule(&rule) : system_del_iprule(&rule);
}

static int
set_ip_stronghost_policy_family(bool add, bool v6, struct interface *iface)
{
struct iprule rule = {
.flags = IPRULE_FWMARK | IPRULE_FWMASK | IPRULE_LOOKUP |
IPRULE_PRIORITY,
.priority = IPRULE_PRIORITY_STRONGHOST,
.fwmark = iface->stronghost_mark,
.fwmask = iface->stronghost_mask,
.lookup = v6 ? iface->ip6table : iface->ip4table,
};

if (!rule.lookup || !rule.fwmask)
return 0;

rule.flags |= v6 ? IPRULE_INET6 : IPRULE_INET4;

return add ? system_add_iprule(&rule) : system_del_iprule(&rule);
}

void
interface_ip_set_stronghost_policy(struct interface *iface, bool enabled)
{
set_ip_stronghost_policy_family(enabled, true, iface);
set_ip_stronghost_policy_family(enabled, false, iface);
}

static bool
__find_ip_addr_target(struct interface_ip_settings *ip, union if_addr *a, bool v6)
{
Expand Down Expand Up @@ -1807,6 +1834,8 @@ void interface_ip_set_enabled(struct interface_ip_settings *ip, bool enabled)

if (ip->iface->policy_rules_set != enabled &&
ip->iface->l3_dev.dev) {
interface_ip_set_stronghost_policy(ip->iface, enabled);

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,
Expand Down
1 change: 1 addition & 0 deletions interface-ip.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ void interface_ip_update_start(struct interface_ip_settings *ip);
void interface_ip_update_complete(struct interface_ip_settings *ip);
void interface_ip_flush(struct interface_ip_settings *ip);
void interface_ip_set_enabled(struct interface_ip_settings *ip, bool enabled);
void interface_ip_set_stronghost_policy(struct interface *iface, bool enabled);
void interface_ip_update_metric(struct interface_ip_settings *ip, int metric);

struct interface *interface_ip_add_target_route(union if_addr *addr, bool v6, struct interface *iface,
Expand Down
48 changes: 48 additions & 0 deletions interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ enum {
IFACE_ATTR_IP6HINT,
IFACE_ATTR_IP4TABLE,
IFACE_ATTR_IP6TABLE,
IFACE_ATTR_STRONGHOST_MARK,
IFACE_ATTR_IP6CLASS,
IFACE_ATTR_DELEGATE,
IFACE_ATTR_IP6IFACEID,
Expand Down Expand Up @@ -100,6 +101,7 @@ static const struct blobmsg_policy iface_attrs[IFACE_ATTR_MAX] = {
[IFACE_ATTR_IP6HINT] = { .name = "ip6hint", .type = BLOBMSG_TYPE_STRING },
[IFACE_ATTR_IP4TABLE] = { .name = "ip4table", .type = BLOBMSG_TYPE_STRING },
[IFACE_ATTR_IP6TABLE] = { .name = "ip6table", .type = BLOBMSG_TYPE_STRING },
[IFACE_ATTR_STRONGHOST_MARK] = { .name = "stronghost_mark", .type = BLOBMSG_TYPE_STRING },
[IFACE_ATTR_IP6CLASS] = { .name = "ip6class", .type = BLOBMSG_TYPE_ARRAY },
[IFACE_ATTR_DELEGATE] = { .name = "delegate", .type = BLOBMSG_TYPE_BOOL },
[IFACE_ATTR_IP6IFACEID] = { .name = "ip6ifaceid", .type = BLOBMSG_TYPE_STRING },
Expand All @@ -114,6 +116,27 @@ const struct uci_blob_param_list interface_attr_list = {
.params = iface_attrs,
};

static bool
interface_parse_stronghost_mark(const char *str, unsigned int *mark,
unsigned int *mask)
{
char *end;
unsigned long value, value_mask;

value = strtoul(str, &end, 0);
if (end == str || *end != '/' || value > UINT32_MAX)
return false;

str = end + 1;
value_mask = strtoul(str, &end, 0);
if (end == str || *end || !value_mask || value_mask > UINT32_MAX)
return false;

*mark = value;
*mask = value_mask;
return *mark && !(*mark & ~*mask);
}

static void
interface_set_main_dev(struct interface *iface, struct device *dev);
static void
Expand Down Expand Up @@ -1047,6 +1070,14 @@ interface_alloc(const char *name, struct blob_attr *config, bool dynamic)
D(INTERFACE, "Failed to resolve routing table: %s", (char *) blobmsg_data(cur));
}

if ((cur = tb[IFACE_ATTR_STRONGHOST_MARK]) &&
!interface_parse_stronghost_mark(blobmsg_data(cur),
&iface->stronghost_mark,
&iface->stronghost_mask))
netifd_log_message(L_WARNING,
"Invalid stronghost_mark value '%s' for interface '%s'\n",
(char *) blobmsg_data(cur), iface->name);

iface->proto_ip.no_delegation = !blobmsg_get_bool_default(tb[IFACE_ATTR_DELEGATE], true);

iface->config_autostart = iface->autostart;
Expand Down Expand Up @@ -1508,6 +1539,7 @@ interface_change_config(struct interface *if_old, struct interface *if_new)
{
struct blob_attr *old_config = if_old->config;
bool reload = false, reload_ip = false, update_prefix_delegation = false;
bool stronghost_policy_changed;

/*
* The interface is being redefined: cancel a pending deferred removal,
Expand Down Expand Up @@ -1546,6 +1578,15 @@ interface_change_config(struct interface *if_old, struct interface *if_new)
__var |= __changed; \
})

stronghost_policy_changed =
if_old->ip4table != if_new->ip4table ||
if_old->ip6table != if_new->ip6table ||
if_old->stronghost_mark != if_new->stronghost_mark ||
if_old->stronghost_mask != if_new->stronghost_mask;

if (stronghost_policy_changed && if_old->policy_rules_set)
interface_ip_set_stronghost_policy(if_old, false);

if_old->config = if_new->config;
if_old->tags = if_new->tags;
if (if_old->config_autostart != if_new->config_autostart) {
Expand Down Expand Up @@ -1595,6 +1636,8 @@ interface_change_config(struct interface *if_old, struct interface *if_new)
UPDATE(proto_ip.no_defaultroute, reload_ip);
UPDATE(ip4table, reload_ip);
UPDATE(ip6table, reload_ip);
UPDATE(stronghost_mark, reload_ip);
UPDATE(stronghost_mask, reload_ip);
interface_merge_assignment_data(if_old, if_new);

#undef UPDATE
Expand Down Expand Up @@ -1624,6 +1667,11 @@ interface_change_config(struct interface *if_old, struct interface *if_new)
interface_ip_set_enabled(&if_old->config_ip, config_ip_enabled);
}

if (stronghost_policy_changed && if_old->state == IFS_UP) {
if_old->updated |= IUF_POLICY;
interface_event(if_old, IFEV_UPDATE);
}

if (update_prefix_delegation)
interface_update_prefix_delegation(&if_old->proto_ip);

Expand Down
3 changes: 3 additions & 0 deletions interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ enum interface_update_flags {
IUF_ROUTE = (1 << 1),
IUF_PREFIX = (1 << 2),
IUF_DATA = (1 << 3),
IUF_POLICY = (1 << 4),
};

struct interface_error {
Expand Down Expand Up @@ -164,6 +165,8 @@ struct interface {
int dns_metric;
unsigned int ip4table;
unsigned int ip6table;
unsigned int stronghost_mark;
unsigned int stronghost_mask;

/* IPv6 assignment parameters */
enum interface_id_selection_type assignment_iface_id_selection;
Expand Down
1 change: 1 addition & 0 deletions iprule.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "interface-ip.h"

#define IPRULE_PRIORITY_ADDR 10000
#define IPRULE_PRIORITY_STRONGHOST 9000
#define IPRULE_PRIORITY_ADDR_MASK 20000
#define IPRULE_PRIORITY_NW 90000
#define IPRULE_PRIORITY_REJECT 4200000000
Expand Down
9 changes: 9 additions & 0 deletions ubus.c
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,8 @@ netifd_dump_status(struct interface *iface)
blobmsg_add_string(&b, NULL, "prefixes");
if (iface->updated & IUF_DATA)
blobmsg_add_string(&b, NULL, "data");
if (iface->updated & IUF_POLICY)
blobmsg_add_string(&b, NULL, "policy");

blobmsg_close_array(&b, a);
}
Expand All @@ -875,6 +877,13 @@ netifd_dump_status(struct interface *iface)
blobmsg_add_u32(&b, "ip4table", iface->ip4table);
if (iface->ip6table)
blobmsg_add_u32(&b, "ip6table", iface->ip6table);
if (iface->stronghost_mask) {
void *mark = blobmsg_open_table(&b, "stronghost_mark");

blobmsg_add_u32(&b, "value", iface->stronghost_mark);
blobmsg_add_u32(&b, "mask", iface->stronghost_mask);
blobmsg_close_table(&b, mark);
}
blobmsg_add_u32(&b, "metric", iface->metric);
blobmsg_add_u32(&b, "dns_metric", iface->dns_metric);
blobmsg_add_u8(&b, "delegation", !iface->proto_ip.no_delegation);
Expand Down