github.com/hustcat/docker@v1.3.3-0.20160314103604-901c67a8eeab/docker/listeners/listeners_unix.go (about) 1 // +build !windows 2 3 package listeners 4 5 import ( 6 "crypto/tls" 7 "fmt" 8 "net" 9 "strconv" 10 11 "github.com/Sirupsen/logrus" 12 "github.com/coreos/go-systemd/activation" 13 "github.com/docker/go-connections/sockets" 14 "github.com/docker/libnetwork/portallocator" 15 ) 16 17 // Init creates new listeners for the server. 18 func Init(proto, addr, socketGroup string, tlsConfig *tls.Config) (ls []net.Listener, err error) { 19 switch proto { 20 case "fd": 21 ls, err = listenFD(addr, tlsConfig) 22 if err != nil { 23 return nil, err 24 } 25 case "tcp": 26 l, err := initTCPSocket(addr, tlsConfig) 27 if err != nil { 28 return nil, err 29 } 30 ls = append(ls, l) 31 case "unix": 32 l, err := sockets.NewUnixSocket(addr, socketGroup) 33 if err != nil { 34 return nil, fmt.Errorf("can't create unix socket %s: %v", addr, err) 35 } 36 ls = append(ls, l) 37 default: 38 return nil, fmt.Errorf("Invalid protocol format: %q", proto) 39 } 40 41 return 42 } 43 44 // listenFD returns the specified socket activated files as a slice of 45 // net.Listeners or all of the activated files if "*" is given. 46 func listenFD(addr string, tlsConfig *tls.Config) ([]net.Listener, error) { 47 var ( 48 err error 49 listeners []net.Listener 50 ) 51 // socket activation 52 if tlsConfig != nil { 53 listeners, err = activation.TLSListeners(false, tlsConfig) 54 } else { 55 listeners, err = activation.Listeners(false) 56 } 57 if err != nil { 58 return nil, err 59 } 60 61 if len(listeners) == 0 { 62 return nil, fmt.Errorf("No sockets found. Make sure the docker daemon was started by systemd.") 63 } 64 65 // default to all fds just like unix:// and tcp:// 66 if addr == "" || addr == "*" { 67 return listeners, nil 68 } 69 70 fdNum, err := strconv.Atoi(addr) 71 if err != nil { 72 return nil, fmt.Errorf("failed to parse systemd address, should be number: %v", err) 73 } 74 fdOffset := fdNum - 3 75 if len(listeners) < int(fdOffset)+1 { 76 return nil, fmt.Errorf("Too few socket activated files passed in") 77 } 78 if listeners[fdOffset] == nil { 79 return nil, fmt.Errorf("failed to listen on systemd activated file at fd %d", fdOffset+3) 80 } 81 for i, ls := range listeners { 82 if i == fdOffset || ls == nil { 83 continue 84 } 85 if err := ls.Close(); err != nil { 86 logrus.Errorf("Failed to close systemd activated file at fd %d: %v", fdOffset+3, err) 87 } 88 } 89 return []net.Listener{listeners[fdOffset]}, nil 90 } 91 92 // allocateDaemonPort ensures that there are no containers 93 // that try to use any port allocated for the docker server. 94 func allocateDaemonPort(addr string) error { 95 host, port, err := net.SplitHostPort(addr) 96 if err != nil { 97 return err 98 } 99 100 intPort, err := strconv.Atoi(port) 101 if err != nil { 102 return err 103 } 104 105 var hostIPs []net.IP 106 if parsedIP := net.ParseIP(host); parsedIP != nil { 107 hostIPs = append(hostIPs, parsedIP) 108 } else if hostIPs, err = net.LookupIP(host); err != nil { 109 return fmt.Errorf("failed to lookup %s address in host specification", host) 110 } 111 112 pa := portallocator.Get() 113 for _, hostIP := range hostIPs { 114 if _, err := pa.RequestPort(hostIP, "tcp", intPort); err != nil { 115 return fmt.Errorf("failed to allocate daemon listening port %d (err: %v)", intPort, err) 116 } 117 } 118 return nil 119 }