diff --git a/src/Makefile b/src/Makefile
index 623ad30c4257c78b064a48fd8587f47a25019482..a65caf028ce7c41da8ff1533bbdc64cce84c64d0 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -25,6 +25,7 @@ CNTLR_OBJS = \
 
 LIBS = -lubus -lubox -ljson-c -lblobmsg_json -luci -pthread
 LIBS += -rdynamic -ldl
+LIBS += -lmaputils
 
 plugin_subdirs ?= $(wildcard plugins/*)
 plugin_sofile = $(wildcard $(d)/*.so)
diff --git a/src/core/cntlr.c b/src/core/cntlr.c
index 69940929b706cf03197076a10f50b147d191c501..3d698687d1d02cc07fedea6e0505422cefcc1cf5 100644
--- a/src/core/cntlr.c
+++ b/src/core/cntlr.c
@@ -902,7 +902,7 @@ static int update_node(struct controller *c, struct node *n)
 					strlen(ipstr) ? "/" : "", uobj[j]);
 		ret = ubus_lookup_id(c->ubus_ctx, uobjpath, &n->uobj[j]);
 		if (ret != UBUS_STATUS_OK) {
-			n->uobj[j] = WIFI_OBJECT_INVALID;
+			n->uobj[j] = OBJECT_INVALID;
 			cntlr_dbg("object '%s' not present!\n", uobjpath);
 			continue;
 		}
@@ -950,7 +950,7 @@ static struct node *alloc_node_init(struct controller *c, char *ipstr)
 					strlen(ipstr) ? "/" : "", uobj[j]);
 		ret = ubus_lookup_id(c->ubus_ctx, uobjpath, &n->uobj[j]);
 		if (ret != UBUS_STATUS_OK) {
-			n->uobj[j] = WIFI_OBJECT_INVALID;
+			n->uobj[j] = OBJECT_INVALID;
 			cntlr_dbg("object '%s' not present!\n", uobjpath);
 			continue;
 		}
@@ -1461,7 +1461,7 @@ static void build_topology_tree(struct ubus_request *req, int utype, struct blob
 			snprintf(uobjpath, 128, "%s/%s", ipstr, uobj[j]);
 			ubus_lookup_id(c->ubus_ctx, uobjpath, &n->uobj[j]);
 			if (n->uobj[j] == 0) {
-				n->uobj[j] = WIFI_OBJECT_INVALID;
+				n->uobj[j] = OBJECT_INVALID;
 				err("object '%s' not present!\n", uobjpath);
 				continue;
 			}
@@ -1659,10 +1659,10 @@ static void perform_tasks_topology_change(struct controller *c)
 	forall_node_get_fhinfo(c);
 }
 
-static void cntlr_event_handler(struct ubus_context *ctx,
-				struct ubus_event_handler *ev,
-				const char *type,
-				struct blob_attr *msg)
+static void cntlr_ubusx_event_handler(struct ubus_context *ctx,
+				      struct ubus_event_handler *ev,
+				      const char *type,
+				      struct blob_attr *msg)
 {
 	struct controller *c = container_of(ev, struct controller, ubusx_ev);
 	const struct blobmsg_policy policy = { "path", BLOBMSG_TYPE_STRING };
@@ -1723,46 +1723,28 @@ static void cntlr_event_handler(struct ubus_context *ctx,
 	}
 }
 
-static int register_bus_events(struct controller *c)
-{
-#if 0
-	if (c->topology != UBUS_OBJECT_INVALID) {
-		cntlr_dbg("Setting up event handler for 'topology' events\n");
-		ubus_register_event_handler(c->ubus_ctx, &c->ubus_ev, "topology.*");
-	}
-#endif
-	cntlr_dbg("Setting up bus event handlers...\n");
-	ubus_register_event_handler(c->ubus_ctx, &c->ubusx_ev, "ubus.object.add");
-	ubus_register_event_handler(c->ubus_ctx, &c->ubusx_ev, "ubus.object.remove");
-	ubus_register_event_handler(c->ubus_ctx, &c->ieee1905_evh, "ieee1905.*");
-
-	return 0;
-}
 
-static void ieee1905_cmdu_event_handler(void *e, struct blob_attr *msg)
+static void cntlr_ieee1905_cmdu_event_handler(void *cntlr, struct blob_attr *msg)
 {
-#define MAX_TLV_BUF	1500		/* FIXME */
-
-	struct controller *c = (struct controller *)e;
-	uint8_t tlvlist[MAX_TLV_BUF] = { 0 };
-	char in_ifname[16] = {0};
-	struct blob_attr *attr;
-	char src[18] = { 0 };
-	uint8_t srcmac[6];
-	int pos = 0;
-	uint16_t type;
-	int mid = 0;
-	struct blob_attr *tb[5];
 	static const struct blobmsg_policy cmdu_attrs[5] = {
-		[0] = { .name = "cmdu_type", .type = BLOBMSG_TYPE_INT32 },
+		[0] = { .name = "type", .type = BLOBMSG_TYPE_INT32 },
 		[1] = { .name = "mid", .type = BLOBMSG_TYPE_INT32 },
-		[2] = { .name = "recv_intf", .type = BLOBMSG_TYPE_STRING },
-		[3] = { .name = "origin", .type = BLOBMSG_TYPE_STRING },
-		[4] = { .name = "streams", .type = BLOBMSG_TYPE_ARRAY },
+		[2] = { .name = "ingress", .type = BLOBMSG_TYPE_STRING },
+		[3] = { .name = "source", .type = BLOBMSG_TYPE_STRING },
+		[4] = { .name = "tlvs", .type = BLOBMSG_TYPE_STRING },
 	};
+	struct controller *c = (struct controller *)cntlr;
+	char in_ifname[16] = {0};
+	struct blob_attr *tb[5];
+	char src[18] = { 0 };
+	uint8_t *tlv = NULL;
+	char *tlvstr = NULL;
+	uint16_t type;
+	uint8_t srcmac[6];
+	uint16_t mid = 0;
+	int len = 0;
 
-
-	trace("%s: ------------>\n", __func__);
+	dbg("%s: --->\n", __func__);
 
 	blobmsg_parse(cmdu_attrs, 5, tb, blob_data(msg), blob_len(msg));
 
@@ -1776,7 +1758,7 @@ static void ieee1905_cmdu_event_handler(void *e, struct blob_attr *msg)
 	}
 
 	if (tb[1])
-		mid = blobmsg_get_u32(tb[1]);
+		mid = (uint16_t)blobmsg_get_u32(tb[1]);
 
 
 	if (tb[2]) {
@@ -1789,54 +1771,48 @@ static void ieee1905_cmdu_event_handler(void *e, struct blob_attr *msg)
 
 	}
 
-
 	if (tb[4]) {
-		int rem;
-		int len;
-
-		blobmsg_for_each_attr(attr, tb[4], rem) {
-			char tlvstr[513] = { 0 };
-			uint8_t tlv[256] = { 0 };
-
-			if (blobmsg_type(attr) != BLOBMSG_TYPE_STRING)
-				continue;
-
-			len = blobmsg_data_len(attr);
-			memcpy(tlvstr, blobmsg_data(attr), len);
-
-			len = (len - 1) / 2;
-			if (pos + len > MAX_TLV_BUF)
-				break;
+		len = blobmsg_data_len(tb[4]);
+		tlvstr = calloc(len + 1, sizeof(char));
+		if (!tlvstr)
+			return;
 
-			strtob(tlvstr, len, tlv);
-			memcpy(&tlvlist[pos], tlv, len);
-			pos += len;
+		strncpy(tlvstr, blobmsg_data(tb[4]), len);
+		len = (len - 1) / 2;
+		tlv = calloc(len, sizeof(uint8_t));
+		if (!tlv) {
+			free(tlvstr);
+			return;
 		}
+
+		strtob(tlvstr, len, tlv);
+		free(tlvstr);
 	}
 
-	cntlr_handle_map_event(c, type, mid, tlvlist, pos);
+	cntlr_handle_map_event(c, type, mid, in_ifname, srcmac, tlv, len);
 
+	if (tlv)
+		free(tlv);
 }
 
-static void ubus_1905_event_handler(struct ubus_context *ctx,
-					struct ubus_event_handler *ev,
-					const char *type,
-					struct blob_attr *msg)
+static void cntlr_ieee1905_event_handler(struct ubus_context *ctx,
+					 struct ubus_event_handler *ev,
+					 const char *type,
+					 struct blob_attr *msg)
 {
-	int i;
-	char *str;
 	struct controller *c = container_of(ev, struct controller, ieee1905_evh);
-	struct wifi_ev_handler {
+	struct ev_handler {
 		const char *ev_type;
 		void (*handler)(void *ctx, struct blob_attr *ev_data);
-	} evs[] = {	{"ieee1905.data",     ieee1905_cmdu_event_handler} };
+	} evs[] = { {"ieee1905.cmdu", cntlr_ieee1905_cmdu_event_handler} };
+	char *str;
+	int i;
 
 	str = blobmsg_format_json(msg, true);
 	if (!str)
 		return;
 
-	info("[ &agent = %p ] Received [event = %s]  [val = %s]\n",
-				c, type, str);
+	dbg("[ &cntlr = %p ] Received [event = %s][val = %s]\n", c, type, str);
 
 	for (i = 0; i < sizeof(evs)/sizeof(evs[0]); i++) {
 		if (!strcmp(type, evs[i].ev_type)) {
@@ -1848,6 +1824,26 @@ static void ubus_1905_event_handler(struct ubus_context *ctx,
 	free(str);
 }
 
+static int cntlr_register_events(struct controller *c)
+{
+#if 0
+	if (c->topology != OBJECT_INVALID) {
+		cntlr_dbg("Setting up event handler for 'topology' events\n");
+		ubus_register_event_handler(c->ubus_ctx, &c->ubus_ev, "topology.*");
+	}
+#endif
+	cntlr_dbg("Setting up bus event handlers...\n");
+
+	c->ubusx_ev.cb = cntlr_ubusx_event_handler;
+	c->ieee1905_evh.cb = cntlr_ieee1905_event_handler;
+
+	ubus_register_event_handler(c->ubus_ctx, &c->ubusx_ev, "ubus.object.add");
+	ubus_register_event_handler(c->ubus_ctx, &c->ubusx_ev, "ubus.object.remove");
+	ubus_register_event_handler(c->ubus_ctx, &c->ieee1905_evh, "ieee1905.*");
+
+	return 0;
+}
+
 /* This function will also be called from topology change event */
 static int get_topology(struct controller *c)
 {
@@ -1900,7 +1896,7 @@ static uint32_t ubus_get_topology_object(struct ubus_context *ctx)
 	status = ubus_lookup_id(ctx, "topology", &id);
 	if (status != UBUS_STATUS_OK) {
 		warn("object 'topology' not present!\n");
-		return WIFI_OBJECT_INVALID;
+		return OBJECT_INVALID;
 	}
 
 	return id;
@@ -1953,9 +1949,9 @@ int start_controller(void)
 #endif
 	/* ev = &c->ubus_ev; */
 	/* ev->cb = cntlr_event_handler_local; */
-	c->ubusx_ev.cb = cntlr_event_handler;
-	c->ieee1905_evh.cb = ubus_1905_event_handler;
-	c->topology = WIFI_OBJECT_INVALID;
+	//c->ubusx_ev.cb = cntlr_ubusx_event_handler;
+	//c->ieee1905_evh.cb = cntlr_ieee1905_event_handler;
+	c->topology = OBJECT_INVALID;
 	INIT_LIST_HEAD(&c->nodelist);
 	INIT_LIST_HEAD(&c->watchlist);
 	as_init_table(&c->as_table);
@@ -1963,34 +1959,40 @@ int start_controller(void)
 
 	c->topology = ubus_get_topology_object(c->ubus_ctx);
 	info("topology object: %d\n", c->topology);
-	if (c->topology != WIFI_OBJECT_INVALID) {
+	if (c->topology != OBJECT_INVALID) {
 		get_topology(c);
 	} else {
 		warn("topologyd may not be running!\n");
+
+#ifdef CONFIG_USE_UBUSX
 		/* S-tree of the topology is not available. However, from the
 		 * available ubus(x) router/wifi objects, we should be able to
 		 * build an unordered list of the nodes in the network.
 		 */
 		enumerate_topology_indirect(c);
+#else
+		goto out_exit;
+#endif
 	}
+
 	perform_tasks_topology_init(c);
-	register_bus_events(c);
+	cntlr_register_events(c);
 	c->heartbeat.cb = cntlr_periodic_run;
 	c->radar_timer.cb = cntlr_radar_exit;
-	uloop_timeout_set(&c->heartbeat, 2 * 1000);
+	uloop_timeout_set(&c->heartbeat, 1 * 1000);
 
-	cntlr_publish_object(c);
+	cntlr_publish_object(c, "map.controller");
 
 	cntlr_register_module(c);
 
 	uloop_run();
 
-/* out_and_exit: */
+out_exit:
 	/* ubus_unregister_event_handler(ctx, ev); */
 	/* cntlr_remove_object(ctx); */
 	ubus_free(ctx);
 	uloop_done();
-	/* free(c); */	/* TODO */
+	free(c);
 
 	return 0;
 }
diff --git a/src/core/cntlr.h b/src/core/cntlr.h
index c4b2015a242a1dd6124b7439cce85a42e39efc22..d8f57f3bd2ecc003fa383b28db1167cc2f1464c8 100644
--- a/src/core/cntlr.h
+++ b/src/core/cntlr.h
@@ -16,8 +16,8 @@
 
 extern const char *ubus_socket;
 
-typedef uint32_t ubus_object_t;
-#define WIFI_OBJECT_INVALID	((uint32_t)-1)
+typedef uint32_t object_t;
+#define OBJECT_INVALID	((uint32_t)-1)
 
 /* This struct maps to fronthaul AP-BSS interface
  * of neighboring nodes.
@@ -63,7 +63,7 @@ enum uplink_type {
 };
 
 struct uobj_struct {
-	ubus_object_t id;
+	object_t id;
 	int (*req)(int argc, char **argv);
 	void (*resp)(struct ubus_request *r, int t, struct blob_attr *m);
 };
@@ -93,7 +93,7 @@ struct node {
 	bool scan_supported;               /** whether scanning supported */
 	struct controller *cntlr;
 #define MAX_UOBJECTS	8
-	ubus_object_t uobj[MAX_UOBJECTS];
+	object_t uobj[MAX_UOBJECTS];
 	/* struct uobj_struct uobj[MAX_UOBJECTS]; */
 	struct uloop_timeout refresh_timer;
 	struct ubus_event_handler evh;
@@ -112,12 +112,13 @@ struct node {
 
 struct controller {
 	void *comm;
+	struct ubus_object obj;
 	struct ubus_context *ubus_ctx;
 	/* struct ubus_event_handler ubus_ev; */  /** for local events */
 	struct ubus_event_handler ubusx_ev; /** for events from remote objs */
 	struct ubus_event_handler ieee1905_evh;
 	struct uloop_timeout heartbeat;
-	ubus_object_t topology;
+	object_t topology;
 	int num_nodes;
 	struct list_head nodelist;
 	struct list_head watchlist;
diff --git a/src/core/cntlr_map.c b/src/core/cntlr_map.c
index f90bb5a1adec29f6a51f91d45726cd1b83c4afad..cf3b410dbbe14a76dfb630774e7af266f0dde852 100644
--- a/src/core/cntlr_map.c
+++ b/src/core/cntlr_map.c
@@ -38,6 +38,8 @@
 #include "worker.h"
 #include "cntlr.h"
 
+#include <map1905/map2.h>
+#include <map1905/maputils.h>
 
 #define for_each_tlv(e, _buf, _len)					  \
 for ((e) = (struct tlv *)(_buf);					  \
@@ -51,134 +53,133 @@ struct tlv {
 } __attribute__ ((packed));
 
 
-typedef int (*map_cmdu_handler_t)(void *cntlr, uint16_t mid, uint8_t *tlvs,
-								int len);
+typedef int (*map_cmdu_handler_t)(void *cntlr, struct cmdu_cstruct *cmdu);
 
 
-int handle_topology_notification(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_topology_notification(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 	return 0;
 }
 
-int handle_topology_response(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_topology_response(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 	return 0;
 }
 
-int handle_ap_autoconfig_search(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_ap_autoconfig_search(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 	return 0;
 }
 
-int handle_ap_autoconfig_response(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_ap_autoconfig_response(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 	return 0;
 }
 
-int handle_ap_autoconfig_wsc(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_ap_autoconfig_wsc(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 	return 0;
 }
 
 
-int handle_1905_ack(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_1905_ack(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 
 	return 0;
 }
 
-int handle_ap_caps_report(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_ap_caps_report(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 
 	return 0;
 }
 
 
-int handle_channel_pref_report(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_channel_pref_report(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 
 	return 0;
 }
 
-int handle_channel_sel_response(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_channel_sel_response(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 
 	return 0;
 }
 
-int handle_oper_channel_report(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_oper_channel_report(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 
 	return 0;
 }
 
-int handle_sta_caps_report(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_sta_caps_report(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 	return 0;
 }
 
-int handle_ap_metrics_response(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_ap_metrics_response(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 	return 0;
 }
 
-int handle_sta_link_metrics_response(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_sta_link_metrics_response(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 	return 0;
 }
 
-int handle_unassoc_sta_link_metrics_response(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_unassoc_sta_link_metrics_response(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 	return 0;
 }
 
-int handle_beacon_metrics_response(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_beacon_metrics_response(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 	return 0;
 }
 
-int handle_sta_steer_btm_report(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_sta_steer_btm_report(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 	return 0;
 }
 
-int handle_sta_steer_complete(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_sta_steer_complete(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 	return 0;
 }
 
-int handle_backhaul_sta_steer_response(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_backhaul_sta_steer_response(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 	return 0;
 }
 
-int handle_channel_scan_report(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_channel_scan_report(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 	return 0;
 }
 
-int handle_sta_disassoc_stats(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_sta_disassoc_stats(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 	return 0;
 }
 
-int handle_assoc_status_notification(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_assoc_status_notification(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 	return 0;
 }
 
-int handle_tunneled_message(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_tunneled_message(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 	return 0;
 }
 
-int handle_backhaul_sta_caps_report(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_backhaul_sta_caps_report(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 	return 0;
 }
 
 
-int handle_failed_connection_msg(void *cntlr, uint16_t mid, uint8_t *tlvs, int len)
+int handle_failed_connection_msg(void *cntlr, struct cmdu_cstruct *cmdu)
 {
 	return 0;
 }
@@ -225,7 +226,7 @@ static const map_cmdu_handler_t cntlr_mapftable[] = {
 
 bool is_cmdu_for_us(void *module, uint16_t type)
 {
-	struct controller *c = (struct controller *)module;
+	//struct controller *c = (struct controller *)module;
 
 	/* TODO: handle cmdu types relevant for operating profile. */
 
@@ -241,12 +242,13 @@ bool is_cmdu_for_us(void *module, uint16_t type)
 }
 
 int cntlr_handle_map_event(void *module, uint16_t cmdutype, uint16_t mid,
-						uint8_t *tlvs, int len)
+			   char *rxif, uint8_t *src, uint8_t *tlvs, int len)
 {
 	struct controller *c = (struct controller *)module;
 	const map_cmdu_handler_t *f;
+	struct cmdu_cstruct *cmdu;
+	int ret = 0;
 	int idx;
-	int ret;
 
 	trace("%s: ---> cmdu = %d\n", __func__, cmdutype);
 
@@ -259,7 +261,13 @@ int cntlr_handle_map_event(void *module, uint16_t cmdutype, uint16_t mid,
 	}
 
 	if (f[idx]) {
-		ret = f[idx](c, mid, tlvs, len);
+		cmdu = map_build_cmdu(cmdutype, mid, rxif, src, tlvs);
+		if (cmdu) {
+			ret = f[idx](c, cmdu);
+			map_free_cmdu(cmdu);
+		} else {
+			dbg("%s: map_build_cmdu() failed!\n", __func__);
+		}
 	}
 
 	//TODO: check ret
diff --git a/src/core/cntlr_map.h b/src/core/cntlr_map.h
index 49a889d1d167af2606857ed9148aae629fae1a9a..a5689e4440df729e008f265ebda94ef4e80eb74b 100644
--- a/src/core/cntlr_map.h
+++ b/src/core/cntlr_map.h
@@ -6,8 +6,8 @@
 extern bool is_cmdu_for_us(void *module, uint16_t type);
 
 extern int cntlr_handle_map_event(void *module, uint16_t cmdutype, uint16_t mid,
-						uint8_t *tlvs, int len);
-
+				  char *rxif, uint8_t *src, uint8_t *tlvs,
+				  int len);
 
 
 #endif /* CNTLR_MAP_H */
diff --git a/src/core/cntlr_ubus.c b/src/core/cntlr_ubus.c
index c42064bc7ddfbed005823be365d53067cdeb2438..29ac9064e4a853456cd386eb8d91d05edca119b2 100644
--- a/src/core/cntlr_ubus.c
+++ b/src/core/cntlr_ubus.c
@@ -32,17 +32,15 @@
 #include "map_module.h"
 
 
-static struct controller *this_cntlr;
-
 static int cntlr_status(struct ubus_context *ctx, struct ubus_object *obj,
-		struct ubus_request_data *req, const char *method,
-		struct blob_attr *msg)
+			struct ubus_request_data *req, const char *method,
+			struct blob_attr *msg)
 {
-	struct controller *c = this_cntlr;
+	struct controller *c = container_of(obj, struct controller, obj);
 	struct hlist_head *stalist = c->as_table;
-	struct node *n;
 	struct netif_fhbss *p;
 	struct blob_buf bb;
+	struct node *n;
 	void *a, *b;
 	int i;
 
@@ -120,40 +118,57 @@ static int cntlr_status(struct ubus_context *ctx, struct ubus_object *obj,
 	return UBUS_STATUS_OK;
 }
 
-struct ubus_method wificntlr_methods[] = {
-	UBUS_METHOD_NOARG("status", cntlr_status),
-};
+int cntlr_publish_object(struct controller *c, const char *objname)
+{
+	struct ubus_object *obj;
+	struct ubus_object_type *obj_type;
+	struct ubus_method *obj_methods;
+	struct ubus_method m[2] = {
+		UBUS_METHOD_NOARG("status", cntlr_status),
+	};
+	int num_methods = ARRAY_SIZE(m);
+	int ret;
 
-struct ubus_object_type wificntlr_type =
-	UBUS_OBJECT_TYPE("map.controller", wificntlr_methods);
+	obj = &c->obj;
+	memset(obj, 0, sizeof(*obj));
 
-struct ubus_object wificntlr_object = {
-	.name = "map.controller",
-	.type = &wificntlr_type,
-	.methods = wificntlr_methods,
-	.n_methods = ARRAY_SIZE(wificntlr_methods),
-};
+	obj_type = calloc(1, sizeof(struct ubus_object_type));
+	if (!obj_type)
+		return -1;
 
-void cntlr_publish_object(struct controller *c)
-{
-	struct ubus_context *ctx = c->ubus_ctx;
-	int ret;
+	obj_methods = calloc(num_methods, sizeof(struct ubus_method));
+	if (!obj_methods) {
+		free(obj_type);
+		return -1;
+	}
 
-	this_cntlr = c;
-	ret = ubus_add_object(ctx, &wificntlr_object);
-	if (ret)
-		err("Failed to add 'map.controller' ubus object: %s\n",
-				ubus_strerror(ret));
+	obj->name = objname;
+	memcpy(obj_methods, m, num_methods * sizeof(struct ubus_method));
+	obj->methods = obj_methods;
+	obj->n_methods = num_methods;
+
+	obj_type->name = obj->name;
+	obj_type->n_methods = obj->n_methods;
+	obj_type->methods = obj->methods;
+	obj->type = obj_type;
+
+	ret = ubus_add_object(c->ubus_ctx, obj);
+	if (ret) {
+		err("Failed to add '%s' err = %s\n", objname, ubus_strerror(ret));
+		free(obj_methods);
+		free(obj_type);
+		return ret;
+	}
+
+	info("Published '%s' object\n", objname);
+
+	return 0;
 }
 
 void cntlr_remove_object(struct controller *c)
 {
-	struct ubus_context *ctx = c->ubus_ctx;
-
-	if (ctx && wificntlr_object.id)
-		ubus_remove_object(ctx, &wificntlr_object);
-
-	this_cntlr = NULL;
+	if (c->ubus_ctx && c->obj.id != OBJECT_INVALID)
+		ubus_remove_object(c->ubus_ctx, &c->obj);
 }
 
 int cntlr_register_module(struct controller *c)
@@ -186,7 +201,7 @@ int cntlr_register_module(struct controller *c)
 	}
 
 	blob_buf_init(&bb, 0);
-	blobmsg_add_u32(&bb, "module", wificntlr_object.id);
+	blobmsg_add_u32(&bb, "module", c->obj.id);
 	btostr((unsigned char *)&m, sizeof(struct map_module), data);
 	blobmsg_add_string(&bb, "data", data);
 	ret = ubus_invoke(ctx, map_id, "register", bb.head, NULL, 0, 3000);
@@ -197,11 +212,11 @@ int cntlr_register_module(struct controller *c)
 
 	blob_buf_free(&bb);
 
-#if 1	// testing notify event
+#if 0	// testing notify event
 	blob_buf_init(&bb, 0);
-	blobmsg_add_u32(&bb, "module", wificntlr_object.id);
+	blobmsg_add_u32(&bb, "module", c->obj.id);
 	blobmsg_add_string(&bb, "data", "Hello World");
-	ret = ubus_notify(ctx, &wificntlr_object, "1905-NOTIFICATION", bb.head, -1);
+	ret = ubus_notify(ctx, &c->obj, "1905-NOTIFICATION", bb.head, -1);
 	if (ret)
 		warn("Failed to notify 1905-NOTIFICATION\n");
 
diff --git a/src/core/cntlr_ubus.h b/src/core/cntlr_ubus.h
index b7eb46dc6f0c36ee9c242dbb0dac14f9ff9fd981..42b326a4d0466e1a0a54b20aa9f1699fed9a8628 100644
--- a/src/core/cntlr_ubus.h
+++ b/src/core/cntlr_ubus.h
@@ -10,7 +10,7 @@
 #ifndef CNTLR_UBUS_H
 #define CNTLR_UBUS_H
 
-extern void cntlr_publish_object(struct controller *c);
+extern int cntlr_publish_object(struct controller *c, const char *objname);
 extern void cntlr_remove_object(struct controller *c);