1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
/*
* netifd - network interface daemon
* Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "netifd.h"
#include "device.h"
#include "config.h"
#include "system.h"
struct tunnel {
struct device dev;
device_state_cb set_state;
};
static int
tunnel_set_state(struct device *dev, bool up)
{
struct tunnel *tun = container_of(dev, struct tunnel, dev);
int ret;
if (up) {
ret = system_add_ip_tunnel(dev->ifname, dev->config);
if (ret != 0)
return ret;
}
ret = tun->set_state(dev, up);
if (ret || !up)
system_del_ip_tunnel(dev->ifname, dev->config);
return ret;
}
static enum dev_change_type
tunnel_reload(struct device *dev, struct blob_attr *attr)
{
struct blob_attr *tb_dev[__DEV_ATTR_MAX];
const struct uci_blob_param_list *cfg = dev->type->config_params;
if (uci_blob_check_equal(dev->config, attr, cfg))
return DEV_CONFIG_NO_CHANGE;
memset(tb_dev, 0, sizeof(tb_dev));
if (attr)
blobmsg_parse(device_attr_list.params, __DEV_ATTR_MAX, tb_dev,
blob_data(attr), blob_len(attr));
device_init_settings(dev, tb_dev);
return DEV_CONFIG_RESTART;
}
static struct device *
tunnel_create(const char *name, struct device_type *devtype,
struct blob_attr *attr)
{
struct tunnel *tun;
struct device *dev;
tun = calloc(1, sizeof(*tun));
if (!tun)
return NULL;
dev = &tun->dev;
if (device_init(dev, devtype, name) < 0) {
device_cleanup(dev);
free(tun);
return NULL;
}
tun->set_state = dev->set_state;
dev->set_state = tunnel_set_state;
device_apply_config(dev, devtype, attr);
device_set_present(dev, true);
return dev;
}
static void
tunnel_free(struct device *dev)
{
struct tunnel *tun = container_of(dev, struct tunnel, dev);
free(tun);
}
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);
}
|