initial commit
This commit is contained in:
commit
e6feefa1fc
26 files changed
+4476
No files matched your search
@@ -0,0 +1,119 @@
|
||||
package weave
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"code.google.com/p/gopacket"
|
||||
"code.google.com/p/gopacket/layers"
|
||||
"code.google.com/p/gopacket/pcap"
|
||||
"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(srcMac net.HardwareAddr, localAddrs []net.Addr, handle *pcap.Handle) func(error) error {
|
||||
networks := make([]LocalAddress, len(localAddrs))
|
||||
idx := 0
|
||||
for _, addr := range localAddrs {
|
||||
ip, ipnet, err := net.ParseCIDR(addr.String())
|
||||
if err == nil && ip.To4() != nil {
|
||||
networks[idx] = LocalAddress{ip: ip.To4(), network: ipnet}
|
||||
idx++
|
||||
}
|
||||
}
|
||||
networks = networks[:idx]
|
||||
if len(networks) == 0 {
|
||||
log.Fatal("Interface has no addresses assigned. Cannot continue")
|
||||
}
|
||||
findIP := func(ip net.IP) net.IP {
|
||||
for _, la := range networks {
|
||||
if la.network.Contains(ip) {
|
||||
return la.ip
|
||||
}
|
||||
}
|
||||
// can't find anything, we'll have to rely on default gateway.
|
||||
return networks[0].ip
|
||||
}
|
||||
|
||||
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
|
||||
srcIP := findIP(dec.ip.SrcIP)
|
||||
icmpFrame, err := dec.formICMPMTUPacket(srcMac, srcIP, ftbe.PMTU)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Println("Injecting ICMP 3,4. PMTU:", ftbe.PMTU)
|
||||
return handle.WritePacketData(icmpFrame)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (dec *EthernetDecoder) formICMPMTUPacket(srcMac net.HardwareAddr, srcIP net.IP, 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: srcMac,
|
||||
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: srcIP},
|
||||
&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)
|
||||
}
|
||||
Reference in new issue
Block a user