|
|
|
@ -16,54 +16,77 @@ import (
|
|
|
|
|
"time"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var OldMac net.HardwareAddr
|
|
|
|
|
var NewMac net.HardwareAddr
|
|
|
|
|
var OldMAC net.HardwareAddr
|
|
|
|
|
var NewMAC net.HardwareAddr
|
|
|
|
|
var OldIP net.IP
|
|
|
|
|
var NewIP net.IP
|
|
|
|
|
var VmReader io.Reader
|
|
|
|
|
var VmWriter io.Writer
|
|
|
|
|
var NetReader io.Reader
|
|
|
|
|
var NetWriter io.Writer
|
|
|
|
|
var Passthrough bool
|
|
|
|
|
|
|
|
|
|
// Start the two plugs and run two concurrent forward methods
|
|
|
|
|
func main() {
|
|
|
|
|
// Get command line arguments
|
|
|
|
|
logLvl := flag.Int("log", 4, "allowed: 5 (debug), 4 (info), 3 (warning), 2 (error), 1 (fatal)")
|
|
|
|
|
oldip := flag.String("oldip", "", "IP before change")
|
|
|
|
|
newip := flag.String("newip", "10.0.0.15", "IP after change")
|
|
|
|
|
oldmac := flag.String("oldmac", "", "MAC before change")
|
|
|
|
|
newmac := flag.String("newmac", "", "MAC after change")
|
|
|
|
|
oldIP := flag.String("oldip", "", "IP before change")
|
|
|
|
|
newIP := flag.String("newip", "10.0.0.15", "IP after change")
|
|
|
|
|
oldMAC := flag.String("oldmac", "", "MAC before change")
|
|
|
|
|
newMAC := flag.String("newmac", "", "MAC after change")
|
|
|
|
|
passthrough := flag.Bool("passthrough", false, "Whether to pass every traffic through")
|
|
|
|
|
proxy := flag.String("proxy", "1", "Number of the proxy switch")
|
|
|
|
|
pidfile := flag.String("pidfile", "", "Location to write the pid to")
|
|
|
|
|
logfile := flag.String("logfile", "", "Location to write output to")
|
|
|
|
|
sockMain := flag.String("smain", "/run/vde/sw_main.sock", "Main switch sock path, - for stdin/out")
|
|
|
|
|
sockProxy := flag.String("sproxy", "/run/vde/sw_proxy1.sock", "Proxy switch sock path")
|
|
|
|
|
pidFile := flag.String("pidfile", "", "Location to write the pid to")
|
|
|
|
|
logFile := flag.String("logfile", "", "Location to write output to")
|
|
|
|
|
flag.Parse()
|
|
|
|
|
log.SetLevel(log.Level(*logLvl))
|
|
|
|
|
OldMac, _ = net.ParseMAC(*oldmac)
|
|
|
|
|
NewMac = util.GenerateMac(*newmac)
|
|
|
|
|
OldIP = net.ParseIP(*oldip).To4()
|
|
|
|
|
NewIP = net.ParseIP(*newip).To4()
|
|
|
|
|
OldMAC, _ = net.ParseMAC(*oldMAC)
|
|
|
|
|
NewMAC = util.GenerateMac(*newMAC)
|
|
|
|
|
OldIP = net.ParseIP(*oldIP).To4()
|
|
|
|
|
NewIP = net.ParseIP(*newIP).To4()
|
|
|
|
|
Passthrough = *passthrough
|
|
|
|
|
log.SetFormatter(&log.TextFormatter{
|
|
|
|
|
DisableTimestamp: true,
|
|
|
|
|
})
|
|
|
|
|
if *logfile != "" {
|
|
|
|
|
if f, err := os.OpenFile(*logfile, os.O_WRONLY | os.O_CREATE, 0755); err != nil {
|
|
|
|
|
log.Error("Error opening logfile ", *logfile)
|
|
|
|
|
if *logFile != "" {
|
|
|
|
|
if f, err := os.OpenFile(*logFile, os.O_WRONLY | os.O_CREATE, 0755); err != nil {
|
|
|
|
|
log.Error("Error opening logFile ", *logFile)
|
|
|
|
|
} else {
|
|
|
|
|
log.SetOutput(f)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
util.WritePIDFile(*pidfile)
|
|
|
|
|
c1 := cmd.New("vde_plug", "/run/vde/sw_main.sock")
|
|
|
|
|
c2 := cmd.New("vde_plug", "/run/vde/sw_proxy"+*proxy+".sock")
|
|
|
|
|
c1.Execute()
|
|
|
|
|
c2.Execute()
|
|
|
|
|
go pipeForward(c1.OutReader, c2.InWriter, cmd.In, *passthrough)
|
|
|
|
|
go pipeForward(c2.OutReader, c1.InWriter, cmd.Out, *passthrough)
|
|
|
|
|
c1.WaitH()
|
|
|
|
|
util.WritePIDFile(*pidFile)
|
|
|
|
|
var c1, c2 *cmd.Cmd
|
|
|
|
|
if *sockMain != "-" {
|
|
|
|
|
c1, NetReader, NetWriter = cmd.Start(*sockMain)
|
|
|
|
|
} else {
|
|
|
|
|
NetReader = os.Stdout
|
|
|
|
|
NetWriter = os.Stdin
|
|
|
|
|
}
|
|
|
|
|
c2, VmReader, VmWriter = cmd.Start(*sockProxy)
|
|
|
|
|
go pipeForward(cmd.In)
|
|
|
|
|
go pipeForward(cmd.Out)
|
|
|
|
|
if *sockMain != "-" {
|
|
|
|
|
c1.WaitH()
|
|
|
|
|
}
|
|
|
|
|
c2.WaitH()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reads from an input and writes to and output,
|
|
|
|
|
// do things to the content in between.
|
|
|
|
|
// Is meant to be run concurrently with "go pipeForward(...)"
|
|
|
|
|
func pipeForward(reader io.Reader, writer io.Writer, prefix string, passthrough bool) {
|
|
|
|
|
func pipeForward(prefix string) {
|
|
|
|
|
var reader io.Reader
|
|
|
|
|
var writer io.Writer
|
|
|
|
|
if prefix == cmd.In {
|
|
|
|
|
reader = NetReader
|
|
|
|
|
writer = VmWriter
|
|
|
|
|
} else {
|
|
|
|
|
reader = VmReader
|
|
|
|
|
writer = NetWriter
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for {
|
|
|
|
|
// Read frame length
|
|
|
|
|
frameLength := make([]byte, 2)
|
|
|
|
@ -99,7 +122,7 @@ func pipeForward(reader io.Reader, writer io.Writer, prefix string, passthrough
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handle DHCP packet (based on IPv4) - drop for now
|
|
|
|
|
if dhcpLayer := packet.Layer(layers.LayerTypeDHCPv4); dhcpLayer != nil && !passthrough {
|
|
|
|
|
if dhcpLayer := packet.Layer(layers.LayerTypeDHCPv4); dhcpLayer != nil && !Passthrough {
|
|
|
|
|
//dhcpPacket, _ := dhcpLayer.(*layers.DHCPv4)
|
|
|
|
|
log.Info(prefix, "DHCP packet dropped")
|
|
|
|
|
continue
|
|
|
|
@ -115,7 +138,7 @@ func pipeForward(reader io.Reader, writer io.Writer, prefix string, passthrough
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Drop IPv6 packets
|
|
|
|
|
if ipv6layer := packet.Layer(layers.LayerTypeIPv6); ipv6layer != nil && !passthrough {
|
|
|
|
|
if ipv6layer := packet.Layer(layers.LayerTypeIPv6); ipv6layer != nil && !Passthrough {
|
|
|
|
|
log.Info(prefix, "IPv6 packet dropped")
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
@ -131,7 +154,7 @@ func pipeForward(reader io.Reader, writer io.Writer, prefix string, passthrough
|
|
|
|
|
log.Debug("End packet")
|
|
|
|
|
|
|
|
|
|
// Forward original frame to other plug
|
|
|
|
|
if passthrough {
|
|
|
|
|
if Passthrough {
|
|
|
|
|
writer.Write(frameLength)
|
|
|
|
|
writer.Write(frameBytes)
|
|
|
|
|
continue
|
|
|
|
@ -208,14 +231,14 @@ func filterIP(prefix string, dst interface{}, src interface{}, context gopacket.
|
|
|
|
|
|
|
|
|
|
// filterMAC checks whether a MAC target selected from src and dst equals a given value. If yes, it is changed
|
|
|
|
|
func filterMAC(prefix string, dst interface{}, src interface{}, context gopacket.LayerType) {
|
|
|
|
|
// If no OldMac is set yet, get it from outgoing src field
|
|
|
|
|
// If no OldMAC is set yet, get it from outgoing src field
|
|
|
|
|
// Has to be HardwareAddr because this is used for ethernet frames which call this method first
|
|
|
|
|
if OldMac == nil {
|
|
|
|
|
if OldMAC == nil {
|
|
|
|
|
if prefix == cmd.In {
|
|
|
|
|
return
|
|
|
|
|
} else if prefix == cmd.Out {
|
|
|
|
|
OldMac = *src.(*net.HardwareAddr)
|
|
|
|
|
log.Info("OldMac set to ", OldMac)
|
|
|
|
|
OldMAC = *src.(*net.HardwareAddr)
|
|
|
|
|
log.Info("OldMAC set to ", OldMAC)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -226,13 +249,13 @@ func filterMAC(prefix string, dst interface{}, src interface{}, context gopacket
|
|
|
|
|
if prefix == cmd.In {
|
|
|
|
|
target = dst
|
|
|
|
|
which = "dst"
|
|
|
|
|
condVal = NewMac
|
|
|
|
|
newVal = OldMac
|
|
|
|
|
condVal = NewMAC
|
|
|
|
|
newVal = OldMAC
|
|
|
|
|
} else if prefix == cmd.Out {
|
|
|
|
|
target = src
|
|
|
|
|
which = "src"
|
|
|
|
|
condVal = OldMac
|
|
|
|
|
newVal = NewMac
|
|
|
|
|
condVal = OldMAC
|
|
|
|
|
newVal = NewMAC
|
|
|
|
|
}
|
|
|
|
|
mac, isMac := target.(*net.HardwareAddr)
|
|
|
|
|
bs, isBs := target.(*[]byte)
|
|
|
|
|