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