1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
|
package ipmanager
import (
"net"
"os/exec"
"syscall"
)
// htons converts uint16 to network byte order
func htons(i uint16) uint16 {
return (i<<8)&0xff00 | i>>8
}
func sendPacketLinux(iface net.Interface, packetData []byte) error {
fd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, int(htons(syscall.ETH_P_ALL)))
if err != nil {
return err
}
defer syscall.Close(fd)
var sll syscall.SockaddrLinklayer
sll.Protocol = htons(syscall.ETH_P_ARP)
sll.Ifindex = iface.Index
sll.Hatype = syscall.ARPHRD_ETHER
sll.Pkttype = syscall.PACKET_BROADCAST
if err = syscall.Bind(fd, &sll); err != nil {
return err
}
return syscall.Sendto(fd, packetData, 0, &sll)
}
// configureAddress assigns virtual IP address
func (c *BasicConfigurer) configureAddress() bool {
log.Infof("Configuring address %s on %s", c.getCIDR(), c.Iface.Name)
result := c.runAddressConfiguration("add")
if result {
if buff, err := c.createGratuitousARP(); err != nil {
log.Warn("Failed to compose gratuitous ARP request: ", err)
} else {
if err := sendPacketLinux(c.Iface, buff); err != nil {
log.Warn("Failed to send gratuitous ARP request: ", err)
}
}
}
return result
}
// deconfigureAddress drops virtual IP address
func (c *BasicConfigurer) deconfigureAddress() bool {
log.Infof("Removing address %s on %s", c.getCIDR(), c.Iface.Name)
return c.runAddressConfiguration("delete")
}
func (c *BasicConfigurer) runAddressConfiguration(action string) bool {
cmd := exec.Command("ip", "addr", action,
c.getCIDR(),
"dev", c.Iface.Name)
output, err := cmd.CombinedOutput()
switch err.(type) {
case *exec.ExitError:
log.Infof("Got error %s", output)
return false
}
if err != nil {
log.Infof("Error running ip address %s %s on %s: %s",
action, c.VIP, c.Iface.Name, err)
return false
}
return true
}
|