To reduce bot traffic you must login to view /gokrazy/rtr7-kernel/raw/branch/master/.gitignore.
The GitHub login only links via username.
Files

81 lines
2.1 KiB
Go

package main
import (
"log"
"strconv"
"unsafe"
"github.com/mdlayher/ndp"
"github.com/vishvananda/netlink/nl"
"golang.org/x/net/ipv6"
"golang.org/x/sys/unix"
)
func DeserializeNdUserOptMsg(b []byte) *unix.NdUseroptmsg {
return (*unix.NdUseroptmsg)(unsafe.Pointer(&b[0:unix.SizeofNdUseroptmsg][0]))
}
func getRDNSS(m []byte, optsEnd int, linkIndex int) (*ndp.RecursiveDNSServer, error) {
opts := m[unix.SizeofNdUseroptmsg:optsEnd]
// Hack together a fake icmp packet so that we can use parsing from ndp
// unix.SizeofNdUseroptmsg == 16 but I don't feel like mangling it right now
buf := make([]byte, 16, 16+len(opts))
buf[0] = byte(ipv6.ICMPTypeRouterAdvertisement)
buf = append(buf, opts...)
pm, err := ndp.ParseMessage(buf)
if err != nil {
return nil, err
}
var (
r *ndp.RecursiveDNSServer
ok bool
)
for _, o := range pm.(*ndp.RouterAdvertisement).Options {
if r, ok = o.(*ndp.RecursiveDNSServer); ok {
for i, addr := range r.Servers {
if addr.IsLinkLocalUnicast() {
// We add the zone here for link-local because the address won't work without the zones
r.Servers[i] = addr.WithZone(strconv.Itoa(linkIndex))
}
}
break
}
}
return r, nil
}
func ListenForSLAACDNS(slaacChannel chan *ndp.RecursiveDNSServer) {
s, err := nl.Subscribe(unix.NETLINK_ROUTE, unix.RTNLGRP_ND_USEROPT)
if err != nil {
log.Printf("Unable to listen for SLAAC DNS changes %v", err)
}
defer s.Close()
for {
msgs, from, err := s.Receive()
if err != nil {
log.Printf("Failed to recieve SLAAC DNS changes. Restart to try again: %v", err)
return
}
if from.Pid != nl.PidKernel {
continue
}
for _, m := range msgs {
if m.Header.Type != unix.RTM_NEWNDUSEROPT {
continue
}
msg := DeserializeNdUserOptMsg(m.Data)
if msg.Family != unix.AF_INET6 || msg.Icmp_type != byte(ipv6.ICMPTypeRouterAdvertisement) {
continue
}
slaacDNSServers, err := getRDNSS(m.Data, unix.SizeofNdUseroptmsg+int(msg.Opts_len), int(msg.Ifindex))
if err == nil && slaacDNSServers != nil && len(slaacDNSServers.Servers) > 0 {
slaacChannel <- slaacDNSServers
} else {
log.Printf("Failed to parse slaac options: %v", err)
}
}
}
}