Files
weave/ethernet_decoder.go
T

95 lines
2.7 KiB
Go

package weave
import (
"bytes"
"code.google.com/p/gopacket"
"code.google.com/p/gopacket/layers"
"log"
"net"
)
func NewEthernetDecoder() *EthernetDecoder {
dec := &EthernetDecoder{}
dec.parser = gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, &dec.eth, &dec.ip)
return dec
}
func (dec *EthernetDecoder) DecodeLayers(data []byte) error {
return dec.parser.DecodeLayers(data, &dec.decoded)
}
func (dec *EthernetDecoder) CheckFrameTooBigFunc(po PacketSink) func(error) error {
return func(err 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.PMTU)
if err != nil {
return err
}
log.Printf("Injecting ICMP 3,4 (%v -> %v): PMTU= %v\n", dec.ip.DstIP, dec.ip.SrcIP, ftbe.PMTU)
return po.WritePacket(icmpFrame)
} else {
return err
}
}
}
func (dec *EthernetDecoder) formICMPMTUPacket(mtu int) ([]byte, error) {
buf := gopacket.NewSerializeBuffer()
opts := gopacket.SerializeOptions{
FixLengths: true,
ComputeChecksums: true}
ipHeaderSize := int(dec.ip.IHL) * 4 // IHL is the number of 32-byte words in the header
payload := gopacket.Payload(dec.ip.BaseLayer.Contents[:ipHeaderSize+8])
err := gopacket.SerializeLayers(buf, opts,
&layers.Ethernet{
SrcMAC: dec.eth.DstMAC,
DstMAC: dec.eth.SrcMAC,
EthernetType: dec.eth.EthernetType},
&layers.IPv4{
Version: 4,
TOS: dec.ip.TOS,
Id: 0,
Flags: 0,
FragOffset: 0,
TTL: 64,
Protocol: layers.IPProtocolICMPv4,
DstIP: dec.ip.SrcIP,
SrcIP: dec.ip.DstIP},
&layers.ICMPv4{
TypeCode: 0x304,
Id: 0,
Seq: uint16(mtu)},
&payload)
if err == nil {
return buf.Bytes(), nil
} else {
return []byte{}, err
}
}
var (
// see http://en.wikipedia.org/wiki/Multicast_address#Ethernet
broadcastMAC, _ = net.ParseMAC("ff:ff:ff:ff:ff:ff")
zeroMAC, _ = net.ParseMAC("00:00:00:00:00:00")
stpMACPrefix = []byte{0x01, 0x80, 0xC2, 0x00, 0x00}
ipv4MulticastMACPrefix = []byte{0x01, 0x00, 0x5E}
ipv6MulticastMACPrefix = []byte{0x33, 0x33}
)
func (dec *EthernetDecoder) DropFrame() bool {
return bytes.Equal(stpMACPrefix, dec.eth.DstMAC[:len(stpMACPrefix)])
}
func (dec *EthernetDecoder) BroadcastFrame() bool {
return bytes.Equal(broadcastMAC, dec.eth.DstMAC) ||
// treat multicast frames as broadcast
bytes.Equal(ipv4MulticastMACPrefix, dec.eth.DstMAC[:len(ipv4MulticastMACPrefix)]) ||
bytes.Equal(ipv6MulticastMACPrefix, dec.eth.DstMAC[:len(ipv6MulticastMACPrefix)])
}
func (dec *EthernetDecoder) IsPMTUVerify() bool {
return bytes.Equal(zeroMAC, dec.eth.SrcMAC) &&
bytes.Equal(zeroMAC, dec.eth.DstMAC)
}