mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
7f473c779a
This fix tries to fix logrus formatting by removing `f` from `logrus.[Error|Warn|Debug|Fatal|Panic|Info]f` when formatting string is not present. Also fix import name to use original project name 'logrus' instead of 'log' Signed-off-by: Daehyeok Mun <daehyeok@gmail.com>
225 lines
5.2 KiB
Go
225 lines
5.2 KiB
Go
// +build solaris
|
|
|
|
package bridge
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"os"
|
|
"os/exec"
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
"github.com/docker/libnetwork/types"
|
|
)
|
|
|
|
var (
|
|
defaultBindingIP = net.IPv4(0, 0, 0, 0)
|
|
)
|
|
|
|
const (
|
|
maxAllocatePortAttempts = 10
|
|
)
|
|
|
|
func addPFRules(epid, bindIntf string, bs []types.PortBinding) {
|
|
var id string
|
|
|
|
if len(epid) > 12 {
|
|
id = epid[:12]
|
|
} else {
|
|
id = epid
|
|
}
|
|
|
|
fname := "/var/lib/docker/network/files/pf." + id
|
|
|
|
f, err := os.OpenFile(fname,
|
|
os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
|
|
if err != nil {
|
|
logrus.Warn("cannot open temp pf file")
|
|
return
|
|
}
|
|
for _, b := range bs {
|
|
r := fmt.Sprintf(
|
|
"pass in on %s proto %s from any to (%s) "+
|
|
"port %d rdr-to %s port %d\n", bindIntf,
|
|
b.Proto.String(), bindIntf, b.HostPort,
|
|
b.IP.String(), b.Port)
|
|
_, err = f.WriteString(r)
|
|
if err != nil {
|
|
logrus.Warnf("cannot write firewall rules to %s: %v", fname, err)
|
|
}
|
|
}
|
|
f.Close()
|
|
|
|
anchor := fmt.Sprintf("_auto/docker/ep%s", id)
|
|
err = exec.Command("/usr/sbin/pfctl", "-a", anchor, "-f", fname).Run()
|
|
if err != nil {
|
|
logrus.Warnf("failed to add firewall rules: %v", err)
|
|
}
|
|
os.Remove(fname)
|
|
}
|
|
|
|
func removePFRules(epid string) {
|
|
var id string
|
|
|
|
if len(epid) > 12 {
|
|
id = epid[:12]
|
|
} else {
|
|
id = epid
|
|
}
|
|
|
|
anchor := fmt.Sprintf("_auto/docker/ep%s", id)
|
|
err := exec.Command("/usr/sbin/pfctl", "-a", anchor, "-F", "all").Run()
|
|
if err != nil {
|
|
logrus.Warnf("failed to remove firewall rules: %v", err)
|
|
}
|
|
}
|
|
|
|
func (n *bridgeNetwork) allocatePorts(ep *bridgeEndpoint, bindIntf string, reqDefBindIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
|
|
if ep.extConnConfig == nil || ep.extConnConfig.PortBindings == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
defHostIP := defaultBindingIP
|
|
if reqDefBindIP != nil {
|
|
defHostIP = reqDefBindIP
|
|
}
|
|
|
|
bs, err := n.allocatePortsInternal(ep.extConnConfig.PortBindings, bindIntf, ep.addr.IP, defHostIP, ulPxyEnabled)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Add PF rules for port bindings, if any
|
|
if len(bs) > 0 {
|
|
addPFRules(ep.id, bindIntf, bs)
|
|
}
|
|
|
|
return bs, err
|
|
}
|
|
|
|
func (n *bridgeNetwork) allocatePortsInternal(bindings []types.PortBinding, bindIntf string, containerIP, defHostIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
|
|
bs := make([]types.PortBinding, 0, len(bindings))
|
|
for _, c := range bindings {
|
|
b := c.GetCopy()
|
|
if err := n.allocatePort(&b, containerIP, defHostIP); err != nil {
|
|
// On allocation failure,release previously
|
|
// allocated ports. On cleanup error, just log
|
|
// a warning message
|
|
if cuErr := n.releasePortsInternal(bs); cuErr != nil {
|
|
logrus.Warnf("Upon allocation failure "+
|
|
"for %v, failed to clear previously "+
|
|
"allocated port bindings: %v", b, cuErr)
|
|
}
|
|
return nil, err
|
|
}
|
|
bs = append(bs, b)
|
|
}
|
|
return bs, nil
|
|
}
|
|
|
|
func (n *bridgeNetwork) allocatePort(bnd *types.PortBinding, containerIP, defHostIP net.IP) error {
|
|
var (
|
|
host net.Addr
|
|
err error
|
|
)
|
|
|
|
// Store the container interface address in the operational binding
|
|
bnd.IP = containerIP
|
|
|
|
// Adjust the host address in the operational binding
|
|
if len(bnd.HostIP) == 0 {
|
|
bnd.HostIP = defHostIP
|
|
}
|
|
|
|
// Adjust HostPortEnd if this is not a range.
|
|
if bnd.HostPortEnd == 0 {
|
|
bnd.HostPortEnd = bnd.HostPort
|
|
}
|
|
|
|
// Construct the container side transport address
|
|
container, err := bnd.ContainerAddr()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Try up to maxAllocatePortAttempts times to get a port that's
|
|
// not already allocated.
|
|
for i := 0; i < maxAllocatePortAttempts; i++ {
|
|
if host, err = n.portMapper.MapRange(container, bnd.HostIP,
|
|
int(bnd.HostPort), int(bnd.HostPortEnd), false); err == nil {
|
|
break
|
|
}
|
|
// There is no point in immediately retrying to map an
|
|
// explicitly chosen port.
|
|
if bnd.HostPort != 0 {
|
|
logrus.Warnf(
|
|
"Failed to allocate and map port %d-%d: %s",
|
|
bnd.HostPort, bnd.HostPortEnd, err)
|
|
break
|
|
}
|
|
logrus.Warnf("Failed to allocate and map port: %s, retry: %d",
|
|
err, i+1)
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Save the host port (regardless it was or not specified in the
|
|
// binding)
|
|
switch netAddr := host.(type) {
|
|
case *net.TCPAddr:
|
|
bnd.HostPort = uint16(host.(*net.TCPAddr).Port)
|
|
return nil
|
|
case *net.UDPAddr:
|
|
bnd.HostPort = uint16(host.(*net.UDPAddr).Port)
|
|
return nil
|
|
default:
|
|
// For completeness
|
|
return ErrUnsupportedAddressType(fmt.Sprintf("%T", netAddr))
|
|
}
|
|
}
|
|
|
|
func (n *bridgeNetwork) releasePorts(ep *bridgeEndpoint) error {
|
|
err := n.releasePortsInternal(ep.portMapping)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
// remove rules if there are any port mappings
|
|
if len(ep.portMapping) > 0 {
|
|
removePFRules(ep.id)
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
func (n *bridgeNetwork) releasePortsInternal(bindings []types.PortBinding) error {
|
|
var errorBuf bytes.Buffer
|
|
|
|
// Attempt to release all port bindings, do not stop on failure
|
|
for _, m := range bindings {
|
|
if err := n.releasePort(m); err != nil {
|
|
errorBuf.WriteString(
|
|
fmt.Sprintf(
|
|
"\ncould not release %v because of %v",
|
|
m, err))
|
|
}
|
|
}
|
|
|
|
if errorBuf.Len() != 0 {
|
|
return errors.New(errorBuf.String())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (n *bridgeNetwork) releasePort(bnd types.PortBinding) error {
|
|
// Construct the host side transport address
|
|
host, err := bnd.HostAddr()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return n.portMapper.Unmap(host)
|
|
}
|