Send connman mailing list submissions to
        [email protected]

To subscribe or unsubscribe via the World Wide Web, visit
        https://lists.01.org/mailman/listinfo/connman
or, via email, send a message with subject or body 'help' to
        [email protected]

You can reach the person managing the list at
        [email protected]

When replying, please edit your Subject line so it is more specific
than "Re: Contents of connman digest..."


Today's Topics:

   1. [RFC PATCH 20/27] service: init and start of acd
      (Peter Meerwald-Stadler)
   2. [RFC PATCH 22/27] service: add ipv4ll as fallback for acd
      (Peter Meerwald-Stadler)
   3. [RFC PATCH 18/27] acd: add handling of received arp packets
      (Peter Meerwald-Stadler)
   4. [RFC PATCH 23/27] acd: add dbus property for address conflict
      (Peter Meerwald-Stadler)
   5. [RFC PATCH 24/27] dhcp: add sending of DHCP decline
      (Peter Meerwald-Stadler)


----------------------------------------------------------------------

Message: 1
Date: Wed, 21 Mar 2018 14:42:30 +0100
From: Peter Meerwald-Stadler <[email protected]>
To: [email protected]
Cc: [email protected],     [email protected]
Subject: [RFC PATCH 20/27] service: init and start of acd
Message-ID: <[email protected]>

From: Christian Spielberger <[email protected]>

---
 src/service.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/src/service.c b/src/service.c
index 459e2534..57aa9359 100644
--- a/src/service.c
+++ b/src/service.c
@@ -35,6 +35,7 @@
 #include <connman/setting.h>
 #include <connman/agent.h>
 #include <connman/acd.h>
+#include <shared/arp.h>
 
 #include "connman.h"
 
@@ -7499,8 +7500,26 @@ void __connman_service_cleanup(void)
        dbus_connection_unref(connection);
 }
 
+static void acdhost_ipv4_available(ACDHost *acd, gpointer user_data)
+{
+}
+
+static void acdhost_ipv4_lost(ACDHost *acd, gpointer user_data)
+{
+}
+
+static void acdhost_ipv4_conflict(ACDHost *acd, gpointer user_data)
+{
+}
+
+static void acdhost_ipv4_maxconflict(ACDHost *acd, gpointer user_data)
+{
+}
+
 int connman_service_start_acd(struct connman_service *service)
 {
+       const char* address;
+       struct in_addr addr;
        if (!service)
                return -EINVAL;
 
@@ -7509,5 +7528,39 @@ int connman_service_start_acd(struct connman_service 
*service)
                return -EINVAL;
        }
 
+       if (!service->acdhost) {
+               int index;
+
+               index = __connman_ipconfig_get_index(service->ipconfig_ipv4);
+               service->acdhost = acdhost_new(index);
+               if (!service->acdhost) {
+                       connman_error("Could not create ACD data structure");
+                       return -EINVAL;
+               }
+
+               acdhost_register_event(service->acdhost,
+                               ACDHOST_EVENT_IPV4_AVAILABLE,
+                               acdhost_ipv4_available, service);
+               acdhost_register_event(service->acdhost,
+                               ACDHOST_EVENT_IPV4_LOST,
+                               acdhost_ipv4_lost, service);
+               acdhost_register_event(service->acdhost,
+                               ACDHOST_EVENT_IPV4_CONFLICT,
+                               acdhost_ipv4_conflict, service);
+               acdhost_register_event(service->acdhost,
+                               ACDHOST_EVENT_IPV4_MAXCONFLICT,
+                               acdhost_ipv4_maxconflict, service);
+       }
+
+       address = __connman_ipconfig_get_local(service->ipconfig_ipv4);
+       if (!address)
+               return -EINVAL;
+
+       connman_info("Starting ACD for address %s", address);
+       if (inet_pton(AF_INET, address, &addr) != 1)
+               connman_error("Could not convert address %s", address);
+
+       acdhost_start(service->acdhost, htonl(addr.s_addr));
+
        return 0;
 }
-- 
2.16.2



------------------------------

Message: 2
Date: Wed, 21 Mar 2018 14:42:32 +0100
From: Peter Meerwald-Stadler <[email protected]>
To: [email protected]
Cc: [email protected],     [email protected]
Subject: [RFC PATCH 22/27] service: add ipv4ll as fallback for acd
Message-ID: <[email protected]>

From: Christian Spielberger <[email protected]>

---
 src/service.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/src/service.c b/src/service.c
index 14e9a456..d8c0e5e7 100644
--- a/src/service.c
+++ b/src/service.c
@@ -99,6 +99,7 @@ struct connman_service {
        bool mdns;
        bool mdns_config;
        ACDHost *acdhost;
+       guint ipv4ll_timeout;
        char *hostname;
        char *domainname;
        char **timeservers;
@@ -145,6 +146,7 @@ static struct connman_ipconfig *create_ip4config(struct 
connman_service *service
 static struct connman_ipconfig *create_ip6config(struct connman_service 
*service,
                int index);
 static void dns_changed(struct connman_service *service);
+static void remove_ipv4ll_timeout(struct connman_service *service);
 
 struct find_data {
        const char *path;
@@ -4893,6 +4895,7 @@ static void service_initialize(struct connman_service 
*service)
        service->wps_advertizing = false;
 
        service->acdhost = NULL;
+       service->ipv4ll_timeout = 0;
 }
 
 /**
@@ -6448,6 +6451,7 @@ int __connman_service_disconnect(struct connman_service 
*service)
        service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE;
        service->proxy = CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
 
+       remove_ipv4ll_timeout(service);
        if (service->acdhost)
                acdhost_stop(service->acdhost);
 
@@ -7532,6 +7536,48 @@ err:
 
 static int service_start_ipv4ll(struct connman_service *service)
 {
+       struct in_addr addr;
+       char* address;
+
+       if (!service->ipconfig_ipv4) {
+               connman_error("Service has no IPv4 configuration");
+               return -EINVAL;
+       }
+
+       /* Apply random IP number. */
+       addr.s_addr = htonl(random_ip());
+       address = inet_ntoa(addr);
+       if (!address) {
+               connman_error("Could not convert IPv4LL random address %u",
+                               addr.s_addr);
+               return -EINVAL;
+       }
+       __connman_ipconfig_set_local(service->ipconfig_ipv4, address);
+
+       connman_info("Probing IPv4LL address %s", address);
+       return connman_service_start_acd(service);
+}
+
+static void remove_ipv4ll_timeout(struct connman_service *service)
+{
+       if (service->ipv4ll_timeout > 0) {
+               g_source_remove(service->ipv4ll_timeout);
+               service->ipv4ll_timeout = 0;
+       }
+}
+
+static gboolean start_ipv4ll_ontimeout(gpointer data)
+{
+       struct connman_service *service = data;
+
+       if (!service)
+               return FALSE;
+
+       /* Start IPv4LL ACD. */
+       if (service_start_ipv4ll(service) < 0)
+               connman_error("Could not start IPv4LL. No address will be 
assigned");
+
+       return FALSE;
 }
 
 static void acdhost_ipv4_lost(ACDHost *acd, gpointer user_data)
@@ -7582,9 +7628,16 @@ static void acdhost_ipv4_maxconflict(ACDHost *acd, 
gpointer user_data)
 {
        struct connman_service *service = user_data;
 
+       remove_ipv4ll_timeout(service);
        connman_info("Had maximum number of conflicts. Next IPv4LL address will 
be "
                        "tried in %d seconds", RATE_LIMIT_INTERVAL);
        /* Wait, then start IPv4LL ACD. */
+       service->ipv4ll_timeout =
+               g_timeout_add_seconds_full(G_PRIORITY_HIGH,
+                               RATE_LIMIT_INTERVAL,
+                               start_ipv4ll_ontimeout,
+                               service,
+                               NULL);
 }
 
 int connman_service_start_acd(struct connman_service *service)
@@ -7599,6 +7652,8 @@ int connman_service_start_acd(struct connman_service 
*service)
                return -EINVAL;
        }
 
+       remove_ipv4ll_timeout(service);
+
        if (!service->acdhost) {
                int index;
 
-- 
2.16.2



------------------------------

Message: 3
Date: Wed, 21 Mar 2018 14:42:28 +0100
From: Peter Meerwald-Stadler <[email protected]>
To: [email protected]
Cc: [email protected],     [email protected]
Subject: [RFC PATCH 18/27] acd: add handling of received arp packets
Message-ID: <[email protected]>

From: Christian Spielberger <[email protected]>

---
 src/acd.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/src/acd.c b/src/acd.c
index 2963d44e..aabbedd5 100644
--- a/src/acd.c
+++ b/src/acd.c
@@ -366,4 +366,86 @@ static gboolean acd_announce_timeout(gpointer acd_data)
 }
 
 static int acd_recv_arp_packet(ACDHost *acd) {
+       ssize_t cnt;
+       struct ether_arp arp;
+       uint32_t ip_n; /* network byte order */
+       struct in_addr addr;
+       int source_conflict;
+       int target_conflict;
+       bool probe;
+       char* confltxt;
+       uint8_t* mac;
+       uint8_t* omac;
+
+       memset(&arp, 0, sizeof(arp));
+       cnt = read(acd->listener_sockfd, &arp, sizeof(arp));
+       if (cnt != sizeof(arp))
+               return -EINVAL;
+
+       if (arp.arp_op != htons(ARPOP_REPLY) &&
+                       arp.arp_op != htons(ARPOP_REQUEST))
+               return -EINVAL;
+
+       if (memcmp(arp.arp_sha, acd->mac_address, ETH_ALEN) == 0)
+               return 0;
+
+       ip_n = htonl(acd->requested_ip);
+       source_conflict = !memcmp(arp.arp_spa, &ip_n, sizeof(uint32_t));
+       probe = !memcmp(arp.arp_spa, "\0\0\0\0", sizeof(uint32_t));
+       target_conflict = probe &&
+               !memcmp(arp.arp_tpa, &ip_n, sizeof(uint32_t));
+
+       if (!source_conflict && !target_conflict)
+               return 0;
+
+       acd->conflicts++;
+
+       confltxt = target_conflict ? "target" : "source";
+
+       addr.s_addr = ip_n;
+       debug(acd, "IPv4 %d %s conflicts detected for address %s. "
+                       "State=%s", acd->conflicts, confltxt, inet_ntoa(addr),
+                       acd_state_texts[acd->state]);
+       mac = acd->mac_address;
+       omac = arp.arp_sha;
+       debug(acd, "Our MAC: %02x:%02x:%02x:%02x:%02x:%02x"
+                          " other MAC: %02x:%02x:%02x:%02x:%02x:%02x",
+                       mac[0], mac[1], mac[2],mac[3], mac[4], mac[5],
+                       omac[0], omac[1], omac[2],omac[3], omac[4], omac[5]);
+
+       if (acd->state == ACD_MONITOR) {
+               if (!source_conflict)
+                       return 0;
+
+               acd->state = ACD_DEFEND;
+               debug(acd, "DEFEND mode conflicts: %d", acd->conflicts);
+               /* Try to defend with a single announce. */
+               send_announce_packet(acd);
+               return 0;
+       } else if (acd->state == ACD_DEFEND) {
+               if (!source_conflict)
+                       return 0;
+
+               debug(acd, "LOST IPv4 address %s", inet_ntoa(addr));
+               if (acd->ipv4_lost_cb)
+                       acd->ipv4_lost_cb(acd, acd->ipv4_lost_data);
+               return 0;
+       }
+
+       if (acd->conflicts < MAX_CONFLICTS) {
+               acdhost_stop(acd);
+
+               /* we need a new request_ip */
+               if (acd->ipv4_conflict_cb)
+                       acd->ipv4_conflict_cb(acd, acd->ipv4_conflict_data);
+       } else {
+               acdhost_stop(acd);
+
+               /* Here we got a lot of conflicts, RFC3927 and RFC5227 state 
that we
+                * have to wait RATE_LIMIT_INTERVAL before retrying. */
+               if (acd->ipv4_max_conflicts_cb)
+                       acd->ipv4_max_conflicts_cb(acd, 
acd->ipv4_max_conflicts_data);
+       }
+
+       return 0;
 }
-- 
2.16.2



------------------------------

Message: 4
Date: Wed, 21 Mar 2018 14:42:33 +0100
From: Peter Meerwald-Stadler <[email protected]>
To: [email protected]
Cc: [email protected],     [email protected]
Subject: [RFC PATCH 23/27] acd: add dbus property for address conflict
Message-ID: <[email protected]>

From: Christian Spielberger <[email protected]>

---
 include/acd.h |  5 +++-
 src/acd.c     | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/service.c |  5 +++-
 3 files changed, 93 insertions(+), 3 deletions(-)

diff --git a/include/acd.h b/include/acd.h
index deaea130..4f483c86 100644
--- a/include/acd.h
+++ b/include/acd.h
@@ -23,6 +23,7 @@
 
 #include <stdint.h>
 #include <glib.h>
+#include <gdbus.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -32,7 +33,7 @@ struct _ACDHost;
 
 typedef struct _ACDHost ACDHost;
 
-ACDHost *acdhost_new(int ifindex);
+ACDHost *acdhost_new(int ifindex, const char* path);
 int acdhost_start(ACDHost *acd, uint32_t ip);
 void acdhost_stop(ACDHost *acd);
 
@@ -50,6 +51,8 @@ void acdhost_register_event(ACDHost *acd,
                            ACDHostEventFunc func,
                            gpointer user_data);
 
+void acdhost_append_dbus_property(ACDHost *acd, DBusMessageIter *dict);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/acd.c b/src/acd.c
index f3a1c759..9b114775 100644
--- a/src/acd.c
+++ b/src/acd.c
@@ -17,8 +17,10 @@
 #include <connman/acd.h>
 #include <connman/log.h>
 #include <connman/inet.h>
+#include <connman/dbus.h>
 #include <shared/arp.h>
 #include <shared/random.h>
+#include <glib.h>
 #include <stdio.h>
 #include <errno.h>
 #include <unistd.h>
@@ -48,6 +50,13 @@ struct _ACDHost {
        uint8_t mac_address[6];
        uint32_t requested_ip; /* host byte order */
 
+       /* address conflict fields */
+       uint32_t ac_ip; /* host byte order */
+       uint8_t ac_mac[6];
+       gint64 ac_timestamp;
+       bool ac_resolved;
+       const char *path;
+
        bool listen_on;
        int listener_sockfd;
        unsigned int retry_times;
@@ -76,6 +85,9 @@ static gboolean send_announce_packet(gpointer acd_data);
 static gboolean acd_announce_timeout(gpointer acd_data);
 static gboolean acd_defend_timeout(gpointer acd_data);
 
+/* for DBus property */
+static void report_conflict(ACDHost *acd);
+
 static void debug(ACDHost *acd, const char *format, ...)
 {
        char str[256];
@@ -89,7 +101,7 @@ static void debug(ACDHost *acd, const char *format, ...)
        va_end(ap);
 }
 
-ACDHost *acdhost_new(int ifindex)
+ACDHost *acdhost_new(int ifindex, const char *path)
 {
        ACDHost *acd;
 
@@ -129,6 +141,12 @@ ACDHost *acdhost_new(int ifindex)
        acd->ipv4_conflict_cb = NULL;
        acd->ipv4_max_conflicts_cb = NULL;
 
+       acd->ac_ip = 0;
+       memset(acd->ac_mac, 0, sizeof(acd->ac_mac));
+       acd->ac_timestamp = 0;
+       acd->ac_resolved = true;
+       acd->path = path;
+
        return acd;
 
 error:
@@ -342,6 +360,11 @@ static gboolean acd_defend_timeout(gpointer acd_data)
        return FALSE;
 }
 
+static bool is_link_local(uint32_t ip)
+{
+       return (ip & LINKLOCAL_ADDR) == LINKLOCAL_ADDR;
+}
+
 static gboolean acd_announce_timeout(gpointer acd_data)
 {
        ACDHost *acd = acd_data;
@@ -358,10 +381,16 @@ static gboolean acd_announce_timeout(gpointer acd_data)
        debug(acd, "switching to monitor mode");
        acd->state = ACD_MONITOR;
 
+       if (!acd->ac_resolved && !is_link_local(acd->requested_ip)) {
+               acd->ac_resolved = true;
+               report_conflict(acd);
+       }
+
        if (acd->ipv4_available_cb)
                acd->ipv4_available_cb(acd,
                                        acd->ipv4_available_data);
        acd->conflicts = 0;
+
        return FALSE;
 }
 
@@ -433,6 +462,14 @@ static int acd_recv_arp_packet(ACDHost *acd) {
        }
 
        if (acd->conflicts < MAX_CONFLICTS) {
+               if (!is_link_local(acd->requested_ip)) {
+                       acd->ac_ip = acd->requested_ip;
+                       memcpy(acd->ac_mac, arp.arp_sha, sizeof(acd->ac_mac));
+                       acd->ac_timestamp = g_get_real_time();
+                       acd->ac_resolved = false;
+                       report_conflict(acd);
+               }
+
                acdhost_stop(acd);
 
                /* we need a new request_ip */
@@ -478,3 +515,50 @@ void acdhost_register_event(ACDHost *acd,
        }
 }
 
+static void append_ac_mac(DBusMessageIter *iter, void *user_data)
+{
+       ACDHost *acd = user_data;
+       char mac[32];
+       uint8_t *m = acd->ac_mac;
+       const char *str = mac;
+       snprintf(mac, sizeof(mac), "%02x:%02x:%02x:%02x:%02x:%02x",
+                       m[0], m[1], m[2], m[3], m[4], m[5]);
+       connman_dbus_dict_append_basic(iter, "Address", DBUS_TYPE_STRING, &str);
+}
+
+static void append_ac_ipv4(DBusMessageIter *iter, void *user_data)
+{
+       ACDHost *acd = user_data;
+       struct in_addr addr;
+       char *a;
+
+       addr.s_addr = htonl(acd->ac_ip);
+       a = inet_ntoa(addr);
+       if (!a)
+               a = "";
+       connman_dbus_dict_append_basic(iter, "Address", DBUS_TYPE_STRING, &a);
+}
+
+static void append_ac_property(DBusMessageIter *iter, void *user_data)
+{
+       ACDHost *acd = user_data;
+
+       connman_dbus_dict_append_dict(iter, "IPv4", append_ac_ipv4, acd);
+       connman_dbus_dict_append_dict(iter, "Ethernet", append_ac_mac, acd);
+       connman_dbus_dict_append_basic(iter, "Timestamp", DBUS_TYPE_INT64,
+                       &acd->ac_timestamp);
+       connman_dbus_dict_append_basic(iter, "Resolved", DBUS_TYPE_BOOLEAN,
+                       &acd->ac_resolved);
+}
+
+void acdhost_append_dbus_property(ACDHost *acd, DBusMessageIter *dict)
+{
+       connman_dbus_dict_append_dict(dict, "LastAddressConflict",
+                       append_ac_property, acd);
+}
+
+static void report_conflict(ACDHost *acd)
+{
+       connman_dbus_property_changed_dict(acd->path, CONNMAN_SERVICE_INTERFACE,
+                       "LastAddressConflict", append_ac_property, acd);
+}
diff --git a/src/service.c b/src/service.c
index d8c0e5e7..bef2d88d 100644
--- a/src/service.c
+++ b/src/service.c
@@ -2529,6 +2529,9 @@ static void append_properties(DBusMessageIter *dict, 
dbus_bool_t limited,
 
        connman_dbus_dict_append_dict(dict, "Provider",
                                                append_provider, service);
+
+       if (service->acdhost)
+               acdhost_append_dbus_property(service->acdhost, dict);
 }
 
 static void append_struct_service(DBusMessageIter *iter,
@@ -7658,7 +7661,7 @@ int connman_service_start_acd(struct connman_service 
*service)
                int index;
 
                index = __connman_ipconfig_get_index(service->ipconfig_ipv4);
-               service->acdhost = acdhost_new(index);
+               service->acdhost = acdhost_new(index, service->path);
                if (!service->acdhost) {
                        connman_error("Could not create ACD data structure");
                        return -EINVAL;
-- 
2.16.2



------------------------------

Message: 5
Date: Wed, 21 Mar 2018 14:42:34 +0100
From: Peter Meerwald-Stadler <[email protected]>
To: [email protected]
Cc: [email protected],     [email protected]
Subject: [RFC PATCH 24/27] dhcp: add sending of DHCP decline
Message-ID: <[email protected]>

From: Christian Spielberger <[email protected]>

---
 gdhcp/client.c | 29 ++++++++++++++++++++++++++++-
 gdhcp/gdhcp.h  |  1 +
 src/connman.h  |  1 +
 src/dhcp.c     | 24 ++++++++++++++++++++++++
 4 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/gdhcp/client.c b/gdhcp/client.c
index 320b7819..405062f4 100644
--- a/gdhcp/client.c
+++ b/gdhcp/client.c
@@ -66,6 +66,7 @@ typedef enum _dhcp_client_state {
        REBOOTING,
        REQUESTING,
        BOUND,
+       DECLINED,
        RENEWING,
        REBINDING,
        RELEASED,
@@ -471,6 +472,30 @@ static int send_discover(GDHCPClient *dhcp_client, 
uint32_t requested)
                                dhcp_client->retry_times % 2);
 }
 
+int g_dhcp_client_decline(GDHCPClient *dhcp_client, uint32_t requested)
+{
+       struct dhcp_packet packet;
+
+       dhcp_client->state = DECLINED;
+       dhcp_client->retry_times = 0;
+
+       debug(dhcp_client, "sending DHCP decline");
+
+       init_packet(dhcp_client, &packet, DHCPDECLINE);
+
+       packet.xid = dhcp_client->xid;
+       packet.secs = dhcp_attempt_secs(dhcp_client);
+
+       if (requested)
+               dhcp_add_option_uint32(&packet, DHCP_REQUESTED_IP, requested);
+
+       add_send_options(dhcp_client, &packet);
+
+       return dhcp_send_raw_packet(&packet, INADDR_ANY, CLIENT_PORT,
+                               INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR,
+                               dhcp_client->ifindex, true);
+}
+
 static int send_request(GDHCPClient *dhcp_client)
 {
        struct dhcp_packet packet;
@@ -2688,6 +2713,7 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const 
char *last_address)
        int re;
        uint32_t addr;
        uint64_t rand;
+       ClientState oldstate = dhcp_client->state;
 
        remove_timeouts(dhcp_client);
 
@@ -2803,7 +2829,7 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const 
char *last_address)
                dhcp_client->start = time(NULL);
        }
 
-       if (!last_address) {
+       if (!last_address || oldstate == DECLINED) {
                addr = 0;
        } else {
                addr = ntohl(inet_addr(last_address));
@@ -3003,6 +3029,7 @@ char *g_dhcp_client_get_netmask(GDHCPClient *dhcp_client)
        case REBOOTING:
        case REQUESTING:
        case RELEASED:
+       case DECLINED:
        case IPV4LL_PROBE:
        case IPV4LL_ANNOUNCE:
        case INFORMATION_REQ:
diff --git a/gdhcp/gdhcp.h b/gdhcp/gdhcp.h
index 1285431e..e3b01311 100644
--- a/gdhcp/gdhcp.h
+++ b/gdhcp/gdhcp.h
@@ -134,6 +134,7 @@ GDHCPClient *g_dhcp_client_new(GDHCPType type, int index,
 
 int g_dhcp_client_start(GDHCPClient *client, const char *last_address);
 void g_dhcp_client_stop(GDHCPClient *client);
+int g_dhcp_client_decline(GDHCPClient *client, uint32_t requested);
 
 GDHCPClient *g_dhcp_client_ref(GDHCPClient *client);
 void g_dhcp_client_unref(GDHCPClient *client);
diff --git a/src/connman.h b/src/connman.h
index 6d1831b1..303fddd3 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -466,6 +466,7 @@ int __connman_dhcp_start(struct connman_ipconfig *ipconfig,
                        struct connman_network *network, dhcp_cb callback,
                        gpointer user_data);
 void __connman_dhcp_stop(struct connman_ipconfig *ipconfig);
+void __connman_dhcp_decline(struct connman_ipconfig *ipconfig);
 int __connman_dhcp_init(void);
 void __connman_dhcp_cleanup(void);
 int __connman_dhcpv6_init(void);
diff --git a/src/dhcp.c b/src/dhcp.c
index b57a7949..42e9f417 100644
--- a/src/dhcp.c
+++ b/src/dhcp.c
@@ -745,6 +745,30 @@ void __connman_dhcp_stop(struct connman_ipconfig *ipconfig)
        }
 }
 
+void __connman_dhcp_decline(struct connman_ipconfig *ipconfig)
+{
+       struct connman_dhcp *dhcp;
+       const char *address;
+       struct in_addr addr;
+
+       DBG("ipconfig_table %p ipconfig %p", ipconfig_table, ipconfig);
+
+       if (!ipconfig_table)
+               return;
+
+       dhcp = g_hash_table_lookup(ipconfig_table, ipconfig);
+       if (dhcp) {
+               address = __connman_ipconfig_get_local(ipconfig);
+               if (!address)
+                       return;
+
+               if (inet_pton(AF_INET, address, &addr) != 1)
+                       connman_error("Could not convert address %s", address);
+
+               g_dhcp_client_decline(dhcp->dhcp_client, htonl(addr.s_addr));
+       }
+}
+
 int __connman_dhcp_init(void)
 {
        DBG("");
-- 
2.16.2



------------------------------

Subject: Digest Footer

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


------------------------------

End of connman Digest, Vol 29, Issue 23
***************************************

Reply via email to