extension_test.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // Copyright 2015 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 icmp
  5. import (
  6. "fmt"
  7. "net"
  8. "reflect"
  9. "testing"
  10. "golang.org/x/net/internal/iana"
  11. )
  12. func TestMarshalAndParseExtension(t *testing.T) {
  13. fn := func(t *testing.T, proto int, hdr, obj []byte, te Extension) error {
  14. b, err := te.Marshal(proto)
  15. if err != nil {
  16. return err
  17. }
  18. if !reflect.DeepEqual(b, obj) {
  19. return fmt.Errorf("got %#v; want %#v", b, obj)
  20. }
  21. for i, wire := range []struct {
  22. data []byte // original datagram
  23. inlattr int // length of padded original datagram, a hint
  24. outlattr int // length of padded original datagram, a want
  25. err error
  26. }{
  27. {nil, 0, -1, errNoExtension},
  28. {make([]byte, 127), 128, -1, errNoExtension},
  29. {make([]byte, 128), 127, -1, errNoExtension},
  30. {make([]byte, 128), 128, -1, errNoExtension},
  31. {make([]byte, 128), 129, -1, errNoExtension},
  32. {append(make([]byte, 128), append(hdr, obj...)...), 127, 128, nil},
  33. {append(make([]byte, 128), append(hdr, obj...)...), 128, 128, nil},
  34. {append(make([]byte, 128), append(hdr, obj...)...), 129, 128, nil},
  35. {append(make([]byte, 512), append(hdr, obj...)...), 511, -1, errNoExtension},
  36. {append(make([]byte, 512), append(hdr, obj...)...), 512, 512, nil},
  37. {append(make([]byte, 512), append(hdr, obj...)...), 513, -1, errNoExtension},
  38. } {
  39. exts, l, err := parseExtensions(wire.data, wire.inlattr)
  40. if err != wire.err {
  41. return fmt.Errorf("#%d: got %v; want %v", i, err, wire.err)
  42. }
  43. if wire.err != nil {
  44. continue
  45. }
  46. if l != wire.outlattr {
  47. return fmt.Errorf("#%d: got %d; want %d", i, l, wire.outlattr)
  48. }
  49. if !reflect.DeepEqual(exts, []Extension{te}) {
  50. return fmt.Errorf("#%d: got %#v; want %#v", i, exts[0], te)
  51. }
  52. }
  53. return nil
  54. }
  55. t.Run("MPLSLabelStack", func(t *testing.T) {
  56. for _, et := range []struct {
  57. proto int
  58. hdr []byte
  59. obj []byte
  60. ext Extension
  61. }{
  62. // MPLS label stack with no label
  63. {
  64. proto: iana.ProtocolICMP,
  65. hdr: []byte{
  66. 0x20, 0x00, 0x00, 0x00,
  67. },
  68. obj: []byte{
  69. 0x00, 0x04, 0x01, 0x01,
  70. },
  71. ext: &MPLSLabelStack{
  72. Class: classMPLSLabelStack,
  73. Type: typeIncomingMPLSLabelStack,
  74. },
  75. },
  76. // MPLS label stack with a single label
  77. {
  78. proto: iana.ProtocolIPv6ICMP,
  79. hdr: []byte{
  80. 0x20, 0x00, 0x00, 0x00,
  81. },
  82. obj: []byte{
  83. 0x00, 0x08, 0x01, 0x01,
  84. 0x03, 0xe8, 0xe9, 0xff,
  85. },
  86. ext: &MPLSLabelStack{
  87. Class: classMPLSLabelStack,
  88. Type: typeIncomingMPLSLabelStack,
  89. Labels: []MPLSLabel{
  90. {
  91. Label: 16014,
  92. TC: 0x4,
  93. S: true,
  94. TTL: 255,
  95. },
  96. },
  97. },
  98. },
  99. // MPLS label stack with multiple labels
  100. {
  101. proto: iana.ProtocolICMP,
  102. hdr: []byte{
  103. 0x20, 0x00, 0x00, 0x00,
  104. },
  105. obj: []byte{
  106. 0x00, 0x0c, 0x01, 0x01,
  107. 0x03, 0xe8, 0xde, 0xfe,
  108. 0x03, 0xe8, 0xe1, 0xff,
  109. },
  110. ext: &MPLSLabelStack{
  111. Class: classMPLSLabelStack,
  112. Type: typeIncomingMPLSLabelStack,
  113. Labels: []MPLSLabel{
  114. {
  115. Label: 16013,
  116. TC: 0x7,
  117. S: false,
  118. TTL: 254,
  119. },
  120. {
  121. Label: 16014,
  122. TC: 0,
  123. S: true,
  124. TTL: 255,
  125. },
  126. },
  127. },
  128. },
  129. } {
  130. if err := fn(t, et.proto, et.hdr, et.obj, et.ext); err != nil {
  131. t.Error(err)
  132. }
  133. }
  134. })
  135. t.Run("InterfaceInfo", func(t *testing.T) {
  136. for _, et := range []struct {
  137. proto int
  138. hdr []byte
  139. obj []byte
  140. ext Extension
  141. }{
  142. // Interface information with no attribute
  143. {
  144. proto: iana.ProtocolICMP,
  145. hdr: []byte{
  146. 0x20, 0x00, 0x00, 0x00,
  147. },
  148. obj: []byte{
  149. 0x00, 0x04, 0x02, 0x00,
  150. },
  151. ext: &InterfaceInfo{
  152. Class: classInterfaceInfo,
  153. },
  154. },
  155. // Interface information with ifIndex and name
  156. {
  157. proto: iana.ProtocolICMP,
  158. hdr: []byte{
  159. 0x20, 0x00, 0x00, 0x00,
  160. },
  161. obj: []byte{
  162. 0x00, 0x10, 0x02, 0x0a,
  163. 0x00, 0x00, 0x00, 0x10,
  164. 0x08, byte('e'), byte('n'), byte('1'),
  165. byte('0'), byte('1'), 0x00, 0x00,
  166. },
  167. ext: &InterfaceInfo{
  168. Class: classInterfaceInfo,
  169. Type: 0x0a,
  170. Interface: &net.Interface{
  171. Index: 16,
  172. Name: "en101",
  173. },
  174. },
  175. },
  176. // Interface information with ifIndex, IPAddr, name and MTU
  177. {
  178. proto: iana.ProtocolIPv6ICMP,
  179. hdr: []byte{
  180. 0x20, 0x00, 0x00, 0x00,
  181. },
  182. obj: []byte{
  183. 0x00, 0x28, 0x02, 0x0f,
  184. 0x00, 0x00, 0x00, 0x0f,
  185. 0x00, 0x02, 0x00, 0x00,
  186. 0xfe, 0x80, 0x00, 0x00,
  187. 0x00, 0x00, 0x00, 0x00,
  188. 0x00, 0x00, 0x00, 0x00,
  189. 0x00, 0x00, 0x00, 0x01,
  190. 0x08, byte('e'), byte('n'), byte('1'),
  191. byte('0'), byte('1'), 0x00, 0x00,
  192. 0x00, 0x00, 0x20, 0x00,
  193. },
  194. ext: &InterfaceInfo{
  195. Class: classInterfaceInfo,
  196. Type: 0x0f,
  197. Interface: &net.Interface{
  198. Index: 15,
  199. Name: "en101",
  200. MTU: 8192,
  201. },
  202. Addr: &net.IPAddr{
  203. IP: net.ParseIP("fe80::1"),
  204. Zone: "en101",
  205. },
  206. },
  207. },
  208. } {
  209. if err := fn(t, et.proto, et.hdr, et.obj, et.ext); err != nil {
  210. t.Error(err)
  211. }
  212. }
  213. })
  214. }
  215. func TestParseInterfaceName(t *testing.T) {
  216. ifi := InterfaceInfo{Interface: &net.Interface{}}
  217. for i, tt := range []struct {
  218. b []byte
  219. error
  220. }{
  221. {[]byte{0, 'e', 'n', '0'}, errInvalidExtension},
  222. {[]byte{4, 'e', 'n', '0'}, nil},
  223. {[]byte{7, 'e', 'n', '0', 0xff, 0xff, 0xff, 0xff}, errInvalidExtension},
  224. {[]byte{8, 'e', 'n', '0', 0xff, 0xff, 0xff}, errMessageTooShort},
  225. } {
  226. if _, err := ifi.parseName(tt.b); err != tt.error {
  227. t.Errorf("#%d: got %v; want %v", i, err, tt.error)
  228. }
  229. }
  230. }