Skip to content

Commit

Permalink
replace pcap with raw socket calls
Browse files Browse the repository at this point in the history
  • Loading branch information
pashagolub committed Jan 13, 2025
1 parent 92c9461 commit a417c03
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 18 deletions.
19 changes: 5 additions & 14 deletions ipmanager/basicConfigurer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (

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

// BasicConfigurer can be used to enable vip-management on nodes
Expand Down Expand Up @@ -55,14 +54,7 @@ const (
)

// arpSendGratuitous is a function that sends gratuitous ARP requests
func (c *BasicConfigurer) arpSendGratuitous() error {
// Open the network interface for sending
handle, err := pcap.OpenLive(c.Iface.Name, 65536, false, pcap.BlockForever)
if err != nil {
return err
}
defer handle.Close()

func (c *BasicConfigurer) createGratuitousARP() ([]byte, error) {
// Create the Ethernet layer
ethLayer := &layers.Ethernet{
SrcMAC: c.Iface.HardwareAddr,
Expand All @@ -89,11 +81,10 @@ func (c *BasicConfigurer) arpSendGratuitous() error {
FixLengths: true,
ComputeChecksums: true,
}
err = gopacket.SerializeLayers(buffer, opts, ethLayer, arpLayer)
if err != nil {
return err

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

// Send the packet
return handle.WritePacketData(buffer.Bytes())
return buffer.Bytes(), nil
}
34 changes: 32 additions & 2 deletions ipmanager/basicConfigurer_linux.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,51 @@
package ipmanager

import (
"net"
"os/exec"
"syscall"
)

const (
arpRequestOp = 1

Check failure on line 10 in ipmanager/basicConfigurer_linux.go

View workflow job for this annotation

GitHub Actions / Build & Test (ubuntu-latest)

const `arpRequestOp` is unused (unused)
arpReplyOp = 2

Check failure on line 11 in ipmanager/basicConfigurer_linux.go

View workflow job for this annotation

GitHub Actions / Build & Test (ubuntu-latest)

const `arpReplyOp` is unused (unused)
)

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 err := c.arpSendGratuitous(); err != nil {
log.Error("Failed to send gratuitous ARP: ", err)
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)
}
}
}

Expand Down
20 changes: 18 additions & 2 deletions ipmanager/basicConfigurer_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ import (
"github.com/cybertec-postgresql/vip-manager/iphlpapi"
)

func sendPacketWindows(iface net.Interface, packetData []byte) error {
// Open a raw socket using Winsock
conn, err := net.Dial("ip4:ethernet", iface.HardwareAddr.String())
if err != nil {
return err
}
defer conn.Close()
// Send the packet
_, err = conn.Write(packetData)
return err
}

// configureAddress assigns virtual IP address
func (c *BasicConfigurer) configureAddress() bool {
log.Infof("Configuring address %s on %s", c.getCIDR(), c.Iface.Name)
Expand All @@ -26,8 +38,12 @@ func (c *BasicConfigurer) configureAddress() bool {
return false
}

if err := c.arpSendGratuitous(); err != nil {
log.Error("Failed to send gratuitous ARP: ", err)
if buff, err := c.createGratuitousARP(); err != nil {
log.Warn("Failed to compose gratuitous ARP request: ", err)
} else {
if err := sendPacketWindows(c.Iface, buff); err != nil {
log.Warn("Failed to send gratuitous ARP request: ", err)
}
}
return true
}
Expand Down

0 comments on commit a417c03

Please sign in to comment.