Send ICMPv6 response to packets larger than session MTU (WIP: checksum wrong?)

This commit is contained in:
Neil Alexander 2018-02-14 22:59:24 +00:00
parent a3a9696880
commit 37e4492b86
2 changed files with 32 additions and 7 deletions

View File

@ -129,7 +129,8 @@ func (i *icmpv6) parse_packet_tun(datain []byte) ([]byte, error) {
response, err := i.handle_ndp(datain[ipv6.HeaderLen:])
if err == nil {
// 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 {
return nil, err
}
@ -148,7 +149,7 @@ func (i *icmpv6) parse_packet_tun(datain []byte) ([]byte, error) {
return nil, nil
}
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
ipv6packet, err := i.create_icmpv6_tun(dst, mtype, mcode, mbody)
if err != nil {
@ -156,7 +157,7 @@ func (i *icmpv6) create_icmpv6_tap(dstmac macAddress, dst net.IP, mtype ipv6.ICM
}
// Create the response buffer
dataout := make([]byte, ETHER+ipv6.HeaderLen+len(mbody))
dataout := make([]byte, ETHER+ipv6.HeaderLen+mbody.Len(0))
// Populate the response ethernet headers
copy(dataout[:6], dstmac[:6])
@ -168,12 +169,12 @@ func (i *icmpv6) create_icmpv6_tap(dstmac macAddress, dst net.IP, mtype ipv6.ICM
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 IPv6 header
ipv6Header := ipv6.Header{
Version: ipv6.Version,
NextHeader: 58,
PayloadLen: len(mbody),
PayloadLen: mbody.Len(0),
HopLimit: 255,
Src: i.mylladdr,
Dst: dst,
@ -183,7 +184,7 @@ func (i *icmpv6) create_icmpv6_tun(dst net.IP, mtype ipv6.ICMPType, mcode int, m
icmpMessage := icmp.Message{
Type: mtype,
Code: mcode,
Body: &icmp.DefaultMessageBody{Data: mbody},
Body: mbody,
}
// Convert the IPv6 header into []byte

View File

@ -23,6 +23,8 @@ package yggdrasil
// The router then runs some sanity checks before passing it to the tun
import "time"
import "golang.org/x/net/icmp"
import "golang.org/x/net/ipv6"
//import "fmt"
//import "net"
@ -145,9 +147,31 @@ func (r *router) sendPacket(bs []byte) {
fallthrough
//default: go func() { sinfo.send<-bs }()
default:
// Generate an ICMPv6 Packet Too Big for packets larger than session MTU
if len(bs) > int(sinfo.getMTU()) {
// TODO: Send ICMPv6 Packet Too Big back to the TUN/TAP adapter
sinfo.core.log.Printf("Packet length %d exceeds session MTU %d", len(bs), sinfo.getMTU())
// Get the size of the oversized payload, up to a max of 900 bytes
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 {
sinfo.core.log.Printf("Sending ICMPv6 Message Too Big")
r.recv <- icmpv6Buf
}
// Don't continue - drop the packet
return
}
select {
case sinfo.send <- bs: