Re: [PATCH] connman : Introduce softap with ip feature to connman
Michael Nazzareno Trimarchi <[email protected]> Mon, 2 Jun 2025 09:40:53 +0200
| Newsgroups | dev.linux.lists.connman |
|---|---|
| Message-ID | <CAOf5uwnBz5gC8+u2PBJAmqa0NnBkww_oG41O=91K4zbcTuTUkg@mail.gmail.com> |
Hi On Mon, Jun 2, 2025 at 8:33 AM Shailesh Rathod/LGSI GPOS Dev <[email protected]> wrote: > > From: Shailesh Rathod<[email protected]> > Date: Mon, 21 Apr 2025 18:16:09 +0900 > > Introduce softap with ip feature to connman > > By default, ConnMan supports tethering with a passphrase. > However, it does not support configuring tethering with a > specific IP address and channel.For certain applications > it is essential to set a specific IP address for the SoftAP. > > To enable support for specifying the IP address > and channel, new properties TetheringIPAddress and > TetheringChannel should be added. > > Signed-off-by: Shailesh Rathod<[email protected]> > --- > src/connman.h | 15 ++++++ > src/technology.c | 122 +++++++++++++++++++++++++++++++++++++++--- > src/tethering.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 267 insertions(+), 6 deletions(-) > > diff --git a/src/connman.h b/src/connman.h > index 32ba559..4241a58 100644 > --- a/src/connman.h > +++ b/src/connman.h > @@ -676,9 +676,24 @@ bool __connman_config_address_provisioned(const char *address, > > #include <connman/tethering.h> > > +struct connman_station_info { > + bool is_connected; > + char *path; > + char *type; > + char ip[64]; > + char mac[32]; > + char hostname[64]; > +}; > + > + Can you drop this extra blank line? Anyway how is different from the one sent by Roman some time ago? Michael > int __connman_tethering_init(void); > void __connman_tethering_cleanup(void); > > +GHashTable *__connman_tethering_get_sta_hash(); > + > +void __connman_tethering_list_clients(DBusMessageIter *array); > +int __connman_tethering_set_enabled_with_ip(const char *ip); > + > const char *__connman_tethering_get_bridge(void); > int __connman_tethering_set_enabled(void); > void __connman_tethering_set_disabled(void); > diff --git a/src/technology.c b/src/technology.c > index 270d83d..719c680 100644 > --- a/src/technology.c > +++ b/src/technology.c > @@ -69,6 +69,8 @@ struct connman_technology { > char *tethering_ident; > char *tethering_passphrase; > int tethering_freq; > + char *tethering_ipaddress; > + unsigned int tethering_channel; > > bool enable_persistent; /* Save the tech state */ > > @@ -195,6 +197,16 @@ static void technology_save(struct connman_technology *technology) > g_free(enc); > } > > + if (technology->tethering_channel) > + g_key_file_set_integer(keyfile, identifier, > + "Tethering.Channel", > + technology->tethering_channel); > + > + if (technology->tethering_ipaddress) > + g_key_file_set_string(keyfile, identifier, > + "Tethering.IP", > + technology->tethering_ipaddress); > + > if (technology->tethering_freq == 0) > technology->tethering_freq = 2412; > > @@ -225,18 +237,25 @@ int connman_technology_tethering_notify(struct connman_technology *technology, > bool enabled) > { > int err; > + const char *ip; > > DBG("technology %p enabled %u", technology, enabled); > > if (technology->tethering == enabled) > return -EALREADY; > > - if (enabled) { > - err = __connman_tethering_set_enabled(); > - if (err < 0) > - return err; > - } else > - __connman_tethering_set_disabled(); > + ip = technology->tethering_ipaddress; > + > + if (enabled) { > + if (!ip || strlen(ip) == 0) > + err = __connman_tethering_set_enabled(); > + else > + err = __connman_tethering_set_enabled_with_ip(ip); > + > + if (err < 0) > + return err; > + } else > + __connman_tethering_set_disabled(); > > technology->tethering = enabled; > tethering_changed(technology); > @@ -417,6 +436,17 @@ bool connman_technology_get_wifi_tethering(const struct connman_technology *tech > return true; > } > > +unsigned int connman_technology_get_wifi_tethering_channel(void) > +{ > + struct connman_technology *technology; > + > + technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI); > + if (!technology) > + return 0; > + > + return technology->tethering_channel; > +} > + > static void free_rfkill(gpointer data) > { > struct connman_rfkill *rfkill = data; > @@ -479,6 +509,12 @@ static void technology_load(struct connman_technology *technology) > > enc = g_key_file_get_string(keyfile, > identifier, "Tethering.Passphrase", NULL); > + > + technology->tethering_channel = g_key_file_get_integer(keyfile, > + identifier, "Tethering.Channel", NULL); > + > + technology->tethering_ipaddress = g_key_file_get_string(keyfile, > + identifier, "Tethering.IP", NULL); > if (enc) { > technology->tethering_passphrase = g_strcompress(enc); > g_free(enc); > @@ -597,6 +633,15 @@ static void append_properties(DBusMessageIter *iter, > connman_dbus_dict_append_basic(&dict, "TetheringPassphrase", > DBUS_TYPE_STRING, > &technology->tethering_passphrase); > + if (technology->tethering_ipaddress) > + connman_dbus_dict_append_basic(&dict, "TetheringIPAddress", > + DBUS_TYPE_STRING, > + &technology->tethering_ipaddress); > + > + if (technology->tethering_channel) > + connman_dbus_dict_append_basic(&dict, "TetheringChannel", > + DBUS_TYPE_UINT32, > + &technology->tethering_channel); > > connman_dbus_dict_append_basic(&dict, "TetheringFreq", > DBUS_TYPE_INT32, > @@ -1016,6 +1061,55 @@ static DBusMessage *set_property(DBusConnection *conn, > DBUS_TYPE_STRING, > &technology->tethering_passphrase); > } > + } else if (g_str_equal(name, "TetheringChannel")) { > + dbus_uint32_t channel; > + > + if (type != DBUS_TYPE_UINT32) > + return __connman_error_invalid_arguments(msg); > + > + dbus_message_iter_get_basic(&value, &channel); > + > + if (technology->type != CONNMAN_SERVICE_TYPE_WIFI) > + return __connman_error_not_supported(msg); > + > + if (channel == 0 || channel > 13) > + return __connman_error_invalid_arguments(msg); > + > + if (technology->tethering_channel != channel) { > + > + technology->tethering_channel = channel; > + technology_save(technology); > + > + connman_dbus_property_changed_basic(technology->path, > + CONNMAN_TECHNOLOGY_INTERFACE, > + "TetheringChannel", > + DBUS_TYPE_UINT32, > + &technology->tethering_channel); > + } > + } else if (g_str_equal(name, "TetheringIPAddress")) { > + const char *str = NULL; > + > + dbus_message_iter_get_basic(&value, &str); > + > + if (technology->type != CONNMAN_SERVICE_TYPE_WIFI) > + return __connman_error_not_supported(msg); > + > + if (!str || strlen(str) == 0) { > + g_free(technology->tethering_ipaddress); > + technology->tethering_ipaddress = NULL; > + return __connman_error_invalid_arguments(msg); > + } > + if (g_strcmp0(technology->tethering_ipaddress, str) != 0) { > + g_free(technology->tethering_ipaddress); > + technology->tethering_ipaddress = g_strdup(str); > + technology_save(technology); > + > + connman_dbus_property_changed_basic(technology->path, > + CONNMAN_TECHNOLOGY_INTERFACE, > + "TetheringIPAddress", > + DBUS_TYPE_STRING, > + &technology->tethering_ipaddress); > + } > } else if (g_str_equal(name, "TetheringFreq")) { > dbus_int32_t freq; > > @@ -1257,6 +1351,7 @@ static void technology_put(struct connman_technology *technology) > g_free(technology->regdom); > g_free(technology->tethering_ident); > g_free(technology->tethering_passphrase); > + g_free(technology->tethering_ipaddress); > g_free(technology); > } > > @@ -1935,3 +2030,18 @@ void __connman_technology_cleanup(void) > > g_free(global_regdom); > } > + > +void __connman_technology_sta_count_changed(enum connman_service_type type, int stacount) > +{ > + struct connman_technology *technology; > + > + technology = technology_find(type); > + if (technology == NULL) > + return; > + > + connman_dbus_property_changed_basic(technology->path, > + CONNMAN_TECHNOLOGY_INTERFACE, "StaCount", > + DBUS_TYPE_INT32, &stacount); > + > + > +} > \ No newline at end of file > diff --git a/src/tethering.c b/src/tethering.c > index f930a26..7039037 100644 > --- a/src/tethering.c > +++ b/src/tethering.c > @@ -49,6 +49,7 @@ > #endif > > #define BRIDGE_NAME "tether" > +#define SUBNET_MASK_24 "255.255.255.0" > > #define DEFAULT_MTU 1500 > > @@ -200,6 +201,7 @@ static void unregister_all_clients(void) > g_hash_table_foreach(clients_table, unregister_client, NULL); > } > > + > int __connman_tethering_set_enabled(void) > { > int index; > @@ -363,6 +365,140 @@ void __connman_tethering_list_clients(DBusMessageIter *array) > g_hash_table_foreach(clients_table, append_client, array); > } > > +static char *get_ip(uint32_t ip) > +{ > + struct in_addr addr; > + > + addr.s_addr = htonl(ip); > + > + return g_strdup(inet_ntoa(addr)); > +} > + > +int __connman_tethering_set_enabled_with_ip(const char *ip) > +{ > + int index; > + int err; > + const char *gateway; > + const char *broadcast; > + const char *subnet_mask; > + const char *start_ip; > + const char *end_ip; > + const char *dns; > + unsigned char prefixlen; > + char **ns; > + > + DBG("enabled %d", tethering_enabled + 1); > + > + if (__sync_fetch_and_add(&tethering_enabled, 1) != 0) > + return 0; > + > + err = __connman_bridge_create(BRIDGE_NAME); > + if (err < 0) { > + __sync_fetch_and_sub(&tethering_enabled, 1); > + return 0; > + } > + > + index = connman_inet_ifindex(BRIDGE_NAME); > + > + __connman_ippool_newaddr(index, ip, 24); > + > + struct in_addr inp; > + uint32_t start, mask; > + > + if (inet_aton(ip, &inp) == 0) > + return 0; > + > + start = ntohl(inp.s_addr); > + mask = ~(0xffffffff >> 24); > + > + start = start & mask; > + > + gateway = ip; > + broadcast = get_ip(start + 255); > + subnet_mask = SUBNET_MASK_24; > + start_ip = get_ip(start + 2); > + end_ip = get_ip(start + 254); > + > + err = __connman_bridge_enable(BRIDGE_NAME, gateway, > + connman_ipaddress_calc_netmask_len(subnet_mask), > + broadcast); > + if (err < 0 && err != -EALREADY) { > + __connman_ippool_free(dhcp_ippool); > + __connman_ippool_deladdr(index, ip, 24); > + __connman_bridge_remove(BRIDGE_NAME); > + __sync_fetch_and_sub(&tethering_enabled, 1); > + err = -EADDRNOTAVAIL; > + goto clean; > + } > + > + ns = connman_setting_get_string_list("FallbackNameservers"); > + if (ns) { > + if (ns[0]) { > + g_free(private_network_primary_dns); > + private_network_primary_dns = g_strdup(ns[0]); > + } > + if (ns[1]) { > + g_free(private_network_secondary_dns); > + private_network_secondary_dns = g_strdup(ns[1]); > + } > + > + DBG("Fallback ns primary %s secondary %s", > + private_network_primary_dns, > + private_network_secondary_dns); > + } > + > + dns = gateway; > + if (__connman_dnsproxy_add_listener(index) < 0) { > + connman_error("Can't add listener %s to DNS proxy", > + BRIDGE_NAME); > + dns = private_network_primary_dns; > + DBG("Serving %s nameserver to clients", dns); > + } > + > + tethering_dhcp_server = dhcp_server_start(BRIDGE_NAME, > + gateway, subnet_mask, > + start_ip, end_ip, > + 24 * 3600, dns); > + if (!tethering_dhcp_server) { > + __connman_bridge_disable(BRIDGE_NAME); > + __connman_ippool_free(dhcp_ippool); > + __connman_ippool_deladdr(index, ip, 24); > + __connman_bridge_remove(BRIDGE_NAME); > + __sync_fetch_and_sub(&tethering_enabled, 1); > + err = -EOPNOTSUPP; > + goto clean; > + } > + > + prefixlen = connman_ipaddress_calc_netmask_len(subnet_mask); > + err = __connman_nat_enable(BRIDGE_NAME, start_ip, prefixlen); > + if (err < 0) { > + connman_error("Cannot enable NAT %d/%s", err, strerror(-err)); > + dhcp_server_stop(tethering_dhcp_server); > + __connman_bridge_disable(BRIDGE_NAME); > + __connman_ippool_free(dhcp_ippool); > + __connman_ippool_deladdr(index, ip, 24); > + __connman_bridge_remove(BRIDGE_NAME); > + __sync_fetch_and_sub(&tethering_enabled, 1); > + err = -EOPNOTSUPP; > + goto clean; > + } > + > + err = __connman_ipv6pd_setup(BRIDGE_NAME); > + if (err < 0 && err != -EINPROGRESS) > + DBG("Cannot setup IPv6 prefix delegation %d/%s", err, > + strerror(-err)); > +clean: > + g_free(broadcast); > + g_free(start_ip); > + g_free(end_ip); > + if ((err == -EOPNOTSUPP) || (err == -EADDRNOTAVAIL)){ > + return err; > + } else { > + DBG("tethering started"); > + return 0; > + } > +} > + > static void setup_tun_interface(unsigned int flags, unsigned change, > void *data) > { > > -- Michael Nazzareno Trimarchi Co-Founder & Chief Executive Officer M. +39 347 913 2170 [email protected] __________________________________ Amarula Solutions BV Joop Geesinkweg 125, 1114 AB, Amsterdam, NL T. +31 (0)85 111 9172 [email protected] www.amarulasolutions.com