// sets IP4 addr on link removing any existing ones first func setAddr4(link *netlink.Vxlan, ipn *net.IPNet) error { addrs, err := netlink.AddrList(link, syscall.AF_INET) if err != nil { return err } addr := netlink.Addr{ipn, ""} existing := false for _, old := range addrs { if old.IPNet.String() == addr.IPNet.String() { existing = true continue } if err = netlink.AddrDel(link, &old); err != nil { return fmt.Errorf("failed to delete IPv4 addr %s from %s", old.String(), link.Attrs().Name) } } if !existing { if err = netlink.AddrAdd(link, &addr); err != nil { return fmt.Errorf("failed to add IP address %s to %s: %s", ipn.String(), link.Attrs().Name, err) } } return nil }
func TestAllocate(t *testing.T) { subnet := net.IPNet{ IP: net.IPv4(0xab, 0xcd, 0xe0, 0x00), Mask: net.CIDRMask(20, 32), } conflicts := map[string]struct{}{} ipSet := map[string]struct{}{} // Only 4k IPs, in 0xfffff000. Guaranteed a collision for i := 0; i < 5000; i++ { ip, err := allocateIP(ipSet, subnet) if err != nil { continue } if _, ok := conflicts[ip]; ok { t.Fatalf("IP Double allocation: 0x%x", ip) } require.True(t, subnet.Contains(net.ParseIP(ip)), fmt.Sprintf("\"%s\" is not in %s", ip, subnet)) conflicts[ip] = struct{}{} } assert.Equal(t, len(conflicts), len(ipSet)) if len(conflicts) < 2500 || len(conflicts) > 4096 { // If the code's working, this is possible but *extremely* unlikely. // Probably a bug. t.Errorf("Too few conflicts: %d", len(conflicts)) } }
func ensureBridgeAddr(br *netlink.Bridge, ipn *net.IPNet, forceAddress bool) error { addrs, err := netlink.AddrList(br, syscall.AF_INET) if err != nil && err != syscall.ENOENT { return fmt.Errorf("could not get list of IP addresses: %v", err) } // if there're no addresses on the bridge, it's ok -- we'll add one if len(addrs) > 0 { ipnStr := ipn.String() for _, a := range addrs { // string comp is actually easiest for doing IPNet comps if a.IPNet.String() == ipnStr { return nil } // If forceAddress is set to true then reconfigure IP address otherwise throw error if forceAddress { if err = deleteBridgeAddr(br, a.IPNet); err != nil { return err } } else { return fmt.Errorf("%q already has an IP address different from %v", br.Name, ipn.String()) } } } addr := &netlink.Addr{IPNet: ipn, Label: ""} if err := netlink.AddrAdd(br, addr); err != nil { return fmt.Errorf("could not add IP address to %q: %v", br.Name, err) } return nil }
// NextSubnetIP returns the next available IP address in a given subnet. func NextSubnetIP(subnet *net.IPNet, ipsInUse []net.IP) (net.IP, error) { ones, bits := subnet.Mask.Size() subnetMaskUint32 := ipUint32(net.IP(subnet.Mask)) inUse := big.NewInt(0) for _, ip := range ipsInUse { if !subnet.Contains(ip) { continue } index := ipIndex(ip, subnetMaskUint32) inUse = inUse.SetBit(inUse, index, 1) } // Now iterate through all addresses in the subnet and return the // first address that is not in use. We start at the first non- // reserved address, and stop short of the last address in the // subnet (i.e. all non-mask bits set), which is the broadcast // address for the subnet. n := ipUint32(subnet.IP) for i := reservedAddressRangeEnd + 1; i < (1<<uint64(bits-ones) - 1); i++ { ip := uint32IP(n + uint32(i)) if !ip.IsGlobalUnicast() { continue } index := ipIndex(ip, subnetMaskUint32) if inUse.Bit(index) == 0 { return ip, nil } } return nil, errors.Errorf("no addresses available in %s", subnet) }
func generateCMD(dst net.IPNet, gw net.IP, is_delete bool) []string { var netmask_str string = net.IP(dst.Mask).String() var ipaddr_str string = dst.IP.String() var gateway_str string = gw.String() var network_str string = dst.String() switch runtime.GOOS { case "darwin": if is_delete { return []string{"route", "delete", "-net", ipaddr_str, gateway_str, netmask_str} } else { return []string{"route", "add", "-net", ipaddr_str, gateway_str, netmask_str} } case "linux": if is_delete { return []string{"ip", "route", "del", network_str} } else { return []string{"ip", "route", "add", network_str, "via", gateway_str} } default: return nil } return nil }
func (a *Allocator) insertBitMask(key SubnetKey, pool *net.IPNet) error { log.Debugf("Inserting bitmask (%s, %s)", key.String(), pool.String()) store := a.getStore(key.AddressSpace) if store == nil { return fmt.Errorf("could not find store for address space %s while inserting bit mask", key.AddressSpace) } ipVer := getAddressVersion(pool.IP) ones, bits := pool.Mask.Size() numAddresses := uint32(1 << uint(bits-ones)) if ipVer == v4 { // Do not let broadcast address be reserved numAddresses-- } // Generate the new address masks. AddressMask content may come from datastore h, err := bitseq.NewHandle(dsDataKey, store, key.String(), numAddresses) if err != nil { return err } if ipVer == v4 { // Do not let network identifier address be reserved h.Set(0) } a.Lock() a.addresses[key] = h a.Unlock() return nil }
// hasIP6Connected parses the list of remote addresses in /proc/net/{tcp,udp}6 or in // /proc/<pid>/net/{tcp,udp}6 and returns addresses that are contained within // the ipnet submitted. It always uses CIDR inclusion, even when only // searching for a single IP (but assuming a /128 bitmask). // Remote addresses exposed in /proc are in hexadecimal notation, and converted into byte slices // to use in ipnet.Contains() func hasIP6Connected(ip net.IP, ipnet *net.IPNet) (found bool, elements []element, err error) { defer func() { if e := recover(); e != nil { err = fmt.Errorf("hasIP6Connected(): %v", e) } }() lns, err := procIP6Entries() if err != nil { panic(err) } // if the ipnet is nil, assume that its a full 128bits mask if ipnet == nil { ipnet = new(net.IPNet) ipnet.IP = ip ipnet.Mask = net.CIDRMask(net.IPv6len*8, net.IPv6len*8) } for _, ipent := range lns { fields := strings.Fields(ipent.line) if len(fields) < 4 { panic("/proc doesn't respect the expected format") } remote := strings.Split(fields[2], ":") if len(remote) != 2 { panic("remote isn't in the form <ip>:<port>") } remoteIP := hexToIP6(remote[0]) if remoteIP == nil { panic("failed to convert remote IP") } // if we've got a match, store the element if ipnet.Contains(remoteIP) { var el element el.RemoteAddr = remoteIP.String() remotePort, err := strconv.ParseUint(remote[1], 16, 16) if err != nil { panic("failed to convert remote port") } el.RemotePort = float64(remotePort) local := strings.Split(fields[1], ":") if len(local) != 2 { panic("local isn't in the form <ip>:<port>") } localAddr := hexToIP6(local[0]) if localAddr == nil { panic("failed to convert local ip") } el.LocalAddr = localAddr.String() localPort, err := strconv.ParseUint(local[1], 16, 16) if err != nil { panic("failed to convert local port") } el.LocalPort = float64(localPort) el.Namespace = ipent.nsIdentifier elements = append(elements, el) found = true } stats.Examined++ } return }
// return an available ip if one is currently available. If not, // return the next available ip for the nextwork func getNextIp(address *net.IPNet) (*net.IP, error) { var ( ownIP = ipToInt(&address.IP) allocated = allocatedIPs[address.String()] first, _ = networkdriver.NetworkRange(address) base = ipToInt(&first) size = int(networkdriver.NetworkSize(address.Mask)) max = int32(size - 2) // size -1 for the broadcast address, -1 for the gateway address pos = atomic.LoadInt32(&allocated.last) ) var ( firstNetIP = address.IP.To4().Mask(address.Mask) firstAsInt = ipToInt(&firstNetIP) + 1 ) for i := int32(0); i < max; i++ { pos = pos%max + 1 next := int32(base + pos) if next == ownIP || next == firstAsInt { continue } if !allocated.Exists(int(pos)) { ip := intToIP(next) allocated.Push(int(pos)) atomic.StoreInt32(&allocated.last, pos) return ip, nil } } return nil, ErrNoAvailableIPs }
func createCBR0(wantCIDR *net.IPNet) error { // recreate cbr0 with wantCIDR if err := exec.Command("brctl", "addbr", "cbr0").Run(); err != nil { glog.Error(err) return err } if err := exec.Command("ip", "addr", "add", wantCIDR.String(), "dev", "cbr0").Run(); err != nil { glog.Error(err) return err } if err := exec.Command("ip", "link", "set", "dev", "cbr0", "mtu", "1460", "up").Run(); err != nil { glog.Error(err) return err } // restart docker // For now just log the error. The containerRuntime check will catch docker failures. // TODO (dawnchen) figure out what we should do for rkt here. if util.UsingSystemdInitSystem() { if err := exec.Command("systemctl", "restart", "docker").Run(); err != nil { glog.Error(err) } } else { if err := exec.Command("service", "docker", "restart").Run(); err != nil { glog.Error(err) } } glog.V(2).Info("Recreated cbr0 and restarted docker") return nil }
func (mgr *filterChain) Setup(instanceChain, bridgeName string, ip net.IP, network *net.IPNet) error { commands := []*exec.Cmd{ // Create filter instance chain exec.Command("iptables", "--wait", "-N", instanceChain), // Allow intra-subnet traffic (Linux ethernet bridging goes through ip stack) exec.Command("iptables", "--wait", "-A", instanceChain, "-s", network.String(), "-d", network.String(), "-j", "ACCEPT"), // Otherwise, use the default filter chain exec.Command("iptables", "--wait", "-A", instanceChain, "--goto", mgr.cfg.DefaultChain), // Bind filter instance chain to filter forward chain exec.Command("iptables", "--wait", "-I", mgr.cfg.ForwardChain, "2", "--in-interface", bridgeName, "--source", ip.String(), "--goto", instanceChain), } for _, cmd := range commands { buffer := &bytes.Buffer{} cmd.Stderr = buffer logger := mgr.logger.Session("setup", lager.Data{"cmd": cmd}) logger.Debug("starting") if err := mgr.runner.Run(cmd); err != nil { stderr, _ := ioutil.ReadAll(buffer) logger.Error("failed", err, lager.Data{"stderr": string(stderr)}) return fmt.Errorf("iptables_manager: filter: %s", err) } logger.Debug("ended") } return nil }
// GetIndexedIP returns a net.IP that is subnet.IP + index in the contiguous IP space. func GetIndexedIP(subnet *net.IPNet, index int) (net.IP, error) { ip := addIPOffset(bigForIP(subnet.IP), index) if !subnet.Contains(ip) { return nil, fmt.Errorf("can't generate IP with index %d from subnet. subnet too small. subnet: %q", index, subnet) } return ip, nil }
func checkAddress(address *net.IPNet) { key := address.String() if _, exists := allocatedIPs[key]; !exists { allocatedIPs[key] = collections.NewOrderedIntSet() availableIPS[key] = collections.NewOrderedIntSet() } }
func generateRandomNetwork(address *net.IPNet) string { tick := float64(time.Now().UnixNano() / 1000000) ones, bits := address.Mask.Size() zeros := bits - ones uniqIPsAmount := math.Pow(2.0, float64(zeros)) rawIP := math.Mod(tick, uniqIPsAmount) remainder := rawIP remainder, octet4 := math.Modf(remainder / 255.0) remainder, octet3 := math.Modf(remainder / 255.0) remainder, octet2 := math.Modf(remainder / 255.0) base := address.IP address.IP = net.IPv4( byte(remainder)|base[0], byte(octet2*255)|base[1], byte(octet3*255)|base[2], byte(octet4*255)|base[3], ) address.IP.Mask(address.Mask) return address.String() }
func (oc *OsdnController) SubnetStartMaster(clusterNetwork *net.IPNet, hostSubnetLength uint) error { subrange := make([]string, 0) subnets, err := oc.Registry.GetSubnets() if err != nil { log.Errorf("Error in initializing/fetching subnets: %v", err) return err } for _, sub := range subnets { subrange = append(subrange, sub.Subnet) if err := oc.validateNode(sub.HostIP); err != nil { // Don't error out; just warn so the error can be corrected with 'oc' log.Errorf("Failed to validate HostSubnet %s: %v", err) } else { log.Infof("Found existing HostSubnet %s", HostSubnetToString(&sub)) } } oc.subnetAllocator, err = netutils.NewSubnetAllocator(clusterNetwork.String(), hostSubnetLength, subrange) if err != nil { return err } go utilwait.Forever(oc.watchNodes, 0) return nil }
// Initialize the repo to be used to announce/write config. // A seperate repo is initialized to read incoming announcements func initConfigWrite(networkCidr *net.IPNet, hostIface, gitRepoURL string) { var err error if !pathExists(EndpointPushSubDir) { log.Debugf("[ %s ] dir not found, creating it..", EndpointPushSubDir) if err = CreatePaths(EndpointPushSubDir); err != nil { log.Fatalf("Could not create the directory [ %s ]: %s", EndpointPushSubDir, err) } else { log.Warnf("Succesfully created the config path [ %s ]", EndpointPushSubDir) } } // Create the cache subdirectories time.Sleep(1 * time.Second) localEndpointIP, _ := getIfaceAddrStr(hostIface) // Fun Go fact: using a + with sprintf is faster then %s since it uses reflection endpointFile := fmt.Sprintf(localEndpointIP + dotjson) log.Debugf("The endpoint file name is [ %s ] ", endpointFile) log.Debugf("Anouncing this endpoint using the source [ %s ] and advertsing network [ %s ] to datastore file [ %s ]", networkCidr, localEndpointIP, endpointFile) endpointConfig := &LocalEndpoint{ Endpoint: localEndpointIP, Network: networkCidr.String(), Meta: "", } var configAnnounce []LocalEndpoint configAnnounce = append(configAnnounce, *endpointConfig) marshallConfig(configAnnounce, configFormat, endpointFile) if log.GetLevel().String() == "debug" { printPretty(configAnnounce, "json") } // Parse the repo name defer gitPushConfig() }
func checkAddress(address *net.IPNet) { key := address.String() if _, exists := allocatedIPs[key]; !exists { allocatedIPs[key] = &iPSet{} availableIPS[key] = &iPSet{} } }
func decodeInet(vr *ValueReader) net.IPNet { var zero net.IPNet if vr.Len() == -1 { vr.Fatal(ProtocolError("Cannot decode null into net.IPNet")) return zero } if vr.Type().FormatCode != BinaryFormatCode { vr.Fatal(ProtocolError(fmt.Sprintf("Unknown field description format code: %v", vr.Type().FormatCode))) return zero } pgType := vr.Type() if vr.Len() != 8 && vr.Len() != 20 { vr.Fatal(ProtocolError(fmt.Sprintf("Received an invalid size for a %s: %d", pgType.Name, vr.Len()))) return zero } if pgType.DataType != InetOid && pgType.DataType != CidrOid { vr.Fatal(ProtocolError(fmt.Sprintf("Cannot decode oid %v into %s", pgType.DataType, pgType.Name))) return zero } vr.ReadByte() // ignore family bits := vr.ReadByte() vr.ReadByte() // ignore is_cidr addressLength := vr.ReadByte() var ipnet net.IPNet ipnet.IP = vr.ReadBytes(int32(addressLength)) ipnet.Mask = net.CIDRMask(int(bits), int(addressLength)*8) return ipnet }
func (this pool) NextAddr(args ...interface{}) string { var addr, netmask string var ipnet *net.IPNet switch len(args) { case 2: addr = args[0].(string) netmask = args[1].(string) ipnet = &net.IPNet{ IP: net.ParseIP(addr), Mask: net.IPMask(net.ParseIP(netmask)), } case 0: for k, _ := range this.cache { ipnet = this.cache[k] break } default: return "" } ip, _, _ := net.ParseCIDR(this.NextCidr(ipnet.String())) return ip.String() }
func getSuitableAddrs(addrs []*address, v4, v6, linklocal, loopback bool, re *regexp.Regexp, mask *net.IPNet) ([]*address, error) { ret := []*address{} for _, a := range addrs { if a.IsLoopback() && !loopback { continue } if !v6 && a.IsV6() { continue } if !v4 && a.IsV4() { continue } if !linklocal && a.IsLinkLocalUnicast() { continue } if !loopback && a.IsLoopback() { continue } if re != nil { if !re.MatchString(a.String()) { continue } } if mask != nil { if !mask.Contains(a.IP) { continue } } ret = append(ret, a) } if len(ret) == 0 { return nil, errors.New("unable to find suitable address") } return ret, nil }
func addRedirectRules(path string, eIP *net.IPNet, ingressPorts []*PortConfig) error { var ingressPortsFile string if len(ingressPorts) != 0 { var err error ingressPortsFile, err = writePortsToFile(ingressPorts) if err != nil { return err } defer os.Remove(ingressPortsFile) } cmd := &exec.Cmd{ Path: reexec.Self(), Args: append([]string{"redirecter"}, path, eIP.String(), ingressPortsFile), Stdout: os.Stdout, Stderr: os.Stderr, } if err := cmd.Run(); err != nil { return fmt.Errorf("reexec failed: %v", err) } return nil }
func (a *Allocator) getAddress(nw *net.IPNet, bitmask *bitseq.Handle, prefAddress net.IP, ipr *AddressRange) (net.IP, error) { var ( ordinal uint64 err error base *net.IPNet ) base = types.GetIPNetCopy(nw) if bitmask.Unselected() <= 0 { return nil, ipamapi.ErrNoAvailableIPs } if ipr == nil && prefAddress == nil { ordinal, err = bitmask.SetAny() } else if prefAddress != nil { hostPart, e := types.GetHostPartIP(prefAddress, base.Mask) if e != nil { return nil, fmt.Errorf("failed to allocate preferred address %s: %v", prefAddress.String(), e) } ordinal = ipToUint64(types.GetMinimalIP(hostPart)) err = bitmask.Set(ordinal) } else { base.IP = ipr.Sub.IP ordinal, err = bitmask.SetAnyInRange(ipr.Start, ipr.End) } if err != nil { return nil, ipamapi.ErrNoAvailableIPs } // Convert IP ordinal for this subnet into IP address return generateAddress(ordinal, base), nil }
func networkAddressForSubnet(subnet *net.IPNet) (net.IP, string, error) { ifaces, err := net.Interfaces() if err != nil { return net.IP{}, "", err } for _, iface := range ifaces { addrs, err := iface.Addrs() if err != nil { continue } for _, addr := range addrs { ip, _, err := net.ParseCIDR(addr.String()) if err != nil { continue } if subnet.Contains(ip) { return ip, iface.Name, nil } } } return net.IP{}, "", fmt.Errorf("No address found in subnet") }
func setAddress(ifaceAddr *string, address *net.IPNet) error { if *ifaceAddr != "" { return types.ForbiddenErrorf("endpoint interface IP present (%s). Cannot be modified with (%s).", *ifaceAddr, address) } *ifaceAddr = address.String() return nil }
func (master *OsdnMaster) SubnetStartMaster(clusterNetwork *net.IPNet, hostSubnetLength uint32) error { subrange := make([]string, 0) subnets, err := master.osClient.HostSubnets().List(kapi.ListOptions{}) if err != nil { log.Errorf("Error in initializing/fetching subnets: %v", err) return err } for _, sub := range subnets.Items { subrange = append(subrange, sub.Subnet) if err = master.networkInfo.validateNodeIP(sub.HostIP); err != nil { // Don't error out; just warn so the error can be corrected with 'oc' log.Errorf("Failed to validate HostSubnet %s: %v", hostSubnetToString(&sub), err) } else { log.Infof("Found existing HostSubnet %s", hostSubnetToString(&sub)) } } master.subnetAllocator, err = netutils.NewSubnetAllocator(clusterNetwork.String(), hostSubnetLength, subrange) if err != nil { return err } go utilwait.Forever(master.watchNodes, 0) go utilwait.Forever(master.watchSubnets, 0) return nil }
func (c *CIDRs) UnmarshalBinary(b []byte) error { if len(b) < 1 { return fmt.Errorf("compare: missing type byte") } if b[0] != byte(TypeCIDRs) { return fmt.Errorf("compare: expected type %d, got %d", TypeCIDRs, b[0]) } b = b[1:] *c = make(CIDRs, 0, len(b)/ipv4CIDRLen) for len(b) > 0 { var n net.IPNet if b[0]&(1<<7) == 0 { // check top bit of ones byte, if 0, IPv4, if 1, IPv6 if len(b) < ipv4CIDRLen { return fmt.Errorf("compare: unexpected end of buffer decoding IPv4 CIDR") } n.Mask = net.CIDRMask(int(b[0]), ipv4Len*8) n.IP = net.IPv4(b[1], b[2], b[3], b[4]) b = b[5:] } else { if len(b) < ipv6CIDRLen { return fmt.Errorf("compare: unexpected end of buffer decoding IPv6 CIDR") } n.Mask = net.CIDRMask(int(b[0]&^(1<<7)), ipv6Len*8) n.IP = make([]byte, ipv6Len) copy(n.IP, b[1:]) b = b[ipv6CIDRLen:] } *c = append(*c, n) } return nil }
func (a *Allocator) parsePoolRequest(addressSpace, pool, subPool string, v6 bool) (*SubnetKey, *net.IPNet, *AddressRange, error) { var ( nw *net.IPNet ipr *AddressRange err error ) if addressSpace == "" { return nil, nil, nil, ipamapi.ErrInvalidAddressSpace } if pool == "" && subPool != "" { return nil, nil, nil, ipamapi.ErrInvalidSubPool } if pool == "" { return nil, nil, nil, nil } if _, nw, err = net.ParseCIDR(pool); err != nil { return nil, nil, nil, ipamapi.ErrInvalidPool } if subPool != "" { if ipr, err = getAddressRange(subPool, nw); err != nil { return nil, nil, nil, err } } return &SubnetKey{AddressSpace: addressSpace, Subnet: nw.String(), ChildSubnet: subPool}, nw, ipr, nil }
func (s *cidrSet) getBeginingAndEndIndices(cidr *net.IPNet) (begin, end int, err error) { begin, end = 0, s.maxCIDRs cidrMask := cidr.Mask maskSize, _ := cidrMask.Size() if !s.clusterCIDR.Contains(cidr.IP.Mask(s.clusterCIDR.Mask)) && !cidr.Contains(s.clusterCIDR.IP.Mask(cidr.Mask)) { return -1, -1, fmt.Errorf("cidr %v is out the range of cluster cidr %v", cidr, s.clusterCIDR) } if s.clusterMaskSize < maskSize { subNetMask := net.CIDRMask(s.subNetMaskSize, 32) begin, err = s.getIndexForCIDR(&net.IPNet{ IP: cidr.IP.To4().Mask(subNetMask), Mask: subNetMask, }) if err != nil { return -1, -1, err } ip := make([]byte, 4) ipInt := binary.BigEndian.Uint32(cidr.IP) | (^binary.BigEndian.Uint32(cidr.Mask)) binary.BigEndian.PutUint32(ip, ipInt) end, err = s.getIndexForCIDR(&net.IPNet{ IP: net.IP(ip).To4().Mask(subNetMask), Mask: subNetMask, }) if err != nil { return -1, -1, err } } return begin, end, nil }
func GenerateNetworkInterfaceUnits(unitsPath string, netDescriptions []netDescriber) error { for i, netDescription := range netDescriptions { ifName := fmt.Sprintf(networking.IfNamePattern, i) netAddress := net.IPNet{ IP: netDescription.GuestIP(), Mask: net.IPMask(netDescription.Mask()), } address := netAddress.String() mac, err := generateMacAddress() if err != nil { return err } opts := []*unit.UnitOption{ unit.NewUnitOption("Unit", "Description", fmt.Sprintf("Network configuration for device: %v", ifName)), unit.NewUnitOption("Unit", "DefaultDependencies", "false"), unit.NewUnitOption("Service", "Type", "oneshot"), unit.NewUnitOption("Service", "RemainAfterExit", "true"), unit.NewUnitOption("Service", "ExecStartPre", downInterfaceCommand(ifName)), unit.NewUnitOption("Service", "ExecStartPre", setMacCommand(ifName, mac.String())), unit.NewUnitOption("Service", "ExecStartPre", upInterfaceCommand(ifName)), unit.NewUnitOption("Service", "ExecStart", addAddressCommand(address, ifName)), unit.NewUnitOption("Install", "RequiredBy", "default.target"), } for _, route := range netDescription.Routes() { gw := route.GW if gw == nil { gw = netDescription.Gateway() } opts = append( opts, unit.NewUnitOption( "Service", "ExecStartPost", addRouteCommand(route.Dst.String(), gw.String()), ), ) } unitName := fmt.Sprintf("interface-%s", ifName) + ".service" unitBytes, err := ioutil.ReadAll(unit.Serialize(opts)) if err != nil { return fmt.Errorf("failed to serialize network unit file to bytes %q: %v", unitName, err) } err = ioutil.WriteFile(filepath.Join(unitsPath, unitName), unitBytes, 0644) if err != nil { return fmt.Errorf("failed to create network unit file %q: %v", unitName, err) } log.Printf("network unit created: %q in %q (iface=%q, addr=%q)", unitName, unitsPath, ifName, address) } return nil }
// Pass an IPNet object to find the value match in leveldb and return // both the matching object (or nil) and the error (or nil) func (db *DB) GetEntry(cidr *net.IPNet) (*heimdall.Entry, error) { if entry, err := db.Get([]byte(cidr.String()), nil); err == nil { timestamp, _ := time.Parse(TIMEFORMAT, string(entry)) return &heimdall.Entry{cidr, timestamp}, nil } else { return nil, err } }
// ReleaseIP adds the provided ip back into the pool of // available ips to be returned for use. func ReleaseIP(network *net.IPNet, ip net.IP) error { lock.Lock() defer lock.Unlock() if allocated, exists := allocatedIPs[network.String()]; exists { delete(allocated.p, ip.String()) } return nil }