diff --git a/src/core/cntlr.c b/src/core/cntlr.c
index ab6d3b605a9a1bb3e422f06a43a275d932d64ff2..8e8bb2d77f38961da98e52104317f1f4130ae90a 100644
--- a/src/core/cntlr.c
+++ b/src/core/cntlr.c
@@ -2060,14 +2060,14 @@ static void cntlr_discovery(struct uloop_timeout *t) /* make into periodic uloop
 	struct controller *c = container_of(t, struct controller, discovery_timer);
 	struct cmdu_buff *cmdu;
 
-	cmdu = cntlr_gen_ap_autoconfig_search(c, NULL, 0x02, 0x00);
+	cmdu = cntlr_gen_ap_autoconfig_search(c, 0x02, 0x00);
 	if (!cmdu)
 		return;
 
 	c->mid_2g = send_cmdu(c, cmdu);
 	cmdu_free(cmdu);
 
-	cmdu = cntlr_gen_ap_autoconfig_search(c, NULL, 0x02, 0x01);
+	cmdu = cntlr_gen_ap_autoconfig_search(c, 0x02, 0x01);
 	if (!cmdu)
 		return;
 
diff --git a/src/core/cntlr_cmdu_generator.c b/src/core/cntlr_cmdu_generator.c
index 88ab330abd0b8b4b462cc9e6888e850f01279f5a..b23f5d5cf63150a2d05b70cfdc1ae354bc61cc82 100644
--- a/src/core/cntlr_cmdu_generator.c
+++ b/src/core/cntlr_cmdu_generator.c
@@ -405,115 +405,53 @@ struct cmdu_buff *cntlr_gen_bk_caps_query(struct controller *c,
 }
 
 struct cmdu_buff *cntlr_gen_ap_autoconfig_search(struct controller *c,
-		char *intf_name, uint8_t profile, uint8_t band)
+		uint8_t profile, uint8_t band)
 {
+	struct cmdu_buff *frm = NULL;
+	struct tlv *t;
+	int ret = 0;
+	uint16_t mid = 0;
+	uint8_t origin[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x13};
+
+	frm = cmdu_alloc_simple(CMDU_TYPE_AP_AUTOCONFIGURATION_SEARCH, &mid);
+	if (!frm) {
+		dbg("%s: -ENOMEM\n", __func__);
+		return NULL;
+	}
+
+	CMDU_SET_RELAY_MCAST(frm->cdata);
+
+	ret = cntlr_gen_al_mac(c, frm, c->almac);
+	if (ret)
+		goto out;
+
+	ret = cntlr_gen_searched_role(c, frm, IEEE80211_ROLE_REGISTRAR);
+	if (ret)
+		goto out;
+
+	ret = cntlr_gen_autoconf_freq_band(c, frm, band);
+	if (ret)
+		goto out;
+
+	ret = cntlr_gen_supp_service(c, frm, SUPPORTED_SERVICE_MULTIAP_CONTROLLER);
+	if (ret)
+		goto out;
+
+	ret = cnltr_gen_searched_service(c, frm,
+			SEARCHED_SERVICE_MULTIAP_CONTROLLER);
+	if (ret)
+		goto out;
+
+	ret = cntlr_gen_map_profile(c, frm, MULTIAP_PROFILE_2);
+	if (ret)
+		goto out;
+
+	memcpy(frm->origin, origin, 6);
+	cmdu_put_eom(frm);
+	return frm;
+out:
+	cmdu_free(frm);
 	return NULL;
-//	struct cmdu_cstruct *cmdu;
-//	struct tlv_supp_service *p = NULL;
-//	struct tlv_searched_service *p1;
-//	struct tlv_map_profile *p2;
-//	struct tlv_al_mac *p3;
-//	struct tlv_autoconf_freq_band *p4;
-//	struct tlv_searched_role *p5;
-//	int i, tlv_index = 0;
-//
-//	cmdu = (struct cmdu_cstruct *)calloc(1,	sizeof(struct cmdu_cstruct));
-//	if (!cmdu) {
-//		trace("failed to malloc cmdu\n");
-//		return NULL;
-//	}
-//
-//	memcpy(cmdu->origin, "\x01\x80\xc2\x00\x00\x13", 6);
-//	if (intf_name)
-//		strncpy(cmdu->intf_name, intf_name,
-//				sizeof(cmdu->intf_name) - 1);
-//	else
-//		strncpy(cmdu->intf_name, c->cfg.al_bridge, sizeof(cmdu->intf_name) - 1);
-//
-//	cmdu->message_type = CMDU_TYPE_AP_AUTOCONFIGURATION_SEARCH;
-//
-//	p = calloc(1, sizeof(struct tlv_supp_service));
-//	if (!p)
-//		goto fail_cmdu;
-//
-//	cmdu->num_tlvs++;
-//	p->tlv_type = MAP_TLV_SUPPORTED_SERVICE;
-//	p->supported_services_list = 1;
-//	p->supported_services = calloc(p->supported_services_list,
-//			sizeof(*p->supported_services));
-//	if (!p->supported_services)
-//		goto fail_p;
-//
-//	for (i = 0; i < p->supported_services_list; i++)
-//		p->supported_services[i].service =
-//				SUPPORTED_SERVICE_MULTIAP_AGENT;
-//
-//	p1 = calloc(1, sizeof(struct tlv_searched_service));
-//	if (!p1)
-//		goto fail_p;
-//
-//	cmdu->num_tlvs++;
-//	p1->tlv_type = MAP_TLV_SEARCHED_SERVICE;
-//	p1->searched_services_list = 1;
-//	p1->service = calloc(p1->searched_services_list, sizeof(*p1->service));
-//	if (!p1->service)
-//		goto fail_p1;
-//
-//	for (i = 0; i < p->supported_services_list; i++)
-//		p->supported_services[i].service =
-//				SEARCHED_SERVICE_MULTIAP_CONTROLLER;
-//
-//	p2 = calloc(1, sizeof(struct tlv_map_profile));
-//	if (!p2)
-//		goto fail_p1;
-//
-//	cmdu->num_tlvs++;
-//	p2->tlv_type = MAP_TLV_MULTIAP_PROFILE;
-//	p2->profile = profile;
-//
-//	p3 = cntlr_gen_al_mac(c, c->almac);
-//	if (!p3)
-//		goto fail_p2;
-//	cmdu->num_tlvs++;
-//
-//	p4 = cntlr_gen_autoconf_freq_band(c, band); /* dummy value */
-//	if (!p4)
-//		goto fail_p3;
-//	cmdu->num_tlvs++;
-//
-//	p5 = cntlr_gen_searched_role(c, 0x00); /* registrar */
-//	if (!p5)
-//		goto fail_p4;
-//	cmdu->num_tlvs++;
-//
-//	cmdu->tlvs = (uint8_t **)calloc(cmdu->num_tlvs,
-//			sizeof(uint8_t *));
-//	if (!cmdu->tlvs)
-//		goto fail_p5;
-//
-//	cmdu->tlvs[tlv_index++] = (uint8_t *)p;
-//	cmdu->tlvs[tlv_index++] = (uint8_t *)p1;
-//	cmdu->tlvs[tlv_index++] = (uint8_t *)p2;
-//	cmdu->tlvs[tlv_index++] = (uint8_t *)p3;
-//	cmdu->tlvs[tlv_index++] = (uint8_t *)p4;
-//	cmdu->tlvs[tlv_index++] = (uint8_t *)p5;
-//
-//	return cmdu;
-//fail_p5:
-//	map_free_tlv_cstruct((uint8_t *) p5);
-//fail_p4:
-//	map_free_tlv_cstruct((uint8_t *) p4);
-//fail_p3:
-//	map_free_tlv_cstruct((uint8_t *) p3);
-//fail_p2:
-//	map_free_tlv_cstruct((uint8_t *) p2);
-//fail_p1:
-//	map_free_tlv_cstruct((uint8_t *) p1);
-//fail_p:
-//	map_free_tlv_cstruct((uint8_t *) p);
-//fail_cmdu:
-//	free(cmdu);
-//	return NULL;
 }
 
 struct cmdu_buff *cntlr_gen_ap_autoconfig_response(struct controller *c,
diff --git a/src/core/cntlr_cmdu_generator.h b/src/core/cntlr_cmdu_generator.h
index 54ea12b6ddc20561c3f2ae01a3cef72c27d11108..d1696c37c0f0c222ee1f6bf1104f75b5faef74dc 100644
--- a/src/core/cntlr_cmdu_generator.h
+++ b/src/core/cntlr_cmdu_generator.h
@@ -29,7 +29,7 @@ struct cmdu_buff *cntlr_gen_policy_config_req(struct controller *c,
 struct cmdu_buff *cntlr_gen_sta_metric_query(struct controller *c,
 		uint8_t *origin, char *intf_name, uint8_t *sta);
 struct cmdu_buff *cntlr_gen_ap_autoconfig_search(struct controller *c,
-		char *intf_name, uint8_t profile, uint8_t band);
+		uint8_t profile, uint8_t band);
 struct cmdu_buff *cntlr_gen_ap_autoconfig_response(struct controller *c,
 		uint8_t *dest, uint8_t band, uint16_t mid);
 struct cmdu_buff *cntlr_gen_ap_autoconfig_wsc(struct controller *c,
diff --git a/src/core/cntlr_tlv_generator.c b/src/core/cntlr_tlv_generator.c
index 76860a519e012112bbc6e3642a5a1430957dfb4e..ef07efb3162cab91c35550ae07275571efc42cb9 100644
--- a/src/core/cntlr_tlv_generator.c
+++ b/src/core/cntlr_tlv_generator.c
@@ -905,34 +905,76 @@ struct tlv_sta_mac *cntlr_gen_sta_mac(struct controller *c, uint8_t *sta)
 //	return p;
 }
 
-struct tlv_searched_role *cntlr_gen_searched_role(struct controller *c,
+int cntlr_gen_searched_role(struct controller *c, struct cmdu_buff *frm,
 		uint8_t role)
 {
-	return NULL;
-//	struct tlv_searched_role *p;
-//
-//	p = calloc(1, sizeof(struct tlv_searched_role));
-//	if (!p)
-//		return NULL;
-//
-//	p->tlv_type = TLV_TYPE_SEARCHED_ROLE;
-//	p->role = role;
-//
-//	return p;
+	struct tlv *t;
+	struct tlv_searched_role *data;
+	int ret;
+
+	t = cmdu_reserve_tlv(frm, 128);
+	if (!t)
+		return -1;
+
+	t->type = TLV_TYPE_SEARCHED_ROLE;
+	t->len = 1;
+	data = (struct tlv_searched_role *) t->data;
+	data->role = role;
+
+	ret = cmdu_put_tlv(frm, t);
+	if (ret) {
+		dbg("%s: error: cmdu_put_tlv()\n", __func__);
+		return -1;
+	}
+
+	return 0;
 }
 
-struct tlv_autoconf_freq_band *cntlr_gen_autoconf_freq_band(struct controller *c,
+int cnltr_gen_searched_service(struct controller *c, struct cmdu_buff *frm,
+		uint8_t service)
+{
+	struct tlv *t;
+	int ret;
+
+	t = cmdu_reserve_tlv(frm, 128);
+	if (!t)
+		return -1;
+
+	t->type = MAP_TLV_SEARCHED_SERVICE;
+	t->len = 2;
+	t->data[0] = 0x1;
+	t->data[1] = service;
+
+	ret = cmdu_put_tlv(frm, t);
+	if (ret) {
+		dbg("%s: error: cmdu_put_tlv()\n", __func__);
+		return -1;
+	}
+
+	return 0;
+}
+
+int cntlr_gen_autoconf_freq_band(struct controller *c, struct cmdu_buff *frm,
 		uint8_t band)
 {
-	return NULL;
-//	struct tlv_autoconf_freq_band *p;
-//
-//	p = calloc(1, sizeof(struct tlv_autoconf_freq_band));
-//	if (!p)
-//		return NULL;
-//
-//	p->tlv_type = TLV_TYPE_AUTOCONFIG_FREQ_BAND;
-//	p->freq_band = band;
-//
-//	return p;
+	struct tlv *t;
+	struct tlv_autoconfig_band *data;
+	int ret;
+
+	t = cmdu_reserve_tlv(frm, 128);
+	if (!t)
+		return -1;
+
+	t->type = TLV_TYPE_AUTOCONFIG_FREQ_BAND;
+	t->len = 1;
+	data = (struct tlv_autoconfig_band *) t->data;
+	data->band = band;
+
+	ret = cmdu_put_tlv(frm, t);
+	if (ret) {
+		dbg("%s: error: cmdu_put_tlv()\n", __func__);
+		return -1;
+	}
+
+	return 0;
 }
diff --git a/src/core/cntlr_tlv_generator.h b/src/core/cntlr_tlv_generator.h
index 821e90a862fdeeb71e532d43bbfc2c274e879698..d981f27a197a44356674673c6b7252a67d794427 100644
--- a/src/core/cntlr_tlv_generator.h
+++ b/src/core/cntlr_tlv_generator.h
@@ -65,8 +65,10 @@ struct tlv_client_assoc_ctrl_request *cntlr_gen_assoc_control_req(
 struct tlv_ap_metric_query *cntlr_gen_ap_metric_query(struct controller *c,
 		uint8_t num_bss, uint8_t *bsslist);
 struct tlv_sta_mac *cntlr_gen_sta_mac(struct controller *c, uint8_t *sta);
-struct tlv_searched_role *cntlr_gen_searched_role(struct controller *c,
+int cntlr_gen_searched_role(struct controller *c, struct cmdu_buff *frm,
 		uint8_t role);
-struct tlv_autoconf_freq_band *cntlr_gen_autoconf_freq_band(struct controller *c,
+int cntlr_gen_autoconf_freq_band(struct controller *c, struct cmdu_buff *frm,
 		uint8_t band);
+int cnltr_gen_searched_service(struct controller *c, struct cmdu_buff *frm,
+		uint8_t service);
 #endif