@@ -11,71 +11,113 @@ import (
1111 "github.com/sirupsen/logrus"
1212)
1313
14- var (
15- defaultBindingIP = net .IPv4 (0 , 0 , 0 , 0 )
16- defaultBindingIPV6 = net .ParseIP ("::" )
17- )
18-
1914func (n * bridgeNetwork ) allocatePorts (ep * bridgeEndpoint , reqDefBindIP net.IP , ulPxyEnabled bool ) ([]types.PortBinding , error ) {
2015 if ep .extConnConfig == nil || ep .extConnConfig .PortBindings == nil {
2116 return nil , nil
2217 }
2318
24- defHostIP := defaultBindingIP
19+ defHostIP := net . IPv4zero // 0.0.0.0
2520 if reqDefBindIP != nil {
2621 defHostIP = reqDefBindIP
2722 }
2823
29- // IPv4 port binding including user land proxy
30- pb , err := n .allocatePortsInternal (ep .extConnConfig .PortBindings , ep .addr .IP , defHostIP , ulPxyEnabled )
31- if err != nil {
32- return nil , err
24+ var containerIPv6 net.IP
25+ if ep .addrv6 != nil {
26+ containerIPv6 = ep .addrv6 .IP
3327 }
3428
35- // IPv6 port binding excluding user land proxy
36- if n .driver .config .EnableIP6Tables && ep .addrv6 != nil {
37- // TODO IPv6 custom default binding IP
38- pbv6 , err := n .allocatePortsInternal (ep .extConnConfig .PortBindings , ep .addrv6 .IP , defaultBindingIPV6 , false )
39- if err != nil {
40- // ensure we clear the previous allocated IPv4 ports
41- n .releasePortsInternal (pb )
42- return nil , err
43- }
44-
45- pb = append (pb , pbv6 ... )
29+ pb , err := n .allocatePortsInternal (ep .extConnConfig .PortBindings , ep .addr .IP , containerIPv6 , defHostIP , ulPxyEnabled )
30+ if err != nil {
31+ return nil , err
4632 }
4733 return pb , nil
4834}
4935
50- func (n * bridgeNetwork ) allocatePortsInternal (bindings []types.PortBinding , containerIP , defHostIP net.IP , ulPxyEnabled bool ) ([]types.PortBinding , error ) {
36+ func (n * bridgeNetwork ) allocatePortsInternal (bindings []types.PortBinding , containerIPv4 , containerIPv6 , defHostIP net.IP , ulPxyEnabled bool ) ([]types.PortBinding , error ) {
5137 bs := make ([]types.PortBinding , 0 , len (bindings ))
5238 for _ , c := range bindings {
53- b := c .GetCopy ()
54- if err := n .allocatePort (& b , containerIP , defHostIP , ulPxyEnabled ); err != nil {
55- // On allocation failure, release previously allocated ports. On cleanup error, just log a warning message
56- if cuErr := n .releasePortsInternal (bs ); cuErr != nil {
57- logrus .Warnf ("Upon allocation failure for %v, failed to clear previously allocated port bindings: %v" , b , cuErr )
39+ bIPv4 := c .GetCopy ()
40+ bIPv6 := c .GetCopy ()
41+ // Allocate IPv4 Port mappings
42+ if ok := n .validatePortBindingIPv4 (& bIPv4 , containerIPv4 , defHostIP ); ok {
43+ if err := n .allocatePort (& bIPv4 , ulPxyEnabled ); err != nil {
44+ // On allocation failure, release previously allocated ports. On cleanup error, just log a warning message
45+ if cuErr := n .releasePortsInternal (bs ); cuErr != nil {
46+ logrus .Warnf ("allocation failure for %v, failed to clear previously allocated ipv4 port bindings: %v" , bIPv4 , cuErr )
47+ }
48+ return nil , err
5849 }
59- return nil , err
50+ bs = append (bs , bIPv4 )
51+ }
52+ // Allocate IPv6 Port mappings
53+ if ok := n .validatePortBindingIPv6 (& bIPv6 , containerIPv6 , defHostIP ); ok {
54+ if err := n .allocatePort (& bIPv6 , ulPxyEnabled ); err != nil {
55+ // On allocation failure, release previously allocated ports. On cleanup error, just log a warning message
56+ if cuErr := n .releasePortsInternal (bs ); cuErr != nil {
57+ logrus .Warnf ("allocation failure for %v, failed to clear previously allocated ipv6 port bindings: %v" , bIPv6 , cuErr )
58+ }
59+ return nil , err
60+ }
61+ bs = append (bs , bIPv6 )
6062 }
61- bs = append (bs , b )
6263 }
6364 return bs , nil
6465}
6566
66- func (n * bridgeNetwork ) allocatePort (bnd * types.PortBinding , containerIP , defHostIP net.IP , ulPxyEnabled bool ) error {
67- var (
68- host net.Addr
69- err error
70- )
71-
72- // Store the container interface address in the operational binding
73- bnd .IP = containerIP
74-
67+ // validatePortBindingIPv4 validates the port binding, populates the missing Host IP field and returns true
68+ // if this is a valid IPv4 binding, else returns false
69+ func (n * bridgeNetwork ) validatePortBindingIPv4 (bnd * types.PortBinding , containerIPv4 , defHostIP net.IP ) bool {
70+ //Return early if there is a valid Host IP, but its not a IPv6 address
71+ if len (bnd .HostIP ) > 0 && bnd .HostIP .To4 () == nil {
72+ return false
73+ }
7574 // Adjust the host address in the operational binding
7675 if len (bnd .HostIP ) == 0 {
76+ // Return early if the default binding address is an IPv6 address
77+ if defHostIP .To4 () == nil {
78+ return false
79+ }
7780 bnd .HostIP = defHostIP
7881 }
82+ bnd .IP = containerIPv4
83+ return true
84+
85+ }
86+
87+ // validatePortBindingIPv6 validates the port binding, populates the missing Host IP field and returns true
88+ // if this is a valid IP6v binding, else returns false
89+ func (n * bridgeNetwork ) validatePortBindingIPv6 (bnd * types.PortBinding , containerIPv6 , defHostIP net.IP ) bool {
90+ // Return early if there is no IPv6 container endpoint
91+ if containerIPv6 == nil {
92+ return false
93+ }
94+ // Return early if there is a valid Host IP, which is a IPv4 address
95+ if len (bnd .HostIP ) > 0 && bnd .HostIP .To4 () != nil {
96+ return false
97+ }
98+
99+ // Setup a binding to "::" if Host IP is empty and the default binding IP is 0.0.0.0
100+ if len (bnd .HostIP ) == 0 {
101+ if defHostIP .Equal (net .IPv4zero ) {
102+ bnd .HostIP = net .IPv6zero
103+ // If the default binding IP is an IPv6 address, use it
104+ } else if defHostIP .To4 () == nil {
105+ bnd .HostIP = defHostIP
106+ // Return false if default binding ip is an IPv4 address
107+ } else {
108+ return false
109+ }
110+ }
111+ bnd .IP = containerIPv6
112+ return true
113+
114+ }
115+
116+ func (n * bridgeNetwork ) allocatePort (bnd * types.PortBinding , ulPxyEnabled bool ) error {
117+ var (
118+ host net.Addr
119+ err error
120+ )
79121
80122 // Adjust HostPortEnd if this is not a range.
81123 if bnd .HostPortEnd == 0 {
@@ -90,7 +132,7 @@ func (n *bridgeNetwork) allocatePort(bnd *types.PortBinding, containerIP, defHos
90132
91133 portmapper := n .portMapper
92134
93- if containerIP .To4 () == nil {
135+ if bnd . IP .To4 () == nil {
94136 portmapper = n .portMapperV6
95137 }
96138
0 commit comments