xoraddr.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. package stun
  4. import (
  5. "errors"
  6. "fmt"
  7. "io"
  8. "net"
  9. "strconv"
  10. "github.com/pion/transport/v2/utils/xor"
  11. )
  12. const (
  13. familyIPv4 uint16 = 0x01
  14. familyIPv6 uint16 = 0x02
  15. )
  16. // XORMappedAddress implements XOR-MAPPED-ADDRESS attribute.
  17. //
  18. // RFC 5389 Section 15.2
  19. type XORMappedAddress struct {
  20. IP net.IP
  21. Port int
  22. }
  23. func (a XORMappedAddress) String() string {
  24. return net.JoinHostPort(a.IP.String(), strconv.Itoa(a.Port))
  25. }
  26. // isIPv4 returns true if ip with len of net.IPv6Len seems to be ipv4.
  27. func isIPv4(ip net.IP) bool {
  28. // Optimized for performance. Copied from net.IP.To4.
  29. return isZeros(ip[0:10]) && ip[10] == 0xff && ip[11] == 0xff
  30. }
  31. // Is p all zeros?
  32. func isZeros(p net.IP) bool {
  33. for i := 0; i < len(p); i++ {
  34. if p[i] != 0 {
  35. return false
  36. }
  37. }
  38. return true
  39. }
  40. // ErrBadIPLength means that len(IP) is not net.{IPv6len,IPv4len}.
  41. var ErrBadIPLength = errors.New("invalid length of IP value")
  42. // AddToAs adds XOR-MAPPED-ADDRESS value to m as t attribute.
  43. func (a XORMappedAddress) AddToAs(m *Message, t AttrType) error {
  44. var (
  45. family = familyIPv4
  46. ip = a.IP
  47. )
  48. if len(a.IP) == net.IPv6len {
  49. if isIPv4(ip) {
  50. ip = ip[12:16] // like in ip.To4()
  51. } else {
  52. family = familyIPv6
  53. }
  54. } else if len(ip) != net.IPv4len {
  55. return ErrBadIPLength
  56. }
  57. value := make([]byte, 32+128)
  58. value[0] = 0 // first 8 bits are zeroes
  59. xorValue := make([]byte, net.IPv6len)
  60. copy(xorValue[4:], m.TransactionID[:])
  61. bin.PutUint32(xorValue[0:4], magicCookie)
  62. bin.PutUint16(value[0:2], family)
  63. bin.PutUint16(value[2:4], uint16(a.Port^magicCookie>>16))
  64. xor.XorBytes(value[4:4+len(ip)], ip, xorValue)
  65. m.Add(t, value[:4+len(ip)])
  66. return nil
  67. }
  68. // AddTo adds XOR-MAPPED-ADDRESS to m. Can return ErrBadIPLength
  69. // if len(a.IP) is invalid.
  70. func (a XORMappedAddress) AddTo(m *Message) error {
  71. return a.AddToAs(m, AttrXORMappedAddress)
  72. }
  73. // GetFromAs decodes XOR-MAPPED-ADDRESS attribute value in message
  74. // getting it as for t type.
  75. func (a *XORMappedAddress) GetFromAs(m *Message, t AttrType) error {
  76. v, err := m.Get(t)
  77. if err != nil {
  78. return err
  79. }
  80. family := bin.Uint16(v[0:2])
  81. if family != familyIPv6 && family != familyIPv4 {
  82. return newDecodeErr("xor-mapped address", "family",
  83. fmt.Sprintf("bad value %d", family),
  84. )
  85. }
  86. ipLen := net.IPv4len
  87. if family == familyIPv6 {
  88. ipLen = net.IPv6len
  89. }
  90. // Ensuring len(a.IP) == ipLen and reusing a.IP.
  91. if len(a.IP) < ipLen {
  92. a.IP = a.IP[:cap(a.IP)]
  93. for len(a.IP) < ipLen {
  94. a.IP = append(a.IP, 0)
  95. }
  96. }
  97. a.IP = a.IP[:ipLen]
  98. for i := range a.IP {
  99. a.IP[i] = 0
  100. }
  101. if len(v) <= 4 {
  102. return io.ErrUnexpectedEOF
  103. }
  104. if err := CheckOverflow(t, len(v[4:]), len(a.IP)); err != nil {
  105. return err
  106. }
  107. a.Port = int(bin.Uint16(v[2:4])) ^ (magicCookie >> 16)
  108. xorValue := make([]byte, 4+TransactionIDSize)
  109. bin.PutUint32(xorValue[0:4], magicCookie)
  110. copy(xorValue[4:], m.TransactionID[:])
  111. xor.XorBytes(a.IP, v[4:], xorValue)
  112. return nil
  113. }
  114. // GetFrom decodes XOR-MAPPED-ADDRESS attribute in message and returns
  115. // error if any. While decoding, a.IP is reused if possible and can be
  116. // rendered to invalid state (e.g. if a.IP was set to IPv6 and then
  117. // IPv4 value were decoded into it), be careful.
  118. //
  119. // Example:
  120. //
  121. // expectedIP := net.ParseIP("213.141.156.236")
  122. // expectedIP.String() // 213.141.156.236, 16 bytes, first 12 of them are zeroes
  123. // expectedPort := 21254
  124. // addr := &XORMappedAddress{
  125. // IP: expectedIP,
  126. // Port: expectedPort,
  127. // }
  128. // // addr were added to message that is decoded as newMessage
  129. // // ...
  130. //
  131. // addr.GetFrom(newMessage)
  132. // addr.IP.String() // 213.141.156.236, net.IPv4Len
  133. // expectedIP.String() // d58d:9cec::ffff:d58d:9cec, 16 bytes, first 4 are IPv4
  134. // // now we have len(expectedIP) = 16 and len(addr.IP) = 4.
  135. func (a *XORMappedAddress) GetFrom(m *Message) error {
  136. return a.GetFromAs(m, AttrXORMappedAddress)
  137. }