From: Marcus Folkesson <[email protected]>

Support for multiple VLANs binded to the same interface.
VLAN services appear as:
        vlan_<MAC to bounded IF>_<VLAN IFNAME>
For example:
        vlan_5c260a4bf6a3_vlan3

Signed-off-by: Marcus Folkesson <[email protected]>
---
 Makefile.plugins  |   5 +
 README            |   8 ++
 configure.ac      |   5 +
 include/device.h  |   1 +
 include/network.h |   1 +
 include/service.h |   3 +-
 plugins/vlan.c    | 369 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/config.c      |   1 +
 src/detect.c      |   1 +
 src/device.c      |  10 ++
 src/network.c     |   7 ++
 src/notifier.c    |   2 +
 src/rfkill.c      |   1 +
 src/rtnl.c        |   3 +
 src/service.c     |  27 +++-
 src/session.c     |   2 +
 src/technology.c  |   4 +
 src/wispr.c       |   1 +
 18 files changed, 448 insertions(+), 3 deletions(-)
 create mode 100644 plugins/vlan.c

diff --git a/Makefile.plugins b/Makefile.plugins
index e90ad19..590f89e 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -13,6 +13,11 @@ builtin_modules += ethernet
 builtin_sources += plugins/ethernet.c
 endif
 
+if VLAN
+builtin_modules += vlan
+builtin_sources += plugins/vlan.c
+endif
+
 if GADGET
 builtin_modules += gadget
 builtin_sources += plugins/gadget.c
diff --git a/README b/README
index 531f396..c505fd9 100644
--- a/README
+++ b/README
@@ -71,6 +71,14 @@ For a working system, certain configuration options need to 
be enabled:
                enabled. This option can be used to build a small daemon
                for a specific system if Ethernet support is not required.
 
+       --disable-vlan
+
+               Disable support for VLAN on Ethernet and/or WiFi interfaces
+
+               By default VLAN technology support is built-in and
+               enabled. This option can be used to build a small daemon
+               for a specific system if VLAN support is not required.
+
        --disable-gadget
 
                Disable support for USB Ethernet Gadget devices
diff --git a/configure.ac b/configure.ac
index dd4b271..80655ef 100644
--- a/configure.ac
+++ b/configure.ac
@@ -291,6 +291,11 @@ AC_ARG_ENABLE(gadget, AC_HELP_STRING([--disable-gadget],
                                        [enable_gadget=${enableval}])
 AM_CONDITIONAL(GADGET, test "${enable_gadget}" != "no")
 
+AC_ARG_ENABLE(vlan, AC_HELP_STRING([--disable-vlan],
+                               [disable VLAN support]),
+                                       [enable_vlan=${enableval}])
+AM_CONDITIONAL(VLAN, test "${enable_vlan}" != "no")
+
 AC_ARG_ENABLE(wifi, AC_HELP_STRING([--disable-wifi],
                                [disable WiFi support]),
                                        [enable_wifi=${enableval}])
diff --git a/include/device.h b/include/device.h
index 57b925c..cd734b3 100644
--- a/include/device.h
+++ b/include/device.h
@@ -43,6 +43,7 @@ enum connman_device_type {
        CONNMAN_DEVICE_TYPE_CELLULAR  = 4,
        CONNMAN_DEVICE_TYPE_GPS       = 5,
        CONNMAN_DEVICE_TYPE_GADGET    = 6,
+       CONNMAN_DEVICE_TYPE_VLAN          = 7,
        CONNMAN_DEVICE_TYPE_VENDOR    = 10000,
 };
 
diff --git a/include/network.h b/include/network.h
index d772699..5212b6f 100644
--- a/include/network.h
+++ b/include/network.h
@@ -46,6 +46,7 @@ enum connman_network_type {
        CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN = 9,
        CONNMAN_NETWORK_TYPE_CELLULAR      = 10,
        CONNMAN_NETWORK_TYPE_GADGET        = 11,
+       CONNMAN_NETWORK_TYPE_VLAN              = 12,
        CONNMAN_NETWORK_TYPE_VENDOR        = 10000,
 };
 
diff --git a/include/service.h b/include/service.h
index 31dfce7..36786e6 100644
--- a/include/service.h
+++ b/include/service.h
@@ -45,8 +45,9 @@ enum connman_service_type {
        CONNMAN_SERVICE_TYPE_VPN       = 7,
        CONNMAN_SERVICE_TYPE_GADGET    = 8,
        CONNMAN_SERVICE_TYPE_P2P       = 9,
+       CONNMAN_SERVICE_TYPE_VLAN       = 10,
 };
-#define        MAX_CONNMAN_SERVICE_TYPES        10
+#define        MAX_CONNMAN_SERVICE_TYPES        11
 
 
 enum connman_service_security {
diff --git a/plugins/vlan.c b/plugins/vlan.c
new file mode 100644
index 0000000..679f92d
--- /dev/null
+++ b/plugins/vlan.c
@@ -0,0 +1,369 @@
+/*
+ *
+*  Connection Manager
+ *
+ *  Copyright (C) 2015  Marcus Folkesson <[email protected]>
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <net/if.h>
+
+#ifndef IFF_LOWER_UP
+#define IFF_LOWER_UP   0x10000
+#endif
+
+#include <glib.h>
+
+#define CONNMAN_API_SUBJECT_TO_CHANGE
+#include <connman/technology.h>
+#include <connman/plugin.h>
+#include <connman/device.h>
+#include <connman/inet.h>
+#include <connman/rtnl.h>
+#include <connman/log.h>
+#include <connman/setting.h>
+
+static bool vlan_tethering = false;
+
+struct ethernet_data {
+       int index;
+       unsigned flags;
+       unsigned int watch;
+       struct connman_network *network;
+};
+
+static int vlan_network_probe(struct connman_network *network)
+{
+       DBG("network %p", network);
+
+       return 0;
+}
+
+static void vlan_network_remove(struct connman_network *network)
+{
+       DBG("network %p", network);
+}
+
+static int vlan_network_connect(struct connman_network *network)
+{
+       DBG("network %p", network);
+
+       connman_network_set_connected(network, true);
+
+       return 0;
+}
+
+static int vlan_network_disconnect(struct connman_network *network)
+{
+       DBG("network %p", network);
+
+       connman_network_set_connected(network, false);
+
+       return 0;
+}
+
+static struct connman_network_driver vlan_network_driver = {
+       .name           = "vlan",
+       .type           = CONNMAN_NETWORK_TYPE_VLAN,
+       .probe          = vlan_network_probe,
+       .remove         = vlan_network_remove,
+       .connect        = vlan_network_connect,
+       .disconnect     = vlan_network_disconnect,
+};
+
+static void add_network(struct connman_device *device,
+                       struct ethernet_data *ethernet)
+{
+       struct connman_network *network;
+       int index;
+
+       network = connman_network_create("vlan",
+                                       CONNMAN_NETWORK_TYPE_VLAN);
+       if (!network)
+               return;
+
+       index = connman_device_get_index(device);
+       connman_network_set_index(network, index);
+
+       connman_network_set_name(network, "VLAN");
+
+       if (connman_device_add_network(device, network) < 0) {
+               connman_network_unref(network);
+               return;
+       }
+
+       if (!vlan_tethering)
+               /*
+                * Prevent service from starting the reconnect
+                * procedure as we do not want the DHCP client
+                * to run when tethering.
+                */
+               connman_network_set_group(network, 
connman_device_get_string(device, "Interface"));
+
+       ethernet->network = network;
+}
+
+static void remove_network(struct connman_device *device,
+                               struct ethernet_data *ethernet)
+{
+       if (!ethernet->network)
+               return;
+
+       connman_device_remove_network(device, ethernet->network);
+       connman_network_unref(ethernet->network);
+
+       ethernet->network = NULL;
+}
+
+static void ethernet_newlink(unsigned flags, unsigned change, void *user_data)
+{
+       struct connman_device *device = user_data;
+       struct ethernet_data *ethernet = connman_device_get_data(device);
+
+       DBG("index %d flags %d change %d", ethernet->index, flags, change);
+
+       if ((ethernet->flags & IFF_UP) != (flags & IFF_UP)) {
+               if (flags & IFF_UP) {
+                       DBG("power on");
+                       connman_device_set_powered(device, true);
+               } else {
+                       DBG("power off");
+                       connman_device_set_powered(device, false);
+               }
+       }
+
+       if ((ethernet->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
+               if (flags & IFF_LOWER_UP) {
+                       DBG("carrier on");
+                       add_network(device, ethernet);
+               } else {
+                       DBG("carrier off");
+                       remove_network(device, ethernet);
+               }
+       }
+
+       ethernet->flags = flags;
+}
+
+static int vlan_dev_probe(struct connman_device *device)
+{
+       struct ethernet_data *ethernet;
+
+       DBG("device %p", device);
+
+       ethernet = g_try_new0(struct ethernet_data, 1);
+       if (!ethernet)
+               return -ENOMEM;
+
+       connman_device_set_data(device, ethernet);
+
+       ethernet->index = connman_device_get_index(device);
+       ethernet->flags = 0;
+
+       ethernet->watch = connman_rtnl_add_newlink_watch(ethernet->index,
+                                               ethernet_newlink, device);
+
+       return 0;
+}
+
+static void vlan_dev_remove(struct connman_device *device)
+{
+       struct ethernet_data *ethernet = connman_device_get_data(device);
+
+       DBG("device %p", device);
+
+       connman_device_set_data(device, NULL);
+
+       connman_rtnl_remove_watch(ethernet->watch);
+
+       remove_network(device, ethernet);
+
+       g_free(ethernet);
+}
+
+static int vlan_dev_enable(struct connman_device *device)
+{
+       struct ethernet_data *ethernet = connman_device_get_data(device);
+
+       DBG("device %p", device);
+
+       return connman_inet_ifup(ethernet->index);
+}
+
+static int vlan_dev_disable(struct connman_device *device)
+{
+       struct ethernet_data *ethernet = connman_device_get_data(device);
+
+       DBG("device %p", device);
+
+       return connman_inet_ifdown(ethernet->index);
+}
+
+static struct connman_device_driver vlan_dev_driver = {
+       .name           = "vlan",
+       .type           = CONNMAN_DEVICE_TYPE_VLAN,
+       .probe          = vlan_dev_probe,
+       .remove         = vlan_dev_remove,
+       .enable         = vlan_dev_enable,
+       .disable        = vlan_dev_disable,
+};
+
+static int vlan_tech_probe(struct connman_technology *technology)
+{
+       return 0;
+}
+
+static void vlan_tech_remove(struct connman_technology *technology)
+{
+       DBG("");
+}
+
+static GList *vlan_interface_list = NULL;
+
+static void vlan_tech_add_interface(struct connman_technology *technology,
+                       int index, const char *name, const char *ident)
+{
+       DBG("index %d name %s ident %s", index, name, ident);
+
+       if (g_list_find(vlan_interface_list, GINT_TO_POINTER((int)index)))
+               return;
+
+       vlan_interface_list = g_list_prepend(vlan_interface_list,
+                                       (GINT_TO_POINTER((int) index)));
+}
+
+static void vlan_tech_remove_interface(struct connman_technology *technology,
+                                                               int index)
+{
+       DBG("index %d", index);
+
+       vlan_interface_list = g_list_remove(vlan_interface_list,
+                                       GINT_TO_POINTER((int) index));
+}
+
+static void vlan_tech_enable_tethering(struct connman_technology *technology,
+                                               const char *bridge)
+{
+       GList *list;
+       struct ethernet_data *ethernet;
+
+       for (list = vlan_interface_list; list; list = list->next) {
+               int index = GPOINTER_TO_INT(list->data);
+               struct connman_device *device =
+                       connman_device_find_by_index(index);
+
+               if (device) {
+                       ethernet = connman_device_get_data(device);
+                       if (ethernet)
+                               remove_network(device, ethernet);
+               }
+
+               connman_technology_tethering_notify(technology, true);
+
+               connman_inet_ifup(index);
+
+               connman_inet_add_to_bridge(index, bridge);
+
+               vlan_tethering = true;
+       }
+}
+
+static void vlan_tech_disable_tethering(struct connman_technology *technology,
+                                               const char *bridge)
+{
+       GList *list;
+
+       for (list = vlan_interface_list; list; list = list->next) {
+               int index = GPOINTER_TO_INT(list->data);
+               struct connman_device *device =
+                       connman_device_find_by_index(index);
+
+               connman_inet_remove_from_bridge(index, bridge);
+
+               connman_technology_tethering_notify(technology, false);
+
+               if (device)
+                       connman_device_reconnect_service(device);
+
+               vlan_tethering = false;
+       }
+}
+
+static int vlan_tech_set_tethering(struct connman_technology *technology,
+                               const char *identifier, const char *passphrase,
+                               const char *bridge, bool enabled)
+{
+       if (!connman_technology_is_tethering_allowed(
+                       CONNMAN_SERVICE_TYPE_VLAN))
+               return 0;
+
+       DBG("bridge %s enabled %d", bridge, enabled);
+
+       if (enabled)
+               vlan_tech_enable_tethering(technology, bridge);
+       else
+               vlan_tech_disable_tethering(technology, bridge);
+
+       return 0;
+}
+
+static struct connman_technology_driver vlan_tech_driver = {
+       .name                   = "vlan",
+       .type                   = CONNMAN_SERVICE_TYPE_VLAN,
+       .probe                  = vlan_tech_probe,
+       .remove                 = vlan_tech_remove,
+       .add_interface          = vlan_tech_add_interface,
+       .remove_interface       = vlan_tech_remove_interface,
+       .set_tethering          = vlan_tech_set_tethering,
+};
+
+static int vlan_init(void)
+{
+       int err;
+
+       err = connman_technology_driver_register(&vlan_tech_driver);
+       if (err < 0)
+               return err;
+
+       err = connman_network_driver_register(&vlan_network_driver);
+       if (err < 0)
+               return err;
+
+       err = connman_device_driver_register(&vlan_dev_driver);
+       if (err < 0) {
+               connman_network_driver_unregister(&vlan_network_driver);
+               return err;
+       }
+
+       return 0;
+}
+
+static void vlan_exit(void)
+{
+       connman_technology_driver_unregister(&vlan_tech_driver);
+
+       connman_network_driver_unregister(&vlan_network_driver);
+
+       connman_device_driver_unregister(&vlan_dev_driver);
+}
+
+CONNMAN_PLUGIN_DEFINE(vlan, "VLAN interface plugin", VERSION,
+               CONNMAN_PLUGIN_PRIORITY_DEFAULT, vlan_init, vlan_exit)
diff --git a/src/config.c b/src/config.c
index a4c117e..9c47a97 100644
--- a/src/config.c
+++ b/src/config.c
@@ -1137,6 +1137,7 @@ static int try_provision_service(struct 
connman_config_service *config,
 
        case CONNMAN_SERVICE_TYPE_ETHERNET:
        case CONNMAN_SERVICE_TYPE_GADGET:
+       case CONNMAN_SERVICE_TYPE_VLAN:
 
                if (__connman_service_string2type(config->type) != type)
                        return -ENOENT;
diff --git a/src/detect.c b/src/detect.c
index 6c03920..0de05f9 100644
--- a/src/detect.c
+++ b/src/detect.c
@@ -63,6 +63,7 @@ static void detect_newlink(unsigned short type, int index,
        case CONNMAN_DEVICE_TYPE_ETHERNET:
        case CONNMAN_DEVICE_TYPE_WIFI:
        case CONNMAN_DEVICE_TYPE_GADGET:
+       case CONNMAN_DEVICE_TYPE_VLAN:
                break;
        }
 
diff --git a/src/device.c b/src/device.c
index c0683ab..c7248ab 100644
--- a/src/device.c
+++ b/src/device.c
@@ -97,6 +97,8 @@ static const char *type2description(enum connman_device_type 
type)
                return "Cellular";
        case CONNMAN_DEVICE_TYPE_GADGET:
                return "Gadget";
+       case CONNMAN_DEVICE_TYPE_VLAN:
+               return "VLAN";
 
        }
 
@@ -121,6 +123,8 @@ static const char *type2string(enum connman_device_type 
type)
                return "cellular";
        case CONNMAN_DEVICE_TYPE_GADGET:
                return "gadget";
+       case CONNMAN_DEVICE_TYPE_VLAN:
+               return "vlan";
 
        }
 
@@ -147,6 +151,8 @@ enum connman_service_type __connman_device_get_service_type(
                return CONNMAN_SERVICE_TYPE_CELLULAR;
        case CONNMAN_DEVICE_TYPE_GADGET:
                return CONNMAN_SERVICE_TYPE_GADGET;
+       case CONNMAN_DEVICE_TYPE_VLAN:
+               return CONNMAN_SERVICE_TYPE_VLAN;
 
        }
 
@@ -852,6 +858,7 @@ int connman_device_add_network(struct connman_device 
*device,
        const char *identifier = connman_network_get_identifier(network);
 
        DBG("device %p network %p", device, network);
+       DBG("IDENTIFIER: %s\n", identifier);
 
        if (!identifier)
                return -EINVAL;
@@ -1093,6 +1100,7 @@ int __connman_device_request_scan(enum 
connman_service_type type)
        case CONNMAN_SERVICE_TYPE_GPS:
        case CONNMAN_SERVICE_TYPE_VPN:
        case CONNMAN_SERVICE_TYPE_GADGET:
+       case CONNMAN_SERVICE_TYPE_VLAN:
                return -EOPNOTSUPP;
        case CONNMAN_SERVICE_TYPE_WIFI:
        case CONNMAN_SERVICE_TYPE_P2P:
@@ -1261,6 +1269,7 @@ struct connman_device 
*connman_device_create_from_index(int index)
                return NULL;
        case CONNMAN_DEVICE_TYPE_ETHERNET:
        case CONNMAN_DEVICE_TYPE_GADGET:
+       case CONNMAN_DEVICE_TYPE_VLAN:
        case CONNMAN_DEVICE_TYPE_WIFI:
                name = index2ident(index, "");
                addr = index2addr(index);
@@ -1284,6 +1293,7 @@ struct connman_device 
*connman_device_create_from_index(int index)
                break;
        case CONNMAN_DEVICE_TYPE_ETHERNET:
        case CONNMAN_DEVICE_TYPE_GADGET:
+       case CONNMAN_DEVICE_TYPE_VLAN:
                ident = index2ident(index, NULL);
                break;
        case CONNMAN_DEVICE_TYPE_WIFI:
diff --git a/src/network.c b/src/network.c
index f61f698..9b7d544 100644
--- a/src/network.c
+++ b/src/network.c
@@ -101,6 +101,8 @@ static const char *type2string(enum connman_network_type 
type)
                return "ethernet";
        case CONNMAN_NETWORK_TYPE_GADGET:
                return "gadget";
+       case CONNMAN_NETWORK_TYPE_VLAN:
+               return "vlan";
        case CONNMAN_NETWORK_TYPE_WIFI:
                return "wifi";
        case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
@@ -749,6 +751,7 @@ static int network_probe(struct connman_network *network)
                return 0;
        case CONNMAN_NETWORK_TYPE_ETHERNET:
        case CONNMAN_NETWORK_TYPE_GADGET:
+       case CONNMAN_NETWORK_TYPE_VLAN:
        case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
        case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
        case CONNMAN_NETWORK_TYPE_CELLULAR:
@@ -779,6 +782,7 @@ static void network_remove(struct connman_network *network)
                break;
        case CONNMAN_NETWORK_TYPE_ETHERNET:
        case CONNMAN_NETWORK_TYPE_GADGET:
+       case CONNMAN_NETWORK_TYPE_VLAN:
        case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
        case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
        case CONNMAN_NETWORK_TYPE_CELLULAR:
@@ -1091,6 +1095,7 @@ void connman_network_set_group(struct connman_network 
*network,
                return;
        case CONNMAN_NETWORK_TYPE_ETHERNET:
        case CONNMAN_NETWORK_TYPE_GADGET:
+       case CONNMAN_NETWORK_TYPE_VLAN:
        case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
        case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
        case CONNMAN_NETWORK_TYPE_CELLULAR:
@@ -1142,6 +1147,7 @@ bool __connman_network_get_weakness(struct 
connman_network *network)
        case CONNMAN_NETWORK_TYPE_VENDOR:
        case CONNMAN_NETWORK_TYPE_ETHERNET:
        case CONNMAN_NETWORK_TYPE_GADGET:
+       case CONNMAN_NETWORK_TYPE_VLAN:
        case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
        case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
        case CONNMAN_NETWORK_TYPE_CELLULAR:
@@ -2041,6 +2047,7 @@ void connman_network_update(struct connman_network 
*network)
                return;
        case CONNMAN_NETWORK_TYPE_ETHERNET:
        case CONNMAN_NETWORK_TYPE_GADGET:
+       case CONNMAN_NETWORK_TYPE_VLAN:
        case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
        case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
        case CONNMAN_NETWORK_TYPE_CELLULAR:
diff --git a/src/notifier.c b/src/notifier.c
index 5ba5324..8517190 100644
--- a/src/notifier.c
+++ b/src/notifier.c
@@ -149,6 +149,7 @@ void __connman_notifier_connect(enum connman_service_type 
type)
                return;
        case CONNMAN_SERVICE_TYPE_ETHERNET:
        case CONNMAN_SERVICE_TYPE_GADGET:
+       case CONNMAN_SERVICE_TYPE_VLAN:
        case CONNMAN_SERVICE_TYPE_WIFI:
        case CONNMAN_SERVICE_TYPE_BLUETOOTH:
        case CONNMAN_SERVICE_TYPE_CELLULAR:
@@ -196,6 +197,7 @@ void __connman_notifier_disconnect(enum 
connman_service_type type)
                return;
        case CONNMAN_SERVICE_TYPE_ETHERNET:
        case CONNMAN_SERVICE_TYPE_GADGET:
+       case CONNMAN_SERVICE_TYPE_VLAN:
        case CONNMAN_SERVICE_TYPE_WIFI:
        case CONNMAN_SERVICE_TYPE_BLUETOOTH:
        case CONNMAN_SERVICE_TYPE_CELLULAR:
diff --git a/src/rfkill.c b/src/rfkill.c
index 2bfb092..2480c70 100644
--- a/src/rfkill.c
+++ b/src/rfkill.c
@@ -88,6 +88,7 @@ static enum rfkill_type convert_service_type(enum 
connman_service_type type)
        case CONNMAN_SERVICE_TYPE_ETHERNET:
        case CONNMAN_SERVICE_TYPE_VPN:
        case CONNMAN_SERVICE_TYPE_GADGET:
+       case CONNMAN_SERVICE_TYPE_VLAN:
        case CONNMAN_SERVICE_TYPE_P2P:
        case CONNMAN_SERVICE_TYPE_UNKNOWN:
                return NUM_RFKILL_TYPES;
diff --git a/src/rtnl.c b/src/rtnl.c
index b8b02c4..15827ab 100644
--- a/src/rtnl.c
+++ b/src/rtnl.c
@@ -170,6 +170,9 @@ static void read_uevent(struct interface_data *interface)
                } else if (strcmp(line + 8, "gadget") == 0) {
                        interface->service_type = CONNMAN_SERVICE_TYPE_GADGET;
                        interface->device_type = CONNMAN_DEVICE_TYPE_GADGET;
+               } else if (strcmp(line + 8, "vlan") == 0) {
+                       interface->service_type = CONNMAN_SERVICE_TYPE_VLAN;
+                       interface->device_type = CONNMAN_DEVICE_TYPE_VLAN;
 
                } else {
                        interface->service_type = CONNMAN_SERVICE_TYPE_UNKNOWN;
diff --git a/src/service.c b/src/service.c
index 7538bdd..fa355ec 100644
--- a/src/service.c
+++ b/src/service.c
@@ -200,6 +200,8 @@ const char *__connman_service_type2string(enum 
connman_service_type type)
                return "vpn";
        case CONNMAN_SERVICE_TYPE_GADGET:
                return "gadget";
+       case CONNMAN_SERVICE_TYPE_VLAN:
+               return "vlan";
        case CONNMAN_SERVICE_TYPE_P2P:
                return "p2p";
        }
@@ -216,6 +218,8 @@ enum connman_service_type 
__connman_service_string2type(const char *str)
                return CONNMAN_SERVICE_TYPE_ETHERNET;
        if (strcmp(str, "gadget") == 0)
                return CONNMAN_SERVICE_TYPE_GADGET;
+       if (strcmp(str, "vlan") == 0)
+               return CONNMAN_SERVICE_TYPE_VLAN;
        if (strcmp(str, "wifi") == 0)
                return CONNMAN_SERVICE_TYPE_WIFI;
        if (strcmp(str, "cellular") == 0)
@@ -372,6 +376,7 @@ int __connman_service_load_modifiable(struct 
connman_service *service)
                /* fall through */
        case CONNMAN_SERVICE_TYPE_WIFI:
        case CONNMAN_SERVICE_TYPE_GADGET:
+       case CONNMAN_SERVICE_TYPE_VLAN:
        case CONNMAN_SERVICE_TYPE_BLUETOOTH:
        case CONNMAN_SERVICE_TYPE_CELLULAR:
        case CONNMAN_SERVICE_TYPE_ETHERNET:
@@ -488,6 +493,7 @@ static int service_load(struct connman_service *service)
                /* fall through */
 
        case CONNMAN_SERVICE_TYPE_ETHERNET:
+       case CONNMAN_SERVICE_TYPE_VLAN:
                autoconnect = g_key_file_get_boolean(keyfile,
                                service->identifier, "AutoConnect", &error);
                if (!error)
@@ -657,6 +663,7 @@ static int service_save(struct connman_service *service)
                /* fall through */
 
        case CONNMAN_SERVICE_TYPE_ETHERNET:
+       case CONNMAN_SERVICE_TYPE_VLAN:
                if (service->favorite)
                        g_key_file_set_boolean(keyfile, service->identifier,
                                        "AutoConnect", service->autoconnect);
@@ -2324,6 +2331,7 @@ static void append_properties(DBusMessageIter *dict, 
dbus_bool_t limited,
        case CONNMAN_SERVICE_TYPE_ETHERNET:
        case CONNMAN_SERVICE_TYPE_BLUETOOTH:
        case CONNMAN_SERVICE_TYPE_GADGET:
+       case CONNMAN_SERVICE_TYPE_VLAN:
                connman_dbus_dict_append_dict(dict, "Ethernet",
                                                append_ethernet, service);
                break;
@@ -3562,6 +3570,7 @@ void __connman_service_set_active_session(bool enable, 
GSList *list)
                case CONNMAN_SERVICE_TYPE_BLUETOOTH:
                case CONNMAN_SERVICE_TYPE_CELLULAR:
                case CONNMAN_SERVICE_TYPE_GADGET:
+               case CONNMAN_SERVICE_TYPE_VLAN:
                        if (enable)
                                active_sessions[type]++;
                        else
@@ -3582,12 +3591,13 @@ void __connman_service_set_active_session(bool enable, 
GSList *list)
                list = g_slist_next(list);
        }
 
-       DBG("eth %d wifi %d bt %d cellular %d gadget %d sessions %d",
+       DBG("eth %d wifi %d bt %d cellular %d gadget %d vlan %d sessions %d",
                        active_sessions[CONNMAN_SERVICE_TYPE_ETHERNET],
                        active_sessions[CONNMAN_SERVICE_TYPE_WIFI],
                        active_sessions[CONNMAN_SERVICE_TYPE_BLUETOOTH],
                        active_sessions[CONNMAN_SERVICE_TYPE_CELLULAR],
                        active_sessions[CONNMAN_SERVICE_TYPE_GADGET],
+                       active_sessions[CONNMAN_SERVICE_TYPE_VLAN],
                        active_count);
 }
 
@@ -4009,7 +4019,8 @@ static DBusMessage *disconnect_service(DBusConnection 
*conn,
 bool __connman_service_remove(struct connman_service *service)
 {
        if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET ||
-                       service->type == CONNMAN_SERVICE_TYPE_GADGET)
+                       service->type == CONNMAN_SERVICE_TYPE_GADGET ||
+                       service->type == CONNMAN_SERVICE_TYPE_VLAN)
                return false;
 
        if (service->immutable || service->hidden ||
@@ -4708,6 +4719,11 @@ static gint service_compare(gconstpointer a, 
gconstpointer b)
                        return -1;
                if (service_b->type == CONNMAN_SERVICE_TYPE_GADGET)
                        return 1;
+
+               if (service_a->type == CONNMAN_SERVICE_TYPE_VLAN)
+                       return -1;
+               if (service_b->type == CONNMAN_SERVICE_TYPE_VLAN)
+                       return 1;
        }
 
        strength = (gint) service_b->strength - (gint) service_a->strength;
@@ -5787,6 +5803,7 @@ static bool prepare_network(struct connman_service 
*service)
                break;
        case CONNMAN_NETWORK_TYPE_ETHERNET:
        case CONNMAN_NETWORK_TYPE_GADGET:
+       case CONNMAN_NETWORK_TYPE_VLAN:
        case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
        case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
        case CONNMAN_NETWORK_TYPE_CELLULAR:
@@ -5845,6 +5862,7 @@ static int service_connect(struct connman_service 
*service)
                return -EINVAL;
        case CONNMAN_SERVICE_TYPE_ETHERNET:
        case CONNMAN_SERVICE_TYPE_GADGET:
+       case CONNMAN_SERVICE_TYPE_VLAN:
        case CONNMAN_SERVICE_TYPE_BLUETOOTH:
        case CONNMAN_SERVICE_TYPE_CELLULAR:
        case CONNMAN_SERVICE_TYPE_VPN:
@@ -5970,6 +5988,7 @@ int __connman_service_connect(struct connman_service 
*service,
 
        case CONNMAN_SERVICE_TYPE_ETHERNET:
        case CONNMAN_SERVICE_TYPE_GADGET:
+       case CONNMAN_SERVICE_TYPE_VLAN:
        case CONNMAN_SERVICE_TYPE_BLUETOOTH:
        case CONNMAN_SERVICE_TYPE_CELLULAR:
        case CONNMAN_SERVICE_TYPE_VPN:
@@ -6580,6 +6599,8 @@ static enum connman_service_type 
convert_network_type(struct connman_network *ne
                return CONNMAN_SERVICE_TYPE_CELLULAR;
        case CONNMAN_NETWORK_TYPE_GADGET:
                return CONNMAN_SERVICE_TYPE_GADGET;
+       case CONNMAN_NETWORK_TYPE_VLAN:
+               return CONNMAN_SERVICE_TYPE_VLAN;
        }
 
        return CONNMAN_SERVICE_TYPE_UNKNOWN;
@@ -6724,6 +6745,7 @@ struct connman_service * 
__connman_service_create_from_network(struct connman_ne
        case CONNMAN_SERVICE_TYPE_GPS:
        case CONNMAN_SERVICE_TYPE_VPN:
        case CONNMAN_SERVICE_TYPE_GADGET:
+       case CONNMAN_SERVICE_TYPE_VLAN:
        case CONNMAN_SERVICE_TYPE_WIFI:
        case CONNMAN_SERVICE_TYPE_CELLULAR:
        case CONNMAN_SERVICE_TYPE_P2P:
@@ -6760,6 +6782,7 @@ struct connman_service * 
__connman_service_create_from_network(struct connman_ne
                                break;
 
                        case CONNMAN_SERVICE_TYPE_GADGET:
+                       case CONNMAN_SERVICE_TYPE_VLAN:
                        case CONNMAN_SERVICE_TYPE_ETHERNET:
                                if (service->autoconnect) {
                                        __connman_service_connect(service,
diff --git a/src/session.c b/src/session.c
index 08facc1..03e824b 100644
--- a/src/session.c
+++ b/src/session.c
@@ -178,6 +178,8 @@ static char *service2bearer(enum connman_service_type type)
                return "ethernet";
        case CONNMAN_SERVICE_TYPE_GADGET:
                return "gadget";
+       case CONNMAN_SERVICE_TYPE_VLAN:
+               return "vlan";
        case CONNMAN_SERVICE_TYPE_WIFI:
                return "wifi";
        case CONNMAN_SERVICE_TYPE_BLUETOOTH:
diff --git a/src/technology.c b/src/technology.c
index 55303a0..bbd2621 100644
--- a/src/technology.c
+++ b/src/technology.c
@@ -140,6 +140,8 @@ static const char *get_name(enum connman_service_type type)
                break;
        case CONNMAN_SERVICE_TYPE_GADGET:
                return "Gadget";
+       case CONNMAN_SERVICE_TYPE_VLAN:
+               return "VLAN";
        case CONNMAN_SERVICE_TYPE_ETHERNET:
                return "Wired";
        case CONNMAN_SERVICE_TYPE_WIFI:
@@ -1334,6 +1336,7 @@ void __connman_technology_add_interface(enum 
connman_service_type type,
        case CONNMAN_SERVICE_TYPE_GPS:
        case CONNMAN_SERVICE_TYPE_VPN:
        case CONNMAN_SERVICE_TYPE_GADGET:
+       case CONNMAN_SERVICE_TYPE_VLAN:
        case CONNMAN_SERVICE_TYPE_P2P:
                break;
        }
@@ -1385,6 +1388,7 @@ void __connman_technology_remove_interface(enum 
connman_service_type type,
        case CONNMAN_SERVICE_TYPE_GPS:
        case CONNMAN_SERVICE_TYPE_VPN:
        case CONNMAN_SERVICE_TYPE_GADGET:
+       case CONNMAN_SERVICE_TYPE_VLAN:
        case CONNMAN_SERVICE_TYPE_P2P:
                break;
        }
diff --git a/src/wispr.c b/src/wispr.c
index ef4bdab..80c669d 100644
--- a/src/wispr.c
+++ b/src/wispr.c
@@ -839,6 +839,7 @@ static int wispr_portal_detect(struct 
connman_wispr_portal_context *wp_context)
 
        switch (service_type) {
        case CONNMAN_SERVICE_TYPE_ETHERNET:
+       case CONNMAN_SERVICE_TYPE_VLAN:
        case CONNMAN_SERVICE_TYPE_WIFI:
        case CONNMAN_SERVICE_TYPE_BLUETOOTH:
        case CONNMAN_SERVICE_TYPE_CELLULAR:
-- 
1.9.1

_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman

Reply via email to