---
include/gprs-context.h | 2 +-
src/gprs.c | 296 +++++++++++++++++++++++++++++++-----------------
2 files changed, 192 insertions(+), 106 deletions(-)
diff --git a/include/gprs-context.h b/include/gprs-context.h
index 88530f6..d03dd47 100644
--- a/include/gprs-context.h
+++ b/include/gprs-context.h
@@ -77,7 +77,7 @@ struct ofono_gprs_context_driver {
void (*remove)(struct ofono_gprs_context *gc);
void (*activate_primary)(struct ofono_gprs_context *gc,
const struct ofono_gprs_primary_context *ctx,
- ofono_gprs_context_up_cb_t cb, void *data);
+ ofono_gprs_context_cb_t cb, void *data);
void (*deactivate_primary)(struct ofono_gprs_context *gc,
unsigned int id,
ofono_gprs_context_cb_t cb, void *data);
diff --git a/src/gprs.c b/src/gprs.c
index 7d36633..b5dd5f2 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -99,10 +99,12 @@ struct ofono_gprs {
struct ofono_atom *atom;
};
+struct pri_context;
+
struct ofono_gprs_context {
struct ofono_gprs *gprs;
+ struct pri_context *pri;
enum ofono_gprs_context_type type;
- ofono_bool_t inuse;
const struct ofono_gprs_context_driver *driver;
void *driver_data;
struct ofono_atom *atom;
@@ -111,12 +113,13 @@ struct ofono_gprs_context {
struct context_settings {
enum ofono_gprs_context_type type;
char *interface;
- gboolean static_ip;
+ enum ofono_gprs_addrconf method;
char *ip;
char *netmask;
char *gateway;
char **dns;
char *proxy;
+ char *ipv6addr;
};
struct pri_context {
@@ -226,6 +229,8 @@ static const char *gprs_proto_to_string(enum ofono_gprs_proto proto)
return "ip";
case OFONO_GPRS_PROTO_IPV6:
return "ipv6";
+ case OFONO_GPRS_PROTO_IPV4V6:
+ return "ipv4v6";
};
return NULL;
@@ -240,11 +245,28 @@ static gboolean gprs_proto_from_string(const char *str,
} else if (g_str_equal(str, "ipv6")) {
*proto = OFONO_GPRS_PROTO_IPV6;
return TRUE;
+ } else if (g_str_equal(str, "ipv4v6")) {
+ *proto = OFONO_GPRS_PROTO_IPV4V6;
+ return TRUE;
}
return FALSE;
}
+static const char *gprs_addrconf_to_string(enum ofono_gprs_addrconf method)
+{
+ switch (method) {
+ case OFONO_GPRS_ADDRCONF_NONE:
+ return NULL;
+ case OFONO_GPRS_ADDRCONF_STATIC:
+ return "static";
+ case OFONO_GPRS_ADDRCONF_DHCP:
+ return "dhcp";
+ }
+
+ return NULL;
+}
+
static unsigned int gprs_cid_alloc(struct ofono_gprs *gprs)
{
return idmap_alloc(gprs->cid_map);
@@ -255,6 +277,49 @@ static void gprs_cid_release(struct ofono_gprs *gprs, unsigned int
id)
idmap_put(gprs->cid_map, id);
}
+static gboolean assign_context(struct pri_context *ctx)
+{
+ struct idmap *cidmap = ctx->gprs->cid_map;
+ unsigned int cid_min;
+ GSList *l;
+
+ if (cidmap == NULL)
+ return FALSE;
+
+ cid_min = idmap_get_min(cidmap);
+
+ ctx->context.cid = gprs_cid_alloc(ctx->gprs);
+ if (ctx->context.cid == 0)
+ return FALSE;
+
+ for (l = ctx->gprs->context_drivers; l; l = l->next) {
+ struct ofono_gprs_context *gc = l->data;
+
+ if (gc->pri != NULL)
+ continue;
+
+ if (gc->type == OFONO_GPRS_CONTEXT_TYPE_ANY ||
+ gc->type == ctx->type) {
+ gc->pri = ctx;
+ ctx->context_driver = gc;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static void release_context(struct pri_context *ctx)
+{
+ if (ctx == NULL || ctx->gprs == NULL)
+ return;
+
+ gprs_cid_release(ctx->gprs, ctx->context.cid);
+ ctx->context.cid = 0;
+ ctx->context_driver->pri = NULL;
+ ctx->context_driver = NULL;
+}
+
static struct pri_context *gprs_context_by_path(struct ofono_gprs *gprs,
const char *ctx_path)
{
@@ -278,6 +343,7 @@ static void context_settings_free(struct context_settings *settings)
g_free(settings->gateway);
g_strfreev(settings->dns);
g_free(settings->proxy);
+ g_free(settings->ipv6addr);
g_free(settings);
}
@@ -316,12 +382,10 @@ static void context_settings_append_variant(struct context_settings
*settings,
goto done;
}
- if (settings->static_ip == TRUE)
- method = "static";
- else
- method = "dhcp";
-
- ofono_dbus_dict_append(&array, "Method", DBUS_TYPE_STRING, &method);
+ method = gprs_addrconf_to_string(settings->method);
+ if (method != NULL)
+ ofono_dbus_dict_append(&array, "Method", DBUS_TYPE_STRING,
+ &method);
if (settings->ip)
ofono_dbus_dict_append(&array, "Address", DBUS_TYPE_STRING,
@@ -335,6 +399,19 @@ static void context_settings_append_variant(struct context_settings
*settings,
ofono_dbus_dict_append(&array, "Gateway", DBUS_TYPE_STRING,
&settings->gateway);
+ if (settings->ipv6addr != NULL) {
+ uint8_t addr[16];
+ char *strll = alloca(INET6_ADDRSTRLEN);
+
+ inet_pton(AF_INET6, settings->ipv6addr, addr);
+ memset(addr, 0, 8);
+ addr[0] = 0xfe;
+ addr[1] = 0x80;
+ inet_ntop(AF_INET6, addr, strll, INET6_ADDRSTRLEN);
+ ofono_dbus_dict_append(&array, "IPv6Address", DBUS_TYPE_STRING,
+ &strll);
+ }
+
if (settings->dns)
ofono_dbus_dict_append_array(&array, "DomainNameServers",
DBUS_TYPE_STRING,
@@ -578,42 +655,27 @@ static void pri_reset_context_settings(struct pri_context *ctx)
g_free(interface);
}
-static void pri_update_context_settings(struct pri_context *ctx,
- const char *interface,
- ofono_bool_t static_ip,
- const char *ip, const char *netmask,
- const char *gateway, const char **dns)
+static void pri_update_context_settings(struct pri_context *ctx)
{
- if (ctx->settings)
- context_settings_free(ctx->settings);
-
- ctx->settings = g_try_new0(struct context_settings, 1);
- if (ctx->settings == NULL)
+ if (ctx->settings == NULL || ctx->settings->interface == NULL)
return;
ctx->settings->type = ctx->type;
- ctx->settings->interface = g_strdup(interface);
- ctx->settings->static_ip = static_ip;
- ctx->settings->ip = g_strdup(ip);
- ctx->settings->netmask = g_strdup(netmask);
- ctx->settings->gateway = g_strdup(gateway);
- ctx->settings->dns = g_strdupv((char **)dns);
-
if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_MMS && ctx->message_proxy)
ctx->settings->proxy = g_strdup(ctx->message_proxy);
- pri_ifupdown(interface, TRUE);
+ pri_ifupdown(ctx->settings->interface, TRUE);
if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_MMS) {
pri_parse_proxy(ctx, ctx->message_proxy);
DBG("proxy %s port %u", ctx->proxy_host, ctx->proxy_port);
- pri_setaddr(interface, ip);
+ pri_setaddr(ctx->settings->interface, ctx->settings->ip);
if (ctx->proxy_host)
- pri_setproxy(interface, ctx->proxy_host);
+ pri_setproxy(ctx->settings->interface, ctx->proxy_host);
}
pri_context_signal_settings(ctx);
@@ -685,30 +747,18 @@ static DBusMessage *pri_get_properties(DBusConnection *conn,
return reply;
}
-static void pri_activate_callback(const struct ofono_error *error,
- const char *interface,
- ofono_bool_t static_ip,
- const char *ip, const char *netmask,
- const char *gateway, const char **dns,
- void *data)
+static void pri_activate_callback(const struct ofono_error *error, void *data)
{
struct pri_context *ctx = data;
DBusConnection *conn = ofono_dbus_get_connection();
dbus_bool_t value;
- DBG("%p %s", ctx, interface);
-
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
DBG("Activating context failed with error: %s",
telephony_error_to_str(error));
__ofono_dbus_pending_reply(&ctx->pending,
__ofono_error_failed(ctx->pending));
-
- gprs_cid_release(ctx->gprs, ctx->context.cid);
- ctx->context.cid = 0;
- ctx->context_driver->inuse = FALSE;
- ctx->context_driver = NULL;
-
+ release_context(ctx);
return;
}
@@ -716,14 +766,7 @@ static void pri_activate_callback(const struct ofono_error *error,
__ofono_dbus_pending_reply(&ctx->pending,
dbus_message_new_method_return(ctx->pending));
- /*
- * If we don't have the interface, don't bother emitting any settings,
- * as nobody can make use of them
- */
- if (interface != NULL)
- pri_update_context_settings(ctx, interface, static_ip,
- ip, netmask, gateway, dns);
-
+ pri_update_context_settings(ctx);
value = ctx->active;
ofono_dbus_signal_property_changed(conn, ctx->path,
OFONO_CONNECTION_CONTEXT_INTERFACE,
@@ -744,11 +787,8 @@ static void pri_deactivate_callback(const struct ofono_error *error,
void *data)
return;
}
- gprs_cid_release(ctx->gprs, ctx->context.cid);
- ctx->context.cid = 0;
+ release_context(ctx);
ctx->active = FALSE;
- ctx->context_driver->inuse = FALSE;
- ctx->context_driver = NULL;
__ofono_dbus_pending_reply(&ctx->pending,
dbus_message_new_method_return(ctx->pending));
@@ -995,38 +1035,6 @@ static DBusMessage *pri_set_message_center(struct pri_context *ctx,
return NULL;
}
-static gboolean assign_context(struct pri_context *ctx)
-{
- struct idmap *cidmap = ctx->gprs->cid_map;
- unsigned int cid_min;
- GSList *l;
-
- if (cidmap == NULL)
- return FALSE;
-
- cid_min = idmap_get_min(cidmap);
-
- ctx->context.cid = gprs_cid_alloc(ctx->gprs);
- if (ctx->context.cid == 0)
- return FALSE;
-
- for (l = ctx->gprs->context_drivers; l; l = l->next) {
- struct ofono_gprs_context *gc = l->data;
-
- if (gc->inuse == TRUE)
- continue;
-
- if (gc->type == OFONO_GPRS_CONTEXT_TYPE_ANY ||
- gc->type == ctx->type) {
- ctx->context_driver = gc;
- ctx->context_driver->inuse = TRUE;
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
static DBusMessage *pri_set_property(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -1179,6 +1187,8 @@ static GDBusSignalTable context_signals[] = {
{ }
};
+
+
static struct pri_context *pri_context_create(struct ofono_gprs *gprs,
const char *name,
enum ofono_gprs_context_type type)
@@ -1344,14 +1354,9 @@ static void gprs_attached_update(struct ofono_gprs *gprs)
if (ctx->active == FALSE)
continue;
- gprs_cid_release(gprs, ctx->context.cid);
- ctx->context.cid = 0;
+ release_context(ctx);
ctx->active = FALSE;
- ctx->context_driver->inuse = FALSE;
- ctx->context_driver = NULL;
-
pri_reset_context_settings(ctx);
-
value = FALSE;
ofono_dbus_signal_property_changed(conn, ctx->path,
OFONO_CONNECTION_CONTEXT_INTERFACE,
@@ -1736,10 +1741,7 @@ static void gprs_deactivate_for_remove(const struct ofono_error
*error,
return;
}
- gprs_cid_release(gprs, ctx->context.cid);
- ctx->context.cid = 0;
- ctx->context_driver->inuse = FALSE;
- ctx->context_driver = NULL;
+ release_context(ctx);
if (gprs->settings) {
g_key_file_remove_group(gprs->settings, ctx->key, NULL);
@@ -1831,12 +1833,9 @@ static void gprs_deactivate_for_all(const struct ofono_error
*error,
return;
}
- gprs_cid_release(gprs, ctx->context.cid);
- ctx->active = FALSE;
- ctx->context.cid = 0;
- ctx->context_driver->inuse = FALSE;
- ctx->context_driver = NULL;
+ release_context(ctx);
+ ctx->active = FALSE;
pri_reset_context_settings(ctx);
value = ctx->active;
@@ -2087,11 +2086,8 @@ void ofono_gprs_context_deactivated(struct ofono_gprs_context *gc,
if (ctx->active == FALSE)
break;
- gprs_cid_release(ctx->gprs, ctx->context.cid);
- ctx->context.cid = 0;
+ release_context(ctx);
ctx->active = FALSE;
- ctx->context_driver->inuse = FALSE;
- ctx->context_driver = NULL;
pri_reset_context_settings(ctx);
@@ -2130,6 +2126,8 @@ static void gprs_context_remove(struct ofono_atom *atom)
if (gc == NULL)
return;
+ release_context(gc->pri);
+
if (gc->driver && gc->driver->remove)
gc->driver->remove(gc);
@@ -2202,6 +2200,94 @@ void ofono_gprs_context_set_type(struct ofono_gprs_context *gc,
gc->type = type;
}
+static struct context_settings *get_settings(struct ofono_gprs_context *gc)
+{
+ if (gc == NULL || gc->pri == NULL)
+ return NULL;
+
+ if (gc->pri->settings == NULL)
+ gc->pri->settings = g_try_new0(struct context_settings, 1);
+
+ return gc->pri->settings;
+}
+
+void ofono_gprs_context_set_interface(struct ofono_gprs_context *gc,
+ const char *interface)
+{
+ struct context_settings *settings = get_settings(gc);
+
+ if (settings == NULL || settings->interface != NULL)
+ return;
+
+ settings->interface = g_strdup(interface);
+}
+
+void ofono_gprs_context_set_ip_addrconf(struct ofono_gprs_context *gc,
+ enum ofono_gprs_addrconf method)
+{
+ struct context_settings *settings = get_settings(gc);
+
+ if (settings == NULL)
+ return;
+
+ settings->method = method;
+}
+
+void ofono_gprs_context_set_ip_address(struct ofono_gprs_context *gc,
+ const char *address)
+{
+ struct context_settings *settings = get_settings(gc);
+
+ if (settings == NULL || settings->ip != NULL)
+ return;
+
+ settings->ip = g_strdup(address);
+}
+
+void ofono_gprs_context_set_ip_netmask(struct ofono_gprs_context *gc,
+ const char *netmask)
+{
+ struct context_settings *settings = get_settings(gc);
+
+ if (settings == NULL || settings->netmask != NULL)
+ return;
+
+ settings->netmask = g_strdup(netmask);
+}
+
+void ofono_gprs_context_set_ip_gateway(struct ofono_gprs_context *gc,
+ const char *gateway)
+{
+ struct context_settings *settings = get_settings(gc);
+
+ if (settings == NULL || settings->gateway != NULL)
+ return;
+
+ settings->gateway = g_strdup(gateway);
+}
+
+void ofono_gprs_context_set_ipv6_address(struct ofono_gprs_context *gc,
+ const char *address)
+{
+ struct context_settings *settings = get_settings(gc);
+
+ if (settings == NULL || settings->ipv6addr != NULL)
+ return;
+
+ settings->ipv6addr = g_strdup(address);
+}
+
+void ofono_gprs_context_set_dns_servers(struct ofono_gprs_context *gc,
+ const char **dns)
+{
+ struct context_settings *settings = get_settings(gc);
+
+ if (settings == NULL || settings->dns != NULL)
+ return;
+
+ settings->dns = g_strdupv((char **)dns);
+}
+
int ofono_gprs_driver_register(const struct ofono_gprs_driver *d)
{
DBG("driver: %p, name: %s", d, d->name);
--
1.7.1