@@ -107,3 +107,14 @@ Properties boolean Powered [readwrite]
This property is only valid for the WiFi technology and it's
optional. Default frequency is 2412 Mhz.
+
+ string TetheringAddress [readwrite]
+
+ The tethering interface (bridge) address.
+
+ Configures the IP address used by the tethering
+ interface. Client addresses will be allocated from
+ the same network.
+
+ If this property is not set, the tethering address is
+ selected automatically.
@@ -680,6 +680,7 @@ int __connman_tethering_init(void);
void __connman_tethering_cleanup(void);
const char *__connman_tethering_get_bridge(void);
+int __connman_tethering_set_ip(uint32_t);
int __connman_tethering_set_enabled(void);
void __connman_tethering_set_disabled(void);
void __connman_tethering_list_clients(DBusMessageIter *array);
@@ -1039,6 +1040,7 @@ void __connman_ippool_cleanup(void);
void __connman_ippool_free(struct connman_ippool *pool);
struct connman_ippool *__connman_ippool_create(int index,
+ uint32_t block_req,
unsigned int start,
unsigned int range,
ippool_collision_cb_t collision_cb,
@@ -322,6 +322,7 @@ void __connman_ippool_deladdr(int index, const char *address,
}
struct connman_ippool *__connman_ippool_create(int index,
+ uint32_t block_req,
unsigned int start,
unsigned int range,
ippool_collision_cb_t collision_cb,
@@ -342,7 +343,11 @@ struct connman_ippool *__connman_ippool_create(int index,
return NULL;
}
- block = get_free_block(start + range);
+ if (block_req)
+ block = block_req;
+ else
+ block = get_free_block(start + range);
+
if (block == 0) {
connman_warn("Could not find a free IP block");
return NULL;
@@ -358,7 +363,8 @@ struct connman_ippool *__connman_ippool_create(int index,
return NULL;
}
- last_block = block;
+ if (!block_req)
+ last_block = block;
info->index = index;
info->start = block;
@@ -373,7 +379,7 @@ struct connman_ippool *__connman_ippool_create(int index,
if (range == 0)
range = 1;
- pool->gateway = get_ip(info->start + 1);
+ pool->gateway = get_ip(info->start + (start > 1 ? start - 1 : 1));
pool->broadcast = get_ip(info->start + 255);
pool->subnet_mask = get_ip(subnet_mask_24);
pool->start_ip = get_ip(block + start);
@@ -140,7 +140,7 @@ static int start_dhcp_server(struct connman_peer *peer)
else
index = connman_device_get_index(peer->device);
- peer->ip_pool = __connman_ippool_create(index, 2, 1, NULL, NULL);
+ peer->ip_pool = __connman_ippool_create(index, 0, 2, 1, NULL, NULL);
if (!peer->ip_pool)
goto error;
@@ -69,6 +69,7 @@ struct connman_technology {
char *tethering_ident;
char *tethering_passphrase;
int tethering_freq;
+ struct connman_ipaddress *tethering_address;
bool enable_persistent; /* Save the tech state */
@@ -202,6 +203,11 @@ static void technology_save(struct connman_technology *technology)
"Tethering.Freq",
technology->tethering_freq);
+ if (technology->tethering_address)
+ g_key_file_set_string(keyfile, identifier,
+ "Tethering.Address",
+ technology->tethering_address->local);
+
done:
g_free(identifier);
@@ -232,6 +238,10 @@ int connman_technology_tethering_notify(struct connman_technology *technology,
return -EALREADY;
if (enabled) {
+ if (technology->tethering_address && technology->tethering_address->local)
+ __connman_tethering_set_ip(ntohl(inet_addr(technology->tethering_address->local)));
+ else
+ __connman_tethering_set_ip(0);
err = __connman_tethering_set_enabled();
if (err < 0)
return err;
@@ -487,6 +497,16 @@ static void technology_load(struct connman_technology *technology)
technology->tethering_freq = g_key_file_get_integer(keyfile,
identifier, "Tethering.Freq", NULL);
+ enc = g_key_file_get_string(keyfile,
+ identifier, "Tethering.Address", NULL);
+ if (enc) {
+ if (!technology->tethering_address)
+ technology->tethering_address = connman_ipaddress_alloc(AF_INET);
+
+ connman_ipaddress_set_ipv4(technology->tethering_address,
+ enc, "255.255.255.0", NULL);
+ }
+
done:
g_free(identifier);
@@ -602,6 +622,11 @@ static void append_properties(DBusMessageIter *iter,
DBUS_TYPE_INT32,
&technology->tethering_freq);
+ if (technology->tethering_address)
+ connman_dbus_dict_append_basic(&dict, "TetheringAddress",
+ DBUS_TYPE_STRING,
+ &technology->tethering_address->local);
+
connman_dbus_dict_close(iter, &dict);
}
@@ -1037,6 +1062,29 @@ static DBusMessage *set_property(DBusConnection *conn,
DBUS_TYPE_INT32,
&technology->tethering_freq);
}
+ } else if (g_str_equal(name, "TetheringAddress")) {
+ const char *address;
+
+ if (type != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
+ return __connman_error_not_supported(msg);
+
+ dbus_message_iter_get_basic(&value, &address);
+
+ if (g_str_equal(address, "")) {
+ if (technology->tethering_address) {
+ connman_ipaddress_free(technology->tethering_address);
+ technology->tethering_address = NULL;
+ }
+ } else {
+ if (!technology->tethering_address)
+ technology->tethering_address = connman_ipaddress_alloc(AF_INET);
+
+ connman_ipaddress_set_ipv4(technology->tethering_address,
+ address, "255.255.255.0", NULL);
+ }
} else if (g_str_equal(name, "Powered")) {
dbus_bool_t enable;
@@ -1257,6 +1305,7 @@ static void technology_put(struct connman_technology *technology)
g_free(technology->regdom);
g_free(technology->tethering_ident);
g_free(technology->tethering_passphrase);
+ connman_ipaddress_free(technology->tethering_address);
g_free(technology);
}
@@ -56,6 +56,7 @@ static char *private_network_primary_dns = NULL;
static char *private_network_secondary_dns = NULL;
static volatile int tethering_enabled;
+static uint32_t tethering_ip_address;
static GDHCPServer *tethering_dhcp_server = NULL;
static struct connman_ippool *dhcp_ippool = NULL;
static DBusConnection *connection;
@@ -200,6 +201,14 @@ static void unregister_all_clients(void)
g_hash_table_foreach(clients_table, unregister_client, NULL);
}
+int __connman_tethering_set_ip(uint32_t ip)
+{
+ tethering_ip_address = ip;
+ if ((tethering_ip_address & 0xff) == 0)
+ tethering_ip_address |= 1;
+ return 0;
+}
+
int __connman_tethering_set_enabled(void)
{
int index;
@@ -225,7 +234,9 @@ int __connman_tethering_set_enabled(void)
}
index = connman_inet_ifindex(BRIDGE_NAME);
- dhcp_ippool = __connman_ippool_create(index, 2, 252,
+ dhcp_ippool = __connman_ippool_create(index, tethering_ip_address & ~0xff,
+ 1 + (tethering_ip_address & 0xff),
+ 253 - (tethering_ip_address & 0xff),
tethering_restart, NULL);
if (!dhcp_ippool) {
connman_error("Fail to create IP pool");
@@ -592,7 +603,7 @@ int __connman_private_network_request(DBusMessage *msg, const char *owner)
pn->fd = fd;
pn->interface = iface;
pn->index = index;
- pn->pool = __connman_ippool_create(pn->index, 1, 1, ippool_disconnect, pn);
+ pn->pool = __connman_ippool_create(pn->index, 0, 1, 1, ippool_disconnect, pn);
if (!pn->pool) {
errno = -ENOMEM;
goto error;
@@ -46,11 +46,11 @@ static void test_case_1(void)
__connman_ippool_init();
- pool = __connman_ippool_create(23, 1, 500, NULL, NULL);
+ pool = __connman_ippool_create(23, 0, 1, 500, NULL, NULL);
g_assert(!pool);
for (i = 0; i < 100000; i++) {
- pool = __connman_ippool_create(23, 1, 20, NULL, NULL);
+ pool = __connman_ippool_create(23, 0, 1, 20, NULL, NULL);
g_assert(pool);
__connman_ippool_free(pool);
@@ -73,7 +73,7 @@ static void test_case_2(void)
/* Test the IP range */
for (i = 1; i < 254; i++) {
- pool = __connman_ippool_create(23, 1, i, NULL, NULL);
+ pool = __connman_ippool_create(23, 0, 1, i, NULL, NULL);
g_assert(pool);
gateway = __connman_ippool_get_gateway(pool);
@@ -130,7 +130,7 @@ static void test_case_3(void)
__connman_ippool_newaddr(46, "172.16.0.1", 11);
while (TRUE) {
- pool = __connman_ippool_create(23, 1, 100, NULL, NULL);
+ pool = __connman_ippool_create(23, 0, 1, 100, NULL, NULL);
if (!pool)
break;
i += 1;
@@ -192,7 +192,7 @@ static void test_case_4(void)
/* Test the IP range collision */
flag = 0;
- pool = __connman_ippool_create(23, 1, 100, collision_cb, &flag);
+ pool = __connman_ippool_create(23, 0, 1, 100, collision_cb, &flag);
g_assert(pool);
gateway = __connman_ippool_get_gateway(pool);
@@ -223,7 +223,7 @@ static void test_case_4(void)
flag = 0;
- pool = __connman_ippool_create(23, 1, 100, collision_cb, &flag);
+ pool = __connman_ippool_create(23, 0, 1, 100, collision_cb, &flag);
g_assert(pool);
gateway = __connman_ippool_get_gateway(pool);
@@ -271,7 +271,7 @@ static void test_case_5(void)
g_assert(flag == 0);
/* pool should return 192.168.0.1 now */
- pool1 = __connman_ippool_create(26, 1, 100, collision_cb, &flag);
+ pool1 = __connman_ippool_create(26, 0, 1, 100, collision_cb, &flag);
g_assert(pool1);
gateway = __connman_ippool_get_gateway(pool1);
@@ -303,7 +303,7 @@ static void test_case_5(void)
/* pool should return 192.168.2.1 now */
flag = 0;
- pool2 = __connman_ippool_create(23, 1, 100, collision_cb, &flag);
+ pool2 = __connman_ippool_create(23, 0, 1, 100, collision_cb, &flag);
g_assert(pool2);
gateway = __connman_ippool_get_gateway(pool2);
@@ -361,7 +361,7 @@ static void test_case_6(void)
g_assert(flag == 0);
/* pool should return 192.168.2.1 now */
- pool1 = __connman_ippool_create(26, 1, 100, collision_cb, &flag);
+ pool1 = __connman_ippool_create(26, 0, 1, 100, collision_cb, &flag);
g_assert(pool1);
gateway = __connman_ippool_get_gateway(pool1);
@@ -393,7 +393,7 @@ static void test_case_6(void)
/* pool should return 192.168.3.1 now */
flag = 0;
- pool2 = __connman_ippool_create(23, 1, 100, collision_cb, &flag);
+ pool2 = __connman_ippool_create(23, 0, 1, 100, collision_cb, &flag);
g_assert(pool2);
gateway = __connman_ippool_get_gateway(pool2);