sccp

package module
v1.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 5, 2025 License: MIT Imports: 10 Imported by: 0

README

go-sccp

Package sccp provides simple and painless handling of SCCP (Signaling Connection Control Part) in SS7/SIGTRAN stack, implemented in the Go Programming Language.

CI status golangci-lint Go Reference GitHub

Disclaimer

This is still an experimental project, and currently in its very early stage of development. Any part of implementations(including exported APIs) may be changed before released as v1.0.0.

Getting started

Run go mod tidy to download the dependency, and you're ready to start developing.

Supported Features

Message Types
Message type Abbreviation Reference Supported?
Connection request CR 4.2 -
Connection confirm CC 4.3 -
Connection refused CREF 4.4 -
Released RLSD 4.5 -
Release complete RLC 4.6 -
Data form 1 DT1 4.7 -
Data form 2 DT2 4.8 -
Data acknowledgement AK 4.9 -
Unitdata UDT 4.10 Yes
Unitdata service UDTS 4.11 -
Expedited data ED 4.12 -
Expedited data acknowledgement EA 4.13 -
Reset request RSR 4.14 -
Reset confirm RSC 4.15 -
Protocol data unit error ERR 4.16 -
Inactivity test IT 4.17 -
Extended unitdata XUDT 4.18 Yes
Extended unitdata service XUDTS 4.19 -
Long unitdata LUDT 4.20 -
Long unitdata service LUDTS 4.21 -
Parameters
Parameter name Reference Supported?
End of optional parameters 3.1 Yes
Destination local reference 3.2 Yes
Source local reference 3.3 Yes
Called party address 3.4 Yes
Calling party address 3.5 Yes
Protocol class 3.6 Yes
Segmenting/reassembling 3.7 Yes
Receive sequence number 3.8 Yes
Sequencing/segmenting 3.9 Yes
Credit 3.10 Yes
Release cause 3.11 Yes
Return cause 3.12 Yes
Reset cause 3.13 Yes
Error cause 3.14 Yes
Refusal cause 3.15 Yes
Data 3.16 Yes
Segmentation 3.17 Yes
Hop counter 3.18 Yes
Importance 3.19 Yes
Long data 3.20 Yes

Author(s)

Yoshiyuki Kurauchi (Website) and contributors.

LICENSE

MIT

Documentation

Overview

Package sccp provides encoding/decoding feature of Signalling Connection Control Part used in SS7/SIGTRAN protocol stack.

This is still an experimental project, and currently in its very early stage of development. Any part of implementations (including exported APIs) may be changed before released as v1.0.0.

Index

Constants

This section is empty.

Variables

View Source
var DefaultSSNStateManager = NewSSNStateManager()

Global state manager instance

Functions

func DisableLogging

func DisableLogging()

DisableLogging disables the logging from the package. Logging is enabled by default.

func EnableLogging

func EnableLogging(l *log.Logger)

EnableLogging enables the logging from the package. If l is nil, it uses default logger provided by the package. Logging is enabled by default.

See also: SetLogger.

func SetLogger

func SetLogger(l *log.Logger)

SetLogger replaces the standard logger with arbitrary *log.Logger.

This package prints just informational logs from goroutines working background that might help developers test the program but can be ignored safely. More important ones that needs any action by caller would be returned as errors.

Types

type BroadcastType

type BroadcastType uint8

Broadcast types

const (
	BroadcastSSA BroadcastType = 1 // Subsystem Allowed
	BroadcastSSP BroadcastType = 2 // Subsystem Prohibited
)

type Message

type Message interface {
	encoding.BinaryMarshaler
	encoding.BinaryUnmarshaler
	MarshalTo([]byte) error
	MarshalLen() int
	MessageType() MsgType
	MessageTypeName() string
	fmt.Stringer
}

Message is an interface that defines SCCP messages.

func ParseMessage

func ParseMessage(b []byte) (Message, error)

ParseMessage decodes the byte sequence into Message by Message Type.

type MsgType

type MsgType uint8

MsgType is type of SCCP message.

const (
	MsgTypeCR    MsgType // CR
	MsgTypeCC            // CC
	MsgTypeCREF          // CREF
	MsgTypeRLSD          // RLSD
	MsgTypeRLC           // RLC
	MsgTypeDT1           // DT1
	MsgTypeDT2           // DT2
	MsgTypeAK            // AK
	MsgTypeUDT           // UDT
	MsgTypeUDTS          // UDTS
	MsgTypeED            // ED
	MsgTypeEA            // EA
	MsgTypeRSR           // RSR
	MsgTypeRSC           // RSC
	MsgTypeERR           // ERR
	MsgTypeIT            // IT
	MsgTypeXUDT          // XUDT
	MsgTypeXUDTS         // XUDTS
	MsgTypeLUDT          // LUDT
	MsgTypeLUDTS         // LUDTS
)

Message Type definitions.

func (MsgType) String

func (i MsgType) String() string

type SCMG

type SCMG struct {
	Type                           SCMGType
	AffectedSSN                    uint8
	AffectedPC                     uint16
	SubsystemMultiplicityIndicator uint8
	SCCPCongestionLevel            uint8
}

SCMG represents a SCCP Management message (SCMG). Chapter 5.3/Q.713

func NewSCMG

func NewSCMG(typ SCMGType, assn uint8, apc uint16, smi uint8, scl uint8) *SCMG

NewSCMG creates a new SCMG.

func ParseSCMG

func ParseSCMG(b []byte) (*SCMG, error)

ParseSCMG decodes given byte sequence as a SCMG.

func (*SCMG) MarshalBinary

func (s *SCMG) MarshalBinary() ([]byte, error)

MarshalBinary returns the byte sequence generated from a SCMG instance.

func (*SCMG) MarshalLen

func (s *SCMG) MarshalLen() int

MarshalLen returns the serial length.

func (*SCMG) MarshalTo

func (s *SCMG) MarshalTo(b []byte) error

MarshalTo puts the byte sequence in the byte array given as b.

func (*SCMG) MessageType

func (s *SCMG) MessageType() SCMGType

MessageType returns the Message Type in int.

func (*SCMG) MessageTypeName

func (s *SCMG) MessageTypeName() string

MessageTypeName returns the Message Type in string.

func (*SCMG) String

func (s *SCMG) String() string

String returns the SCMG values in human readable format.

func (*SCMG) UnmarshalBinary

func (s *SCMG) UnmarshalBinary(b []byte) error

UnmarshalBinary sets the values retrieved from byte sequence in a SCMG.

type SCMGType

type SCMGType uint8

SCMGType is type of SCMG message.

const (
	SCMGTypeSSA SCMGType // SSA
	SCMGTypeSSP          // SSP
	SCMGTypeSST          // SST
	SCMGTypeSOR          // SOR
	SCMGTypeSOG          // SOG
	SCMGTypeSSC          // SSC
)

Table 23/Q.713

func (SCMGType) String

func (i SCMGType) String() string

type SSNEntry

type SSNEntry struct {
	SSN             uint8
	PointCode       uint16
	State           SSNState
	IsLocal         bool
	LastStateChange time.Time
	TestTimer       *time.Timer
	TestInterval    time.Duration
	TestRetries     int
	MaxTestRetries  int
	// contains filtered or unexported fields
}

SSNEntry represents a subsystem entry with state management

func (*SSNEntry) IsAllowed

func (s *SSNEntry) IsAllowed() bool

State check methods

func (*SSNEntry) IsProhibited

func (s *SSNEntry) IsProhibited() bool

func (*SSNEntry) MarkAllowed

func (s *SSNEntry) MarkAllowed()

func (*SSNEntry) MarkProhibited

func (s *SSNEntry) MarkProhibited()

type SSNState

type SSNState uint8

SSNState represents the state of a subsystem

const (
	SSNStateProhibited SSNState = 0 // Out of Service
	SSNStateAllowed    SSNState = 1 // In Service
)

type SSNStateManager

type SSNStateManager struct {

	// Configuration
	DefaultTestInterval time.Duration
	MaxTestInterval     time.Duration
	MaxTestRetries      int

	// Callbacks
	OnStateChange func(*SSNEntry, SSNState, StateChangeReason)
	OnBroadcast   func(BroadcastType, *SSNEntry)
	// contains filtered or unexported fields
}

SSNStateManager manages all subsystem states

func NewSSNStateManager

func NewSSNStateManager() *SSNStateManager

func (*SSNStateManager) AddEntry

func (sm *SSNStateManager) AddEntry(pc uint16, ssn uint8, isLocal bool) *SSNEntry

func (*SSNStateManager) GetEntry

func (sm *SSNStateManager) GetEntry(pc uint16, ssn uint8) *SSNEntry

func (*SSNStateManager) HandleSSA

func (sm *SSNStateManager) HandleSSA(pc uint16, ssn uint8) error

HandleSSA - Handle remote Subsystem Allowed message

func (*SSNStateManager) HandleSSP

func (sm *SSNStateManager) HandleSSP(pc uint16, ssn uint8) error

HandleSSP - Handle remote Subsystem Prohibited message

func (*SSNStateManager) HandleSST

func (sm *SSNStateManager) HandleSST(pc uint16, ssn uint8) error

HandleSST - Handle Subsystem Test message

func (*SSNStateManager) HandleUserInService

func (sm *SSNStateManager) HandleUserInService(pc uint16, ssn uint8) error

HandleUserInService - Handle N-STATE Request with UIS

func (*SSNStateManager) HandleUserOutOfService

func (sm *SSNStateManager) HandleUserOutOfService(pc uint16, ssn uint8) error

HandleUserOutOfService - Handle N-STATE Request with UOS

func (*SSNStateManager) ProcessSCMGMessage

func (sm *SSNStateManager) ProcessSCMGMessage(scmg *SCMG) error

ProcessSCMGMessage - Process incoming SCMG messages

type StateChangeReason

type StateChangeReason uint8

State change reasons

const (
	ReasonUserInitiated    StateChangeReason = 1
	ReasonNetworkInitiated StateChangeReason = 2
	ReasonTestTimeout      StateChangeReason = 3
	ReasonTestResponse     StateChangeReason = 4
)

type UDT

type UDT struct {
	Type                MsgType
	ProtocolClass       *params.ProtocolClass
	SLS                 uint8
	CalledPartyAddress  *params.PartyAddress
	CallingPartyAddress *params.PartyAddress
	Data                *params.Data
	// contains filtered or unexported fields
}

UDT represents a SCCP Message Unit Data (UDT).

func NewUDT

func NewUDT(pcls int, retOnErr bool, cdpa, cgpa *params.PartyAddress, data []byte) *UDT

Enhanced NewUDT with correct pointer calculation

func NewUDT(pcls int, retOnErr bool, cdpa, cgpa *params.PartyAddress, data []byte) (*UDT, error) {
	// ... validation code ...

	u := &UDT{
		Type:                MsgTypeUDT,
		ProtocolClass:       params.NewProtocolClass(pcls, retOnErr),
		SLS:                 0,
		CalledPartyAddress:  cdpa,
		CallingPartyAddress: cgpa,
		Data:                params.NewData(data),
	}

	// Use fixed 11-byte address lengths for pointer calculation
	u.ptr1 = 3  // Called Party starts after 3 pointer bytes
	u.ptr2 = 15 // 3 + 11 + 1 = 15 (Called + length byte)
	u.ptr3 = 27 // 15 + 11 + 1 = 27 (Calling + length byte)

	return u, nil
}

func (*UDT) CdAddress

func (u *UDT) CdAddress() string

func (*UDT) CdGT

func (u *UDT) CdGT() string

CdGT returns the GT in CalledPartyAddress in human readable string.

func (*UDT) CgAddress

func (u *UDT) CgAddress() string

func (*UDT) CgGT

func (u *UDT) CgGT() string

CgGT returns the GT in CalledPartyAddress in human readable string.

func (*UDT) GetProtocolClassInfo

func (u *UDT) GetProtocolClassInfo() (class int, hasReturnOption bool)

method to get protocol class info

func (*UDT) IsValidForProcessing

func (u *UDT) IsValidForProcessing() bool

check if UDT is valid for processing

func (*UDT) MarshalBinary

func (u *UDT) MarshalBinary() ([]byte, error)

NewUDT creates a new UDT. func NewUDT(pcls int, retOnErr bool, sls uint8, cdpa, cgpa *params.PartyAddress, data []byte) *UDT {

	//protocol class validation
	if pcls != 0 && pcls != 1 {
		logf("Invalid protocol class %d for UDT, only 0 and 1 are valid", pcls)
		return nil
	}

	// Validate addresses for routing
	if cdpa != nil && !cdpa.IsValidForRouting() {
		logf("Warning: Called Party Address may not be valid for %s routing", cdpa.GetRoutingType())
	}

	if cgpa != nil && !cgpa.IsValidForRouting() {
		logf("Warning: Calling Party Address may not be valid for %s routing", cgpa.GetRoutingType())
	}

	u := &UDT{
		Type: MsgTypeUDT,
		//ProtocolClass:       params.NewProtocolClass(pcls, retOnErr),
		//SLS:                 sls,
		CalledPartyAddress:  cdpa,
		CallingPartyAddress: cgpa,
		Data:                params.NewData(data),
	}

	// Validate protocol class
	if err := u.ValidateProtocolClass(); err != nil {
		logf("UDT validation failed: %v", err)
		return nil
	}

	u.ptr1 = 3
	u.ptr2 = u.ptr1 + uint8(cdpa.MarshalLen()) - 1
	u.ptr3 = u.ptr2 + uint8(cgpa.MarshalLen()) - 1

	return u
}
func NewUDT(pcls int, retOnErr bool, cdpa, cgpa *params.PartyAddress, data []byte) (*UDT, error) {
	// Validate protocol class
	if pcls != 0 && pcls != 1 {
		return nil, fmt.Errorf("invalid protocol class %d for UDT, only 0 and 1 are valid", pcls)
	}

	// Validate addresses and data
	if cdpa == nil {
		return nil, fmt.Errorf("called party address cannot be nil")
	}
	if cgpa == nil {
		return nil, fmt.Errorf("calling party address cannot be nil")
	}
	if data == nil {
		return nil, fmt.Errorf("data cannot be nil")
	}

	u := &UDT{
		Type:                MsgTypeUDT,
		ProtocolClass:       params.NewProtocolClass(pcls, retOnErr), // Include retOnErr
		CalledPartyAddress:  cdpa,
		CallingPartyAddress: cgpa,
		Data:                params.NewData(data),
	}

	// Calculate pointers
	u.ptr1 = 4
	cdpaLen := cdpa.MarshalLen()
	u.ptr2 = u.ptr1 + uint8(cdpaLen) + 1
	cgpaLen := cgpa.MarshalLen()
	u.ptr3 = u.ptr2 + uint8(cgpaLen) + 1

	fmt.Printf("Successfully created UDT: Class=%d, RetOnErr=%t, CalledLen=%d, CallingLen=%d, DataLen=%d\n",
		pcls, retOnErr, cdpaLen, cgpaLen, len(data))

	return u, nil
}

MarshalBinary returns the byte sequence generated from a UDT instance.

func (*UDT) MarshalLen

func (u *UDT) MarshalLen() int

Enhanced MarshalLen calculation

func (*UDT) MarshalTo

func (u *UDT) MarshalTo(b []byte) error

MarshalTo puts the byte sequence in the byte array given as b. SCCP is dependent on the Pointers when serializing, which means that it might fail when invalid Pointers are set. Enhanced MarshalTo function using library only

func (*UDT) MessageType

func (u *UDT) MessageType() MsgType

MessageType returns the Message Type in int.

func (*UDT) MessageTypeName

func (u *UDT) MessageTypeName() string

MessageTypeName returns the Message Type in string.

func (*UDT) String

func (u *UDT) String() string

MarshalLen returns the serial length.

func (u *UDT) MarshalLen() int {
	l := 6 // MsgType, ProtocolClass, pointers

	l += int(u.ptr3) - 1 // length without Data
	if param := u.Data; param != nil {
		l += param.MarshalLen()
	}

	return l
}
func (u *UDT) MarshalLen() int {
	l := 1 // Message Type
	l += 1 // Protocol Class - THIS WAS MISSING!
	l += 3 // Three pointer bytes

	// Called Party Address
	if u.CalledPartyAddress != nil {
		l += 1 + u.CalledPartyAddress.MarshalLen() // length byte + address
	} else {
		l += 1 // Just length byte (0)
	}

	// Calling Party Address
	if u.CallingPartyAddress != nil {
		l += 1 + u.CallingPartyAddress.MarshalLen() // length byte + address
	} else {
		l += 1 // Just length byte (0)
	}

	// Data
	if u.Data != nil {
		l += 1 + u.Data.MarshalLen() // length byte + data
	} else {
		l += 1 // Just length byte (0)
	}

	return l
}

String returns the UDT values in human readable format.

func (*UDT) UnmarshalBinary

func (u *UDT) UnmarshalBinary(b []byte) error

UnmarshalBinary sets the values retrieved from byte sequence in a SCCP UDT.

func (u *UDT) UnmarshalBinary(b []byte) error {
	l := len(b)
	if l <= 4 {
		return io.ErrUnexpectedEOF
	}

	u.Type = MsgType(b[0])

	// Start reading pointers from position 1 (no protocol class and SLS)
	offset := 1

	u.ptr1 = b[offset]
	u.ptr2 = b[offset+1]
	u.ptr3 = b[offset+2]

	// Calculate absolute positions - pointers are relative to the pointer section start
	ptrSectionStart := offset
	offsetPtr1 := ptrSectionStart + int(u.ptr1)
	offsetPtr2 := ptrSectionStart + int(u.ptr2)
	offsetPtr3 := ptrSectionStart + int(u.ptr3)

	if l < offsetPtr1+1 { // where CdPA starts
		return io.ErrUnexpectedEOF
	}
	if l < offsetPtr2+1 { // where CgPA starts
		return io.ErrUnexpectedEOF
	}
	if l < offsetPtr3+1 { // where u.Data starts
		return io.ErrUnexpectedEOF
	}

	cdpaEnd := offsetPtr1 + int(b[offsetPtr1]) + 1 // +1 is the data length included from the beginning
	if l < cdpaEnd {                               // where CdPA ends
		return io.ErrUnexpectedEOF
	}
	cgpaEnd := offsetPtr2 + int(b[offsetPtr2]) + 1
	if l < cgpaEnd { // where CgPA ends
		return io.ErrUnexpectedEOF
	}
	dataEnd := offsetPtr3 + int(b[offsetPtr3]) + 1
	if l < dataEnd { // where Data ends
		return io.ErrUnexpectedEOF
	}

	var err error
	u.CalledPartyAddress, _, err = params.ParseCalledPartyAddress(b[offsetPtr1:cdpaEnd])
	if err != nil {
		return err
	}

	u.CallingPartyAddress, _, err = params.ParseCallingPartyAddress(b[offsetPtr2:cgpaEnd])
	if err != nil {
		return err
	}

	u.Data = &params.Data{}
	if _, err = u.Data.Read(b[offsetPtr3:dataEnd]); err != nil {
		return err
	}

	return nil
}

func (*UDT) ValidateProtocolClass

func (u *UDT) ValidateProtocolClass() error

protocol class validation for UDT

type UnsupportedTypeError

type UnsupportedTypeError uint8

UnsupportedTypeError indicates the value in Version field is invalid.

func (UnsupportedTypeError) Error

func (e UnsupportedTypeError) Error() string

Error returns the type of receiver and some additional message.

type XUDT

type XUDT struct {
	Type                    MsgType
	ProtocolClass           *params.ProtocolClass
	HopCounter              *params.HopCounter
	CalledPartyAddress      *params.PartyAddress
	CallingPartyAddress     *params.PartyAddress
	Data                    *params.Data
	Segmentation            *params.Segmentation
	Importance              *params.Importance
	EndOfOptionalParameters *params.EndOfOptionalParameters
	// contains filtered or unexported fields
}

XUDT represents a SCCP Message Extended unitdata (XUDT).

func NewXUDT

func NewXUDT(pcls int, retOnErr bool, hc uint8, cdpa, cgpa *params.PartyAddress, data []byte, opts ...params.Parameter) *XUDT

NewXUDT creates a new XUDT.

func ParseXUDT

func ParseXUDT(b []byte) (*XUDT, error)

ParseXUDT decodes given byte sequence as a SCCP XUDT.

func (*XUDT) CdGT

func (x *XUDT) CdGT() string

CdGT returns the GT in CalledPartyAddress in human readable string.

func (*XUDT) CgGT

func (x *XUDT) CgGT() string

CgGT returns the GT in CalledPartyAddress in human readable string.

func (*XUDT) MarshalBinary

func (x *XUDT) MarshalBinary() ([]byte, error)

MarshalBinary returns the byte sequence generated from a XUDT instance.

func (*XUDT) MarshalLen

func (x *XUDT) MarshalLen() int

MarshalLen returns the serial length.

func (*XUDT) MarshalTo

func (x *XUDT) MarshalTo(b []byte) error

MarshalTo puts the byte sequence in the byte array given as b. SCCP is dependent on the Pointers when serializing, which means that it might fail when invalid Pointers are set.

func (*XUDT) MessageType

func (x *XUDT) MessageType() MsgType

MessageType returns the Message Type in int.

func (*XUDT) MessageTypeName

func (x *XUDT) MessageTypeName() string

MessageTypeName returns the Message Type in string.

func (*XUDT) String

func (x *XUDT) String() string

String returns the XUDT values in human readable format.

func (*XUDT) UnmarshalBinary

func (x *XUDT) UnmarshalBinary(b []byte) error

UnmarshalBinary sets the values retrieved from byte sequence in a SCCP XUDT.

Directories

Path Synopsis
examples
client command
Command client sends given payload on top of SCCP UDT message.
Command client sends given payload on top of SCCP UDT message.
server command
Command receiver receives SCCP messages from the client and prints them out.
Command receiver receives SCCP messages from the client and prints them out.
Package utils provides some utilities which might be useful specifically for GTP(or other telco protocols).
Package utils provides some utilities which might be useful specifically for GTP(or other telco protocols).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL