github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/libnetwork/netutils/utils_linux.go (about) 1 // +build linux 2 // Network utility functions. 3 4 package netutils 5 6 import ( 7 "fmt" 8 "net" 9 "strings" 10 11 "github.com/docker/libnetwork/ipamutils" 12 "github.com/docker/libnetwork/ns" 13 "github.com/docker/libnetwork/osl" 14 "github.com/docker/libnetwork/resolvconf" 15 "github.com/docker/libnetwork/types" 16 "github.com/pkg/errors" 17 "github.com/vishvananda/netlink" 18 ) 19 20 var ( 21 networkGetRoutesFct func(netlink.Link, int) ([]netlink.Route, error) 22 ) 23 24 // CheckRouteOverlaps checks whether the passed network overlaps with any existing routes 25 func CheckRouteOverlaps(toCheck *net.IPNet) error { 26 if networkGetRoutesFct == nil { 27 networkGetRoutesFct = ns.NlHandle().RouteList 28 } 29 networks, err := networkGetRoutesFct(nil, netlink.FAMILY_V4) 30 if err != nil { 31 return err 32 } 33 for _, network := range networks { 34 if network.Dst != nil && NetworkOverlaps(toCheck, network.Dst) { 35 return ErrNetworkOverlaps 36 } 37 } 38 return nil 39 } 40 41 // GenerateIfaceName returns an interface name using the passed in 42 // prefix and the length of random bytes. The api ensures that the 43 // there are is no interface which exists with that name. 44 func GenerateIfaceName(nlh *netlink.Handle, prefix string, len int) (string, error) { 45 linkByName := netlink.LinkByName 46 if nlh != nil { 47 linkByName = nlh.LinkByName 48 } 49 for i := 0; i < 3; i++ { 50 name, err := GenerateRandomName(prefix, len) 51 if err != nil { 52 continue 53 } 54 _, err = linkByName(name) 55 if err != nil { 56 if strings.Contains(err.Error(), "not found") { 57 return name, nil 58 } 59 return "", err 60 } 61 } 62 return "", types.InternalErrorf("could not generate interface name") 63 } 64 65 // ElectInterfaceAddresses looks for an interface on the OS with the 66 // specified name and returns returns all its IPv4 and IPv6 addresses in CIDR notation. 67 // If a failure in retrieving the addresses or no IPv4 address is found, an error is returned. 68 // If the interface does not exist, it chooses from a predefined 69 // list the first IPv4 address which does not conflict with other 70 // interfaces on the system. 71 func ElectInterfaceAddresses(name string) ([]*net.IPNet, []*net.IPNet, error) { 72 var ( 73 v4Nets []*net.IPNet 74 v6Nets []*net.IPNet 75 ) 76 77 defer osl.InitOSContext()() 78 79 link, _ := ns.NlHandle().LinkByName(name) 80 if link != nil { 81 v4addr, err := ns.NlHandle().AddrList(link, netlink.FAMILY_V4) 82 if err != nil { 83 return nil, nil, err 84 } 85 v6addr, err := ns.NlHandle().AddrList(link, netlink.FAMILY_V6) 86 if err != nil { 87 return nil, nil, err 88 } 89 for _, nlAddr := range v4addr { 90 v4Nets = append(v4Nets, nlAddr.IPNet) 91 } 92 for _, nlAddr := range v6addr { 93 v6Nets = append(v6Nets, nlAddr.IPNet) 94 } 95 } 96 97 if link == nil || len(v4Nets) == 0 { 98 // Choose from predefined local scope networks 99 v4Net, err := FindAvailableNetwork(ipamutils.PredefinedLocalScopeDefaultNetworks) 100 if err != nil { 101 return nil, nil, errors.Wrapf(err, "PredefinedLocalScopeDefaultNetworks List: %+v", 102 ipamutils.PredefinedLocalScopeDefaultNetworks) 103 } 104 v4Nets = append(v4Nets, v4Net) 105 } 106 107 return v4Nets, v6Nets, nil 108 } 109 110 // FindAvailableNetwork returns a network from the passed list which does not 111 // overlap with existing interfaces in the system 112 func FindAvailableNetwork(list []*net.IPNet) (*net.IPNet, error) { 113 // We don't check for an error here, because we don't really care if we 114 // can't read /data/data/hilled.pwnterm/files/usr/etc/resolv.conf. So instead we skip the append if resolvConf 115 // is nil. It either doesn't exist, or we can't read it for some reason. 116 var nameservers []string 117 if rc, err := resolvconf.Get(); err == nil { 118 nameservers = resolvconf.GetNameserversAsCIDR(rc.Content) 119 } 120 for _, nw := range list { 121 if err := CheckNameserverOverlaps(nameservers, nw); err == nil { 122 if err := CheckRouteOverlaps(nw); err == nil { 123 return nw, nil 124 } 125 } 126 } 127 return nil, fmt.Errorf("no available network") 128 }