EtherGuard-VPN/tap/tap_stdio.go

139 lines
3.4 KiB
Go

package tap
import (
"fmt"
"os"
"github.com/KusakabeSi/EtherGuardVPN/config"
)
type L2MODE uint8
const (
NoChange L2MODE = iota
KeyboardDebug //Register to server
BoardcastAndNodeID
)
func GetL2Mode(mode string) L2MODE {
switch mode {
case "nochg":
return NoChange
case "kbdbg":
return KeyboardDebug
case "noL2":
return BoardcastAndNodeID
}
return NoChange
}
type StdIOTap struct {
name string
mtu int
macaddr MacAddress
L2mode L2MODE
events chan Event
}
func Charform2mac(b byte) MacAddress {
if b == 'b' {
return MacAddress{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
}
return MacAddress{0xaa, 0xbb, 0xcc, 0xdd, 0xee, b - 48}
}
func Mac2charForm(m []byte) byte {
var M MacAddress
copy(M[:], m)
if IsNotUnicast(M) {
return 'b'
}
return m[5] + 48
}
// New creates and returns a new TUN interface for the application.
func CreateStdIOTAP(iconfig config.InterfaceConf, NodeID config.Vertex) (tapdev Device, err error) {
// Setup TUN Config
if err != nil {
fmt.Println(err.Error())
}
macaddr, err := GetMacAddr(iconfig.MacAddrPrefix, uint32(NodeID))
if err != nil {
fmt.Println("ERROR: Failed parse mac address:", iconfig.MacAddrPrefix)
return nil, err
}
tapdev = &StdIOTap{
name: iconfig.Name,
mtu: 1500,
macaddr: macaddr,
L2mode: GetL2Mode(iconfig.L2HeaderMode),
events: make(chan Event, 1<<5),
}
tapdev.Events() <- EventUp
return
}
// SetMTU sets the Maximum Tansmission Unit Size for a
// Packet on the interface.
func (tap *StdIOTap) Read(buf []byte, offset int) (int, error) {
switch tap.L2mode {
case KeyboardDebug:
size, err := os.Stdin.Read(buf[offset+10:])
packet := buf[offset:]
src := Charform2mac(packet[11])
dst := Charform2mac(packet[10])
copy(packet[0:6], dst[:])
copy(packet[6:12], src[:])
return size - 2 + 12, err
case BoardcastAndNodeID:
size, err := os.Stdin.Read(buf[offset+12:])
packet := buf[offset:]
src := tap.macaddr
dst := Charform2mac('b')
copy(packet[0:6], dst[:])
copy(packet[6:12], src[:])
return size + 12, err
default:
size, err := os.Stdin.Read(buf[offset:])
return size, err
}
} // read a packet from the device (without any additional headers)
func (tap *StdIOTap) Write(buf []byte, offset int) (size int, err error) {
packet := buf[offset:]
switch tap.L2mode {
case KeyboardDebug:
src := Mac2charForm(packet[6:12])
dst := Mac2charForm(packet[0:6])
packet[10] = dst
packet[11] = src
size, err = os.Stdout.Write(packet[10:])
return
case BoardcastAndNodeID:
size, err = os.Stdout.Write(packet[12:])
return
default:
size, err = os.Stdout.Write(packet)
return
}
} // writes a packet to the device (without any additional headers)
func (tap *StdIOTap) Flush() error {
return nil
} // flush all previous writes to the device
func (tap *StdIOTap) MTU() (int, error) {
return tap.mtu, nil
} // returns the MTU of the device
func (tap *StdIOTap) Name() (string, error) {
return tap.name, nil
} // fetches and returns the current name
func (tap *StdIOTap) Events() chan Event {
return tap.events
} // returns a constant channel of events related to the device
func (tap *StdIOTap) Close() error {
tap.events <- EventDown
os.Stdin.Close()
os.Stdin.WriteString("end\n")
close(tap.events)
panic("No solution for this issue: https://stackoverflow.com/questions/44270803/is-there-a-good-way-to-cancel-a-blocking-read , I'm panic!")
} // stops the device and closes the event channel