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_METHOD = local

View File

@@ -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

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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,6 +416,7 @@ interface_l3_dev_cb(struct device_user *dep, enum device_event ev)
switch (ev) {
case DEV_EVENT_LINK_DOWN:
if (iface->proto_handler->flags & PROTO_FLAG_TEARDOWN_ON_L3_LINK_DOWN)
interface_proto_event(iface->proto, PROTO_CMD_TEARDOWN, false);
break;
default:
@@ -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,6 +693,7 @@ interface_proto_event_cb(struct interface_proto_state *state, enum interface_pro
switch (ev) {
case IFPEV_UP:
if (iface->state != IFS_SETUP) {
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,9 +1092,11 @@ 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;
if (!keep_old)
interface_ip_update_start(&iface->proto_ip);
}
@@ -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);

View File

@@ -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);

View File

@@ -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);
}

View File

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

View File

@@ -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,7 +562,6 @@ 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->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);

View File

@@ -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);
}
}

View File

@@ -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 {

View File

@@ -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
}
;;

View File

@@ -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;

View File

@@ -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);
if (!set_df) {
/* ttl != 0 and nopmtudisc are incompatible */
if (ttl && !set_df) {
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);

View File

@@ -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);

View File

@@ -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);
}

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));
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)
@@ -687,6 +699,7 @@ netifd_dump_status(struct interface *iface)
if (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);

View File

@@ -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 *

View File

@@ -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>

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 const struct device_type vlan_type = {
static struct device_type vlan_type = {
.name = "VLAN",
.config_params = &device_attr_list,
.free = free_vlan_if,

View File

@@ -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);
}

View File

@@ -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:
wdev->config_state = IFC_NORMAL;
if (wdev->autostart)
__wireless_device_set_up(wdev);
wdev->config_state = IFC_NORMAL;
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);
}

View File

@@ -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;