diff --git a/src/assoc_ctrl.c b/src/assoc_ctrl.c
index 5fb478fc7cdc1acb90ed87381277ae77e2c9bb79..de78f2289c0ab395c4ddf3cd1946a7c2bf2f6c55 100644
--- a/src/assoc_ctrl.c
+++ b/src/assoc_ctrl.c
@@ -255,7 +255,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 };
@@ -336,7 +336,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)++;
@@ -349,6 +348,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)
 {
@@ -591,6 +615,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)