gsup: add OSMO_GSUP_SUPPORTED_RAT_TYPES_IE and OSMO_GSUP_CURRENT_RAT_TYPE_IE

OSMO_GSUP_SUPPORTED_RAT_TYPES_IE corresponds to the Supported RAT Types
Indicator from 3GPP TS 29.002. See 8.1.2 MAP_UPDATE_LOCATION service,
which indicates the capabilities of the MSC/VLR to the HLR.

So far, have room for eight RAT types in the gsup_msg. That is an arbitrary
random choice without any rationale.

OSMO_GSUP_CURRENT_RAT_TYPE_IE is useful to communicate the currently
used RAN / RAT type of the current subscriber during Location Updating Request.

Change-Id: I93850710ab55a605bf61b95063a69682a2899bb1
diff --git a/src/gsm/gsup.c b/src/gsm/gsup.c
index 2e6690e..2f9d85d 100644
--- a/src/gsm/gsup.c
+++ b/src/gsm/gsup.c
@@ -297,6 +297,7 @@
 		     struct osmo_gsup_message *gsup_msg)
 {
 	int rc;
+	int i;
 	uint8_t tag;
 	/* the shift/match functions expect non-const pointers, but we'll
 	 * either copy the data or cast pointers back to const before returning
@@ -459,6 +460,21 @@
 			gsup_msg->cn_domain = *value;
 			break;
 
+		case OSMO_GSUP_SUPPORTED_RAT_TYPES_IE:
+			if (value_len > ARRAY_SIZE(gsup_msg->supported_rat_types)) {
+				LOGP(DLGSUP, LOGL_ERROR, "nr of supported RAT types %zu > %zu\n",
+					value_len, ARRAY_SIZE(gsup_msg->supported_rat_types));
+				return -GMM_CAUSE_COND_IE_ERR;
+			}
+			for (i = 0; i < value_len; i++)
+				gsup_msg->supported_rat_types[i] = value[i];
+			gsup_msg->supported_rat_types_len = value_len;
+			break;
+
+		case OSMO_GSUP_CURRENT_RAT_TYPE_IE:
+			gsup_msg->current_rat_type = *value;
+			break;
+
 		case OSMO_GSUP_CHARG_CHAR_IE:
 			gsup_msg->pdp_charg_enc = value;
 			gsup_msg->pdp_charg_enc_len = value_len;
@@ -856,6 +872,25 @@
 	if ((u8 = gsup_msg->cause_sm))
 		msgb_tlv_put(msg, OSMO_GSUP_CAUSE_SM_IE, sizeof(u8), &u8);
 
+	if (gsup_msg->supported_rat_types_len) {
+		int i;
+		uint8_t *len = msgb_tl_put(msg, OSMO_GSUP_SUPPORTED_RAT_TYPES_IE);
+		*len = gsup_msg->supported_rat_types_len;
+		for (i = 0; i < gsup_msg->supported_rat_types_len; i++) {
+			if (!gsup_msg->supported_rat_types[i] ||
+			    gsup_msg->supported_rat_types[i] >= OSMO_RAT_COUNT) {
+				LOGP(DLGSUP, LOGL_ERROR, "Failed to encode RAT type %s (nr %d)\n",
+				     osmo_rat_type_name(gsup_msg->supported_rat_types[i]), i);
+				return -EINVAL;
+			}
+			msgb_v_put(msg, gsup_msg->supported_rat_types[i]);
+		}
+	}
+	if (gsup_msg->current_rat_type != OSMO_RAT_UNKNOWN) {
+		u8 = gsup_msg->current_rat_type;
+		msgb_tlv_put(msg, OSMO_GSUP_CURRENT_RAT_TYPE_IE, sizeof(u8), &u8);
+	}
+
 	return 0;
 }