mirror of
https://github.com/cwinfo/yggdrasil-go.git
synced 2024-11-22 15:20:30 +00:00
Merge pull request #15 from neilalexander/packettoobig
Implement Path MTU Discovery using session MTU
This commit is contained in:
commit
120ce8bd2f
@ -8,6 +8,7 @@ import "net"
|
|||||||
import "golang.org/x/net/ipv6"
|
import "golang.org/x/net/ipv6"
|
||||||
import "golang.org/x/net/icmp"
|
import "golang.org/x/net/icmp"
|
||||||
import "encoding/binary"
|
import "encoding/binary"
|
||||||
|
import "errors"
|
||||||
|
|
||||||
type macAddress [6]byte
|
type macAddress [6]byte
|
||||||
|
|
||||||
@ -129,14 +130,12 @@ func (i *icmpv6) parse_packet_tun(datain []byte) ([]byte, error) {
|
|||||||
response, err := i.handle_ndp(datain[ipv6.HeaderLen:])
|
response, err := i.handle_ndp(datain[ipv6.HeaderLen:])
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// Create our ICMPv6 response
|
// Create our ICMPv6 response
|
||||||
responsePacket, err := i.create_icmpv6_tun(ipv6Header.Src, ipv6.ICMPTypeNeighborAdvertisement, 0, response)
|
responsePacket, err := i.create_icmpv6_tun(ipv6Header.Src, ipv6.ICMPTypeNeighborAdvertisement, 0,
|
||||||
|
&icmp.DefaultMessageBody{Data: response})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix the checksum because I don't even know why, net/icmp is stupid
|
|
||||||
responsePacket[17] ^= 0x4
|
|
||||||
|
|
||||||
// Send it back
|
// Send it back
|
||||||
return responsePacket, nil
|
return responsePacket, nil
|
||||||
} else {
|
} else {
|
||||||
@ -145,10 +144,10 @@ func (i *icmpv6) parse_packet_tun(datain []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, errors.New("ICMPv6 type not matched")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *icmpv6) create_icmpv6_tap(dstmac macAddress, dst net.IP, mtype ipv6.ICMPType, mcode int, mbody []byte) ([]byte, error) {
|
func (i *icmpv6) create_icmpv6_tap(dstmac macAddress, dst net.IP, mtype ipv6.ICMPType, mcode int, mbody icmp.MessageBody) ([]byte, error) {
|
||||||
// Pass through to create_icmpv6_tun
|
// Pass through to create_icmpv6_tun
|
||||||
ipv6packet, err := i.create_icmpv6_tun(dst, mtype, mcode, mbody)
|
ipv6packet, err := i.create_icmpv6_tun(dst, mtype, mcode, mbody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -156,7 +155,7 @@ func (i *icmpv6) create_icmpv6_tap(dstmac macAddress, dst net.IP, mtype ipv6.ICM
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the response buffer
|
// Create the response buffer
|
||||||
dataout := make([]byte, ETHER+ipv6.HeaderLen+len(mbody))
|
dataout := make([]byte, ETHER+len(ipv6packet))
|
||||||
|
|
||||||
// Populate the response ethernet headers
|
// Populate the response ethernet headers
|
||||||
copy(dataout[:6], dstmac[:6])
|
copy(dataout[:6], dstmac[:6])
|
||||||
@ -168,36 +167,36 @@ func (i *icmpv6) create_icmpv6_tap(dstmac macAddress, dst net.IP, mtype ipv6.ICM
|
|||||||
return dataout, nil
|
return dataout, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *icmpv6) create_icmpv6_tun(dst net.IP, mtype ipv6.ICMPType, mcode int, mbody []byte) ([]byte, error) {
|
func (i *icmpv6) create_icmpv6_tun(dst 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(i.mylladdr, dst))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Create the IPv6 header
|
// Create the IPv6 header
|
||||||
ipv6Header := ipv6.Header{
|
ipv6Header := ipv6.Header{
|
||||||
Version: ipv6.Version,
|
Version: ipv6.Version,
|
||||||
NextHeader: 58,
|
NextHeader: 58,
|
||||||
PayloadLen: len(mbody),
|
PayloadLen: len(icmpMessageBuf),
|
||||||
HopLimit: 255,
|
HopLimit: 255,
|
||||||
Src: i.mylladdr,
|
Src: i.mylladdr,
|
||||||
Dst: dst,
|
Dst: dst,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the ICMPv6 message
|
|
||||||
icmpMessage := icmp.Message{
|
|
||||||
Type: mtype,
|
|
||||||
Code: mcode,
|
|
||||||
Body: &icmp.DefaultMessageBody{Data: mbody},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the IPv6 header into []byte
|
// Convert the IPv6 header into []byte
|
||||||
ipv6HeaderBuf, err := ipv6Header_Marshal(&ipv6Header)
|
ipv6HeaderBuf, err := ipv6Header_Marshal(&ipv6Header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the ICMPv6 message into []byte
|
|
||||||
icmpMessageBuf, err := icmpMessage.Marshal(icmp.IPv6PseudoHeader(ipv6Header.Dst, ipv6Header.Src))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct the packet
|
// Construct the packet
|
||||||
responsePacket := make([]byte, ipv6.HeaderLen+ipv6Header.PayloadLen)
|
responsePacket := make([]byte, ipv6.HeaderLen+ipv6Header.PayloadLen)
|
||||||
copy(responsePacket[:ipv6.HeaderLen], ipv6HeaderBuf)
|
copy(responsePacket[:ipv6.HeaderLen], ipv6HeaderBuf)
|
||||||
@ -210,11 +209,11 @@ func (i *icmpv6) create_icmpv6_tun(dst net.IP, mtype ipv6.ICMPType, mcode int, m
|
|||||||
func (i *icmpv6) handle_ndp(in []byte) ([]byte, error) {
|
func (i *icmpv6) handle_ndp(in []byte) ([]byte, error) {
|
||||||
// Ignore NDP requests for anything outside of fd00::/8
|
// Ignore NDP requests for anything outside of fd00::/8
|
||||||
if in[8] != 0xFD {
|
if in[8] != 0xFD {
|
||||||
return nil, nil
|
return nil, errors.New("Not an NDP for fd00::/8")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create our NDP message body response
|
// Create our NDP message body response
|
||||||
body := make([]byte, 32)
|
body := make([]byte, 28)
|
||||||
binary.BigEndian.PutUint32(body[:4], uint32(0x20000000))
|
binary.BigEndian.PutUint32(body[:4], uint32(0x20000000))
|
||||||
copy(body[4:20], in[8:24]) // Target address
|
copy(body[4:20], in[8:24]) // Target address
|
||||||
body[20] = uint8(2)
|
body[20] = uint8(2)
|
||||||
|
@ -23,6 +23,8 @@ package yggdrasil
|
|||||||
// The router then runs some sanity checks before passing it to the tun
|
// The router then runs some sanity checks before passing it to the tun
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
import "golang.org/x/net/icmp"
|
||||||
|
import "golang.org/x/net/ipv6"
|
||||||
|
|
||||||
//import "fmt"
|
//import "fmt"
|
||||||
//import "net"
|
//import "net"
|
||||||
@ -145,9 +147,28 @@ func (r *router) sendPacket(bs []byte) {
|
|||||||
fallthrough
|
fallthrough
|
||||||
//default: go func() { sinfo.send<-bs }()
|
//default: go func() { sinfo.send<-bs }()
|
||||||
default:
|
default:
|
||||||
|
// Generate an ICMPv6 Packet Too Big for packets larger than session MTU
|
||||||
if len(bs) > int(sinfo.getMTU()) {
|
if len(bs) > int(sinfo.getMTU()) {
|
||||||
// TODO: Send ICMPv6 Packet Too Big back to the TUN/TAP adapter
|
// Get the size of the oversized payload, up to a max of 900 bytes
|
||||||
sinfo.core.log.Printf("Packet length %d exceeds session MTU %d", len(bs), sinfo.getMTU())
|
window := 900
|
||||||
|
if int(sinfo.getMTU()) < window {
|
||||||
|
window = int(sinfo.getMTU())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the Packet Too Big response
|
||||||
|
ptb := &icmp.PacketTooBig{
|
||||||
|
MTU: int(sinfo.getMTU()),
|
||||||
|
Data: bs[:window],
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the ICMPv6 response from it
|
||||||
|
icmpv6Buf, err := r.core.tun.icmpv6.create_icmpv6_tun(bs[8:24], ipv6.ICMPTypePacketTooBig, 0, ptb)
|
||||||
|
if err == nil {
|
||||||
|
r.recv <- icmpv6Buf
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't continue - drop the packet
|
||||||
|
return
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
case sinfo.send <- bs:
|
case sinfo.send <- bs:
|
||||||
|
@ -279,7 +279,7 @@ func (ss *sessions) handlePing(ping *sessionPing) {
|
|||||||
// send
|
// send
|
||||||
var bs []byte
|
var bs []byte
|
||||||
bs, sinfo.packet = sinfo.packet, nil
|
bs, sinfo.packet = sinfo.packet, nil
|
||||||
go func() { sinfo.send <- bs }()
|
ss.core.router.sendPacket(bs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user