File: basicConfigurer_linux.go

package info (click to toggle)
vip-manager2 4.0.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 360 kB
  • sloc: sh: 169; makefile: 33
file content (75 lines) | stat: -rw-r--r-- 1,840 bytes parent folder | download
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
}