github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/libnetwork/portmapper/mapper_linux_test.go (about) 1 package portmapper 2 3 import ( 4 "net" 5 "strings" 6 "testing" 7 8 "github.com/docker/docker/libnetwork/iptables" 9 ) 10 11 func init() { 12 // override this func to mock out the proxy server 13 newProxy = newMockProxyCommand 14 } 15 16 func TestSetIptablesChain(t *testing.T) { 17 pm := New("") 18 19 c := &iptables.ChainInfo{ 20 Name: "TEST", 21 } 22 23 if pm.chain != nil { 24 t.Fatal("chain should be nil at init") 25 } 26 27 pm.SetIptablesChain(c, "lo") 28 if pm.chain == nil { 29 t.Fatal("chain should not be nil after set") 30 } 31 } 32 33 func TestMapTCPPorts(t *testing.T) { 34 pm := New("") 35 dstIP1 := net.ParseIP("192.168.0.1") 36 dstIP2 := net.ParseIP("192.168.0.2") 37 dstAddr1 := &net.TCPAddr{IP: dstIP1, Port: 80} 38 dstAddr2 := &net.TCPAddr{IP: dstIP2, Port: 80} 39 40 srcAddr1 := &net.TCPAddr{Port: 1080, IP: net.ParseIP("172.16.0.1")} 41 srcAddr2 := &net.TCPAddr{Port: 1080, IP: net.ParseIP("172.16.0.2")} 42 43 addrEqual := func(addr1, addr2 net.Addr) bool { 44 return (addr1.Network() == addr2.Network()) && (addr1.String() == addr2.String()) 45 } 46 47 if host, err := pm.Map(srcAddr1, dstIP1, 80, true); err != nil { 48 t.Fatalf("Failed to allocate port: %s", err) 49 } else if !addrEqual(dstAddr1, host) { 50 t.Fatalf("Incorrect mapping result: expected %s:%s, got %s:%s", 51 dstAddr1.String(), dstAddr1.Network(), host.String(), host.Network()) 52 } 53 54 if _, err := pm.Map(srcAddr1, dstIP1, 80, true); err == nil { 55 t.Fatalf("Port is in use - mapping should have failed") 56 } 57 58 if _, err := pm.Map(srcAddr2, dstIP1, 80, true); err == nil { 59 t.Fatalf("Port is in use - mapping should have failed") 60 } 61 62 if _, err := pm.Map(srcAddr2, dstIP2, 80, true); err != nil { 63 t.Fatalf("Failed to allocate port: %s", err) 64 } 65 66 if pm.Unmap(dstAddr1) != nil { 67 t.Fatalf("Failed to release port") 68 } 69 70 if pm.Unmap(dstAddr2) != nil { 71 t.Fatalf("Failed to release port") 72 } 73 74 if pm.Unmap(dstAddr2) == nil { 75 t.Fatalf("Port already released, but no error reported") 76 } 77 } 78 79 func TestGetUDPKey(t *testing.T) { 80 addr := &net.UDPAddr{IP: net.ParseIP("192.168.1.5"), Port: 53} 81 82 key := getKey(addr) 83 84 if expected := "192.168.1.5:53/udp"; key != expected { 85 t.Fatalf("expected key %s got %s", expected, key) 86 } 87 } 88 89 func TestGetTCPKey(t *testing.T) { 90 addr := &net.TCPAddr{IP: net.ParseIP("192.168.1.5"), Port: 80} 91 92 key := getKey(addr) 93 94 if expected := "192.168.1.5:80/tcp"; key != expected { 95 t.Fatalf("expected key %s got %s", expected, key) 96 } 97 } 98 99 func TestGetUDPIPAndPort(t *testing.T) { 100 addr := &net.UDPAddr{IP: net.ParseIP("192.168.1.5"), Port: 53} 101 102 ip, port := getIPAndPort(addr) 103 if expected := "192.168.1.5"; ip.String() != expected { 104 t.Fatalf("expected ip %s got %s", expected, ip) 105 } 106 107 if ep := 53; port != ep { 108 t.Fatalf("expected port %d got %d", ep, port) 109 } 110 } 111 112 func TestMapUDPPorts(t *testing.T) { 113 pm := New("") 114 dstIP1 := net.ParseIP("192.168.0.1") 115 dstIP2 := net.ParseIP("192.168.0.2") 116 dstAddr1 := &net.UDPAddr{IP: dstIP1, Port: 80} 117 dstAddr2 := &net.UDPAddr{IP: dstIP2, Port: 80} 118 119 srcAddr1 := &net.UDPAddr{Port: 1080, IP: net.ParseIP("172.16.0.1")} 120 srcAddr2 := &net.UDPAddr{Port: 1080, IP: net.ParseIP("172.16.0.2")} 121 122 addrEqual := func(addr1, addr2 net.Addr) bool { 123 return (addr1.Network() == addr2.Network()) && (addr1.String() == addr2.String()) 124 } 125 126 if host, err := pm.Map(srcAddr1, dstIP1, 80, true); err != nil { 127 t.Fatalf("Failed to allocate port: %s", err) 128 } else if !addrEqual(dstAddr1, host) { 129 t.Fatalf("Incorrect mapping result: expected %s:%s, got %s:%s", 130 dstAddr1.String(), dstAddr1.Network(), host.String(), host.Network()) 131 } 132 133 if _, err := pm.Map(srcAddr1, dstIP1, 80, true); err == nil { 134 t.Fatalf("Port is in use - mapping should have failed") 135 } 136 137 if _, err := pm.Map(srcAddr2, dstIP1, 80, true); err == nil { 138 t.Fatalf("Port is in use - mapping should have failed") 139 } 140 141 if _, err := pm.Map(srcAddr2, dstIP2, 80, true); err != nil { 142 t.Fatalf("Failed to allocate port: %s", err) 143 } 144 145 if pm.Unmap(dstAddr1) != nil { 146 t.Fatalf("Failed to release port") 147 } 148 149 if pm.Unmap(dstAddr2) != nil { 150 t.Fatalf("Failed to release port") 151 } 152 153 if pm.Unmap(dstAddr2) == nil { 154 t.Fatalf("Port already released, but no error reported") 155 } 156 } 157 158 func TestMapAllPortsSingleInterface(t *testing.T) { 159 pm := New("") 160 dstIP1 := net.ParseIP("0.0.0.0") 161 srcAddr1 := &net.TCPAddr{Port: 1080, IP: net.ParseIP("172.16.0.1")} 162 163 hosts := []net.Addr{} 164 var host net.Addr 165 var err error 166 167 defer func() { 168 for _, val := range hosts { 169 pm.Unmap(val) 170 } 171 }() 172 173 for i := 0; i < 10; i++ { 174 start, end := pm.Allocator.Begin, pm.Allocator.End 175 for i := start; i < end; i++ { 176 if host, err = pm.Map(srcAddr1, dstIP1, 0, true); err != nil { 177 t.Fatal(err) 178 } 179 180 hosts = append(hosts, host) 181 } 182 183 if _, err := pm.Map(srcAddr1, dstIP1, start, true); err == nil { 184 t.Fatalf("Port %d should be bound but is not", start) 185 } 186 187 for _, val := range hosts { 188 if err := pm.Unmap(val); err != nil { 189 t.Fatal(err) 190 } 191 } 192 193 hosts = []net.Addr{} 194 } 195 } 196 197 func TestMapTCPDummyListen(t *testing.T) { 198 pm := New("") 199 dstIP := net.ParseIP("0.0.0.0") 200 dstAddr := &net.TCPAddr{IP: dstIP, Port: 80} 201 202 // no-op for dummy 203 srcAddr := &net.TCPAddr{Port: 1080, IP: net.ParseIP("172.16.0.1")} 204 205 addrEqual := func(addr1, addr2 net.Addr) bool { 206 return (addr1.Network() == addr2.Network()) && (addr1.String() == addr2.String()) 207 } 208 209 if host, err := pm.Map(srcAddr, dstIP, 80, false); err != nil { 210 t.Fatalf("Failed to allocate port: %s", err) 211 } else if !addrEqual(dstAddr, host) { 212 t.Fatalf("Incorrect mapping result: expected %s:%s, got %s:%s", 213 dstAddr.String(), dstAddr.Network(), host.String(), host.Network()) 214 } 215 if _, err := net.Listen("tcp", "0.0.0.0:80"); err == nil { 216 t.Fatal("Listen on mapped port without proxy should fail") 217 } else { 218 if !strings.Contains(err.Error(), "address already in use") { 219 t.Fatalf("Error should be about address already in use, got %v", err) 220 } 221 } 222 if _, err := net.Listen("tcp", "0.0.0.0:81"); err != nil { 223 t.Fatal(err) 224 } 225 if host, err := pm.Map(srcAddr, dstIP, 81, false); err == nil { 226 t.Fatalf("Bound port shouldn't be allocated, but it was on: %v", host) 227 } else { 228 if !strings.Contains(err.Error(), "address already in use") { 229 t.Fatalf("Error should be about address already in use, got %v", err) 230 } 231 } 232 } 233 234 func TestMapUDPDummyListen(t *testing.T) { 235 pm := New("") 236 dstIP := net.ParseIP("0.0.0.0") 237 dstAddr := &net.UDPAddr{IP: dstIP, Port: 80} 238 239 // no-op for dummy 240 srcAddr := &net.UDPAddr{Port: 1080, IP: net.ParseIP("172.16.0.1")} 241 242 addrEqual := func(addr1, addr2 net.Addr) bool { 243 return (addr1.Network() == addr2.Network()) && (addr1.String() == addr2.String()) 244 } 245 246 if host, err := pm.Map(srcAddr, dstIP, 80, false); err != nil { 247 t.Fatalf("Failed to allocate port: %s", err) 248 } else if !addrEqual(dstAddr, host) { 249 t.Fatalf("Incorrect mapping result: expected %s:%s, got %s:%s", 250 dstAddr.String(), dstAddr.Network(), host.String(), host.Network()) 251 } 252 if _, err := net.ListenUDP("udp", &net.UDPAddr{IP: dstIP, Port: 80}); err == nil { 253 t.Fatal("Listen on mapped port without proxy should fail") 254 } else { 255 if !strings.Contains(err.Error(), "address already in use") { 256 t.Fatalf("Error should be about address already in use, got %v", err) 257 } 258 } 259 if _, err := net.ListenUDP("udp", &net.UDPAddr{IP: dstIP, Port: 81}); err != nil { 260 t.Fatal(err) 261 } 262 if host, err := pm.Map(srcAddr, dstIP, 81, false); err == nil { 263 t.Fatalf("Bound port shouldn't be allocated, but it was on: %v", host) 264 } else { 265 if !strings.Contains(err.Error(), "address already in use") { 266 t.Fatalf("Error should be about address already in use, got %v", err) 267 } 268 } 269 }