Commit 659a8199 authored by Robert Schmidt's avatar Robert Schmidt

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.
parent d0f32d8a
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment