github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/libnetwork/drvregistry/drvregistry.go (about) 1 package drvregistry 2 3 import ( 4 "errors" 5 "fmt" 6 "strings" 7 "sync" 8 9 "github.com/docker/docker/pkg/plugingetter" 10 "github.com/docker/libnetwork/driverapi" 11 "github.com/docker/libnetwork/ipamapi" 12 "github.com/docker/libnetwork/types" 13 ) 14 15 type driverData struct { 16 driver driverapi.Driver 17 capability driverapi.Capability 18 } 19 20 type ipamData struct { 21 driver ipamapi.Ipam 22 capability *ipamapi.Capability 23 // default address spaces are provided by ipam driver at registration time 24 defaultLocalAddressSpace, defaultGlobalAddressSpace string 25 } 26 27 type driverTable map[string]*driverData 28 type ipamTable map[string]*ipamData 29 30 // DrvRegistry holds the registry of all network drivers and IPAM drivers that it knows about. 31 type DrvRegistry struct { 32 sync.Mutex 33 drivers driverTable 34 ipamDrivers ipamTable 35 dfn DriverNotifyFunc 36 ifn IPAMNotifyFunc 37 pluginGetter plugingetter.PluginGetter 38 } 39 40 // Functors definition 41 42 // InitFunc defines the driver initialization function signature. 43 type InitFunc func(driverapi.DriverCallback, map[string]interface{}) error 44 45 // IPAMWalkFunc defines the IPAM driver table walker function signature. 46 type IPAMWalkFunc func(name string, driver ipamapi.Ipam, cap *ipamapi.Capability) bool 47 48 // DriverWalkFunc defines the network driver table walker function signature. 49 type DriverWalkFunc func(name string, driver driverapi.Driver, capability driverapi.Capability) bool 50 51 // IPAMNotifyFunc defines the notify function signature when a new IPAM driver gets registered. 52 type IPAMNotifyFunc func(name string, driver ipamapi.Ipam, cap *ipamapi.Capability) error 53 54 // DriverNotifyFunc defines the notify function signature when a new network driver gets registered. 55 type DriverNotifyFunc func(name string, driver driverapi.Driver, capability driverapi.Capability) error 56 57 // New returns a new driver registry handle. 58 func New(lDs, gDs interface{}, dfn DriverNotifyFunc, ifn IPAMNotifyFunc, pg plugingetter.PluginGetter) (*DrvRegistry, error) { 59 r := &DrvRegistry{ 60 drivers: make(driverTable), 61 ipamDrivers: make(ipamTable), 62 dfn: dfn, 63 ifn: ifn, 64 pluginGetter: pg, 65 } 66 67 return r, nil 68 } 69 70 // AddDriver adds a network driver to the registry. 71 func (r *DrvRegistry) AddDriver(ntype string, fn InitFunc, config map[string]interface{}) error { 72 return fn(r, config) 73 } 74 75 // WalkIPAMs walks the IPAM drivers registered in the registry and invokes the passed walk function and each one of them. 76 func (r *DrvRegistry) WalkIPAMs(ifn IPAMWalkFunc) { 77 type ipamVal struct { 78 name string 79 data *ipamData 80 } 81 82 r.Lock() 83 ivl := make([]ipamVal, 0, len(r.ipamDrivers)) 84 for k, v := range r.ipamDrivers { 85 ivl = append(ivl, ipamVal{name: k, data: v}) 86 } 87 r.Unlock() 88 89 for _, iv := range ivl { 90 if ifn(iv.name, iv.data.driver, iv.data.capability) { 91 break 92 } 93 } 94 } 95 96 // WalkDrivers walks the network drivers registered in the registry and invokes the passed walk function and each one of them. 97 func (r *DrvRegistry) WalkDrivers(dfn DriverWalkFunc) { 98 type driverVal struct { 99 name string 100 data *driverData 101 } 102 103 r.Lock() 104 dvl := make([]driverVal, 0, len(r.drivers)) 105 for k, v := range r.drivers { 106 dvl = append(dvl, driverVal{name: k, data: v}) 107 } 108 r.Unlock() 109 110 for _, dv := range dvl { 111 if dfn(dv.name, dv.data.driver, dv.data.capability) { 112 break 113 } 114 } 115 } 116 117 // Driver returns the actual network driver instance and its capability which registered with the passed name. 118 func (r *DrvRegistry) Driver(name string) (driverapi.Driver, *driverapi.Capability) { 119 r.Lock() 120 defer r.Unlock() 121 122 d, ok := r.drivers[name] 123 if !ok { 124 return nil, nil 125 } 126 127 return d.driver, &d.capability 128 } 129 130 // IPAM returns the actual IPAM driver instance and its capability which registered with the passed name. 131 func (r *DrvRegistry) IPAM(name string) (ipamapi.Ipam, *ipamapi.Capability) { 132 r.Lock() 133 defer r.Unlock() 134 135 i, ok := r.ipamDrivers[name] 136 if !ok { 137 return nil, nil 138 } 139 140 return i.driver, i.capability 141 } 142 143 // IPAMDefaultAddressSpaces returns the default address space strings for the passed IPAM driver name. 144 func (r *DrvRegistry) IPAMDefaultAddressSpaces(name string) (string, string, error) { 145 r.Lock() 146 defer r.Unlock() 147 148 i, ok := r.ipamDrivers[name] 149 if !ok { 150 return "", "", fmt.Errorf("ipam %s not found", name) 151 } 152 153 return i.defaultLocalAddressSpace, i.defaultGlobalAddressSpace, nil 154 } 155 156 // GetPluginGetter returns the plugingetter 157 func (r *DrvRegistry) GetPluginGetter() plugingetter.PluginGetter { 158 return r.pluginGetter 159 } 160 161 // RegisterDriver registers the network driver when it gets discovered. 162 func (r *DrvRegistry) RegisterDriver(ntype string, driver driverapi.Driver, capability driverapi.Capability) error { 163 if strings.TrimSpace(ntype) == "" { 164 return errors.New("network type string cannot be empty") 165 } 166 167 r.Lock() 168 dd, ok := r.drivers[ntype] 169 r.Unlock() 170 171 if ok && dd.driver.IsBuiltIn() { 172 return driverapi.ErrActiveRegistration(ntype) 173 } 174 175 if r.dfn != nil { 176 if err := r.dfn(ntype, driver, capability); err != nil { 177 return err 178 } 179 } 180 181 dData := &driverData{driver, capability} 182 183 r.Lock() 184 r.drivers[ntype] = dData 185 r.Unlock() 186 187 return nil 188 } 189 190 func (r *DrvRegistry) registerIpamDriver(name string, driver ipamapi.Ipam, caps *ipamapi.Capability) error { 191 if strings.TrimSpace(name) == "" { 192 return errors.New("ipam driver name string cannot be empty") 193 } 194 195 r.Lock() 196 dd, ok := r.ipamDrivers[name] 197 r.Unlock() 198 if ok && dd.driver.IsBuiltIn() { 199 return types.ForbiddenErrorf("ipam driver %q already registered", name) 200 } 201 202 locAS, glbAS, err := driver.GetDefaultAddressSpaces() 203 if err != nil { 204 return types.InternalErrorf("ipam driver %q failed to return default address spaces: %v", name, err) 205 } 206 207 if r.ifn != nil { 208 if err := r.ifn(name, driver, caps); err != nil { 209 return err 210 } 211 } 212 213 r.Lock() 214 r.ipamDrivers[name] = &ipamData{driver: driver, defaultLocalAddressSpace: locAS, defaultGlobalAddressSpace: glbAS, capability: caps} 215 r.Unlock() 216 217 return nil 218 } 219 220 // RegisterIpamDriver registers the IPAM driver discovered with default capabilities. 221 func (r *DrvRegistry) RegisterIpamDriver(name string, driver ipamapi.Ipam) error { 222 return r.registerIpamDriver(name, driver, &ipamapi.Capability{}) 223 } 224 225 // RegisterIpamDriverWithCapabilities registers the IPAM driver discovered with specified capabilities. 226 func (r *DrvRegistry) RegisterIpamDriverWithCapabilities(name string, driver ipamapi.Ipam, caps *ipamapi.Capability) error { 227 return r.registerIpamDriver(name, driver, caps) 228 }