gprs_ns2: add recursive anchor to protect against double free

When free'ing a NSE/NSVC/BIND ensure there can't be a double
free by using a free anchor in the struct.

Recursive free's can happen when the NS user reacts on an event
(e.g. GPRS_NS2_AFF_CAUSE_VC_FAILURE) and calls the free().
Or when the user free's a NSVC when the NSE uses SNS as configuration,
the fsm tries to free it again.

Change-Id: If9823aadaa936e136aa43e88cee925ddd5974841
diff --git a/src/gb/gprs_ns2.c b/src/gb/gprs_ns2.c
index fb2965a..45cdfcc 100644
--- a/src/gb/gprs_ns2.c
+++ b/src/gb/gprs_ns2.c
@@ -639,9 +639,9 @@
  *  \param[in] nsvc NS-VC to destroy */
 void gprs_ns2_free_nsvc(struct gprs_ns2_vc *nsvc)
 {
-	if (!nsvc)
+	if (!nsvc || nsvc->freed)
 		return;
-
+	nsvc->freed = true;
 	ns2_prim_status_ind(nsvc->nse, nsvc, 0, GPRS_NS2_AFF_CAUSE_VC_FAILURE);
 
 	llist_del(&nsvc->list);
@@ -671,7 +671,7 @@
 {
 	struct gprs_ns2_vc *nsvc, *tmp;
 
-	if (!nse)
+	if (!nse || nse->freed)
 		return;
 
 	llist_for_each_entry_safe(nsvc, tmp, &nse->nsvc, list) {
@@ -889,9 +889,11 @@
  *  \param[in] nse NS Entity to destroy */
 void gprs_ns2_free_nse(struct gprs_ns2_nse *nse)
 {
-	if (!nse)
+	struct gprs_ns2_vc *nsvc, *nsvc2;
+	if (!nse || nse->freed)
 		return;
 
+	nse->freed = true;
 	nse->alive = false;
 	if (nse->bss_sns_fi) {
 		osmo_fsm_inst_term(nse->bss_sns_fi, OSMO_FSM_TERM_REQUEST, NULL);
@@ -901,6 +903,9 @@
 	gprs_ns2_free_nsvcs(nse);
 	ns2_prim_status_ind(nse, NULL, 0, GPRS_NS2_AFF_CAUSE_FAILURE);
 	rate_ctr_group_free(nse->ctrg);
+	llist_for_each_entry_safe(nsvc, nsvc2, &nse->nsvc, list) {
+		gprs_ns2_free_nsvc(nsvc);
+	}
 
 	llist_del(&nse->list);
 	talloc_free(nse);
@@ -1466,9 +1471,10 @@
 {
 	struct gprs_ns2_vc *nsvc, *tmp;
 	struct gprs_ns2_nse *nse;
-	if (!bind)
+	if (!bind || bind->freed)
 		return;
 
+	bind->freed = true;
 	llist_for_each_entry_safe(nsvc, tmp, &bind->nsvc, blist) {
 		gprs_ns2_free_nsvc(nsvc);
 	}