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.
 
 
 

323 lines
7.7 KiB

  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. "encoding/binary"
  7. "net"
  8. "strings"
  9. "golang.org/x/net/internal/iana"
  10. )
  11. const (
  12. classInterfaceInfo = 2
  13. )
  14. const (
  15. attrMTU = 1 << iota
  16. attrName
  17. attrIPAddr
  18. attrIfIndex
  19. )
  20. // An InterfaceInfo represents interface and next-hop identification.
  21. type InterfaceInfo struct {
  22. Class int // extension object class number
  23. Type int // extension object sub-type
  24. Interface *net.Interface
  25. Addr *net.IPAddr
  26. }
  27. func (ifi *InterfaceInfo) nameLen() int {
  28. if len(ifi.Interface.Name) > 63 {
  29. return 64
  30. }
  31. l := 1 + len(ifi.Interface.Name)
  32. return (l + 3) &^ 3
  33. }
  34. func (ifi *InterfaceInfo) attrsAndLen(proto int) (attrs, l int) {
  35. l = 4
  36. if ifi.Interface != nil && ifi.Interface.Index > 0 {
  37. attrs |= attrIfIndex
  38. l += 4
  39. if len(ifi.Interface.Name) > 0 {
  40. attrs |= attrName
  41. l += ifi.nameLen()
  42. }
  43. if ifi.Interface.MTU > 0 {
  44. attrs |= attrMTU
  45. l += 4
  46. }
  47. }
  48. if ifi.Addr != nil {
  49. switch proto {
  50. case iana.ProtocolICMP:
  51. if ifi.Addr.IP.To4() != nil {
  52. attrs |= attrIPAddr
  53. l += 4 + net.IPv4len
  54. }
  55. case iana.ProtocolIPv6ICMP:
  56. if ifi.Addr.IP.To16() != nil && ifi.Addr.IP.To4() == nil {
  57. attrs |= attrIPAddr
  58. l += 4 + net.IPv6len
  59. }
  60. }
  61. }
  62. return
  63. }
  64. // Len implements the Len method of Extension interface.
  65. func (ifi *InterfaceInfo) Len(proto int) int {
  66. _, l := ifi.attrsAndLen(proto)
  67. return l
  68. }
  69. // Marshal implements the Marshal method of Extension interface.
  70. func (ifi *InterfaceInfo) Marshal(proto int) ([]byte, error) {
  71. attrs, l := ifi.attrsAndLen(proto)
  72. b := make([]byte, l)
  73. if err := ifi.marshal(proto, b, attrs, l); err != nil {
  74. return nil, err
  75. }
  76. return b, nil
  77. }
  78. func (ifi *InterfaceInfo) marshal(proto int, b []byte, attrs, l int) error {
  79. binary.BigEndian.PutUint16(b[:2], uint16(l))
  80. b[2], b[3] = classInterfaceInfo, byte(ifi.Type)
  81. for b = b[4:]; len(b) > 0 && attrs != 0; {
  82. switch {
  83. case attrs&attrIfIndex != 0:
  84. b = ifi.marshalIfIndex(proto, b)
  85. attrs &^= attrIfIndex
  86. case attrs&attrIPAddr != 0:
  87. b = ifi.marshalIPAddr(proto, b)
  88. attrs &^= attrIPAddr
  89. case attrs&attrName != 0:
  90. b = ifi.marshalName(proto, b)
  91. attrs &^= attrName
  92. case attrs&attrMTU != 0:
  93. b = ifi.marshalMTU(proto, b)
  94. attrs &^= attrMTU
  95. }
  96. }
  97. return nil
  98. }
  99. func (ifi *InterfaceInfo) marshalIfIndex(proto int, b []byte) []byte {
  100. binary.BigEndian.PutUint32(b[:4], uint32(ifi.Interface.Index))
  101. return b[4:]
  102. }
  103. func (ifi *InterfaceInfo) parseIfIndex(b []byte) ([]byte, error) {
  104. if len(b) < 4 {
  105. return nil, errMessageTooShort
  106. }
  107. ifi.Interface.Index = int(binary.BigEndian.Uint32(b[:4]))
  108. return b[4:], nil
  109. }
  110. func (ifi *InterfaceInfo) marshalIPAddr(proto int, b []byte) []byte {
  111. switch proto {
  112. case iana.ProtocolICMP:
  113. binary.BigEndian.PutUint16(b[:2], uint16(iana.AddrFamilyIPv4))
  114. copy(b[4:4+net.IPv4len], ifi.Addr.IP.To4())
  115. b = b[4+net.IPv4len:]
  116. case iana.ProtocolIPv6ICMP:
  117. binary.BigEndian.PutUint16(b[:2], uint16(iana.AddrFamilyIPv6))
  118. copy(b[4:4+net.IPv6len], ifi.Addr.IP.To16())
  119. b = b[4+net.IPv6len:]
  120. }
  121. return b
  122. }
  123. func (ifi *InterfaceInfo) parseIPAddr(b []byte) ([]byte, error) {
  124. if len(b) < 4 {
  125. return nil, errMessageTooShort
  126. }
  127. afi := int(binary.BigEndian.Uint16(b[:2]))
  128. b = b[4:]
  129. switch afi {
  130. case iana.AddrFamilyIPv4:
  131. if len(b) < net.IPv4len {
  132. return nil, errMessageTooShort
  133. }
  134. ifi.Addr.IP = make(net.IP, net.IPv4len)
  135. copy(ifi.Addr.IP, b[:net.IPv4len])
  136. b = b[net.IPv4len:]
  137. case iana.AddrFamilyIPv6:
  138. if len(b) < net.IPv6len {
  139. return nil, errMessageTooShort
  140. }
  141. ifi.Addr.IP = make(net.IP, net.IPv6len)
  142. copy(ifi.Addr.IP, b[:net.IPv6len])
  143. b = b[net.IPv6len:]
  144. }
  145. return b, nil
  146. }
  147. func (ifi *InterfaceInfo) marshalName(proto int, b []byte) []byte {
  148. l := byte(ifi.nameLen())
  149. b[0] = l
  150. copy(b[1:], []byte(ifi.Interface.Name))
  151. return b[l:]
  152. }
  153. func (ifi *InterfaceInfo) parseName(b []byte) ([]byte, error) {
  154. if 4 > len(b) || len(b) < int(b[0]) {
  155. return nil, errMessageTooShort
  156. }
  157. l := int(b[0])
  158. if l%4 != 0 || 4 > l || l > 64 {
  159. return nil, errInvalidExtension
  160. }
  161. var name [63]byte
  162. copy(name[:], b[1:l])
  163. ifi.Interface.Name = strings.Trim(string(name[:]), "\000")
  164. return b[l:], nil
  165. }
  166. func (ifi *InterfaceInfo) marshalMTU(proto int, b []byte) []byte {
  167. binary.BigEndian.PutUint32(b[:4], uint32(ifi.Interface.MTU))
  168. return b[4:]
  169. }
  170. func (ifi *InterfaceInfo) parseMTU(b []byte) ([]byte, error) {
  171. if len(b) < 4 {
  172. return nil, errMessageTooShort
  173. }
  174. ifi.Interface.MTU = int(binary.BigEndian.Uint32(b[:4]))
  175. return b[4:], nil
  176. }
  177. func parseInterfaceInfo(b []byte) (Extension, error) {
  178. ifi := &InterfaceInfo{
  179. Class: int(b[2]),
  180. Type: int(b[3]),
  181. }
  182. if ifi.Type&(attrIfIndex|attrName|attrMTU) != 0 {
  183. ifi.Interface = &net.Interface{}
  184. }
  185. if ifi.Type&attrIPAddr != 0 {
  186. ifi.Addr = &net.IPAddr{}
  187. }
  188. attrs := ifi.Type & (attrIfIndex | attrIPAddr | attrName | attrMTU)
  189. for b = b[4:]; len(b) > 0 && attrs != 0; {
  190. var err error
  191. switch {
  192. case attrs&attrIfIndex != 0:
  193. b, err = ifi.parseIfIndex(b)
  194. attrs &^= attrIfIndex
  195. case attrs&attrIPAddr != 0:
  196. b, err = ifi.parseIPAddr(b)
  197. attrs &^= attrIPAddr
  198. case attrs&attrName != 0:
  199. b, err = ifi.parseName(b)
  200. attrs &^= attrName
  201. case attrs&attrMTU != 0:
  202. b, err = ifi.parseMTU(b)
  203. attrs &^= attrMTU
  204. }
  205. if err != nil {
  206. return nil, err
  207. }
  208. }
  209. if ifi.Interface != nil && ifi.Interface.Name != "" && ifi.Addr != nil && ifi.Addr.IP.To16() != nil && ifi.Addr.IP.To4() == nil {
  210. ifi.Addr.Zone = ifi.Interface.Name
  211. }
  212. return ifi, nil
  213. }
  214. const (
  215. classInterfaceIdent = 3
  216. typeInterfaceByName = 1
  217. typeInterfaceByIndex = 2
  218. typeInterfaceByAddress = 3
  219. )
  220. // An InterfaceIdent represents interface identification.
  221. type InterfaceIdent struct {
  222. Class int // extension object class number
  223. Type int // extension object sub-type
  224. Name string // interface name
  225. Index int // interface index
  226. AFI int // address family identifier; see address family numbers in IANA registry
  227. Addr []byte // address
  228. }
  229. // Len implements the Len method of Extension interface.
  230. func (ifi *InterfaceIdent) Len(_ int) int {
  231. switch ifi.Type {
  232. case typeInterfaceByName:
  233. l := len(ifi.Name)
  234. if l > 255 {
  235. l = 255
  236. }
  237. return 4 + (l+3)&^3
  238. case typeInterfaceByIndex:
  239. return 4 + 4
  240. case typeInterfaceByAddress:
  241. return 4 + 4 + (len(ifi.Addr)+3)&^3
  242. default:
  243. return 4
  244. }
  245. }
  246. // Marshal implements the Marshal method of Extension interface.
  247. func (ifi *InterfaceIdent) Marshal(proto int) ([]byte, error) {
  248. b := make([]byte, ifi.Len(proto))
  249. if err := ifi.marshal(proto, b); err != nil {
  250. return nil, err
  251. }
  252. return b, nil
  253. }
  254. func (ifi *InterfaceIdent) marshal(proto int, b []byte) error {
  255. l := ifi.Len(proto)
  256. binary.BigEndian.PutUint16(b[:2], uint16(l))
  257. b[2], b[3] = classInterfaceIdent, byte(ifi.Type)
  258. switch ifi.Type {
  259. case typeInterfaceByName:
  260. copy(b[4:], ifi.Name)
  261. case typeInterfaceByIndex:
  262. binary.BigEndian.PutUint32(b[4:4+4], uint32(ifi.Index))
  263. case typeInterfaceByAddress:
  264. binary.BigEndian.PutUint16(b[4:4+2], uint16(ifi.AFI))
  265. b[4+2] = byte(len(ifi.Addr))
  266. copy(b[4+4:], ifi.Addr)
  267. }
  268. return nil
  269. }
  270. func parseInterfaceIdent(b []byte) (Extension, error) {
  271. ifi := &InterfaceIdent{
  272. Class: int(b[2]),
  273. Type: int(b[3]),
  274. }
  275. switch ifi.Type {
  276. case typeInterfaceByName:
  277. ifi.Name = strings.Trim(string(b[4:]), string(0))
  278. case typeInterfaceByIndex:
  279. if len(b[4:]) < 4 {
  280. return nil, errInvalidExtension
  281. }
  282. ifi.Index = int(binary.BigEndian.Uint32(b[4 : 4+4]))
  283. case typeInterfaceByAddress:
  284. if len(b[4:]) < 4 {
  285. return nil, errInvalidExtension
  286. }
  287. ifi.AFI = int(binary.BigEndian.Uint16(b[4 : 4+2]))
  288. l := int(b[4+2])
  289. if len(b[4+4:]) < l {
  290. return nil, errInvalidExtension
  291. }
  292. ifi.Addr = make([]byte, l)
  293. copy(ifi.Addr, b[4+4:])
  294. }
  295. return ifi, nil
  296. }