Currently, only the peer as a client is supported. As a P2P peer is
always in IPv4 via DHCP there is just one ipconfig object, only handled
through dhcpv4.
---
 plugins/wifi.c |   5 ++-
 src/peer.c     | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 124 insertions(+), 1 deletion(-)

diff --git a/plugins/wifi.c b/plugins/wifi.c
index 48a9cf3..3c8f26f 100644
--- a/plugins/wifi.c
+++ b/plugins/wifi.c
@@ -2080,6 +2080,7 @@ static void peer_found(GSupplicantPeer *peer)
        struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
        struct connman_peer *connman_peer;
        const char *identifier, *name;
+       int ret;
 
        identifier = g_supplicant_peer_get_identifier(peer);
        name = g_supplicant_peer_get_name(peer);
@@ -2094,7 +2095,9 @@ static void peer_found(GSupplicantPeer *peer)
        connman_peer_set_name(connman_peer, name);
        connman_peer_set_device(connman_peer, wifi->device);
 
-       connman_peer_register(connman_peer);
+       ret = connman_peer_register(connman_peer);
+       if (ret < 0 && ret != -EALREADY)
+               connman_peer_unref(connman_peer);
 }
 
 static void peer_lost(GSupplicantPeer *peer)
diff --git a/src/peer.c b/src/peer.c
index a0134d7..80120fc 100644
--- a/src/peer.c
+++ b/src/peer.c
@@ -47,6 +47,7 @@ struct connman_peer {
        char *name;
        char *path;
        enum connman_peer_state state;
+       struct connman_ipconfig *ipconfig;
        bool registered;
 };
 
@@ -61,6 +62,13 @@ static void peer_free(gpointer data)
                peer->path = NULL;
        }
 
+       if (peer->ipconfig) {
+               __connman_ipconfig_set_ops(peer->ipconfig, NULL);
+               __connman_ipconfig_set_data(peer->ipconfig, NULL);
+               __connman_ipconfig_unref(peer->ipconfig);
+               peer->ipconfig = NULL;
+       }
+
        if (peer->device) {
                connman_device_unref(peer->device);
                peer->device = NULL;
@@ -335,10 +343,34 @@ struct connman_device *connman_peer_get_device(struct 
connman_peer *peer)
        return peer->device;
 }
 
+static void dhcp_callback(struct connman_ipconfig *ipconfig,
+                       struct connman_network *network,
+                       bool success, gpointer data)
+{
+       struct connman_peer *peer = data;
+       int err;
+
+       if (!success)
+               goto error;
+
+       DBG("lease acquired for ipconfig %p", ipconfig);
+
+       err = __connman_ipconfig_address_add(ipconfig);
+       if (err < 0)
+               goto error;
+
+       return;
+
+error:
+       __connman_ipconfig_address_remove(ipconfig);
+       connman_peer_set_state(peer, CONNMAN_PEER_STATE_FAILURE);
+}
+
 int connman_peer_set_state(struct connman_peer *peer,
                                        enum connman_peer_state new_state)
 {
        enum connman_peer_state old_state = peer->state;
+       int err;
 
        if (old_state == new_state)
                return -EALREADY;
@@ -348,13 +380,24 @@ int connman_peer_set_state(struct connman_peer *peer,
                return -EINVAL;
        case CONNMAN_PEER_STATE_IDLE:
        case CONNMAN_PEER_STATE_ASSOCIATION:
+               break;
        case CONNMAN_PEER_STATE_CONFIGURATION:
+               __connman_ipconfig_enable(peer->ipconfig);
+
+               err = __connman_dhcp_start(peer->ipconfig,
+                                               NULL, dhcp_callback, peer);
+               if (err < 0)
+                       return connman_peer_set_state(peer,
+                                               CONNMAN_PEER_STATE_FAILURE);
                break;
        case CONNMAN_PEER_STATE_READY:
                break;
        case CONNMAN_PEER_STATE_DISCONNECT:
                break;
        case CONNMAN_PEER_STATE_FAILURE:
+               __connman_dhcp_stop(peer->ipconfig);
+               __connman_ipconfig_disable(peer->ipconfig);
+
                break;
        };
 
@@ -364,6 +407,76 @@ int connman_peer_set_state(struct connman_peer *peer,
        return 0;
 }
 
+static void peer_up(struct connman_ipconfig *ipconfig, const char *ifname)
+{
+       DBG("%s up", ifname);
+}
+
+static void peer_down(struct connman_ipconfig *ipconfig, const char *ifname)
+{
+       DBG("%s down", ifname);
+}
+
+static void peer_lower_up(struct connman_ipconfig *ipconfig,
+                                                       const char *ifname)
+{
+       DBG("%s lower up", ifname);
+}
+
+static void peer_lower_down(struct connman_ipconfig *ipconfig,
+                                                       const char *ifname)
+{
+       struct connman_peer *peer = __connman_ipconfig_get_data(ipconfig);
+
+       DBG("%s lower down", ifname);
+
+       __connman_ipconfig_disable(ipconfig);
+       connman_peer_set_state(peer, CONNMAN_PEER_STATE_DISCONNECT);
+}
+
+static void peer_ip_bound(struct connman_ipconfig *ipconfig,
+                                                       const char *ifname)
+{
+       struct connman_peer *peer = __connman_ipconfig_get_data(ipconfig);
+
+       DBG("%s ip bound", ifname);
+
+       connman_peer_set_state(peer, CONNMAN_PEER_STATE_READY);
+}
+
+static void peer_ip_release(struct connman_ipconfig *ipconfig,
+                                                       const char *ifname)
+{
+       DBG("%s ip release", ifname);
+}
+
+static const struct connman_ipconfig_ops peer_ip_ops = {
+       .up             = peer_up,
+       .down           = peer_down,
+       .lower_up       = peer_lower_up,
+       .lower_down     = peer_lower_down,
+       .ip_bound       = peer_ip_bound,
+       .ip_release     = peer_ip_release,
+       .route_set      = NULL,
+       .route_unset    = NULL,
+};
+
+static struct connman_ipconfig *create_ipconfig(int index, void *user_data)
+{
+       struct connman_ipconfig *ipconfig;
+
+       ipconfig = __connman_ipconfig_create(index,
+                                               CONNMAN_IPCONFIG_TYPE_IPV4);
+       if (!ipconfig)
+               return NULL;
+
+       __connman_ipconfig_set_method(ipconfig, CONNMAN_IPCONFIG_METHOD_DHCP);
+       __connman_ipconfig_set_data(ipconfig, user_data);
+       __connman_ipconfig_set_ops(ipconfig, &peer_ip_ops);
+
+       return ipconfig;
+}
+
 static const GDBusMethodTable peer_methods[] = {
        { GDBUS_METHOD("GetProperties",
                        NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
@@ -388,11 +501,18 @@ static char *get_peer_path(struct connman_device *device,
 
 int connman_peer_register(struct connman_peer *peer)
 {
+       int index;
+
        DBG("peer %p", peer);
 
        if (peer->path && peer->registered)
                return -EALREADY;
 
+       index = connman_device_get_index(peer->device);
+       peer->ipconfig = create_ipconfig(index, peer);
+       if (!peer->ipconfig)
+               return -ENOMEM;
+
        peer->path = get_peer_path(peer->device, peer->identifier);
        DBG("path %s", peer->path);
 
-- 
1.8.5.5

_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman

Reply via email to