You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

114 lines
2.6 KiB

  1. package nfqueue
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "log"
  6. "time"
  7. "tea.fen.gg/fengg/go-nfqueue/internal/unix"
  8. "github.com/mdlayher/netlink"
  9. )
  10. func extractAttribute(log *log.Logger, a *Attribute, data []byte) error {
  11. ad, err := netlink.NewAttributeDecoder(data)
  12. if err != nil {
  13. return err
  14. }
  15. ad.ByteOrder = binary.BigEndian
  16. for ad.Next() {
  17. switch ad.Type() {
  18. case nfQaPacketHdr:
  19. packetID := binary.BigEndian.Uint32(ad.Bytes()[:4])
  20. a.PacketID = &packetID
  21. hwProto := binary.BigEndian.Uint16(ad.Bytes()[4:6])
  22. a.HwProtocol = &hwProto
  23. hook := uint8(ad.Bytes()[6])
  24. a.Hook = &hook
  25. case nfQaMark:
  26. mark := ad.Uint32()
  27. a.Mark = &mark
  28. case nfQaTimestamp:
  29. var sec, usec int64
  30. r := bytes.NewReader(ad.Bytes()[:8])
  31. if err := binary.Read(r, binary.BigEndian, &sec); err != nil {
  32. return err
  33. }
  34. r = bytes.NewReader(ad.Bytes()[8:])
  35. if err := binary.Read(r, binary.BigEndian, &usec); err != nil {
  36. return err
  37. }
  38. timestamp := time.Unix(sec, usec*1000)
  39. a.Timestamp = &timestamp
  40. case nfQaIfIndexInDev:
  41. inDev := ad.Uint32()
  42. a.InDev = &inDev
  43. case nfQaIfIndexOutDev:
  44. outDev := ad.Uint32()
  45. a.OutDev = &outDev
  46. case nfQaIfIndexPhysInDev:
  47. physInDev := ad.Uint32()
  48. a.PhysInDev = &physInDev
  49. case nfQaIfIndexPhysOutDev:
  50. physOutDev := ad.Uint32()
  51. a.PhysOutDev = &physOutDev
  52. case nfQaHwAddr:
  53. hwAddrLen := binary.BigEndian.Uint16(ad.Bytes()[:2])
  54. hwAddr := (ad.Bytes())[4 : 4+hwAddrLen]
  55. a.HwAddr = &hwAddr
  56. case nfQaPayload:
  57. payload := ad.Bytes()
  58. a.Payload = &payload
  59. case nfQaCt:
  60. ct := ad.Bytes()
  61. a.Ct = &ct
  62. case nfQaCtInfo:
  63. ctInfo := ad.Uint32()
  64. a.CtInfo = &ctInfo
  65. case nfQaCapLen:
  66. capLen := ad.Uint32()
  67. a.CapLen = &capLen
  68. case nfQaSkbInfo:
  69. skbInfo := ad.Bytes()
  70. a.SkbInfo = &skbInfo
  71. case nfQaExp:
  72. exp := ad.Bytes()
  73. a.Exp = &exp
  74. case nfQaUID:
  75. uid := ad.Uint32()
  76. a.UID = &uid
  77. case nfQaGID:
  78. gid := ad.Uint32()
  79. a.GID = &gid
  80. case nfQaSecCtx:
  81. secCtx := ad.String()
  82. a.SecCtx = &secCtx
  83. case nfQaL2HDR:
  84. l2hdr := ad.Bytes()
  85. a.L2Hdr = &l2hdr
  86. default:
  87. log.Printf("Unknown attribute Type: 0x%x\tData: %v\n", ad.Type(), ad.Bytes())
  88. }
  89. }
  90. return ad.Err()
  91. }
  92. func checkHeader(data []byte) int {
  93. if (data[0] == unix.AF_INET || data[0] == unix.AF_INET6) && data[1] == unix.NFNETLINK_V0 {
  94. return 4
  95. }
  96. return 0
  97. }
  98. func extractAttributes(log *log.Logger, msg []byte) (Attribute, error) {
  99. attrs := Attribute{}
  100. offset := checkHeader(msg[:2])
  101. if err := extractAttribute(log, &attrs, msg[offset:]); err != nil {
  102. return attrs, err
  103. }
  104. return attrs, nil
  105. }