Skip to content

Commit

Permalink
Fix issues (#7)
Browse files Browse the repository at this point in the history
* feat(n3iwf): Refactor folder structure

* Allow AMF selected by SelectedPLMNIdentity

* Return EAP Failure if no avaliabe AMF after selection

* Remove PDUSessionResourceListCxtRelCpl IE for UEContextReleaseComplete if no ue.pdu is available

* Fix sending wrong message type (InitialUEMessage istead of UplinkNASTransport) when UE send AN Parameters

* Fix wrong inner ipsec address format

* Use NAS envelop for nas messages sent through TCP

* Fix misplaced SPIs when CREATE_CHILD_SA exchange and forward pduSessionEstablishmentAccept to UE

* Make paired child SAs have different SPIs and adapt to message ID of landslide

* Refactor code using the new function encapNasMsgToEnvelope and decapNasMsgFromEnvelope

* Separate IKE SA Message ID of initiator and responder

* Modify IPsec SA info output format

Co-authored-by: sophiatseng <[email protected]>
  • Loading branch information
yt8956gh and sophiatseng authored Mar 2, 2022
1 parent c856d5f commit 4a7f68e
Show file tree
Hide file tree
Showing 36 changed files with 437 additions and 175 deletions.
File renamed without changes.
8 changes: 4 additions & 4 deletions gtp/handler/handler.go → internal/gtp/handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import (
gtp "github.com/wmnsk/go-gtp/gtpv1"
gtpMsg "github.com/wmnsk/go-gtp/gtpv1/message"

n3iwfContext "github.com/free5gc/n3iwf/context"
"github.com/free5gc/n3iwf/gre"
gtpQoSMsg "github.com/free5gc/n3iwf/gtp/message"
"github.com/free5gc/n3iwf/logger"
"github.com/free5gc/n3iwf/internal/gre"
gtpQoSMsg "github.com/free5gc/n3iwf/internal/gtp/message"
"github.com/free5gc/n3iwf/internal/logger"
n3iwfContext "github.com/free5gc/n3iwf/pkg/context"
)

var gtpLog *logrus.Entry
Expand Down
2 changes: 1 addition & 1 deletion gtp/message/message.go → internal/gtp/message/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (

gtpMessage "github.com/wmnsk/go-gtp/gtpv1/message"

"github.com/free5gc/n3iwf/logger"
"github.com/free5gc/n3iwf/internal/logger"
)

// [TS 38.415] 5.5.2 Frame format for the PDU Session user plane protocol
Expand Down
6 changes: 3 additions & 3 deletions gtp/service/service.go → internal/gtp/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
gtp "github.com/wmnsk/go-gtp/gtpv1"
gtpMsg "github.com/wmnsk/go-gtp/gtpv1/message"

n3iwfContext "github.com/free5gc/n3iwf/context"
"github.com/free5gc/n3iwf/gtp/handler"
"github.com/free5gc/n3iwf/logger"
"github.com/free5gc/n3iwf/internal/gtp/handler"
"github.com/free5gc/n3iwf/internal/logger"
n3iwfContext "github.com/free5gc/n3iwf/pkg/context"
)

var gtpLog *logrus.Entry
Expand Down
File renamed without changes.
6 changes: 3 additions & 3 deletions ngap/dispatcher.go → internal/ngap/dispatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"git.cs.nctu.edu.tw/calee/sctp"
"github.com/sirupsen/logrus"

"github.com/free5gc/n3iwf/context"
"github.com/free5gc/n3iwf/logger"
"github.com/free5gc/n3iwf/ngap/handler"
"github.com/free5gc/n3iwf/internal/logger"
"github.com/free5gc/n3iwf/internal/ngap/handler"
"github.com/free5gc/n3iwf/pkg/context"
"github.com/free5gc/ngap"
"github.com/free5gc/ngap/ngapType"
)
Expand Down
87 changes: 63 additions & 24 deletions ngap/handler/handler.go → internal/ngap/handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import (
"github.com/sirupsen/logrus"

"github.com/free5gc/aper"
"github.com/free5gc/n3iwf/context"
gtp_service "github.com/free5gc/n3iwf/gtp/service"
"github.com/free5gc/n3iwf/ike/handler"
ike_message "github.com/free5gc/n3iwf/ike/message"
"github.com/free5gc/n3iwf/logger"
ngap_message "github.com/free5gc/n3iwf/ngap/message"
gtp_service "github.com/free5gc/n3iwf/internal/gtp/service"
"github.com/free5gc/n3iwf/internal/logger"
ngap_message "github.com/free5gc/n3iwf/internal/ngap/message"
"github.com/free5gc/n3iwf/pkg/context"
"github.com/free5gc/n3iwf/pkg/ike/handler"
ike_message "github.com/free5gc/n3iwf/pkg/ike/message"
"github.com/free5gc/ngap/ngapConvert"
"github.com/free5gc/ngap/ngapType"
)
Expand Down Expand Up @@ -711,7 +711,7 @@ func HandleInitialContextSetupRequest(amf *context.N3IWFAMF, message *ngapType.N
// Build IKE message
responseIKEMessage.BuildIKEHeader(ikeSecurityAssociation.RemoteSPI,
ikeSecurityAssociation.LocalSPI, ike_message.IKE_AUTH, ike_message.ResponseBitCheck,
ikeSecurityAssociation.MessageID)
ikeSecurityAssociation.InitiatorMessageID)
responseIKEMessage.Payloads.Reset()

// EAP Success
Expand Down Expand Up @@ -839,7 +839,7 @@ func handlePDUSessionResourceSetupRequestTransfer(ue *context.N3IWFUe, pduSessio
return false, responseTransfer
}
} else {
pduSession.SecurityIntegrity = false
pduSession.SecurityIntegrity = true
pduSession.SecurityCipher = true
}

Expand Down Expand Up @@ -1159,6 +1159,18 @@ func HandleUEContextReleaseCommand(amf *context.N3IWFAMF, message *ngapType.NGAP
ngap_message.SendUEContextReleaseComplete(amf, n3iwfUe, nil)
}

func encapNasMsgToEnvelope(nasPDU *ngapType.NASPDU) []byte {
// According to TS 24.502 8.2.4,
// in order to transport a NAS message over the non-3GPP access between the UE and the N3IWF,
// the NAS message shall be framed in a NAS message envelope as defined in subclause 9.4.
// According to TS 24.502 9.4,
// a NAS message envelope = Length | NAS Message
nasEnv := make([]byte, 2)
binary.BigEndian.PutUint16(nasEnv, uint16(len(nasPDU.Value)))
nasEnv = append(nasEnv, nasPDU.Value...)
return nasEnv
}

func HandleDownlinkNASTransport(amf *context.N3IWFAMF, message *ngapType.NGAPPDU) {
ngapLog.Infoln("[N3IWF] Handle Downlink NAS Transport")

Expand Down Expand Up @@ -1283,7 +1295,7 @@ func HandleDownlinkNASTransport(amf *context.N3IWFAMF, message *ngapType.NGAPPDU

if nasPDU != nil {
// TODO: Send NAS PDU to UE
if n3iwfUe.N3IWFChildSecurityAssociation == nil {
if !n3iwfUe.SignallingIPsecSAEstablished {
var identifier uint8
ikeSecurityAssociation := n3iwfUe.N3IWFIKESecurityAssociation

Expand All @@ -1301,7 +1313,7 @@ func HandleDownlinkNASTransport(amf *context.N3IWFAMF, message *ngapType.NGAPPDU
// Build IKE message
responseIKEMessage.BuildIKEHeader(ikeSecurityAssociation.RemoteSPI,
ikeSecurityAssociation.LocalSPI, ike_message.IKE_AUTH, ike_message.ResponseBitCheck,
ikeSecurityAssociation.MessageID)
ikeSecurityAssociation.InitiatorMessageID)
responseIKEMessage.Payloads.Reset()

// EAP-5G
Expand All @@ -1317,14 +1329,18 @@ func HandleDownlinkNASTransport(amf *context.N3IWFAMF, message *ngapType.NGAPPDU
handler.SendIKEMessageToUE(n3iwfUe.IKEConnection.Conn, n3iwfUe.IKEConnection.N3IWFAddr,
n3iwfUe.IKEConnection.UEAddr, responseIKEMessage)
} else {
// Using a "NAS message envelope" to transport a NAS message
// over the non-3GPP access between the UE and the N3IWF
nasEnv := encapNasMsgToEnvelope(nasPDU)

// Check ue.TCPConnection. If failed, retry 2 times.
maxRetryTimes := 3
for i := 0; i < maxRetryTimes; i++ {
if n3iwfUe.TCPConnection == nil {
if i == (maxRetryTimes - 1) {
ngapLog.Warn(
"No connection found for UE to send NAS message. This message will be cached in N3IWF")
n3iwfUe.TemporaryCachedNASMessage = nasPDU.Value
n3iwfUe.TemporaryCachedNASMessage = nasEnv
return
} else {
ngapLog.Warn("No NAS signalling session found, retry...")
Expand All @@ -1336,7 +1352,7 @@ func HandleDownlinkNASTransport(amf *context.N3IWFAMF, message *ngapType.NGAPPDU
}

// Send to UE
if n, err := n3iwfUe.TCPConnection.Write(nasPDU.Value); err != nil {
if n, err := n3iwfUe.TCPConnection.Write(nasEnv); err != nil {
ngapLog.Errorf("Writing via IPSec signalling SA failed: %+v", err)
} else {
ngapLog.Trace("Forward NWu <- N2")
Expand All @@ -1359,6 +1375,7 @@ func HandlePDUSessionResourceSetupRequest(amf *context.N3IWFAMF, message *ngapTy
var nasPDU *ngapType.NASPDU
var pduSessionResourceSetupListSUReq *ngapType.PDUSessionResourceSetupListSUReq
var iesCriticalityDiagnostics ngapType.CriticalityDiagnosticsIEList
var pduSessionEstablishmentAccept *ngapType.NASPDU

var n3iwfUe *context.N3IWFUe
n3iwfSelf := context.N3IWFSelf()
Expand Down Expand Up @@ -1445,7 +1462,11 @@ func HandlePDUSessionResourceSetupRequest(amf *context.N3IWFAMF, message *ngapTy
ngapLog.Error("No IPSec NAS signalling SA for this UE")
return
} else {
if n, err := n3iwfUe.TCPConnection.Write(nasPDU.Value); err != nil {
// Using a "NAS message envelope" to transport a NAS message
// over the non-3GPP access between the UE and the N3IWF
nasEnv := encapNasMsgToEnvelope(nasPDU)

if n, err := n3iwfUe.TCPConnection.Write(nasEnv); err != nil {
ngapLog.Errorf("Send NAS to UE failed: %+v", err)
return
} else {
Expand All @@ -1467,8 +1488,7 @@ func HandlePDUSessionResourceSetupRequest(amf *context.N3IWFAMF, message *ngapTy

for _, item := range pduSessionResourceSetupListSUReq.List {
pduSessionID := item.PDUSessionID.Value
// TODO: send NAS to UE
// pduSessionNasPdu := item.NASPDU
pduSessionEstablishmentAccept = item.PDUSessionNASPDU
snssai := item.SNSSAI

transfer := ngapType.PDUSessionResourceSetupRequestTransfer{}
Expand Down Expand Up @@ -1513,18 +1533,17 @@ func HandlePDUSessionResourceSetupRequest(amf *context.N3IWFAMF, message *ngapTy

ikeSecurityAssociation := n3iwfUe.N3IWFIKESecurityAssociation

// Add MessageID for IKE security association
ikeSecurityAssociation.MessageID++

// Send CREATE_CHILD_SA to UE
ikeMessage := new(ike_message.IKEMessage)
var ikePayload ike_message.IKEPayloadContainer

// Build IKE message
ikeMessage.BuildIKEHeader(ikeSecurityAssociation.LocalSPI,
ikeSecurityAssociation.RemoteSPI, ike_message.CREATE_CHILD_SA,
ike_message.InitiatorBitCheck, ikeSecurityAssociation.MessageID)
ikeMessage.BuildIKEHeader(ikeSecurityAssociation.RemoteSPI,
ikeSecurityAssociation.LocalSPI, ike_message.CREATE_CHILD_SA,
0, ikeSecurityAssociation.ResponderMessageID)
ikeMessage.Payloads.Reset()
// Add MessageID for IKE security association
ikeSecurityAssociation.ResponderMessageID++

// Build SA
requestSA := ikePayload.BuildSecurityAssociation()
Expand Down Expand Up @@ -1554,10 +1573,18 @@ func HandlePDUSessionResourceSetupRequest(amf *context.N3IWFAMF, message *ngapTy
proposal.IntegrityAlgorithm.BuildTransform(
ike_message.TypeIntegrityAlgorithm, ike_message.AUTH_HMAC_SHA1_96, nil, nil, nil)
}

// RFC 7296
// Diffie-Hellman transform is optional in CREATE_CHILD_SA
// proposal.DiffieHellmanGroup.BuildTransform(
// ike_message.TypeDiffieHellmanGroup, ike_message.DH_1024_BIT_MODP, nil, nil, nil)

// ESN transform
proposal.ExtendedSequenceNumbers.BuildTransform(
ike_message.TypeExtendedSequenceNumbers, ike_message.ESN_NO, nil, nil, nil)

n3iwfUe.CreateHalfChildSA(ikeMessage.MessageID, spi)

// Build Nonce
nonceData := handler.GenerateRandomNumber().Bytes()
ikePayload.BuildNonce(nonceData)
Expand All @@ -1571,6 +1598,7 @@ func HandlePDUSessionResourceSetupRequest(amf *context.N3IWFAMF, message *ngapTy
tsi.TrafficSelectors.BuildIndividualTrafficSelector(
ike_message.TS_IPV4_ADDR_RANGE, ike_message.IPProtocolAll,
0, 65535, n3iwfIPAddr.To4(), n3iwfIPAddr.To4())

// TSr
ueIPAddr := n3iwfUe.IPSecInnerIP
tsr := ikePayload.BuildTrafficSelectorResponder()
Expand All @@ -1589,13 +1617,15 @@ func HandlePDUSessionResourceSetupRequest(amf *context.N3IWFAMF, message *ngapTy
ngapLog.Errorf("Encrypting IKE message failed: %+v", err)
n3iwfUe.TemporaryPDUSessionSetupData.UnactivatedPDUSession =
n3iwfUe.TemporaryPDUSessionSetupData.UnactivatedPDUSession[1:]
cause := buildCause(ngapType.CausePresentTransport, ngapType.CauseTransportPresentTransportResourceUnavailable)
cause := buildCause(ngapType.CausePresentTransport,
ngapType.CauseTransportPresentTransportResourceUnavailable)
transfer, err := ngap_message.BuildPDUSessionResourceSetupUnsuccessfulTransfer(*cause, nil)
if err != nil {
ngapLog.Errorf("Build PDU Session Resource Setup Unsuccessful Transfer Failed: %+v", err)
continue
}
ngap_message.AppendPDUSessionResourceFailedToSetupListSURes(n3iwfUe.TemporaryPDUSessionSetupData.FailedListSURes,
ngap_message.AppendPDUSessionResourceFailedToSetupListSURes(
n3iwfUe.TemporaryPDUSessionSetupData.FailedListSURes,
pduSessionID, transfer)
continue
}
Expand All @@ -1606,10 +1636,19 @@ func HandlePDUSessionResourceSetupRequest(amf *context.N3IWFAMF, message *ngapTy
} else {
// Send PDU Session Resource Setup Response to AMF
ngap_message.SendPDUSessionResourceSetupResponse(amf, n3iwfUe,
n3iwfUe.TemporaryPDUSessionSetupData.SetupListSURes, n3iwfUe.TemporaryPDUSessionSetupData.FailedListSURes, nil)
n3iwfUe.TemporaryPDUSessionSetupData.SetupListSURes,
n3iwfUe.TemporaryPDUSessionSetupData.FailedListSURes, nil)
break
}
}

// TS 23.501 4.12.5 Requested PDU Session Establishment via Untrusted non-3GPP Access
// After all IPsec Child SAs are established, the N3IWF shall forward to UE via the signalling IPsec SA
// the PDU Session Establishment Accept message
nasEnv := encapNasMsgToEnvelope(pduSessionEstablishmentAccept)

// Cache the pduSessionEstablishmentAccept and forward to the UE after all CREATE_CHILD_SAs finish
n3iwfUe.TemporaryCachedNASMessage = nasEnv
}
}

Expand Down
38 changes: 20 additions & 18 deletions ngap/message/build.go → internal/ngap/message/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import (
"encoding/hex"

"github.com/free5gc/aper"
"github.com/free5gc/n3iwf/context"
"github.com/free5gc/n3iwf/logger"
"github.com/free5gc/n3iwf/util"
"github.com/free5gc/n3iwf/internal/logger"
"github.com/free5gc/n3iwf/internal/util"
"github.com/free5gc/n3iwf/pkg/context"
"github.com/free5gc/ngap"
"github.com/free5gc/ngap/ngapConvert"
"github.com/free5gc/ngap/ngapType"
Expand Down Expand Up @@ -544,24 +544,26 @@ func BuildUEContextReleaseComplete(ue *context.N3IWFUe,

uEContextReleaseCompleteIEs.List = append(uEContextReleaseCompleteIEs.List, ie)

// PDU Session Resource List
ie = ngapType.UEContextReleaseCompleteIEs{}
ie.Id.Value = ngapType.ProtocolIEIDPDUSessionResourceListCxtRelCpl
ie.Criticality.Value = ngapType.CriticalityPresentReject
ie.Value.Present = ngapType.UEContextReleaseCompleteIEsPresentPDUSessionResourceListCxtRelCpl
ie.Value.PDUSessionResourceListCxtRelCpl = new(ngapType.PDUSessionResourceListCxtRelCpl)
// PDU Session Resource List (optional)
if len(ue.PduSessionList) > 0 {
ie = ngapType.UEContextReleaseCompleteIEs{}
ie.Id.Value = ngapType.ProtocolIEIDPDUSessionResourceListCxtRelCpl
ie.Criticality.Value = ngapType.CriticalityPresentReject
ie.Value.Present = ngapType.UEContextReleaseCompleteIEsPresentPDUSessionResourceListCxtRelCpl
ie.Value.PDUSessionResourceListCxtRelCpl = new(ngapType.PDUSessionResourceListCxtRelCpl)

pDUSessionResourceListCxtRelCpl := ie.Value.PDUSessionResourceListCxtRelCpl
pDUSessionResourceListCxtRelCpl := ie.Value.PDUSessionResourceListCxtRelCpl

// PDU Session Resource Item (in PDU Session Resource List)
for _, pduSession := range ue.PduSessionList {
pDUSessionResourceItemCxtRelCpl := ngapType.PDUSessionResourceItemCxtRelCpl{}
pDUSessionResourceItemCxtRelCpl.PDUSessionID.Value = pduSession.Id
pDUSessionResourceListCxtRelCpl.List =
append(pDUSessionResourceListCxtRelCpl.List, pDUSessionResourceItemCxtRelCpl)
}
// PDU Session Resource Item (in PDU Session Resource List)
for _, pduSession := range ue.PduSessionList {
pDUSessionResourceItemCxtRelCpl := ngapType.PDUSessionResourceItemCxtRelCpl{}
pDUSessionResourceItemCxtRelCpl.PDUSessionID.Value = pduSession.Id
pDUSessionResourceListCxtRelCpl.List =
append(pDUSessionResourceListCxtRelCpl.List, pDUSessionResourceItemCxtRelCpl)
}

uEContextReleaseCompleteIEs.List = append(uEContextReleaseCompleteIEs.List, ie)
uEContextReleaseCompleteIEs.List = append(uEContextReleaseCompleteIEs.List, ie)
}

// Criticality Diagnostics (optional)
if criticalityDiagnostics != nil {
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions ngap/message/send.go → internal/ngap/message/send.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import (
"git.cs.nctu.edu.tw/calee/sctp"
"github.com/sirupsen/logrus"

"github.com/free5gc/n3iwf/context"
"github.com/free5gc/n3iwf/logger"
"github.com/free5gc/n3iwf/internal/logger"
"github.com/free5gc/n3iwf/pkg/context"
"github.com/free5gc/ngap/ngapType"
)

Expand Down
8 changes: 4 additions & 4 deletions ngap/service/service.go → internal/ngap/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import (
"git.cs.nctu.edu.tw/calee/sctp"
"github.com/sirupsen/logrus"

"github.com/free5gc/n3iwf/context"
"github.com/free5gc/n3iwf/logger"
"github.com/free5gc/n3iwf/ngap"
"github.com/free5gc/n3iwf/ngap/message"
"github.com/free5gc/n3iwf/internal/logger"
"github.com/free5gc/n3iwf/internal/ngap"
"github.com/free5gc/n3iwf/internal/ngap/message"
"github.com/free5gc/n3iwf/pkg/context"
lib_ngap "github.com/free5gc/ngap"
)

Expand Down
Loading

0 comments on commit 4a7f68e

Please sign in to comment.