mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2024-11-23 18:15:24 +00:00
move ICMP PacketTooBig sending into core
This commit is contained in:
parent
8621223a1f
commit
3393db8e77
@ -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…
Reference in New Issue
Block a user