gsup.h: define newly added PCO IE

PCO - Protocol Configuration Options 3GPP TS 24.008 / 10.5.6.3.
The PCO will be used by the osmo-epdg to pass PCO internally.
The PCO will be passed towards to the PGW in the Session Request.

Related: OS#6369
Related: osmo-gsm-manuals.git Change-Id Id912ead4e1205f84a40af6505a5ddf050d1e086d
Change-Id: I0f9de90c7c67fe194b441a9d118eba70f09afb5e
diff --git a/TODO-RELEASE b/TODO-RELEASE
index 3e75184..01f7c41 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -20,3 +20,4 @@
 gsm		ABI change		add UI queue to struct lapdm_datalink
 gsm		ADD			gsup.h: struct osmo_gsup_pdp_info fields pdp_type_nr, pdp_type_org, deprecate pdp_type.
 gsm		ABI change			gsup.h: Add field pdp_address in struct osmo_gsup_pdp_info shifts the struct, and in turn fields in struct osmo_gsup_message.
+gsm		ABI change		gsup.h: Add field pco in struct osmo_gsup_message. Length of the struct osmo_gsup_message increase.
diff --git a/include/osmocom/gsm/gsup.h b/include/osmocom/gsm/gsup.h
index a17a729..6ad72d2 100644
--- a/include/osmocom/gsm/gsup.h
+++ b/include/osmocom/gsm/gsup.h
@@ -61,6 +61,7 @@
 /*! Maximum number of octets encoding MSISDN in BCD format */
 #define OSMO_GSUP_MAX_MSISDN_LEN		9
 #define OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN	43 /* TS 24.008 10.5.4.7 */
+#define OSMO_GSUP_MAX_PCO_LEN			251
 
 /*! Information Element Identifiers for GSUP IEs */
 enum osmo_gsup_iei {
@@ -80,6 +81,7 @@
 	OSMO_GSUP_ACCESS_POINT_NAME_IE		= 0x12,
 	OSMO_GSUP_PDP_QOS_IE			= 0x13,
 	OSMO_GSUP_CHARG_CHAR_IE			= 0x14,
+	OSMO_GSUP_PCO_IE			= 0x15,
 	OSMO_GSUP_RAND_IE			= 0x20,
 	OSMO_GSUP_SRES_IE			= 0x21,
 	OSMO_GSUP_KC_IE				= 0x22,
@@ -406,6 +408,12 @@
 	enum osmo_rat_type		current_rat_type;
 	enum osmo_rat_type		supported_rat_types[8]; /*!< arbitrary choice */
 	size_t				supported_rat_types_len;
+
+	/*! PCO protocol option 3GPP TS 24.008 10.5.6.3 / Table 10.5.136. PCO contains Octet 3-ZA */
+	const uint8_t			*pco;
+	/*! Number of bytes of the PCO. */
+	size_t				pco_len;
+
 };
 
 int osmo_gsup_decode(const uint8_t *data, size_t data_len,
diff --git a/src/gsm/gsup.c b/src/gsm/gsup.c
index 3daf75c..4f0a1b5 100644
--- a/src/gsm/gsup.c
+++ b/src/gsm/gsup.c
@@ -506,6 +506,11 @@
 			gsup_msg->rand = value;
 			break;
 
+		case OSMO_GSUP_PCO_IE:
+			gsup_msg->pco = value;
+			gsup_msg->pco_len = value_len;
+			break;
+
 		case OSMO_GSUP_MSISDN_IE:
 			gsup_msg->msisdn_enc = value;
 			gsup_msg->msisdn_enc_len = value_len;
@@ -872,6 +877,11 @@
 	if (gsup_msg->rand)
 		msgb_tlv_put(msg, OSMO_GSUP_RAND_IE, 16, gsup_msg->rand);
 
+	if (gsup_msg->pco && gsup_msg->pco_len > 0) {
+		if (gsup_msg->pco_len > OSMO_GSUP_MAX_PCO_LEN)
+			return -EINVAL;
+		msgb_tlv_put(msg, OSMO_GSUP_PCO_IE, gsup_msg->pco_len, gsup_msg->pco);
+	}
 	if (gsup_msg->cn_domain) {
 		uint8_t dn = gsup_msg->cn_domain;
 		msgb_tlv_put(msg, OSMO_GSUP_CN_DOMAIN_IE, 1, &dn);