external_ip_mapper.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. package ice
  2. import (
  3. "net"
  4. "strings"
  5. )
  6. func validateIPString(ipStr string) (net.IP, bool, error) {
  7. ip := net.ParseIP(ipStr)
  8. if ip == nil {
  9. return nil, false, ErrInvalidNAT1To1IPMapping
  10. }
  11. return ip, (ip.To4() != nil), nil
  12. }
  13. // ipMapping holds the mapping of local and external IP address for a particular IP family
  14. type ipMapping struct {
  15. ipSole net.IP // when non-nil, this is the sole external IP for one local IP assumed
  16. ipMap map[string]net.IP // local-to-external IP mapping (k: local, v: external)
  17. }
  18. func (m *ipMapping) setSoleIP(ip net.IP) error {
  19. if m.ipSole != nil || len(m.ipMap) > 0 {
  20. return ErrInvalidNAT1To1IPMapping
  21. }
  22. m.ipSole = ip
  23. return nil
  24. }
  25. func (m *ipMapping) addIPMapping(locIP, extIP net.IP) error {
  26. if m.ipSole != nil {
  27. return ErrInvalidNAT1To1IPMapping
  28. }
  29. locIPStr := locIP.String()
  30. // check if dup of local IP
  31. if _, ok := m.ipMap[locIPStr]; ok {
  32. return ErrInvalidNAT1To1IPMapping
  33. }
  34. m.ipMap[locIPStr] = extIP
  35. return nil
  36. }
  37. func (m *ipMapping) findExternalIP(locIP net.IP) (net.IP, error) {
  38. if m.ipSole != nil {
  39. return m.ipSole, nil
  40. }
  41. extIP, ok := m.ipMap[locIP.String()]
  42. if !ok {
  43. return nil, ErrExternalMappedIPNotFound
  44. }
  45. return extIP, nil
  46. }
  47. type externalIPMapper struct {
  48. ipv4Mapping ipMapping
  49. ipv6Mapping ipMapping
  50. candidateType CandidateType
  51. }
  52. func newExternalIPMapper(candidateType CandidateType, ips []string) (*externalIPMapper, error) { //nolint:gocognit
  53. if len(ips) == 0 {
  54. return nil, nil
  55. }
  56. if candidateType == CandidateTypeUnspecified {
  57. candidateType = CandidateTypeHost // defaults to host
  58. } else if candidateType != CandidateTypeHost && candidateType != CandidateTypeServerReflexive {
  59. return nil, ErrUnsupportedNAT1To1IPCandidateType
  60. }
  61. m := &externalIPMapper{
  62. ipv4Mapping: ipMapping{ipMap: map[string]net.IP{}},
  63. ipv6Mapping: ipMapping{ipMap: map[string]net.IP{}},
  64. candidateType: candidateType,
  65. }
  66. for _, extIPStr := range ips {
  67. ipPair := strings.Split(extIPStr, "/")
  68. if len(ipPair) == 0 || len(ipPair) > 2 {
  69. return nil, ErrInvalidNAT1To1IPMapping
  70. }
  71. extIP, isExtIPv4, err := validateIPString(ipPair[0])
  72. if err != nil {
  73. return nil, err
  74. }
  75. if len(ipPair) == 1 {
  76. if isExtIPv4 {
  77. if err := m.ipv4Mapping.setSoleIP(extIP); err != nil {
  78. return nil, err
  79. }
  80. } else {
  81. if err := m.ipv6Mapping.setSoleIP(extIP); err != nil {
  82. return nil, err
  83. }
  84. }
  85. } else {
  86. locIP, isLocIPv4, err := validateIPString(ipPair[1])
  87. if err != nil {
  88. return nil, err
  89. }
  90. if isExtIPv4 {
  91. if !isLocIPv4 {
  92. return nil, ErrInvalidNAT1To1IPMapping
  93. }
  94. if err := m.ipv4Mapping.addIPMapping(locIP, extIP); err != nil {
  95. return nil, err
  96. }
  97. } else {
  98. if isLocIPv4 {
  99. return nil, ErrInvalidNAT1To1IPMapping
  100. }
  101. if err := m.ipv6Mapping.addIPMapping(locIP, extIP); err != nil {
  102. return nil, err
  103. }
  104. }
  105. }
  106. }
  107. return m, nil
  108. }
  109. func (m *externalIPMapper) findExternalIP(localIPStr string) (net.IP, error) {
  110. locIP, isLocIPv4, err := validateIPString(localIPStr)
  111. if err != nil {
  112. return nil, err
  113. }
  114. if isLocIPv4 {
  115. return m.ipv4Mapping.findExternalIP(locIP)
  116. }
  117. return m.ipv6Mapping.findExternalIP(locIP)
  118. }