diff --git a/src/assoc_ctrl.c b/src/assoc_ctrl.c
index e7f92a24390ca211ac3472ae912df60753a8a2a0..47ca5c2dde6f856a122ef3ccf16747bbae95e368 100644
--- a/src/assoc_ctrl.c
+++ b/src/assoc_ctrl.c
@@ -256,7 +256,7 @@ struct rsta {
 	uint16_t validity;
 };
 
-int assoc_ctrl_read_restrictions(struct agent *a, uint8_t *bssid,
+static int assoc_ctrl_read_restrictions(struct agent *a, uint8_t *bssid,
 			struct rsta *fr, int *num_fr)
 {
 	struct blob_buf bssids = { 0 };
@@ -337,7 +337,6 @@ int assoc_ctrl_read_restrictions(struct agent *a, uint8_t *bssid,
 				fr[*num_fr].validity = 0;
 			} else {
 				fr[*num_fr].validity = duration - elapsed;
-				/* TODO: remove outdated entry from file */
 			}
 
 			(*num_fr)++;
@@ -350,6 +349,31 @@ out:
 	return ret;
 }
 
+static void assoc_ctrl_clean_expired(struct agent *a, uint8_t *bssid,
+			struct rsta *fr, int *num_fr)
+{
+	int i;
+
+	for (i = 0; i < *num_fr; i++) {
+		if ((fr[i].mode == ASSOC_CTRL_TIMED_BLOCK || fr[i].mode == ASSOC_CTRL_BLOCK)
+				&& fr[i].validity == 0) {
+			int j;
+
+			/* remove from file */
+			assoc_ctrl_update_restrict_file(bssid, fr[i].macaddr,
+					0, ASSOC_CTRL_UNBLOCK);
+			/* remove fr[i] from fr */
+			for (j = i; j < *num_fr - 1; j++)
+				memcpy(&fr[j], &fr[j + 1], sizeof(struct rsta));
+			memset(&fr[*num_fr - 1], 0, sizeof(struct rsta));
+			/* decrease num_fr */
+			(*num_fr)--;
+			/* decrease i */
+			i--;
+		}
+	}
+}
+
 static void agent_disconnect_stas(struct agent *a, int num_sta,
 		uint8_t sta_macs[][6], struct netif_ap *ap)
 {
@@ -592,6 +616,8 @@ int assoc_ctrl_sync_from_file(struct agent *a, struct netif_ap *ap)
 	if (ret)
 		return ret;
 
+	/* Remove all outdated entries from file */
+	assoc_ctrl_clean_expired(a, ap->bssid, fr, &num_fr);
 
 	/* 1. Add/Update STAs: file list -> runtime list */
 	if (num_fr > 0)