diff --git a/ie/pfd-contents.go b/ie/pfd-contents.go index 2212b247..e336a358 100644 --- a/ie/pfd-contents.go +++ b/ie/pfd-contents.go @@ -112,7 +112,7 @@ func NewPFDContentsFields(fd, url, dn, cp, dnp string, afd, aurl, adnp []string) f.SetDNPFlag() } - if afd != nil { + if len(afd) > 0 { l := 0 for _, a := range afd { l += 2 + len([]byte(a)) @@ -123,7 +123,7 @@ func NewPFDContentsFields(fd, url, dn, cp, dnp string, afd, aurl, adnp []string) f.SetAFDFlag() } - if aurl != nil { + if len(aurl) > 0 { l := 0 for _, a := range aurl { l += 2 + len([]byte(a)) @@ -134,7 +134,7 @@ func NewPFDContentsFields(fd, url, dn, cp, dnp string, afd, aurl, adnp []string) f.SetAURLFlag() } - if adnp != nil { + if len(adnp) > 0 { l := 0 for _, a := range adnp { l += 2 + len([]byte(a)) @@ -240,7 +240,7 @@ func ParsePFDContentsFields(b []byte) (*PFDContentsFields, error) { // UnmarshalBinary parses b into IE. func (f *PFDContentsFields) UnmarshalBinary(b []byte) error { l := len(b) - if l < 3 { + if l < 2 { return io.ErrUnexpectedEOF } @@ -293,7 +293,7 @@ func (f *PFDContentsFields) UnmarshalBinary(b []byte) error { } if f.HasAFD() { - if len(b[offset:]) < offset+2+int(f.AFDLength) { + if len(b[offset:]) < 2+int(f.AFDLength) { return io.ErrUnexpectedEOF } f.AFDLength = binary.BigEndian.Uint16(b[offset : offset+2]) @@ -309,12 +309,13 @@ func (f *PFDContentsFields) UnmarshalBinary(b []byte) error { break } f.AdditionalFlowDescription = append(f.AdditionalFlowDescription, string(p[o+2:o+2+int(l)])) + o += 2 + int(l) } offset += 2 + int(f.AFDLength) } if f.HasAURL() { - if len(b[offset:]) < offset+2+int(f.AURLLength) { + if len(b[offset:]) < 2+int(f.AURLLength) { return io.ErrUnexpectedEOF } f.AURLLength = binary.BigEndian.Uint16(b[offset : offset+2]) @@ -330,12 +331,13 @@ func (f *PFDContentsFields) UnmarshalBinary(b []byte) error { break } f.AdditionalURL = append(f.AdditionalURL, string(p[o+2:o+2+int(l)])) + o += 2 + int(l) } offset += 2 + int(f.AURLLength) } if f.HasADNP() { - if len(b[offset:]) < offset+2+int(f.ADNPLength) { + if len(b[offset:]) < 2+int(f.ADNPLength) { return io.ErrUnexpectedEOF } f.ADNPLength = binary.BigEndian.Uint16(b[offset : offset+2]) @@ -351,6 +353,7 @@ func (f *PFDContentsFields) UnmarshalBinary(b []byte) error { break } f.AdditionalDomainNameAndProtocol = append(f.AdditionalDomainNameAndProtocol, string(p[o+2:o+2+int(l)])) + o += 2 + int(l) } } diff --git a/message/pfd-management-request_test.go b/message/pfd-management-request_test.go index 03a761b9..5ca497d3 100644 --- a/message/pfd-management-request_test.go +++ b/message/pfd-management-request_test.go @@ -16,6 +16,64 @@ import ( func TestPFDManagementRequest(t *testing.T) { cases := []testutil.TestCase{ { + Description: "Empty PFDContent", + Structured: message.NewPFDManagementRequest(seq, + ie.NewApplicationIDsPFDs( + ie.NewApplicationID("https://github.com/wmnsk/go-pfcp/"), + ie.NewPFDContext( + ie.NewPFDContents("", "", "", "", "", []string{}, []string{}, []string{}), + ), + ), + ), + Serialized: []byte{ + 0x20, 0x03, // Flag + MsgType: PFCP PFD Mgmt Req + 0x00, 0x37, // Msg Len + 0x11, 0x22, 0x33, 0x00, // Seq Num + 1 byte spare + 0x00, 0x3a, // IE type: Application ID's PFDs (58) + 0x00, 0x2f, // IE Len + // ApplicationID + 0x00, 0x18, // IE Type: Application ID + 0x00, 0x21, // IE Len + 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x6d, 0x6e, 0x73, 0x6b, 0x2f, 0x67, 0x6f, 0x2d, 0x70, 0x66, 0x63, 0x70, 0x2f, + // PFD Context + 0x00, 0x3b, // IE type: PFD Context + 0x00, 0x06, // IE Len + 0x00, 0x3d, // IE type: PFD Content + 0x00, 0x02, // IE Len + 0x00, 0x00, // Flag (0x00, no FD, no CP, no DN, ... nothing) + Spare + }, + }, { + Description: "Empty PFDContent + NodeID", + Structured: message.NewPFDManagementRequest(seq, + ie.NewApplicationIDsPFDs( + ie.NewApplicationID("te5t@pp"), + ie.NewPFDContext( + ie.NewPFDContents("", "", "", "", "", []string{}, []string{}, []string{}), + ), + ), + ie.NewNodeID("172.16.41.51", "", ""), + ), + Serialized: []byte{ + 0x20, 0x03, // Flag + MsgType: PFCP PFD Mgmt Req + 0x00, 0x26, // Msg Len + 0x11, 0x22, 0x33, 0x00, // Seq Num + 1 byte spare + 0x00, 0x3a, // IE type: Application ID's PFDs (58) + 0x00, 0x15, // IE Len + // ApplicationID + 0x00, 0x18, // IE Type: Application ID + 0x00, 0x07, // IE Len + 0x74, 0x65, 0x35, 0x74, 0x40, 0x70, 0x70, // te5t@pp + // PFD Context + 0x00, 0x3b, // IE type: PFD Context + 0x00, 0x06, // IE Len + 0x00, 0x3d, // IE type: PFD Content + 0x00, 0x02, // IE Len + 0x00, 0x00, // Flag (0x00, no FD, no CP, no DN, ... nothing) + Spare + 0x00, 0x3c, // IE Type: Node ID + 0x00, 0x05, 0x00, // IE Len + 1 byte spare + 0xac, 0x10, 0x29, 0x33, + }, + }, { Description: "Single IE", Structured: message.NewPFDManagementRequest(seq, ie.NewApplicationIDsPFDs( @@ -92,6 +150,59 @@ func TestPFDManagementRequest(t *testing.T) { 0x00, 0x08, 0x00, 0x02, 0x33, 0x33, 0x00, 0x02, 0x34, 0x34, // AURL 0x00, 0x08, 0x00, 0x02, 0x35, 0x35, 0x00, 0x02, 0x36, 0x36, // ADNP }, + }, { + Description: "PFDContent(FD + AFD) + NodeID", + Structured: message.NewPFDManagementRequest(seq, + ie.NewApplicationIDsPFDs( + ie.NewApplicationID("te5t@pp"), + ie.NewPFDContext( + ie.NewPFDContents("permit out ip from 172.16.61.0/24 to 10.62.0.7", + "", "", "", "", + []string{"permit in ip from 10.62.0.7 to 172.16.61.0/24"}, + []string{}, nil), + ), + ), + ie.NewNodeID("172.16.41.51", "", ""), + ), + Serialized: []byte{ + 0x20, 0x03, // Flag + MsgType: PFCP PFD Mgmt Req + 0x00, 0x87, // Len + 0x11, 0x22, 0x33, 0x00, // 3 bytes Seq number + 1 byte spare + 0x00, 0x3a, // IE type: Application ID's PFDs (58) + 0x00, 0x76, // IE Len + // Application ID + 0x00, 0x18, // IE type: Application ID + 0x00, 0x07, // IE Len + 0x74, 0x65, 0x35, 0x74, 0x40, 0x70, 0x70, // Application ID: te5t@pp + // PFD Context + 0x00, 0x3b, // IE type: PFD Context + 0x00, 0x67, // IE Len + // PFD Content + 0x00, 0x3d, // IE type: PFD Content + 0x00, 0x63, // IE Len + 0x21, 0x00, // Flag (Flow Desc 0x01 + Additional Flow Desc 0x20) + Spare + 0x00, 0x2e, // Len(Flow Description) + // Flow Description + 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x20, 0x6f, + 0x75, 0x74, 0x20, 0x69, 0x70, 0x20, 0x66, 0x72, + 0x6f, 0x6d, 0x20, 0x31, 0x37, 0x32, 0x2e, 0x31, + 0x36, 0x2e, 0x36, 0x31, 0x2e, 0x30, 0x2f, 0x32, + 0x34, 0x20, 0x74, 0x6f, 0x20, 0x31, 0x30, 0x2e, + 0x36, 0x32, 0x2e, 0x30, 0x2e, 0x37, + // Additional Flow Description + 0x00, 0x2f, // Len(Additional Flow Description) + 0x00, 0x2d, // Len(Flow Description) + 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x20, 0x69, + 0x6e, 0x20, 0x69, 0x70, 0x20, 0x66, 0x72, 0x6f, + 0x6d, 0x20, 0x31, 0x30, 0x2e, 0x36, 0x32, 0x2e, + 0x30, 0x2e, 0x37, 0x20, 0x74, 0x6f, 0x20, 0x31, + 0x37, 0x32, 0x2e, 0x31, 0x36, 0x2e, 0x36, 0x31, + 0x2e, 0x30, 0x2f, 0x32, 0x34, + // Node ID + 0x00, 0x3c, // IE Type: Node ID + 0x00, 0x05, 0x00, // IE Len + spare + 0xac, 0x10, 0x29, 0x33, // Node ID: 172.16.41.51 + }, }, }