Scripts/programs to test FreeBSD ethernet interfaces.
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.
 
 
 
 
 

140 lines
3.6 KiB

  1. # git+https://github.com/secdev/scapy.git
  2. import fcntl
  3. import os
  4. import struct
  5. import sys
  6. from scapy.all import *
  7. from scapy.arch.bpf.consts import BIOCGBLEN, BIOCGDLT, BIOCSDLT, BIOCSETIF, BIOCIMMEDIATE
  8. from ctypes import Structure, c_char, c_long, c_int, c_uint, c_ushort, c_uint16, c_uint32, sizeof
  9. class ReprStructureMixin:
  10. def format_field(self, k):
  11. try:
  12. bits = getattr(self, '_bits_%s' % k)
  13. return str(makebits(getattr(self, k), bits))
  14. except AttributeError:
  15. return repr(getattr(self, k))
  16. def __repr__(self):
  17. args = tuple(self.format_field(x[0]) for x in self._fields_)
  18. return '%s(%s)' % (self.__class__.__name__, ', '.join(args))
  19. class Timeval(Structure, ReprStructureMixin):
  20. _fields_ = [
  21. ('tv_sec', c_long),
  22. ('tv_usec', c_long),
  23. ]
  24. class bpf_hdr(Structure, ReprStructureMixin):
  25. _fields_ = [
  26. ('bh_tstamp', Timeval),
  27. ('bh_caplen', c_uint32),
  28. ('bh_datalen', c_uint32),
  29. ('bh_hdrlen', c_ushort),
  30. ]
  31. pkthdrbits = { 1: 'CSUM', 2: 'VLAN_TAG', 4: 'TSTMP' }
  32. # awk '{ print $3 ": '"'"'" $2 "'"'"'," }'
  33. csumflagbits = {
  34. 0x00000001: 'CSUM_IP',
  35. 0x00000002: 'CSUM_IP_UDP',
  36. 0x00000004: 'CSUM_IP_TCP',
  37. 0x00000008: 'CSUM_IP_SCTP',
  38. 0x00000010: 'CSUM_IP_TSO',
  39. 0x00000020: 'CSUM_IP_ISCSI',
  40. 0x00000040: 'CSUM_INNER_IP6_UDP',
  41. 0x00000080: 'CSUM_INNER_IP6_TCP',
  42. 0x00000100: 'CSUM_INNER_IP6_TSO',
  43. 0x00000200: 'CSUM_IP6_UDP',
  44. 0x00000400: 'CSUM_IP6_TCP',
  45. 0x00000800: 'CSUM_IP6_SCTP',
  46. 0x00001000: 'CSUM_IP6_TSO',
  47. 0x00002000: 'CSUM_IP6_ISCSI',
  48. 0x00004000: 'CSUM_INNER_IP',
  49. 0x00008000: 'CSUM_INNER_IP_UDP',
  50. 0x00010000: 'CSUM_INNER_IP_TCP',
  51. 0x00020000: 'CSUM_INNER_IP_TSO',
  52. 0x00040000: 'CSUM_ENCAP_VXLAN',
  53. 0x00080000: 'CSUM_ENCAP_RSVD1',
  54. 0x00100000: 'CSUM_INNER_L3_CALC',
  55. 0x00200000: 'CSUM_INNER_L3_VALID',
  56. 0x00400000: 'CSUM_INNER_L4_CALC',
  57. 0x00800000: 'CSUM_INNER_L4_VALID',
  58. 0x01000000: 'CSUM_L3_CALC',
  59. 0x02000000: 'CSUM_L3_VALID',
  60. 0x04000000: 'CSUM_L4_CALC',
  61. 0x08000000: 'CSUM_L4_VALID',
  62. 0x10000000: 'CSUM_L5_CALC',
  63. 0x20000000: 'CSUM_L5_VALID',
  64. 0x40000000: 'CSUM_COALESCED',
  65. 0x80000000: 'CSUM_SND_TAG',
  66. }
  67. class fbsdpkthdr(Structure, ReprStructureMixin):
  68. _bits_fph_bits = pkthdrbits
  69. _bits_fph_csum_flags = csumflagbits
  70. _fields_ = [
  71. ('fph_magic', c_char * 4),
  72. ('fph_hdrlen', c_uint32),
  73. ('fph_recvif', c_char * 16),
  74. ('fph_bits', c_uint32),
  75. ('fph_flowid', c_uint32),
  76. ('fph_csum_flags', c_uint32),
  77. ('fph_csum_data', c_uint32),
  78. ('fph_vlan_tag', c_uint16),
  79. ]
  80. class BPF:
  81. def __init__(self, iface):
  82. f = self._fp = os.open('/dev/bpf', os.O_RDONLY)
  83. l = fcntl.ioctl(f, BIOCGBLEN, b'\x00'*4, True)
  84. sz = c_int.from_buffer_copy(l)
  85. self._blen = sz.value
  86. fcntl.ioctl(f, BIOCIMMEDIATE, struct.pack('I', 1))
  87. fcntl.ioctl(f, BIOCSETIF, struct.pack('16s16x', iface.encode()))
  88. fcntl.ioctl(f, BIOCSDLT, struct.pack('I', 154))
  89. def getpkt(self):
  90. bytes = os.read(self._fp, self._blen)
  91. bpfhdr = bpf_hdr.from_buffer_copy(bytes)
  92. off = bpfhdr.bh_hdrlen
  93. fbsdhdr = fbsdpkthdr.from_buffer_copy(bytes, off)
  94. off += fbsdhdr.fph_hdrlen
  95. pkt = bytes[off:]
  96. return fbsdhdr, pkt
  97. def makebits(val, bits):
  98. r = [ v for k, v in bits.items() if k & val ]
  99. if not r:
  100. return 0
  101. return '|'.join(r)
  102. if __name__ == '__main__':
  103. bpf = BPF(sys.argv[1])
  104. while True:
  105. hdr, pkt = bpf.getpkt()
  106. print(repr(hdr))
  107. #pkthdr = struct.unpack(fbsdpkthdr, pkt[hdrlen:hdrlen + fbsdpkthdrlen])
  108. #pkthdr = list(pkthdr)
  109. #pkthdr[2] = pkthdr[2].strip(b'\x00').decode('us-ascii')
  110. #print(repr(pkthdr), fbsdpkthdrlen)
  111. if hdr.fph_magic != b'FBSD':
  112. print('magic wrong')
  113. continue
  114. # XXX calcsize is wrong here
  115. if sizeof(hdr) != hdr.fph_hdrlen:
  116. print('length mismatch')
  117. continue
  118. print(repr(Ether(pkt))[:300])