diff --git a/router/crypto.go b/router/crypto.go index 1f1b9b10..9da2d05d 100644 --- a/router/crypto.go +++ b/router/crypto.go @@ -245,7 +245,7 @@ func (ne *NaClEncryptor) TotalLen() int { // Frame Decryptors -type FrameConsumer func(*LocalConnection, *net.UDPAddr, []byte, []byte, uint16, []byte) error +type FrameConsumer func(*LocalConnection, *net.UDPAddr, []byte, []byte, uint16, []byte) type Decryptor interface { IterateFrames(FrameConsumer, *UDPPacket) error @@ -281,7 +281,7 @@ func NewNonDecryptor(conn *LocalConnection) *NonDecryptor { return &NonDecryptor{conn: conn} } -func (nd *NonDecryptor) IterateFrames(fun FrameConsumer, packet *UDPPacket) error { +func (nd *NonDecryptor) IterateFrames(consumer FrameConsumer, packet *UDPPacket) error { buf := packet.Packet for len(buf) >= (2 + NameSize + NameSize) { srcNameByte := buf[:NameSize] @@ -295,10 +295,7 @@ func (nd *NonDecryptor) IterateFrames(fun FrameConsumer, packet *UDPPacket) erro } frame := buf[:length] buf = buf[length:] - err := fun(nd.conn, packet.Sender, srcNameByte, dstNameByte, length, frame) - if err != nil { - return err - } + consumer(nd.conn, packet.Sender, srcNameByte, dstNameByte, length, frame) } if len(buf) > 0 { return PacketDecodingError{Desc: fmt.Sprintf("%d octets of trailing garbage", len(buf))} @@ -348,13 +345,13 @@ func (nd *NaClDecryptor) ReceiveNonce(msg []byte) { } } -func (nd *NaClDecryptor) IterateFrames(fun FrameConsumer, packet *UDPPacket) error { +func (nd *NaClDecryptor) IterateFrames(consumer FrameConsumer, packet *UDPPacket) error { buf, err := nd.decrypt(packet.Packet) if err != nil { return PacketDecodingError{Fatal: true, Desc: fmt.Sprint("decryption failed; ", err)} } packet.Packet = buf - return nd.NonDecryptor.IterateFrames(fun, packet) + return nd.NonDecryptor.IterateFrames(consumer, packet) } func (nd *NaClDecryptor) decrypt(buf []byte) ([]byte, error) { diff --git a/router/ethernet_decoder.go b/router/ethernet_decoder.go index 46c7af4f..6588c0ad 100644 --- a/router/ethernet_decoder.go +++ b/router/ethernet_decoder.go @@ -25,21 +25,7 @@ func (dec *EthernetDecoder) DecodeLayers(data []byte) error { return dec.parser.DecodeLayers(data, &dec.decoded) } -func (dec *EthernetDecoder) CheckFrameTooBig(err error, sendFrame func([]byte) error) error { - if ftbe, ok := err.(FrameTooBigError); ok { - // we know: 1. ip is valid, 2. it was ip and DF was set - icmpFrame, err := dec.formICMPMTUPacket(ftbe.EPMTU) - if err != nil { - return err - } - log.Printf("Sending ICMP 3,4 (%v -> %v): PMTU= %v\n", dec.ip.DstIP, dec.ip.SrcIP, ftbe.EPMTU) - return sendFrame(icmpFrame) - } else { - return err - } -} - -func (dec *EthernetDecoder) formICMPMTUPacket(mtu int) ([]byte, error) { +func (dec *EthernetDecoder) sendICMPFragNeeded(mtu int, sendFrame func([]byte) error) error { buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ FixLengths: true, @@ -67,9 +53,11 @@ func (dec *EthernetDecoder) formICMPMTUPacket(mtu int) ([]byte, error) { Seq: uint16(mtu)}, &payload) if err != nil { - return []byte{}, err + return err } - return buf.Bytes(), nil + + log.Printf("Sending ICMP 3,4 (%v -> %v): PMTU= %v\n", dec.ip.DstIP, dec.ip.SrcIP, mtu) + return sendFrame(buf.Bytes()) } var ( diff --git a/router/router.go b/router/router.go index 8eaa34e4..80b87512 100644 --- a/router/router.go +++ b/router/router.go @@ -105,8 +105,6 @@ func (router *Router) sniff(pio PacketSourceSink) { log.Println("Sniffing traffic on", router.Iface) dec := NewEthernetDecoder() - injectFrame := func(frame []byte) error { return pio.WritePacket(frame) } - checkFrameTooBig := func(err error) error { return dec.CheckFrameTooBig(err, injectFrame) } mac := router.Iface.HardwareAddr if router.Macs.Enter(mac, router.Ourself.Peer) { log.Println("Discovered our MAC", mac) @@ -116,12 +114,12 @@ func (router *Router) sniff(pio PacketSourceSink) { pkt, err := pio.ReadPacket() checkFatal(err) router.LogFrame("Sniffed", pkt, nil) - checkWarn(router.handleCapturedPacket(pkt, dec, checkFrameTooBig)) + checkWarn(router.handleCapturedPacket(pkt, dec, pio)) } }() } -func (router *Router) handleCapturedPacket(frameData []byte, dec *EthernetDecoder, checkFrameTooBig func(error) error) error { +func (router *Router) handleCapturedPacket(frameData []byte, dec *EthernetDecoder, po PacketSink) error { dec.DecodeLayers(frameData) decodedLen := len(dec.decoded) if decodedLen == 0 { @@ -163,7 +161,11 @@ func (router *Router) handleCapturedPacket(frameData []byte, dec *EthernetDecode router.Ourself.Broadcast(df, frameCopy, dec) return nil } else { - return checkFrameTooBig(router.Ourself.Forward(dstPeer, df, frameCopy, dec)) + err := router.Ourself.Forward(dstPeer, df, frameCopy, dec) + if ftbe, ok := err.(FrameTooBigError); ok { + err = dec.sendICMPFragNeeded(ftbe.EPMTU, po.WritePacket) + } + return err } } @@ -267,32 +269,22 @@ func (router *Router) udpReader(conn *net.UDPConn, po PacketSink) { } func (router *Router) handleUDPPacketFunc(dec *EthernetDecoder, po PacketSink) FrameConsumer { - checkFrameTooBig := func(err error, srcPeer *Peer) error { - if err == nil { // optimisation: avoid closure creation in common case - return nil - } - return dec.CheckFrameTooBig(err, - func(icmpFrame []byte) error { - return router.Ourself.Forward(srcPeer, false, icmpFrame, nil) - }) - } - - return func(relayConn *LocalConnection, sender *net.UDPAddr, srcNameByte, dstNameByte []byte, frameLen uint16, frame []byte) error { + return func(relayConn *LocalConnection, sender *net.UDPAddr, srcNameByte, dstNameByte []byte, frameLen uint16, frame []byte) { srcName := PeerNameFromBin(srcNameByte) dstName := PeerNameFromBin(dstNameByte) srcPeer, found := router.Peers.Fetch(srcName) if !found { - return nil + return } dstPeer, found := router.Peers.Fetch(dstName) if !found { - return nil + return } dec.DecodeLayers(frame) decodedLen := len(dec.decoded) if decodedLen == 0 { - return nil + return } // Handle special frames produced internally (rather than // captured/forwarded) by the remote router. @@ -306,7 +298,7 @@ func (router *Router) handleUDPPacketFunc(dec *EthernetDecoder, po PacketSink) F if srcPeer != relayConn.Remote() || dstPeer != router.Ourself.Peer { // A special frame not originating from the remote, or // not for us? How odd; let's just drop it. - return nil + return } switch { case frameLen == EthernetOverhead+8: @@ -319,7 +311,7 @@ func (router *Router) handleUDPPacketFunc(dec *EthernetDecoder, po PacketSink) F binary.BigEndian.PutUint16(frameLenBytes, uint16(frameLen-EthernetOverhead)) relayConn.SendProtocolMsg(ProtocolMsg{ProtocolPMTUVerified, frameLenBytes}) } - return nil + return } df := decodedLen == 2 && (dec.ip.Flags&layers.IPv4DontFragment != 0) @@ -331,7 +323,16 @@ func (router *Router) handleUDPPacketFunc(dec *EthernetDecoder, po PacketSink) F } else { router.LogFrame("Relaying", frame, &dec.eth) } - return checkFrameTooBig(router.Ourself.Relay(srcPeer, dstPeer, df, frame, dec), srcPeer) + + err := router.Ourself.Relay(srcPeer, dstPeer, df, frame, dec) + if ftbe, ok := err.(FrameTooBigError); ok { + err = dec.sendICMPFragNeeded(ftbe.EPMTU, func(icmpFrame []byte) error { + return router.Ourself.Forward(srcPeer, false, icmpFrame, nil) + }) + } + + checkWarn(err) + return } srcMac := dec.eth.SrcMAC @@ -348,8 +349,6 @@ func (router *Router) handleUDPPacketFunc(dec *EthernetDecoder, po PacketSink) F router.LogFrame("Relaying broadcast", frame, &dec.eth) router.Ourself.RelayBroadcast(srcPeer, df, frame, dec) } - - return nil } }