[PATCH] Connman : Initial P2P Group Managemen t API Support (CreateGroup,  GetGroups, Disc onnectGroup)

Shailesh Rathod/LGSI Connectivity Team <[email protected]> Mon, 7 Jul 2025 07:06:58 +0000
Newsgroups dev.linux.lists.connman
Message-ID <SE1P216MB2647C4352BF93E35C79680A8F04FA@SE1P216MB2647.KORP216.PROD.OUTLOOK.COM>
From f8e016205a0220ae93979b6413db97d6d55236d7 Mon Sep 17 00:00:00 2001
From: shailesh <[email protected]>
Date: Mon, 16 Jun 2025 11:39:54 +0000
Subject: [PATCH] Initial P2P Group Management API Support (CreateGroup,
 GetGroups, DisconnectGroup)

- Add new D-Bus APIs to ConnMan for Wi-Fi Direct (P2P) group management:
    - CreateGroup: Create a P2P group with identifier and passphrase.
    - GetGroups: List all current P2P groups and their properties.
    - DisconnectGroup: Disconnect a running P2P group.
- Implement group tracking, D-Bus signals for group add/remove, and group property reporting.
- Integrate with wpa_supplicant for group creation, persistence, and teardown.
- Add utility functions for MAC address formatting and DHCP pool management.
- Update Makefile and headers to register new APIs and structures.
- Extend plugins/wifi, manager, and technology logic to support P2P group lifecycle.
- Add new files: include/group.h, src/group.c, src/p2pgo.c.
- Update documentation and comments for new APIs and structures.
---
 Makefile.am               |   5 +-
 gdhcp/gdhcp.h             |  16 +
 gdhcp/server.c            |   6 -
 gsupplicant/gsupplicant.h |  61 +++
 gsupplicant/supplicant.c  | 796 +++++++++++++++++++++++++++++-
 include/dbus.h            |   2 +-
 include/group.h           | 175 +++++++
 include/peer.h            |   3 +
 include/technology.h      |   6 +-
 plugins/wifi.c            | 252 +++++++++-
 src/connman.h             |  33 ++
 src/group.c               | 993 ++++++++++++++++++++++++++++++++++++++
 src/ippool.c              |  40 ++
 src/manager.c             | 114 +++++
 src/p2pgo.c               | 477 ++++++++++++++++++
 src/peer.c                |  18 +
 src/technology.c          |  77 +++
 src/util.c                |  39 ++
 18 files changed, 3090 insertions(+), 23 deletions(-)
 create mode 100644 include/group.h
 create mode 100644 src/group.c
 create mode 100644 src/p2pgo.c

diff --git a/Makefile.am b/Makefile.am
index b5881a8..eb0efbe 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -12,7 +12,8 @@ include_HEADERS = include/log.h include/plugin.h \
                  include/storage.h include/provision.h \
                  include/session.h include/ipaddress.h include/agent.h \
                  include/inotify.h include/peer.h include/machine.h \
-                 include/acd.h include/tethering.h
+                 include/acd.h include/tethering.h \
+                 include/group.h
 
 nodist_include_HEADERS = include/version.h
 
@@ -130,7 +131,7 @@ src_connmand_SOURCES = $(gdhcp_sources) $(gweb_sources) $(stats_sources) \
                  src/6to4.c src/ippool.c src/bridge.c src/nat.c \
                  src/ipaddress.c src/inotify.c src/ipv6pd.c src/peer.c \
                  src/peer_service.c src/machine.c src/util.c \
-                 src/acd.c
+                 src/acd.c src/group.c src/p2pgo.c
 
 if INTERNAL_DNS_BACKEND
 src_connmand_SOURCES += src/dnsproxy.c
diff --git a/gdhcp/gdhcp.h b/gdhcp/gdhcp.h
index e3b0131..0475e7b 100644
--- a/gdhcp/gdhcp.h
+++ b/gdhcp/gdhcp.h
@@ -25,6 +25,7 @@
 #include <stdbool.h>
 #include <stdint.h>
 #include <arpa/inet.h>
+#include <netinet/if_ether.h>
 
 #include <glib.h>
 
@@ -37,6 +38,21 @@ struct _GDHCPClient;
 
 typedef struct _GDHCPClient GDHCPClient;
 
+/**
+ * Represents a DHCP lease.
+ *
+ * This structure contains information about a DHCP lease, including:
+ * - `expire`: The expiration time of the lease.
+ * - `lease_nip`: The leased IP address in network byte order.
+ * - `lease_mac`: The MAC address associated with the lease.
+ */
+struct dhcp_lease {
+    time_t expire;          // Expiration time of the lease.
+    uint32_t lease_nip;     // Leased IP address (network byte order).
+    uint8_t lease_mac[ETH_ALEN]; // MAC address associated with the lease.
+};
+
+
 typedef enum {
      G_DHCP_CLIENT_ERROR_NONE,
      G_DHCP_CLIENT_ERROR_INTERFACE_UNAVAILABLE,
diff --git a/gdhcp/server.c b/gdhcp/server.c
index 52ea2a5..970f293 100644
--- a/gdhcp/server.c
+++ b/gdhcp/server.c
@@ -70,12 +70,6 @@ struct _GDHCPServer {
      gpointer debug_data;
 };
 
-struct dhcp_lease {
-     time_t expire;
-     uint32_t lease_nip;
-     uint8_t lease_mac[ETH_ALEN];
-};
-
 static inline void debug(GDHCPServer *server, const char *format, ...)
 {
      char str[256];
diff --git a/gsupplicant/gsupplicant.h b/gsupplicant/gsupplicant.h
index 77c2d46..26d5f73 100644
--- a/gsupplicant/gsupplicant.h
+++ b/gsupplicant/gsupplicant.h
@@ -205,6 +205,21 @@ struct _GSupplicantP2PServiceParams {
 
 typedef struct _GSupplicantP2PServiceParams GSupplicantP2PServiceParams;
 
+
+/*
+ * Parameters used to add a new P2P (Wi-Fi Direct) group:
+ * - 'persistent': whether the group should be persistent and remembered across sessions.
+ * - 'persistent_group_object': D-Bus object path referring to an existing persistent group (if reusing).
+ * - 'frequency': the desired frequency (in MHz) to create the group on; 0 means auto-selection.
+ */
+struct _GSupplicantP2PGroupAddParams {
+     dbus_bool_t persistent;
+     const char *persistent_group_object;
+     dbus_int32_t frequency;
+};
+
+typedef struct _GSupplicantP2PGroupAddParams GSupplicantP2PGroupAddParams;
+
 /* global API */
 typedef void (*GSupplicantCountryCallback) (int result,
                                    const char *alpha2,
@@ -253,6 +268,22 @@ int g_supplicant_interface_p2p_connect(GSupplicantInterface *interface,
 int g_supplicant_interface_p2p_disconnect(GSupplicantInterface *interface,
                              GSupplicantPeerParams *peer_params);
 
+/* Disconnects a running P2P group on the given interface. */
+int g_supplicant_interface_p2p_group_disconnect(GSupplicantInterface *interface,
+                             GSupplicantInterfaceCallback callback,
+                             void *user_data);
+
+/* Adds a persistent P2P group using the specified SSID configuration. */
+int g_supplicant_interface_p2p_persistent_group_add(GSupplicantInterface *interface,
+                             GSupplicantSSID *ssid, GSupplicantInterfaceCallback callback,
+                             void *user_data);
+
+/* Creates a new P2P group with optional parameters like persistence and frequency. */
+int g_supplicant_interface_p2p_group_add(GSupplicantInterface *interface,
+                       GSupplicantP2PGroupAddParams *group_data,
+                       GSupplicantInterfaceCallback callback,
+                       void *user_data);
+
 int g_supplicant_interface_p2p_listen(GSupplicantInterface *interface,
                                    int period, int interval);
 
@@ -264,6 +295,10 @@ int g_supplicant_interface_p2p_add_service(GSupplicantInterface *interface,
 int g_supplicant_interface_p2p_del_service(GSupplicantInterface *interface,
                        GSupplicantP2PServiceParams *p2p_service_params);
 
+/* Flushes all P2P peer information and cached data from the given interface. */
+int g_supplicant_interface_p2p_flush(GSupplicantInterface *interface,
+                       GSupplicantInterfaceCallback callback, void *user_data);
+
 int g_supplicant_set_widi_ies(GSupplicantP2PServiceParams *p2p_service_params,
                              GSupplicantInterfaceCallback callback,
                              void *user_data);
@@ -362,6 +397,30 @@ bool g_supplicant_peer_is_client(GSupplicantPeer *peer);
 bool g_supplicant_peer_has_requested_connection(GSupplicantPeer *peer);
 unsigned int g_supplicant_network_get_keymgmt(GSupplicantNetwork *network);
 
+/* Returns the interface associated with the given P2P group. */
+GSupplicantInterface *g_supplicant_group_get_interface(GSupplicantGroup *group);
+
+/* Returns the original interface that initiated the given P2P group. */
+GSupplicantInterface *g_supplicant_group_get_orig_interface(GSupplicantGroup *group);
+
+/* Returns the D-Bus object path of the given P2P group. */
+char *g_supplicant_group_get_object_path(GSupplicantGroup *group);
+
+/* Returns the role (e.g., GO or client) of the given P2P group. */
+int g_supplicant_group_get_role(GSupplicantGroup *group);
+
+/* Returns the SSID of the given P2P group. */
+char *g_supplicant_group_get_ssid(GSupplicantGroup *group);
+
+/* Returns the passphrase used by the P2P group. */
+char *g_supplicant_group_get_passphrase(GSupplicantGroup *group);
+
+/* Returns the operating frequency of the P2P group. */
+int g_supplicant_group_get_frequency(GSupplicantGroup *group);
+
+/* Returns whether the P2P group is persistent or not. */
+bool g_supplicant_group_get_persistent(GSupplicantGroup *group);
+
 struct _GSupplicantCallbacks {
      void (*system_ready) (void);
      void (*system_killed) (void);
@@ -391,6 +450,8 @@ struct _GSupplicantCallbacks {
                        int reasoncode);
      void (*assoc_status_code)(GSupplicantInterface *interface,
                        int reasoncode);
+     void (*p2p_group_started)(GSupplicantGroup *group);
+     void (*p2p_group_finished)(GSupplicantInterface *interface);
 };
 
 typedef struct _GSupplicantCallbacks GSupplicantCallbacks;
diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c
index 7facfe8..36159e6 100644
--- a/gsupplicant/supplicant.c
+++ b/gsupplicant/supplicant.c
@@ -44,6 +44,7 @@
 #define IEEE80211_CAP_IBSS   0x0002
 #define IEEE80211_CAP_PRIVACY      0x0010
 
+#define MAX_P2P_SSID_LEN                 32
 #define BSS_UNKNOWN_STRENGTH    -90
 
 static DBusConnection *connection;
@@ -253,12 +254,21 @@ struct _GSupplicantPeer {
      bool connection_requested;
 };
 
+/*
+ * Structure representing a Wi-Fi P2P group, including its associated interfaces, * D-Bus path, role (GO/client), list of peer members, SSID, passphrase,
+ * persistence status, and operating frequency.
+ */
 struct _GSupplicantGroup {
      GSupplicantInterface *interface;
      GSupplicantInterface *orig_interface;
      char *path;
      int role;
      GSList *members;
+     char *ssid;
+     char *passphrase;
+     bool persistent;
+     int frequency;
+     char * psk;
 };
 
 struct interface_data {
@@ -302,6 +312,8 @@ struct interface_scan_data {
 
 static int network_remove(struct interface_data *data);
 
+void __connman_util_byte_to_string(unsigned char *src, char *dest, int len);
+
 static inline void debug(const char *format, ...)
 {
      char str[256];
@@ -674,6 +686,152 @@ static void callback_peer_changed(GSupplicantPeer *peer,
      callbacks_pointer->peer_changed(peer, state);
 }
 
+/**
+ * Invokes the registered P2P group started callback, if set,
+ * passing the newly created GSupplicantGroup as the argument.
+ *
+ * @param group Pointer to the newly created GSupplicantGroup.
+ */
+static void callback_p2p_group_started(GSupplicantGroup *group)
+{
+     if (!callbacks_pointer)
+           return;
+
+     if (!callbacks_pointer->p2p_group_started)
+           return;
+
+     callbacks_pointer->p2p_group_started(group);
+}
+
+/**
+ * Calls the registered P2P group finished callback, if available,
+ * passing the GSupplicantInterface that finished the P2P group.
+ *
+ * @param interface Pointer to the GSupplicantInterface that finished the P2P group.
+ */
+static void callback_p2p_group_finished(GSupplicantInterface *interface)
+{
+     if (!callbacks_pointer)
+           return;
+
+     if (!callbacks_pointer->p2p_group_finished)
+           return;
+
+     callbacks_pointer->p2p_group_finished(interface);
+}
+
+/**
+ * Returns the GSupplicantInterface associated with the given GSupplicantGroup.
+ *
+ * @param group The pointer to the GSupplicantGroup instance.
+ * @return The GSupplicantInterface associated with the group, or NULL if the group is NULL.
+ */
+GSupplicantInterface *g_supplicant_group_get_interface(GSupplicantGroup *group)
+{
+     if (!group)
+           return NULL;
+
+     return group->interface;
+}
+
+/**
+ * Returns the original/physical interface associated with the given P2P group.
+ *
+ * @param group Pointer to the GSupplicantGroup.
+ * @return Pointer to the original GSupplicantInterface, or NULL if group is NULL.
+ */
+GSupplicantInterface *g_supplicant_group_get_orig_interface(GSupplicantGroup *group)
+{
+     if (!group)
+           return NULL;
+
+     return group->orig_interface;
+}
+
+/**
+ * Returns the D-Bus object path associated with the given P2P group.
+ *
+ * @param group Pointer to the GSupplicantGroup.
+ * @return The object path string, or NULL if the group is NULL.
+ */
+char *g_supplicant_group_get_object_path(GSupplicantGroup *group)
+{
+     if (!group)
+           return NULL;
+
+     return group->path;
+}
+
+/**
+ * Retrieves the SSID string of the specified P2P group.
+ *
+ * @param group Pointer to the GSupplicantGroup.
+ * @return The SSID string, or NULL if the group is NULL.
+ */
+char *g_supplicant_group_get_ssid(GSupplicantGroup *group)
+{
+     if (!group)
+           return NULL;
+
+     return group->ssid;
+}
+
+/**
+ * Retrieves the passphrase of the specified P2P group.
+ *
+ * @param group Pointer to the GSupplicantGroup.
+ * @return The passphrase string, or NULL if the group is NULL.
+ */
+char *g_supplicant_group_get_passphrase(GSupplicantGroup *group)
+{
+     if (!group)
+           return NULL;
+
+     return group->passphrase;
+}
+
+/**
+ * Retrieves the operating frequency (in MHz) of the specified P2P group.
+ *
+ * @param group Pointer to the GSupplicantGroup.
+ * @return The frequency value, or 0 if the group is NULL.
+ */
+int g_supplicant_group_get_frequency(GSupplicantGroup *group)
+{
+     if (!group)
+           return 0;
+
+     return group->frequency;
+}
+
+/**
+ * Retrieves the role of the specified P2P group.
+ *
+ * @param group Pointer to the GSupplicantGroup.
+ * @return The role value, or 0 if the group is NULL.
+ */
+int g_supplicant_group_get_role(GSupplicantGroup *group)
+{
+     if (!group)
+           return 0;
+
+     return group->role;
+}
+
+/**
+ * Checks whether the specified P2P group is persistent.
+ *
+ * @param group Pointer to the GSupplicantGroup.
+ * @return true if the group is persistent, false if not or if group is NULL.
+ */
+bool g_supplicant_group_get_persistent(GSupplicantGroup *group)
+{
+     if (!group)
+           return false;
+
+     return group->persistent;
+}
+
 static void callback_peer_request(GSupplicantPeer *peer)
 {
      if (!callbacks_pointer)
@@ -3321,14 +3479,40 @@ static void signal_peer_changed(const char *path, DBusMessageIter *iter)
            peer->connection_requested = false;
 }
 
+/**
+ * Holds P2P group signal data:
+ * peer_obj_path - object path of the peer device,
+ * iface_address - MAC address of the interface,
+ * interface_obj_path - object path of the local interface,
+ * group_obj_path - object path of the group,
+ * role - role of the device in the group,
+ * persistent - whether the group is persistent or not.
+ */
 struct group_sig_data {
      const char *peer_obj_path;
      unsigned char iface_address[ETH_ALEN];
      const char *interface_obj_path;
      const char *group_obj_path;
      int role;
+     bool persistent;
 };
 
+/**
+ * Parses and assigns P2P group signal properties from DBus message iterator to the provided group_sig_data struct.
+ *
+ * @param key       Property name string.
+ * @param iter      DBus message iterator pointing to the property value.
+ * @param user_data Pointer to group_sig_data struct where parsed data will be stored.
+ *
+ * Handles the following keys:
+ * - "peer_interface_addr": copies MAC address into iface_address.
+ * - "role": sets role enum based on string ("GO" or client).
+ * - "peer_object": stores peer device object path.
+ * - "interface_object": stores local interface object path.
+ * - "group_object": stores group object path.
+ * - "persistent": sets persistence flag.
+ */
+
 static void group_sig_property(const char *key, DBusMessageIter *iter,
                                          void *user_data)
 {
@@ -3361,6 +3545,8 @@ static void group_sig_property(const char *key, DBusMessageIter *iter,
            dbus_message_iter_get_basic(iter, &data->interface_obj_path);
      else if (g_strcmp0(key, "group_object") == 0)
            dbus_message_iter_get_basic(iter, &data->group_obj_path);
+     else if (g_strcmp0(key, "persistent") == 0)
+           dbus_message_iter_get_basic(iter, &data->persistent);
 
 }
 
@@ -3412,12 +3598,169 @@ static void signal_group_failure(const char *path, DBusMessageIter *iter)
      peer->connection_requested = false;
 }
 
+/**
+ * Processes P2P group properties received via DBus and updates the GSupplicantGroup struct accordingly.
+ *
+ * @param key       Property name string.
+ * @param iter      DBus message iterator pointing to the property value.
+ * @param user_data Pointer to GSupplicantGroup struct to update with property values.
+ *
+ * Supported keys:
+ * - "SSID": copies SSID byte array to group's ssid string.
+ * - "Passphrase": copies passphrase string to group's passphrase.
+ * - "Frequency": sets group's frequency value.
+ *
+ * If key is NULL, triggers the p2p_group_started callback for the group.
+ */
+static void p2p_group_property(const char *key, DBusMessageIter *iter,
+                                                                       void *user_data)
+{
+     GSupplicantGroup *group = user_data;
+
+     SUPPLICANT_DBG("key %s", key);
+
+     if (!key) {
+           callback_p2p_group_started(group);
+           return;
+     }
+
+     if (!iter)
+           return;
+
+     if (g_strcmp0(key, "SSID") == 0) {
+           DBusMessageIter array;
+           char *ssid;
+           int ssid_len;
+
+           dbus_message_iter_recurse(iter, &array);
+           dbus_message_iter_get_fixed_array(&array, &ssid, &ssid_len);
+
+           if (ssid_len > 0 && ssid_len < 33) {
+                 group->ssid = g_strndup(ssid, ssid_len);
+           }
+     } else if (g_strcmp0(key, "Passphrase") == 0) {
+           char *passphrase;
+
+           dbus_message_iter_get_basic(iter, &passphrase);
+           group->passphrase = g_strdup(passphrase);
+     } else if (g_strcmp0(key, "Frequency") == 0) {
+           dbus_uint16_t frequency = 0;
+
+           dbus_message_iter_get_basic(iter, &frequency);
+           group->frequency = frequency;
+     }
+
+     callback_p2p_group_started(group);
+}
+
+static void p2p_group_psk_property(const char *key, DBusMessageIter *iter,
+                                                           void *user_data)
+{
+     GSupplicantGroup *group = user_data;
+     int len = 0;
+     unsigned char *psk;
+     char psk_s[65];
+     DBusMessageIter iter_array;
+
+     if(iter == NULL)
+           return;
+
+     if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
+     {
+           SUPPLICANT_DBG("not array %d\n", dbus_message_iter_get_arg_type(iter));
+           return;
+     }
+
+     dbus_message_iter_recurse(iter, &iter_array);
+
+     dbus_message_iter_get_fixed_array(&iter_array, &psk, &len);
+     __connman_util_byte_to_string(psk, psk_s, len);
+     group->psk = g_strdup(psk_s);
+     SUPPLICANT_DBG("psk : %s\n", group->psk);
+}
+
+static void p2p_group_passphrase_property(const char *key, DBusMessageIter *iter,
+                                                                       void *user_data)
+{
+     GSupplicantGroup *group = user_data;
+     char *passphrase;
+
+     if(iter == NULL)
+           return;
+
+     dbus_message_iter_get_basic(iter, &passphrase);
+     group->passphrase = g_strdup(passphrase);
+
+     SUPPLICANT_DBG("passphrase : %s\n", group->passphrase);
+
+}
+
+static void p2p_group_ssid_property(const char *key, DBusMessageIter *iter,
+                                                           void *user_data)
+{
+     GSupplicantGroup *group = user_data;
+     char *ssid;
+     int len = 0;
+     DBusMessageIter iter_array;
+     GSupplicantPeer *peer = NULL;
+
+     if(iter == NULL)
+           return;
+
+     dbus_message_iter_recurse(iter, &iter_array);
+
+     dbus_message_iter_get_fixed_array(&iter_array, &ssid, &len);
+
+     if(len >= MAX_P2P_SSID_LEN)
+           len = MAX_P2P_SSID_LEN - 1;
+
+     group->ssid = g_strndup(ssid, len);
+     callback_p2p_group_started(group);
+}
+
+
+/**
+ * Called when a P2P group is started; initiates retrieval of all group properties
+ * over DBus for the given group path, updating the group's properties via callback.
+ *
+ * @param group Pointer to the GSupplicantGroup representing the started P2P group.
+ *              Must have a valid 'path' to the DBus group object.
+ */
+static void interface_p2p_group_started(GSupplicantGroup *group) {
+
+     if (!group->path)
+           return;
+
+     supplicant_dbus_property_get(group->path, SUPPLICANT_INTERFACE ".Group",
+                                         "PSK", p2p_group_psk_property, group, NULL);
+
+     supplicant_dbus_property_get(group->path, SUPPLICANT_INTERFACE ".Group",
+                                         "Passphrase", p2p_group_passphrase_property, group, NULL);
+
+     supplicant_dbus_property_get(group->path, SUPPLICANT_INTERFACE ".Group",
+                                         "SSID", p2p_group_ssid_property, group, NULL);
+}
+
+
+
+/**
+ * Handles the DBus signal indicating a P2P group has started.
+ *
+ * Looks up the interface from the provided path, extracts group-related properties,
+ * creates a new GSupplicantGroup if it doesn't exist, initializes it, and inserts it
+ * into relevant hash tables. If a pending peer is associated, updates its state.
+ * Finally, triggers retrieval of group properties asynchronously.
+ *
+ * @param path  DBus object path of the interface sending the signal.
+ * @param iter  Iterator over DBus message arguments containing group properties.
+ */
+
 static void signal_group_started(const char *path, DBusMessageIter *iter)
 {
      GSupplicantInterface *interface, *g_interface;
      struct group_sig_data data = {};
      GSupplicantGroup *group;
-     GSupplicantPeer *peer;
+     GSupplicantPeer *peer = NULL;
 
      SUPPLICANT_DBG("");
 
@@ -3429,11 +3772,13 @@ static void signal_group_started(const char *path, DBusMessageIter *iter)
      if (!data.interface_obj_path || !data.group_obj_path)
            return;
 
-     peer = g_hash_table_lookup(interface->peer_table,
-                                   interface->pending_peer_path);
-     interface->pending_peer_path = NULL;
-     if (!peer)
-           return;
+     if (interface->pending_peer_path) {
+           peer = g_hash_table_lookup(interface->peer_table,
+                                         interface->pending_peer_path);
+           interface->pending_peer_path = NULL;
+           if (!peer)
+                 return;
+     }
 
      g_interface = g_hash_table_lookup(interface_table,
                                    data.interface_obj_path);
@@ -3453,12 +3798,16 @@ static void signal_group_started(const char *path, DBusMessageIter *iter)
      group->orig_interface = interface;
      group->path = g_strdup(data.group_obj_path);
      group->role = data.role;
-
+     group->persistent = data.persistent;
      g_hash_table_insert(interface->group_table, group->path, group);
      g_hash_table_replace(group_mapping, group->path, group);
 
-     peer->current_group_iface = g_interface;
-     callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_STARTED);
+     if (peer) {
+           peer->current_group_iface = g_interface;
+           callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_STARTED);
+     }
+
+     interface_p2p_group_started(group);
 }
 
 static void remove_peer_group_interface(GHashTable *group_table,
@@ -3506,6 +3855,7 @@ static void signal_group_finished(const char *path, DBusMessageIter *iter)
      g_hash_table_remove(group_mapping, data.group_obj_path);
 
      g_hash_table_remove(interface->group_table, data.group_obj_path);
+     callback_p2p_group_finished(interface);
 }
 
 static void signal_group_request(const char *path, DBusMessageIter *iter)
@@ -3683,6 +4033,9 @@ static DBusHandlerResult g_supplicant_filter(DBusConnection *conn,
 
 void g_supplicant_interface_cancel(GSupplicantInterface *interface)
 {
+     if (!interface)
+           return;
+
      SUPPLICANT_DBG("Cancelling any pending DBus calls");
      supplicant_dbus_method_call_cancel_all(interface);
      supplicant_dbus_property_call_cancel_all(interface);
@@ -5630,6 +5983,82 @@ int g_supplicant_interface_p2p_disconnect(GSupplicantInterface *interface,
      return -EINPROGRESS;
 }
 
+/**
+ * Handles the result of a P2P group disconnect operation.
+ *
+ * Checks if an error was reported during the disconnect request,
+ * logs it if present, and invokes the user callback with the status.
+ * Finally, frees the allocated interface_data structure.
+ *
+ * @param error      Error string returned by the DBus call, or NULL on success.
+ * @param iter       DBus message iterator for additional response data (unused).
+ * @param user_data  Pointer to interface_data containing callback info and user data.
+ */
+static void interface_p2p_disconnect_result(const char *error,
+                                                                             DBusMessageIter *iter, void *user_data)
+{
+     struct interface_data *data = user_data;
+     int err = 0;
+
+     if (error) {
+           SUPPLICANT_DBG("error %s", error);
+           err = -EIO;
+     }
+
+     if (data->callback)
+           data->callback(err, data->interface, data->user_data);
+
+     dbus_free(data);
+}
+
+/**
+ * Initiates a disconnect from the current P2P group on the specified interface.
+ *
+ * Allocates and sets up user callback data, then calls the
+ * "Disconnect" DBus method on the P2PDevice interface.
+ *
+ * @param interface  Pointer to the GSupplicantInterface to disconnect.
+ * @param callback   Function to call when disconnect completes or fails.
+ * @param user_data  User data to pass to the callback function.
+ *
+ * @return  -EINVAL if interface is NULL,
+ *          -ENOMEM if memory allocation fails,
+ *          -EINPROGRESS if the disconnect request is sent successfully,
+ *          or a negative error code if the DBus call fails immediately.
+ */
+int g_supplicant_interface_p2p_group_disconnect(GSupplicantInterface *interface,
+                                                                             GSupplicantInterfaceCallback callback,
+                                                                             void *user_data)
+{
+     struct interface_data *data;
+     int ret;
+
+     if (!interface)
+           return -EINVAL;
+
+     data = dbus_malloc0(sizeof(*data));
+     if (!data)
+           return -ENOMEM;
+
+     data->interface = interface;
+     data->callback = callback;
+     data->user_data = user_data;
+
+     SUPPLICANT_DBG("interface->path : %s\n", interface->path);
+
+     ret = supplicant_dbus_method_call(interface->path,
+                                                     SUPPLICANT_INTERFACE ".Interface.P2PDevice",
+                                                     "Disconnect", NULL,
+                                                     interface_p2p_disconnect_result, data, NULL);
+
+     if (ret < 0) {
+           dbus_free(data);
+           return ret;
+     }
+
+     return -EINPROGRESS;
+}
+
 struct p2p_service_data {
      bool registration;
      GSupplicantInterface *interface;
@@ -5763,6 +6192,355 @@ int g_supplicant_interface_p2p_del_service(GSupplicantInterface *interface,
      return -EINPROGRESS;
 }
 
+/**
+ * Structure holding context information for initiating a P2P group addition.
+ *
+ * @interface              The interface on which to add the P2P group.
+ * @callback               Function to call when the group addition completes or fails.
+ * @p2p_group_add_params   Parameters for the group to be added (e.g., frequency, persistence).
+ * @user_data              User-defined data to pass to the callback.
+ */
+struct interface_p2p_group_add_data {
+     GSupplicantInterface *interface;
+     GSupplicantInterfaceCallback callback;
+     GSupplicantP2PGroupAddParams *p2p_group_add_params;
+     void *user_data;
+};
+
+/**
+ * Constructs a D-Bus dictionary of parameters for a P2P group addition request.
+ *
+ * This function populates a D-Bus message iterator with key-value pairs
+ * based on the values in the provided GSupplicantP2PGroupAddParams structure.
+ *
+ * @iter        The D-Bus message iterator to write the dictionary into.
+ * @user_data   Pointer to a struct interface_p2p_group_add_data containing
+ *              the group addition parameters and context.
+ *
+ * Fields added to the dictionary (if valid):
+ * - "persistent": boolean flag indicating whether the group is persistent.
+ * - "persistent_group_object": object path of a previously saved persistent group.
+ * - "frequency": operating frequency (channel) for the group.
+ */
+
+static void interface_p2p_group_add_params(DBusMessageIter *iter, void *user_data)
+{
+     DBusMessageIter dict;
+     struct interface_p2p_group_add_data *data = user_data;
+
+     supplicant_dbus_dict_open(iter, &dict);
+
+
+     if (data && data->p2p_group_add_params) {
+           GSupplicantP2PGroupAddParams* params = data->p2p_group_add_params;
+
+           if(params->persistent == TRUE) {
+                 supplicant_dbus_dict_append_basic(&dict, "persistent",
+                                                                       DBUS_TYPE_BOOLEAN, &params->persistent);
+           }
+
+           if(params->persistent_group_object != NULL)     {
+                 supplicant_dbus_dict_append_basic(&dict, "persistent_group_object",
+                                                                       DBUS_TYPE_OBJECT_PATH, &params->persistent_group_object);
+           }
+
+           if(params->frequency >= 0) {
+                 supplicant_dbus_dict_append_basic(&dict, "frequency",
+                                                                       DBUS_TYPE_INT32, &params->frequency);
+           }
+     }
+
+     supplicant_dbus_dict_close(iter, &dict);
+}
+
+/**
+ * Handles the result of a P2P group addition operation and invokes the registered callback.
+ *
+ * This function is called when a response is received for a P2P group add request,
+ * either successfully or with an error. It extracts the error status, invokes the
+ * callback provided in the request context, and frees the context memory.
+ *
+ * @error       A string describing the error if the operation failed, or NULL on success.
+ * @iter        D-Bus message iterator containing any returned data (unused here).
+ * @user_data   Pointer to a struct interface_p2p_group_add_data holding the original request context.
+ */
+
+static void interface_p2p_group_add_result(const char *error,
+                       DBusMessageIter *iter, void *user_data)
+{
+     struct interface_p2p_group_add_data *data = user_data;
+     int err = 0;
+
+     if (error != NULL) {
+           SUPPLICANT_DBG("error %s", error);
+           err = -EIO;
+     }
+
+     if (data->callback != NULL)
+           data->callback(err, data->interface, data->user_data);
+
+     dbus_free(data);
+}
+
+/**
+ * Initiates the creation of a P2P group via wpa_supplicant's GroupAdd D-Bus method.
+ *
+ * This function sends a D-Bus method call to request the creation of a new
+ * Wi-Fi Direct (P2P) group, using optional parameters like frequency or a
+ * persistent group object. Upon completion, the provided callback is invoked.
+ *
+ * @interface    Pointer to the GSupplicantInterface representing the P2P device.
+ * @group_data   Pointer to GSupplicantP2PGroupAddParams containing optional group settings.
+ * @callback     Function to be called upon completion of the operation.
+ * @user_data    User-specific data passed to the callback.
+ *
+ * @return       0 on success, negative errno-style error code on failure:
+ *               -EINVAL if the interface is NULL,
+ *               -ENOTSUP if the interface doesn't support P2P,
+ *               -ENOMEM if memory allocation fails,
+ *               or a negative value from supplicant_dbus_method_call.
+ */
+
+int g_supplicant_interface_p2p_group_add(GSupplicantInterface *interface,
+                       GSupplicantP2PGroupAddParams *group_data,
+                       GSupplicantInterfaceCallback callback,
+                                         void *user_data)
+{
+     struct interface_p2p_group_add_data *data;
+     int ret;
+
+     if (!interface)
+           return -EINVAL;
+
+     if (!interface->p2p_support)
+           return -ENOTSUP;
+
+     data = dbus_malloc0(sizeof(*data));
+     if (data == NULL)
+           return -ENOMEM;
+
+     data->interface = interface;
+     data->callback = callback;
+     data->user_data = user_data;
+     data->p2p_group_add_params = group_data;
+
+     ret = supplicant_dbus_method_call(interface->path,
+                             SUPPLICANT_INTERFACE ".Interface.P2PDevice",
+                             "GroupAdd",
+                             interface_p2p_group_add_params, interface_p2p_group_add_result,
+                             data, NULL);
+
+     if (ret < 0)
+           dbus_free(data);
+
+     return ret;
+}
+
+/**
+ * Appends parameters for adding a persistent P2P group to a D-Bus message.
+ *
+ * This function populates a D-Bus dictionary with the "persistent_group_object"
+ * key, setting it to the object path of the previously saved persistent group
+ * (network) on the specified interface.
+ *
+ * @iter        D-Bus message iterator used to construct the method call.
+ * @user_data   Pointer to an interface_connect_data struct, providing access
+ *              to the GSupplicantInterface and its persistent group path.
+ */
+
+static void interface_p2p_persistent_group_add_params(DBusMessageIter *iter,
+                                         void *user_data)
+{
+     DBusMessageIter dict;
+     struct interface_connect_data *data = user_data;
+     GSupplicantInterface *interface = data->interface;
+
+     supplicant_dbus_dict_open(iter, &dict);
+
+     supplicant_dbus_dict_append_basic(&dict, "persistent_group_object",
+                                   DBUS_TYPE_OBJECT_PATH, &interface->network_path);
+
+     supplicant_dbus_dict_close(iter, &dict);
+}
+
+/**
+ * Handles the result of a persistent P2P group add operation.
+ *
+ * Parses the result of a "GroupAdd" D-Bus method call for a persistent group.
+ * If an error occurred, it logs the error and parses it using supplicant error helpers.
+ * Finally, it invokes the registered callback with the resulting status and frees
+ * the interface_connect_data structure.
+ *
+ * @error       String representing the D-Bus error name (NULL if no error).
+ * @iter        D-Bus message iterator pointing to error details (if any).
+ * @user_data   Pointer to interface_connect_data containing the interface and
+ *              callback to invoke upon completion.
+ */
+
+static void interface_p2p_persistent_group_add_result(const char *error,
+                       DBusMessageIter *iter, void *user_data)
+{
+     struct interface_connect_data *data = user_data;
+     int err;
+
+     err = 0;
+     if (error) {
+           SUPPLICANT_DBG("Group add error %s", error);
+           err = parse_supplicant_error(iter);
+     }
+
+     if (data->callback)
+           data->callback(err, data->interface, data->user_data);
+
+     dbus_free(data);
+}
+
+/**
+ * Handles the result of a persistent group creation request and triggers GroupAdd.
+ *
+ * This function processes the result of a persistent group creation D-Bus call.
+ * On success, it extracts the object path of the newly created persistent group,
+ * stores it in the interface struct, and then issues a "GroupAdd" request using
+ * that object. On failure, it logs the error, parses it using supplicant helpers,
+ * and invokes the registered callback with the error code. Cleans up resources accordingly.
+ *
+ * @error       D-Bus error string, or NULL if operation was successful.
+ * @iter        D-Bus message iterator pointing to the result or error detail.
+ * @user_data   Pointer to interface_connect_data, holding interface and callback context.
+ */
+
+static void interface_p2p_persistent_group_result(const char *error,
+                       DBusMessageIter *iter, void *user_data)
+{
+     struct interface_connect_data *data = user_data;
+     GSupplicantInterface *interface = data->interface;
+     const char *path = NULL;
+     int err;
+
+     if (error)
+           goto error;
+
+     dbus_message_iter_get_basic(iter, &path);
+     if (!path)
+           goto error;
+
+     g_free(interface->network_path);
+     interface->network_path = g_strdup(path);
+
+     SUPPLICANT_DBG("data->interface->path : %s\n", data->interface->path);
+
+     supplicant_dbus_method_call(data->interface->path,
+                             SUPPLICANT_INTERFACE ".Interface.P2PDevice",
+                             "GroupAdd",
+                             interface_p2p_persistent_group_add_params,
+                             interface_p2p_persistent_group_add_result,
+                             data, NULL);
+     return;
+
+     error:
+           SUPPLICANT_DBG("GroupAdd error %s", error);
+           err = parse_supplicant_error(iter);
+           if (data->callback)
+                 data->callback(err, data->interface, data->user_data);
+
+           g_free(interface->network_path);
+           interface->network_path = NULL;
+           g_free(data);
+}
+
+/**
+ * Appends parameters required to create a persistent P2P group into a D-Bus message.
+ *
+ * This function sets up the D-Bus dictionary with appropriate configuration values
+ * for persistent P2P group creation. It includes operational mode (`mode` = 3),
+ * disabled state (`disabled` = 2), security settings (via `add_network_security()`),
+ * and the SSID (as a null-terminated string). These values are written into the
+ * D-Bus message iterator passed by the caller.
+ *
+ * @iter        Pointer to the main D-Bus message iterator to append dictionary to.
+ * @user_data   Pointer to interface_connect_data containing the SSID configuration.
+ */
+
+static void interface_p2p_persistent_group_params(DBusMessageIter *iter, void *user_data)
+{
+     DBusMessageIter dict;
+     struct interface_connect_data *data = user_data;
+     GSupplicantSSID *ssid = data->ssid;
+     dbus_uint32_t mode = 3;
+     dbus_uint32_t disabled = 2;
+
+     supplicant_dbus_dict_open(iter, &dict);
+
+     supplicant_dbus_dict_append_basic(&dict, "mode", DBUS_TYPE_UINT32, &mode);
+     supplicant_dbus_dict_append_basic(&dict, "disabled",
+                                   DBUS_TYPE_UINT32, &disabled);
+
+     add_network_security(&dict, ssid);
+
+     //The data structure is set up as a byte buffer, however
+     //SSID->SSID is created by ssid_ap_init - it is a null terminated string.
+     supplicant_dbus_dict_append_basic(&dict, "ssid",
+                             DBUS_TYPE_STRING,
+                             &(ssid->ssid));
+
+     supplicant_dbus_dict_close(iter, &dict);
+}
+
+
+/**
+ * Initiates the creation of a persistent P2P group via the supplicant.
+ *
+ * This function checks if the interface supports P2P and allocates memory for the operation context.
+ * It sets up the parameters required to create a persistent group and calls the D-Bus method
+ * "AddPersistentGroup" on the supplicant's P2PDevice interface. On success, it returns -EINPROGRESS
+ * to indicate asynchronous processing; otherwise, returns an appropriate error code.
+ *
+ * @interface     Pointer to the GSupplicantInterface to use for the operation.
+ * @ssid          Pointer to GSupplicantSSID containing the SSID for the persistent group.
+ * @callback      Callback function to be invoked when the operation completes.
+ * @user_data     User data to be passed to the callback.
+ *
+ * @return        -EINPROGRESS on success (asynchronous),
+ *                negative errno on failure.
+ */
+
+int g_supplicant_interface_p2p_persistent_group_add(GSupplicantInterface *interface,
+                       GSupplicantSSID *ssid,
+                       GSupplicantInterfaceCallback callback,
+                                         void *user_data)
+{
+     struct interface_connect_data *data;
+     int ret;
+
+     if (!interface)
+           return -EINVAL;
+
+     if (!interface->p2p_support)
+           return -ENOTSUP;
+
+     data = dbus_malloc0(sizeof(*data));
+     if (!data)
+           return -ENOMEM;
+
+     data->interface = interface;
+     data->callback = callback;
+     data->ssid = ssid;
+     data->user_data = user_data;
+
+     ret = supplicant_dbus_method_call(interface->path,
+                             SUPPLICANT_INTERFACE ".Interface.P2PDevice",
+                             "AddPersistentGroup",
+                             interface_p2p_persistent_group_params,
+                             interface_p2p_persistent_group_result,
+                             data, NULL);
+
+     if (ret < 0) {
+           dbus_free(data);
+           return ret;
+     }
+
+     return -EINPROGRESS;
+}
 struct p2p_listen_data {
      int period;
      int interval;
diff --git a/include/dbus.h b/include/dbus.h
index bcab418..7be36c2 100644
--- a/include/dbus.h
+++ b/include/dbus.h
@@ -45,7 +45,7 @@ extern "C" {
 #define CONNMAN_SESSION_INTERFACE  CONNMAN_SERVICE ".Session"
 #define CONNMAN_NOTIFICATION_INTERFACE   CONNMAN_SERVICE ".Notification"
 #define CONNMAN_PEER_INTERFACE           CONNMAN_SERVICE ".Peer"
-
+#define CONNMAN_GROUP_INTERFACE          CONNMAN_SERVICE ".Group"
 #define CONNMAN_PRIVILEGE_MODIFY   1
 #define CONNMAN_PRIVILEGE_SECRET   2
 
diff --git a/include/group.h b/include/group.h
new file mode 100644
index 0000000..d009194
--- /dev/null
+++ b/include/group.h
@@ -0,0 +1,175 @@
+#ifndef __CONNMAN_GROUP_H
+#define __CONNMAN_GROUP_H
+
+#include <gsupplicant/gsupplicant.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Represents a P2P group within ConnMan, tracking its configuration and peer state.
+ *
+ * This structure holds all relevant information for a Wi-Fi Direct (P2P) group
+ * managed by ConnMan, including D-Bus path, network parameters, ownership flags,
+ * peer metadata, and interface handles.
+ *
+ * @refcount           Reference count for memory management.
+ * @identifier         Unique identifier for the group.
+ * @path               D-Bus object path for the group.
+ * @interface          Pointer to the GSupplicantInterface used for this group.
+ * @orig_interface     Pointer to the original interface that initiated the group.
+ * @name               SSID or friendly name of the group.
+ * @passphrase         Passphrase used for group security.
+ * @peer_ip            Optional static IP address of the peer.
+ * @is_group_owner     Whether the local device is the group owner.
+ * @is_persistent      Indicates if the group is persistent across sessions.
+ * @tethering          Whether the group is in tethering mode.
+ * @autonomous         True if group was created without negotiation.
+ * @freq               Frequency (channel) used for the group.
+ * @is_static_ip       True if a static IP is assigned to this group.
+ * @group_owner        MAC address of the group owner peer (if not local).
+ * @peer_list          GSList of connected peer devices.
+ * @peer_hash          GHashTable mapping peer object paths to peer structs.
+ * @peer_intf          GHashTable mapping peer interface addresses to objects.
+ */
+
+struct connman_group {
+     int refcount;
+     char *identifier;
+     char *path;
+     GSupplicantInterface *interface;
+     GSupplicantInterface *orig_interface;
+
+     char *name;
+     char *passphrase;
+     char *peer_ip;
+     bool is_group_owner;
+     bool is_persistent;
+     bool tethering;
+     bool autonomous;
+     int freq;
+     bool is_static_ip;
+
+     const char *group_owner;
+     GSList *peer_list;
+     GHashTable *peer_hash;
+     GHashTable *peer_intf;
+};
+
+/**
+ * Increase the reference count of a ConnMan group object, with debug info.
+ * @param group Pointer to the connman_group to be referenced.
+ */
+#define connman_group_ref(group) \
+     connman_group_ref_debug(group, __FILE__, __LINE__, __func__)
+
+/**
+ * Decrease the reference count of a ConnMan group object, with debug info.
+ * Frees the group when the count reaches zero.
+ * @param group Pointer to the connman_group to be unreferenced.
+ */
+#define connman_group_unref(group) \
+     connman_group_unref_debug(group, __FILE__, __LINE__, __func__)
+
+/**
+ * Prefix used for wildcard SSIDs in P2P groups.
+ */
+#define P2P_WILDCARD_SSID "DIRECT-"
+
+/**
+ * Length of the P2P wildcard SSID prefix.
+ */
+#define P2P_WILDCARD_SSID_LEN 7
+
+/**
+ * Maximum allowed length for a P2P SSID.
+ */
+#define P2P_MAX_SSID 32
+
+/**
+ * Returns the current active connman_group instance.
+ * @return Pointer to the current connman_group.
+ */
+struct connman_group *__connman_group();
+
+/**
+ * Retrieves the D-Bus object path of the specified group.
+ * @param group Pointer to the connman_group.
+ * @return Const string of the group's D-Bus object path.
+ */
+const char* __connman_group_get_path(struct connman_group *group);
+
+/**
+ * Retrieves the unique identifier of the specified group.
+ * @param group Pointer to the connman_group.
+ * @return Const string of the group's identifier.
+ */
+const char* __connman_group_get_identifier(struct connman_group *group);
+
+/**
+ * Accepts an incoming connection request on the group using WPS parameters.
+ * @param group Pointer to the connman_group.
+ * @param wps_params Pointer to the WPS parameters for connection.
+ * @return 0 on success, negative error code on failure.
+ */
+int __connman_group_accept_connection(struct connman_group *group, GSupplicantPeerParams *wps_params);
+
+/**
+ * Checks whether any connman_group currently exists.
+ * @return true if a group exists, false otherwise.
+ */
+bool __connman_group_exist(void);
+
+/**
+ * Looks up a connman_group by its identifier.
+ * @param identifier Unique identifier string of the group.
+ * @return Pointer to the connman_group if found, NULL otherwise.
+ */
+struct connman_group *__connman_group_lookup_from_ident(const char *identifier);
+
+/**
+ * Appends the list of connman groups into a D-Bus message iterator.
+ * @param iter Pointer to the DBusMessageIter to append group list information.
+ */
+void __connman_group_list_struct(DBusMessageIter *iter);
+
+/**
+ * Creates a new connman_group with the given parameters.
+ * @param iface Pointer to the GSupplicantInterface for this group.
+ * @param ifname Network interface name string.
+ * @param ssid SSID string for the group.
+ * @param passphrase Passphrase string for securing the group.
+ * @param go True if the local device is the Group Owner.
+ * @param persistent True if the group is persistent.
+ * @param go_path D-Bus object path of the Group Owner interface.
+ * @param autonomous True if the group was autonomously created.
+ * @param freq Operating frequency (channel) for the group.
+ * @return Pointer to the newly created connman_group.
+ */
+struct connman_group* __connman_group_create(GSupplicantInterface *iface, const char *ifname, const char *ssid, const char *passphrase,
+                                                                   bool go, bool persistent, const char *go_path, bool autonomous, int freq);
+
+/**
+ * Removes and cleans up the connman_group associated with the given interface.
+ * @param interface Pointer to the GSupplicantInterface whose group is to be removed.
+ */
+void __connman_group_remove(GSupplicantInterface *interface);
+
+/**
+ * Initializes the connman_group subsystem, preparing internal structures.
+ */
+void __connman_group_init(void);
+
+/**
+ * Cleans up the connman_group subsystem, freeing resources.
+ */
+void __connman_group_cleanup(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CONNMAN_GROUP_H */
+
diff --git a/include/peer.h b/include/peer.h
index 8066393..6fe5e64 100644
--- a/include/peer.h
+++ b/include/peer.h
@@ -109,6 +109,9 @@ struct connman_peer_driver {
 int connman_peer_driver_register(struct connman_peer_driver *driver);
 void connman_peer_driver_unregister(struct connman_peer_driver *driver);
 
+struct connman_peer *connman_peer_get_by_path(const char *path);
+void __connman_peer_get_properties_struct(DBusMessageIter *iter, gpointer user_data);
+
 bool connman_peer_service_is_master(void);
 
 #ifdef __cplusplus
diff --git a/include/technology.h b/include/technology.h
index fd7b87a..391b446 100644
--- a/include/technology.h
+++ b/include/technology.h
@@ -23,6 +23,7 @@
 #define __CONNMAN_TECHNOLOGY_H
 
 #include <connman/service.h>
+#include <gdbus.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -66,11 +67,14 @@ struct connman_technology_driver {
      int (*set_regdom) (struct connman_technology *technology,
                                    const char *alpha2);
      int (*set_p2p_listen) (struct connman_technology *technology, bool enable);
+     int (*set_p2p_go) (DBusMessage *msg, struct connman_technology *technology,
+                                   const char *identifier, const char *passphrase);
 };
 
 int connman_technology_driver_register(struct connman_technology_driver *driver);
 void connman_technology_driver_unregister(struct connman_technology_driver *driver);
-
+void connman_technology_set_p2p_listen(struct connman_technology *technology,bool enabled);
+bool connman_technology_get_p2p_listen(struct connman_technology *technology);
 #ifdef __cplusplus
 }
 #endif
diff --git a/plugins/wifi.c b/plugins/wifi.c
index cbfcf5d..9fa22dd 100644
--- a/plugins/wifi.c
+++ b/plugins/wifi.c
@@ -55,8 +55,9 @@
 #include <connman/utsname.h>
 #include <connman/machine.h>
 #include <connman/tethering.h>
-
+#include "include/group.h"
 #include <gsupplicant/gsupplicant.h>
+#include "include/dbus.h"
 
 #include "src/shared/util.h"
 
@@ -73,6 +74,16 @@
 #define P2P_CONNECTION_TIMEOUT 100
 #define P2P_LISTEN_PERIOD 500
 #define P2P_LISTEN_INTERVAL 2000
+// Prefix string used for naming P2P group interfaces.
+static char *p2p_group_if_prefix = "p2p-";
+
+// Stores the current P2P group interface name, if assigned.
+static char *p2p_group_ifname = NULL;
+
+// Stores the interface index of the current P2P group interface; -1 if uninitialized.
+static int p2p_group_ifindex = -1;
+
+static char *p2p_go_identifier = NULL;
 
 #define ASSOC_STATUS_AUTH_TIMEOUT 16
 #define ASSOC_STATUS_NO_CLIENT 17
@@ -81,6 +92,8 @@
 static struct connman_technology *wifi_technology = NULL;
 static struct connman_technology *p2p_technology = NULL;
 
+static DBusConnection *connection;
+
 enum wifi_ap_capability{
      WIFI_AP_UNKNOWN   = 0,
      WIFI_AP_SUPPORTED       = 1,
@@ -181,11 +194,28 @@ static GList *pending_wifi_device = NULL;
 static GList *p2p_iface_list = NULL;
 static bool wfd_service_registered = false;
 
+// Holds the current DBus message related to group operations.
+static DBusMessage *group_msg;
+
+// Flag indicating whether a P2P group creation is in progress.
+static bool create_group_flag = false;
+
+// Stops an ongoing P2P device discovery or find operation.
+// 'data' is user-defined data passed to the function.
+static gboolean p2p_find_stop(gpointer data);
+
+// Initializes a GSupplicantSSID structure with the given SSID and passphrase.
+// Returns a pointer to the initialized GSupplicantSSID.
+static GSupplicantSSID *ssid_ap_init_p2p(const char *ssid, const char *passphrase);
+
+
 static void start_autoscan(struct connman_device *device);
 static int tech_set_tethering(struct connman_technology *technology,
                        const char *bridge, bool enabled);
 static int tech_set_p2p_listen(struct connman_technology *technology, bool enable);
 
+void __connman_p2p_go_set_bridge(char *bridge);
+
 static int p2p_tech_probe(struct connman_technology *technology)
 {
      p2p_technology = technology;
@@ -198,11 +228,88 @@ static void p2p_tech_remove(struct connman_technology *technology)
      p2p_technology = NULL;
 }
 
+/**
+ * Sets up a P2P Group Owner (GO) on the specified technology.
+ *
+ * @param msg        The DBus message initiating the request.
+ * @param technology The ConnMan technology on which to set the P2P GO.
+ * @param identifier Optional identifier for a persistent group.
+ * @param passphrase Optional passphrase for the P2P group.
+ *
+ * @return 0 on success, negative error code on failure.
+ *
+ * This function iterates over all interfaces supporting P2P, stops
+ * any ongoing P2P discovery or listen mode if necessary, and then
+ * creates a P2P group on each interface. If identifier or passphrase
+ * is provided, it attempts to add a persistent group with those credentials.
+ * Otherwise, it creates a new temporary group. The DBus message is
+ * referenced and a flag is set to indicate group creation is in progress.
+ */
+
+static int tech_set_p2p_go(DBusMessage *msg, struct connman_technology *technology,
+           const char *identifier, const char *passphrase) {
+     GList *list;
+     GSupplicantInterface *interface;
+     struct wifi_data *wifi;
+     struct wifi_tethering_info *info;
+     char p2p_ssid[P2P_MAX_SSID] = {0x00,};
+     int err;
+
+     if (!p2p_technology)
+           return -EOPNOTSUPP;
+
+     for (list = iface_list; list; list = list->next) {
+           struct wifi_data *wifi = list->data;
+           GSupplicantInterface *iface = wifi->interface;
+
+           if (!iface || !g_supplicant_interface_has_p2p(iface))
+                 continue;
+
+           if (connman_technology_get_p2p_listen(technology) == TRUE) {
+                 wifi->servicing--;
+                 if (!wifi->servicing || wifi->servicing < 0) {
+                       g_supplicant_interface_p2p_listen(iface, 0, 0);
+                       wifi->servicing = 0;
+                       connman_technology_set_p2p_listen(technology, false);
+                 }
+           } else {
+                 if (wifi->device)
+                       p2p_find_stop(wifi->device);
+           }
+
+           info = g_try_malloc0(sizeof(struct wifi_tethering_info));
+           if (info == NULL )
+                 return -ENOMEM;
+
+           info->wifi = wifi;
+           info->technology = technology;
+
+           if (identifier || passphrase) {
+                 snprintf(p2p_ssid, P2P_MAX_SSID, "%s%s", P2P_WILDCARD_SSID, identifier);
+                 info->ssid = ssid_ap_init_p2p(p2p_ssid, passphrase);
+
+                 err = g_supplicant_interface_p2p_persistent_group_add(iface,
+                             info->ssid, NULL, info);
+
+           } else {
+                 err = g_supplicant_interface_p2p_group_add(iface, NULL,
+                             NULL, info);
+           }
+
+           group_msg = dbus_message_ref(msg);
+           create_group_flag = true;
+     }
+
+     return -err;
+}
+
+
 static struct connman_technology_driver p2p_tech_driver = {
      .name       = "p2p",
      .type       = CONNMAN_SERVICE_TYPE_P2P,
      .probe            = p2p_tech_probe,
      .remove           = p2p_tech_remove,
+     .set_p2p_go = tech_set_p2p_go,
 };
 
 static bool is_p2p_connecting(void)
@@ -1536,6 +1643,8 @@ static void finalize_interface_creation(struct wifi_data *wifi)
      if (wifi->p2p_device)
            return;
 
+     __connman_group_init();
+
      if (!wifi->autoscan)
            setup_autoscan(wifi);
 
@@ -1601,6 +1710,8 @@ static int wifi_enable(struct connman_device *device)
      if (is_p2p_connecting())
            return -EINPROGRESS;
 
+     __connman_group_init();
+
      interface = connman_inet_ifname(index);
      ret = g_supplicant_interface_create(interface, driver, NULL,
                                    interface_create_callback,
@@ -1647,7 +1758,7 @@ static int wifi_disable(struct connman_device *device)
 
      remove_networks(device, wifi);
      remove_peers(wifi);
-
+     __connman_group_cleanup();
      ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
      if (ret < 0)
            return ret;
@@ -3336,6 +3447,80 @@ static void assoc_status_code(GSupplicantInterface *interface, int status_code)
      }
 }
 
+/**
+ * Handles the event when a P2P group has started.
+ *
+ * @param group The GSupplicantGroup representing the started P2P group.
+ *
+ * This function retrieves the associated wifi data and group properties
+ * (SSID, passphrase, frequency, role, persistence), creates or updates
+ * a corresponding ConnMan group structure, and if the device is the group
+ * owner and the group was just created, sends a DBus reply with the group's
+ * object path. It also resets the creation flag and releases the DBus message.
+ */
+
+static void p2p_group_started(GSupplicantGroup *group)
+{
+
+     struct wifi_data *wifi;
+     struct connman_group *connman_group = NULL;
+     GSupplicantInterface *iface = g_supplicant_group_get_interface(group);
+
+     wifi = g_supplicant_interface_get_data(iface);
+
+     if(!wifi)
+           return;
+
+     const char* go_path = g_supplicant_group_get_object_path(group);
+
+     bool is_group_owner = false;
+     if (g_supplicant_group_get_role(group) == G_SUPPLICANT_GROUP_ROLE_GO){
+           is_group_owner =  true;
+           __connman_p2p_go_set_bridge(p2p_group_ifname);
+     }
+     const char *ssid = g_supplicant_group_get_ssid(group);
+     const char *passphrase = g_supplicant_group_get_passphrase(group);
+     int freq = g_supplicant_group_get_frequency(group);
+     bool persistent = g_supplicant_group_get_persistent(group);
+
+     connman_group = __connman_group_create(iface, p2p_group_ifname, ssid, passphrase,
+                             is_group_owner, persistent, go_path, create_group_flag, freq);
+
+     const char *connman_group_path = __connman_group_get_path(connman_group);
+
+     if (is_group_owner)
+                 p2p_go_identifier = g_strdup(__connman_group_get_identifier(connman_group));
+     if (is_group_owner && create_group_flag) {
+           g_dbus_send_reply(connection, group_msg,
+                                   DBUS_TYPE_OBJECT_PATH, &connman_group_path,
+                                   DBUS_TYPE_INVALID);
+
+           create_group_flag = FALSE;
+           dbus_message_unref(group_msg);
+     }
+}
+
+/**
+ * Handles the event when a P2P group has finished.
+ *
+ * @param interface The GSupplicantInterface for the P2P group that finished.
+ *
+ * This function logs the event and removes the associated ConnMan group
+ * corresponding to the given interface.
+ */
+
+static void p2p_group_finished(GSupplicantInterface *interface)
+{
+     DBG("");
+
+     if (p2p_go_identifier) {
+                 g_free(p2p_go_identifier);
+               p2p_go_identifier = NULL;
+     }
+
+     __connman_group_remove(interface);
+}
+
 static const GSupplicantCallbacks callbacks = {
      .system_ready           = system_ready,
      .system_killed          = system_killed,
@@ -3359,9 +3544,10 @@ static const GSupplicantCallbacks callbacks = {
      .debug                  = debug,
      .disconnect_reasoncode  = disconnect_reasoncode,
      .assoc_status_code      = assoc_status_code,
+     .p2p_group_started      = p2p_group_started,
+     .p2p_group_finished     = p2p_group_finished,
 };
 
-
 static int tech_probe(struct connman_technology *technology)
 {
      wifi_technology = technology;
@@ -3374,6 +3560,35 @@ static void tech_remove(struct connman_technology *technology)
      wifi_technology = NULL;
 }
 
+
+static GSupplicantSSID *ssid_ap_init_p2p(const char *ssid, const char *passphrase)
+{
+     GSupplicantSSID *ap;
+
+     ap = g_try_malloc0(sizeof(GSupplicantSSID));
+     if (!ap)
+           return NULL;
+
+     ap->mode = G_SUPPLICANT_MODE_MASTER;
+     ap->ssid = ssid;
+     ap->ssid_len = strlen(ssid);
+     ap->scan_ssid = 0;
+     ap->freq = 2412;
+
+     if (!passphrase || strlen(passphrase) == 0) {
+           ap->security = G_SUPPLICANT_SECURITY_NONE;
+           ap->passphrase = NULL;
+     } else {
+            ap->security = G_SUPPLICANT_SECURITY_PSK;
+            ap->protocol = G_SUPPLICANT_PROTO_RSN;
+            ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
+            ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
+            ap->passphrase = passphrase;
+     }
+
+     return ap;
+}
+
 static GSupplicantSSID *ssid_ap_init(const struct connman_technology *technology)
 {
      GSupplicantSSID *ap;
@@ -3657,6 +3872,34 @@ static int tech_set_regdom(struct connman_technology *technology, const char *al
      return g_supplicant_set_country(alpha2, regdom_callback, NULL);
 }
 
+/**
+ * Adds a network interface to the ConnMan technology.
+ *
+ * @param technology Pointer to the ConnMan technology structure.
+ * @param index Index of the interface.
+ * @param name Name of the network interface.
+ * @param ident Identifier string for the interface.
+ *
+ * This function checks if the interface name has the P2P group prefix
+ * ("p2p-") and, if so, stores the interface name and index in the
+ * corresponding global variables for later use.
+ */
+
+static void tech_add_interface(struct connman_technology *technology,
+                 int index, const char *name, const char *ident)
+{
+     DBG("index %d name %s ident %s", index, name, ident);
+
+     if(p2p_group_if_prefix && g_str_has_prefix(name, p2p_group_if_prefix)) {
+           if (p2p_group_ifname) {
+                 g_free(p2p_group_ifname);
+                 p2p_group_ifname = NULL;
+           }
+           p2p_group_ifname = g_strdup(name);
+           p2p_group_ifindex = index;
+     }
+}
+
 static struct connman_technology_driver tech_driver = {
      .name       = "wifi",
      .type       = CONNMAN_SERVICE_TYPE_WIFI,
@@ -3665,12 +3908,13 @@ static struct connman_technology_driver tech_driver = {
      .set_tethering    = tech_set_tethering,
      .set_regdom = tech_set_regdom,
      .set_p2p_listen = tech_set_p2p_listen,
+     .add_interface    = tech_add_interface,
 };
 
 static int wifi_init(void)
 {
      int err;
-
+     connection = connman_dbus_get_connection();
      err = connman_network_driver_register(&network_driver);
      if (err < 0)
            return err;
diff --git a/src/connman.h b/src/connman.h
index f2b1228..034a990 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -596,8 +596,27 @@ void __connman_technology_remove_interface(enum connman_service_type type,
                        int index, const char *ident);
 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
                                    int result, const char *alpha2);
+/**
+ * Sets up a P2P Group Owner (GO) for the ConnMan technology.
+ *
+ * @param msg       The D-Bus message requesting the P2P GO setup.
+ * @param ident     Identifier (SSID suffix) to be used for the P2P group.
+ * @param passphrase Passphrase for the P2P group.
+ *
+ * @return 0 on success or a negative error code on failure.
+ *
+ * This function configures and starts a P2P group owner with the given
+ * identifier and passphrase using the ConnMan and supplicant interfaces.
+ */
+int __connman_technology_set_p2p_go(DBusMessage *msg, const char *ident,
+                       const char *passphrase);
 const char *__connman_technology_get_regdom(enum connman_service_type type);
 
+int __connman_tethering_set_enabled(void);
+void __connman_tethering_set_disabled(void);
+
+
+
 #include <connman/device.h>
 
 int __connman_device_init(const char *device, const char *nodevice);
@@ -1052,6 +1071,17 @@ typedef void (*ippool_collision_cb_t) (struct connman_ippool *pool,
 int __connman_ippool_init(void);
 void __connman_ippool_cleanup(void);
 
+
+#define __connman_ippool_ref(ipconfig) \
+     __connman_ippool_ref_debug(ipconfig, __FILE__, __LINE__, __func__)
+#define __connman_ippool_unref(ipconfig) \
+     __connman_ippool_unref_debug(ipconfig, __FILE__, __LINE__, __func__)
+
+struct connman_ippool *__connman_ippool_ref_debug(struct connman_ippool *pool,
+           const char *file, int line, const char *caller);
+void __connman_ippool_unref_debug(struct connman_ippool *pool,
+           const char *file, int line, const char *caller);
+
 void __connman_ippool_free(struct connman_ippool *pool);
 
 struct connman_ippool *__connman_ippool_create(int index,
@@ -1066,6 +1096,8 @@ const char *__connman_ippool_get_subnet_mask(struct connman_ippool *pool);
 const char *__connman_ippool_get_start_ip(struct connman_ippool *pool);
 const char *__connman_ippool_get_end_ip(struct connman_ippool *pool);
 
+char *__connman_util_insert_colon_to_mac_addr(const char *mac_addr);
+
 void __connman_ippool_newaddr(int index, const char *address,
                        unsigned char prefixlen);
 void __connman_ippool_deladdr(int index, const char *address,
@@ -1146,3 +1178,4 @@ int __connman_util_get_random(uint64_t *val);
 unsigned int __connman_util_random_delay_ms(unsigned int secs);
 int __connman_util_init(void);
 void __connman_util_cleanup(void);
+void __connman_p2p_set_dhcp_pool(struct connman_ippool *ippool);
diff --git a/src/group.c b/src/group.c
new file mode 100644
index 0000000..8715d65
--- /dev/null
+++ b/src/group.c
@@ -0,0 +1,993 @@
+/*
+ *
+ *  Connection Manager
+ *
+ *  Copyright (C) 2025 LG Electronics, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+#include <gdbus.h>
+#include <ctype.h>
+
+#include <connman/storage.h>
+#include <connman/setting.h>
+#include <connman/agent.h>
+#include "include/group.h"
+#include <gsupplicant/gsupplicant.h>
+
+#include "connman.h"
+
+/*
+ * Global static variables used for P2P group management:
+ *
+ * connection   - The active D-Bus connection used to communicate with external services.
+ * group_list   - List of currently tracked P2P groups.
+ * group_hash   - Hash table for quick lookup of groups by their object path or identifier.
+ */
+static DBusConnection *connection = NULL;
+static GList *group_list = NULL;
+static GHashTable *group_hash = NULL;
+
+
+void __connman_p2p_go_tethering_set_enabled(void);
+void __connman_p2p_go_tethering_set_disabled(void);
+int __connman_p2p_go_set_enabled(void);
+int __connman_p2p_go_set_disabled(void);
+
+/*
+ * Structure used to pass peer-related callback data:
+ *
+ * iter  - Pointer to the D-Bus message iterator used for constructing responses.
+ * group - Pointer to the associated connman_group structure representing the current P2P group.
+ */
+struct peer_cb_data {
+     DBusMessageIter *iter;
+     struct connman_group *group;
+};
+
+/*
+ * Retrieves an existing connman_group by identifier or creates a new one if not found.
+ *
+ * identifier - The unique identifier for the P2P group.
+ *
+ * Returns a pointer to the connman_group structure associated with the given identifier,
+ * initializing internal group tracking structures (hash tables and list) if needed.
+ */
+
+
+static struct connman_group *group_get(const char *identifier)
+{
+     struct connman_group *group;
+
+     group = g_hash_table_lookup(group_hash, identifier);
+     if (group) {
+           return group;
+     }
+
+     group = g_try_new0(struct connman_group, 1);
+     if (!group)
+           return NULL;
+
+     DBG("group %p", group);
+
+     group->identifier = g_strdup(identifier);
+     group->peer_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
+     group->peer_intf = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
+
+     group_list = g_list_prepend(group_list, group);
+
+     g_hash_table_insert(group_hash, group->identifier, group);
+
+     return group;
+}
+
+static int set_tethering(struct connman_group *group,
+           bool enabled)
+{
+     group->tethering = enabled;
+     dbus_bool_t val = enabled;
+
+     connman_dbus_property_changed_basic(group->path,
+                 CONNMAN_GROUP_INTERFACE, "Tethering",
+                 DBUS_TYPE_BOOLEAN,
+                 &val);
+
+     if (enabled == TRUE) {
+           __connman_p2p_go_set_enabled();
+           __connman_p2p_go_tethering_set_enabled();
+     } else {
+           __connman_p2p_go_tethering_set_disabled();
+           __connman_p2p_go_set_disabled();
+
+     }
+     return 0;
+}
+
+/**
+ * Handles a D-Bus SetProperty method call for a connman_group object.
+ *
+ * @param conn      The D-Bus connection.
+ * @param msg       The incoming D-Bus message containing the property name and value.
+ * @param user_data Pointer to the associated connman_group structure.
+ *
+ * @return          A D-Bus message representing the reply or error.
+ *
+ * This method currently supports setting the "Tethering" boolean property.
+ * It validates the argument, applies the change, and sends a reply or error
+ * based on the operation outcome.
+ */
+
+
+static DBusMessage *set_property(DBusConnection *conn,
+                             DBusMessage *msg, void *user_data)
+{
+     struct connman_group *group = user_data;
+     DBusMessageIter iter, value;
+     const char *name;
+     int type;
+
+     DBG("group %p", group);
+
+     if (dbus_message_iter_init(msg, &iter) == FALSE)
+           return __connman_error_invalid_arguments(msg);
+
+     if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+           return __connman_error_invalid_arguments(msg);
+
+     dbus_message_iter_get_basic(&iter, &name);
+     dbus_message_iter_next(&iter);
+
+     if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+           return __connman_error_invalid_arguments(msg);
+
+     dbus_message_iter_recurse(&iter, &value);
+
+     type = dbus_message_iter_get_arg_type(&value);
+
+     if (g_str_equal(name, "Tethering") == TRUE) {
+           int err;
+           bool tethering;
+
+           if (type != DBUS_TYPE_BOOLEAN)
+                 return __connman_error_invalid_arguments(msg);
+
+           dbus_message_iter_get_basic(&value, &tethering);
+
+           if (group->tethering == tethering) {
+                 if (tethering == FALSE)
+                       return __connman_error_already_disabled(msg);
+                 else
+                       return __connman_error_already_enabled(msg);
+           }
+
+           err = set_tethering(group, tethering);
+           if (err < 0)
+                 return __connman_error_failed(msg, -err);
+     }
+
+     return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+/*
+ * Appends relevant group properties to the D-Bus message dictionary.
+ *
+ * @param dict  - D-Bus dictionary iterator to append properties into.
+ * @param group - Pointer to the connman_group structure whose properties are appended.
+ *
+ * Appends the following properties if available:
+ * - "Name": group's SSID name (if present)
+ * - "Owner": boolean indicating if this device is the group owner
+ * - "Passphrase": group's passphrase (only if this device is GO)
+ * - "OwnerPath": D-Bus object path of the group owner (only if not GO)
+ * - "Persistent": boolean indicating persistent group status
+ * - "Tethering": boolean indicating tethering state
+ */
+
+static void append_properties(DBusMessageIter *dict, struct connman_group *group)
+{
+     dbus_bool_t val;
+
+     if(group->name)
+           connman_dbus_dict_append_basic(dict, "Name", DBUS_TYPE_STRING, &group->name);
+
+     val = group->is_group_owner;
+     connman_dbus_dict_append_basic(dict, "Owner", DBUS_TYPE_BOOLEAN, &val);
+
+     if(group->is_group_owner)
+           connman_dbus_dict_append_basic(dict, "Passphrase", DBUS_TYPE_STRING, &group->passphrase);
+     else
+           connman_dbus_dict_append_basic(dict, "OwnerPath", DBUS_TYPE_OBJECT_PATH, &group->group_owner);
+
+     val = group->is_persistent;
+     connman_dbus_dict_append_basic(dict, "Persistent", DBUS_TYPE_BOOLEAN, &val);
+
+     val = group->tethering;
+     connman_dbus_dict_append_basic(dict, "Tethering", DBUS_TYPE_BOOLEAN, &val);
+}
+
+/*
+ * Handles the D-Bus GetProperties method call for a connman_group object.
+ *
+ * @param conn      - D-Bus connection (unused in this function).
+ * @param msg       - Incoming D-Bus message requesting properties.
+ * @param user_data - Pointer to the connman_group whose properties are requested.
+ *
+ * @return A D-Bus reply message containing a dictionary of the group's properties,
+ *         such as Name, Owner, Passphrase, OwnerPath, Persistent, and Tethering.
+ *
+ * The function builds a D-Bus reply message, appends all relevant properties of
+ * the group using append_properties(), and returns the message for sending back
+ * to the client.
+ */
+
+ static DBusMessage *get_properties(DBusConnection *conn,
+     DBusMessage *msg, void *user_data)
+{
+     struct connman_group *group = user_data;
+     DBusMessage *reply;
+     DBusMessageIter array, dict;
+
+     DBG("group %p", group);
+
+     reply = dbus_message_new_method_return(msg);
+     if (reply == NULL)
+           return NULL;
+
+     dbus_message_iter_init_append(reply, &array);
+
+     connman_dbus_dict_open(&array, &dict);
+     append_properties(&dict, group);
+     connman_dbus_dict_close(&array, &dict);
+
+     return reply;
+}
+
+/**
+ * Sends a D-Bus signal to notify that a group has been added.
+ *
+ * @param group Pointer to the connman_group structure representing the added group.
+ *
+ * This function constructs a D-Bus signal message with the "GroupAdded" signal name,
+ * appends the group's object path and properties, and sends the signal over the active
+ * D-Bus connection. The signal includes details such as the group's name, owner status,
+ * passphrase, and tethering state.
+ */
+static void group_added_signal(struct connman_group *group)
+{
+     DBusMessage *signal;
+     DBusMessageIter iter;
+     DBusMessageIter dict;
+
+     signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
+                 CONNMAN_MANAGER_INTERFACE, "GroupAdded");
+     if (!signal)
+           return;
+
+     dbus_message_iter_init_append(signal, &iter);
+     dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+                                         &group->path);
+
+     connman_dbus_dict_open(&iter, &dict);
+     append_properties(&dict, group);
+     connman_dbus_dict_close(&iter, &dict);
+
+     dbus_connection_send(connection, signal, NULL);
+     dbus_message_unref(signal);
+}
+
+/**
+ * Sends a D-Bus signal to notify that a group has been removed.
+ *
+ * @param group Pointer to the connman_group structure representing the removed group.
+ *
+ * This function emits a D-Bus signal with the "GroupRemoved" signal name, appending
+ * the group's object path to indicate which group has been removed. The signal is sent
+ * over the active D-Bus connection to notify clients about the removal of the group.
+ */
+static void group_removed_signal(struct connman_group *group)
+{
+     g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
+                 CONNMAN_MANAGER_INTERFACE, "GroupRemoved",
+                 DBUS_TYPE_OBJECT_PATH, &group->path,
+                 DBUS_TYPE_INVALID);
+}
+
+/**
+ * Callback function for handling P2P disconnection events.
+ *
+ * @param result    Integer indicating the result of the disconnection operation.
+ * @param interface Pointer to the GSupplicantInterface representing the P2P interface.
+ * @param user_data Pointer to the connman_group structure associated with the disconnection.
+ *
+ * This function is invoked when a P2P disconnection operation completes. It logs the
+ * group information for debugging purposes and can be extended to handle additional
+ * cleanup or notification logic.
+ */
+static void p2p_disconnect_callback(int result,
+                                                     GSupplicantInterface *interface,
+                                                     void *user_data)
+{
+     struct connman_group *group = user_data;
+
+     DBG("group %p\n", group);
+}
+
+/**
+ * Handles a D-Bus method call to disconnect a P2P group.
+ *
+ * @param conn      Pointer to the D-Bus connection.
+ * @param msg       Pointer to the incoming D-Bus message requesting the disconnection.
+ * @param user_data Pointer to the connman_group structure representing the P2P group.
+ *
+ * @return A D-Bus reply message indicating the success or failure of the operation.
+ *
+ * This function initiates the disconnection of a P2P group using the supplicant interface.
+ * If the operation fails, it returns an appropriate error message. If the disconnection
+ * is in progress, it waits for the callback (`p2p_disconnect_callback`) to handle the result.
+ */
+static DBusMessage *p2p_disconnect(DBusConnection *conn,
+                                                     DBusMessage *msg, void *user_data)
+{
+     struct connman_group *group = user_data;
+     int err = 0;
+
+     DBG("group %p", group);
+
+     // Initiate the P2P group disconnection using the supplicant interface.
+     err = g_supplicant_interface_p2p_group_disconnect(group->interface,
+                                                                                   p2p_disconnect_callback,
+                                                                                   group);
+
+     if (err < 0) {
+           // If the error is not EINPROGRESS, return a failure message.
+           if (err != -EINPROGRESS)
+                 return __connman_error_failed(msg, -err);
+     }
+
+     // Return a generic D-Bus reply indicating the operation was initiated.
+     return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+/**
+ * Handles a D-Bus method call to invite a peer to a P2P group.
+ *
+ * @param conn      Pointer to the D-Bus connection.
+ * @param msg       Pointer to the incoming D-Bus message requesting the invitation.
+ * @param user_data Pointer to the connman_group structure representing the P2P group.
+ *
+ * @return A D-Bus reply message indicating the success or failure of the operation.
+ *
+ * This function is a placeholder for inviting a peer to a P2P group. It currently
+ * returns a generic D-Bus reply indicating that the operation was initiated.
+ * The actual implementation needs to be added.
+ */
+static DBusMessage *p2p_invite(DBusConnection *conn,
+                                               DBusMessage *msg, void *user_data)
+{
+     // TODO: Implement the logic for inviting a peer to a P2P group.
+     return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+/**
+ * Appends peer information to a D-Bus message structure.
+ *
+ * @param value     Pointer to the peer identifier (value from the hash table).
+ * @param user_data Pointer to the peer_cb_data structure containing the D-Bus iterator
+ *                  and the associated connman_group.
+ *
+ * This function retrieves peer-related information from the connman_group structure
+ * and appends it to the D-Bus message as a structured entry. It includes the peer's
+ * object path and an empty dictionary for additional properties.
+ */
+static void append_peer_struct(gpointer value, gpointer user_data)
+{
+     struct peer_cb_data *cbd = user_data;
+     const char *peer_ident = value;
+     const char *service_path;
+     DBusMessageIter entry, dict;
+
+     DBG("peer_ident %s", peer_ident);
+
+     // Open a new container in the D-Bus message for the peer structure.
+     dbus_message_iter_open_container(cbd->iter, DBUS_TYPE_STRUCT, NULL, &entry);
+
+     // Retrieve the service path associated with the peer identifier.
+     service_path = g_hash_table_lookup(cbd->group->peer_hash, peer_ident);
+
+     // Append the service path to the D-Bus message.
+     dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH, &service_path);
+
+     // Open and close an empty dictionary for additional peer properties.
+     connman_dbus_dict_open(&entry, &dict);
+     connman_dbus_dict_close(&entry, &dict);
+
+     // Close the container for the peer structure.
+     dbus_message_iter_close_container(cbd->iter, &entry);
+}
+
+/**
+ * Appends all peer structures to a D-Bus message iterator.
+ *
+ * @param iter      Pointer to the D-Bus message iterator where peer structures will be appended.
+ * @param user_data Pointer to the connman_group structure containing the list of peers.
+ *
+ * This function iterates through the peer list in the connman_group structure and appends
+ * each peer's information to the D-Bus message using the `append_peer_struct` function.
+ * It uses a helper structure (`peer_cb_data`) to pass the iterator and group information
+ * to the callback function.
+ */
+static void append_peer_structs(DBusMessageIter *iter, void *user_data)
+{
+     struct connman_group *group = user_data;
+     struct peer_cb_data cbd;
+
+     cbd.iter = iter;
+     cbd.group = group;
+
+     DBG("iter %p group %p", iter, group);
+
+     // Iterate through the peer list and append each peer's structure.
+     g_slist_foreach(group->peer_list, append_peer_struct, &cbd);
+}
+
+/**
+ * Appends group owner (GO) information to a D-Bus message structure.
+ *
+ * @param iter      Pointer to the D-Bus message iterator where the GO information will be appended.
+ * @param user_data Pointer to the connman_group structure representing the P2P group.
+ *
+ * This function appends the group owner's object path and an empty dictionary for additional
+ * properties to the D-Bus message. If the group or group owner is NULL, the function returns
+ * without performing any operations.
+ */
+static void append_peer_go(DBusMessageIter *iter, void *user_data)
+{
+     struct connman_group *group = user_data;
+     const char *peer_ident, *peer_dev_addr = NULL;
+     DBusMessageIter entry, dict;
+     struct connman_peer *connman_peer;
+
+     // Return early if the group or group owner is NULL.
+     if (group == NULL || g_list_find(group_list, group) == NULL || group->group_owner == NULL)
+           return;
+
+     // Open a new container in the D-Bus message for the group owner structure.
+     dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &entry);
+
+     // Append the group owner's object path to the D-Bus message.
+     dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH, &group->group_owner);
+
+           connman_peer = connman_peer_get_by_path(group->group_owner);
+     if(connman_peer) {
+           peer_ident = connman_peer_get_identifier(connman_peer);
+           __connman_peer_get_properties_struct(&entry, connman_peer);
+     } else {
+           connman_dbus_dict_open(&entry, &dict);
+           peer_ident = strrchr(group->group_owner, '_') + 1;
+           peer_dev_addr = __connman_util_insert_colon_to_mac_addr(peer_ident);
+           connman_dbus_dict_append_basic(&dict, "DeviceAddress", DBUS_TYPE_STRING, &peer_dev_addr);
+           connman_dbus_dict_close(&entry, &dict);
+     }
+
+     // Open and close an empty dictionary for additional GO properties.
+
+
+     // Close the container for the group owner structure.
+     dbus_message_iter_close_container(iter, &entry);
+     g_free(peer_dev_addr);
+}
+
+/**
+ * Handles a D-Bus method call to retrieve peer information for a P2P group.
+ *
+ * @param conn      Pointer to the D-Bus connection.
+ * @param msg       Pointer to the incoming D-Bus message requesting peer information.
+ * @param user_data Pointer to the connman_group structure representing the P2P group.
+ *
+ * @return A D-Bus reply message containing peer information.
+ *
+ * This function constructs a D-Bus reply message based on the group's ownership status.
+ * If the group is owned by this device, it appends all peer structures using the
+ * `append_peer_structs` function. Otherwise, it appends the group owner information
+ * using the `append_peer_go` function.
+ */
+static DBusMessage *get_peers(DBusConnection *conn, DBusMessage *msg, void *user_data)
+{
+     struct connman_group *group = user_data;
+     DBusMessage *reply;
+
+     // Create a reply message for the incoming D-Bus method call.
+     reply = dbus_message_new_method_return(msg);
+     if (reply == NULL)
+           return NULL;
+
+     // Append peer information based on the group's ownership status.
+     if (group->is_group_owner)
+           __connman_dbus_append_objpath_dict_array(reply, append_peer_structs, group);
+     else
+           __connman_dbus_append_objpath_dict_array(reply, append_peer_go, group);
+
+     return reply;
+}
+
+/**
+ * Defines the D-Bus methods for the connman_group interface.
+ *
+ * This table specifies the methods supported by the connman_group interface, including:
+ * - `GetProperties`: Retrieves the group's properties.
+ * - `SetProperty`: Sets a specific property of the group.
+ * - `Disconnect`: Disconnects the P2P group.
+ * - `Invite`: Invites a peer to the P2P group.
+ * - `GetPeers`: Retrieves information about peers in the P2P group.
+ *
+ * Each entry includes the method name, input/output arguments, and the corresponding
+ * handler function.
+ */
+static const GDBusMethodTable group_methods[] = {
+     { GDBUS_DEPRECATED_METHOD("GetProperties",
+                 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                 get_properties) },
+     { GDBUS_METHOD("SetProperty",
+                 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
+                 NULL, set_property) },
+     { GDBUS_METHOD("Disconnect",
+                 NULL, NULL, p2p_disconnect) },
+     { GDBUS_METHOD("Invite",
+                 GDBUS_ARGS({ "service_path", "s" }),
+                 NULL, p2p_invite) },
+     { GDBUS_METHOD("GetPeers",
+                 NULL, GDBUS_ARGS({ "peers", "a(oa{sv})" }),
+                 get_peers) },
+     {},
+};
+
+/**
+ * Defines the D-Bus signals for the connman_group interface.
+ *
+ * This table specifies the signals emitted by the connman_group interface, including:
+ * - `PropertyChanged`: Emitted when a property of the group changes.
+ * - `PeerAdded`: Emitted when a new peer is added to the group.
+ * - `PeerRemoved`: Emitted when a peer is removed from the group.
+ *
+ * Each entry includes the signal name and its arguments.
+ */
+static const GDBusSignalTable group_signals[] = {
+     { GDBUS_SIGNAL("PropertyChanged",
+                 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
+     { GDBUS_SIGNAL("PeerAdded",
+                 GDBUS_ARGS({ "path", "o" })) },
+     { GDBUS_SIGNAL("PeerRemoved",
+                 GDBUS_ARGS({ "path", "o" })) },
+     { },
+};
+
+/**
+ * Retrieves the D-Bus object path of a connman_group.
+ *
+ * @param group Pointer to the connman_group structure.
+ *
+ * @return The D-Bus object path of the group if the group is valid, otherwise NULL.
+ *
+ * This function checks if the provided connman_group pointer is valid and returns
+ * its associated D-Bus object path. If the group is NULL, it returns NULL.
+ */
+const char* __connman_group_get_path(struct connman_group *group)
+{
+     if (group)
+           return group->path;
+
+     return NULL;
+}
+
+/**
+ * Retrieves the identifier of a connman_group.
+ *
+ * @param group Pointer to the connman_group structure.
+ *
+ * @return The identifier of the group.
+ *
+ * This function returns the unique identifier associated with the connman_group structure.
+ * It assumes that the group pointer is valid and does not perform null checks.
+ */
+const char* __connman_group_get_identifier(struct connman_group *group)
+{
+     return group->identifier;
+}
+
+/**
+ * Checks if any connman_group exists.
+ *
+ * @return `true` if the group list is not empty, otherwise `false`.
+ *
+ * This function verifies whether there are any groups in the global `group_list`.
+ * It returns `false` if the list is NULL or contains no data, indicating no groups exist.
+ */
+bool __connman_group_exist(void)
+{
+     if (!group_list || !group_list->data)
+           return false;
+
+     return true;
+}
+
+/**
+ * Looks up a connman_group by its identifier.
+ *
+ * @param identifier Pointer to the unique identifier of the group.
+ *
+ * @return A pointer to the connman_group structure if found, or creates a new group
+ *         if it does not exist.
+ *
+ * This function uses the `group_get` function to retrieve an existing connman_group
+ * by its identifier or create a new one if no matching group is found.
+ */
+struct connman_group *__connman_group_lookup_from_ident(const char *identifier)
+{
+     return group_get(identifier);
+}
+
+/**
+ * Appends group properties to a D-Bus dictionary iterator.
+ *
+ * @param dict      Pointer to the D-Bus dictionary iterator where properties will be appended.
+ * @param user_data Pointer to the connman_group structure containing the properties.
+ *
+ * This function uses the `append_properties` function to add relevant properties
+ * of the connman_group to the provided D-Bus dictionary iterator.
+ */
+static void append_dict_properties(DBusMessageIter *dict, void *user_data)
+{
+     struct connman_group *group = user_data;
+
+     append_properties(dict, group);
+}
+
+/**
+ * Appends a connman_group structure to a D-Bus message iterator.
+ *
+ * @param iter      Pointer to the D-Bus message iterator where the group structure will be appended.
+ * @param function  Callback function to append additional properties to the dictionary.
+ * @param group     Pointer to the connman_group structure representing the group.
+ *
+ * This function appends the group's object path and a dictionary of properties to the
+ * provided D-Bus message iterator. If a callback function is provided, it is used to
+ * append additional properties to the dictionary.
+ */
+static void append_struct_group(DBusMessageIter *iter,
+                                               connman_dbus_append_cb_t function,
+                                               struct connman_group *group)
+     {
+     DBusMessageIter entry, dict;
+
+     // Open a new container in the D-Bus message for the group structure.
+     dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &entry);
+
+     // Append the group's object path to the D-Bus message.
+     dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH, &group->path);
+
+     // Open the dictionary for appending group properties.
+     connman_dbus_dict_open(&entry, &dict);
+
+     // If a callback function is provided, use it to append additional properties.
+     if (function)
+           function(&dict, group);
+
+     // Close the dictionary after appending properties.
+     connman_dbus_dict_close(&entry, &dict);
+
+     // Close the container for the group structure.
+     dbus_message_iter_close_container(iter, &entry);
+}
+
+/**
+ * Appends a connman_group structure to a D-Bus message iterator.
+ *
+ * @param value     Pointer to the connman_group structure to be appended.
+ * @param user_data Pointer to the D-Bus message iterator where the group structure will be appended.
+ *
+ * This function checks if the group's object path is valid before appending the group
+ * structure to the D-Bus message. It uses the `append_struct_group` function to append
+ * the group's object path and properties.
+ */
+static void append_struct(gpointer value, gpointer user_data)
+{
+     struct connman_group *group = value;
+     DBusMessageIter *iter = user_data;
+
+     // Skip if the group's object path is invalid.
+     if (!group->path)
+           return;
+
+     // Append the group structure to the D-Bus message.
+     append_struct_group(iter, append_dict_properties, group);
+}
+
+/**
+ * Appends all connman_group structures to a D-Bus message iterator.
+ *
+ * @param iter Pointer to the D-Bus message iterator where the group structures will be appended.
+ *
+ * This function iterates through the global `group_list` and appends each group's
+ * structure to the provided D-Bus message iterator using the `append_struct` function.
+ */
+void __connman_group_list_struct(DBusMessageIter *iter)
+{
+     g_list_foreach(group_list, append_struct, iter);
+}
+
+/**
+ * Registers a connman_group with the D-Bus system.
+ *
+ * @param group Pointer to the connman_group structure to be registered.
+ *
+ * @return 0 on success, or a negative error code if the group is already registered.
+ *
+ * This function assigns a unique D-Bus object path to the group, registers the group
+ * interface with the D-Bus system, and emits a "GroupAdded" signal to notify clients
+ * about the new group. If the group is already registered (i.e., has a valid path),
+ * it returns `-EALREADY`.
+ */
+static int group_register(struct connman_group *group)
+{
+     DBG("group %p", group);
+
+     // Check if the group is already registered.
+     if (group->path != NULL)
+           return -EALREADY;
+
+     // Assign a unique D-Bus object path to the group.
+     group->path = g_strdup_printf("%s/group/%s", CONNMAN_PATH, group->identifier);
+
+     DBG("path %s", group->path);
+
+     // Register the group interface with the D-Bus system.
+     g_dbus_register_interface(connection, group->path,
+                                               CONNMAN_GROUP_INTERFACE,
+                                               group_methods, group_signals,
+                                               NULL, group, NULL);
+
+     if (!group->autonomous)
+                 __connman_p2p_set_dhcp_pool(NULL);
+
+     // Emit a "GroupAdded" signal to notify clients about the new group.
+     group_added_signal(group);
+
+     return 0;
+}
+
+/**
+ * Callback function for handling the creation of a P2P interface.
+ *
+ * @param result    Integer indicating the result of the interface creation operation.
+ * @param interface Pointer to the GSupplicantInterface representing the created interface.
+ * @param user_data Pointer to the connman_group structure associated with the interface.
+ *
+ * This function is invoked when a P2P interface creation operation completes. It logs
+ * the result and interface name for debugging purposes and assigns the created interface
+ * to the connman_group structure.
+ */
+static void interface_create_callback(int result,
+                                                           GSupplicantInterface *interface,
+                                                           void *user_data)
+{
+     struct connman_group *group = user_data;
+
+     DBG("result %d ifname %s", result,
+           g_supplicant_interface_get_ifname(interface));
+
+     // Assign the created interface to the group.
+     group->interface = interface;
+}
+
+/**
+ * Creates and initializes a connman_group structure.
+ *
+ * @param iface       Pointer to the GSupplicantInterface representing the P2P interface.
+ * @param ifname      Name of the network interface.
+ * @param ssid        SSID of the group.
+ * @param passphrase  Passphrase for the group (used if the device is the group owner).
+ * @param go          Boolean indicating if the device is the group owner.
+ * @param persistent  Boolean indicating if the group is persistent.
+ * @param go_path     D-Bus object path of the group owner (used if the device is not the group owner).
+ * @param autonomous  Boolean indicating if the group is autonomous.
+ * @param freq        Frequency of the group.
+ *
+ * @return Pointer to the created connman_group structure, or NULL if creation fails.
+ *
+ * This function initializes a connman_group structure with the provided parameters,
+ * registers the group with the D-Bus system, and initiates the creation of the P2P interface.
+ * It generates a unique identifier for the group based on the SSID and uses it to retrieve
+ * or create the group.
+ */
+struct connman_group* __connman_group_create(GSupplicantInterface *iface, const char *ifname, const char *ssid, const char *passphrase,
+                                                                       bool go, bool persistent, const char *go_path, bool autonomous, int freq)
+{
+     struct connman_group *group;
+     char *ident;
+     int ssid_len = strlen(ssid);
+     GString *name = g_string_sized_new(ssid_len * 2 + 1);
+     int i = 0;
+     int ret = 0;
+
+     DBG("ssid : %s, len : %d\n", ssid, ssid_len);
+
+     // Generate a unique identifier for the group based on the SSID.
+     for (i = 0; i < ssid_len; i++) {
+           g_string_append_printf(name, "%02x", ssid[i]);
+     }
+
+     ident = g_string_free(name, FALSE);
+
+     DBG("ident : %s\n", ident);
+
+     // Retrieve or create the group using the identifier.
+     group = group_get(ident);
+
+     if (!group)
+           return NULL;
+
+     // Initialize the group properties.
+     group->name = g_strdup(ssid);
+     group->is_group_owner = go;
+     if (go) {
+           group->passphrase = g_strdup(passphrase);
+     }
+     group->is_persistent = persistent;
+     group->group_owner = go_path;
+     group->autonomous = autonomous;
+     group->freq = freq;
+     group->is_static_ip = false;
+     group->orig_interface = iface;
+
+     DBG("go path : %s\n", go_path);
+
+     // Register the group with the D-Bus system.
+     ret = group_register(group);
+
+     // If registration succeeds, initiate the creation of the P2P interface.
+     if (ret == 0) {
+           g_supplicant_interface_create(ifname, "nl80211", NULL, interface_create_callback, group);
+     }
+
+     return group;
+}
+
+/**
+ * Removes a connman_group associated with a given P2P interface.
+ *
+ * @param interface Pointer to the GSupplicantInterface representing the P2P interface.
+ *
+ * This function searches for a connman_group associated with the provided interface
+ * in the global `group_list`. If found, it unregisters the group from the D-Bus system,
+ * emits a "GroupRemoved" signal, and cleans up all resources associated with the group.
+ */
+void __connman_group_remove(GSupplicantInterface *interface)
+{
+     GList *list;
+     struct connman_group *group = NULL;
+
+     // Return early if there are no groups in the list.
+     if (!group_list)
+           return;
+
+     // Iterate through the group list to find the group associated with the interface.
+     for (list = group_list; list != NULL; list = list->next) {
+           group = list->data;
+
+           if (group->interface == interface) {
+                 break;
+           }
+     }
+
+     // If the group is found, proceed with removal.
+     if (group) {
+           DBG("group removed\n");
+
+           // Ensure the D-Bus connection is initialized.
+           if (!connection)
+                 connection = connman_dbus_get_connection();
+
+           DBG("group path : %s\n", group->path);
+
+           // Emit a "GroupRemoved" signal to notify clients.
+           group_removed_signal(group);
+
+           // Unregister the group interface from the D-Bus system.
+           g_dbus_unregister_interface(connection, group->path, CONNMAN_GROUP_INTERFACE);
+
+           // Remove the group from the hash table and list.
+           g_hash_table_remove(group_hash, group->identifier);
+           group_list = g_list_remove(group_list, group);
+
+           // Destroy the group's hash tables and free allocated memory.
+           g_hash_table_destroy(group->peer_hash);
+           g_hash_table_destroy(group->peer_intf);
+
+           g_free(group->path);
+           g_free(group);
+     }
+}
+
+/**
+ * Initializes the connman_group system.
+ *
+ * This function sets up the global D-Bus connection and initializes the hash table
+ * used for managing connman_group objects. It must be called before any group-related
+ * operations are performed.
+ */
+void __connman_group_init(void)
+{
+     // Establish the global D-Bus connection.
+     connection = connman_dbus_get_connection();
+
+     // Initialize the hash table for managing connman_group objects.
+     group_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
+}
+
+/**
+ * Cleans up all connman_group objects and releases associated resources.
+ *
+ * This function iterates through the global `group_list`, removes each group,
+ * and releases its resources. It also destroys the global `group_hash` table.
+ * Special handling is included to prevent crashes by checking for null paths
+ * and ensuring proper cleanup of D-Bus interfaces and supplicant connections.
+ */
+void __connman_group_cleanup(void)
+{
+     GList *list;
+
+     // Return early if there are no groups to clean up.
+     if (!group_list)
+           return;
+
+     // Iterate through the group list and clean up each group.
+     for (list = group_list; list != NULL; list = list->next) {
+           struct connman_group *group = list->data;
+
+           /*
+                 * Checking if group->path == null is added to prevent connman crash [NCVTDEFFECT-2085].
+                 * For further investigation, PLAT-16133 is created to find a better solution
+                 * other than checking null.
+                 */
+           if (group && group->path && strstr(group->path, "group") != NULL) {
+                 // Emit a "GroupRemoved" signal to notify clients.
+                 group_removed_signal(group);
+
+                 // Disconnect the P2P group and unregister the D-Bus interface.
+                 if (group->interface) {
+                       g_supplicant_interface_p2p_group_disconnect(group->interface, NULL, NULL);
+                       g_dbus_unregister_interface(connection, group->path, CONNMAN_GROUP_INTERFACE);
+                 }
+           }
+     }
+
+     // Free the group list and reset the global pointer.
+     list = group_list;
+     group_list = NULL;
+     g_list_free(list);
+
+     // Destroy the global hash table and reset the pointer.
+     g_hash_table_destroy(group_hash);
+     group_hash = NULL;
+}
\ No newline at end of file
diff --git a/src/ippool.c b/src/ippool.c
index f2e9b00..235d08c 100644
--- a/src/ippool.c
+++ b/src/ippool.c
@@ -42,6 +42,8 @@ struct address_info {
 };
 
 struct connman_ippool {
+     unsigned int refcount;
+
      struct address_info *info;
 
      char *gateway;
@@ -81,6 +83,44 @@ void __connman_ippool_free(struct connman_ippool *pool)
      g_free(pool);
 }
 
+struct connman_ippool *
+__connman_ippool_ref_debug(struct connman_ippool *pool,
+                       const char *file, int line, const char *caller)
+{
+     DBG("%p ref %d by %s:%d:%s()", pool, pool->refcount + 1,
+           file, line, caller);
+
+     __sync_fetch_and_add(&pool->refcount, 1);
+
+     return pool;
+}
+
+void __connman_ippool_unref_debug(struct connman_ippool *pool,
+                       const char *file, int line, const char *caller)
+{
+     if (!pool)
+           return;
+
+     DBG("%p ref %d by %s:%d:%s()", pool, pool->refcount - 1,
+           file, line, caller);
+
+     if (__sync_fetch_and_sub(&pool->refcount, 1) != 1)
+           return;
+
+     if (pool->info) {
+           allocated_blocks = g_slist_remove(allocated_blocks, pool->info);
+           g_free(pool->info);
+     }
+
+     g_free(pool->gateway);
+     g_free(pool->broadcast);
+     g_free(pool->start_ip);
+     g_free(pool->end_ip);
+     g_free(pool->subnet_mask);
+
+     g_free(pool);
+}
+
 static char *get_ip(uint32_t ip)
 {
      struct in_addr addr;
diff --git a/src/manager.c b/src/manager.c
index 892d3a4..b1992dd 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -30,6 +30,7 @@
 #include <connman/agent.h>
 
 #include "connman.h"
+#include "include/group.h"
 
 static bool connman_state_idle;
 static dbus_bool_t sessionmode;
@@ -521,6 +522,107 @@ error:
 
 }
 
+/**
+ * Handles a D-Bus method call to create a P2P group.
+ *
+ * @param conn      Pointer to the D-Bus connection.
+ * @param msg       Pointer to the incoming D-Bus message requesting group creation.
+ * @param data      Additional user data (unused in this function).
+ *
+ * @return NULL on success, or a D-Bus error message on failure.
+ *
+ * This function validates the input arguments from the D-Bus message, including the
+ * group identifier and passphrase. It ensures the identifier length and passphrase
+ * meet the required constraints. If valid, it invokes the P2P group creation logic
+ * using `__connman_technology_set_p2p_go`. On failure, it returns an appropriate
+ * D-Bus error message.
+ */
+static DBusMessage *create_group(DBusConnection *conn,
+                                                     DBusMessage *msg, void *data)
+{
+     DBusMessageIter iter;
+     const char *identifier, *passphrase;
+     int err;
+
+     DBG("");
+
+     // Validate the D-Bus message and initialize the iterator.
+     if (dbus_message_iter_init(msg, &iter) == FALSE)
+           return __connman_error_invalid_arguments(msg);
+
+     // Validate the group identifier argument.
+     if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+           return __connman_error_invalid_arguments(msg);
+
+     dbus_message_iter_get_basic(&iter, &identifier);
+
+     if (strlen(identifier) > (P2P_MAX_SSID - P2P_WILDCARD_SSID_LEN))
+           return __connman_error_invalid_arguments(msg);
+
+     dbus_message_iter_next(&iter);
+
+     // Validate the passphrase argument.
+     if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+           return __connman_error_invalid_arguments(msg);
+
+     dbus_message_iter_get_basic(&iter, &passphrase);
+
+     if ((strlen(passphrase) > 1 && strlen(passphrase) < 8) || strlen(passphrase) > 63)
+           return __connman_error_passphrase_required(msg);
+
+     // Attempt to create the P2P group.
+     err = __connman_technology_set_p2p_go(msg, identifier, passphrase);
+
+     if (err < 0)
+           return __connman_error_failed(msg, -err);
+
+     return NULL;
+}
+
+/**
+ * Appends all connman_group structures to a D-Bus message iterator.
+ *
+ * @param iter      Pointer to the D-Bus message iterator where group structures will be appended.
+ * @param user_data Additional user data (unused in this function).
+ *
+ * This function calls `__connman_group_list_struct` to append all group structures
+ * from the global group list to the provided D-Bus message iterator.
+ */
+static void append_group_structs(DBusMessageIter *iter, void *user_data)
+{
+     __connman_group_list_struct(iter);
+}
+
+/**
+ * Handles a D-Bus method call to retrieve all P2P groups.
+ *
+ * @param conn      Pointer to the D-Bus connection.
+ * @param msg       Pointer to the incoming D-Bus message requesting group information.
+ * @param data      Additional user data (unused in this function).
+ *
+ * @return A D-Bus reply message containing all P2P groups, or NULL if the reply could not be created.
+ *
+ * This function constructs a D-Bus reply message and appends all P2P group structures
+ * using the `append_group_structs` function. The group information is retrieved from
+ * the global group list.
+ */
+static DBusMessage *get_groups(DBusConnection *conn,
+                                               DBusMessage *msg, void *data)
+{
+     DBusMessage *reply;
+
+     // Create a reply message for the incoming D-Bus method call.
+     reply = dbus_message_new_method_return(msg);
+     if (!reply)
+           return NULL;
+
+     // Append all P2P group structures to the reply message.
+     __connman_dbus_append_objpath_dict_array(reply, append_group_structs, NULL);
+
+     return reply;
+}
+
+
 static const GDBusMethodTable manager_methods[] = {
      { GDBUS_METHOD("GetProperties",
                  NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
@@ -583,6 +685,13 @@ static const GDBusMethodTable manager_methods[] = {
      { GDBUS_METHOD("UnregisterPeerService",
                  GDBUS_ARGS({ "specification", "a{sv}" }), NULL,
                  unregister_peer_service) },
+     { GDBUS_ASYNC_METHOD("CreateGroup",
+                       GDBUS_ARGS({ "identifier", "s" },{ "passphrase", "s" }),
+                       GDBUS_ARGS({ "path", "o" }),
+                       create_group) },
+     { GDBUS_METHOD("GetGroups",
+                       NULL, GDBUS_ARGS({ "groups", "a(oa{sv})" }),
+                       get_groups) },
      { },
 };
 
@@ -603,6 +712,11 @@ static const GDBusSignalTable manager_signals[] = {
      { GDBUS_SIGNAL("TetheringClientsChanged",
                  GDBUS_ARGS({ "registered", "as" },
                              { "removed", "as" })) },
+     { GDBUS_SIGNAL("GroupAdded",
+                 GDBUS_ARGS({ "path", "o" },
+                             { "properties", "a{sv}" })) },
+     { GDBUS_SIGNAL("GroupRemoved",
+                 GDBUS_ARGS({ "path", "o"})) },
      { },
 };
 
diff --git a/src/p2pgo.c b/src/p2pgo.c
new file mode 100644
index 0000000..f58caa6
--- /dev/null
+++ b/src/p2pgo.c
@@ -0,0 +1,477 @@
+/*
+ *
+ *  Connection Manager
+ *
+ *  Copyright (C) 2007-2012  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2011 ProFUSION embedded systems
+ *  Copyright (C) 2013 LG Electronics, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <linux/sockios.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <linux/if_tun.h>
+#include <linux/if_bridge.h>
+
+#include "connman.h"
+
+#include <gdhcp/gdhcp.h>
+
+#include <gdbus.h>
+
+#ifndef DBUS_TYPE_UNIX_FD
+#define DBUS_TYPE_UNIX_FD -1
+#endif
+
+/**
+ * Default DNS server for the bridge network.
+ *
+ * This DNS server is used for name resolution in the private network
+ * created for P2P connections.
+ */
+#define BRIDGE_DNS "8.8.8.8"
+
+/**
+ * Default Maximum Transmission Unit (MTU) size.
+ *
+ * This value defines the maximum size of packets that can be transmitted
+ * over the network interface.
+ */
+#define DEFAULT_MTU 1500
+
+/**
+ * Primary DNS server for the private network.
+ *
+ * This is an alias for the bridge DNS server used in the private network.
+ */
+#define PRIVATE_NETWORK_PRIMARY_DNS BRIDGE_DNS
+
+/**
+ * Secondary DNS server for the private network.
+ *
+ * This DNS server is used as a fallback for name resolution in the private network.
+ */
+#define PRIVATE_NETWORK_SECONDARY_DNS "8.8.4.4"
+
+/**
+ * Default IP block for P2P connections.
+ *
+ * This IP block is used to assign IP addresses in the private network
+ * created for P2P connections. The block corresponds to 192.168.49.x.
+ */
+#define P2P_DEFAULT_BLOCK 0xc0a83100 // 192.168.49.x
+
+/**
+ * Pointer to the DHCP server used for tethering.
+ *
+ * This global variable represents the DHCP server instance responsible
+ * for managing IP address allocation in the tethering network.
+ */
+static GDHCPServer *tethering_dhcp_server = NULL;
+
+/**
+ * Pointer to the IP pool used for DHCP.
+ *
+ * This global variable represents the IP pool used by the DHCP server
+ * to allocate IP addresses to devices in the network.
+ */
+static struct connman_ippool *dhcp_ippool = NULL;
+
+/**
+ * Name of the bridge interface.
+ *
+ * This global variable holds the name of the bridge interface used
+ * for managing the tethering network.
+ */
+static char *bridge_name;
+
+/**
+ * Sets the name of the bridge interface for P2P Group Owner (GO).
+ *
+ * @param bridge Pointer to the string representing the bridge interface name.
+ *
+ * This function assigns the provided bridge name to the global `bridge_name` variable.
+ * The name is duplicated using `g_strdup` to ensure proper memory management.
+ */
+void __connman_p2p_go_set_bridge(char *bridge)
+{
+     bridge_name = g_strdup(bridge);
+}
+
+/**
+ * Retrieves the name of the bridge interface for P2P Group Owner (GO).
+ *
+ * @return Pointer to the string representing the bridge interface name.
+ *
+ * This function returns the global `bridge_name` variable, which holds
+ * the name of the bridge interface used for managing the tethering network.
+ */
+const char *__connman_p2p_go_get_bridge(void)
+{
+     return bridge_name;
+}
+
+/**
+ * Logs debug information for the DHCP server.
+ *
+ * @param str  Pointer to the string containing the debug message.
+ * @param data Pointer to additional data (typically the context or identifier).
+ *
+ * This function logs the provided debug message along with the associated data
+ * using the `connman_info` logging mechanism.
+ */
+static void dhcp_server_debug(const char *str, void *data)
+{
+     connman_info("%s: %s\n", (const char *) data, str);
+}
+
+/**
+ * Logs error messages for the DHCP server.
+ *
+ * @param error Enum value representing the DHCP server error.
+ *
+ * This function maps the provided `GDHCPServerError` enum value to a corresponding
+ * error message and logs it using the `connman_error` logging mechanism.
+ */
+static void dhcp_server_error(GDHCPServerError error)
+{
+     switch (error) {
+     case G_DHCP_SERVER_ERROR_NONE:
+           connman_error("OK");
+           break;
+     case G_DHCP_SERVER_ERROR_INTERFACE_UNAVAILABLE:
+           connman_error("Interface unavailable");
+           break;
+     case G_DHCP_SERVER_ERROR_INTERFACE_IN_USE:
+           connman_error("Interface in use");
+           break;
+     case G_DHCP_SERVER_ERROR_INTERFACE_DOWN:
+           connman_error("Interface down");
+           break;
+     case G_DHCP_SERVER_ERROR_NOMEM:
+           connman_error("No memory");
+           break;
+     case G_DHCP_SERVER_ERROR_INVALID_INDEX:
+           connman_error("Invalid index");
+           break;
+     case G_DHCP_SERVER_ERROR_INVALID_OPTION:
+           connman_error("Invalid option");
+           break;
+     case G_DHCP_SERVER_ERROR_IP_ADDRESS_INVALID:
+           connman_error("Invalid address");
+           break;
+     }
+}
+
+/**
+ * Starts a DHCP server for the specified bridge interface.
+ *
+ * @param bridge     Name of the bridge interface.
+ * @param router     IP address of the router.
+ * @param subnet     Subnet mask for the network.
+ * @param start_ip   Starting IP address for the DHCP range.
+ * @param end_ip     Ending IP address for the DHCP range.
+ * @param lease_time Lease time for DHCP clients.
+ * @param dns        DNS server address.
+ *
+ * @return Pointer to the created `GDHCPServer` instance, or NULL on failure.
+ *
+ * This function initializes and starts a DHCP server for the specified bridge interface.
+ * It configures the server with the provided network settings, including IP range, subnet,
+ * router, DNS server, and lease time. Debugging and error handling are also set up.
+ */
+static GDHCPServer *dhcp_server_start(const char *bridge,
+                                                           const char *router, const char *subnet,
+                                                           const char *start_ip, const char *end_ip,
+                                                           unsigned int lease_time, const char *dns)
+{
+     GDHCPServerError error;
+     GDHCPServer *dhcp_server;
+     int index;
+
+     DBG("");
+
+     // Get the interface index for the bridge.
+     index = connman_inet_ifindex(bridge);
+     if (index < 0)
+           return NULL;
+
+     // Create a new DHCP server instance.
+     dhcp_server = g_dhcp_server_new(G_DHCP_IPV4, index, &error);
+     if (!dhcp_server) {
+           dhcp_server_error(error);
+           return NULL;
+     }
+
+     // Set debugging information for the DHCP server.
+     g_dhcp_server_set_debug(dhcp_server, dhcp_server_debug, "DHCP server");
+
+     // Configure the DHCP server with the provided settings.
+     g_dhcp_server_set_lease_time(dhcp_server, lease_time);
+     g_dhcp_server_set_option(dhcp_server, G_DHCP_SUBNET, subnet);
+     g_dhcp_server_set_option(dhcp_server, G_DHCP_ROUTER, router);
+     g_dhcp_server_set_option(dhcp_server, G_DHCP_DNS_SERVER, dns);
+     g_dhcp_server_set_ip_range(dhcp_server, start_ip, end_ip);
+
+     // Start the DHCP server.
+     g_dhcp_server_start(dhcp_server);
+
+     return dhcp_server;
+}
+
+/**
+ * Stops and releases the DHCP server instance.
+ *
+ * @param server Pointer to the `GDHCPServer` instance to be stopped.
+ *
+ * This function checks if the provided DHCP server instance is valid.
+ * If valid, it releases the reference to the server using `g_dhcp_server_unref`.
+ */
+static void dhcp_server_stop(GDHCPServer *server)
+{
+     if (!server)
+           return;
+
+     // Release the reference to the DHCP server.
+     g_dhcp_server_unref(server);
+}
+
+/**
+ * Enables the P2P Group Owner (GO) functionality.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ *
+ * This function sets up the P2P Group Owner (GO) by creating an IP pool,
+ * enabling the bridge interface, configuring DNS proxy, and starting a DHCP server.
+ * It handles errors at each step and ensures proper cleanup if any operation fails.
+ */
+int __connman_p2p_go_set_enabled(void)
+{
+     int index;
+     int err;
+     const char *gateway;
+     const char *broadcast;
+     const char *subnet_mask;
+     const char *start_ip;
+     const char *end_ip;
+     const char *dns;
+
+     // Get the interface index for the bridge.
+     index = connman_inet_ifindex(bridge_name);
+     connman_info("p2pgo.c : index = %d", index);
+
+     // Create an IP pool for the bridge interface.
+     dhcp_ippool = __connman_ippool_create(index, 2, 252, NULL, NULL);
+     if (!dhcp_ippool) {
+           connman_error("Fail to create IP pool");
+           __connman_bridge_remove(bridge_name);
+     }
+
+     // Retrieve IP configuration details from the IP pool.
+     gateway = __connman_ippool_get_gateway(dhcp_ippool);
+     broadcast = __connman_ippool_get_broadcast(dhcp_ippool);
+     subnet_mask = __connman_ippool_get_subnet_mask(dhcp_ippool);
+     start_ip = __connman_ippool_get_start_ip(dhcp_ippool);
+     end_ip = __connman_ippool_get_end_ip(dhcp_ippool);
+
+     // Enable the bridge interface with the retrieved configuration.
+     err = __connman_bridge_enable(bridge_name, gateway,
+                                                     connman_ipaddress_calc_netmask_len(subnet_mask), broadcast);
+     if (err < 0 && err != -EALREADY) {
+           __connman_ippool_unref(dhcp_ippool);
+           __connman_bridge_remove(bridge_name);
+     }
+
+     // Set up DNS proxy for the bridge interface.
+     dns = gateway;
+     if (__connman_dnsproxy_add_listener(index) < 0) {
+           connman_error("Can't add listener %s to DNS proxy", bridge_name);
+           dns = BRIDGE_DNS;
+     }
+
+     // Start the DHCP server for the bridge interface.
+     tethering_dhcp_server = dhcp_server_start(bridge_name,
+                                                                       gateway, subnet_mask,
+                                                                       start_ip, end_ip,
+                                                                       24 * 3600, dns);
+     if (tethering_dhcp_server == NULL) {
+           __connman_bridge_disable(bridge_name);
+           __connman_ippool_unref(dhcp_ippool);
+           __connman_bridge_remove(bridge_name);
+     }
+
+     DBG("p2p go dhcp started");
+     return 0;
+}
+
+/**
+ * Disables the P2P Group Owner (GO) functionality.
+ *
+ * This function stops the DHCP server, removes DNS proxy listeners, disables NAT,
+ * and cleans up the bridge interface and IP pool associated with the P2P Group Owner.
+ * It ensures proper cleanup of resources to disable the P2P GO functionality.
+ */
+void __connman_p2p_go_set_disabled(void)
+{
+     int index;
+
+     // Get the interface index for the bridge.
+     index = connman_inet_ifindex(bridge_name);
+     if (index < 0)
+           return;
+
+     // Remove DNS proxy listener for the bridge interface.
+     __connman_dnsproxy_remove_listener(index);
+
+     // Disable NAT for the bridge interface.
+     __connman_nat_disable(bridge_name);
+
+     // Stop the DHCP server and release its resources.
+     dhcp_server_stop(tethering_dhcp_server);
+     tethering_dhcp_server = NULL;
+
+     // Disable the bridge interface.
+     __connman_bridge_disable(bridge_name);
+
+     // Release the IP pool associated with the bridge.
+     __connman_ippool_unref(dhcp_ippool);
+
+     // Remove the bridge interface.
+     __connman_bridge_remove(bridge_name);
+
+     DBG("p2p go stopped");
+}
+
+/**
+ * Enables NAT (Network Address Translation) for P2P Group Owner (GO) tethering.
+ *
+ * This function retrieves the subnet mask and starting IP address from the IP pool,
+ * calculates the prefix length, and enables NAT for the bridge interface to allow
+ * tethering functionality.
+ */
+void __connman_p2p_go_tethering_set_enabled(void)
+{
+     unsigned char prefixlen;
+     const char *subnet_mask;
+     const char *start_ip;
+
+     // Retrieve the subnet mask and starting IP address from the IP pool.
+     subnet_mask = __connman_ippool_get_subnet_mask(dhcp_ippool);
+     start_ip = __connman_ippool_get_start_ip(dhcp_ippool);
+
+     // Calculate the prefix length from the subnet mask.
+     prefixlen = connman_ipaddress_calc_netmask_len(subnet_mask);
+
+     // Enable NAT for the bridge interface using the starting IP and prefix length.
+     __connman_nat_enable(bridge_name, start_ip, prefixlen);
+}
+
+/**
+ * Disables NAT (Network Address Translation) for P2P Group Owner (GO) tethering.
+ *
+ * This function disables NAT for the bridge interface associated with the P2P Group Owner,
+ * ensuring that tethering functionality is properly stopped.
+ */
+void __connman_p2p_go_tethering_set_disabled(void)
+{
+     __connman_nat_disable(bridge_name);
+}
+
+/**
+ * Retrieves the local IP address of the P2P Group Owner (GO).
+ *
+ * @return Pointer to the string representing the local IP address, or NULL if unavailable.
+ *
+ * This function checks if the DHCP IP pool is initialized and retrieves the gateway
+ * IP address from the pool, which represents the local IP address of the P2P Group Owner.
+ */
+const char* __connman_p2p_group_get_local_ip(void)
+{
+     if (dhcp_ippool) {
+           const char *gateway = __connman_ippool_get_gateway(dhcp_ippool);
+           return gateway;
+     }
+
+     return NULL;
+}
+
+/**
+ * Appends the local gateway address to a D-Bus message iterator.
+ *
+ * @param iter Pointer to the D-Bus message iterator where the gateway address will be appended.
+ *
+ * This function retrieves the local IP address of the P2P Group Owner (GO) using
+ * `__connman_p2p_group_get_local_ip` and appends it to the D-Bus message iterator
+ * as the "LocalAddress" property, if available.
+ */
+void __connman_dhcpserver_append_gateway(DBusMessageIter* iter)
+{
+     const char* local_address = __connman_p2p_group_get_local_ip();
+     if (local_address != NULL)
+           connman_dbus_dict_append_basic(iter, "LocalAddress", DBUS_TYPE_STRING, &local_address);
+}
+
+/**
+ * Initializes the P2P Group Owner (GO) functionality.
+ *
+ * @return 0 on success.
+ *
+ * This function serves as the initialization routine for the P2P Group Owner (GO).
+ * Currently, it only logs a debug message and returns success.
+ */
+int __connman_p2p_go_init(void)
+{
+     DBG("Initializing P2P Group Owner (GO)");
+     return 0;
+}
+
+/**
+ * Sets the DHCP IP pool for P2P Group Owner (GO).
+ *
+ * @param ippool Pointer to the `connman_ippool` structure representing the DHCP IP pool.
+ *
+ * This function assigns the provided IP pool to the global `dhcp_ippool` variable,
+ * which is used for managing IP address allocation in the P2P Group Owner network.
+ */
+void __connman_p2p_set_dhcp_pool(struct connman_ippool *ippool)
+{
+     dhcp_ippool = ippool;
+}
+
+/**
+ * Cleans up the P2P Group Owner (GO) functionality.
+ *
+ * This function serves as the cleanup routine for the P2P Group Owner (GO).
+ * Currently, it only logs a debug message.
+ */
+void __connman_p2p_go_cleanup(void)
+{
+     DBG("Cleaning up P2P Group Owner (GO)");
+}
\ No newline at end of file
diff --git a/src/peer.c b/src/peer.c
index 2b2c636..03c96c0 100644
--- a/src/peer.c
+++ b/src/peer.c
@@ -185,6 +185,8 @@ error:
      return err;
 }
 
+
+
 static void reply_pending(struct connman_peer *peer, int error)
 {
      if (!peer->pending)
@@ -1200,6 +1202,22 @@ static void disconnect_peer_hash_table(gpointer key,
      peer_disconnect(peer);
 }
 
+struct connman_peer *connman_peer_get_by_path(const char *path)
+{
+     struct connman_peer *peer;
+
+     peer = g_hash_table_lookup(peers_table, path);
+
+     return peer;
+}
+
+void __connman_peer_get_properties_struct(DBusMessageIter *iter, gpointer user_data)
+{
+     struct connman_peer *peer = user_data;
+
+     append_properties(iter, peer);
+}
+
 void __connman_peer_disconnect_all(void)
 {
      g_hash_table_foreach(peers_table, disconnect_peer_hash_table, NULL);
diff --git a/src/technology.c b/src/technology.c
index fc90663..10041a1 100644
--- a/src/technology.c
+++ b/src/technology.c
@@ -1343,6 +1343,63 @@ void __connman_technology_notify_regdom_by_device(struct connman_device *device,
      connman_technology_regdom_notify(technology, alpha2);
 }
 
+/**
+ * Sets up a P2P group owner (GO) for the P2P technology.
+ *
+ * @param msg        Pointer to the D-Bus message requesting the operation.
+ * @param ident      Identifier for the P2P group.
+ * @param passphrase Passphrase for the P2P group.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ *
+ * This function finds the P2P technology and iterates through its drivers to
+ * set up a P2P group owner (GO). If the identifier or passphrase is invalid,
+ * they are set to NULL. The function invokes the `set_p2p_go` method of each
+ * driver and handles errors appropriately.
+ */
+int __connman_technology_set_p2p_go(DBusMessage *msg, const char *ident, const char *passphrase)
+{
+     struct connman_technology *technology;
+     GSList *tech_drivers;
+     int result = 0;
+     int err;
+
+     // Find the P2P technology.
+     technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
+
+     DBG("technology %p", technology);
+
+     if (!technology)
+           return -EINVAL;
+
+     // Validate the identifier and passphrase.
+     if (strlen(ident) < 1 || strlen(passphrase) < 1) {
+           ident = NULL;
+           passphrase = NULL;
+     }
+
+     // Iterate through the technology's drivers to set up the P2P GO.
+     for (tech_drivers = technology->driver_list; tech_drivers;
+                 tech_drivers = g_slist_next(tech_drivers)) {
+           struct connman_technology_driver *driver = tech_drivers->data;
+
+           if (!driver || !driver->set_p2p_go)
+                 continue;
+
+           err = driver->set_p2p_go(msg, technology, ident, passphrase);
+
+           if (result == -EINPROGRESS)
+                 continue;
+
+           if (err == -EINPROGRESS || err == 0) {
+                 result = err;
+                 continue;
+           }
+     }
+
+     return 0;
+}
+
 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
 {
      struct connman_technology *technology = data;
@@ -2146,6 +2203,26 @@ void __connman_technology_sta_count_changed(enum connman_service_type type, int
         connman_dbus_property_changed_basic(technology->path,
                                         CONNMAN_TECHNOLOGY_INTERFACE, "StaCount",
                                         DBUS_TYPE_INT32, &stacount);
+}
 
+void connman_technology_set_p2p_listen(struct connman_technology *technology, bool enabled)
+{
+     dbus_bool_t listen_enabled;
+
+     if (enabled == technology->p2p_listen)
+           return;
 
+     technology->p2p_listen = enabled;
+     listen_enabled = enabled;
+
+     connman_dbus_property_changed_basic(technology->path,
+                 CONNMAN_TECHNOLOGY_INTERFACE,
+                 "P2PListen",
+                 DBUS_TYPE_BOOLEAN,
+                 &listen_enabled);
+}
+
+bool connman_technology_get_p2p_listen(struct connman_technology *technology)
+{
+     return technology->p2p_listen;
 }
\ No newline at end of file
diff --git a/src/util.c b/src/util.c
index 03b14cd..991677c 100644
--- a/src/util.c
+++ b/src/util.c
@@ -30,6 +30,7 @@
 #include <stdint.h>
 #include <unistd.h>
 #include <errno.h>
+#include <stdio.h>
 #include <stdlib.h>
 
 #include "connman.h"
@@ -59,6 +60,17 @@ int __connman_util_get_random(uint64_t *val)
      return r;
 }
 
+void __connman_util_byte_to_string(unsigned char *src, char *dest, int len)
+{
+     int i=0;
+
+     for(i=0; i<len; i++) {
+           snprintf(&dest[i*2], 3, "%02x", src[i]);
+     }
+
+     dest[len*2] = '\0';
+}
+
 int __connman_util_init(void)
 {
      int r = 0;
@@ -102,3 +114,30 @@ unsigned int __connman_util_random_delay_ms(unsigned int secs)
        __connman_util_get_random(&rand);
        return rand % (secs * 1000);
 }
+
+char *__connman_util_insert_colon_to_mac_addr(const char *mac_addr)
+{
+     char *result = g_try_malloc(18);
+     int i;
+
+     if (!mac_addr || strlen(mac_addr) < 12) {
+           g_free(result);
+           return NULL;
+     }
+
+     for (i=0; i<6; i++) {
+           result[i*3] = mac_addr[i*2];
+           result[i*3+1] = mac_addr[i*2+1];
+     }
+
+     result[2] = ':';
+     result[5] = ':';
+     result[8] = ':';
+     result[11] = ':';
+     result[14] = ':';
+     result[17] = '\0';
+
+     DBG("before: %s, after: %s", mac_addr, result);
+
+     return result;
+}