diff --git a/src/provision.c b/src/provision.c
index a2dfcf6cde5a..22413d2ccde6 100644
--- a/src/provision.c
+++ b/src/provision.c
@@ -32,7 +32,8 @@ bool __ofono_provision_get_settings(const char *mcc,
 	if (mcc == NULL || strlen(mcc) == 0 || mnc == NULL || strlen(mnc) == 0)
 		return false;
 
-	r = provision_db_lookup(pdb, mcc, mnc, spn, &contexts, &n_contexts);
+	r = provision_db_lookup(pdb, mcc, mnc, spn, NULL,
+					&contexts, &n_contexts);
 	if (r < 0)
 		return false;
 
diff --git a/src/provisiondb.c b/src/provisiondb.c
index 53305eab0594..6a913d8d1540 100644
--- a/src/provisiondb.c
+++ b/src/provisiondb.c
@@ -69,6 +69,7 @@ struct context {
 	__le64 password_offset;
 	__le64 mmsproxy_offset;
 	__le64 mmsc_offset;
+	__le64 tags_offset;
 } __attribute__((packed));
 
 struct provision_db {
@@ -218,7 +219,25 @@ static int __get_string(struct provision_db *pdb, uint64_t offset,
 	return 0;
 }
 
+static bool tags_match(char **tags_filter, const char *tags)
+{
+	_auto_(l_strv_free) char **split_tags = 0;
+	unsigned int i;
+
+	if (!tags_filter || !tags)
+		return true;
+
+	split_tags = l_strsplit(tags, ',');
+
+	for (i = 0; tags_filter[i]; i++)
+		if (l_strv_contains(split_tags, tags_filter[i]))
+			return true;
+
+	return false;
+}
+
 static int __get_contexts(struct provision_db *pdb, uint64_t offset,
+				char **tags_filter,
 				struct provision_db_entry **contexts,
 				size_t *n_contexts)
 {
@@ -227,6 +246,7 @@ static int __get_contexts(struct provision_db *pdb, uint64_t offset,
 	uint64_t i;
 	struct provision_db_entry *ret;
 	int r;
+	uint64_t n_matched = 0;
 
 	if (offset + sizeof(__le64) >= pdb->contexts_size)
 		return -EPROTO;
@@ -242,43 +262,54 @@ static int __get_contexts(struct provision_db *pdb, uint64_t offset,
 	for (i = 0; i < num; i++, offset += sizeof(struct context)) {
 		struct context *context = start + offset;
 
-		ret[i].type = L_LE32_TO_CPU(context->type);
-		ret[i].proto = L_LE32_TO_CPU(context->protocol);
-		ret[i].auth_method = L_LE32_TO_CPU(context->authentication);
+		r = __get_string(pdb, L_LE64_TO_CPU(context->tags_offset),
+					&ret[n_matched].tags);
+		if (r < 0)
+			goto fail;
+
+		if (!tags_match(tags_filter, ret[n_matched].tags))
+			continue;
+
+		ret[n_matched].type = L_LE32_TO_CPU(context->type);
+		ret[n_matched].proto = L_LE32_TO_CPU(context->protocol);
+		ret[n_matched].auth_method =
+			L_LE32_TO_CPU(context->authentication);
 
 		r = __get_string(pdb, L_LE64_TO_CPU(context->name_offset),
-					&ret[i].name);
+					&ret[n_matched].name);
 		if (r < 0)
 			goto fail;
 
 		r = __get_string(pdb, L_LE64_TO_CPU(context->apn_offset),
-					&ret[i].apn);
+					&ret[n_matched].apn);
 		if (r < 0)
 			goto fail;
 
 		r = __get_string(pdb, L_LE64_TO_CPU(context->username_offset),
-					&ret[i].username);
+					&ret[n_matched].username);
 		if (r < 0)
 			goto fail;
 
 		r = __get_string(pdb, L_LE64_TO_CPU(context->password_offset),
-					&ret[i].password);
+					&ret[n_matched].password);
 		if (r < 0)
 			goto fail;
 
 		r = __get_string(pdb, L_LE64_TO_CPU(context->mmsproxy_offset),
-					&ret[i].message_proxy);
+					&ret[n_matched].message_proxy);
 		if (r < 0)
 			goto fail;
 
 		r = __get_string(pdb, L_LE64_TO_CPU(context->mmsc_offset),
-					&ret[i].message_center);
+					&ret[n_matched].message_center);
 		if (r < 0)
 			goto fail;
+
+		n_matched += 1;
 	}
 
 	*contexts = ret;
-	*n_contexts = num;
+	*n_contexts = n_matched;
 	return 0;
 
 fail:
@@ -374,6 +405,7 @@ static int key_from_mcc_mnc(const char *mcc, const char *mnc, uint32_t *key)
 
 int provision_db_lookup(struct provision_db *pdb,
 			const char *mcc, const char *mnc, const char *match_spn,
+			char **tags_filter,
 			struct provision_db_entry **items, size_t *n_items)
 {
 	int r;
@@ -436,5 +468,5 @@ int provision_db_lookup(struct provision_db *pdb,
 		return -ENOENT;
 
 	return __get_contexts(pdb, L_LE64_TO_CPU(found->context_offset),
-				items, n_items);
+				tags_filter, items, n_items);
 }
diff --git a/src/provisiondb.h b/src/provisiondb.h
index ee203c6154af..2c70bc15cb26 100644
--- a/src/provisiondb.h
+++ b/src/provisiondb.h
@@ -19,6 +19,7 @@ struct provision_db_entry {
 	enum ofono_gprs_auth_method auth_method;
 	const char *message_proxy;
 	const char *message_center;
+	const char *tags;
 };
 
 struct provision_db *provision_db_new(const char *pathname);
@@ -27,5 +28,6 @@ void provision_db_free(struct provision_db *pdb);
 
 int provision_db_lookup(struct provision_db *pdb,
 			const char *mcc, const char *mnc, const char *spn,
+			char **tags_filter,
 			struct provision_db_entry **items,
 			size_t *n_items);
diff --git a/tools/lookup-apn.c b/tools/lookup-apn.c
index 34d689a434cf..abb95f38f470 100644
--- a/tools/lookup-apn.c
+++ b/tools/lookup-apn.c
@@ -50,7 +50,7 @@ static int lookup_apn(const char *match_mcc, const char *match_mnc,
 	fprintf(stdout, "Searching for info for network: %s%s, spn: %s\n",
 			match_mcc, match_mnc, match_spn ? match_spn : "<None>");
 
-	r = provision_db_lookup(pdb, match_mcc, match_mnc, match_spn,
+	r = provision_db_lookup(pdb, match_mcc, match_mnc, match_spn, NULL,
 					&contexts, &n_contexts);
 	if (r < 0) {
 		fprintf(stderr, "Unable to lookup: %s\n", strerror(-r));
diff --git a/unit/test-provision.c b/unit/test-provision.c
index 9c3dfad43a62..b80f4d80fa0e 100644
--- a/unit/test-provision.c
+++ b/unit/test-provision.c
@@ -27,7 +27,8 @@ static void null_provision_db(const void *data)
 	size_t n_items;
 	int r;
 
-	r = provision_db_lookup(NULL, "123", "345", NULL, &items, &n_items);
+	r = provision_db_lookup(NULL, "123", "345", NULL, NULL,
+				&items, &n_items);
 	assert(r == -EBADF);
 }
 
@@ -37,16 +38,18 @@ static void invalid_mcc_mnc(const void *data)
 	size_t n_items;
 	int r;
 
-	r = provision_db_lookup(pdb, "3444", "33", NULL, &items, &n_items);
+	r = provision_db_lookup(pdb, "3444", "33", NULL, NULL,
+				&items, &n_items);
 	assert(r == -EINVAL);
 
-	r = provision_db_lookup(pdb, "3ab", "33", NULL, &items, &n_items);
+	r = provision_db_lookup(pdb, "3ab", "33", NULL, NULL, &items, &n_items);
 	assert(r == -EINVAL);
 
-	r = provision_db_lookup(pdb, "333", "3", NULL, &items, &n_items);
+	r = provision_db_lookup(pdb, "333", "3", NULL, NULL, &items, &n_items);
 	assert(r == -EINVAL);
 
-	r = provision_db_lookup(pdb, "333", "3334", NULL, &items, &n_items);
+	r = provision_db_lookup(pdb, "333", "3334", NULL, NULL,
+			&items, &n_items);
 	assert(r == -EINVAL);
 }
 
@@ -225,7 +228,7 @@ static void provision_lookup(const void *data)
 	size_t i;
 	int r;
 
-	r = provision_db_lookup(pdb, test->mcc, test->mnc, test->spn,
+	r = provision_db_lookup(pdb, test->mcc, test->mnc, test->spn, NULL,
 					&items, &n_items);
 	assert(r == test->result);
 
