123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- package netconf
- import (
- "encoding/binary"
- "fmt"
- "math/rand"
- "net"
- "github.com/rancher/os/pkg/log"
- "github.com/j-keck/arping"
- "github.com/vishvananda/netlink"
- "github.com/vishvananda/netlink/nl"
- )
- func AssignLinkLocalIP(link netlink.Link) error {
- ifaceName := link.Attrs().Name
- addrs, err := getLinkAddrs(link)
- if err != nil {
- return err
- }
- for _, addr := range addrs {
- if addr.String()[:7] == "169.254" {
- log.Info("Link Local IP already set on interface")
- return nil
- }
- }
- randSource, err := getPseudoRandomGenerator(link.Attrs().HardwareAddr)
- if err != nil {
- return err
- }
- // try a random address upto 10 times
- for i := 0; i < 10; i++ {
- randGenerator := rand.New(*randSource)
- randomNum := randGenerator.Uint32()
- dstIP := getNewIPV4LLAddr(randomNum)
- if dstIP[2] == 0 || dstIP[2] == 255 {
- i--
- continue
- }
- _, _, err := arping.PingOverIfaceByName(dstIP, ifaceName)
- if err != nil {
- // this ip is not being used
- addr, err := netlink.ParseAddr(dstIP.String() + "/16")
- if err != nil {
- log.Errorf("error while parsing ipv4ll addr, err = %v", err)
- return err
- }
- if err := netlink.AddrAdd(link, addr); err != nil {
- log.Error("ipv4ll addr add failed")
- return err
- }
- log.Infof("Set %s on %s", dstIP.String(), link.Attrs().Name)
- return nil
- }
- }
- log.Error("Could not find a suitable ipv4ll")
- return fmt.Errorf("Could not find a suitable ipv4ll")
- }
- func RemoveLinkLocalIP(link netlink.Link) error {
- addrs, err := getLinkAddrs(link)
- if err != nil {
- return err
- }
- for _, addr := range addrs {
- if addr.String()[:7] == "169.254" {
- if err := netlink.AddrDel(link, &addr); err != nil {
- log.Error("ipv4ll addr del failed")
- return err
- }
- log.Infof("Removed LinkLocal %s from %s", addr.String(), link.Attrs().Name)
- return nil
- }
- }
- return nil
- }
- func getNewIPV4LLAddr(randomNum uint32) net.IP {
- byte1 := randomNum & 255 // use least significant 8 bits
- byte2 := randomNum >> 24 // use most significant 8 bits
- return []byte{169, 254, byte(byte1), byte(byte2)}
- }
- func getPseudoRandomGenerator(haAddr []byte) (*rand.Source, error) {
- seed, _ := binary.Varint(haAddr)
- src := rand.NewSource(seed)
- return &src, nil
- }
- func getLinkAddrs(link netlink.Link) ([]netlink.Addr, error) {
- addrs, err := netlink.AddrList(link, nl.FAMILY_ALL)
- if err != nil {
- log.Error("Error fetching existing ip on interface, %s", err)
- err = nil // atm, we ignore this, as the link may not have one?
- }
- return addrs, err
- }
|