introduce abstraction for packet i/o

This commit is contained in:
Matthias Radestock committed 2014-08-20 11:18:12 +01:00
1 parent 5b7666a850
commit cb2cdc90cc
4 files changed
+78 -33

No files matched your search

+2 -3
View File
@@ -4,7 +4,6 @@ import (
"bytes"
"code.google.com/p/gopacket"
"code.google.com/p/gopacket/layers"
"code.google.com/p/gopacket/pcap"
"log"
"net"
)
@@ -19,7 +18,7 @@ func (dec *EthernetDecoder) DecodeLayers(data []byte) error {
return dec.parser.DecodeLayers(data, &dec.decoded)
}
func (dec *EthernetDecoder) CheckFrameTooBigFunc(handle *pcap.Handle) func(error) error {
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
@@ -28,7 +27,7 @@ func (dec *EthernetDecoder) CheckFrameTooBigFunc(handle *pcap.Handle) func(error
return err
}
log.Printf("Injecting ICMP 3,4 (%v -> %v): PMTU= %v\n", dec.ip.DstIP, dec.ip.SrcIP, ftbe.PMTU)
return handle.WritePacketData(icmpFrame)
return po.WritePacket(icmpFrame)
} else {
return err
}
+49
View File
@@ -0,0 +1,49 @@
package weave
import (
"code.google.com/p/gopacket/pcap"
)
type PcapIO struct {
handle *pcap.Handle
}
func NewPcapIO(ifName string, bufSz int) (handle *PcapIO, err error) {
inactive, err := pcap.NewInactiveHandle(ifName)
if err != nil {
return
}
defer inactive.CleanUp()
if inactive.SetPromisc(true) != nil {
return
}
if inactive.SetSnapLen(65535) != nil {
return
}
if inactive.SetTimeout(-1) != nil {
return
}
if inactive.SetImmediateMode(true) != nil {
return
}
if inactive.SetBufferSize(bufSz) != nil {
return
}
active, err := inactive.Activate()
if err != nil {
return
}
if active.SetDirection(pcap.DirectionIn) != nil {
return
}
return &PcapIO{handle: active}, nil
}
func (pi *PcapIO) ReadPacket() (data []byte, err error) {
data, _, err = pi.handle.ReadPacketData()
return
}
func (po *PcapIO) WritePacket(data []byte) error {
return po.handle.WritePacketData(data)
}
+14 -30
View File
@@ -3,7 +3,6 @@ package weave
import (
"bytes"
"code.google.com/p/gopacket/layers"
"code.google.com/p/gopacket/pcap"
"encoding/binary"
"fmt"
"io"
@@ -39,12 +38,13 @@ func (router *Router) UsingPassword() bool {
}
func (router *Router) Start() {
handle := router.createPCap(true, 65535, router.BufSz)
pio, err := NewPcapIO(router.Iface.Name, router.BufSz)
checkFatal(err)
router.ConnectionMaker = StartConnectionMaker(router)
router.Topology = StartTopology(router)
router.UDPListener = router.listenUDP(Port, handle)
router.UDPListener = router.listenUDP(Port, pio)
router.listenTCP(Port)
router.sniff(handle)
router.sniff(pio)
}
func (router *Router) Status() string {
@@ -58,19 +58,18 @@ func (router *Router) Status() string {
return buf.String()
}
func (router *Router) sniff(handle *pcap.Handle) {
func (router *Router) sniff(pio PacketSourceSink) {
log.Println("Sniffing traffic on", router.Iface)
dec := NewEthernetDecoder()
checkFrameTooBig := dec.CheckFrameTooBigFunc(handle)
checkFrameTooBig := dec.CheckFrameTooBigFunc(pio)
mac := router.Iface.HardwareAddr
if router.Macs.Enter(mac, router.Ourself) {
log.Println("Discovered our MAC", mac)
}
go func() {
defer handle.Close()
for {
pkt, _, err := handle.ReadPacketData()
pkt, err := pio.ReadPacket()
checkFatal(err)
router.LogFrame("Sniffed", pkt, nil)
checkWarn(router.handleCapturedPacket(pkt, dec, checkFrameTooBig))
@@ -142,7 +141,7 @@ func (router *Router) acceptTCP(tcpConn *net.TCPConn) {
NewLocalConnection(connRemote, UnknownPeerName, tcpConn, nil, router)
}
func (router *Router) listenUDP(localPort int, handle *pcap.Handle) *net.UDPConn {
func (router *Router) listenUDP(localPort int, po PacketSink) *net.UDPConn {
localAddr, err := net.ResolveUDPAddr("udp4", fmt.Sprint(":", localPort))
checkFatal(err)
conn, err := net.ListenUDP("udp4", localAddr)
@@ -154,14 +153,14 @@ func (router *Router) listenUDP(localPort int, handle *pcap.Handle) *net.UDPConn
// This one makes sure all packets we send out do not have DF set on them.
err = syscall.SetsockoptInt(fd, syscall.IPPROTO_IP, syscall.IP_MTU_DISCOVER, syscall.IP_PMTUDISC_DONT)
checkFatal(err)
go router.udpReader(conn, handle)
go router.udpReader(conn, po)
return conn
}
func (router *Router) udpReader(conn *net.UDPConn, handle *pcap.Handle) {
func (router *Router) udpReader(conn *net.UDPConn, po PacketSink) {
defer conn.Close()
dec := NewEthernetDecoder()
handleUDPPacket := router.handleUDPPacketFunc(dec, handle)
handleUDPPacket := router.handleUDPPacketFunc(dec, po)
buf := make([]byte, MaxUDPPacketSize)
for {
n, sender, err := conn.ReadFromUDP(buf)
@@ -193,8 +192,8 @@ func (router *Router) udpReader(conn *net.UDPConn, handle *pcap.Handle) {
}
}
func (router *Router) handleUDPPacketFunc(dec *EthernetDecoder, handle *pcap.Handle) FrameConsumer {
checkFrameTooBig := dec.CheckFrameTooBigFunc(handle)
func (router *Router) handleUDPPacketFunc(dec *EthernetDecoder, po PacketSink) FrameConsumer {
checkFrameTooBig := dec.CheckFrameTooBigFunc(po)
return func(relayConn *LocalConnection, sender *net.UDPAddr, srcNameByte, dstNameByte []byte, frameLen uint16, frame []byte) error {
srcName := PeerNameFromBin(srcNameByte)
@@ -251,7 +250,7 @@ func (router *Router) handleUDPPacketFunc(dec *EthernetDecoder, handle *pcap.Han
log.Println("Discovered remote MAC", srcMac, "at", srcPeer.Name)
}
router.LogFrame("Injecting", frame, &dec.eth)
checkWarn(handle.WritePacketData(frame))
checkWarn(po.WritePacket(frame))
dstPeer, found = router.Macs.Lookup(dec.eth.DstMAC)
if !found || dec.BroadcastFrame() || dstPeer != router.Ourself {
df := decodedLen == 2 && (dec.ip.Flags&layers.IPv4DontFragment != 0)
@@ -260,18 +259,3 @@ func (router *Router) handleUDPPacketFunc(dec *EthernetDecoder, handle *pcap.Han
return nil
}
}
func (router *Router) createPCap(promisc bool, snaplen int, buffSize int) *pcap.Handle {
inactive, err := pcap.NewInactiveHandle(router.Iface.Name)
checkFatal(err)
defer inactive.CleanUp()
checkFatal(inactive.SetPromisc(promisc))
checkFatal(inactive.SetSnapLen(snaplen))
checkFatal(inactive.SetTimeout(-1))
checkFatal(inactive.SetImmediateMode(true))
checkFatal(inactive.SetBufferSize(buffSize))
active, err := inactive.Activate()
checkFatal(err)
checkFatal(active.SetDirection(pcap.DirectionIn))
return active
}
+13
View File
@@ -272,3 +272,16 @@ type NaClDecryptorInstance struct {
highestOffsetSeen uint16
nonceChan chan *[24]byte
}
type PacketSource interface {
ReadPacket() ([]byte, error)
}
type PacketSink interface {
WritePacket([]byte) error
}
type PacketSourceSink interface {
PacketSource
PacketSink
}