mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 03:05:07 +03:00 
			
		
		
		
	move ICMP PacketTooBig sending into core
This commit is contained in:
		
							parent
							
								
									8621223a1f
								
							
						
					
					
						commit
						3393db8e77
					
				
					 5 changed files with 33 additions and 106 deletions
				
			
		| 
						 | 
					@ -231,6 +231,18 @@ func (c *Core) MaxMTU() uint64 {
 | 
				
			||||||
	return c.store.maxSessionMTU()
 | 
						return c.store.maxSessionMTU()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SetMTU can only safely be called after Init and before Start.
 | 
				
			||||||
 | 
					func (c *Core) SetMTU(mtu uint64) {
 | 
				
			||||||
 | 
						if mtu < 1280 {
 | 
				
			||||||
 | 
							mtu = 1280
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c.store.mtu = mtu
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Core) MTU() uint64 {
 | 
				
			||||||
 | 
						return c.store.mtu
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Implement io.ReadWriteCloser
 | 
					// Implement io.ReadWriteCloser
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Core) Read(p []byte) (n int, err error) {
 | 
					func (c *Core) Read(p []byte) (n int, err error) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,9 @@ import (
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"golang.org/x/net/icmp"
 | 
				
			||||||
 | 
						"golang.org/x/net/ipv6"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	iwt "github.com/Arceliar/ironwood/types"
 | 
						iwt "github.com/Arceliar/ironwood/types"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/address"
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/address"
 | 
				
			||||||
| 
						 | 
					@ -26,6 +29,7 @@ type keyStore struct {
 | 
				
			||||||
	addrBuffer   map[address.Address]*buffer
 | 
						addrBuffer   map[address.Address]*buffer
 | 
				
			||||||
	subnetToInfo map[address.Subnet]*keyInfo
 | 
						subnetToInfo map[address.Subnet]*keyInfo
 | 
				
			||||||
	subnetBuffer map[address.Subnet]*buffer
 | 
						subnetBuffer map[address.Subnet]*buffer
 | 
				
			||||||
 | 
						mtu          uint64
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type keyInfo struct {
 | 
					type keyInfo struct {
 | 
				
			||||||
| 
						 | 
					@ -53,6 +57,7 @@ func (k *keyStore) init(core *Core) {
 | 
				
			||||||
	k.addrBuffer = make(map[address.Address]*buffer)
 | 
						k.addrBuffer = make(map[address.Address]*buffer)
 | 
				
			||||||
	k.subnetToInfo = make(map[address.Subnet]*keyInfo)
 | 
						k.subnetToInfo = make(map[address.Subnet]*keyInfo)
 | 
				
			||||||
	k.subnetBuffer = make(map[address.Subnet]*buffer)
 | 
						k.subnetBuffer = make(map[address.Subnet]*buffer)
 | 
				
			||||||
 | 
						k.mtu = 1280 // Default to something safe, expect user to set this
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (k *keyStore) sendToAddress(addr address.Address, bs []byte) {
 | 
					func (k *keyStore) sendToAddress(addr address.Address, bs []byte) {
 | 
				
			||||||
| 
						 | 
					@ -238,18 +243,19 @@ func (k *keyStore) readPC(p []byte) (int, error) {
 | 
				
			||||||
		if len(bs) < 40 {
 | 
							if len(bs) < 40 {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		/* TODO? ICMP packet too big, for now tuntap sends this when needed
 | 
							if len(bs) > int(k.mtu) {
 | 
				
			||||||
		  if len(bs) > int(tun.MTU()) {
 | 
								// Using bs would make it leak off the stack, so copy to buf
 | 
				
			||||||
 | 
								buf := make([]byte, 40)
 | 
				
			||||||
 | 
								copy(buf, bs)
 | 
				
			||||||
			ptb := &icmp.PacketTooBig{
 | 
								ptb := &icmp.PacketTooBig{
 | 
				
			||||||
				  MTU:  int(tun.mtu),
 | 
									MTU:  int(k.mtu),
 | 
				
			||||||
				  Data: bs[:40],
 | 
									Data: buf[:40],
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			  if packet, err := CreateICMPv6(bs[8:24], bs[24:40], ipv6.ICMPTypePacketTooBig, 0, ptb); err == nil {
 | 
								if packet, err := CreateICMPv6(buf[8:24], buf[24:40], ipv6.ICMPTypePacketTooBig, 0, ptb); err == nil {
 | 
				
			||||||
				  _, _ = tun.core.WriteTo(packet, from)
 | 
									_, _ = k.writePC(packet)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		*/
 | 
					 | 
				
			||||||
		var srcAddr, dstAddr address.Address
 | 
							var srcAddr, dstAddr address.Address
 | 
				
			||||||
		var srcSubnet, dstSubnet address.Subnet
 | 
							var srcSubnet, dstSubnet address.Subnet
 | 
				
			||||||
		copy(srcAddr[:], bs[8:])
 | 
							copy(srcAddr[:], bs[8:])
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,80 +0,0 @@
 | 
				
			||||||
package tuntap
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// The ICMPv6 module implements functions to easily create ICMPv6
 | 
					 | 
				
			||||||
// packets. These functions, when mixed with the built-in Go IPv6
 | 
					 | 
				
			||||||
// and ICMP libraries, can be used to send control messages back
 | 
					 | 
				
			||||||
// to the host. Examples include:
 | 
					 | 
				
			||||||
// - NDP messages, when running in TAP mode
 | 
					 | 
				
			||||||
// - Packet Too Big messages, when packets exceed the session MTU
 | 
					 | 
				
			||||||
// - Destination Unreachable messages, when a session prohibits
 | 
					 | 
				
			||||||
//   incoming traffic
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"encoding/binary"
 | 
					 | 
				
			||||||
	"net"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"golang.org/x/net/icmp"
 | 
					 | 
				
			||||||
	"golang.org/x/net/ipv6"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type ICMPv6 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Marshal returns the binary encoding of h.
 | 
					 | 
				
			||||||
func ipv6Header_Marshal(h *ipv6.Header) ([]byte, error) {
 | 
					 | 
				
			||||||
	b := make([]byte, 40)
 | 
					 | 
				
			||||||
	b[0] |= byte(h.Version) << 4
 | 
					 | 
				
			||||||
	b[0] |= byte(h.TrafficClass) >> 4
 | 
					 | 
				
			||||||
	b[1] |= byte(h.TrafficClass) << 4
 | 
					 | 
				
			||||||
	b[1] |= byte(h.FlowLabel >> 16)
 | 
					 | 
				
			||||||
	b[2] = byte(h.FlowLabel >> 8)
 | 
					 | 
				
			||||||
	b[3] = byte(h.FlowLabel)
 | 
					 | 
				
			||||||
	binary.BigEndian.PutUint16(b[4:6], uint16(h.PayloadLen))
 | 
					 | 
				
			||||||
	b[6] = byte(h.NextHeader)
 | 
					 | 
				
			||||||
	b[7] = byte(h.HopLimit)
 | 
					 | 
				
			||||||
	copy(b[8:24], h.Src)
 | 
					 | 
				
			||||||
	copy(b[24:40], h.Dst)
 | 
					 | 
				
			||||||
	return b, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Creates an ICMPv6 packet based on the given icmp.MessageBody and other
 | 
					 | 
				
			||||||
// parameters, complete with IP headers only, which can be written directly to
 | 
					 | 
				
			||||||
// a TUN adapter, or called directly by the CreateICMPv6L2 function when
 | 
					 | 
				
			||||||
// generating a message for TAP adapters.
 | 
					 | 
				
			||||||
func CreateICMPv6(dst net.IP, src net.IP, mtype ipv6.ICMPType, mcode int, mbody icmp.MessageBody) ([]byte, error) {
 | 
					 | 
				
			||||||
	// Create the ICMPv6 message
 | 
					 | 
				
			||||||
	icmpMessage := icmp.Message{
 | 
					 | 
				
			||||||
		Type: mtype,
 | 
					 | 
				
			||||||
		Code: mcode,
 | 
					 | 
				
			||||||
		Body: mbody,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Convert the ICMPv6 message into []byte
 | 
					 | 
				
			||||||
	icmpMessageBuf, err := icmpMessage.Marshal(icmp.IPv6PseudoHeader(src, dst))
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Create the IPv6 header
 | 
					 | 
				
			||||||
	ipv6Header := ipv6.Header{
 | 
					 | 
				
			||||||
		Version:    ipv6.Version,
 | 
					 | 
				
			||||||
		NextHeader: 58,
 | 
					 | 
				
			||||||
		PayloadLen: len(icmpMessageBuf),
 | 
					 | 
				
			||||||
		HopLimit:   255,
 | 
					 | 
				
			||||||
		Src:        src,
 | 
					 | 
				
			||||||
		Dst:        dst,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Convert the IPv6 header into []byte
 | 
					 | 
				
			||||||
	ipv6HeaderBuf, err := ipv6Header_Marshal(&ipv6Header)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Construct the packet
 | 
					 | 
				
			||||||
	responsePacket := make([]byte, ipv6.HeaderLen+ipv6Header.PayloadLen)
 | 
					 | 
				
			||||||
	copy(responsePacket[:ipv6.HeaderLen], ipv6HeaderBuf)
 | 
					 | 
				
			||||||
	copy(responsePacket[ipv6.HeaderLen:], icmpMessageBuf)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Send it back
 | 
					 | 
				
			||||||
	return responsePacket, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,5 @@
 | 
				
			||||||
package tuntap
 | 
					package tuntap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"golang.org/x/net/icmp"
 | 
					 | 
				
			||||||
	"golang.org/x/net/ipv6"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const TUN_OFFSET_BYTES = 4
 | 
					const TUN_OFFSET_BYTES = 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (tun *TunAdapter) read() {
 | 
					func (tun *TunAdapter) read() {
 | 
				
			||||||
| 
						 | 
					@ -37,15 +32,8 @@ func (tun *TunAdapter) write() {
 | 
				
			||||||
			tun.log.Errorln("Exiting tun writer due to core read error:", err)
 | 
								tun.log.Errorln("Exiting tun writer due to core read error:", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if n > int(tun.MTU()) {
 | 
							if !tun.isEnabled {
 | 
				
			||||||
			ptb := &icmp.PacketTooBig{
 | 
								continue // Nothing to do, the tun isn't enabled
 | 
				
			||||||
				MTU:  int(tun.mtu),
 | 
					 | 
				
			||||||
				Data: bs[:40],
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if packet, err := CreateICMPv6(bs[8:24], bs[24:40], ipv6.ICMPTypePacketTooBig, 0, ptb); err == nil {
 | 
					 | 
				
			||||||
				_, _ = tun.core.Write(packet)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		bs = buf[:TUN_OFFSET_BYTES+n]
 | 
							bs = buf[:TUN_OFFSET_BYTES+n]
 | 
				
			||||||
		if _, err = tun.iface.Write(bs, TUN_OFFSET_BYTES); err != nil {
 | 
							if _, err = tun.iface.Write(bs, TUN_OFFSET_BYTES); err != nil {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -139,6 +139,7 @@ func (tun *TunAdapter) _start() error {
 | 
				
			||||||
	if tun.MTU() != mtu {
 | 
						if tun.MTU() != mtu {
 | 
				
			||||||
		tun.log.Warnf("Warning: Interface MTU %d automatically adjusted to %d (supported range is 1280-%d)", tun.config.IfMTU, tun.MTU(), MaximumMTU())
 | 
							tun.log.Warnf("Warning: Interface MTU %d automatically adjusted to %d (supported range is 1280-%d)", tun.config.IfMTU, tun.MTU(), MaximumMTU())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						tun.core.SetMTU(tun.MTU())
 | 
				
			||||||
	tun.isOpen = true
 | 
						tun.isOpen = true
 | 
				
			||||||
	tun.isEnabled = true
 | 
						tun.isEnabled = true
 | 
				
			||||||
	go tun.read()
 | 
						go tun.read()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue