File: basicConfigurer.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 (90 lines) | stat: -rw-r--r-- 2,659 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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package ipmanager

import (
	"errors"
	"net"
	"strings"

	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
)

// BasicConfigurer can be used to enable vip-management on nodes
// that handle their own network connection, in setups where it is
// sufficient to add the virtual ip using `ip addr add ...` .
// After adding the virtual ip to the specified interface,
// a gratuitous ARP package is sent out to update the tables of
// nearby routers and other devices.
type BasicConfigurer struct {
	*IPConfiguration
	ntecontext uint32 //used by Windows to delete IP address
}

func newBasicConfigurer(config *IPConfiguration) (*BasicConfigurer, error) {
	c := &BasicConfigurer{IPConfiguration: config, ntecontext: 0}
	if c.Iface.HardwareAddr == nil || c.Iface.HardwareAddr.String() == "00:00:00:00:00:00" {
		return nil, errors.New(`Cannot run vip-manager on the loopback device
as its hardware address is the local address (00:00:00:00:00:00),
which prohibits sending of gratuitous ARP messages`)
	}
	return c, nil
}

// queryAddress returns if the address is assigned
func (c *BasicConfigurer) queryAddress() bool {
	iface, err := net.InterfaceByName(c.Iface.Name)
	if err != nil {
		return false
	}
	addresses, err := iface.Addrs()
	if err != nil {
		return false
	}
	for _, address := range addresses {
		if strings.Contains(address.String(), c.getCIDR()) {
			return true
		}
	}
	return false
}

const (
	MACAddressSize  = 6
	IPv4AddressSize = 4
)

// createGratuitousARP prepares a packet with a gratuitous ARP request
func (c *BasicConfigurer) createGratuitousARP() ([]byte, error) {
	// Create the Ethernet layer
	ethLayer := &layers.Ethernet{
		SrcMAC:       c.Iface.HardwareAddr,
		DstMAC:       net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // Broadcast
		EthernetType: layers.EthernetTypeARP,
	}

	// Create the ARP layer
	arpLayer := &layers.ARP{
		AddrType:          layers.LinkTypeEthernet,
		Protocol:          layers.EthernetTypeIPv4,
		HwAddressSize:     MACAddressSize,
		ProtAddressSize:   IPv4AddressSize,
		Operation:         layers.ARPReply, // Gratuitous ARP is sent as a reply
		SourceHwAddress:   c.Iface.HardwareAddr,
		SourceProtAddress: c.IPConfiguration.VIP.AsSlice(),
		DstHwAddress:      c.Iface.HardwareAddr, // Gratuitous ARP targets itself
		DstProtAddress:    c.IPConfiguration.VIP.AsSlice(),
	}

	// Create a packet with the layers
	buffer := gopacket.NewSerializeBuffer()
	opts := gopacket.SerializeOptions{
		FixLengths:       true,
		ComputeChecksums: true,
	}

	if err := gopacket.SerializeLayers(buffer, opts, ethLayer, arpLayer); err != nil {
		return nil, err
	}

	return buffer.Bytes(), nil
}