Index: uspace/srv/loc/category.c
===================================================================
--- uspace/srv/loc/category.c	(revision 16dc8870242df10ae64ee7bcbf125aa8607cb7fb)
+++ uspace/srv/loc/category.c	(revision 278ac72d2dae454404705248646f24d3dd51f94c)
@@ -54,4 +54,35 @@
 	list_append(&cat->cat_list, &cdir->categories);
 }
+
+/** Get list of categories. */
+int categ_dir_get_categories(categ_dir_t *cdir, category_id_t *id_buf,
+    size_t buf_size, size_t *act_size)
+{
+	size_t act_cnt;
+	size_t buf_cnt;
+
+	assert(fibril_mutex_is_locked(&cdir->mutex));
+
+	buf_cnt = buf_size / sizeof(category_id_t);
+
+	act_cnt = list_count(&cdir->categories);
+	*act_size = act_cnt * sizeof(category_id_t);
+
+	if (buf_size % sizeof(category_id_t) != 0)
+		return EINVAL;
+
+	size_t pos = 0;
+	list_foreach(cdir->categories, item) {
+		category_t *cat =
+		    list_get_instance(item, category_t, cat_list);
+
+		if (pos < buf_cnt)
+			id_buf[pos] = cat->id;
+		pos++;
+	}
+
+	return EOK;
+}
+
 
 /** Initialize category structure. */
Index: uspace/srv/loc/category.h
===================================================================
--- uspace/srv/loc/category.h	(revision 16dc8870242df10ae64ee7bcbf125aa8607cb7fb)
+++ uspace/srv/loc/category.h	(revision 278ac72d2dae454404705248646f24d3dd51f94c)
@@ -69,4 +69,6 @@
 extern void categ_dir_init(categ_dir_t *);
 extern void categ_dir_add_cat(categ_dir_t *, category_t *);
+extern int categ_dir_get_categories(categ_dir_t *, service_id_t *, size_t,
+    size_t *);
 extern category_t *category_new(const char *);
 extern int category_add_service(category_t *, loc_service_t *);
Index: uspace/srv/loc/loc.c
===================================================================
--- uspace/srv/loc/loc.c	(revision 16dc8870242df10ae64ee7bcbf125aa8607cb7fb)
+++ uspace/srv/loc/loc.c	(revision 278ac72d2dae454404705248646f24d3dd51f94c)
@@ -755,4 +755,43 @@
 }
 
+static void loc_get_categories(ipc_callid_t iid, ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	size_t act_size;
+	int rc;
+	
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	category_id_t *id_buf = (category_id_t *) malloc(size);
+	if (id_buf == NULL) {
+		fibril_mutex_unlock(&cdir.mutex);
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	fibril_mutex_lock(&cdir.mutex);
+	
+	rc = categ_dir_get_categories(&cdir, id_buf, size, &act_size);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&cdir.mutex);
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	fibril_mutex_unlock(&cdir.mutex);
+	
+	sysarg_t retval = async_data_read_finalize(callid, id_buf, size);
+	free(id_buf);
+	
+	async_answer_1(iid, retval, act_size);
+}
+
 static void loc_get_namespaces(ipc_callid_t iid, ipc_call_t *icall)
 {
@@ -1181,4 +1220,7 @@
 		case LOC_GET_SERVICE_COUNT:
 			loc_get_service_count(callid, &call);
+			break;
+		case LOC_GET_CATEGORIES:
+			loc_get_categories(callid, &call);
 			break;
 		case LOC_GET_NAMESPACES:
