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.
 
 
 

260 lines
5.8 KiB

  1. // Copyright 2012 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package ipv4
  5. import (
  6. "bytes"
  7. "encoding/binary"
  8. "net"
  9. "reflect"
  10. "runtime"
  11. "strings"
  12. "testing"
  13. "golang.org/x/net/internal/socket"
  14. )
  15. type headerTest struct {
  16. wireHeaderFromKernel []byte
  17. wireHeaderToKernel []byte
  18. wireHeaderFromTradBSDKernel []byte
  19. wireHeaderToTradBSDKernel []byte
  20. wireHeaderFromFreeBSD10Kernel []byte
  21. wireHeaderToFreeBSD10Kernel []byte
  22. *Header
  23. }
  24. var headerLittleEndianTests = []headerTest{
  25. // TODO(mikio): Add platform dependent wire header formats when
  26. // we support new platforms.
  27. {
  28. wireHeaderFromKernel: []byte{
  29. 0x45, 0x01, 0xbe, 0xef,
  30. 0xca, 0xfe, 0x45, 0xdc,
  31. 0xff, 0x01, 0xde, 0xad,
  32. 172, 16, 254, 254,
  33. 192, 168, 0, 1,
  34. },
  35. wireHeaderToKernel: []byte{
  36. 0x45, 0x01, 0xbe, 0xef,
  37. 0xca, 0xfe, 0x45, 0xdc,
  38. 0xff, 0x01, 0xde, 0xad,
  39. 172, 16, 254, 254,
  40. 192, 168, 0, 1,
  41. },
  42. wireHeaderFromTradBSDKernel: []byte{
  43. 0x45, 0x01, 0xdb, 0xbe,
  44. 0xca, 0xfe, 0xdc, 0x45,
  45. 0xff, 0x01, 0xde, 0xad,
  46. 172, 16, 254, 254,
  47. 192, 168, 0, 1,
  48. },
  49. wireHeaderToTradBSDKernel: []byte{
  50. 0x45, 0x01, 0xef, 0xbe,
  51. 0xca, 0xfe, 0xdc, 0x45,
  52. 0xff, 0x01, 0xde, 0xad,
  53. 172, 16, 254, 254,
  54. 192, 168, 0, 1,
  55. },
  56. wireHeaderFromFreeBSD10Kernel: []byte{
  57. 0x45, 0x01, 0xef, 0xbe,
  58. 0xca, 0xfe, 0xdc, 0x45,
  59. 0xff, 0x01, 0xde, 0xad,
  60. 172, 16, 254, 254,
  61. 192, 168, 0, 1,
  62. },
  63. wireHeaderToFreeBSD10Kernel: []byte{
  64. 0x45, 0x01, 0xef, 0xbe,
  65. 0xca, 0xfe, 0xdc, 0x45,
  66. 0xff, 0x01, 0xde, 0xad,
  67. 172, 16, 254, 254,
  68. 192, 168, 0, 1,
  69. },
  70. Header: &Header{
  71. Version: Version,
  72. Len: HeaderLen,
  73. TOS: 1,
  74. TotalLen: 0xbeef,
  75. ID: 0xcafe,
  76. Flags: DontFragment,
  77. FragOff: 1500,
  78. TTL: 255,
  79. Protocol: 1,
  80. Checksum: 0xdead,
  81. Src: net.IPv4(172, 16, 254, 254),
  82. Dst: net.IPv4(192, 168, 0, 1),
  83. },
  84. },
  85. // with option headers
  86. {
  87. wireHeaderFromKernel: []byte{
  88. 0x46, 0x01, 0xbe, 0xf3,
  89. 0xca, 0xfe, 0x45, 0xdc,
  90. 0xff, 0x01, 0xde, 0xad,
  91. 172, 16, 254, 254,
  92. 192, 168, 0, 1,
  93. 0xff, 0xfe, 0xfe, 0xff,
  94. },
  95. wireHeaderToKernel: []byte{
  96. 0x46, 0x01, 0xbe, 0xf3,
  97. 0xca, 0xfe, 0x45, 0xdc,
  98. 0xff, 0x01, 0xde, 0xad,
  99. 172, 16, 254, 254,
  100. 192, 168, 0, 1,
  101. 0xff, 0xfe, 0xfe, 0xff,
  102. },
  103. wireHeaderFromTradBSDKernel: []byte{
  104. 0x46, 0x01, 0xdb, 0xbe,
  105. 0xca, 0xfe, 0xdc, 0x45,
  106. 0xff, 0x01, 0xde, 0xad,
  107. 172, 16, 254, 254,
  108. 192, 168, 0, 1,
  109. 0xff, 0xfe, 0xfe, 0xff,
  110. },
  111. wireHeaderToTradBSDKernel: []byte{
  112. 0x46, 0x01, 0xf3, 0xbe,
  113. 0xca, 0xfe, 0xdc, 0x45,
  114. 0xff, 0x01, 0xde, 0xad,
  115. 172, 16, 254, 254,
  116. 192, 168, 0, 1,
  117. 0xff, 0xfe, 0xfe, 0xff,
  118. },
  119. wireHeaderFromFreeBSD10Kernel: []byte{
  120. 0x46, 0x01, 0xf3, 0xbe,
  121. 0xca, 0xfe, 0xdc, 0x45,
  122. 0xff, 0x01, 0xde, 0xad,
  123. 172, 16, 254, 254,
  124. 192, 168, 0, 1,
  125. 0xff, 0xfe, 0xfe, 0xff,
  126. },
  127. wireHeaderToFreeBSD10Kernel: []byte{
  128. 0x46, 0x01, 0xf3, 0xbe,
  129. 0xca, 0xfe, 0xdc, 0x45,
  130. 0xff, 0x01, 0xde, 0xad,
  131. 172, 16, 254, 254,
  132. 192, 168, 0, 1,
  133. 0xff, 0xfe, 0xfe, 0xff,
  134. },
  135. Header: &Header{
  136. Version: Version,
  137. Len: HeaderLen + 4,
  138. TOS: 1,
  139. TotalLen: 0xbef3,
  140. ID: 0xcafe,
  141. Flags: DontFragment,
  142. FragOff: 1500,
  143. TTL: 255,
  144. Protocol: 1,
  145. Checksum: 0xdead,
  146. Src: net.IPv4(172, 16, 254, 254),
  147. Dst: net.IPv4(192, 168, 0, 1),
  148. Options: []byte{0xff, 0xfe, 0xfe, 0xff},
  149. },
  150. },
  151. }
  152. func TestMarshalHeader(t *testing.T) {
  153. for i, tt := range []struct {
  154. h *Header
  155. err error
  156. }{
  157. {nil, errNilHeader},
  158. {&Header{Len: HeaderLen - 1}, errHeaderTooShort},
  159. } {
  160. if _, err := tt.h.Marshal(); err != tt.err {
  161. t.Errorf("#%d: got %v; want %v", i, err, tt.err)
  162. }
  163. }
  164. if socket.NativeEndian != binary.LittleEndian {
  165. t.Skip("no test for non-little endian machine yet")
  166. }
  167. for _, tt := range headerLittleEndianTests {
  168. b, err := tt.Header.Marshal()
  169. if err != nil {
  170. t.Fatal(err)
  171. }
  172. var wh []byte
  173. switch runtime.GOOS {
  174. case "darwin", "dragonfly", "netbsd":
  175. wh = tt.wireHeaderToTradBSDKernel
  176. case "freebsd":
  177. switch {
  178. case freebsdVersion < 1000000:
  179. wh = tt.wireHeaderToTradBSDKernel
  180. case 1000000 <= freebsdVersion && freebsdVersion < 1100000:
  181. wh = tt.wireHeaderToFreeBSD10Kernel
  182. default:
  183. wh = tt.wireHeaderToKernel
  184. }
  185. default:
  186. wh = tt.wireHeaderToKernel
  187. }
  188. if !bytes.Equal(b, wh) {
  189. t.Fatalf("got %#v; want %#v", b, wh)
  190. }
  191. }
  192. }
  193. func TestParseHeader(t *testing.T) {
  194. for i, tt := range []struct {
  195. h *Header
  196. wh []byte
  197. err error
  198. }{
  199. {nil, nil, errNilHeader},
  200. {&Header{}, nil, errNilHeader},
  201. {&Header{}, make([]byte, HeaderLen-1), errHeaderTooShort},
  202. {&Header{}, []byte{
  203. 0x46, 0x00, 0x00, 0x00,
  204. 0x00, 0x00, 0x00, 0x00,
  205. 0x00, 0x00, 0x00, 0x00,
  206. 0x00, 0x00, 0x00, 0x00,
  207. 0x00, 0x00, 0x00, 0x00,
  208. }, errExtHeaderTooShort},
  209. } {
  210. if err := tt.h.Parse(tt.wh); err != tt.err {
  211. t.Fatalf("#%d: got %v; want %v", i, err, tt.err)
  212. }
  213. }
  214. if socket.NativeEndian != binary.LittleEndian {
  215. t.Skip("no test for big endian machine yet")
  216. }
  217. for _, tt := range headerLittleEndianTests {
  218. var wh []byte
  219. switch runtime.GOOS {
  220. case "darwin", "dragonfly", "netbsd":
  221. wh = tt.wireHeaderFromTradBSDKernel
  222. case "freebsd":
  223. switch {
  224. case freebsdVersion < 1000000:
  225. wh = tt.wireHeaderFromTradBSDKernel
  226. case 1000000 <= freebsdVersion && freebsdVersion < 1100000:
  227. wh = tt.wireHeaderFromFreeBSD10Kernel
  228. default:
  229. wh = tt.wireHeaderFromKernel
  230. }
  231. default:
  232. wh = tt.wireHeaderFromKernel
  233. }
  234. h, err := ParseHeader(wh)
  235. if err != nil {
  236. t.Fatal(err)
  237. }
  238. if err := h.Parse(wh); err != nil {
  239. t.Fatal(err)
  240. }
  241. if !reflect.DeepEqual(h, tt.Header) {
  242. t.Fatalf("got %#v; want %#v", h, tt.Header)
  243. }
  244. s := h.String()
  245. if strings.Contains(s, ",") {
  246. t.Fatalf("should be space-separated values: %s", s)
  247. }
  248. }
  249. }