Hi Tomasz,

On ke, 2014-07-16 at 16:17 +0300, Tomasz Bursztyka wrote:
> This will finally handle the default case when our local device ends up
> as the P2P group owner and thus needs to be the dhcp server as well.
> ---
>  src/peer.c | 145 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 134 insertions(+), 11 deletions(-)
> 
> diff --git a/src/peer.c b/src/peer.c
> index 3a6f178..ff5483c 100644
> --- a/src/peer.c
> +++ b/src/peer.c
> @@ -25,6 +25,7 @@
>  
>  #include <errno.h>
>  #include <gdbus.h>
> +#include <gdhcp/gdhcp.h>
>  
>  #include "connman.h"
>  
> @@ -52,8 +53,12 @@ struct connman_peer {
>       DBusMessage *pending;
>       bool registered;
>       bool connection_master;
> +     struct connman_ippool *ip_pool;
> +     GDHCPServer *dhcp_server;
>  };
>  
> +static void stop_dhcp_server(struct connman_peer *peer);

Do we need forward declaration here? It looks like the
stop_dhcp_server() could be put here instead?

> +
>  static void reply_pending(struct connman_peer *peer, int error)
>  {
>       if (!peer->pending)
> @@ -83,6 +88,8 @@ static void peer_free(gpointer data)
>               peer->ipconfig = NULL;
>       }
>  
> +     stop_dhcp_server(peer);
> +
>       if (peer->device) {
>               connman_device_unref(peer->device);
>               peer->device = NULL;
> @@ -341,11 +348,14 @@ static int peer_disconnect(struct connman_peer *peer)
>  
>       reply_pending(peer, ECONNABORTED);
>  
> +     if (peer->connection_master)
> +             stop_dhcp_server(peer);
> +     else
> +             __connman_dhcp_stop(peer->ipconfig);
> +
>       if (peer_driver->disconnect)
>               err = peer_driver->disconnect(peer);
>  
> -     __connman_dhcp_stop(peer->ipconfig);
> -
>       return err;
>  }
>  
> @@ -493,6 +503,99 @@ void connman_peer_set_as_master(struct connman_peer 
> *peer, bool master)
>       peer->connection_master = master;
>  }
>  
> +static void stop_dhcp_server(struct connman_peer *peer)
> +{
> +     DBG("");
> +
> +     if (peer->dhcp_server) {
> +             g_dhcp_server_stop(peer->dhcp_server);
> +             g_dhcp_server_unref(peer->dhcp_server);
> +     }
> +     peer->dhcp_server = NULL;
> +
> +     if (peer->ip_pool)
> +             __connman_ippool_unref(peer->ip_pool);
> +     peer->ip_pool = NULL;
> +}

Moving this before reply_pending()?

> +
> +static void dhcp_server_debug(const char *str, void *data)
> +{
> +     connman_info("%s: %s\n", (const char *) data, str);
> +}
> +
> +static gboolean dhcp_server_started(gpointer data)
> +{
> +     struct connman_peer *peer = data;
> +
> +     connman_peer_set_state(peer, CONNMAN_PEER_STATE_READY);

What happens if this was last ref to peer and it is removed at this
point? Will the dhcp server be still active?

> +     connman_peer_unref(peer);
> +
> +     return FALSE;
> +}
> +
> +static int start_dhcp_server(struct connman_peer *peer)
> +{
> +     const char *start_ip, *end_ip;
> +     GDHCPServerError dhcp_error;
> +     const char *broadcast;
> +     const char *gateway;
> +     const char *subnet;
> +     int prefixlen;
> +     int index;
> +     int err;
> +
> +     DBG("");
> +
> +     err = -ENOMEM;
> +
> +     if (peer->sub_device)
> +             index = connman_device_get_index(peer->sub_device);
> +     else
> +             index = connman_device_get_index(peer->device);
> +
> +     peer->ip_pool = __connman_ippool_create(index, 2, 1, NULL, NULL);

Do we only support one address (==one client) here?

> +     if (!peer->ip_pool)
> +             goto error;
> +
> +     gateway = __connman_ippool_get_gateway(peer->ip_pool);
> +     subnet = __connman_ippool_get_subnet_mask(peer->ip_pool);
> +     broadcast = __connman_ippool_get_broadcast(peer->ip_pool);
> +     start_ip = __connman_ippool_get_start_ip(peer->ip_pool);
> +     end_ip = __connman_ippool_get_end_ip(peer->ip_pool);
> +
> +     prefixlen = connman_ipaddress_calc_netmask_len(subnet);
> +
> +     err = __connman_inet_modify_address(RTM_NEWADDR,
> +                             NLM_F_REPLACE | NLM_F_ACK, index, AF_INET,
> +                             gateway, NULL, prefixlen, broadcast);
> +     if (err < 0)
> +             goto error;
> +
> +     peer->dhcp_server = g_dhcp_server_new(G_DHCP_IPV4, index, &dhcp_error);
> +     if (!peer->dhcp_server)
> +             goto error;
> +
> +     g_dhcp_server_set_debug(peer->dhcp_server,
> +                                     dhcp_server_debug, "Peer DHCP server");
> +     g_dhcp_server_set_lease_time(peer->dhcp_server, 3600);
> +     g_dhcp_server_set_option(peer->dhcp_server, G_DHCP_SUBNET, subnet);
> +     g_dhcp_server_set_option(peer->dhcp_server, G_DHCP_ROUTER, gateway);
> +     g_dhcp_server_set_option(peer->dhcp_server, G_DHCP_DNS_SERVER, NULL);
> +     g_dhcp_server_set_ip_range(peer->dhcp_server, start_ip, end_ip);
> +
> +     err = g_dhcp_server_start(peer->dhcp_server);
> +     if (err < 0)
> +             goto error;
> +
> +     g_timeout_add_seconds(0, dhcp_server_started, connman_peer_ref(peer));
> +
> +     return 0;
> +
> +error:
> +     stop_dhcp_server(peer);
> +     return err;
> +}
> +
>  static void dhcp_callback(struct connman_ipconfig *ipconfig,
>                       struct connman_network *network,
>                       bool success, gpointer data)
> @@ -516,6 +619,17 @@ error:
>       connman_peer_set_state(peer, CONNMAN_PEER_STATE_FAILURE);
>  }
>  
> +static int start_dhcp_client(struct connman_peer *peer)
> +{
> +     if (peer->sub_device)
> +             __connman_ipconfig_set_index(peer->ipconfig,
> +                             connman_device_get_index(peer->sub_device));
> +
> +     __connman_ipconfig_enable(peer->ipconfig);
> +
> +     return __connman_dhcp_start(peer->ipconfig, NULL, dhcp_callback, peer);
> +}
> +
>  int connman_peer_set_state(struct connman_peer *peer,
>                                       enum connman_peer_state new_state)
>  {
> @@ -534,13 +648,10 @@ int connman_peer_set_state(struct connman_peer *peer,
>       case CONNMAN_PEER_STATE_ASSOCIATION:
>               break;
>       case CONNMAN_PEER_STATE_CONFIGURATION:
> -             if (peer->sub_device)
> -                     __connman_ipconfig_set_index(peer->ipconfig,
> -                             connman_device_get_index(peer->sub_device));
> -             __connman_ipconfig_enable(peer->ipconfig);
> -
> -             err = __connman_dhcp_start(peer->ipconfig,
> -                                             NULL, dhcp_callback, peer);
> +             if (peer->connection_master)
> +                     err = start_dhcp_server(peer);
> +             else
> +                     err = start_dhcp_client(peer);
>               if (err < 0)
>                       return connman_peer_set_state(peer,
>                                               CONNMAN_PEER_STATE_FAILURE);
> @@ -549,12 +660,24 @@ int connman_peer_set_state(struct connman_peer *peer,
>               reply_pending(peer, 0);
>               break;
>       case CONNMAN_PEER_STATE_DISCONNECT:
> +             if (peer->connection_master)
> +                     stop_dhcp_server(peer);
> +             peer->connection_master = false;
>               peer->sub_device = NULL;
> +
>               break;
>       case CONNMAN_PEER_STATE_FAILURE:
>               reply_pending(peer, ENOTCONN);
> -             __connman_dhcp_stop(peer->ipconfig);
> -             __connman_ipconfig_disable(peer->ipconfig);
> +
> +             peer_disconnect(peer);
> +
> +             if (!peer->connection_master) {
> +                     __connman_dhcp_stop(peer->ipconfig);
> +                     __connman_ipconfig_disable(peer->ipconfig);
> +             } else
> +                     stop_dhcp_server(peer);
> +
> +             peer->connection_master = false;
>               peer->sub_device = NULL;
>  
>               break;


Cheers,
Jukka


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

Reply via email to