Handle IPv6/IPv4v6 PDU sessions
Handle IPv6 (and IPv4v6) PDU sessions by correctly instructing nas_config() to set up the interface with provided IP addresses. Note that as of now, IPv6 PDU sessions have not been fully tested. Remove a useless assert at the gNB; to my understanding the gNB does not care about the IP session type (at least for IP), as it just transparently tunnels the IP packets from/to GTP. I added a comment in the code where to change to request a PDU session different from IPv4. Currently it is hardcoded to IPv4, and it seems that a default OAI 5GC config would reject a PDU session type different from IPv4.
This commit is contained in:
@@ -310,7 +310,6 @@ static int decodePDUSessionResourceSetup(pdusession_t *session)
|
||||
/* mandatory PDUSessionType */
|
||||
case NGAP_ProtocolIE_ID_id_PDUSessionType:
|
||||
session->pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType;
|
||||
AssertFatal(session->pdu_session_type == PDUSessionType_ipv4 || session->pdu_session_type == PDUSessionType_ipv4v6, "To be developped: support not IPv4 sessions\n");
|
||||
break;
|
||||
|
||||
/* optional SecurityIndication */
|
||||
|
||||
@@ -32,6 +32,29 @@ static uint16_t getShort(uint8_t *input)
|
||||
return htons(tmp16);
|
||||
}
|
||||
|
||||
static int capture_ipv4_addr(const uint8_t *addr, char *ip, size_t len)
|
||||
{
|
||||
return snprintf(ip, len, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
|
||||
}
|
||||
|
||||
static int capture_ipv6_addr(const uint8_t *addr, char *ip, size_t len)
|
||||
{
|
||||
// 24.501 Sec 9.11.4.10: "an interface identifier for the IPv6 link local
|
||||
// address": link local starts with fe80::, and only the last 64bits are
|
||||
// given (middle is zero)
|
||||
return snprintf(ip,
|
||||
len,
|
||||
"fe80::%02x%02x:%02x%02x:%02x%02x:%02x%02x",
|
||||
addr[0],
|
||||
addr[1],
|
||||
addr[2],
|
||||
addr[3],
|
||||
addr[4],
|
||||
addr[5],
|
||||
addr[6],
|
||||
addr[7]);
|
||||
}
|
||||
|
||||
void capture_pdu_session_establishment_accept_msg(uint8_t *buffer, uint32_t msg_length)
|
||||
{
|
||||
security_protected_nas_5gs_msg_t sec_nas_hdr;
|
||||
@@ -103,25 +126,35 @@ void capture_pdu_session_establishment_accept_msg(uint8_t *buffer, uint32_t msg_
|
||||
psea_msg.pdu_addr_ie.pdu_length = *curPtr++;
|
||||
psea_msg.pdu_addr_ie.pdu_type = *curPtr++;
|
||||
|
||||
DevAssert(psea_msg.pdu_addr_ie.pdu_type == PDU_SESSION_TYPE_IPV4);
|
||||
uint8_t *addr = psea_msg.pdu_addr_ie.pdu_addr_oct;
|
||||
if (psea_msg.pdu_addr_ie.pdu_type == PDU_SESSION_TYPE_IPV4) {
|
||||
pdu_address_t *addr = &psea_msg.pdu_addr_ie;
|
||||
addr->pdu_addr_oct1 = *curPtr++;
|
||||
addr->pdu_addr_oct2 = *curPtr++;
|
||||
addr->pdu_addr_oct3 = *curPtr++;
|
||||
addr->pdu_addr_oct4 = *curPtr++;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
addr[i] = *curPtr++;
|
||||
char ip[20];
|
||||
snprintf(ip,
|
||||
sizeof(ip),
|
||||
"%d.%d.%d.%d",
|
||||
addr->pdu_addr_oct1,
|
||||
addr->pdu_addr_oct2,
|
||||
addr->pdu_addr_oct3,
|
||||
addr->pdu_addr_oct4);
|
||||
capture_ipv4_addr(&addr[0], ip, sizeof(ip));
|
||||
nas_config(1, ip, NULL, "oaitun_ue");
|
||||
setup_ue_ipv4_route(1, ip, "oaitun_ue");
|
||||
LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Received UE IP: %s\n", ip);
|
||||
} else if (psea_msg.pdu_addr_ie.pdu_type == PDU_SESSION_TYPE_IPV6) {
|
||||
for (int i = 0; i < 8; ++i)
|
||||
addr[i] = *curPtr++;
|
||||
char ipv6[40];
|
||||
capture_ipv6_addr(addr, ipv6, sizeof(ipv6));
|
||||
nas_config(1, NULL, ipv6, "oaitun_ue");
|
||||
} else if (psea_msg.pdu_addr_ie.pdu_type == PDU_SESSION_TYPE_IPV4V6) {
|
||||
// 24.501 Sec 9.11.4.10: "If the PDU session type value indicates
|
||||
// IPv4v6, the PDU address information in octet 4 to octet 11
|
||||
// contains an interface identifier for the IPv6 link local address
|
||||
// and in octet 12 to octet 15 contains an IPv4 address."
|
||||
for (int i = 0; i < 12; ++i)
|
||||
addr[i] = *curPtr++;
|
||||
char ipv6[40];
|
||||
capture_ipv6_addr(addr, ipv6, sizeof(ipv6));
|
||||
char ipv4[20];
|
||||
capture_ipv4_addr(&addr[8], ipv4, sizeof(ipv4));
|
||||
nas_config(1, ipv4, ipv6, "oaitun_ue");
|
||||
setup_ue_ipv4_route(1, ipv4, "oaitun_ue");
|
||||
} else {
|
||||
LOG_E(NAS, "unknown/unhandled PDU session establishment accept PDU type %d\n", psea_msg.pdu_addr_ie.pdu_type);
|
||||
curPtr += psea_msg.pdu_addr_ie.pdu_length;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -114,10 +114,7 @@ typedef struct pdu_address_s {
|
||||
uint8_t pdu_iei; /* PDU Address IEI (0x29) */
|
||||
uint8_t pdu_length; /* Length of PDU address contents */
|
||||
uint8_t pdu_type; /* PDU session type value */
|
||||
uint8_t pdu_addr_oct1; /* PDU address information (1st Octet)*/
|
||||
uint8_t pdu_addr_oct2; /* PDU address information (2nd Octet)*/
|
||||
uint8_t pdu_addr_oct3; /* PDU address information (3rd Octet)*/
|
||||
uint8_t pdu_addr_oct4; /* PDU address information (4th Octet)*/
|
||||
uint8_t pdu_addr_oct[12]; /* PDU address information (depending on type, up to 12 bytes)*/
|
||||
} pdu_address_t; /* TS 24.501 9.11.4.10 */
|
||||
|
||||
typedef struct dnn_s {
|
||||
|
||||
@@ -1176,7 +1176,7 @@ static void request_default_pdusession(int instance, int nssai_idx)
|
||||
{
|
||||
MessageDef *message_p = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_PDU_SESSION_REQ);
|
||||
NAS_PDU_SESSION_REQ(message_p).pdusession_id = 10; /* first or default pdu session */
|
||||
NAS_PDU_SESSION_REQ(message_p).pdusession_type = 0x91;
|
||||
NAS_PDU_SESSION_REQ(message_p).pdusession_type = 0x91; // 0x91 = IPv4, 0x92 = IPv6, 0x93 = IPv4v6
|
||||
NAS_PDU_SESSION_REQ(message_p).sst = nas_allowed_nssai[nssai_idx].sst;
|
||||
NAS_PDU_SESSION_REQ(message_p).sd = nas_allowed_nssai[nssai_idx].sd;
|
||||
itti_send_msg_to_task(TASK_NAS_NRUE, instance, message_p);
|
||||
|
||||
Reference in New Issue
Block a user