introduce abstraction for packet i/o
This commit is contained in:
1 parent
5b7666a850
commit
cb2cdc90cc
4 files changed
+78
-33
No files matched your search
+2
-3
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Reference in new issue
Block a user