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

Reply via email to