Advertisement
Borik

Untitled

Apr 21st, 2025
395
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 11.53 KB | None | 0 0
  1. package libnas
  2.  
  3. import (
  4.     "encoding/binary"
  5.     "errors"
  6.     "fmt"
  7.     "log"
  8.     "reflect"
  9.     "strconv"
  10. )
  11.  
  12. // TNasMsg
  13. // all implementations should be a pointer to type
  14. type TNasMsg interface {
  15.     Unmarshal(pdu []byte) (res TNasMsg, err error)
  16. }
  17.  
  18. type TNasMsgIE interface {
  19.     Value() []byte
  20.     Set(any)
  21. }
  22.  
  23. func (pdu *TNAS) UnmarshalNasPdu() (res TNasMsg, err error) {
  24.     t, err := pdu.Type()
  25.     if err != nil {
  26.         return
  27.     }
  28.     switch pdu.PD() {
  29.     case PROTOCOL_DISCRIMINATOR_EPS_MOBILITY_MANAGEMENT_MESSAGES:
  30.         switch t {
  31.         case NAS_EMM_MESSAGE_TYPE_ATTACH_ACCEPT:
  32.             return (&TEmmAttachAccept{}).Unmarshal(pdu.decodedMsg.msg)
  33.         case NAS_EMM_MESSAGE_TYPE_ATTACH_REQUEST:
  34.             return (&TEmmAttachRequest{}).Unmarshal(pdu.decodedMsg.msg)
  35.         case NAS_EMM_MESSAGE_TYPE_SECURITY_MODE_COMMAND:
  36.             return (&TEmmSecurityModeCommand{}).Unmarshal(pdu.decodedMsg.msg)
  37.         case NAS_EMM_MESSAGE_TYPE_SECURITY_MODE_COMPLETE:
  38.             return (&tEmmSecurityModeComplete{}).Unmarshal(pdu.decodedMsg.msg)
  39.         case NAS_EMM_MESSAGE_TYPE_AUTHENTICATION_RESPONSE:
  40.             return (&TEmmAuthenticationResponse{}).Unmarshal(pdu.decodedMsg.msg)
  41.         default:
  42.             return nil, errors.New("not supported")
  43.         }
  44.     case PROTOCOL_DISCRIMINATOR_EPS_SESSION_MANAGEMENT_MESSAGES:
  45.         switch t {
  46.         case NAS_ESM_MESSAGE_TYPE_ESM_INFORMATION_RESPONSE:
  47.             return (&TEsmInformationResponse{}).Unmarshal(pdu.decodedMsg.msg)
  48.         case NAS_ESM_MESSAGE_TYPE_ESM_INFORMATION_REQUEST:
  49.             return (&TEsmInformationRequest{}).Unmarshal(pdu.decodedMsg.msg)
  50.         case NAS_ESM_MESSAGE_TYPE_PDN_CONNECTIVITY_REQUEST:
  51.             return (&TEsmPdnConnectivityRequest{}).Unmarshal(pdu.decodedMsg.msg)
  52.         case NAS_ESM_MESSAGE_TYPE_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST:
  53.             return (&TEsmActivateDefaultEpsBearerContextRequest{}).Unmarshal(pdu.decodedMsg.msg)
  54.         default:
  55.             return nil, errors.New("not supported")
  56.         }
  57.     default:
  58.         return nil, errors.New("not supported")
  59.     }
  60. }
  61.  
  62. func MarshalNasPdu(msg TNasMsg) (res []byte, err error) {
  63.     sMsg := reflect.ValueOf(msg)
  64.     tMsg := sMsg.Type()
  65.     if tMsg.Kind() == reflect.Pointer {
  66.         tMsg = tMsg.Elem()
  67.         sMsg = reflect.ValueOf(msg).Elem()
  68.     }
  69.     for i := 0; i < sMsg.NumField(); i++ {
  70.         ieV := sMsg.Field(i)
  71.         var complVal bool
  72.         if ieV.Type().Implements(reflect.TypeOf((*TNasMsgIE)(nil)).Elem()) {
  73.             ieV = ieV.MethodByName("Value").Call([]reflect.Value{})[0]
  74.             complVal = true
  75.         } else if ieV.CanAddr() && ieV.Addr().Type().Implements(reflect.TypeOf((*TNasMsgIE)(nil)).Elem()) {
  76.             ieV = ieV.Addr().MethodByName("Value").Call([]reflect.Value{})[0]
  77.             complVal = true
  78.         }
  79.         var vRes []byte
  80.         ieT := tMsg.Field(i).Tag.Get("nas_ie_type")
  81.         switch ieT {
  82.         case "V":
  83.             ieL := tMsg.Field(i).Tag.Get("nas_ie_length")
  84.             if ieL == "1/2" {
  85.                 ieP := tMsg.Field(i).Tag.Get("nas_ie_position")
  86.                 if ieP == "LSB" {
  87.                     vRes = []byte{byte(ieV.Uint())}
  88.                 } else if ieP == "MSB" {
  89.                     // todo implement here complex types
  90.                     res[len(res)-1] = (res[len(res)-1] & 0x0f) | byte(ieV.Uint()<<4)
  91.                     continue
  92.                 }
  93.             } else {
  94.                 var l int
  95.                 l, err = strconv.Atoi(ieL)
  96.                 if err != nil {
  97.                     return nil, err
  98.                 }
  99.                 vRes = make([]byte, l)
  100.                 if l == 1 {
  101.                     vRes[0] = byte(ieV.Uint())
  102.                 } else {
  103.                     copy(vRes, ieV.Bytes()[:l])
  104.                 }
  105.             }
  106.         case "LV":
  107.             l := byte(len(ieV.Bytes()))
  108.             vRes = append(vRes, l)
  109.             vRes = append(vRes, ieV.Bytes()...)
  110.         case "LVE":
  111.             l := uint16(len(ieV.Bytes()))
  112.             la := make([]byte, 2)
  113.             _, _ = binary.Encode(la, binary.BigEndian, l)
  114.             vRes = append(vRes, la...)
  115.             vRes = append(vRes, ieV.Bytes()...)
  116.         case "T":
  117.             if ieV.IsNil() {
  118.                 continue
  119.             }
  120.             var iei int64
  121.             iei, err = strconv.ParseInt(tMsg.Field(i).Tag.Get("nas_iei"), 0, 8)
  122.             if err != nil {
  123.                 return nil, err
  124.             }
  125.             vRes = append(vRes, byte(iei))
  126.         case "TV":
  127.             if ieV.IsNil() {
  128.                 continue
  129.             }
  130.             ieL := tMsg.Field(i).Tag.Get("nas_ie_length")
  131.             var l int
  132.             l, err = strconv.Atoi(ieL)
  133.             if err != nil {
  134.                 return nil, err
  135.             }
  136.             var iei int64
  137.             iei, err = strconv.ParseInt(tMsg.Field(i).Tag.Get("nas_iei"), 0, 8)
  138.             if err != nil {
  139.                 return nil, err
  140.             }
  141.             var _ieV reflect.Value
  142.             if complVal {
  143.                 _ieV = ieV
  144.             } else {
  145.                 _ieV = ieV.Elem()
  146.             }
  147.             if l == 1 {
  148.                 vRes = append(vRes, _ieV.Bytes()[0]|byte(iei)<<4)
  149.             } else {
  150.                 l-- // skip ie identifier - it is one byte always
  151.                 vRes = append(vRes, byte(iei))
  152.                 vRes = append(vRes, _ieV.Bytes()[:l]...)
  153.             }
  154.         case "TLV":
  155.             if ieV.IsNil() {
  156.                 continue
  157.             }
  158.             var iei int64
  159.             iei, err = strconv.ParseInt(tMsg.Field(i).Tag.Get("nas_iei"), 0, 8)
  160.             if err != nil {
  161.                 return nil, err
  162.             }
  163.             var _ieV reflect.Value
  164.             if complVal {
  165.                 _ieV = ieV
  166.             } else {
  167.                 _ieV = ieV.Elem()
  168.             }
  169.             l := byte(len(_ieV.Bytes()))
  170.             vRes = append(vRes, byte(iei))
  171.             vRes = append(vRes, l)
  172.             vRes = append(vRes, _ieV.Bytes()[:l]...)
  173.         case "TLVE":
  174.             if ieV.IsNil() {
  175.                 continue
  176.             }
  177.             var iei int64
  178.             iei, err = strconv.ParseInt(tMsg.Field(i).Tag.Get("nas_iei"), 0, 8)
  179.             if err != nil {
  180.                 return nil, err
  181.             }
  182.             var _ieV reflect.Value
  183.             if complVal {
  184.                 _ieV = ieV
  185.             } else {
  186.                 _ieV = ieV.Elem()
  187.             }
  188.             l := uint16(len(_ieV.Bytes()))
  189.             la := make([]byte, 2)
  190.             _, _ = binary.Encode(la, binary.BigEndian, l)
  191.             vRes = append(vRes, byte(iei))
  192.             vRes = append(vRes, la...)
  193.             vRes = append(vRes, _ieV.Bytes()[:l]...)
  194.         }
  195.         if vRes != nil {
  196.             res = append(res, vRes...)
  197.         }
  198.     }
  199.     return
  200. }
  201.  
  202. func unmarshalNasPdu(pdu []byte, t reflect.Type) (res TNasMsg, err error) {
  203.     if t.Kind() != reflect.Struct {
  204.         return nil, errors.New("can unmarshal only to struct")
  205.     }
  206.     sRes := reflect.New(t)
  207.     sMsg := sRes.Elem()
  208.     tMsg := sMsg.Type()
  209.     var pPos, tFieldsStart int
  210.  
  211. mandatoryFields:
  212.     for i := 0; i < sMsg.NumField(); i++ {
  213.         ieT, ok := tMsg.Field(i).Tag.Lookup("nas_ie_type")
  214.         if !ok { // skip untagged fields of message struct
  215.             continue
  216.         }
  217.         var val reflect.Value
  218.         switch ieT {
  219.         case "V":
  220.             ieL := tMsg.Field(i).Tag.Get("nas_ie_length")
  221.             if ieL == "1/2" {
  222.                 a := uint8(0)
  223.                 val = reflect.ValueOf(&a).Elem()
  224.                 if tMsg.Field(i).Tag.Get("nas_ie_position") == "LSB" {
  225.                     val.SetUint(uint64(pdu[pPos] & 0xf))
  226.                 } else if tMsg.Field(i).Tag.Get("nas_ie_position") == "MSB" {
  227.                     val.SetUint(uint64(pdu[pPos] >> 4))
  228.                     pPos++
  229.                 } else {
  230.                     return nil, errors.New(fmt.Sprintf("nas_ie_position must be LSB or MSB but %s found",
  231.                         tMsg.Field(i).Tag.Get("nas_ie_position")))
  232.                 }
  233.             } else if ieL == "1" {
  234.                 a := uint8(0)
  235.                 val = reflect.ValueOf(&a).Elem()
  236.                 if val.Kind() != reflect.Uint8 {
  237.                     return nil, errors.New(fmt.Sprintf("field with nas_ie_type V and length 1/2 can "+
  238.                         "have only byte/Uint8 kind, but %s found", val.Kind()))
  239.                 }
  240.                 val.SetUint(uint64(pdu[pPos]))
  241.                 pPos++
  242.             } else {
  243.                 l, err := strconv.Atoi(ieL)
  244.                 if err != nil {
  245.                     return nil, err
  246.                 }
  247.                 a := make([]byte, l)
  248.                 val = reflect.ValueOf(&a).Elem()
  249.                 if val.Kind() != reflect.Slice {
  250.                     return nil, errors.New(fmt.Sprintf("field with nas_ie_type V and length more then 1 "+
  251.                         "can be only slice, but %s found", val.Kind()))
  252.                 }
  253.                 val.SetBytes(pdu[pPos : pPos+l])
  254.                 pPos += l
  255.             }
  256.         case "LV":
  257.             l := int(pdu[pPos])
  258.             pPos++
  259.             a := make([]byte, l)
  260.             val = reflect.ValueOf(&a).Elem()
  261.             if val.Kind() != reflect.Slice {
  262.                 return nil, errors.New(fmt.Sprintf("field with nas_ie_type LV "+
  263.                     "can be only slice, but %s found", val.Kind()))
  264.             }
  265.             val.SetBytes(pdu[pPos : pPos+l])
  266.             pPos += l
  267.         case "LVE":
  268.             var l uint16
  269.             _, err = binary.Decode(pdu[pPos:pPos+2], binary.BigEndian, &l)
  270.             if err != nil {
  271.                 return nil, err
  272.             }
  273.             pPos += 2
  274.             a := make([]byte, l)
  275.             val = reflect.ValueOf(&a).Elem()
  276.             if val.Kind() != reflect.Slice {
  277.                 return nil, errors.New(fmt.Sprintf("field with nas_ie_type LVE "+
  278.                     "can be only slice, but %s found", val.Kind()))
  279.             }
  280.             val.SetBytes(pdu[pPos : pPos+int(l)])
  281.             pPos += int(l)
  282.         default:
  283.             tFieldsStart = i
  284.             break mandatoryFields
  285.         }
  286.         if sMsg.Field(i).Type().Implements(reflect.TypeOf((*TNasMsgIE)(nil)).Elem()) {
  287.             sMsg.Field(i).MethodByName("Set").Call([]reflect.Value{val})
  288.         } else if sMsg.Field(i).CanAddr() && sMsg.Field(i).Addr().Type().Implements(reflect.TypeOf((*TNasMsgIE)(nil)).Elem()) {
  289.             sMsg.Field(i).Addr().MethodByName("Set").Call([]reflect.Value{val})
  290.         } else {
  291.             sMsg.Field(i).Set(val.Convert(sMsg.Field(i).Type()))
  292.         }
  293.     }
  294.  
  295.     for pPos < len(pdu) {
  296.         var idx int
  297.         idx, err = getFieldIdxByIEI(sMsg, pdu[pPos], tFieldsStart)
  298.         if errors.Is(err, ENASUnknownIEI{}) {
  299.             log.Print(err)
  300.             err = nil
  301.             if pdu[pPos]&0b10000000 == 0b10000000 {
  302.                 pPos++
  303.                 continue
  304.             } else if pdu[pPos]&0b01111000 == 0b01111000 {
  305.                 var l uint16
  306.                 _, _ = binary.Decode(pdu[pPos+1:pPos+3], binary.BigEndian, &l)
  307.                 pPos += 3 + int(l)
  308.                 continue
  309.             } else {
  310.                 l := pdu[pPos+1]
  311.                 pPos += 2 + int(l)
  312.                 continue
  313.             }
  314.         } else if err != nil {
  315.             return nil, err
  316.         }
  317.         if sMsg.Field(idx).Type().Kind() != reflect.Pointer {
  318.             return nil, errors.New(fmt.Sprintf("field with nas_ie_type T... should be pointer but "+
  319.                 "%s found", sMsg.Field(idx).Type().Kind()))
  320.         }
  321.         var sVal []byte
  322.         switch tMsg.Field(idx).Tag.Get("nas_ie_type") {
  323.         case "T":
  324.             val := reflect.New(sMsg.Field(idx).Elem().Type()).Elem()
  325.             if val.Kind() != reflect.Bool {
  326.                 return nil, errors.New(fmt.Sprintf("field with nas_ie_type T should be *bool, but *%s found",
  327.                     val.Kind()))
  328.             }
  329.             val.SetBool(true)
  330.             sMsg.Field(idx).Elem().Set(val)
  331.             pPos++
  332.             continue
  333.         case "TV":
  334.             if sMsg.Field(idx).Type().Elem().Kind() != reflect.Slice {
  335.                 return nil, errors.New(fmt.Sprintf("field with nas_ie_type TV and length >1 should be "+
  336.                     "*slice, but *%s found", sMsg.Field(idx).Type().Elem().Kind()))
  337.             }
  338.             ieL := tMsg.Field(idx).Tag.Get("nas_ie_length")
  339.             var l int
  340.             l, err = strconv.Atoi(ieL)
  341.             if err != nil {
  342.                 return nil, err
  343.             }
  344.             if l > 1 {
  345.                 sVal = pdu[pPos+1 : pPos+l]
  346.             } else {
  347.                 sVal = pdu[pPos : pPos+1]
  348.                 sVal[0] &= 0x0f
  349.             }
  350.             pPos += l
  351.         case "TLV":
  352.             if sMsg.Field(idx).Type().Elem().Kind() != reflect.Slice {
  353.                 return nil, errors.New(fmt.Sprintf("field with nas_ie_type TV and length >1 should be "+
  354.                     "*slice, but *%s found", sMsg.Field(idx).Type().Elem().Kind()))
  355.             }
  356.             l := int(pdu[pPos+1])
  357.             sVal = pdu[pPos+2 : pPos+2+l]
  358.             pPos += 2 + l
  359.         case "TLVE":
  360.             if sMsg.Field(idx).Type().Elem().Kind() != reflect.Slice {
  361.                 return nil, errors.New(fmt.Sprintf("field with nas_ie_type TV and length >1 should be "+
  362.                     "*slice, but *%s found", sMsg.Field(idx).Type().Elem().Kind()))
  363.             }
  364.             var l uint16
  365.             _, err = binary.Decode(pdu[pPos+1:pPos+3], binary.BigEndian, &l)
  366.             if err != nil {
  367.                 return nil, err
  368.             }
  369.             sVal = pdu[pPos+3 : pPos+3+int(l)]
  370.             pPos += 3 + int(l)
  371.         }
  372.         if tMsg.Field(idx).Type.Implements(reflect.TypeOf((*TNasMsgIE)(nil)).Elem()) {
  373.             val := reflect.New(sMsg.Field(idx).Type().Elem())
  374.             val.MethodByName("Set").Call([]reflect.Value{reflect.ValueOf(sVal)})
  375.             sMsg.Field(idx).Set(val)
  376.         } else {
  377.             sMsg.Field(idx).Set(reflect.ValueOf(&sVal))
  378.         }
  379.     }
  380.     pRes := reflect.ValueOf(&res)
  381.     pRes.Elem().Set(sRes)
  382.     return res, nil
  383. }
  384.  
  385. func getFieldIdxByIEI(sMsg reflect.Value, iei byte, startIdx int) (res int, err error) {
  386.     tMsg := sMsg.Type()
  387.     for i := startIdx; i < sMsg.NumField(); i++ {
  388.         tag := tMsg.Field(i).Tag.Get("nas_iei")
  389.         if tag == "" {
  390.             continue
  391.         }
  392.         var fIei int64
  393.         fIei, err = strconv.ParseInt(tag, 0, 8)
  394.         if err != nil {
  395.             return
  396.         }
  397.         if byte(fIei) == iei || byte(fIei) == iei>>4 {
  398.             return i, nil
  399.         }
  400.     }
  401.     return res, NewENASUnknownIEI(iei)
  402. }
  403.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement