Skip to content

Commit

Permalink
Improve logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Kioubit committed Jul 7, 2024
1 parent 243e9b9 commit 3e6b548
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 42 deletions.
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
module pndpd

go 1.20
go 1.22.5

require (
golang.org/x/net v0.9.0
golang.org/x/sys v0.7.0
golang.org/x/net v0.27.0
golang.org/x/sys v0.22.0
)
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
47 changes: 29 additions & 18 deletions pndp/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func setPromisc(fd int, iface string, enable bool, withInterfaceFlags bool) {
iFace, err := net.InterfaceByName(iface)
if err != nil {
showFatalError(err.Error())
return
}

mReq := unix.PacketMreq{
Expand All @@ -95,34 +96,44 @@ func setPromisc(fd int, iface string, enable bool, withInterfaceFlags bool) {
// ---------------------------------------------------------------------
}

func selectSourceIP(iface *net.Interface) []byte {
var _, ulaSpace, _ = net.ParseCIDR("fc00::/7")
var result = emptyIpv6
ifaceaddrs, err := iface.Addrs()
func selectSourceIP(iface *net.Interface) (gua []byte, ula []byte) {
gua = emptyIpv6
ula = emptyIpv6
interfaceAddresses, err := iface.Addrs()
if err != nil {
return result
return gua, ula
}

for _, n := range ifaceaddrs {
tip, _, err := net.ParseCIDR(n.String())
var haveUla = false
var haveGua = false
for _, n := range interfaceAddresses {
if haveGua && haveUla {
break
}
testIP, _, err := net.ParseCIDR(n.String())
if err != nil {
break
}
var haveUla = false
if isIpv6(tip.String()) {
if tip.IsGlobalUnicast() {
haveUla = true
result = tip

if !ulaSpace.Contains(tip) {
break
if isIpv6(testIP.String()) {
if testIP.IsGlobalUnicast() {
if !ulaSpace.Contains(testIP) {
haveGua = true
gua = testIP
} else {
haveUla = true
ula = testIP
}
} else if testIP.IsLinkLocalUnicast() {
if !haveUla {
ula = testIP
}
if !haveGua {
gua = testIP
}
} else if tip.IsLinkLocalUnicast() && !haveUla {
result = tip
}
}
}
return result
return gua, ula
}

func getInterfaceNetworkList(iface *net.Interface) []*net.IPNet {
Expand Down
18 changes: 11 additions & 7 deletions pndp/interfaceMon.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,14 @@ func getUpdates() {
continue
}

srcIP := selectSourceIP(iface)
srcIP, srcIPUla := selectSourceIP(iface)
monMutex.Lock()

for i := range monInterfaceList {
if monInterfaceList[i].iface.Name == iface.Name {
oldMonIface := monInterfaceList[i]
oldMonIface.sourceIP = srcIP
oldMonIface.sourceIPULA = srcIPUla
if oldMonIface.autosense {
oldMonIface.networks = getInterfaceNetworkList(iface)
}
Expand All @@ -78,11 +79,12 @@ func getUpdates() {
}

type monInterface struct {
addCount int
sourceIP []byte //TODO ULA
networks []*net.IPNet
iface *net.Interface
autosense bool
addCount int
sourceIP []byte
sourceIPULA []byte
networks []*net.IPNet
iface *net.Interface
autosense bool
}

var (
Expand All @@ -100,6 +102,7 @@ func addInterfaceToMon(iface string, autosense bool) {
niface, err := net.InterfaceByName(iface)
if err != nil {
showFatalError(err.Error())
return
}

for i := range monInterfaceList {
Expand All @@ -117,7 +120,7 @@ func addInterfaceToMon(iface string, autosense bool) {
autosense: autosense,
iface: niface,
}
newMonIface.sourceIP = selectSourceIP(niface)
newMonIface.sourceIP, newMonIface.sourceIPULA = selectSourceIP(niface)
newMonIface.networks = getInterfaceNetworkList(niface)

monInterfaceList = append(monInterfaceList, newMonIface)
Expand All @@ -132,6 +135,7 @@ func removeInterfaceFromMon(iface string) {
niface, err := net.InterfaceByName(iface)
if err != nil {
showFatalError(err.Error())
return
}
for i := range monInterfaceList {
if monInterfaceList[i].iface.Name == niface.Name {
Expand Down
2 changes: 1 addition & 1 deletion pndp/netlink.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func newNetlinkSocket(protocol int, multicastGroups ...uint) (*netlinkSocket, er
socket.lsa.Family = unix.AF_NETLINK

for _, g := range multicastGroups {
socket.lsa.Groups |= (1 << (g - 1))
socket.lsa.Groups |= 1 << (g - 1)
}

err = unix.Bind(fd, &socket.lsa)
Expand Down
2 changes: 1 addition & 1 deletion pndp/packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ func calculateChecksum(h *ipv6Header, payload []byte) uint16 {
}

func checksumAddition(b []byte, buf uint16) uint16 {
var sum uint32 = uint32(buf)
var sum = uint32(buf)
cv := len(b) - 1
for i := 0; i < cv; i += 2 {
sum += uint32(uint16(b[i])<<8 | uint16(b[i+1]))
Expand Down
20 changes: 12 additions & 8 deletions pndp/responder.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ func respond(iface string, requests chan *ndpRequest, respondType ndpType, ndpQu
showFatalError(err.Error())
}

var selectedSelfSourceIP = emptyIpv6

for {
var req *ndpRequest
if (ndpQuestionChan == nil && respondType == ndp_ADV) || (ndpQuestionChan != nil && respondType == ndp_SOL) {
Expand Down Expand Up @@ -80,7 +78,6 @@ func respond(iface string, requests chan *ndpRequest, respondType ndpType, ndpQu
continue
}

selectedSelfSourceIP = getInterfaceInfo(respondIface).sourceIP
// Auto-sense
if autoSense != "" {
filter = getInterfaceInfo(autoiface).networks
Expand All @@ -100,9 +97,17 @@ func respond(iface string, requests chan *ndpRequest, respondType ndpType, ndpQu
}
}

intInfo := getInterfaceInfo(respondIface)
var selectedSelfSourceIPGua = intInfo.sourceIP
var selectedSelfSourceIPUla = intInfo.sourceIPULA
var selectedSelfSourceIP = selectedSelfSourceIPGua
if ulaSpace.Contains(req.answeringForIP) {
selectedSelfSourceIP = selectedSelfSourceIPUla
}

if req.sourceIface == iface {
slog.Debug("Sending packet", "type", respondType, "dest", ipValue{req.dstIP}, "interface", respondIface.Name)
sendNDPPacket(fd, selectedSelfSourceIP, req.srcIP, req.answeringForIP, respondIface.HardwareAddr, respondType)
sendNDPPacket(fd, req.dstIP, req.srcIP, req.answeringForIP, respondIface.HardwareAddr, respondType)
} else {
if respondType == ndp_ADV {
if !bytes.Equal(req.dstIP, allNodesMulticastIPv6) { // Skip in case of unsolicited advertisement
Expand All @@ -125,6 +130,7 @@ func respond(iface string, requests chan *ndpRequest, respondType ndpType, ndpQu
}
}
slog.Debug("Sending packet", "type", respondType, "dest", ipValue{req.dstIP}, "interface", respondIface.Name)

sendNDPPacket(fd, selectedSelfSourceIP, req.dstIP, req.answeringForIP, respondIface.HardwareAddr, respondType)
}
}
Expand All @@ -145,11 +151,9 @@ func sendNDPPacket(fd int, ownIP []byte, dstIP []byte, ndpTargetIP []byte, ndpTa
var t [16]byte
copy(t[:], dstIP)

d := syscall.SockaddrInet6{
Port: 0,
err = syscall.Sendto(fd, packet, 0, &syscall.SockaddrInet6{
Addr: t,
}
err = syscall.Sendto(fd, packet, 0, &d)
})
if err != nil {
slog.Error("Error sending packet", err)
}
Expand Down
3 changes: 3 additions & 0 deletions pndp/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package pndp
import (
"fmt"
"log/slog"
"net"
"net/netip"
"os"
)
Expand Down Expand Up @@ -44,3 +45,5 @@ func (v macValue) LogValue() slog.Value {
// Htons Convert a uint16 to host byte order (big endian)
func htons(v uint16) int { return int(htons16(v)) }
func htons16(v uint16) uint16 { return (v << 8) | (v >> 8) }

var _, ulaSpace, _ = net.ParseCIDR("fc00::/7")
5 changes: 5 additions & 0 deletions pndp_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ ip netns exec pndpd-i sysctl -w net.ipv6.conf.all.forwarding=1
# Provider bridge
ip -netns pndpd-p link add br0 type bridge
ip -netns pndpd-p addr add fd00::/62 dev br0
ip -netns pndpd-p addr add 2001:db8::/62 dev br0
ip -netns pndpd-p link set dev br0 address 00:00:00:00:00:01 # Predictable link-local
ip -netns pndpd-p link set up dev br0

Expand All @@ -23,12 +24,14 @@ ip -netns pndpd-p link set veth-c0 master br0

ip -netns pndpd-p link set veth-p netns pndpd-c
ip -netns pndpd-c addr add fd00:0:0:1::/128 dev veth-p
ip -netns pndpd-c addr add 2001:db8:0:1::/128 dev veth-p
ip -netns pndpd-c link set up dev veth-p
ip -netns pndpd-c route add default via fe80::200:ff:fe00:1 dev veth-p

# Bridge on client 0
ip -netns pndpd-c link add br0 type bridge
ip -netns pndpd-c addr add fd00:0:0:1::/64 dev br0
ip -netns pndpd-c addr add 2001:db8:0:1::/64 dev br0
ip -netns pndpd-c link set dev br0 address 00:00:00:00:00:02
ip -netns pndpd-c link set up dev br0

Expand All @@ -39,6 +42,7 @@ ip -netns pndpd-c link set veth-i0 master br0

ip -netns pndpd-c link set veth-c netns pndpd-i
ip -netns pndpd-i addr add fd00:0:0:1::100/64 dev veth-c
ip -netns pndpd-i addr add 2001:db8:0:1::100/64 dev veth-c
ip -netns pndpd-i link set up dev veth-c
ip -netns pndpd-i route add default via fd00:0:0:1:: dev veth-c

Expand All @@ -49,6 +53,7 @@ sleep 2

# Perform tests
ip netns exec pndpd-p ping -c 5 -w 10 fd00:0:0:1::100
ip netns exec pndpd-p ping -c 5 -w 10 2001:db8:0:1::100

kill -n 2 "$PID"
wait
Expand Down

0 comments on commit 3e6b548

Please sign in to comment.