interface.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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. "net"
  7. "strings"
  8. "golang.org/x/net/internal/iana"
  9. )
  10. const (
  11. classInterfaceInfo = 2
  12. afiIPv4 = 1
  13. afiIPv6 = 2
  14. )
  15. const (
  16. attrMTU = 1 << iota
  17. attrName
  18. attrIPAddr
  19. attrIfIndex
  20. )
  21. // An InterfaceInfo represents interface and next-hop identification.
  22. type InterfaceInfo struct {
  23. Class int // extension object class number
  24. Type int // extension object sub-type
  25. Interface *net.Interface
  26. Addr *net.IPAddr
  27. }
  28. func (ifi *InterfaceInfo) nameLen() int {
  29. if len(ifi.Interface.Name) > 63 {
  30. return 64
  31. }
  32. l := 1 + len(ifi.Interface.Name)
  33. return (l + 3) &^ 3
  34. }
  35. func (ifi *InterfaceInfo) attrsAndLen(proto int) (attrs, l int) {
  36. l = 4
  37. if ifi.Interface != nil && ifi.Interface.Index > 0 {
  38. attrs |= attrIfIndex
  39. l += 4
  40. if len(ifi.Interface.Name) > 0 {
  41. attrs |= attrName
  42. l += ifi.nameLen()
  43. }
  44. if ifi.Interface.MTU > 0 {
  45. attrs |= attrMTU
  46. l += 4
  47. }
  48. }
  49. if ifi.Addr != nil {
  50. switch proto {
  51. case iana.ProtocolICMP:
  52. if ifi.Addr.IP.To4() != nil {
  53. attrs |= attrIPAddr
  54. l += 4 + net.IPv4len
  55. }
  56. case iana.ProtocolIPv6ICMP:
  57. if ifi.Addr.IP.To16() != nil && ifi.Addr.IP.To4() == nil {
  58. attrs |= attrIPAddr
  59. l += 4 + net.IPv6len
  60. }
  61. }
  62. }
  63. return
  64. }
  65. // Len implements the Len method of Extension interface.
  66. func (ifi *InterfaceInfo) Len(proto int) int {
  67. _, l := ifi.attrsAndLen(proto)
  68. return l
  69. }
  70. // Marshal implements the Marshal method of Extension interface.
  71. func (ifi *InterfaceInfo) Marshal(proto int) ([]byte, error) {
  72. attrs, l := ifi.attrsAndLen(proto)
  73. b := make([]byte, l)
  74. if err := ifi.marshal(proto, b, attrs, l); err != nil {
  75. return nil, err
  76. }
  77. return b, nil
  78. }
  79. func (ifi *InterfaceInfo) marshal(proto int, b []byte, attrs, l int) error {
  80. b[0], b[1] = byte(l>>8), byte(l)
  81. b[2], b[3] = classInterfaceInfo, byte(ifi.Type)
  82. for b = b[4:]; len(b) > 0 && attrs != 0; {
  83. switch {
  84. case attrs&attrIfIndex != 0:
  85. b = ifi.marshalIfIndex(proto, b)
  86. attrs &^= attrIfIndex
  87. case attrs&attrIPAddr != 0:
  88. b = ifi.marshalIPAddr(proto, b)
  89. attrs &^= attrIPAddr
  90. case attrs&attrName != 0:
  91. b = ifi.marshalName(proto, b)
  92. attrs &^= attrName
  93. case attrs&attrMTU != 0:
  94. b = ifi.marshalMTU(proto, b)
  95. attrs &^= attrMTU
  96. }
  97. }
  98. return nil
  99. }
  100. func (ifi *InterfaceInfo) marshalIfIndex(proto int, b []byte) []byte {
  101. b[0], b[1], b[2], b[3] = byte(ifi.Interface.Index>>24), byte(ifi.Interface.Index>>16), byte(ifi.Interface.Index>>8), byte(ifi.Interface.Index)
  102. return b[4:]
  103. }
  104. func (ifi *InterfaceInfo) parseIfIndex(b []byte) ([]byte, error) {
  105. if len(b) < 4 {
  106. return nil, errMessageTooShort
  107. }
  108. ifi.Interface.Index = int(b[0])<<24 | int(b[1])<<16 | int(b[2])<<8 | int(b[3])
  109. return b[4:], nil
  110. }
  111. func (ifi *InterfaceInfo) marshalIPAddr(proto int, b []byte) []byte {
  112. switch proto {
  113. case iana.ProtocolICMP:
  114. b[0], b[1] = byte(afiIPv4>>8), byte(afiIPv4)
  115. copy(b[4:4+net.IPv4len], ifi.Addr.IP.To4())
  116. b = b[4+net.IPv4len:]
  117. case iana.ProtocolIPv6ICMP:
  118. b[0], b[1] = byte(afiIPv6>>8), byte(afiIPv6)
  119. copy(b[4:4+net.IPv6len], ifi.Addr.IP.To16())
  120. b = b[4+net.IPv6len:]
  121. }
  122. return b
  123. }
  124. func (ifi *InterfaceInfo) parseIPAddr(b []byte) ([]byte, error) {
  125. if len(b) < 4 {
  126. return nil, errMessageTooShort
  127. }
  128. afi := int(b[0])<<8 | int(b[1])
  129. b = b[4:]
  130. switch afi {
  131. case afiIPv4:
  132. if len(b) < net.IPv4len {
  133. return nil, errMessageTooShort
  134. }
  135. ifi.Addr.IP = make(net.IP, net.IPv4len)
  136. copy(ifi.Addr.IP, b[:net.IPv4len])
  137. b = b[net.IPv4len:]
  138. case afiIPv6:
  139. if len(b) < net.IPv6len {
  140. return nil, errMessageTooShort
  141. }
  142. ifi.Addr.IP = make(net.IP, net.IPv6len)
  143. copy(ifi.Addr.IP, b[:net.IPv6len])
  144. b = b[net.IPv6len:]
  145. }
  146. return b, nil
  147. }
  148. func (ifi *InterfaceInfo) marshalName(proto int, b []byte) []byte {
  149. l := byte(ifi.nameLen())
  150. b[0] = l
  151. copy(b[1:], []byte(ifi.Interface.Name))
  152. return b[l:]
  153. }
  154. func (ifi *InterfaceInfo) parseName(b []byte) ([]byte, error) {
  155. if 4 > len(b) || len(b) < int(b[0]) {
  156. return nil, errMessageTooShort
  157. }
  158. l := int(b[0])
  159. if l%4 != 0 || 4 > l || l > 64 {
  160. return nil, errInvalidExtension
  161. }
  162. var name [63]byte
  163. copy(name[:], b[1:l])
  164. ifi.Interface.Name = strings.Trim(string(name[:]), "\000")
  165. return b[l:], nil
  166. }
  167. func (ifi *InterfaceInfo) marshalMTU(proto int, b []byte) []byte {
  168. b[0], b[1], b[2], b[3] = byte(ifi.Interface.MTU>>24), byte(ifi.Interface.MTU>>16), byte(ifi.Interface.MTU>>8), byte(ifi.Interface.MTU)
  169. return b[4:]
  170. }
  171. func (ifi *InterfaceInfo) parseMTU(b []byte) ([]byte, error) {
  172. if len(b) < 4 {
  173. return nil, errMessageTooShort
  174. }
  175. ifi.Interface.MTU = int(b[0])<<24 | int(b[1])<<16 | int(b[2])<<8 | int(b[3])
  176. return b[4:], nil
  177. }
  178. func parseInterfaceInfo(b []byte) (Extension, error) {
  179. ifi := &InterfaceInfo{
  180. Class: int(b[2]),
  181. Type: int(b[3]),
  182. }
  183. if ifi.Type&(attrIfIndex|attrName|attrMTU) != 0 {
  184. ifi.Interface = &net.Interface{}
  185. }
  186. if ifi.Type&attrIPAddr != 0 {
  187. ifi.Addr = &net.IPAddr{}
  188. }
  189. attrs := ifi.Type & (attrIfIndex | attrIPAddr | attrName | attrMTU)
  190. for b = b[4:]; len(b) > 0 && attrs != 0; {
  191. var err error
  192. switch {
  193. case attrs&attrIfIndex != 0:
  194. b, err = ifi.parseIfIndex(b)
  195. attrs &^= attrIfIndex
  196. case attrs&attrIPAddr != 0:
  197. b, err = ifi.parseIPAddr(b)
  198. attrs &^= attrIPAddr
  199. case attrs&attrName != 0:
  200. b, err = ifi.parseName(b)
  201. attrs &^= attrName
  202. case attrs&attrMTU != 0:
  203. b, err = ifi.parseMTU(b)
  204. attrs &^= attrMTU
  205. }
  206. if err != nil {
  207. return nil, err
  208. }
  209. }
  210. if ifi.Interface != nil && ifi.Interface.Name != "" && ifi.Addr != nil && ifi.Addr.IP.To16() != nil && ifi.Addr.IP.To4() == nil {
  211. ifi.Addr.Zone = ifi.Interface.Name
  212. }
  213. return ifi, nil
  214. }