[Feature][API-532][connman] add ifconfig for gsw

Change-Id: I7c9a854b2d99abc9dcb3f275217da101f9a89faa
diff --git a/meta/meta-mediatek-mt2735/recipes-connectivity/connman/connman/lynq_ifconfig_cmd.patch b/meta/meta-mediatek-mt2735/recipes-connectivity/connman/connman/lynq_ifconfig_cmd.patch
new file mode 100755
index 0000000..86cee4d
--- /dev/null
+++ b/meta/meta-mediatek-mt2735/recipes-connectivity/connman/connman/lynq_ifconfig_cmd.patch
@@ -0,0 +1,445 @@
+--- connman-1.41/src/manager.c	2022-01-28 22:48:01.000000000 +0800
++++ connman-1.41/src/manager_new.c	2022-08-20 17:16:50.031688400 +0800
+@@ -29,6 +29,13 @@
+ 
+ #include <connman/agent.h>
+ 
++#include <stdio.h>
++#include <unistd.h>
++#include <sys/socket.h>
++#include <net/if.h>
++#include <net/if_arp.h>
++#include <sys/ioctl.h>
++
+ #include "connman.h"
+ 
+ static bool connman_state_idle;
+@@ -69,12 +76,61 @@
+ 	return reply;
+ }
+ 
++struct dev_info {
++    const char * dev_name;
++    char identifier[128];
++    char group[16];
++    int index;
++};
++
++void device_enum_callback (int index, void *user_data) {
++    struct dev_info * dev = (struct dev_info*)user_data;
++    unsigned short type;
++    int sock_mac;
++    struct ifreq ifr_mac;
++
++    DBG("index:%d, ptr %p", index, dev);
++    if (dev == NULL) {
++        return;
++    }
++
++    if (g_strcmp0(dev->dev_name, connman_inet_ifname(index)) == 0) {
++        type = __connman_ipconfig_get_type_from_index(index);
++        DBG("index:%d, type %d", index, type);
++        if ( type == ARPHRD_ETHER || type == ARPHRD_EETHER) {
++            sock_mac = socket( AF_INET, SOCK_STREAM, 0 );
++
++            if( sock_mac == -1) {
++                DBG("bad sock mac");
++                return;
++            }
++            strcpy(ifr_mac.ifr_name, dev->dev_name);
++            if( (ioctl( sock_mac, SIOCGIFHWADDR, &ifr_mac)) >= 0) {
++                sprintf(dev->identifier, "ethernet_%02x%02x%02x%02x%02x%02x_cable",
++                        (unsigned char)ifr_mac.ifr_hwaddr.sa_data[0],
++                        (unsigned char)ifr_mac.ifr_hwaddr.sa_data[1],
++                        (unsigned char)ifr_mac.ifr_hwaddr.sa_data[2],
++                        (unsigned char)ifr_mac.ifr_hwaddr.sa_data[3],
++                        (unsigned char)ifr_mac.ifr_hwaddr.sa_data[4],
++                        (unsigned char)ifr_mac.ifr_hwaddr.sa_data[5]);
++                strcpy(dev->group, "Wired");
++                dev->index = index;
++            }
++
++            close( sock_mac );
++        }
++    }
++}
++
+ static DBusMessage *set_property(DBusConnection *conn,
+ 					DBusMessage *msg, void *data)
+ {
+ 	DBusMessageIter iter, value;
+ 	const char *name;
+ 	int type;
++    struct dev_info dev;
++    struct connman_service * service_ptr;
++    int err = 0;
+ 
+ 	DBG("conn %p", conn);
+ 
+@@ -108,14 +164,105 @@
+ 		if (type != DBUS_TYPE_BOOLEAN)
+ 			return __connman_error_invalid_arguments(msg);
+ 
+-		dbus_message_iter_get_basic(&value, &sessionmode);
+-
++        dbus_message_iter_get_basic(&value, &sessionmode);
+ 	} else
+ 		return __connman_error_invalid_property(msg);
+ 
+ 	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+ }
+ 
++static DBusMessage *set_ipconfig(DBusConnection *conn,
++                    DBusMessage *msg, void *data)
++{
++    DBusMessageIter iter, value;
++    const char *name;
++    int type;
++    struct dev_info dev;
++    struct connman_service * service_ptr;
++    int err = 0;
++
++    DBG("conn %p", conn);
++    memset(&dev, 0, sizeof (dev));
++
++    if (!dbus_message_iter_init(msg, &iter))
++        return __connman_error_invalid_arguments(msg);
++
++    if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
++        return __connman_error_invalid_arguments(msg);
++
++    dbus_message_iter_get_basic(&iter, &name);
++    dbus_message_iter_next(&iter);
++
++    if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
++        return __connman_error_invalid_arguments(msg);
++
++    dbus_message_iter_recurse(&iter, &value);
++
++    type = dbus_message_iter_get_arg_type(&value);
++
++    if (!g_str_equal(name, "")) {
++        dev.dev_name = name;
++        DBG("%s, %s", name, dev.dev_name);
++        __connman_ipconfig_foreach(&device_enum_callback, &dev);
++        if (dev.identifier[0] == '\0') {
++            return __connman_error_invalid_arguments(msg);
++        }
++
++        service_ptr = __connman_service_lookup_from_index(dev.index);
++
++        DBG("servcie+ptr %p", service_ptr);
++        if (service_ptr != NULL) {
++            DBG("return EEXIST");
++            return __connman_error_failed(msg, -EEXIST);
++        }
++        struct connman_ipconfig *ipconfig, *new_ipconfig;
++        enum connman_ipconfig_method old_method, new_method;
++
++        int index;
++        const char *service_identifier = dev.identifier;
++        const char* servcie_name = dev.group;
++
++        old_method = __connman_ipconfig_get_method(ipconfig);
++        index = __connman_ipconfig_get_index(ipconfig);
++
++        new_ipconfig = __connman_ipconfig_create(index,
++                            CONNMAN_IPCONFIG_TYPE_IPV4);
++        if (!new_ipconfig)
++            return __connman_error_invalid_arguments(msg);
++
++        if (1) {
++            err = __connman_ipconfig_set_config(new_ipconfig, &value);
++            if (err < 0) {
++                __connman_ipconfig_unref(new_ipconfig);
++                return __connman_error_invalid_arguments(msg);
++            }
++
++            new_method = __connman_ipconfig_get_method(new_ipconfig);
++        }
++
++        GKeyFile *keyfile;
++
++        keyfile = g_key_file_new();
++        if (!keyfile)
++            return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
++
++        if (servcie_name)
++            g_key_file_set_string(keyfile, service_identifier,
++                            "Name", servcie_name);
++
++        if (new_ipconfig)
++            __connman_ipconfig_save(new_ipconfig, keyfile,
++                    service_identifier, "IPv4.");
++
++        __connman_storage_save_service(keyfile, service_identifier);
++
++        g_key_file_free(keyfile);
++    } else
++        return __connman_error_invalid_property(msg);
++
++	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
++}
++
+ static void append_technology_structs(DBusMessageIter *iter, void *user_data)
+ {
+ 	__connman_technology_list_struct(iter);
+@@ -582,7 +729,10 @@
+ 			register_peer_service) },
+ 	{ GDBUS_METHOD("UnregisterPeerService",
+ 			GDBUS_ARGS({ "specification", "a{sv}" }), NULL,
+-			unregister_peer_service) },
++            unregister_peer_service) },
++    { GDBUS_METHOD("SetIPConfig",
++            GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
++            NULL, set_ipconfig) },
+ 	{ },
+ };
+ 
+--- connman-1.41/client/commands.c	2022-01-28 22:48:01.000000000 +0800
++++ connman-1.41/client/commands_new.c	2022-08-20 18:37:54.452762100 +0800
+@@ -45,6 +45,11 @@
+ #include "agent.h"
+ #include "vpnconnections.h"
+ 
++#include <sys/socket.h>
++#include <net/if.h>
++#include <net/if_arp.h>
++#include <sys/ioctl.h>
++
+ static DBusConnection *connection;
+ static GHashTable *service_hash;
+ static GHashTable *vpnconnection_hash;
+@@ -980,6 +985,12 @@
+ 	struct connman_option *options;
+ };
+ 
++struct ipconfig_options {
++    char *service_name;
++    char *ipconfig_cmd;
++    struct config_append append;
++};
++
+ static void config_append_ipv4(DBusMessageIter *iter,
+ 		void *user_data)
+ {
+@@ -999,6 +1010,59 @@
+ 	append->values = i;
+ }
+ 
++static int ipconfig_return(DBusMessageIter *iter, int errnum,
++            const char *error, void *user_data)
++{
++     struct ipconfig_options * config = user_data;
++
++    char * path;
++    int sock_mac;
++    struct ifreq ifr_mac;
++    char identifier[64];
++
++//    printf("ipconfig_return %d %s\n", errnum, error);
++    if (errnum == -EEXIST || (error && strstr(error, "-17") != NULL)) {
++//        printf("exits service\n");
++        sock_mac = socket( AF_INET, SOCK_STREAM, 0 );
++
++        if( sock_mac == -1) {
++            return -1;
++        }
++
++        strcpy(ifr_mac.ifr_name, config->service_name);
++        if( (ioctl( sock_mac, SIOCGIFHWADDR, &ifr_mac)) >= 0) {
++            sprintf(identifier, "ethernet_%02x%02x%02x%02x%02x%02x_cable",
++                    (unsigned char)ifr_mac.ifr_hwaddr.sa_data[0],
++                    (unsigned char)ifr_mac.ifr_hwaddr.sa_data[1],
++                    (unsigned char)ifr_mac.ifr_hwaddr.sa_data[2],
++                    (unsigned char)ifr_mac.ifr_hwaddr.sa_data[3],
++                    (unsigned char)ifr_mac.ifr_hwaddr.sa_data[4],
++                    (unsigned char)ifr_mac.ifr_hwaddr.sa_data[5]);
++        }
++
++        close( sock_mac );
++
++        path = g_strdup_printf("/net/connman/service/%s", identifier);
++        //printf("service name %s\n", identifier);
++        __connmanctl_dbus_set_property_dict(connection,
++                path, "net.connman.Service",
++                config_return, g_strdup(identifier),
++                "IPv4.Configuration", DBUS_TYPE_STRING,
++                config_append_ipv4, &config->append);
++    }
++    else if (error)
++        fprintf(stderr, "Error %s: %s\n", config->service_name, error);
++	else if (config->ipconfig_cmd) {
++		system(config->ipconfig_cmd);
++		g_free(config->ipconfig_cmd);
++	}
++
++    g_free(config->service_name);
++    g_free(user_data);
++
++    return 0;
++}
++
+ static void config_append_ipv6(DBusMessageIter *iter, void *user_data)
+ {
+ 	struct config_append *append = user_data;
+@@ -1327,6 +1391,78 @@
+ 	return result;
+ }
+ 
++static int cmd_ipconfig(char *args[], int num, struct connman_option *options)
++{
++    int result = 0, res = 0, index = 2, oldindex = 0;
++    int c;
++    char *service_name, *path;
++    char **opt_start;
++    struct config_append append;
++    struct ipconfig_options *ipconfig_ptr;
++
++    service_name = args[1];
++    if (!service_name)
++        return -EINVAL;
++//    printf("ifconfig name %s\n", service_name);
++
++    while (index < num && args[index]) {
++        c = parse_args(args[index], options);
++        opt_start = &args[index + 1];
++        append.opts = opt_start;
++        append.values = 0;
++        ipconfig_ptr = g_new0(struct ipconfig_options, 1);
++        ipconfig_ptr->service_name = g_strdup(service_name);
++		ipconfig_ptr->ipconfig_cmd = NULL;
++        ipconfig_ptr->append.opts = opt_start;
++        ipconfig_ptr->append.values = 0;
++
++        res = 0;
++
++        oldindex = index;
++        path = g_strdup_printf("/");
++
++        switch (c) {
++        case 'i':
++        {
++			if (num > 4 && strcmp(args[2], "--ipv4") == 0 && strcmp(args[3], "manual") == 0) {
++				if (num > 5)
++					ipconfig_ptr->ipconfig_cmd = g_strdup_printf("ifconfig %s %s netmask %s", service_name, args[4], args[5]);
++				else
++					ipconfig_ptr->ipconfig_cmd = g_strdup_printf("ifconfig %s %s", service_name, args[4]);
++			}
++            res = __connmanctl_dbus_method_call_with_name(connection,
++                    "net.connman", path, "net.connman.Manager", "SetIPConfig",
++                    ipconfig_return, ipconfig_ptr,
++                    service_name, DBUS_TYPE_STRING,
++                    config_append_ipv4, &append);
++
++//            printf("res is %d\n", res);
++            index += append.values;
++            break;
++        }
++
++        default:
++            res = -EINVAL;
++            break;
++        }
++
++        g_free(path);
++
++        if (res < 0) {
++            if (res == -EINPROGRESS)
++                result = -EINPROGRESS;
++            else
++                printf("Error '%s': %s\n", args[oldindex],
++                        strerror(-res));
++        } else
++            index += res;
++
++        index++;
++    }
++
++    return result;
++}
++
+ static DBusHandlerResult monitor_changed(DBusConnection *connection,
+ 		DBusMessage *message, void *user_data)
+ {
+@@ -2825,6 +2961,8 @@
+ 	  lookup_service_arg },
+ 	{ "config",       "<service>",    config_options,  cmd_config,
+ 	  "Set service configuration options", lookup_config },
++    { "ifconfig",       "<interface>",    config_options,  cmd_ipconfig,
++      "Set interface configuration options", lookup_config },
+ 	{ "monitor",      "[off]",        monitor_options, cmd_monitor,
+ 	  "Monitor signals from interfaces", lookup_monitor },
+ 	{ "agent", "on|off",              NULL,            cmd_agent,
+--- connman-1.41/client/dbus_helpers.h	2022-01-28 22:48:01.000000000 +0800
++++ connman-1.41/client/dbus_helpers_new.h	2022-08-20 17:17:32.301009500 +0800
+@@ -49,6 +49,14 @@
+ 		void * user_data, connmanctl_dbus_append_func_t append_fn,
+ 		void *append_data);
+ 
++int __connmanctl_dbus_method_call_with_name(DBusConnection *connection,
++        const char *service, const char *path,
++        const char *interface, const char *method,
++        connmanctl_dbus_method_return_func_t cb, void * user_data,
++        const char *property, int type,
++        connmanctl_dbus_append_func_t append_fn,
++        void *append_data);
++
+ int __connmanctl_dbus_set_property(DBusConnection *connection,
+ 		const char *path, const char *interface,
+ 		connmanctl_dbus_method_return_func_t cb, void * user_data,
+--- connman-1.41/client/dbus_helpers.c	2022-01-28 22:48:01.000000000 +0800
++++ connman-1.41/client/dbus_helpers_new.c	2022-08-20 17:54:29.303478800 +0800
+@@ -289,6 +289,52 @@
+ 	return send_method_call(connection, message, cb, user_data);
+ }
+ 
++int __connmanctl_dbus_method_call_with_name(DBusConnection *connection,
++        const char *service, const char *path,
++        const char *interface, const char *method,
++        connmanctl_dbus_method_return_func_t cb, void * user_data,
++        const char *property, int type,
++        connmanctl_dbus_append_func_t append_fn,
++        void *append_data)
++{
++    DBusMessage *message;
++    DBusMessageIter iter, variant, dict;
++
++    message = dbus_message_new_method_call(service, path, interface,
++            method);
++
++    if (!message)
++        return -ENOMEM;
++
++    //printf("set property path:%s,interface:%s\n", path, interface);
++    if (!message)
++        return -ENOMEM;
++
++    dbus_message_iter_init_append(message, &iter);
++    dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property);
++    dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
++            DBUS_TYPE_ARRAY_AS_STRING
++                DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
++                    DBUS_TYPE_STRING_AS_STRING
++                    DBUS_TYPE_VARIANT_AS_STRING
++                DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
++            &variant);
++
++    dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
++            DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
++                DBUS_TYPE_STRING_AS_STRING
++                DBUS_TYPE_VARIANT_AS_STRING
++            DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
++            &dict);
++
++    append_fn(&dict, append_data);
++
++    dbus_message_iter_close_container(&variant, &dict);
++    dbus_message_iter_close_container(&iter, &variant);
++
++    return send_method_call(connection, message, cb, user_data);
++}
++
+ int __connmanctl_dbus_set_property(DBusConnection *connection,
+ 		const char *path, const char *interface,
+ 		connmanctl_dbus_method_return_func_t cb, void * user_data,
diff --git a/meta/meta-mediatek-mt2735/recipes-connectivity/connman/connman_%.bbappend b/meta/meta-mediatek-mt2735/recipes-connectivity/connman/connman_%.bbappend
index 10bcc18..48244d8 100755
--- a/meta/meta-mediatek-mt2735/recipes-connectivity/connman/connman_%.bbappend
+++ b/meta/meta-mediatek-mt2735/recipes-connectivity/connman/connman_%.bbappend
@@ -3,5 +3,6 @@
 SRC_URI += "\
             file://lynq_wifi_ap_sta.patch \
             file://lynq_wifi_netmask.patch \
+            file://lynq_ifconfig_cmd.patch \
             "