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