diff --git a/src/yggdrasil/icmpv6.go b/src/yggdrasil/icmpv6.go index f96a9c9a..85a6bbb7 100644 --- a/src/yggdrasil/icmpv6.go +++ b/src/yggdrasil/icmpv6.go @@ -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 diff --git a/src/yggdrasil/router.go b/src/yggdrasil/router.go index e0884ef4..abd51c41 100644 --- a/src/yggdrasil/router.go +++ b/src/yggdrasil/router.go @@ -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: