Bump netifd versiob 2017.01.25

This commit is contained in:
2017-03-18 22:47:13 +01:00
parent 7195cc3d28
commit 45d0a9919a
30 changed files with 521 additions and 187 deletions

View File

@@ -4,7 +4,7 @@
# #
################################################################################ ################################################################################
NETIFD_VERSION:= 2016.06.06 NETIFD_VERSION:= 2017.01.25
NETIFD_SITE = $(TOPDIR)/../../src/3P/netifd/builders/cmake NETIFD_SITE = $(TOPDIR)/../../src/3P/netifd/builders/cmake
NETIFD_SITE_METHOD = local NETIFD_SITE_METHOD = local

View File

@@ -5,11 +5,6 @@ ADD_DEFINITIONS(-Os -Wall -Werror --std=gnu99 -Wmissing-declarations)
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
IF(APPLE)
INCLUDE_DIRECTORIES(/opt/local/include)
LINK_DIRECTORIES(/opt/local/lib)
ENDIF()
SET(SOURCES SET(SOURCES
main.c utils.c system.c tunnel.c handler.c main.c utils.c system.c tunnel.c handler.c
interface.c interface-ip.c interface-event.c interface.c interface-ip.c interface-event.c

View File

@@ -30,8 +30,6 @@ struct alias_device {
char name[]; char name[];
}; };
static const struct device_type alias_device_type;
static void alias_set_device(struct alias_device *alias, struct device *dev) static void alias_set_device(struct alias_device *alias, struct device *dev)
{ {
if (dev == alias->dep.dev) { if (dev == alias->dep.dev) {
@@ -61,8 +59,10 @@ static void alias_set_device(struct alias_device *alias, struct device *dev)
device_set_ifindex(&alias->dev, dev->ifindex); device_set_ifindex(&alias->dev, dev->ifindex);
device_set_ifname(&alias->dev, dev->ifname); device_set_ifname(&alias->dev, dev->ifname);
device_add_user(&alias->dep, dev); device_add_user(&alias->dep, dev);
} else } else {
device_set_ifname(&alias->dev, ""); device_set_ifname(&alias->dev, "");
device_set_link(&alias->dev, false);
}
} }
static int static int
@@ -111,7 +111,8 @@ static void alias_device_cb(struct device_user *dep, enum device_event ev)
} }
static struct device * static struct device *
alias_device_create(const char *name, struct blob_attr *attr) alias_device_create(const char *name, struct device_type *devtype,
struct blob_attr *attr)
{ {
struct alias_device *alias; struct alias_device *alias;
@@ -122,7 +123,7 @@ alias_device_create(const char *name, struct blob_attr *attr)
strcpy(alias->name, name); strcpy(alias->name, name);
alias->dev.set_state = alias_device_set_state; alias->dev.set_state = alias_device_set_state;
alias->dev.hidden = true; alias->dev.hidden = true;
device_init_virtual(&alias->dev, &alias_device_type, NULL); device_init_virtual(&alias->dev, devtype, NULL);
alias->avl.key = alias->name; alias->avl.key = alias->name;
avl_insert(&aliases, &alias->avl); avl_insert(&aliases, &alias->avl);
alias->dep.alias = true; alias->dep.alias = true;
@@ -160,7 +161,7 @@ static int alias_check_state(struct device *dev)
return 0; return 0;
} }
static const struct device_type alias_device_type = { static struct device_type alias_device_type = {
.name = "Network alias", .name = "Network alias",
.create = alias_device_create, .create = alias_device_create,
.free = alias_device_free, .free = alias_device_free,
@@ -190,7 +191,7 @@ device_alias_get(const char *name)
if (alias) if (alias)
return &alias->dev; return &alias->dev;
return alias_device_create(name, NULL); return alias_device_create(name, &alias_device_type, NULL);
} }
static void __init alias_init(void) static void __init alias_init(void)

View File

@@ -72,17 +72,21 @@ static const struct uci_blob_param_list bridge_attr_list = {
.next = { &device_attr_list }, .next = { &device_attr_list },
}; };
static struct device *bridge_create(const char *name, struct blob_attr *attr); static struct device *bridge_create(const char *name, struct device_type *devtype,
struct blob_attr *attr);
static void bridge_config_init(struct device *dev); static void bridge_config_init(struct device *dev);
static void bridge_free(struct device *dev); static void bridge_free(struct device *dev);
static void bridge_dump_info(struct device *dev, struct blob_buf *b); static void bridge_dump_info(struct device *dev, struct blob_buf *b);
enum dev_change_type enum dev_change_type
bridge_reload(struct device *dev, struct blob_attr *attr); bridge_reload(struct device *dev, struct blob_attr *attr);
const struct device_type bridge_device_type = { static struct device_type bridge_device_type = {
.name = "Bridge", .name = "bridge",
.config_params = &bridge_attr_list, .config_params = &bridge_attr_list,
.bridge_capability = true,
.name_prefix = "br",
.create = bridge_create, .create = bridge_create,
.config_init = bridge_config_init, .config_init = bridge_config_init,
.reload = bridge_reload, .reload = bridge_reload,
@@ -390,24 +394,25 @@ bridge_set_state(struct device *dev, bool up)
} }
static struct bridge_member * static struct bridge_member *
bridge_create_member(struct bridge_state *bst, struct device *dev, bool hotplug) bridge_create_member(struct bridge_state *bst, const char *name,
struct device *dev, bool hotplug)
{ {
struct bridge_member *bm; struct bridge_member *bm;
bm = calloc(1, sizeof(*bm) + strlen(dev->ifname) + 1); bm = calloc(1, sizeof(*bm) + strlen(name) + 1);
if (!bm) if (!bm)
return NULL; return NULL;
bm->bst = bst; bm->bst = bst;
bm->dev.cb = bridge_member_cb; bm->dev.cb = bridge_member_cb;
bm->dev.hotplug = hotplug; bm->dev.hotplug = hotplug;
strcpy(bm->name, dev->ifname); strcpy(bm->name, name);
bm->dev.dev = dev; bm->dev.dev = dev;
vlist_add(&bst->members, &bm->node, bm->name); vlist_add(&bst->members, &bm->node, bm->name);
// Need to look up the bridge member again as the above // Need to look up the bridge member again as the above
// created pointer will be freed in case the bridge member // created pointer will be freed in case the bridge member
// already existed // already existed
bm = vlist_find(&bst->members, dev->ifname, bm, node); bm = vlist_find(&bst->members, name, bm, node);
if (hotplug && bm) if (hotplug && bm)
bm->node.version = -1; bm->node.version = -1;
@@ -451,7 +456,7 @@ bridge_add_member(struct bridge_state *bst, const char *name)
if (!dev) if (!dev)
return; return;
bridge_create_member(bst, dev, false); bridge_create_member(bst, name, dev, false);
} }
static int static int
@@ -459,7 +464,7 @@ bridge_hotplug_add(struct device *dev, struct device *member)
{ {
struct bridge_state *bst = container_of(dev, struct bridge_state, dev); struct bridge_state *bst = container_of(dev, struct bridge_state, dev);
bridge_create_member(bst, member, true); bridge_create_member(bst, member->ifname, member, true);
return 0; return 0;
} }
@@ -519,8 +524,12 @@ bridge_dump_info(struct device *dev, struct blob_buf *b)
system_if_dump_info(dev, b); system_if_dump_info(dev, b);
list = blobmsg_open_array(b, "bridge-members"); list = blobmsg_open_array(b, "bridge-members");
vlist_for_each_element(&bst->members, bm, node) vlist_for_each_element(&bst->members, bm, node) {
if (bm->dev.dev->hidden)
continue;
blobmsg_add_string(b, NULL, bm->dev.dev->ifname); blobmsg_add_string(b, NULL, bm->dev.dev->ifname);
}
blobmsg_close_array(b, list); blobmsg_close_array(b, list);
} }
@@ -559,8 +568,6 @@ bridge_apply_settings(struct bridge_state *bst, struct blob_attr **tb)
/* defaults */ /* defaults */
cfg->stp = false; cfg->stp = false;
cfg->forward_delay = 2; cfg->forward_delay = 2;
cfg->igmp_snoop = true;
cfg->multicast_querier = true;
cfg->robustness = 2; cfg->robustness = 2;
cfg->query_interval = 12500; cfg->query_interval = 12500;
cfg->query_response_interval = 1000; cfg->query_response_interval = 1000;
@@ -646,6 +653,9 @@ bridge_reload(struct device *dev, struct blob_attr *attr)
blobmsg_parse(bridge_attrs, __BRIDGE_ATTR_MAX, tb_br, blobmsg_parse(bridge_attrs, __BRIDGE_ATTR_MAX, tb_br,
blob_data(attr), blob_len(attr)); blob_data(attr), blob_len(attr));
if (tb_dev[DEV_ATTR_MACADDR])
bst->primary_port = NULL;
bst->ifnames = tb_br[BRIDGE_ATTR_IFNAME]; bst->ifnames = tb_br[BRIDGE_ATTR_IFNAME];
device_init_settings(dev, tb_dev); device_init_settings(dev, tb_dev);
bridge_apply_settings(bst, tb_br); bridge_apply_settings(bst, tb_br);
@@ -699,7 +709,8 @@ bridge_retry_members(struct uloop_timeout *timeout)
} }
static struct device * static struct device *
bridge_create(const char *name, struct blob_attr *attr) bridge_create(const char *name, struct device_type *devtype,
struct blob_attr *attr)
{ {
struct bridge_state *bst; struct bridge_state *bst;
struct device *dev = NULL; struct device *dev = NULL;
@@ -709,7 +720,7 @@ bridge_create(const char *name, struct blob_attr *attr)
return NULL; return NULL;
dev = &bst->dev; dev = &bst->dev;
device_init(dev, &bridge_device_type, name); device_init(dev, devtype, name);
dev->config_pending = true; dev->config_pending = true;
bst->retry.cb = bridge_retry_members; bst->retry.cb = bridge_retry_members;
@@ -724,3 +735,8 @@ bridge_create(const char *name, struct blob_attr *attr)
return dev; return dev;
} }
static void __init bridge_device_type_init(void)
{
device_type_add(&bridge_device_type);
}

View File

@@ -16,7 +16,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <uci/uci.h> #include <uci.h>
#include "netifd.h" #include "netifd.h"
#include "interface.h" #include "interface.h"
@@ -53,18 +53,18 @@ config_section_idx(struct uci_section *s)
} }
static int static int
config_parse_bridge_interface(struct uci_section *s) config_parse_bridge_interface(struct uci_section *s, struct device_type *devtype)
{ {
char *name; char *name;
name = alloca(strlen(s->e.name) + 4); name = alloca(strlen(s->e.name) + strlen(devtype->name_prefix) + 2);
sprintf(name, "br-%s", s->e.name); sprintf(name, "%s-%s", devtype->name_prefix, s->e.name);
blobmsg_add_string(&b, "name", name); blobmsg_add_string(&b, "name", name);
uci_to_blob(&b, s, bridge_device_type.config_params); uci_to_blob(&b, s, devtype->config_params);
if (!device_create(name, &bridge_device_type, b.head)) { if (!device_create(name, devtype, b.head)) {
D(INTERFACE, "Failed to create bridge for interface '%s'\n", s->e.name); D(INTERFACE, "Failed to create '%s' device for interface '%s'\n",
return -EINVAL; devtype->name, s->e.name);
} }
blob_buf_init(&b, 0); blob_buf_init(&b, 0);
@@ -79,6 +79,7 @@ config_parse_interface(struct uci_section *s, bool alias)
const char *type = NULL, *disabled; const char *type = NULL, *disabled;
struct blob_attr *config; struct blob_attr *config;
bool bridge = false; bool bridge = false;
struct device_type *devtype = NULL;
disabled = uci_lookup_option_string(uci_ctx, s, "disabled"); disabled = uci_lookup_option_string(uci_ctx, s, "disabled");
if (disabled && !strcmp(disabled, "1")) if (disabled && !strcmp(disabled, "1"))
@@ -88,8 +89,12 @@ config_parse_interface(struct uci_section *s, bool alias)
if (!alias) if (!alias)
type = uci_lookup_option_string(uci_ctx, s, "type"); type = uci_lookup_option_string(uci_ctx, s, "type");
if (type && !strcmp(type, "bridge")) {
if (config_parse_bridge_interface(s)) if (type)
devtype = device_type_get(type);
if (devtype && devtype->bridge_capability) {
if (config_parse_bridge_interface(s, devtype))
return; return;
bridge = true; bridge = true;
@@ -157,7 +162,7 @@ config_init_devices(void)
uci_foreach_element(&uci_network->sections, e) { uci_foreach_element(&uci_network->sections, e) {
const struct uci_blob_param_list *params = NULL; const struct uci_blob_param_list *params = NULL;
struct uci_section *s = uci_to_section(e); struct uci_section *s = uci_to_section(e);
const struct device_type *devtype = NULL; struct device_type *devtype = NULL;
struct device *dev; struct device *dev;
const char *type, *name; const char *type, *name;
@@ -169,18 +174,8 @@ config_init_devices(void)
continue; continue;
type = uci_lookup_option_string(uci_ctx, s, "type"); type = uci_lookup_option_string(uci_ctx, s, "type");
if (type) { if (type)
if (!strcmp(type, "8021ad")) devtype = device_type_get(type);
devtype = &vlandev_device_type;
else if (!strcmp(type, "8021q"))
devtype = &vlandev_device_type;
else if (!strcmp(type, "bridge"))
devtype = &bridge_device_type;
else if (!strcmp(type, "macvlan"))
devtype = &macvlan_device_type;
else if (!strcmp(type, "tunnel"))
devtype = &tunnel_device_type;
}
if (devtype) if (devtype)
params = devtype->config_params; params = devtype->config_params;

View File

@@ -15,7 +15,7 @@
#define __NETIFD_CONFIG_H #define __NETIFD_CONFIG_H
#include <libubox/blobmsg.h> #include <libubox/blobmsg.h>
#include <uci/uci_blob.h> #include <uci_blob.h>
extern bool config_init; extern bool config_init;

View File

@@ -24,10 +24,13 @@
#include <netinet/ether.h> #include <netinet/ether.h>
#endif #endif
#include <libubox/list.h>
#include "netifd.h" #include "netifd.h"
#include "system.h" #include "system.h"
#include "config.h" #include "config.h"
static struct list_head devtypes = LIST_HEAD_INIT(devtypes);
static struct avl_tree devices; static struct avl_tree devices;
static bool default_ps = true; static bool default_ps = true;
@@ -51,9 +54,11 @@ static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = {
[DEV_ATTR_DADTRANSMITS] = { .name = "dadtransmits", .type = BLOBMSG_TYPE_INT32 }, [DEV_ATTR_DADTRANSMITS] = { .name = "dadtransmits", .type = BLOBMSG_TYPE_INT32 },
[DEV_ATTR_MULTICAST_TO_UNICAST] = { .name = "multicast_to_unicast", .type = BLOBMSG_TYPE_BOOL }, [DEV_ATTR_MULTICAST_TO_UNICAST] = { .name = "multicast_to_unicast", .type = BLOBMSG_TYPE_BOOL },
[DEV_ATTR_MULTICAST_ROUTER] = { .name = "multicast_router", .type = BLOBMSG_TYPE_INT32 }, [DEV_ATTR_MULTICAST_ROUTER] = { .name = "multicast_router", .type = BLOBMSG_TYPE_INT32 },
[DEV_ATTR_MULTICAST_FAST_LEAVE] = { .name = "multicast_fast_leave", . type = BLOBMSG_TYPE_BOOL },
[DEV_ATTR_MULTICAST] = { .name ="multicast", .type = BLOBMSG_TYPE_BOOL }, [DEV_ATTR_MULTICAST] = { .name ="multicast", .type = BLOBMSG_TYPE_BOOL },
[DEV_ATTR_LEARNING] = { .name ="learning", .type = BLOBMSG_TYPE_BOOL }, [DEV_ATTR_LEARNING] = { .name ="learning", .type = BLOBMSG_TYPE_BOOL },
[DEV_ATTR_UNICAST_FLOOD] = { .name ="unicast_flood", .type = BLOBMSG_TYPE_BOOL }, [DEV_ATTR_UNICAST_FLOOD] = { .name ="unicast_flood", .type = BLOBMSG_TYPE_BOOL },
[DEV_ATTR_SENDREDIRECTS] = { .name = "sendredirects", .type = BLOBMSG_TYPE_BOOL },
}; };
const struct uci_blob_param_list device_attr_list = { const struct uci_blob_param_list device_attr_list = {
@@ -63,6 +68,36 @@ const struct uci_blob_param_list device_attr_list = {
static int __devlock = 0; static int __devlock = 0;
int device_type_add(struct device_type *devtype)
{
if (device_type_get(devtype->name)) {
netifd_log_message(L_WARNING, "Device handler '%s' already exists\n",
devtype->name);
return 1;
}
netifd_log_message(L_NOTICE, "Added device handler type: %s\n",
devtype->name);
list_add(&devtype->list, &devtypes);
return 0;
}
/* Retrieve the device type for the given name. If 'bridge' is true, the type
* must have bridge capabilities
*/
struct device_type *
device_type_get(const char *tname)
{
struct device_type *cur;
list_for_each_entry(cur, &devtypes, list)
if (!strcmp(cur->name, tname))
return cur;
return NULL;
}
void device_lock(void) void device_lock(void)
{ {
__devlock++; __devlock++;
@@ -118,11 +153,15 @@ simple_device_set_state(struct device *dev, bool state)
} }
static struct device * static struct device *
simple_device_create(const char *name, struct blob_attr *attr) simple_device_create(const char *name, struct device_type *devtype,
struct blob_attr *attr)
{ {
struct blob_attr *tb[__DEV_ATTR_MAX]; struct blob_attr *tb[__DEV_ATTR_MAX];
struct device *dev = NULL; struct device *dev = NULL;
/* device type is unused for simple devices */
devtype = NULL;
blobmsg_parse(dev_attrs, __DEV_ATTR_MAX, tb, blob_data(attr), blob_len(attr)); blobmsg_parse(dev_attrs, __DEV_ATTR_MAX, tb, blob_data(attr), blob_len(attr));
dev = device_get(name, true); dev = device_get(name, true);
if (!dev) if (!dev)
@@ -141,7 +180,7 @@ static void simple_device_free(struct device *dev)
free(dev); free(dev);
} }
const struct device_type simple_device_type = { struct device_type simple_device_type = {
.name = "Network device", .name = "Network device",
.config_params = &device_attr_list, .config_params = &device_attr_list,
@@ -184,8 +223,11 @@ device_merge_settings(struct device *dev, struct device_settings *n)
s->multicast : os->multicast; s->multicast : os->multicast;
n->multicast_to_unicast = s->multicast_to_unicast; n->multicast_to_unicast = s->multicast_to_unicast;
n->multicast_router = s->multicast_router; n->multicast_router = s->multicast_router;
n->multicast_fast_leave = s->multicast_fast_leave;
n->learning = s->learning; n->learning = s->learning;
n->unicast_flood = s->unicast_flood; n->unicast_flood = s->unicast_flood;
n->sendredirects = s->flags & DEV_OPT_SENDREDIRECTS ?
s->sendredirects : os->sendredirects;
n->flags = s->flags | os->flags | os->valid_flags; n->flags = s->flags | os->flags | os->valid_flags;
} }
@@ -201,12 +243,12 @@ device_init_settings(struct device *dev, struct blob_attr **tb)
if ((cur = tb[DEV_ATTR_ENABLED])) if ((cur = tb[DEV_ATTR_ENABLED]))
disabled = !blobmsg_get_bool(cur); disabled = !blobmsg_get_bool(cur);
if ((cur = tb[DEV_ATTR_MTU])) { if ((cur = tb[DEV_ATTR_MTU]) && blobmsg_get_u32(cur) >= 68) {
s->mtu = blobmsg_get_u32(cur); s->mtu = blobmsg_get_u32(cur);
s->flags |= DEV_OPT_MTU; s->flags |= DEV_OPT_MTU;
} }
if ((cur = tb[DEV_ATTR_MTU6])) { if ((cur = tb[DEV_ATTR_MTU6]) && blobmsg_get_u32(cur) >= 1280) {
s->mtu6 = blobmsg_get_u32(cur); s->mtu6 = blobmsg_get_u32(cur);
s->flags |= DEV_OPT_MTU6; s->flags |= DEV_OPT_MTU6;
} }
@@ -304,6 +346,11 @@ device_init_settings(struct device *dev, struct blob_attr **tb)
DPRINTF("Invalid value: %d - (Use 0: never, 1: learn, 2: always)\n", blobmsg_get_u32(cur)); DPRINTF("Invalid value: %d - (Use 0: never, 1: learn, 2: always)\n", blobmsg_get_u32(cur));
} }
if ((cur = tb[DEV_ATTR_MULTICAST_FAST_LEAVE])) {
s->multicast_fast_leave = blobmsg_get_bool(cur);
s->flags |= DEV_OPT_MULTICAST_FAST_LEAVE;
}
if ((cur = tb[DEV_ATTR_MULTICAST])) { if ((cur = tb[DEV_ATTR_MULTICAST])) {
s->multicast = blobmsg_get_bool(cur); s->multicast = blobmsg_get_bool(cur);
s->flags |= DEV_OPT_MULTICAST; s->flags |= DEV_OPT_MULTICAST;
@@ -319,6 +366,11 @@ device_init_settings(struct device *dev, struct blob_attr **tb)
s->flags |= DEV_OPT_UNICAST_FLOOD; s->flags |= DEV_OPT_UNICAST_FLOOD;
} }
if ((cur = tb[DEV_ATTR_SENDREDIRECTS])) {
s->sendredirects = blobmsg_get_bool(cur);
s->flags |= DEV_OPT_SENDREDIRECTS;
}
device_set_disabled(dev, disabled); device_set_disabled(dev, disabled);
} }
@@ -406,6 +458,10 @@ void device_release(struct device_user *dep)
device_broadcast_event(dev, DEV_EVENT_TEARDOWN); device_broadcast_event(dev, DEV_EVENT_TEARDOWN);
if (!dev->external) if (!dev->external)
dev->set_state(dev, false); dev->set_state(dev, false);
if (dev->active)
return;
device_broadcast_event(dev, DEV_EVENT_DOWN); device_broadcast_event(dev, DEV_EVENT_DOWN);
} }
@@ -417,7 +473,7 @@ int device_check_state(struct device *dev)
return dev->type->check_state(dev); return dev->type->check_state(dev);
} }
void device_init_virtual(struct device *dev, const struct device_type *type, const char *name) void device_init_virtual(struct device *dev, struct device_type *type, const char *name)
{ {
assert(dev); assert(dev);
assert(type); assert(type);
@@ -434,7 +490,7 @@ void device_init_virtual(struct device *dev, const struct device_type *type, con
dev->set_state = set_device_state; dev->set_state = set_device_state;
} }
int device_init(struct device *dev, const struct device_type *type, const char *ifname) int device_init(struct device *dev, struct device_type *type, const char *ifname)
{ {
int ret; int ret;
@@ -729,7 +785,7 @@ device_init_pending(void)
} }
static enum dev_change_type static enum dev_change_type
device_set_config(struct device *dev, const struct device_type *type, device_set_config(struct device *dev, struct device_type *type,
struct blob_attr *attr) struct blob_attr *attr)
{ {
struct blob_attr *tb[__DEV_ATTR_MAX]; struct blob_attr *tb[__DEV_ATTR_MAX];
@@ -758,7 +814,7 @@ device_set_config(struct device *dev, const struct device_type *type,
} }
enum dev_change_type enum dev_change_type
device_apply_config(struct device *dev, const struct device_type *type, device_apply_config(struct device *dev, struct device_type *type,
struct blob_attr *config) struct blob_attr *config)
{ {
enum dev_change_type change; enum dev_change_type change;
@@ -883,13 +939,13 @@ device_set_default_ps(bool state)
} }
struct device * struct device *
device_create(const char *name, const struct device_type *type, device_create(const char *name, struct device_type *type,
struct blob_attr *config) struct blob_attr *config)
{ {
struct device *odev = NULL, *dev; struct device *odev = NULL, *dev;
enum dev_change_type change; enum dev_change_type change;
odev = device_get(name, false); odev = device_find(name);
if (odev) { if (odev) {
odev->current_config = true; odev->current_config = true;
change = device_apply_config(odev, type, config); change = device_apply_config(odev, type, config);
@@ -908,7 +964,7 @@ device_create(const char *name, const struct device_type *type,
if (!config) if (!config)
return NULL; return NULL;
dev = type->create(name, config); dev = type->create(name, type, config);
if (!dev) if (!dev)
return NULL; return NULL;
@@ -994,12 +1050,16 @@ device_dump_status(struct blob_buf *b, struct device *dev)
blobmsg_add_u8(b, "multicast_to_unicast", st.multicast_to_unicast); blobmsg_add_u8(b, "multicast_to_unicast", st.multicast_to_unicast);
if (st.flags & DEV_OPT_MULTICAST_ROUTER) if (st.flags & DEV_OPT_MULTICAST_ROUTER)
blobmsg_add_u32(b, "multicast_router", st.multicast_router); blobmsg_add_u32(b, "multicast_router", st.multicast_router);
if (st.flags & DEV_OPT_MULTICAST_FAST_LEAVE)
blobmsg_add_u8(b, "multicast_fast_leave", st.multicast_fast_leave);
if (st.flags & DEV_OPT_MULTICAST) if (st.flags & DEV_OPT_MULTICAST)
blobmsg_add_u8(b, "multicast", st.multicast); blobmsg_add_u8(b, "multicast", st.multicast);
if (st.flags & DEV_OPT_LEARNING) if (st.flags & DEV_OPT_LEARNING)
blobmsg_add_u8(b, "learning", st.learning); blobmsg_add_u8(b, "learning", st.learning);
if (st.flags & DEV_OPT_UNICAST_FLOOD) if (st.flags & DEV_OPT_UNICAST_FLOOD)
blobmsg_add_u8(b, "unicast_flood", st.unicast_flood); blobmsg_add_u8(b, "unicast_flood", st.unicast_flood);
if (st.flags & DEV_OPT_SENDREDIRECTS)
blobmsg_add_u8(b, "sendredirects", st.sendredirects);
} }
s = blobmsg_open_table(b, "statistics"); s = blobmsg_open_table(b, "statistics");
@@ -1009,3 +1069,8 @@ device_dump_status(struct blob_buf *b, struct device *dev)
system_if_dump_stats(dev, b); system_if_dump_stats(dev, b);
blobmsg_close_table(b, s); blobmsg_close_table(b, s);
} }
static void __init simple_device_type_init(void)
{
device_type_add(&simple_device_type);
}

View File

@@ -19,6 +19,7 @@
#include <netinet/in.h> #include <netinet/in.h>
struct device; struct device;
struct device_type;
struct device_user; struct device_user;
struct device_hotplug_ops; struct device_hotplug_ops;
struct interface; struct interface;
@@ -44,10 +45,12 @@ enum {
DEV_ATTR_DADTRANSMITS, DEV_ATTR_DADTRANSMITS,
DEV_ATTR_MULTICAST_TO_UNICAST, DEV_ATTR_MULTICAST_TO_UNICAST,
DEV_ATTR_MULTICAST_ROUTER, DEV_ATTR_MULTICAST_ROUTER,
DEV_ATTR_MULTICAST_FAST_LEAVE,
DEV_ATTR_MULTICAST, DEV_ATTR_MULTICAST,
DEV_ATTR_LEARNING, DEV_ATTR_LEARNING,
DEV_ATTR_UNICAST_FLOOD, DEV_ATTR_UNICAST_FLOOD,
DEV_ATTR_NEIGHGCSTALETIME, DEV_ATTR_NEIGHGCSTALETIME,
DEV_ATTR_SENDREDIRECTS,
__DEV_ATTR_MAX, __DEV_ATTR_MAX,
}; };
@@ -62,9 +65,13 @@ struct device_type {
struct list_head list; struct list_head list;
const char *name; const char *name;
bool bridge_capability;
const char *name_prefix;
const struct uci_blob_param_list *config_params; const struct uci_blob_param_list *config_params;
struct device *(*create)(const char *name, struct blob_attr *attr); struct device *(*create)(const char *name, struct device_type *devtype,
struct blob_attr *attr);
void (*config_init)(struct device *); void (*config_init)(struct device *);
enum dev_change_type (*reload)(struct device *, struct blob_attr *); enum dev_change_type (*reload)(struct device *, struct blob_attr *);
void (*dump_info)(struct device *, struct blob_buf *buf); void (*dump_info)(struct device *, struct blob_buf *buf);
@@ -94,6 +101,8 @@ enum {
DEV_OPT_LEARNING = (1 << 17), DEV_OPT_LEARNING = (1 << 17),
DEV_OPT_UNICAST_FLOOD = (1 << 18), DEV_OPT_UNICAST_FLOOD = (1 << 18),
DEV_OPT_NEIGHGCSTALETIME = (1 << 19), DEV_OPT_NEIGHGCSTALETIME = (1 << 19),
DEV_OPT_MULTICAST_FAST_LEAVE = (1 << 20),
DEV_OPT_SENDREDIRECTS = (1 << 21),
}; };
/* events broadcasted to all users of a device */ /* events broadcasted to all users of a device */
@@ -156,9 +165,11 @@ struct device_settings {
unsigned int dadtransmits; unsigned int dadtransmits;
bool multicast_to_unicast; bool multicast_to_unicast;
unsigned int multicast_router; unsigned int multicast_router;
bool multicast_fast_leave;
bool multicast; bool multicast;
bool learning; bool learning;
bool unicast_flood; bool unicast_flood;
bool sendredirects;
}; };
/* /*
@@ -166,7 +177,7 @@ struct device_settings {
* can be used to support VLANs as well * can be used to support VLANs as well
*/ */
struct device { struct device {
const struct device_type *type; struct device_type *type;
struct avl_node avl; struct avl_node avl;
struct safe_list users; struct safe_list users;
@@ -217,30 +228,29 @@ struct device_hotplug_ops {
}; };
extern const struct uci_blob_param_list device_attr_list; extern const struct uci_blob_param_list device_attr_list;
extern const struct device_type simple_device_type; extern struct device_type simple_device_type;
extern const struct device_type bridge_device_type; extern struct device_type tunnel_device_type;
extern const struct device_type tunnel_device_type;
extern const struct device_type macvlan_device_type;
extern const struct device_type vlandev_device_type;
void device_lock(void); void device_lock(void);
void device_unlock(void); void device_unlock(void);
struct device *device_create(const char *name, const struct device_type *type, int device_type_add(struct device_type *devtype);
struct device_type *device_type_get(const char *tname);
struct device *device_create(const char *name, struct device_type *type,
struct blob_attr *config); struct blob_attr *config);
void device_init_settings(struct device *dev, struct blob_attr **tb); void device_init_settings(struct device *dev, struct blob_attr **tb);
void device_init_pending(void); void device_init_pending(void);
enum dev_change_type enum dev_change_type
device_apply_config(struct device *dev, const struct device_type *type, device_apply_config(struct device *dev, struct device_type *type,
struct blob_attr *config); struct blob_attr *config);
void device_reset_config(void); void device_reset_config(void);
void device_reset_old(void); void device_reset_old(void);
void device_set_default_ps(bool state); void device_set_default_ps(bool state);
void device_init_virtual(struct device *dev, const struct device_type *type, const char *name); void device_init_virtual(struct device *dev, struct device_type *type, const char *name);
int device_init(struct device *iface, const struct device_type *type, const char *ifname); int device_init(struct device *iface, struct device_type *type, const char *ifname);
void device_cleanup(struct device *dev); void device_cleanup(struct device *dev);
struct device *device_find(const char *name); struct device *device_find(const char *name);
struct device *device_get(const char *name, int create); struct device *device_get(const char *name, int create);

View File

@@ -30,7 +30,14 @@ static void task_complete(struct uloop_process *proc, int ret);
static struct uloop_process task = { static struct uloop_process task = {
.cb = task_complete, .cb = task_complete,
}; };
static const char * const eventnames[] = {"ifdown", "ifup", "ifupdate", "free", "reload"}; static const char * const eventnames[] = {
[IFEV_DOWN] = "ifdown",
[IFEV_UP] = "ifup",
[IFEV_UPDATE] = "ifupdate",
[IFEV_FREE] = "free",
[IFEV_RELOAD] = "reload",
[IFEV_LINK_UP] = "iflink",
};
static void static void
run_cmd(const char *ifname, const char *device, enum interface_event event, run_cmd(const char *ifname, const char *device, enum interface_event event,
@@ -117,6 +124,10 @@ interface_queue_event(struct interface *iface, enum interface_event ev)
netifd_ubus_interface_notify(iface, ev != IFEV_DOWN); netifd_ubus_interface_notify(iface, ev != IFEV_DOWN);
/* no hotplug.d calls for link up */
if (ev == IFEV_LINK_UP)
return;
if (current == iface) { if (current == iface) {
/* an event for iface is being processed */ /* an event for iface is being processed */
if (!list_empty(&iface->hotplug_list)) { if (!list_empty(&iface->hotplug_list)) {
@@ -178,15 +189,17 @@ static void interface_event_cb(struct interface_user *dep, struct interface *ifa
enum interface_event ev) enum interface_event ev)
{ {
switch (ev) { switch (ev) {
case IFEV_LINK_UP:
case IFEV_UP: case IFEV_UP:
case IFEV_UPDATE: case IFEV_UPDATE:
case IFEV_DOWN: case IFEV_DOWN:
interface_queue_event(iface, ev); interface_queue_event(iface, ev);
break; break;
case IFEV_FREE: case IFEV_FREE:
case IFEV_RELOAD:
interface_dequeue_event(iface); interface_dequeue_event(iface);
break; break;
default:
break;
} }
} }

View File

@@ -40,6 +40,7 @@ enum {
ROUTE_SOURCE, ROUTE_SOURCE,
ROUTE_ONLINK, ROUTE_ONLINK,
ROUTE_TYPE, ROUTE_TYPE,
ROUTE_PROTO,
__ROUTE_MAX __ROUTE_MAX
}; };
@@ -54,7 +55,8 @@ static const struct blobmsg_policy route_attr[__ROUTE_MAX] = {
[ROUTE_VALID] = { .name = "valid", .type = BLOBMSG_TYPE_INT32 }, [ROUTE_VALID] = { .name = "valid", .type = BLOBMSG_TYPE_INT32 },
[ROUTE_SOURCE] = { .name = "source", .type = BLOBMSG_TYPE_STRING }, [ROUTE_SOURCE] = { .name = "source", .type = BLOBMSG_TYPE_STRING },
[ROUTE_ONLINK] = { .name = "onlink", .type = BLOBMSG_TYPE_BOOL }, [ROUTE_ONLINK] = { .name = "onlink", .type = BLOBMSG_TYPE_BOOL },
[ROUTE_TYPE] = { .name = "type", .type = BLOBMSG_TYPE_STRING } [ROUTE_TYPE] = { .name = "type", .type = BLOBMSG_TYPE_STRING },
[ROUTE_PROTO] = { .name = "proto", .type = BLOBMSG_TYPE_STRING },
}; };
const struct uci_blob_param_list route_attr_list = { const struct uci_blob_param_list route_attr_list = {
@@ -405,6 +407,14 @@ interface_ip_add_route(struct interface *iface, struct blob_attr *attr, bool v6)
route->flags |= DEVROUTE_TYPE; route->flags |= DEVROUTE_TYPE;
} }
if ((cur = tb[ROUTE_PROTO]) != NULL) {
if (!system_resolve_rt_proto(blobmsg_data(cur), &route->proto)) {
DPRINTF("Failed to resolve proto type: %s\n", (char *) blobmsg_data(cur));
goto error;
}
route->flags |= DEVROUTE_PROTO;
}
interface_set_route_info(iface, route); interface_set_route_info(iface, route);
vlist_add(&ip->route, &route->node, route); vlist_add(&ip->route, &route->node, route);
return; return;
@@ -478,10 +488,13 @@ interface_handle_subnet_route(struct interface *iface, struct device_addr *addr,
memcpy(&r->addr, &addr->addr, sizeof(r->addr)); memcpy(&r->addr, &addr->addr, sizeof(r->addr));
clear_if_addr(&r->addr, r->mask); clear_if_addr(&r->addr, r->mask);
r->flags |= DEVADDR_KERNEL; if (!system_resolve_rt_proto("kernel", &r->proto))
return;
r->flags |= DEVROUTE_PROTO;
system_del_route(dev, r); system_del_route(dev, r);
r->flags &= ~DEVADDR_KERNEL; r->flags &= ~DEVROUTE_PROTO;
interface_set_route_info(iface, r); interface_set_route_info(iface, r);
system_add_route(dev, r); system_add_route(dev, r);
@@ -634,7 +647,7 @@ interface_update_proto_route(struct vlist_tree *tree,
if (node_old && node_new) if (node_old && node_new)
keep = !memcmp(&route_old->nexthop, &route_new->nexthop, sizeof(route_old->nexthop)) && keep = !memcmp(&route_old->nexthop, &route_new->nexthop, sizeof(route_old->nexthop)) &&
(route_old->mtu == route_new->mtu) && (route_old->type == route_new->type) && (route_old->mtu == route_new->mtu) && (route_old->type == route_new->type) &&
!route_old->failed; (route_old->proto == route_new->proto) && !route_old->failed;
if (node_old) { if (node_old) {
if (!(route_old->flags & DEVADDR_EXTERNAL) && route_old->enabled && !keep) if (!(route_old->flags & DEVADDR_EXTERNAL) && route_old->enabled && !keep)
@@ -1197,10 +1210,70 @@ write_resolv_conf_entries(FILE *f, struct interface_ip_settings *ip, const char
} }
} }
/* Sorting of interface resolver entries : */
/* Primary on interface dns_metric : lowest metric first */
/* Secondary on interface metric : lowest metric first */
/* Finally alphabetical order of interface names */
static int resolv_conf_iface_cmp(const void *k1, const void *k2, void *ptr)
{
const struct interface *iface1 = k1, *iface2 = k2;
if (iface1->dns_metric != iface2->dns_metric)
return iface1->dns_metric - iface2->dns_metric;
if (iface1->metric != iface2->metric)
return iface1->metric - iface2->metric;
return strcmp(iface1->name, iface2->name);
}
static void
__interface_write_dns_entries(FILE *f)
{
struct interface *iface;
struct {
struct avl_node node;
} *entry, *n_entry;
struct avl_tree resolv_conf_iface_entries;
avl_init(&resolv_conf_iface_entries, resolv_conf_iface_cmp, false, NULL);
vlist_for_each_element(&interfaces, iface, node) {
if (iface->state != IFS_UP)
continue;
if (vlist_simple_empty(&iface->proto_ip.dns_search) &&
vlist_simple_empty(&iface->proto_ip.dns_servers) &&
vlist_simple_empty(&iface->config_ip.dns_search) &&
vlist_simple_empty(&iface->config_ip.dns_servers))
continue;
entry = calloc(1, sizeof(*entry));
if (!entry)
continue;
entry->node.key = iface;
avl_insert(&resolv_conf_iface_entries, &entry->node);
}
avl_for_each_element(&resolv_conf_iface_entries, entry, node) {
iface = (struct interface *)entry->node.key;
fprintf(f, "# Interface %s\n", iface->name);
write_resolv_conf_entries(f, &iface->config_ip, iface->ifname);
if (!iface->proto_ip.no_dns)
write_resolv_conf_entries(f, &iface->proto_ip, iface->ifname);
}
avl_remove_all_elements(&resolv_conf_iface_entries, entry, node, n_entry)
free(entry);
}
void void
interface_write_resolv_conf(void) interface_write_resolv_conf(void)
{ {
struct interface *iface;
char *path = alloca(strlen(resolv_conf) + 5); char *path = alloca(strlen(resolv_conf) + 5);
FILE *f; FILE *f;
uint32_t crcold, crcnew; uint32_t crcold, crcnew;
@@ -1213,21 +1286,8 @@ interface_write_resolv_conf(void)
return; return;
} }
vlist_for_each_element(&interfaces, iface, node) { __interface_write_dns_entries(f);
if (iface->state != IFS_UP)
continue;
if (vlist_simple_empty(&iface->proto_ip.dns_search) &&
vlist_simple_empty(&iface->proto_ip.dns_servers) &&
vlist_simple_empty(&iface->config_ip.dns_search) &&
vlist_simple_empty(&iface->config_ip.dns_servers))
continue;
fprintf(f, "# Interface %s\n", iface->name);
write_resolv_conf_entries(f, &iface->config_ip, iface->ifname);
if (!iface->proto_ip.no_dns)
write_resolv_conf_entries(f, &iface->proto_ip, iface->ifname);
}
fflush(f); fflush(f);
rewind(f); rewind(f);
crcnew = crc32_file(f); crcnew = crc32_file(f);

View File

@@ -31,8 +31,8 @@ enum device_addr_flags {
/* route overrides the default interface mtu */ /* route overrides the default interface mtu */
DEVROUTE_MTU = (1 << 4), DEVROUTE_MTU = (1 << 4),
/* route automatically added by kernel */ /* route overrides the default proto type */
DEVADDR_KERNEL = (1 << 5), DEVROUTE_PROTO = (1 << 5),
/* address is off-link (no subnet-route) */ /* address is off-link (no subnet-route) */
DEVADDR_OFFLINK = (1 << 6), DEVADDR_OFFLINK = (1 << 6),
@@ -92,6 +92,7 @@ struct device_route {
union if_addr nexthop; union if_addr nexthop;
int mtu; int mtu;
unsigned int type; unsigned int type;
unsigned int proto;
time_t valid_until; time_t valid_until;
/* must be last */ /* must be last */

View File

@@ -35,6 +35,7 @@ enum {
IFACE_ATTR_PEERDNS, IFACE_ATTR_PEERDNS,
IFACE_ATTR_DNS, IFACE_ATTR_DNS,
IFACE_ATTR_DNS_SEARCH, IFACE_ATTR_DNS_SEARCH,
IFACE_ATTR_DNS_METRIC,
IFACE_ATTR_METRIC, IFACE_ATTR_METRIC,
IFACE_ATTR_INTERFACE, IFACE_ATTR_INTERFACE,
IFACE_ATTR_IP6ASSIGN, IFACE_ATTR_IP6ASSIGN,
@@ -57,6 +58,7 @@ static const struct blobmsg_policy iface_attrs[IFACE_ATTR_MAX] = {
[IFACE_ATTR_METRIC] = { .name = "metric", .type = BLOBMSG_TYPE_INT32 }, [IFACE_ATTR_METRIC] = { .name = "metric", .type = BLOBMSG_TYPE_INT32 },
[IFACE_ATTR_DNS] = { .name = "dns", .type = BLOBMSG_TYPE_ARRAY }, [IFACE_ATTR_DNS] = { .name = "dns", .type = BLOBMSG_TYPE_ARRAY },
[IFACE_ATTR_DNS_SEARCH] = { .name = "dns_search", .type = BLOBMSG_TYPE_ARRAY }, [IFACE_ATTR_DNS_SEARCH] = { .name = "dns_search", .type = BLOBMSG_TYPE_ARRAY },
[IFACE_ATTR_DNS_METRIC] = { .name = "dns_metric", .type = BLOBMSG_TYPE_INT32 },
[IFACE_ATTR_INTERFACE] = { .name = "interface", .type = BLOBMSG_TYPE_STRING }, [IFACE_ATTR_INTERFACE] = { .name = "interface", .type = BLOBMSG_TYPE_STRING },
[IFACE_ATTR_IP6ASSIGN] = { .name = "ip6assign", .type = BLOBMSG_TYPE_INT32 }, [IFACE_ATTR_IP6ASSIGN] = { .name = "ip6assign", .type = BLOBMSG_TYPE_INT32 },
[IFACE_ATTR_IP6HINT] = { .name = "ip6hint", .type = BLOBMSG_TYPE_STRING }, [IFACE_ATTR_IP6HINT] = { .name = "ip6hint", .type = BLOBMSG_TYPE_STRING },
@@ -260,6 +262,7 @@ mark_interface_down(struct interface *iface)
if (state == IFS_DOWN) if (state == IFS_DOWN)
return; return;
iface->link_up_event = false;
iface->state = IFS_DOWN; iface->state = IFS_DOWN;
if (state == IFS_UP) if (state == IFS_UP)
interface_event(iface, IFEV_DOWN); interface_event(iface, IFEV_DOWN);
@@ -355,6 +358,11 @@ interface_set_link_state(struct interface *iface, bool new_state)
netifd_log_message(L_NOTICE, "Interface '%s' has link connectivity %s\n", iface->name, new_state ? "" : "loss"); netifd_log_message(L_NOTICE, "Interface '%s' has link connectivity %s\n", iface->name, new_state ? "" : "loss");
iface->link_state = new_state; iface->link_state = new_state;
interface_check_state(iface); interface_check_state(iface);
if (new_state && iface->force_link && iface->state == IFS_UP && !iface->link_up_event) {
interface_event(iface, IFEV_LINK_UP);
iface->link_up_event = true;
}
} }
static void static void
@@ -408,7 +416,8 @@ interface_l3_dev_cb(struct device_user *dep, enum device_event ev)
switch (ev) { switch (ev) {
case DEV_EVENT_LINK_DOWN: case DEV_EVENT_LINK_DOWN:
interface_proto_event(iface->proto, PROTO_CMD_TEARDOWN, false); if (iface->proto_handler->flags & PROTO_FLAG_TEARDOWN_ON_L3_LINK_DOWN)
interface_proto_event(iface->proto, PROTO_CMD_TEARDOWN, false);
break; break;
default: default:
break; break;
@@ -550,8 +559,7 @@ interface_alias_cb(struct interface_user *dep, struct interface *iface, enum int
case IFEV_FREE: case IFEV_FREE:
interface_remove_user(dep); interface_remove_user(dep);
break; break;
case IFEV_RELOAD: default:
case IFEV_UPDATE:
break; break;
} }
} }
@@ -580,6 +588,8 @@ interface_claim_device(struct interface *iface)
if (iface->parent_iface.iface) if (iface->parent_iface.iface)
interface_remove_user(&iface->parent_iface); interface_remove_user(&iface->parent_iface);
device_lock();
if (iface->parent_ifname) { if (iface->parent_ifname) {
parent = vlist_find(&interfaces, iface->parent_ifname, parent, node); parent = vlist_find(&interfaces, iface->parent_ifname, parent, node);
iface->parent_iface.cb = interface_alias_cb; iface->parent_iface.cb = interface_alias_cb;
@@ -595,6 +605,8 @@ interface_claim_device(struct interface *iface)
if (dev) if (dev)
interface_set_main_dev(iface, dev); interface_set_main_dev(iface, dev);
device_unlock();
if (iface->proto_handler->flags & PROTO_FLAG_INIT_AVAILABLE) if (iface->proto_handler->flags & PROTO_FLAG_INIT_AVAILABLE)
interface_set_available(iface, true); interface_set_available(iface, true);
} }
@@ -681,7 +693,8 @@ interface_proto_event_cb(struct interface_proto_state *state, enum interface_pro
switch (ev) { switch (ev) {
case IFPEV_UP: case IFPEV_UP:
if (iface->state != IFS_SETUP) { if (iface->state != IFS_SETUP) {
interface_event(iface, IFEV_UPDATE); if (iface->state == IFS_UP && iface->updated)
interface_event(iface, IFEV_UPDATE);
return; return;
} }
@@ -785,6 +798,9 @@ interface_alloc(const char *name, struct blob_attr *config)
if ((cur = tb[IFACE_ATTR_DNS_SEARCH])) if ((cur = tb[IFACE_ATTR_DNS_SEARCH]))
interface_add_dns_search_list(&iface->config_ip, cur); interface_add_dns_search_list(&iface->config_ip, cur);
if ((cur = tb[IFACE_ATTR_DNS_METRIC]))
iface->dns_metric = blobmsg_get_u32(cur);
if ((cur = tb[IFACE_ATTR_METRIC])) if ((cur = tb[IFACE_ATTR_METRIC]))
iface->metric = blobmsg_get_u32(cur); iface->metric = blobmsg_get_u32(cur);
@@ -1076,10 +1092,12 @@ set_config_state(struct interface *iface, enum interface_config_state s)
} }
void void
interface_update_start(struct interface *iface) interface_update_start(struct interface *iface, const bool keep_old)
{ {
iface->updated = 0; iface->updated = 0;
interface_ip_update_start(&iface->proto_ip);
if (!keep_old)
interface_ip_update_start(&iface->proto_ip);
} }
void void
@@ -1175,6 +1193,7 @@ interface_change_config(struct interface *if_old, struct interface *if_new)
if_old->parent_ifname = if_new->parent_ifname; if_old->parent_ifname = if_new->parent_ifname;
if_old->proto_handler = if_new->proto_handler; if_old->proto_handler = if_new->proto_handler;
if_old->force_link = if_new->force_link; if_old->force_link = if_new->force_link;
if_old->dns_metric = if_new->dns_metric;
if_old->proto_ip.no_dns = if_new->proto_ip.no_dns; if_old->proto_ip.no_dns = if_new->proto_ip.no_dns;
interface_replace_dns(&if_old->config_ip, &if_new->config_ip); interface_replace_dns(&if_old->config_ip, &if_new->config_ip);

View File

@@ -26,6 +26,7 @@ enum interface_event {
IFEV_UPDATE, IFEV_UPDATE,
IFEV_FREE, IFEV_FREE,
IFEV_RELOAD, IFEV_RELOAD,
IFEV_LINK_UP,
}; };
enum interface_state { enum interface_state {
@@ -113,6 +114,7 @@ struct interface {
bool force_link; bool force_link;
bool dynamic; bool dynamic;
bool policy_rules_set; bool policy_rules_set;
bool link_up_event;
time_t start_time; time_t start_time;
enum interface_state state; enum interface_state state;
@@ -143,6 +145,7 @@ struct interface {
struct vlist_tree host_routes; struct vlist_tree host_routes;
int metric; int metric;
int dns_metric;
unsigned int ip4table; unsigned int ip4table;
unsigned int ip6table; unsigned int ip6table;
@@ -196,7 +199,7 @@ void interface_add_error(struct interface *iface, const char *subsystem,
int interface_add_data(struct interface *iface, const struct blob_attr *data); int interface_add_data(struct interface *iface, const struct blob_attr *data);
int interface_parse_data(struct interface *iface, const struct blob_attr *attr); int interface_parse_data(struct interface *iface, const struct blob_attr *attr);
void interface_update_start(struct interface *iface); void interface_update_start(struct interface *iface, const bool keep_old);
void interface_update_complete(struct interface *iface); void interface_update_complete(struct interface *iface);
void interface_start_pending(void); void interface_start_pending(void);

View File

@@ -228,7 +228,8 @@ macvlan_reload(struct device *dev, struct blob_attr *attr)
} }
static struct device * static struct device *
macvlan_create(const char *name, struct blob_attr *attr) macvlan_create(const char *name, struct device_type *devtype,
struct blob_attr *attr)
{ {
struct macvlan_device *mvdev; struct macvlan_device *mvdev;
struct device *dev = NULL; struct device *dev = NULL;
@@ -238,7 +239,7 @@ macvlan_create(const char *name, struct blob_attr *attr)
return NULL; return NULL;
dev = &mvdev->dev; dev = &mvdev->dev;
device_init(dev, &macvlan_device_type, name); device_init(dev, devtype, name);
dev->config_pending = true; dev->config_pending = true;
mvdev->set_state = dev->set_state; mvdev->set_state = dev->set_state;
@@ -252,8 +253,8 @@ macvlan_create(const char *name, struct blob_attr *attr)
return dev; return dev;
} }
const struct device_type macvlan_device_type = { static struct device_type macvlan_device_type = {
.name = "MAC VLAN", .name = "macvlan",
.config_params = &macvlan_attr_list, .config_params = &macvlan_attr_list,
.create = macvlan_create, .create = macvlan_create,
.config_init = macvlan_config_init, .config_init = macvlan_config_init,
@@ -261,3 +262,8 @@ const struct device_type macvlan_device_type = {
.free = macvlan_free, .free = macvlan_free,
.dump_info = macvlan_dump_info, .dump_info = macvlan_dump_info,
}; };
static void __init macvlan_device_type_init(void)
{
device_type_add(&macvlan_device_type);
}

View File

@@ -24,7 +24,7 @@
#include <libubox/ustream.h> #include <libubox/ustream.h>
#include <libubox/utils.h> #include <libubox/utils.h>
#include <ubus/libubus.h> #include <libubus.h>
#include "utils.h" #include "utils.h"

View File

@@ -44,7 +44,6 @@ struct proto_shell_handler {
char *config_buf; char *config_buf;
char *script_name; char *script_name;
bool init_available; bool init_available;
bool no_proto_task;
struct uci_blob_param_list config; struct uci_blob_param_list config;
}; };
@@ -306,7 +305,7 @@ proto_shell_task_finish(struct proto_shell_state *state,
if (state->renew_pending) if (state->renew_pending)
proto_shell_handler(&state->proto, proto_shell_handler(&state->proto,
PROTO_CMD_RENEW, false); PROTO_CMD_RENEW, false);
else if (!state->handler->no_proto_task && else if (!(state->handler->proto.flags & PROTO_FLAG_NO_TASK) &&
!state->proto_task.uloop.pending && !state->proto_task.uloop.pending &&
state->sm == S_SETUP) state->sm == S_SETUP)
proto_shell_handler(&state->proto, proto_shell_handler(&state->proto,
@@ -539,10 +538,10 @@ proto_shell_update_link(struct proto_shell_state *state, struct blob_attr *data,
return UBUS_STATUS_UNKNOWN_ERROR; return UBUS_STATUS_UNKNOWN_ERROR;
device_set_present(dev, true); device_set_present(dev, true);
interface_update_start(iface);
} }
interface_update_start(iface, keep);
proto_apply_ip_settings(iface, data, addr_ext); proto_apply_ip_settings(iface, data, addr_ext);
if ((cur = tb[NOTIFY_ROUTES]) != NULL) if ((cur = tb[NOTIFY_ROUTES]) != NULL)
@@ -563,8 +562,7 @@ proto_shell_update_link(struct proto_shell_state *state, struct blob_attr *data,
interface_update_complete(state->proto.iface); interface_update_complete(state->proto.iface);
if ((state->sm != S_SETUP_ABORT) && (state->sm != S_TEARDOWN)) { if ((state->sm != S_SETUP_ABORT) && (state->sm != S_TEARDOWN)) {
if (!keep) state->proto.proto_event(&state->proto, IFPEV_UP);
state->proto.proto_event(&state->proto, IFPEV_UP);
state->sm = S_IDLE; state->sm = S_IDLE;
} }
@@ -892,7 +890,8 @@ proto_shell_add_handler(const char *script, const char *name, json_object *obj)
handler->proto.flags |= PROTO_FLAG_NODEV; handler->proto.flags |= PROTO_FLAG_NODEV;
tmp = json_get_field(obj, "no-proto-task", json_type_boolean); tmp = json_get_field(obj, "no-proto-task", json_type_boolean);
handler->no_proto_task = tmp && json_object_get_boolean(tmp); if (tmp && json_object_get_boolean(tmp))
handler->proto.flags |= PROTO_FLAG_NO_TASK;
tmp = json_get_field(obj, "available", json_type_boolean); tmp = json_get_field(obj, "available", json_type_boolean);
if (tmp && json_object_get_boolean(tmp)) if (tmp && json_object_get_boolean(tmp))
@@ -906,6 +905,10 @@ proto_shell_add_handler(const char *script, const char *name, json_object *obj)
if (tmp && json_object_get_boolean(tmp)) if (tmp && json_object_get_boolean(tmp))
handler->proto.flags |= PROTO_FLAG_LASTERROR; handler->proto.flags |= PROTO_FLAG_LASTERROR;
tmp = json_get_field(obj, "teardown-on-l3-link-down", json_type_boolean);
if (tmp && json_object_get_boolean(tmp))
handler->proto.flags |= PROTO_FLAG_TEARDOWN_ON_L3_LINK_DOWN;
config = json_get_field(obj, "config", json_type_array); config = json_get_field(obj, "config", json_type_array);
if (config) if (config)
handler->config_buf = netifd_handler_parse_config(&handler->config, config); handler->config_buf = netifd_handler_parse_config(&handler->config, config);

View File

@@ -36,6 +36,7 @@ enum {
OPT_GATEWAY, OPT_GATEWAY,
OPT_IP6GW, OPT_IP6GW,
OPT_IP6PREFIX, OPT_IP6PREFIX,
OPT_IP6DEPRECATED,
__OPT_MAX, __OPT_MAX,
}; };
@@ -47,6 +48,7 @@ static const struct blobmsg_policy proto_ip_attributes[__OPT_MAX] = {
[OPT_GATEWAY] = { .name = "gateway", .type = BLOBMSG_TYPE_STRING }, [OPT_GATEWAY] = { .name = "gateway", .type = BLOBMSG_TYPE_STRING },
[OPT_IP6GW] = { .name = "ip6gw", .type = BLOBMSG_TYPE_STRING }, [OPT_IP6GW] = { .name = "ip6gw", .type = BLOBMSG_TYPE_STRING },
[OPT_IP6PREFIX] = { .name = "ip6prefix", .type = BLOBMSG_TYPE_ARRAY }, [OPT_IP6PREFIX] = { .name = "ip6prefix", .type = BLOBMSG_TYPE_ARRAY },
[OPT_IP6DEPRECATED] = { .name = "ip6deprecated", .type = BLOBMSG_TYPE_BOOL },
}; };
static const struct uci_blob_param_info proto_ip_attr_info[__OPT_MAX] = { static const struct uci_blob_param_info proto_ip_attr_info[__OPT_MAX] = {
@@ -113,7 +115,7 @@ alloc_device_addr(bool v6, bool ext)
static bool static bool
parse_addr(struct interface *iface, const char *str, bool v6, int mask, parse_addr(struct interface *iface, const char *str, bool v6, int mask,
bool ext, uint32_t broadcast) bool ext, uint32_t broadcast, bool deprecated)
{ {
struct device_addr *addr; struct device_addr *addr;
int af = v6 ? AF_INET6 : AF_INET; int af = v6 ? AF_INET6 : AF_INET;
@@ -123,22 +125,36 @@ parse_addr(struct interface *iface, const char *str, bool v6, int mask,
return false; return false;
addr->mask = mask; addr->mask = mask;
if (!parse_ip_and_netmask(af, str, &addr->addr, &addr->mask)) { if (!parse_ip_and_netmask(af, str, &addr->addr, &addr->mask))
interface_add_error(iface, "proto", "INVALID_ADDRESS", &str, 1); goto error;
free(addr);
return false; if (!v6) {
} if (IN_EXPERIMENTAL(ntohl(addr->addr.in.s_addr)))
goto error;
} else if (IN6_IS_ADDR_MULTICAST(&addr->addr.in6))
goto error;
if (broadcast) if (broadcast)
addr->broadcast = broadcast; addr->broadcast = broadcast;
if (deprecated)
addr->preferred_until = system_get_rtime();
vlist_add(&iface->proto_ip.addr, &addr->node, &addr->flags); vlist_add(&iface->proto_ip.addr, &addr->node, &addr->flags);
return true; return true;
error:
interface_add_error(iface, "proto", "INVALID_ADDRESS", &str, 1);
free(addr);
return false;
} }
static int static int
parse_static_address_option(struct interface *iface, struct blob_attr *attr, parse_static_address_option(struct interface *iface, struct blob_attr *attr,
bool v6, int netmask, bool ext, uint32_t broadcast) bool v6, int netmask, bool ext, uint32_t broadcast,
bool deprecated)
{ {
struct blob_attr *cur; struct blob_attr *cur;
int n_addr = 0; int n_addr = 0;
@@ -150,7 +166,7 @@ parse_static_address_option(struct interface *iface, struct blob_attr *attr,
n_addr++; n_addr++;
if (!parse_addr(iface, blobmsg_data(cur), v6, netmask, ext, if (!parse_addr(iface, blobmsg_data(cur), v6, netmask, ext,
broadcast)) broadcast, deprecated))
return -1; return -1;
} }
@@ -390,6 +406,7 @@ proto_apply_static_ip_settings(struct interface *iface, struct blob_attr *attr)
struct blob_attr *cur; struct blob_attr *cur;
const char *error; const char *error;
unsigned int netmask = 32; unsigned int netmask = 32;
bool ip6deprecated;
int n_v4 = 0, n_v6 = 0; int n_v4 = 0, n_v6 = 0;
struct in_addr bcast = {}; struct in_addr bcast = {};
@@ -410,13 +427,15 @@ proto_apply_static_ip_settings(struct interface *iface, struct blob_attr *attr)
} }
} }
ip6deprecated = blobmsg_get_bool_default(tb[OPT_IP6DEPRECATED], false);
if ((cur = tb[OPT_IPADDR])) if ((cur = tb[OPT_IPADDR]))
n_v4 = parse_static_address_option(iface, cur, false, n_v4 = parse_static_address_option(iface, cur, false,
netmask, false, bcast.s_addr); netmask, false, bcast.s_addr, false);
if ((cur = tb[OPT_IP6ADDR])) if ((cur = tb[OPT_IP6ADDR]))
n_v6 = parse_static_address_option(iface, cur, true, n_v6 = parse_static_address_option(iface, cur, true,
128, false, 0); 128, false, 0, ip6deprecated);
if ((cur = tb[OPT_IP6PREFIX])) if ((cur = tb[OPT_IP6PREFIX]))
if (parse_prefix_list(iface, cur) < 0) if (parse_prefix_list(iface, cur) < 0)
@@ -567,7 +586,14 @@ proto_dump_handlers(struct blob_buf *b)
blobmsg_add_string(b, p->config_params->params[i].name, uci_get_validate_string(p->config_params, i)); blobmsg_add_string(b, p->config_params->params[i].name, uci_get_validate_string(p->config_params, i));
blobmsg_close_table(b, v); blobmsg_close_table(b, v);
} }
blobmsg_add_u8(b, "immediate", !!(p->flags & PROTO_FLAG_IMMEDIATE));
blobmsg_add_u8(b, "no_device", !!(p->flags & PROTO_FLAG_NODEV)); blobmsg_add_u8(b, "no_device", !!(p->flags & PROTO_FLAG_NODEV));
blobmsg_add_u8(b, "init_available", !!(p->flags & PROTO_FLAG_INIT_AVAILABLE));
blobmsg_add_u8(b, "renew_available", !!(p->flags & PROTO_FLAG_RENEW_AVAILABLE));
blobmsg_add_u8(b, "force_link_default", !!(p->flags & PROTO_FLAG_FORCE_LINK_DEFAULT));
blobmsg_add_u8(b, "last_error", !!(p->flags & PROTO_FLAG_LASTERROR));
blobmsg_add_u8(b, "teardown_on_l3_link_down", !!(p->flags & PROTO_FLAG_TEARDOWN_ON_L3_LINK_DOWN));
blobmsg_add_u8(b, "no_task", !!(p->flags & PROTO_FLAG_NO_TASK));
blobmsg_close_table(b, c); blobmsg_close_table(b, c);
} }
} }

View File

@@ -38,6 +38,8 @@ enum {
PROTO_FLAG_RENEW_AVAILABLE = (1 << 3), PROTO_FLAG_RENEW_AVAILABLE = (1 << 3),
PROTO_FLAG_FORCE_LINK_DEFAULT = (1 << 4), PROTO_FLAG_FORCE_LINK_DEFAULT = (1 << 4),
PROTO_FLAG_LASTERROR = (1 << 5), PROTO_FLAG_LASTERROR = (1 << 5),
PROTO_FLAG_TEARDOWN_ON_L3_LINK_DOWN = (1 << 6),
PROTO_FLAG_NO_TASK = (1 << 7),
}; };
struct interface_proto_state { struct interface_proto_state {

View File

@@ -1,4 +1,5 @@
NETIFD_MAIN_DIR="${NETIFD_MAIN_DIR:-/lib/netifd}" NETIFD_MAIN_DIR="${NETIFD_MAIN_DIR:-/lib/netifd}"
PROTO_DEFAULT_OPTIONS="defaultroute peerdns metric"
. /usr/share/libubox/jshn.sh . /usr/share/libubox/jshn.sh
. $NETIFD_MAIN_DIR/utils.sh . $NETIFD_MAIN_DIR/utils.sh
@@ -15,6 +16,18 @@ proto_config_add_boolean() {
config_add_boolean "$@" config_add_boolean "$@"
} }
proto_config_add_defaults() {
proto_config_add_boolean "defaultroute"
proto_config_add_boolean "peerdns"
proto_config_add_int "metric"
}
proto_add_dynamic_defaults() {
[ -n "$defaultroute" ] && json_add_boolean defaultroute "$defaultroute"
[ -n "$peerdns" ] && json_add_boolean peerdns "$peerdns"
[ -n "$metric" ] && json_add_int metric "$metric"
}
_proto_do_teardown() { _proto_do_teardown() {
json_load "$data" json_load "$data"
eval "proto_$1_teardown \"$interface\" \"$ifname\"" eval "proto_$1_teardown \"$interface\" \"$ifname\""
@@ -365,6 +378,7 @@ init_proto() {
no_proto_task=0 no_proto_task=0
available=0 available=0
renew_handler=0 renew_handler=0
teardown_on_l3_link_down=0
add_default_handler "proto_$1_init_config" add_default_handler "proto_$1_init_config"
@@ -378,6 +392,7 @@ init_proto() {
json_add_boolean available "$available" json_add_boolean available "$available"
json_add_boolean renew-handler "$renew_handler" json_add_boolean renew-handler "$renew_handler"
json_add_boolean lasterror "$lasterror" json_add_boolean lasterror "$lasterror"
json_add_boolean teardown-on-l3-link-down "$teardown_on_l3_link_down"
json_dump json_dump
} }
;; ;;

View File

@@ -202,6 +202,12 @@ bool system_resolve_rt_type(const char *type, unsigned int *id)
return true; return true;
} }
bool system_resolve_rt_proto(const char *type, unsigned int *id)
{
*id = 0;
return true;
}
bool system_resolve_rt_table(const char *name, unsigned int *id) bool system_resolve_rt_table(const char *name, unsigned int *id)
{ {
*id = 0; *id = 0;

View File

@@ -52,7 +52,6 @@
#define IFA_FLAGS (IFA_MULTICAST + 1) #define IFA_FLAGS (IFA_MULTICAST + 1)
#endif #endif
#include <string.h> #include <string.h>
#include <fcntl.h> #include <fcntl.h>
#include <glob.h> #include <glob.h>
@@ -326,6 +325,11 @@ static void system_bridge_set_multicast_to_unicast(struct device *dev, const cha
system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val); system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
} }
static void system_bridge_set_multicast_fast_leave(struct device *dev, const char *val)
{
system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_fast_leave", dev->ifname, val);
}
static void system_bridge_set_hairpin_mode(struct device *dev, const char *val) static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
{ {
system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val); system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
@@ -392,6 +396,11 @@ static void system_bridge_set_unicast_flood(struct device *dev, const char *val)
system_set_dev_sysctl("/sys/class/net/%s/brport/unicast_flood", dev->ifname, val); system_set_dev_sysctl("/sys/class/net/%s/brport/unicast_flood", dev->ifname, val);
} }
static void system_set_sendredirects(struct device *dev, const char *val)
{
system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects", dev->ifname, val);
}
static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz) static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
{ {
int fd = -1, ret = -1; int fd = -1, ret = -1;
@@ -480,6 +489,12 @@ static int system_get_dadtransmits(struct device *dev, char *buf, const size_t b
dev->ifname, buf, buf_sz); dev->ifname, buf, buf_sz);
} }
static int system_get_sendredirects(struct device *dev, char *buf, const size_t buf_sz)
{
return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects",
dev->ifname, buf, buf_sz);
}
// Evaluate netlink messages // Evaluate netlink messages
static int cb_rtnl_event(struct nl_msg *msg, void *arg) static int cb_rtnl_event(struct nl_msg *msg, void *arg)
{ {
@@ -680,6 +695,10 @@ int system_bridge_addif(struct device *bridge, struct device *dev)
system_bridge_set_multicast_router(dev, buf, false); system_bridge_set_multicast_router(dev, buf, false);
} }
if (dev->settings.flags & DEV_OPT_MULTICAST_FAST_LEAVE &&
dev->settings.multicast_fast_leave)
system_bridge_set_multicast_fast_leave(dev, "1");
if (dev->settings.flags & DEV_OPT_LEARNING && if (dev->settings.flags & DEV_OPT_LEARNING &&
!dev->settings.learning) !dev->settings.learning)
system_bridge_set_learning(dev, "0"); system_bridge_set_learning(dev, "0");
@@ -1279,6 +1298,11 @@ system_if_get_settings(struct device *dev, struct device_settings *s)
s->dadtransmits = strtoul(buf, NULL, 0); s->dadtransmits = strtoul(buf, NULL, 0);
s->flags |= DEV_OPT_DADTRANSMITS; s->flags |= DEV_OPT_DADTRANSMITS;
} }
if (!system_get_sendredirects(dev, buf, sizeof(buf))) {
s->sendredirects = strtoul(buf, NULL, 0);
s->flags |= DEV_OPT_SENDREDIRECTS;
}
} }
static void static void
@@ -1384,6 +1408,8 @@ system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned
!s->multicast ? IFF_MULTICAST : 0) < 0) !s->multicast ? IFF_MULTICAST : 0) < 0)
s->flags &= ~DEV_OPT_MULTICAST; s->flags &= ~DEV_OPT_MULTICAST;
} }
if (s->flags & DEV_OPT_SENDREDIRECTS & apply_mask)
system_set_sendredirects(dev, s->sendredirects ? "1" : "0");
system_if_apply_rps_xps(dev, s); system_if_apply_rps_xps(dev, s);
} }
@@ -1755,7 +1781,7 @@ static int system_rt(struct device *dev, struct device_route *route, int cmd)
.rtm_dst_len = route->mask, .rtm_dst_len = route->mask,
.rtm_src_len = route->sourcemask, .rtm_src_len = route->sourcemask,
.rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC, .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
.rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC, .rtm_protocol = (route->flags & DEVROUTE_PROTO) ? route->proto : RTPROT_STATIC,
.rtm_scope = RT_SCOPE_NOWHERE, .rtm_scope = RT_SCOPE_NOWHERE,
.rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST, .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
.rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0, .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
@@ -1873,6 +1899,45 @@ bool system_resolve_rt_type(const char *type, unsigned int *id)
return system_rtn_aton(type, id); return system_rtn_aton(type, id);
} }
bool system_resolve_rt_proto(const char *type, unsigned int *id)
{
FILE *f;
char *e, buf[128];
unsigned int n, proto = 256;
if ((n = strtoul(type, &e, 0)) >= 0 && !*e && e != type)
proto = n;
else if (!strcmp(type, "unspec"))
proto = RTPROT_UNSPEC;
else if (!strcmp(type, "kernel"))
proto = RTPROT_KERNEL;
else if (!strcmp(type, "boot"))
proto = RTPROT_BOOT;
else if (!strcmp(type, "static"))
proto = RTPROT_STATIC;
else if ((f = fopen("/etc/iproute2/rt_protos", "r")) != NULL) {
while (fgets(buf, sizeof(buf) - 1, f) != NULL) {
if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
continue;
n = strtoul(e, NULL, 10);
e = strtok(NULL, " \t\n");
if (e && !strcmp(e, type)) {
proto = n;
break;
}
}
fclose(f);
}
if (proto > 255)
return false;
*id = proto;
return true;
}
bool system_resolve_rt_table(const char *name, unsigned int *id) bool system_resolve_rt_table(const char *name, unsigned int *id)
{ {
FILE *f; FILE *f;
@@ -2118,7 +2183,7 @@ static int system_add_gre_tunnel(const char *name, const char *kind,
uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0; uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
uint16_t iflags = 0, oflags = 0; uint16_t iflags = 0, oflags = 0;
uint8_t tos = 0; uint8_t tos = 0;
int ret = 0, ttl = 64; int ret = 0, ttl = 0;
nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE); nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
if (!nlm) if (!nlm)
@@ -2146,8 +2211,6 @@ static int system_add_gre_tunnel(const char *name, const char *kind,
if ((cur = tb[TUNNEL_ATTR_TTL])) if ((cur = tb[TUNNEL_ATTR_TTL]))
ttl = blobmsg_get_u32(cur); ttl = blobmsg_get_u32(cur);
nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
if ((cur = tb[TUNNEL_ATTR_TOS])) { if ((cur = tb[TUNNEL_ATTR_TOS])) {
char *str = blobmsg_get_string(cur); char *str = blobmsg_get_string(cur);
if (strcmp(str, "inherit")) { if (strcmp(str, "inherit")) {
@@ -2221,6 +2284,9 @@ static int system_add_gre_tunnel(const char *name, const char *kind,
if (flags) if (flags)
nla_put_u32(nlm, IFLA_GRE_FLAGS, flags); nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
if (!ttl)
ttl = 64;
} else { } else {
struct in_addr inbuf; struct in_addr inbuf;
bool set_df = true; bool set_df = true;
@@ -2256,17 +2322,23 @@ static int system_add_gre_tunnel(const char *name, const char *kind,
if ((cur = tb[TUNNEL_ATTR_DF])) if ((cur = tb[TUNNEL_ATTR_DF]))
set_df = blobmsg_get_bool(cur); set_df = blobmsg_get_bool(cur);
/* ttl !=0 and nopmtudisc are incompatible */ if (!set_df) {
if (ttl && !set_df) { /* ttl != 0 and nopmtudisc are incompatible */
ret = -EINVAL; if (ttl) {
goto failure; ret = -EINVAL;
} goto failure;
}
} else if (!ttl)
ttl = 64;
nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0); nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
nla_put_u8(nlm, IFLA_GRE_TOS, tos); nla_put_u8(nlm, IFLA_GRE_TOS, tos);
} }
if (ttl)
nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
if (oflags) if (oflags)
nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags); nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
@@ -2476,10 +2548,14 @@ int system_update_ipv6_mtu(struct device *dev, int mtu)
{ {
int ret = -1; int ret = -1;
char buf[64]; char buf[64];
int fd;
snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu", snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
dev->ifname); dev->ifname);
int fd = open(buf, O_RDWR); fd = open(buf, O_RDWR);
if (fd < 0)
return ret;
if (!mtu) { if (!mtu) {
ssize_t len = read(fd, buf, sizeof(buf) - 1); ssize_t len = read(fd, buf, sizeof(buf) - 1);

View File

@@ -146,6 +146,7 @@ int system_del_route(struct device *dev, struct device_route *route);
int system_flush_routes(void); int system_flush_routes(void);
bool system_resolve_rt_type(const char *type, unsigned int *id); bool system_resolve_rt_type(const char *type, unsigned int *id);
bool system_resolve_rt_proto(const char *type, unsigned int *id);
bool system_resolve_rt_table(const char *name, unsigned int *id); bool system_resolve_rt_table(const char *name, unsigned int *id);
bool system_is_default_rt_table(unsigned int id); bool system_is_default_rt_table(unsigned int id);
bool system_resolve_rpfilter(const char *filter, unsigned int *id); bool system_resolve_rpfilter(const char *filter, unsigned int *id);

View File

@@ -61,7 +61,8 @@ tunnel_reload(struct device *dev, struct blob_attr *attr)
} }
static struct device * static struct device *
tunnel_create(const char *name, struct blob_attr *attr) tunnel_create(const char *name, struct device_type *devtype,
struct blob_attr *attr)
{ {
struct tunnel *tun; struct tunnel *tun;
struct device *dev; struct device *dev;
@@ -71,10 +72,10 @@ tunnel_create(const char *name, struct blob_attr *attr)
return NULL; return NULL;
dev = &tun->dev; dev = &tun->dev;
device_init(dev, &tunnel_device_type, name); device_init(dev, devtype, name);
tun->set_state = dev->set_state; tun->set_state = dev->set_state;
dev->set_state = tunnel_set_state; dev->set_state = tunnel_set_state;
device_apply_config(dev, &tunnel_device_type, attr); device_apply_config(dev, devtype, attr);
device_set_present(dev, true); device_set_present(dev, true);
return dev; return dev;
@@ -88,12 +89,15 @@ tunnel_free(struct device *dev)
free(tun); free(tun);
} }
const struct device_type tunnel_device_type = { struct device_type tunnel_device_type = {
.name = "IP tunnel", .name = "tunnel",
.config_params = &tunnel_attr_list, .config_params = &tunnel_attr_list,
.reload = tunnel_reload, .reload = tunnel_reload,
.create = tunnel_create, .create = tunnel_create,
.free = tunnel_free, .free = tunnel_free,
}; };
static void __init tunnel_device_type_init(void)
{
device_type_add(&tunnel_device_type);
}

View File

@@ -204,7 +204,7 @@ netifd_dev_status(struct ubus_context *ctx, struct ubus_object *obj,
blobmsg_parse(dev_policy, __DEV_MAX, tb, blob_data(msg), blob_len(msg)); blobmsg_parse(dev_policy, __DEV_MAX, tb, blob_data(msg), blob_len(msg));
if (tb[DEV_NAME]) { if (tb[DEV_NAME]) {
dev = device_get(blobmsg_data(tb[DEV_NAME]), false); dev = device_find(blobmsg_data(tb[DEV_NAME]));
if (!dev) if (!dev)
return UBUS_STATUS_INVALID_ARGUMENT; return UBUS_STATUS_INVALID_ARGUMENT;
} }
@@ -486,6 +486,9 @@ interface_ip_dump_route_list(struct interface_ip_settings *ip, bool enabled)
if (route->flags & DEVROUTE_TYPE) if (route->flags & DEVROUTE_TYPE)
blobmsg_add_u32(&b, "type", route->type); blobmsg_add_u32(&b, "type", route->type);
if (route->flags & DEVROUTE_PROTO)
blobmsg_add_u32(&b, "proto", route->proto);
if (route->flags & DEVROUTE_MTU) if (route->flags & DEVROUTE_MTU)
blobmsg_add_u32(&b, "mtu", route->mtu); blobmsg_add_u32(&b, "mtu", route->mtu);
@@ -600,12 +603,21 @@ interface_ip_dump_prefix_assignment_list(struct interface *iface)
if (prefix->valid_until) if (prefix->valid_until)
blobmsg_add_u32(&b, "valid", prefix->valid_until - now); blobmsg_add_u32(&b, "valid", prefix->valid_until - now);
void *c = blobmsg_open_table(&b, "local-address");
if (assign->enabled) {
buf = blobmsg_alloc_string_buffer(&b, "address", buflen);
inet_ntop(AF_INET6, &assign->addr, buf, buflen);
blobmsg_add_string_buffer(&b);
blobmsg_add_u32(&b, "mask", assign->length < 64 ? 64 : assign->length);
}
blobmsg_close_table(&b, c);
blobmsg_close_table(&b, a); blobmsg_close_table(&b, a);
} }
} }
} }
static void static void
interface_ip_dump_dns_server_list(struct interface_ip_settings *ip, interface_ip_dump_dns_server_list(struct interface_ip_settings *ip,
bool enabled) bool enabled)
@@ -685,8 +697,9 @@ netifd_dump_status(struct interface *iface)
if (iface->ip4table) if (iface->ip4table)
blobmsg_add_u32(&b, "ip4table", iface->ip4table); blobmsg_add_u32(&b, "ip4table", iface->ip4table);
if (iface->ip6table) if (iface->ip6table)
blobmsg_add_u32(&b, "ip6table", iface->ip6table); blobmsg_add_u32(&b, "ip6table", iface->ip6table);
blobmsg_add_u32(&b, "metric", iface->metric); 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); blobmsg_add_u8(&b, "delegation", !iface->proto_ip.no_delegation);
a = blobmsg_open_array(&b, "ipv4-address"); a = blobmsg_open_array(&b, "ipv4-address");
interface_ip_dump_address_list(&iface->config_ip, false, true); interface_ip_dump_address_list(&iface->config_ip, false, true);

View File

@@ -119,7 +119,6 @@ int
parse_ip_and_netmask(int af, const char *str, void *addr, unsigned int *netmask) parse_ip_and_netmask(int af, const char *str, void *addr, unsigned int *netmask)
{ {
char *astr = alloca(strlen(str) + 1); char *astr = alloca(strlen(str) + 1);
int ret = 0;
strcpy(astr, str); strcpy(astr, str);
if (!split_netmask(astr, netmask, af == AF_INET6)) if (!split_netmask(astr, netmask, af == AF_INET6))
@@ -133,23 +132,7 @@ parse_ip_and_netmask(int af, const char *str, void *addr, unsigned int *netmask)
return 0; return 0;
} }
ret = inet_pton(af, astr, addr); return inet_pton(af, astr, addr);
if (ret > 0) {
if (af == AF_INET) {
struct in_addr *ip4_addr = (struct in_addr *)addr;
uint32_t host_addr = ntohl(ip4_addr->s_addr);
if (IN_EXPERIMENTAL(host_addr)) {
return 0;
}
}
else if (af == AF_INET6) {
if (IN6_IS_ADDR_MULTICAST((struct in6_addr *)addr)) {
return 0;
}
}
}
return ret;
} }
char * char *

View File

@@ -16,7 +16,7 @@
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <uci/uci_blob.h> #include <uci_blob.h>
#include <libubox/list.h> #include <libubox/list.h>
#include <libubox/avl.h> #include <libubox/avl.h>
#include <libubox/avl-cmp.h> #include <libubox/avl-cmp.h>

View File

@@ -96,7 +96,7 @@ static void vlan_dev_cb(struct device_user *dep, enum device_event ev)
static struct device *get_vlan_device(struct device *dev, int id, bool create) static struct device *get_vlan_device(struct device *dev, int id, bool create)
{ {
static const struct device_type vlan_type = { static struct device_type vlan_type = {
.name = "VLAN", .name = "VLAN",
.config_params = &device_attr_list, .config_params = &device_attr_list,
.free = free_vlan_if, .free = free_vlan_if,

View File

@@ -20,14 +20,12 @@
#include "system.h" #include "system.h"
enum { enum {
VLANDEV_ATTR_TYPE,
VLANDEV_ATTR_IFNAME, VLANDEV_ATTR_IFNAME,
VLANDEV_ATTR_VID, VLANDEV_ATTR_VID,
__VLANDEV_ATTR_MAX __VLANDEV_ATTR_MAX
}; };
static const struct blobmsg_policy vlandev_attrs[__VLANDEV_ATTR_MAX] = { static const struct blobmsg_policy vlandev_attrs[__VLANDEV_ATTR_MAX] = {
[VLANDEV_ATTR_TYPE] = { "type", BLOBMSG_TYPE_STRING },
[VLANDEV_ATTR_IFNAME] = { "ifname", BLOBMSG_TYPE_STRING }, [VLANDEV_ATTR_IFNAME] = { "ifname", BLOBMSG_TYPE_STRING },
[VLANDEV_ATTR_VID] = { "vid", BLOBMSG_TYPE_INT32 }, [VLANDEV_ATTR_VID] = { "vid", BLOBMSG_TYPE_INT32 },
}; };
@@ -40,6 +38,8 @@ static const struct uci_blob_param_list vlandev_attr_list = {
.next = { &device_attr_list }, .next = { &device_attr_list },
}; };
static struct device_type vlan8021q_device_type;
struct vlandev_device { struct vlandev_device {
struct device dev; struct device dev;
struct device_user parent; struct device_user parent;
@@ -158,15 +158,10 @@ vlandev_apply_settings(struct vlandev_device *mvdev, struct blob_attr **tb)
struct vlandev_config *cfg = &mvdev->config; struct vlandev_config *cfg = &mvdev->config;
struct blob_attr *cur; struct blob_attr *cur;
cfg->proto = VLAN_PROTO_8021Q; cfg->proto = (mvdev->dev.type == &vlan8021q_device_type) ?
VLAN_PROTO_8021Q : VLAN_PROTO_8021AD;
cfg->vid = 1; cfg->vid = 1;
if ((cur = tb[VLANDEV_ATTR_TYPE]))
{
if(!strcmp(blobmsg_data(cur), "8021ad"))
cfg->proto = VLAN_PROTO_8021AD;
}
if ((cur = tb[VLANDEV_ATTR_VID])) if ((cur = tb[VLANDEV_ATTR_VID]))
cfg->vid = (uint16_t) blobmsg_get_u32(cur); cfg->vid = (uint16_t) blobmsg_get_u32(cur);
} }
@@ -216,7 +211,8 @@ vlandev_reload(struct device *dev, struct blob_attr *attr)
} }
static struct device * static struct device *
vlandev_create(const char *name, struct blob_attr *attr) vlandev_create(const char *name, struct device_type *devtype,
struct blob_attr *attr)
{ {
struct vlandev_device *mvdev; struct vlandev_device *mvdev;
struct device *dev = NULL; struct device *dev = NULL;
@@ -226,7 +222,7 @@ vlandev_create(const char *name, struct blob_attr *attr)
return NULL; return NULL;
dev = &mvdev->dev; dev = &mvdev->dev;
device_init(dev, &vlandev_device_type, name); device_init(dev, devtype, name);
dev->config_pending = true; dev->config_pending = true;
mvdev->set_state = dev->set_state; mvdev->set_state = dev->set_state;
@@ -240,8 +236,8 @@ vlandev_create(const char *name, struct blob_attr *attr)
return dev; return dev;
} }
const struct device_type vlandev_device_type = { static struct device_type vlan8021ad_device_type = {
.name = "VLANDEV", .name = "8021ad",
.config_params = &vlandev_attr_list, .config_params = &vlandev_attr_list,
.create = vlandev_create, .create = vlandev_create,
.config_init = vlandev_config_init, .config_init = vlandev_config_init,
@@ -249,3 +245,19 @@ const struct device_type vlandev_device_type = {
.free = vlandev_free, .free = vlandev_free,
.dump_info = vlandev_dump_info, .dump_info = vlandev_dump_info,
}; };
static struct device_type vlan8021q_device_type = {
.name = "8021q",
.config_params = &vlandev_attr_list,
.create = vlandev_create,
.config_init = vlandev_config_init,
.reload = vlandev_reload,
.free = vlandev_free,
.dump_info = vlandev_dump_info,
};
static void __init vlandev_device_type_init(void)
{
device_type_add(&vlan8021ad_device_type);
device_type_add(&vlan8021q_device_type);
}

View File

@@ -83,7 +83,7 @@ vif_config_add_bridge(struct blob_buf *buf, struct blob_attr *networks, bool pre
if (!dev) if (!dev)
return; return;
if (dev->type != &bridge_device_type) if (!dev->type->bridge_capability)
return; return;
} }
@@ -287,6 +287,12 @@ __wireless_device_set_up(struct wireless_device *wdev)
if (wdev->disabled) if (wdev->disabled)
return; return;
if (wdev->retry_setup_failed)
return;
if (!wdev->autostart)
return;
if (wdev->state != IFS_DOWN || config_init) if (wdev->state != IFS_DOWN || config_init)
return; return;
@@ -314,9 +320,9 @@ wdev_handle_config_change(struct wireless_device *wdev)
switch(state) { switch(state) {
case IFC_NORMAL: case IFC_NORMAL:
case IFC_RELOAD: case IFC_RELOAD:
__wireless_device_set_up(wdev);
wdev->config_state = IFC_NORMAL; wdev->config_state = IFC_NORMAL;
if (wdev->autostart)
__wireless_device_set_up(wdev);
break; break;
case IFC_REMOVE: case IFC_REMOVE:
wireless_device_free(wdev); wireless_device_free(wdev);
@@ -399,7 +405,7 @@ wireless_device_retry_setup(struct wireless_device *wdev)
return; return;
if (--wdev->retry < 0) if (--wdev->retry < 0)
wdev->autostart = false; wdev->retry_setup_failed = true;
__wireless_device_set_down(wdev); __wireless_device_set_down(wdev);
} }
@@ -424,6 +430,7 @@ wireless_device_script_task_cb(struct netifd_process *proc, int ret)
void void
wireless_device_set_down(struct wireless_device *wdev) wireless_device_set_down(struct wireless_device *wdev)
{ {
wdev->retry_setup_failed = false;
wdev->autostart = false; wdev->autostart = false;
__wireless_device_set_down(wdev); __wireless_device_set_down(wdev);
} }
@@ -467,6 +474,7 @@ wdev_change_config(struct wireless_device *wdev, struct wireless_device *wd_new)
free(wdev->config); free(wdev->config);
wdev->config = blob_memdup(new_config); wdev->config = blob_memdup(new_config);
wdev->disabled = disabled; wdev->disabled = disabled;
wdev->retry_setup_failed = false;
wdev_set_config_state(wdev, IFC_RELOAD); wdev_set_config_state(wdev, IFC_RELOAD);
} }
@@ -605,6 +613,7 @@ vif_update(struct vlist_tree *tree, struct vlist_node *node_new,
wireless_interface_init_config(vif_new); wireless_interface_init_config(vif_new);
} else if (vif_old) { } else if (vif_old) {
D(WIRELESS, "Delete wireless interface %s on device %s\n", vif_old->name, wdev->name); D(WIRELESS, "Delete wireless interface %s on device %s\n", vif_old->name, wdev->name);
wireless_interface_handle_link(vif_old, false);
free((void *) vif_old->section); free((void *) vif_old->section);
free(vif_old->config); free(vif_old->config);
free(vif_old); free(vif_old);
@@ -681,8 +690,8 @@ wireless_device_create(struct wireless_driver *drv, const char *name, struct blo
wdev->config_state = IFC_NORMAL; wdev->config_state = IFC_NORMAL;
wdev->name = strcpy(name_buf, name); wdev->name = strcpy(name_buf, name);
wdev->config = data; wdev->config = data;
wdev->config_autostart = true; wdev->retry_setup_failed = false;
wdev->autostart = wdev->config_autostart; wdev->autostart = true;
INIT_LIST_HEAD(&wdev->script_proc); INIT_LIST_HEAD(&wdev->script_proc);
vlist_init(&wdev->interfaces, avl_strcmp, vif_update); vlist_init(&wdev->interfaces, avl_strcmp, vif_update);
wdev->interfaces.keep_old = true; wdev->interfaces.keep_old = true;
@@ -752,6 +761,7 @@ wireless_device_status(struct wireless_device *wdev, struct blob_buf *b)
blobmsg_add_u8(b, "pending", wdev->state == IFS_SETUP || wdev->state == IFS_TEARDOWN); blobmsg_add_u8(b, "pending", wdev->state == IFS_SETUP || wdev->state == IFS_TEARDOWN);
blobmsg_add_u8(b, "autostart", wdev->autostart); blobmsg_add_u8(b, "autostart", wdev->autostart);
blobmsg_add_u8(b, "disabled", wdev->disabled); blobmsg_add_u8(b, "disabled", wdev->disabled);
blobmsg_add_u8(b, "retry_setup_failed", wdev->retry_setup_failed);
put_container(b, wdev->config, "config"); put_container(b, wdev->config, "config");
i = blobmsg_open_array(b, "interfaces"); i = blobmsg_open_array(b, "interfaces");
@@ -991,6 +1001,5 @@ wireless_start_pending(void)
struct wireless_device *wdev; struct wireless_device *wdev;
vlist_for_each_element(&wireless_devices, wdev, node) vlist_for_each_element(&wireless_devices, wdev, node)
if (wdev->autostart) __wireless_device_set_up(wdev);
__wireless_device_set_up(wdev);
} }

View File

@@ -53,9 +53,9 @@ struct wireless_device {
struct blob_attr *config; struct blob_attr *config;
struct blob_attr *data; struct blob_attr *data;
bool config_autostart;
bool autostart; bool autostart;
bool disabled; bool disabled;
bool retry_setup_failed;
enum interface_state state; enum interface_state state;
enum interface_config_state config_state; enum interface_config_state config_state;