Bump netifd versiob 2017.01.25
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
#
|
||||
################################################################################
|
||||
|
||||
NETIFD_VERSION:= 2016.06.06
|
||||
NETIFD_VERSION:= 2017.01.25
|
||||
|
||||
NETIFD_SITE = $(TOPDIR)/../../src/3P/netifd/builders/cmake
|
||||
NETIFD_SITE_METHOD = local
|
||||
|
||||
@@ -5,11 +5,6 @@ ADD_DEFINITIONS(-Os -Wall -Werror --std=gnu99 -Wmissing-declarations)
|
||||
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
|
||||
|
||||
IF(APPLE)
|
||||
INCLUDE_DIRECTORIES(/opt/local/include)
|
||||
LINK_DIRECTORIES(/opt/local/lib)
|
||||
ENDIF()
|
||||
|
||||
SET(SOURCES
|
||||
main.c utils.c system.c tunnel.c handler.c
|
||||
interface.c interface-ip.c interface-event.c
|
||||
|
||||
@@ -30,8 +30,6 @@ struct alias_device {
|
||||
char name[];
|
||||
};
|
||||
|
||||
static const struct device_type alias_device_type;
|
||||
|
||||
static void alias_set_device(struct alias_device *alias, struct device *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_ifname(&alias->dev, dev->ifname);
|
||||
device_add_user(&alias->dep, dev);
|
||||
} else
|
||||
} else {
|
||||
device_set_ifname(&alias->dev, "");
|
||||
device_set_link(&alias->dev, false);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -111,7 +111,8 @@ static void alias_device_cb(struct device_user *dep, enum device_event ev)
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -122,7 +123,7 @@ alias_device_create(const char *name, struct blob_attr *attr)
|
||||
strcpy(alias->name, name);
|
||||
alias->dev.set_state = alias_device_set_state;
|
||||
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;
|
||||
avl_insert(&aliases, &alias->avl);
|
||||
alias->dep.alias = true;
|
||||
@@ -160,7 +161,7 @@ static int alias_check_state(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct device_type alias_device_type = {
|
||||
static struct device_type alias_device_type = {
|
||||
.name = "Network alias",
|
||||
.create = alias_device_create,
|
||||
.free = alias_device_free,
|
||||
@@ -190,7 +191,7 @@ device_alias_get(const char *name)
|
||||
if (alias)
|
||||
return &alias->dev;
|
||||
|
||||
return alias_device_create(name, NULL);
|
||||
return alias_device_create(name, &alias_device_type, NULL);
|
||||
}
|
||||
|
||||
static void __init alias_init(void)
|
||||
|
||||
@@ -72,17 +72,21 @@ static const struct uci_blob_param_list bridge_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_free(struct device *dev);
|
||||
static void bridge_dump_info(struct device *dev, struct blob_buf *b);
|
||||
enum dev_change_type
|
||||
bridge_reload(struct device *dev, struct blob_attr *attr);
|
||||
|
||||
const struct device_type bridge_device_type = {
|
||||
.name = "Bridge",
|
||||
static struct device_type bridge_device_type = {
|
||||
.name = "bridge",
|
||||
.config_params = &bridge_attr_list,
|
||||
|
||||
.bridge_capability = true,
|
||||
.name_prefix = "br",
|
||||
|
||||
.create = bridge_create,
|
||||
.config_init = bridge_config_init,
|
||||
.reload = bridge_reload,
|
||||
@@ -390,24 +394,25 @@ bridge_set_state(struct device *dev, bool up)
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
bm = calloc(1, sizeof(*bm) + strlen(dev->ifname) + 1);
|
||||
bm = calloc(1, sizeof(*bm) + strlen(name) + 1);
|
||||
if (!bm)
|
||||
return NULL;
|
||||
|
||||
bm->bst = bst;
|
||||
bm->dev.cb = bridge_member_cb;
|
||||
bm->dev.hotplug = hotplug;
|
||||
strcpy(bm->name, dev->ifname);
|
||||
strcpy(bm->name, name);
|
||||
bm->dev.dev = dev;
|
||||
vlist_add(&bst->members, &bm->node, bm->name);
|
||||
// Need to look up the bridge member again as the above
|
||||
// created pointer will be freed in case the bridge member
|
||||
// already existed
|
||||
bm = vlist_find(&bst->members, dev->ifname, bm, node);
|
||||
bm = vlist_find(&bst->members, name, bm, node);
|
||||
if (hotplug && bm)
|
||||
bm->node.version = -1;
|
||||
|
||||
@@ -451,7 +456,7 @@ bridge_add_member(struct bridge_state *bst, const char *name)
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
bridge_create_member(bst, dev, false);
|
||||
bridge_create_member(bst, name, dev, false);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
bridge_create_member(bst, member, true);
|
||||
bridge_create_member(bst, member->ifname, member, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -519,8 +524,12 @@ bridge_dump_info(struct device *dev, struct blob_buf *b)
|
||||
system_if_dump_info(dev, b);
|
||||
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_close_array(b, list);
|
||||
}
|
||||
@@ -559,8 +568,6 @@ bridge_apply_settings(struct bridge_state *bst, struct blob_attr **tb)
|
||||
/* defaults */
|
||||
cfg->stp = false;
|
||||
cfg->forward_delay = 2;
|
||||
cfg->igmp_snoop = true;
|
||||
cfg->multicast_querier = true;
|
||||
cfg->robustness = 2;
|
||||
cfg->query_interval = 12500;
|
||||
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,
|
||||
blob_data(attr), blob_len(attr));
|
||||
|
||||
if (tb_dev[DEV_ATTR_MACADDR])
|
||||
bst->primary_port = NULL;
|
||||
|
||||
bst->ifnames = tb_br[BRIDGE_ATTR_IFNAME];
|
||||
device_init_settings(dev, tb_dev);
|
||||
bridge_apply_settings(bst, tb_br);
|
||||
@@ -699,7 +709,8 @@ bridge_retry_members(struct uloop_timeout *timeout)
|
||||
}
|
||||
|
||||
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 device *dev = NULL;
|
||||
@@ -709,7 +720,7 @@ bridge_create(const char *name, struct blob_attr *attr)
|
||||
return NULL;
|
||||
|
||||
dev = &bst->dev;
|
||||
device_init(dev, &bridge_device_type, name);
|
||||
device_init(dev, devtype, name);
|
||||
dev->config_pending = true;
|
||||
bst->retry.cb = bridge_retry_members;
|
||||
|
||||
@@ -724,3 +735,8 @@ bridge_create(const char *name, struct blob_attr *attr)
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
static void __init bridge_device_type_init(void)
|
||||
{
|
||||
device_type_add(&bridge_device_type);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <uci/uci.h>
|
||||
#include <uci.h>
|
||||
|
||||
#include "netifd.h"
|
||||
#include "interface.h"
|
||||
@@ -53,18 +53,18 @@ config_section_idx(struct uci_section *s)
|
||||
}
|
||||
|
||||
static int
|
||||
config_parse_bridge_interface(struct uci_section *s)
|
||||
config_parse_bridge_interface(struct uci_section *s, struct device_type *devtype)
|
||||
{
|
||||
char *name;
|
||||
|
||||
name = alloca(strlen(s->e.name) + 4);
|
||||
sprintf(name, "br-%s", s->e.name);
|
||||
name = alloca(strlen(s->e.name) + strlen(devtype->name_prefix) + 2);
|
||||
sprintf(name, "%s-%s", devtype->name_prefix, s->e.name);
|
||||
blobmsg_add_string(&b, "name", name);
|
||||
|
||||
uci_to_blob(&b, s, bridge_device_type.config_params);
|
||||
if (!device_create(name, &bridge_device_type, b.head)) {
|
||||
D(INTERFACE, "Failed to create bridge for interface '%s'\n", s->e.name);
|
||||
return -EINVAL;
|
||||
uci_to_blob(&b, s, devtype->config_params);
|
||||
if (!device_create(name, devtype, b.head)) {
|
||||
D(INTERFACE, "Failed to create '%s' device for interface '%s'\n",
|
||||
devtype->name, s->e.name);
|
||||
}
|
||||
|
||||
blob_buf_init(&b, 0);
|
||||
@@ -79,6 +79,7 @@ config_parse_interface(struct uci_section *s, bool alias)
|
||||
const char *type = NULL, *disabled;
|
||||
struct blob_attr *config;
|
||||
bool bridge = false;
|
||||
struct device_type *devtype = NULL;
|
||||
|
||||
disabled = uci_lookup_option_string(uci_ctx, s, "disabled");
|
||||
if (disabled && !strcmp(disabled, "1"))
|
||||
@@ -88,8 +89,12 @@ config_parse_interface(struct uci_section *s, bool alias)
|
||||
|
||||
if (!alias)
|
||||
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;
|
||||
|
||||
bridge = true;
|
||||
@@ -157,7 +162,7 @@ config_init_devices(void)
|
||||
uci_foreach_element(&uci_network->sections, e) {
|
||||
const struct uci_blob_param_list *params = NULL;
|
||||
struct uci_section *s = uci_to_section(e);
|
||||
const struct device_type *devtype = NULL;
|
||||
struct device_type *devtype = NULL;
|
||||
struct device *dev;
|
||||
const char *type, *name;
|
||||
|
||||
@@ -169,18 +174,8 @@ config_init_devices(void)
|
||||
continue;
|
||||
|
||||
type = uci_lookup_option_string(uci_ctx, s, "type");
|
||||
if (type) {
|
||||
if (!strcmp(type, "8021ad"))
|
||||
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 (type)
|
||||
devtype = device_type_get(type);
|
||||
|
||||
if (devtype)
|
||||
params = devtype->config_params;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#define __NETIFD_CONFIG_H
|
||||
|
||||
#include <libubox/blobmsg.h>
|
||||
#include <uci/uci_blob.h>
|
||||
#include <uci_blob.h>
|
||||
|
||||
extern bool config_init;
|
||||
|
||||
|
||||
@@ -24,10 +24,13 @@
|
||||
#include <netinet/ether.h>
|
||||
#endif
|
||||
|
||||
#include <libubox/list.h>
|
||||
|
||||
#include "netifd.h"
|
||||
#include "system.h"
|
||||
#include "config.h"
|
||||
|
||||
static struct list_head devtypes = LIST_HEAD_INIT(devtypes);
|
||||
static struct avl_tree devices;
|
||||
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_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_FAST_LEAVE] = { .name = "multicast_fast_leave", . type = BLOBMSG_TYPE_BOOL },
|
||||
[DEV_ATTR_MULTICAST] = { .name ="multicast", .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_SENDREDIRECTS] = { .name = "sendredirects", .type = BLOBMSG_TYPE_BOOL },
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
__devlock++;
|
||||
@@ -118,11 +153,15 @@ simple_device_set_state(struct device *dev, bool state)
|
||||
}
|
||||
|
||||
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 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));
|
||||
dev = device_get(name, true);
|
||||
if (!dev)
|
||||
@@ -141,7 +180,7 @@ static void simple_device_free(struct device *dev)
|
||||
free(dev);
|
||||
}
|
||||
|
||||
const struct device_type simple_device_type = {
|
||||
struct device_type simple_device_type = {
|
||||
.name = "Network device",
|
||||
.config_params = &device_attr_list,
|
||||
|
||||
@@ -184,8 +223,11 @@ device_merge_settings(struct device *dev, struct device_settings *n)
|
||||
s->multicast : os->multicast;
|
||||
n->multicast_to_unicast = s->multicast_to_unicast;
|
||||
n->multicast_router = s->multicast_router;
|
||||
n->multicast_fast_leave = s->multicast_fast_leave;
|
||||
n->learning = s->learning;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -201,12 +243,12 @@ device_init_settings(struct device *dev, struct blob_attr **tb)
|
||||
if ((cur = tb[DEV_ATTR_ENABLED]))
|
||||
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->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->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));
|
||||
}
|
||||
|
||||
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])) {
|
||||
s->multicast = blobmsg_get_bool(cur);
|
||||
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;
|
||||
}
|
||||
|
||||
if ((cur = tb[DEV_ATTR_SENDREDIRECTS])) {
|
||||
s->sendredirects = blobmsg_get_bool(cur);
|
||||
s->flags |= DEV_OPT_SENDREDIRECTS;
|
||||
}
|
||||
|
||||
device_set_disabled(dev, disabled);
|
||||
}
|
||||
|
||||
@@ -406,6 +458,10 @@ void device_release(struct device_user *dep)
|
||||
device_broadcast_event(dev, DEV_EVENT_TEARDOWN);
|
||||
if (!dev->external)
|
||||
dev->set_state(dev, false);
|
||||
|
||||
if (dev->active)
|
||||
return;
|
||||
|
||||
device_broadcast_event(dev, DEV_EVENT_DOWN);
|
||||
}
|
||||
|
||||
@@ -417,7 +473,7 @@ int device_check_state(struct device *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(type);
|
||||
@@ -434,7 +490,7 @@ void device_init_virtual(struct device *dev, const struct device_type *type, con
|
||||
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;
|
||||
|
||||
@@ -729,7 +785,7 @@ device_init_pending(void)
|
||||
}
|
||||
|
||||
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 *tb[__DEV_ATTR_MAX];
|
||||
@@ -758,7 +814,7 @@ device_set_config(struct device *dev, const struct device_type *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)
|
||||
{
|
||||
enum dev_change_type change;
|
||||
@@ -883,13 +939,13 @@ device_set_default_ps(bool state)
|
||||
}
|
||||
|
||||
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 device *odev = NULL, *dev;
|
||||
enum dev_change_type change;
|
||||
|
||||
odev = device_get(name, false);
|
||||
odev = device_find(name);
|
||||
if (odev) {
|
||||
odev->current_config = true;
|
||||
change = device_apply_config(odev, type, config);
|
||||
@@ -908,7 +964,7 @@ device_create(const char *name, const struct device_type *type,
|
||||
if (!config)
|
||||
return NULL;
|
||||
|
||||
dev = type->create(name, config);
|
||||
dev = type->create(name, type, config);
|
||||
if (!dev)
|
||||
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);
|
||||
if (st.flags & DEV_OPT_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)
|
||||
blobmsg_add_u8(b, "multicast", st.multicast);
|
||||
if (st.flags & DEV_OPT_LEARNING)
|
||||
blobmsg_add_u8(b, "learning", st.learning);
|
||||
if (st.flags & DEV_OPT_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");
|
||||
@@ -1009,3 +1069,8 @@ device_dump_status(struct blob_buf *b, struct device *dev)
|
||||
system_if_dump_stats(dev, b);
|
||||
blobmsg_close_table(b, s);
|
||||
}
|
||||
|
||||
static void __init simple_device_type_init(void)
|
||||
{
|
||||
device_type_add(&simple_device_type);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <netinet/in.h>
|
||||
|
||||
struct device;
|
||||
struct device_type;
|
||||
struct device_user;
|
||||
struct device_hotplug_ops;
|
||||
struct interface;
|
||||
@@ -44,10 +45,12 @@ enum {
|
||||
DEV_ATTR_DADTRANSMITS,
|
||||
DEV_ATTR_MULTICAST_TO_UNICAST,
|
||||
DEV_ATTR_MULTICAST_ROUTER,
|
||||
DEV_ATTR_MULTICAST_FAST_LEAVE,
|
||||
DEV_ATTR_MULTICAST,
|
||||
DEV_ATTR_LEARNING,
|
||||
DEV_ATTR_UNICAST_FLOOD,
|
||||
DEV_ATTR_NEIGHGCSTALETIME,
|
||||
DEV_ATTR_SENDREDIRECTS,
|
||||
__DEV_ATTR_MAX,
|
||||
};
|
||||
|
||||
@@ -62,9 +65,13 @@ struct device_type {
|
||||
struct list_head list;
|
||||
const char *name;
|
||||
|
||||
bool bridge_capability;
|
||||
const char *name_prefix;
|
||||
|
||||
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 *);
|
||||
enum dev_change_type (*reload)(struct device *, struct blob_attr *);
|
||||
void (*dump_info)(struct device *, struct blob_buf *buf);
|
||||
@@ -94,6 +101,8 @@ enum {
|
||||
DEV_OPT_LEARNING = (1 << 17),
|
||||
DEV_OPT_UNICAST_FLOOD = (1 << 18),
|
||||
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 */
|
||||
@@ -156,9 +165,11 @@ struct device_settings {
|
||||
unsigned int dadtransmits;
|
||||
bool multicast_to_unicast;
|
||||
unsigned int multicast_router;
|
||||
bool multicast_fast_leave;
|
||||
bool multicast;
|
||||
bool learning;
|
||||
bool unicast_flood;
|
||||
bool sendredirects;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -166,7 +177,7 @@ struct device_settings {
|
||||
* can be used to support VLANs as well
|
||||
*/
|
||||
struct device {
|
||||
const struct device_type *type;
|
||||
struct device_type *type;
|
||||
|
||||
struct avl_node avl;
|
||||
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 device_type simple_device_type;
|
||||
extern const struct device_type bridge_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;
|
||||
extern struct device_type simple_device_type;
|
||||
extern struct device_type tunnel_device_type;
|
||||
|
||||
void device_lock(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);
|
||||
void device_init_settings(struct device *dev, struct blob_attr **tb);
|
||||
void device_init_pending(void);
|
||||
|
||||
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);
|
||||
|
||||
void device_reset_config(void);
|
||||
void device_reset_old(void);
|
||||
void device_set_default_ps(bool state);
|
||||
|
||||
void device_init_virtual(struct device *dev, const struct device_type *type, const char *name);
|
||||
int device_init(struct device *iface, const struct device_type *type, const char *ifname);
|
||||
void device_init_virtual(struct device *dev, struct device_type *type, const char *name);
|
||||
int device_init(struct device *iface, struct device_type *type, const char *ifname);
|
||||
void device_cleanup(struct device *dev);
|
||||
struct device *device_find(const char *name);
|
||||
struct device *device_get(const char *name, int create);
|
||||
|
||||
@@ -30,7 +30,14 @@ static void task_complete(struct uloop_process *proc, int ret);
|
||||
static struct uloop_process task = {
|
||||
.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
|
||||
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);
|
||||
|
||||
/* no hotplug.d calls for link up */
|
||||
if (ev == IFEV_LINK_UP)
|
||||
return;
|
||||
|
||||
if (current == iface) {
|
||||
/* an event for iface is being processed */
|
||||
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)
|
||||
{
|
||||
switch (ev) {
|
||||
case IFEV_LINK_UP:
|
||||
case IFEV_UP:
|
||||
case IFEV_UPDATE:
|
||||
case IFEV_DOWN:
|
||||
interface_queue_event(iface, ev);
|
||||
break;
|
||||
case IFEV_FREE:
|
||||
case IFEV_RELOAD:
|
||||
interface_dequeue_event(iface);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ enum {
|
||||
ROUTE_SOURCE,
|
||||
ROUTE_ONLINK,
|
||||
ROUTE_TYPE,
|
||||
ROUTE_PROTO,
|
||||
__ROUTE_MAX
|
||||
};
|
||||
|
||||
@@ -54,7 +55,8 @@ static const struct blobmsg_policy route_attr[__ROUTE_MAX] = {
|
||||
[ROUTE_VALID] = { .name = "valid", .type = BLOBMSG_TYPE_INT32 },
|
||||
[ROUTE_SOURCE] = { .name = "source", .type = BLOBMSG_TYPE_STRING },
|
||||
[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 = {
|
||||
@@ -405,6 +407,14 @@ interface_ip_add_route(struct interface *iface, struct blob_attr *attr, bool v6)
|
||||
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);
|
||||
vlist_add(&ip->route, &route->node, route);
|
||||
return;
|
||||
@@ -478,10 +488,13 @@ interface_handle_subnet_route(struct interface *iface, struct device_addr *addr,
|
||||
memcpy(&r->addr, &addr->addr, sizeof(r->addr));
|
||||
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);
|
||||
|
||||
r->flags &= ~DEVADDR_KERNEL;
|
||||
r->flags &= ~DEVROUTE_PROTO;
|
||||
interface_set_route_info(iface, r);
|
||||
|
||||
system_add_route(dev, r);
|
||||
@@ -634,7 +647,7 @@ interface_update_proto_route(struct vlist_tree *tree,
|
||||
if (node_old && node_new)
|
||||
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->failed;
|
||||
(route_old->proto == route_new->proto) && !route_old->failed;
|
||||
|
||||
if (node_old) {
|
||||
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
|
||||
interface_write_resolv_conf(void)
|
||||
{
|
||||
struct interface *iface;
|
||||
char *path = alloca(strlen(resolv_conf) + 5);
|
||||
FILE *f;
|
||||
uint32_t crcold, crcnew;
|
||||
@@ -1213,21 +1286,8 @@ interface_write_resolv_conf(void)
|
||||
return;
|
||||
}
|
||||
|
||||
vlist_for_each_element(&interfaces, iface, node) {
|
||||
if (iface->state != IFS_UP)
|
||||
continue;
|
||||
__interface_write_dns_entries(f);
|
||||
|
||||
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);
|
||||
rewind(f);
|
||||
crcnew = crc32_file(f);
|
||||
|
||||
@@ -31,8 +31,8 @@ enum device_addr_flags {
|
||||
/* route overrides the default interface mtu */
|
||||
DEVROUTE_MTU = (1 << 4),
|
||||
|
||||
/* route automatically added by kernel */
|
||||
DEVADDR_KERNEL = (1 << 5),
|
||||
/* route overrides the default proto type */
|
||||
DEVROUTE_PROTO = (1 << 5),
|
||||
|
||||
/* address is off-link (no subnet-route) */
|
||||
DEVADDR_OFFLINK = (1 << 6),
|
||||
@@ -92,6 +92,7 @@ struct device_route {
|
||||
union if_addr nexthop;
|
||||
int mtu;
|
||||
unsigned int type;
|
||||
unsigned int proto;
|
||||
time_t valid_until;
|
||||
|
||||
/* must be last */
|
||||
|
||||
@@ -35,6 +35,7 @@ enum {
|
||||
IFACE_ATTR_PEERDNS,
|
||||
IFACE_ATTR_DNS,
|
||||
IFACE_ATTR_DNS_SEARCH,
|
||||
IFACE_ATTR_DNS_METRIC,
|
||||
IFACE_ATTR_METRIC,
|
||||
IFACE_ATTR_INTERFACE,
|
||||
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_DNS] = { .name = "dns", .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_IP6ASSIGN] = { .name = "ip6assign", .type = BLOBMSG_TYPE_INT32 },
|
||||
[IFACE_ATTR_IP6HINT] = { .name = "ip6hint", .type = BLOBMSG_TYPE_STRING },
|
||||
@@ -260,6 +262,7 @@ mark_interface_down(struct interface *iface)
|
||||
if (state == IFS_DOWN)
|
||||
return;
|
||||
|
||||
iface->link_up_event = false;
|
||||
iface->state = IFS_DOWN;
|
||||
if (state == IFS_UP)
|
||||
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");
|
||||
iface->link_state = new_state;
|
||||
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
|
||||
@@ -408,7 +416,8 @@ interface_l3_dev_cb(struct device_user *dep, enum device_event ev)
|
||||
|
||||
switch (ev) {
|
||||
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;
|
||||
default:
|
||||
break;
|
||||
@@ -550,8 +559,7 @@ interface_alias_cb(struct interface_user *dep, struct interface *iface, enum int
|
||||
case IFEV_FREE:
|
||||
interface_remove_user(dep);
|
||||
break;
|
||||
case IFEV_RELOAD:
|
||||
case IFEV_UPDATE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -580,6 +588,8 @@ interface_claim_device(struct interface *iface)
|
||||
if (iface->parent_iface.iface)
|
||||
interface_remove_user(&iface->parent_iface);
|
||||
|
||||
device_lock();
|
||||
|
||||
if (iface->parent_ifname) {
|
||||
parent = vlist_find(&interfaces, iface->parent_ifname, parent, node);
|
||||
iface->parent_iface.cb = interface_alias_cb;
|
||||
@@ -595,6 +605,8 @@ interface_claim_device(struct interface *iface)
|
||||
if (dev)
|
||||
interface_set_main_dev(iface, dev);
|
||||
|
||||
device_unlock();
|
||||
|
||||
if (iface->proto_handler->flags & PROTO_FLAG_INIT_AVAILABLE)
|
||||
interface_set_available(iface, true);
|
||||
}
|
||||
@@ -681,7 +693,8 @@ interface_proto_event_cb(struct interface_proto_state *state, enum interface_pro
|
||||
switch (ev) {
|
||||
case IFPEV_UP:
|
||||
if (iface->state != IFS_SETUP) {
|
||||
interface_event(iface, IFEV_UPDATE);
|
||||
if (iface->state == IFS_UP && iface->updated)
|
||||
interface_event(iface, IFEV_UPDATE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -785,6 +798,9 @@ interface_alloc(const char *name, struct blob_attr *config)
|
||||
if ((cur = tb[IFACE_ATTR_DNS_SEARCH]))
|
||||
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]))
|
||||
iface->metric = blobmsg_get_u32(cur);
|
||||
|
||||
@@ -1076,10 +1092,12 @@ set_config_state(struct interface *iface, enum interface_config_state s)
|
||||
}
|
||||
|
||||
void
|
||||
interface_update_start(struct interface *iface)
|
||||
interface_update_start(struct interface *iface, const bool keep_old)
|
||||
{
|
||||
iface->updated = 0;
|
||||
interface_ip_update_start(&iface->proto_ip);
|
||||
|
||||
if (!keep_old)
|
||||
interface_ip_update_start(&iface->proto_ip);
|
||||
}
|
||||
|
||||
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->proto_handler = if_new->proto_handler;
|
||||
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;
|
||||
interface_replace_dns(&if_old->config_ip, &if_new->config_ip);
|
||||
|
||||
@@ -26,6 +26,7 @@ enum interface_event {
|
||||
IFEV_UPDATE,
|
||||
IFEV_FREE,
|
||||
IFEV_RELOAD,
|
||||
IFEV_LINK_UP,
|
||||
};
|
||||
|
||||
enum interface_state {
|
||||
@@ -113,6 +114,7 @@ struct interface {
|
||||
bool force_link;
|
||||
bool dynamic;
|
||||
bool policy_rules_set;
|
||||
bool link_up_event;
|
||||
|
||||
time_t start_time;
|
||||
enum interface_state state;
|
||||
@@ -143,6 +145,7 @@ struct interface {
|
||||
struct vlist_tree host_routes;
|
||||
|
||||
int metric;
|
||||
int dns_metric;
|
||||
unsigned int ip4table;
|
||||
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_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_start_pending(void);
|
||||
|
||||
@@ -228,7 +228,8 @@ macvlan_reload(struct device *dev, struct blob_attr *attr)
|
||||
}
|
||||
|
||||
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 device *dev = NULL;
|
||||
@@ -238,7 +239,7 @@ macvlan_create(const char *name, struct blob_attr *attr)
|
||||
return NULL;
|
||||
|
||||
dev = &mvdev->dev;
|
||||
device_init(dev, &macvlan_device_type, name);
|
||||
device_init(dev, devtype, name);
|
||||
dev->config_pending = true;
|
||||
|
||||
mvdev->set_state = dev->set_state;
|
||||
@@ -252,8 +253,8 @@ macvlan_create(const char *name, struct blob_attr *attr)
|
||||
return dev;
|
||||
}
|
||||
|
||||
const struct device_type macvlan_device_type = {
|
||||
.name = "MAC VLAN",
|
||||
static struct device_type macvlan_device_type = {
|
||||
.name = "macvlan",
|
||||
.config_params = &macvlan_attr_list,
|
||||
.create = macvlan_create,
|
||||
.config_init = macvlan_config_init,
|
||||
@@ -261,3 +262,8 @@ const struct device_type macvlan_device_type = {
|
||||
.free = macvlan_free,
|
||||
.dump_info = macvlan_dump_info,
|
||||
};
|
||||
|
||||
static void __init macvlan_device_type_init(void)
|
||||
{
|
||||
device_type_add(&macvlan_device_type);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <libubox/ustream.h>
|
||||
#include <libubox/utils.h>
|
||||
|
||||
#include <ubus/libubus.h>
|
||||
#include <libubus.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@ struct proto_shell_handler {
|
||||
char *config_buf;
|
||||
char *script_name;
|
||||
bool init_available;
|
||||
bool no_proto_task;
|
||||
|
||||
struct uci_blob_param_list config;
|
||||
};
|
||||
@@ -306,7 +305,7 @@ proto_shell_task_finish(struct proto_shell_state *state,
|
||||
if (state->renew_pending)
|
||||
proto_shell_handler(&state->proto,
|
||||
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->sm == S_SETUP)
|
||||
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;
|
||||
|
||||
device_set_present(dev, true);
|
||||
|
||||
interface_update_start(iface);
|
||||
}
|
||||
|
||||
interface_update_start(iface, keep);
|
||||
|
||||
proto_apply_ip_settings(iface, data, addr_ext);
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -892,7 +890,8 @@ proto_shell_add_handler(const char *script, const char *name, json_object *obj)
|
||||
handler->proto.flags |= PROTO_FLAG_NODEV;
|
||||
|
||||
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);
|
||||
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))
|
||||
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);
|
||||
if (config)
|
||||
handler->config_buf = netifd_handler_parse_config(&handler->config, config);
|
||||
|
||||
@@ -36,6 +36,7 @@ enum {
|
||||
OPT_GATEWAY,
|
||||
OPT_IP6GW,
|
||||
OPT_IP6PREFIX,
|
||||
OPT_IP6DEPRECATED,
|
||||
__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_IP6GW] = { .name = "ip6gw", .type = BLOBMSG_TYPE_STRING },
|
||||
[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] = {
|
||||
@@ -113,7 +115,7 @@ alloc_device_addr(bool v6, bool ext)
|
||||
|
||||
static bool
|
||||
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;
|
||||
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;
|
||||
|
||||
addr->mask = mask;
|
||||
if (!parse_ip_and_netmask(af, str, &addr->addr, &addr->mask)) {
|
||||
interface_add_error(iface, "proto", "INVALID_ADDRESS", &str, 1);
|
||||
free(addr);
|
||||
return false;
|
||||
}
|
||||
if (!parse_ip_and_netmask(af, str, &addr->addr, &addr->mask))
|
||||
goto error;
|
||||
|
||||
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)
|
||||
addr->broadcast = broadcast;
|
||||
|
||||
if (deprecated)
|
||||
addr->preferred_until = system_get_rtime();
|
||||
|
||||
vlist_add(&iface->proto_ip.addr, &addr->node, &addr->flags);
|
||||
return true;
|
||||
|
||||
error:
|
||||
interface_add_error(iface, "proto", "INVALID_ADDRESS", &str, 1);
|
||||
free(addr);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
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;
|
||||
int n_addr = 0;
|
||||
@@ -150,7 +166,7 @@ parse_static_address_option(struct interface *iface, struct blob_attr *attr,
|
||||
|
||||
n_addr++;
|
||||
if (!parse_addr(iface, blobmsg_data(cur), v6, netmask, ext,
|
||||
broadcast))
|
||||
broadcast, deprecated))
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -390,6 +406,7 @@ proto_apply_static_ip_settings(struct interface *iface, struct blob_attr *attr)
|
||||
struct blob_attr *cur;
|
||||
const char *error;
|
||||
unsigned int netmask = 32;
|
||||
bool ip6deprecated;
|
||||
int n_v4 = 0, n_v6 = 0;
|
||||
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]))
|
||||
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]))
|
||||
n_v6 = parse_static_address_option(iface, cur, true,
|
||||
128, false, 0);
|
||||
128, false, 0, ip6deprecated);
|
||||
|
||||
if ((cur = tb[OPT_IP6PREFIX]))
|
||||
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_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, "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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ enum {
|
||||
PROTO_FLAG_RENEW_AVAILABLE = (1 << 3),
|
||||
PROTO_FLAG_FORCE_LINK_DEFAULT = (1 << 4),
|
||||
PROTO_FLAG_LASTERROR = (1 << 5),
|
||||
PROTO_FLAG_TEARDOWN_ON_L3_LINK_DOWN = (1 << 6),
|
||||
PROTO_FLAG_NO_TASK = (1 << 7),
|
||||
};
|
||||
|
||||
struct interface_proto_state {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
NETIFD_MAIN_DIR="${NETIFD_MAIN_DIR:-/lib/netifd}"
|
||||
PROTO_DEFAULT_OPTIONS="defaultroute peerdns metric"
|
||||
|
||||
. /usr/share/libubox/jshn.sh
|
||||
. $NETIFD_MAIN_DIR/utils.sh
|
||||
@@ -15,6 +16,18 @@ proto_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() {
|
||||
json_load "$data"
|
||||
eval "proto_$1_teardown \"$interface\" \"$ifname\""
|
||||
@@ -365,6 +378,7 @@ init_proto() {
|
||||
no_proto_task=0
|
||||
available=0
|
||||
renew_handler=0
|
||||
teardown_on_l3_link_down=0
|
||||
|
||||
add_default_handler "proto_$1_init_config"
|
||||
|
||||
@@ -378,6 +392,7 @@ init_proto() {
|
||||
json_add_boolean available "$available"
|
||||
json_add_boolean renew-handler "$renew_handler"
|
||||
json_add_boolean lasterror "$lasterror"
|
||||
json_add_boolean teardown-on-l3-link-down "$teardown_on_l3_link_down"
|
||||
json_dump
|
||||
}
|
||||
;;
|
||||
|
||||
@@ -202,6 +202,12 @@ bool system_resolve_rt_type(const char *type, unsigned int *id)
|
||||
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)
|
||||
{
|
||||
*id = 0;
|
||||
|
||||
@@ -52,7 +52,6 @@
|
||||
#define IFA_FLAGS (IFA_MULTICAST + 1)
|
||||
#endif
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
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 &&
|
||||
!dev->settings.learning)
|
||||
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->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
|
||||
@@ -1384,6 +1408,8 @@ system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned
|
||||
!s->multicast ? IFF_MULTICAST : 0) < 0)
|
||||
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);
|
||||
}
|
||||
@@ -1755,7 +1781,7 @@ static int system_rt(struct device *dev, struct device_route *route, int cmd)
|
||||
.rtm_dst_len = route->mask,
|
||||
.rtm_src_len = route->sourcemask,
|
||||
.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_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
|
||||
.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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
uint16_t iflags = 0, oflags = 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);
|
||||
if (!nlm)
|
||||
@@ -2146,8 +2211,6 @@ static int system_add_gre_tunnel(const char *name, const char *kind,
|
||||
if ((cur = tb[TUNNEL_ATTR_TTL]))
|
||||
ttl = blobmsg_get_u32(cur);
|
||||
|
||||
nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
|
||||
|
||||
if ((cur = tb[TUNNEL_ATTR_TOS])) {
|
||||
char *str = blobmsg_get_string(cur);
|
||||
if (strcmp(str, "inherit")) {
|
||||
@@ -2221,6 +2284,9 @@ static int system_add_gre_tunnel(const char *name, const char *kind,
|
||||
|
||||
if (flags)
|
||||
nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
|
||||
|
||||
if (!ttl)
|
||||
ttl = 64;
|
||||
} else {
|
||||
struct in_addr inbuf;
|
||||
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]))
|
||||
set_df = blobmsg_get_bool(cur);
|
||||
|
||||
/* ttl !=0 and nopmtudisc are incompatible */
|
||||
if (ttl && !set_df) {
|
||||
ret = -EINVAL;
|
||||
goto failure;
|
||||
}
|
||||
if (!set_df) {
|
||||
/* ttl != 0 and nopmtudisc are incompatible */
|
||||
if (ttl) {
|
||||
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_TOS, tos);
|
||||
}
|
||||
|
||||
if (ttl)
|
||||
nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
|
||||
|
||||
if (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;
|
||||
char buf[64];
|
||||
int fd;
|
||||
|
||||
snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
|
||||
dev->ifname);
|
||||
|
||||
int fd = open(buf, O_RDWR);
|
||||
fd = open(buf, O_RDWR);
|
||||
if (fd < 0)
|
||||
return ret;
|
||||
|
||||
if (!mtu) {
|
||||
ssize_t len = read(fd, buf, sizeof(buf) - 1);
|
||||
|
||||
@@ -146,6 +146,7 @@ int system_del_route(struct device *dev, struct device_route *route);
|
||||
int system_flush_routes(void);
|
||||
|
||||
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_is_default_rt_table(unsigned int id);
|
||||
bool system_resolve_rpfilter(const char *filter, unsigned int *id);
|
||||
|
||||
@@ -61,7 +61,8 @@ tunnel_reload(struct device *dev, struct blob_attr *attr)
|
||||
}
|
||||
|
||||
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 device *dev;
|
||||
@@ -71,10 +72,10 @@ tunnel_create(const char *name, struct blob_attr *attr)
|
||||
return NULL;
|
||||
|
||||
dev = &tun->dev;
|
||||
device_init(dev, &tunnel_device_type, name);
|
||||
device_init(dev, devtype, name);
|
||||
tun->set_state = dev->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);
|
||||
|
||||
return dev;
|
||||
@@ -88,12 +89,15 @@ tunnel_free(struct device *dev)
|
||||
free(tun);
|
||||
}
|
||||
|
||||
const struct device_type tunnel_device_type = {
|
||||
.name = "IP tunnel",
|
||||
struct device_type tunnel_device_type = {
|
||||
.name = "tunnel",
|
||||
.config_params = &tunnel_attr_list,
|
||||
.reload = tunnel_reload,
|
||||
.create = tunnel_create,
|
||||
.free = tunnel_free,
|
||||
};
|
||||
|
||||
|
||||
static void __init tunnel_device_type_init(void)
|
||||
{
|
||||
device_type_add(&tunnel_device_type);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
if (tb[DEV_NAME]) {
|
||||
dev = device_get(blobmsg_data(tb[DEV_NAME]), false);
|
||||
dev = device_find(blobmsg_data(tb[DEV_NAME]));
|
||||
if (!dev)
|
||||
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)
|
||||
blobmsg_add_u32(&b, "type", route->type);
|
||||
|
||||
if (route->flags & DEVROUTE_PROTO)
|
||||
blobmsg_add_u32(&b, "proto", route->proto);
|
||||
|
||||
if (route->flags & DEVROUTE_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)
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
interface_ip_dump_dns_server_list(struct interface_ip_settings *ip,
|
||||
bool enabled)
|
||||
@@ -685,8 +697,9 @@ netifd_dump_status(struct interface *iface)
|
||||
if (iface->ip4table)
|
||||
blobmsg_add_u32(&b, "ip4table", iface->ip4table);
|
||||
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, "dns_metric", iface->dns_metric);
|
||||
blobmsg_add_u8(&b, "delegation", !iface->proto_ip.no_delegation);
|
||||
a = blobmsg_open_array(&b, "ipv4-address");
|
||||
interface_ip_dump_address_list(&iface->config_ip, false, true);
|
||||
|
||||
@@ -119,7 +119,6 @@ int
|
||||
parse_ip_and_netmask(int af, const char *str, void *addr, unsigned int *netmask)
|
||||
{
|
||||
char *astr = alloca(strlen(str) + 1);
|
||||
int ret = 0;
|
||||
|
||||
strcpy(astr, str);
|
||||
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;
|
||||
}
|
||||
|
||||
ret = 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;
|
||||
return inet_pton(af, astr, addr);
|
||||
}
|
||||
|
||||
char *
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <uci/uci_blob.h>
|
||||
#include <uci_blob.h>
|
||||
#include <libubox/list.h>
|
||||
#include <libubox/avl.h>
|
||||
#include <libubox/avl-cmp.h>
|
||||
|
||||
@@ -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 const struct device_type vlan_type = {
|
||||
static struct device_type vlan_type = {
|
||||
.name = "VLAN",
|
||||
.config_params = &device_attr_list,
|
||||
.free = free_vlan_if,
|
||||
|
||||
@@ -20,14 +20,12 @@
|
||||
#include "system.h"
|
||||
|
||||
enum {
|
||||
VLANDEV_ATTR_TYPE,
|
||||
VLANDEV_ATTR_IFNAME,
|
||||
VLANDEV_ATTR_VID,
|
||||
__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_VID] = { "vid", BLOBMSG_TYPE_INT32 },
|
||||
};
|
||||
@@ -40,6 +38,8 @@ static const struct uci_blob_param_list vlandev_attr_list = {
|
||||
.next = { &device_attr_list },
|
||||
};
|
||||
|
||||
static struct device_type vlan8021q_device_type;
|
||||
|
||||
struct vlandev_device {
|
||||
struct device dev;
|
||||
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 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;
|
||||
|
||||
if ((cur = tb[VLANDEV_ATTR_TYPE]))
|
||||
{
|
||||
if(!strcmp(blobmsg_data(cur), "8021ad"))
|
||||
cfg->proto = VLAN_PROTO_8021AD;
|
||||
}
|
||||
|
||||
if ((cur = tb[VLANDEV_ATTR_VID]))
|
||||
cfg->vid = (uint16_t) blobmsg_get_u32(cur);
|
||||
}
|
||||
@@ -216,7 +211,8 @@ vlandev_reload(struct device *dev, struct blob_attr *attr)
|
||||
}
|
||||
|
||||
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 device *dev = NULL;
|
||||
@@ -226,7 +222,7 @@ vlandev_create(const char *name, struct blob_attr *attr)
|
||||
return NULL;
|
||||
|
||||
dev = &mvdev->dev;
|
||||
device_init(dev, &vlandev_device_type, name);
|
||||
device_init(dev, devtype, name);
|
||||
dev->config_pending = true;
|
||||
|
||||
mvdev->set_state = dev->set_state;
|
||||
@@ -240,8 +236,8 @@ vlandev_create(const char *name, struct blob_attr *attr)
|
||||
return dev;
|
||||
}
|
||||
|
||||
const struct device_type vlandev_device_type = {
|
||||
.name = "VLANDEV",
|
||||
static struct device_type vlan8021ad_device_type = {
|
||||
.name = "8021ad",
|
||||
.config_params = &vlandev_attr_list,
|
||||
.create = vlandev_create,
|
||||
.config_init = vlandev_config_init,
|
||||
@@ -249,3 +245,19 @@ const struct device_type vlandev_device_type = {
|
||||
.free = vlandev_free,
|
||||
.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);
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ vif_config_add_bridge(struct blob_buf *buf, struct blob_attr *networks, bool pre
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
if (dev->type != &bridge_device_type)
|
||||
if (!dev->type->bridge_capability)
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -287,6 +287,12 @@ __wireless_device_set_up(struct wireless_device *wdev)
|
||||
if (wdev->disabled)
|
||||
return;
|
||||
|
||||
if (wdev->retry_setup_failed)
|
||||
return;
|
||||
|
||||
if (!wdev->autostart)
|
||||
return;
|
||||
|
||||
if (wdev->state != IFS_DOWN || config_init)
|
||||
return;
|
||||
|
||||
@@ -314,9 +320,9 @@ wdev_handle_config_change(struct wireless_device *wdev)
|
||||
switch(state) {
|
||||
case IFC_NORMAL:
|
||||
case IFC_RELOAD:
|
||||
__wireless_device_set_up(wdev);
|
||||
|
||||
wdev->config_state = IFC_NORMAL;
|
||||
if (wdev->autostart)
|
||||
__wireless_device_set_up(wdev);
|
||||
break;
|
||||
case IFC_REMOVE:
|
||||
wireless_device_free(wdev);
|
||||
@@ -399,7 +405,7 @@ wireless_device_retry_setup(struct wireless_device *wdev)
|
||||
return;
|
||||
|
||||
if (--wdev->retry < 0)
|
||||
wdev->autostart = false;
|
||||
wdev->retry_setup_failed = true;
|
||||
|
||||
__wireless_device_set_down(wdev);
|
||||
}
|
||||
@@ -424,6 +430,7 @@ wireless_device_script_task_cb(struct netifd_process *proc, int ret)
|
||||
void
|
||||
wireless_device_set_down(struct wireless_device *wdev)
|
||||
{
|
||||
wdev->retry_setup_failed = false;
|
||||
wdev->autostart = false;
|
||||
__wireless_device_set_down(wdev);
|
||||
}
|
||||
@@ -467,6 +474,7 @@ wdev_change_config(struct wireless_device *wdev, struct wireless_device *wd_new)
|
||||
free(wdev->config);
|
||||
wdev->config = blob_memdup(new_config);
|
||||
wdev->disabled = disabled;
|
||||
wdev->retry_setup_failed = false;
|
||||
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);
|
||||
} else if (vif_old) {
|
||||
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(vif_old->config);
|
||||
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->name = strcpy(name_buf, name);
|
||||
wdev->config = data;
|
||||
wdev->config_autostart = true;
|
||||
wdev->autostart = wdev->config_autostart;
|
||||
wdev->retry_setup_failed = false;
|
||||
wdev->autostart = true;
|
||||
INIT_LIST_HEAD(&wdev->script_proc);
|
||||
vlist_init(&wdev->interfaces, avl_strcmp, vif_update);
|
||||
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, "autostart", wdev->autostart);
|
||||
blobmsg_add_u8(b, "disabled", wdev->disabled);
|
||||
blobmsg_add_u8(b, "retry_setup_failed", wdev->retry_setup_failed);
|
||||
put_container(b, wdev->config, "config");
|
||||
|
||||
i = blobmsg_open_array(b, "interfaces");
|
||||
@@ -991,6 +1001,5 @@ wireless_start_pending(void)
|
||||
struct wireless_device *wdev;
|
||||
|
||||
vlist_for_each_element(&wireless_devices, wdev, node)
|
||||
if (wdev->autostart)
|
||||
__wireless_device_set_up(wdev);
|
||||
__wireless_device_set_up(wdev);
|
||||
}
|
||||
|
||||
@@ -53,9 +53,9 @@ struct wireless_device {
|
||||
struct blob_attr *config;
|
||||
struct blob_attr *data;
|
||||
|
||||
bool config_autostart;
|
||||
bool autostart;
|
||||
bool disabled;
|
||||
bool retry_setup_failed;
|
||||
|
||||
enum interface_state state;
|
||||
enum interface_config_state config_state;
|
||||
|
||||
Reference in New Issue
Block a user