From: Sjur Brændeland <sjur.brandel...@stericsson.com> Use rtnl_caif_* functions to create network interfaces. The conn_info struct is also re-structured in order to hold the relevant information for network interfaces. --- drivers/stemodem/gprs-context.c | 76 ++++++++++++++++++++++++++++++++++----- 1 files changed, 67 insertions(+), 9 deletions(-)
diff --git a/drivers/stemodem/gprs-context.c b/drivers/stemodem/gprs-context.c index 62643ee..8b5cfdc 100644 --- a/drivers/stemodem/gprs-context.c +++ b/drivers/stemodem/gprs-context.c @@ -47,6 +47,7 @@ #include "stemodem.h" #include "caif_socket.h" #include "if_caif.h" +#include "caif_rtnl.h" #define MAX_CAIF_DEVICES 4 #define MAX_DNS 2 @@ -66,10 +67,18 @@ struct gprs_context_data { }; struct conn_info { + /* + * cid is allocated in oFono Core and is identifying + * the Account. cid = 0 indicates that it is currently unused. + */ unsigned int cid; - unsigned int device; + /* Id used by CAIF and EPPSD to identify the CAIF channel*/ unsigned int channel_id; - char interface[10]; + /* Linux Interface Id */ + unsigned int ifindex; + /* Linux Interface name */ + char interface[IF_NAMESIZE]; + gboolean created; }; struct eppsd_response { @@ -77,7 +86,6 @@ struct eppsd_response { char ip_address[IP_ADDR_LEN]; char subnet_mask[IP_ADDR_LEN]; char mtu[IP_ADDR_LEN]; - char default_gateway[IP_ADDR_LEN]; char dns_server1[IP_ADDR_LEN]; char dns_server2[IP_ADDR_LEN]; char p_cscf_server[IP_ADDR_LEN]; @@ -97,8 +105,6 @@ static void start_element_handler(GMarkupParseContext *context, rsp->current = rsp->subnet_mask; else if (!strcmp(element_name, "mtu")) rsp->current = rsp->mtu; - else if (!strcmp(element_name, "default_gateway")) - rsp->current = rsp->default_gateway; else if (!strcmp(element_name, "dns_server") && rsp->dns_server1[0] == '\0') rsp->current = rsp->dns_server1; @@ -124,7 +130,7 @@ static void text_handler(GMarkupParseContext *context, if (rsp->current) { strncpy(rsp->current, text, IP_ADDR_LEN); - rsp->current[IP_ADDR_LEN] = 0; + rsp->current[IP_ADDR_LEN] = '\0'; } } @@ -167,12 +173,38 @@ static struct conn_info *conn_info_create(unsigned int channel_id) return connection; } +static void rtnl_callback(int ifindex, char *ifname, void *user_data) +{ + struct conn_info *conn = user_data; + + if (ifindex < 0) { + conn->created = FALSE; + ofono_error("Failed to create caif interface %s", + conn->interface); + return; + } + + strncpy(conn->interface, ifname, sizeof(conn->interface)); + conn->ifindex = ifindex; + conn->created = TRUE; +} + /* * Creates a new IP interface for CAIF. */ static gboolean caif_if_create(struct conn_info *conn) { - return FALSE; + int err; + + err = caif_rtnl_create_interface(IFLA_CAIF_IPV4_CONNID, + conn->channel_id, FALSE, + rtnl_callback, conn); + if (err < 0) { + DBG("Failed to create IP interface for CAIF"); + return FALSE; + } + + return TRUE; } /* @@ -180,6 +212,18 @@ static gboolean caif_if_create(struct conn_info *conn) */ static void caif_if_remove(struct conn_info *conn) { + if (!conn->created) + return; + + if (caif_rtnl_delete_interface(conn->ifindex) < 0) { + ofono_error("Failed to delete caif interface %s", + conn->interface); + return; + } + + DBG("removed CAIF interface ch:%d ifname:%s ifindex:%d\n", + conn->channel_id, conn->interface, conn->ifindex); + return; } static void ste_eppsd_down_cb(gboolean ok, GAtResult *result, @@ -283,7 +327,7 @@ static void ste_eppsd_up_cb(gboolean ok, GAtResult *result, gpointer user_data) dns[2] = NULL; CALLBACK_WITH_SUCCESS(cb, conn->interface, TRUE, rsp.ip_address, - rsp.subnet_mask, rsp.default_gateway, + rsp.subnet_mask, NULL, dns, cbd->data); return; @@ -380,6 +424,11 @@ static void ste_gprs_activate_primary(struct ofono_gprs_context *gc, } conn = l->data; + if (!conn->created) { + DBG("CAIF interface not created (rtnl error?)"); + goto error; + } + conn->cid = ctx->cid; len = snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IP\"", ctx->cid); @@ -460,6 +509,7 @@ static void ste_cgact_read_cb(gboolean ok, GAtResult *result, struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); gint cid, state; GAtResultIter iter; + GSList *l; if (!ok) return; @@ -483,6 +533,13 @@ static void ste_cgact_read_cb(gboolean ok, GAtResult *result, ofono_gprs_context_deactivated(gc, gcd->active_context); gcd->active_context = 0; + l = g_slist_find_custom(g_caif_devices, GUINT_TO_POINTER(cid), + conn_compare_by_cid); + if (l) { + struct conn_info *conn = l->data; + conn->cid = 0; + } + break; } } @@ -540,7 +597,6 @@ static int ste_gprs_context_probe(struct ofono_gprs_context *gc, static void ste_gprs_context_remove(struct ofono_gprs_context *gc) { struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); - g_slist_foreach(g_caif_devices, (GFunc) caif_if_remove, NULL); g_slist_foreach(g_caif_devices, (GFunc) g_free, NULL); g_slist_free(g_caif_devices); @@ -562,10 +618,12 @@ static struct ofono_gprs_context_driver driver = { void ste_gprs_context_init() { + caif_rtnl_init(); ofono_gprs_context_driver_register(&driver); } void ste_gprs_context_exit() { + caif_rtnl_exit(); ofono_gprs_context_driver_unregister(&driver); } -- 1.6.3.3 _______________________________________________ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono