mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 11:15:07 +03:00 
			
		
		
		
	Track further neighbor state, don't send more NDPs than needed
This commit is contained in:
		
							parent
							
								
									d50e1bc803
								
							
						
					
					
						commit
						adc32fe92f
					
				
					 2 changed files with 66 additions and 32 deletions
				
			
		| 
						 | 
					@ -13,6 +13,7 @@ import (
 | 
				
			||||||
	"encoding/binary"
 | 
						"encoding/binary"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"golang.org/x/net/icmp"
 | 
						"golang.org/x/net/icmp"
 | 
				
			||||||
	"golang.org/x/net/ipv6"
 | 
						"golang.org/x/net/ipv6"
 | 
				
			||||||
| 
						 | 
					@ -26,7 +27,14 @@ type icmpv6 struct {
 | 
				
			||||||
	tun      *tunDevice
 | 
						tun      *tunDevice
 | 
				
			||||||
	mylladdr net.IP
 | 
						mylladdr net.IP
 | 
				
			||||||
	mymac    macAddress
 | 
						mymac    macAddress
 | 
				
			||||||
	peermacs map[address]macAddress
 | 
						peermacs map[address]neighbor
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type neighbor struct {
 | 
				
			||||||
 | 
						mac               macAddress
 | 
				
			||||||
 | 
						learned           bool
 | 
				
			||||||
 | 
						lastadvertisement time.Time
 | 
				
			||||||
 | 
						lastsolicitation  time.Time
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Marshal returns the binary encoding of h.
 | 
					// Marshal returns the binary encoding of h.
 | 
				
			||||||
| 
						 | 
					@ -51,7 +59,7 @@ func ipv6Header_Marshal(h *ipv6.Header) ([]byte, error) {
 | 
				
			||||||
// addresses.
 | 
					// addresses.
 | 
				
			||||||
func (i *icmpv6) init(t *tunDevice) {
 | 
					func (i *icmpv6) init(t *tunDevice) {
 | 
				
			||||||
	i.tun = t
 | 
						i.tun = t
 | 
				
			||||||
	i.peermacs = make(map[address]macAddress)
 | 
						i.peermacs = make(map[address]neighbor)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Our MAC address and link-local address
 | 
						// Our MAC address and link-local address
 | 
				
			||||||
	i.mymac = macAddress{
 | 
						i.mymac = macAddress{
 | 
				
			||||||
| 
						 | 
					@ -168,7 +176,11 @@ func (i *icmpv6) parse_packet_tun(datain []byte, datamac *[]byte) ([]byte, error
 | 
				
			||||||
			var mac macAddress
 | 
								var mac macAddress
 | 
				
			||||||
			copy(addr[:], ipv6Header.Src[:])
 | 
								copy(addr[:], ipv6Header.Src[:])
 | 
				
			||||||
			copy(mac[:], (*datamac)[:])
 | 
								copy(mac[:], (*datamac)[:])
 | 
				
			||||||
			i.peermacs[addr] = mac
 | 
								neighbor := i.peermacs[addr]
 | 
				
			||||||
 | 
								neighbor.mac = mac
 | 
				
			||||||
 | 
								neighbor.learned = true
 | 
				
			||||||
 | 
								neighbor.lastadvertisement = time.Now()
 | 
				
			||||||
 | 
								i.peermacs[addr] = neighbor
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return nil, errors.New("No response needed")
 | 
							return nil, errors.New("No response needed")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -242,27 +254,11 @@ func (i *icmpv6) create_icmpv6_tun(dst net.IP, src net.IP, mtype ipv6.ICMPType,
 | 
				
			||||||
	return responsePacket, nil
 | 
						return responsePacket, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (i *icmpv6) create_ndp_tap(in []byte) ([]byte, error) {
 | 
					func (i *icmpv6) create_ndp_tap(dst address) ([]byte, error) {
 | 
				
			||||||
	// Parse the IPv6 packet headers
 | 
					 | 
				
			||||||
	ipv6Header, err := ipv6.ParseHeader(in[:ipv6.HeaderLen])
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Check if the packet is IPv6
 | 
					 | 
				
			||||||
	if ipv6Header.Version != ipv6.Version {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Check if the packet is ICMPv6
 | 
					 | 
				
			||||||
	if ipv6Header.NextHeader != 58 {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Create the ND payload
 | 
						// Create the ND payload
 | 
				
			||||||
	var payload [28]byte
 | 
						var payload [28]byte
 | 
				
			||||||
	copy(payload[:4], []byte{0x00, 0x00, 0x00, 0x00})
 | 
						copy(payload[:4], []byte{0x00, 0x00, 0x00, 0x00})
 | 
				
			||||||
	copy(payload[4:20], ipv6Header.Dst[:])
 | 
						copy(payload[4:20], dst[:])
 | 
				
			||||||
	copy(payload[20:22], []byte{0x01, 0x01})
 | 
						copy(payload[20:22], []byte{0x01, 0x01})
 | 
				
			||||||
	copy(payload[22:28], i.mymac[:6])
 | 
						copy(payload[22:28], i.mymac[:6])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -272,7 +268,7 @@ func (i *icmpv6) create_ndp_tap(in []byte) ([]byte, error) {
 | 
				
			||||||
		0xFF, 0x02, 0x00, 0x00,
 | 
							0xFF, 0x02, 0x00, 0x00,
 | 
				
			||||||
		0x00, 0x00, 0x00, 0x00,
 | 
							0x00, 0x00, 0x00, 0x00,
 | 
				
			||||||
		0x00, 0x00, 0x00, 0x01, 0xFF})
 | 
							0x00, 0x00, 0x00, 0x01, 0xFF})
 | 
				
			||||||
	copy(dstaddr[13:], ipv6Header.Dst[13:16])
 | 
						copy(dstaddr[13:], dst[13:16])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Create the multicast MAC
 | 
						// Create the multicast MAC
 | 
				
			||||||
	var dstmac macAddress
 | 
						var dstmac macAddress
 | 
				
			||||||
| 
						 | 
					@ -287,6 +283,9 @@ func (i *icmpv6) create_ndp_tap(in []byte) ([]byte, error) {
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						neighbor := i.peermacs[dstaddr]
 | 
				
			||||||
 | 
						neighbor.lastsolicitation = time.Now()
 | 
				
			||||||
 | 
						i.peermacs[dstaddr] = neighbor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return requestPacket, nil
 | 
						return requestPacket, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@ package yggdrasil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
	"yggdrasil/defaults"
 | 
						"yggdrasil/defaults"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/songgao/packets/ethernet"
 | 
						"github.com/songgao/packets/ethernet"
 | 
				
			||||||
| 
						 | 
					@ -49,6 +50,21 @@ func (tun *tunDevice) start(ifname string, iftapmode bool, addr string, mtu int)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	go func() { panic(tun.read()) }()
 | 
						go func() { panic(tun.read()) }()
 | 
				
			||||||
	go func() { panic(tun.write()) }()
 | 
						go func() { panic(tun.write()) }()
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
								if _, ok := tun.icmpv6.peermacs[tun.core.router.addr]; ok {
 | 
				
			||||||
 | 
									break
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								request, err := tun.icmpv6.create_ndp_tap(tun.core.router.addr)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									panic(err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if _, err := tun.iface.Write(request); err != nil {
 | 
				
			||||||
 | 
									panic(err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								time.Sleep(time.Second)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -76,7 +92,35 @@ func (tun *tunDevice) write() error {
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				return errors.New("Invalid address family")
 | 
									return errors.New("Invalid address family")
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if peermac, ok := tun.icmpv6.peermacs[destAddr]; ok {
 | 
								sendndp := func(destAddr address) {
 | 
				
			||||||
 | 
									neigh, known := tun.icmpv6.peermacs[destAddr]
 | 
				
			||||||
 | 
									known = known && (time.Since(neigh.lastsolicitation).Seconds() < 30)
 | 
				
			||||||
 | 
									if !known {
 | 
				
			||||||
 | 
										request, err := tun.icmpv6.create_ndp_tap(destAddr)
 | 
				
			||||||
 | 
										if err != nil {
 | 
				
			||||||
 | 
											panic(err)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										if _, err := tun.iface.Write(request); err != nil {
 | 
				
			||||||
 | 
											panic(err)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										tun.icmpv6.peermacs[destAddr] = neighbor{
 | 
				
			||||||
 | 
											lastsolicitation: time.Now(),
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var peermac macAddress
 | 
				
			||||||
 | 
								var peerknown bool
 | 
				
			||||||
 | 
								if neighbor, ok := tun.icmpv6.peermacs[destAddr]; ok && neighbor.learned {
 | 
				
			||||||
 | 
									peermac = neighbor.mac
 | 
				
			||||||
 | 
									peerknown = true
 | 
				
			||||||
 | 
								} else if neighbor, ok := tun.icmpv6.peermacs[tun.core.router.addr]; ok && neighbor.learned {
 | 
				
			||||||
 | 
									peermac = neighbor.mac
 | 
				
			||||||
 | 
									peerknown = true
 | 
				
			||||||
 | 
									sendndp(destAddr)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									sendndp(tun.core.router.addr)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if peerknown {
 | 
				
			||||||
				var frame ethernet.Frame
 | 
									var frame ethernet.Frame
 | 
				
			||||||
				frame.Prepare(
 | 
									frame.Prepare(
 | 
				
			||||||
					peermac[:6],          // Destination MAC address
 | 
										peermac[:6],          // Destination MAC address
 | 
				
			||||||
| 
						 | 
					@ -88,16 +132,7 @@ func (tun *tunDevice) write() error {
 | 
				
			||||||
				if _, err := tun.iface.Write(frame); err != nil {
 | 
									if _, err := tun.iface.Write(frame); err != nil {
 | 
				
			||||||
					panic(err)
 | 
										panic(err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				request, err := tun.icmpv6.create_ndp_tap(data)
 | 
					 | 
				
			||||||
				if err != nil {
 | 
					 | 
				
			||||||
					panic(err)
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
				if _, err := tun.iface.Write(request); err != nil {
 | 
					 | 
				
			||||||
					panic(err)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			if _, err := tun.iface.Write(data); err != nil {
 | 
								if _, err := tun.iface.Write(data); err != nil {
 | 
				
			||||||
				panic(err)
 | 
									panic(err)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue