vlr: auth_fsm: clarify success/failure result

Explicitly send distinct parent events on auth success and failure. So
far determining success depended only on the data pointer passed on with
the event. Distinct events clarify the logging and the FSM code.

This prepares for a third FSM outcome to be added in a subsequent patch,
to separately signal when the HLR has no auth data.

No functional change.

Related: OS#4830
Change-Id: I02776dfe6785983f2ebe398f57867f5ceb288ba0
diff --git a/src/libvlr/vlr_access_req_fsm.c b/src/libvlr/vlr_access_req_fsm.c
index 5f4795f..bcf589e 100644
--- a/src/libvlr/vlr_access_req_fsm.c
+++ b/src/libvlr/vlr_access_req_fsm.c
@@ -40,6 +40,7 @@
 	OSMO_VALUE_STRING(PR_ARQ_E_START),
 	OSMO_VALUE_STRING(PR_ARQ_E_ID_IMSI),
 	OSMO_VALUE_STRING(PR_ARQ_E_AUTH_RES),
+	OSMO_VALUE_STRING(PR_ARQ_E_AUTH_FAILURE),
 	OSMO_VALUE_STRING(PR_ARQ_E_CIPH_RES),
 	OSMO_VALUE_STRING(PR_ARQ_E_UPD_LOC_RES),
 	OSMO_VALUE_STRING(PR_ARQ_E_TRACE_RES),
@@ -344,6 +345,7 @@
 					0, 0);
 		vsub->auth_fsm = auth_fsm_start(vsub, fi,
 						PR_ARQ_E_AUTH_RES,
+						PR_ARQ_E_AUTH_FAILURE,
 						par->is_r99,
 						par->is_utran);
 	} else {
@@ -438,15 +440,19 @@
 {
 	enum gsm48_reject_value *cause = data;
 
-	OSMO_ASSERT(event == PR_ARQ_E_AUTH_RES);
+	switch (event) {
+	case PR_ARQ_E_AUTH_RES:
+		/* Node 2 */
+		_proc_arq_vlr_node2(fi);
+		return;
 
-	if (!cause || *cause) {
+	case PR_ARQ_E_AUTH_FAILURE:
 		proc_arq_fsm_done(fi, cause? *cause : GSM48_REJECT_NETWORK_FAILURE);
 		return;
-	}
 
-	/* Node 2 */
-	_proc_arq_vlr_node2(fi);
+	default:
+		OSMO_ASSERT(false);
+	}
 }
 
 static void proc_arq_vlr_fn_w_ciph(struct osmo_fsm_inst *fi,
@@ -551,7 +557,8 @@
 	},
 	[PR_ARQ_S_WAIT_AUTH] = {
 		.name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_AUTH),
-		.in_event_mask = S(PR_ARQ_E_AUTH_RES),
+		.in_event_mask = S(PR_ARQ_E_AUTH_RES) |
+				 S(PR_ARQ_E_AUTH_FAILURE),
 		.out_state_mask = S(PR_ARQ_S_DONE) |
 				  S(PR_ARQ_S_WAIT_CIPH) |
 				  S(PR_ARQ_S_WAIT_UPD_LOC_CHILD) |
diff --git a/src/libvlr/vlr_auth_fsm.c b/src/libvlr/vlr_auth_fsm.c
index a6b5cd2..0583d7c 100644
--- a/src/libvlr/vlr_auth_fsm.c
+++ b/src/libvlr/vlr_auth_fsm.c
@@ -51,6 +51,9 @@
 	bool auth_requested;
 
 	int auth_tuple_max_reuse_count; /* see vlr->cfg instead */
+
+	uint32_t parent_event_success;
+	uint32_t parent_event_failure;
 };
 
 /***********************************************************************
@@ -240,14 +243,21 @@
 /* Terminate the Auth FSM Instance and notify parent */
 static void auth_fsm_term(struct osmo_fsm_inst *fi, enum gsm48_reject_value result)
 {
+	struct auth_fsm_priv *afp = fi->priv;
+
 	LOGPFSM(fi, "Authentication terminating with result %s\n",
 		vlr_auth_fsm_result_name(result));
 
-	/* Do one final state transition (mostly for logging purpose) */
-	if (!result)
+	/* Do one final state transition (mostly for logging purpose) and set the parent_term_event according to success
+	 * or failure. */
+	if (!result) {
+		/* No reject value means success */
 		osmo_fsm_inst_state_chg(fi, VLR_SUB_AS_AUTHENTICATED, 0, 0);
-	else
+		fi->proc.parent_term_event = afp->parent_event_success;
+	} else {
 		osmo_fsm_inst_state_chg(fi, VLR_SUB_AS_AUTH_FAILED, 0, 0);
+		fi->proc.parent_term_event = afp->parent_event_failure;
+	}
 
 	/* return the result to the parent FSM */
 	osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, &result);
@@ -593,23 +603,23 @@
 /* MSC->VLR: Start Procedure Authenticate_VLR (TS 23.012 Ch. 4.1.2.2) */
 struct osmo_fsm_inst *auth_fsm_start(struct vlr_subscr *vsub,
 				     struct osmo_fsm_inst *parent,
-				     uint32_t parent_term_event,
+				     uint32_t parent_event_success,
+				     uint32_t parent_event_failure,
 				     bool is_r99,
 				     bool is_utran)
 {
 	struct osmo_fsm_inst *fi;
 	struct auth_fsm_priv *afp;
 
-	fi = osmo_fsm_inst_alloc_child(&vlr_auth_fsm, parent,
-					parent_term_event);
+	fi = osmo_fsm_inst_alloc_child(&vlr_auth_fsm, parent, parent_event_failure);
 	if (!fi) {
-		osmo_fsm_inst_dispatch(parent, parent_term_event, 0);
+		osmo_fsm_inst_dispatch(parent, parent_event_failure, 0);
 		return NULL;
 	}
 
 	afp = talloc_zero(fi, struct auth_fsm_priv);
 	if (!afp) {
-		osmo_fsm_inst_dispatch(parent, parent_term_event, 0);
+		osmo_fsm_inst_dispatch(parent, parent_event_failure, 0);
 		return NULL;
 	}
 
@@ -618,6 +628,8 @@
 		afp->by_imsi = true;
 	afp->is_r99 = is_r99;
 	afp->is_utran = is_utran;
+	afp->parent_event_success = parent_event_success;
+	afp->parent_event_failure = parent_event_failure;
 	fi->priv = afp;
 	vsub->auth_fsm = fi;
 
diff --git a/src/libvlr/vlr_auth_fsm.h b/src/libvlr/vlr_auth_fsm.h
index 73ab53f..44a5650 100644
--- a/src/libvlr/vlr_auth_fsm.h
+++ b/src/libvlr/vlr_auth_fsm.h
@@ -31,7 +31,8 @@
 
 struct osmo_fsm_inst *auth_fsm_start(struct vlr_subscr *vsub,
 				     struct osmo_fsm_inst *parent,
-				     uint32_t parent_term_event,
+				     uint32_t parent_event_success,
+				     uint32_t parent_event_failure,
 				     bool is_r99,
 				     bool is_utran);
 
diff --git a/src/libvlr/vlr_lu_fsm.c b/src/libvlr/vlr_lu_fsm.c
index 224dd9f..1287bb6 100644
--- a/src/libvlr/vlr_lu_fsm.c
+++ b/src/libvlr/vlr_lu_fsm.c
@@ -643,6 +643,7 @@
 	OSMO_VALUE_STRING(VLR_ULA_E_SEND_ID_ACK),
 	OSMO_VALUE_STRING(VLR_ULA_E_SEND_ID_NACK),
 	OSMO_VALUE_STRING(VLR_ULA_E_AUTH_RES),
+	OSMO_VALUE_STRING(VLR_ULA_E_AUTH_FAILURE),
 	OSMO_VALUE_STRING(VLR_ULA_E_CIPH_RES),
 	OSMO_VALUE_STRING(VLR_ULA_E_ID_IMSI),
 	OSMO_VALUE_STRING(VLR_ULA_E_ID_IMEI),
@@ -910,7 +911,9 @@
 		osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_AUTH,
 					LU_TIMEOUT_LONG, 0);
 		vsub->auth_fsm = auth_fsm_start(lfp->vsub,
-						fi, VLR_ULA_E_AUTH_RES,
+						fi,
+						VLR_ULA_E_AUTH_RES,
+						VLR_ULA_E_AUTH_FAILURE,
 						lfp->is_r99,
 						lfp->is_utran);
 	} else {
@@ -1143,17 +1146,21 @@
 	struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
 	enum gsm48_reject_value *res = data;
 
-	OSMO_ASSERT(event == VLR_ULA_E_AUTH_RES);
-
 	lfp->upd_hlr_vlr_fsm = NULL;
 
-	if (!res || *res) {
+	switch (event) {
+	case VLR_ULA_E_AUTH_RES:
+		/* Result == Pass */
+		vlr_loc_upd_post_auth(fi);
+		return;
+
+	case VLR_ULA_E_AUTH_FAILURE:
 		lu_fsm_failure(fi, res? *res : GSM48_REJECT_NETWORK_FAILURE);
 		return;
-	}
 
-	/* Result == Pass */
-	vlr_loc_upd_post_auth(fi);
+	default:
+		OSMO_ASSERT(false);
+	}
 }
 
 static void lu_fsm_wait_ciph(struct osmo_fsm_inst *fi, uint32_t event,
@@ -1368,7 +1375,8 @@
 		.action = lu_fsm_wait_pvlr,
 	},
 	[VLR_ULA_S_WAIT_AUTH] = {
-		.in_event_mask = S(VLR_ULA_E_AUTH_RES),
+		.in_event_mask = S(VLR_ULA_E_AUTH_RES) |
+				 S(VLR_ULA_E_AUTH_FAILURE),
 		.out_state_mask = S(VLR_ULA_S_WAIT_CIPH) |
 				  S(VLR_ULA_S_WAIT_LU_COMPL) |
 				  S(VLR_ULA_S_WAIT_HLR_UPD) |