mirror of
https://github.com/RoganDawes/P4wnP1_aloa.git
synced 2025-03-17 21:31:56 +01:00
Added bridge interface creation, USB gadget state parsing over RPC, some refinements
This commit is contained in:
parent
3a9ec59b18
commit
93e2d163ed
@ -9,10 +9,12 @@ import (
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
pb "../proto"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func main() {
|
||||
//Parse cli flags, should be replaced with cobra
|
||||
getUsbGadgetConf := flag.Bool("get_gadget_state", false, "Retrieves the current USB gadget state")
|
||||
blinkCountPtr := flag.Int("blink", -1, "LED blink count (0 = LED off, 255 = LED solid, 1..254 blink n times)")
|
||||
var rpcHostPtr string
|
||||
var rpcPortPtr string
|
||||
@ -36,9 +38,19 @@ func main() {
|
||||
defer cancel()
|
||||
|
||||
if *blinkCountPtr >= 0 {
|
||||
c.SetLEDSettings(ctx, &pb.LEDSettings{ BlinkCount: uint32(*blinkCountPtr) })
|
||||
_, err1 := c.SetLEDSettings(ctx, &pb.LEDSettings{BlinkCount: uint32(*blinkCountPtr)})
|
||||
if err1 != nil {
|
||||
log.Printf("Error setting LED blink count %d: %v", *blinkCountPtr, err1)
|
||||
}
|
||||
}
|
||||
|
||||
if *getUsbGadgetConf {
|
||||
r, err := c.GetGadgetSettings(ctx, &pb.Empty{})
|
||||
if err != nil {
|
||||
log.Fatalf("could not get GadgetSettings: %v", err)
|
||||
}
|
||||
log.Printf("USB Settings %s: %+v", reflect.TypeOf(*r), *r)
|
||||
}
|
||||
|
||||
/*
|
||||
r, err := c.GetGadgetSettings(ctx, &pb.Empty{})
|
||||
|
51
core/network.go
Normal file
51
core/network.go
Normal file
@ -0,0 +1,51 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"github.com/docker/libcontainer/netlink"
|
||||
"net"
|
||||
"log"
|
||||
)
|
||||
|
||||
func CreateBridge(name string) error {
|
||||
return netlink.CreateBridge(name, false)
|
||||
}
|
||||
|
||||
func DeleteBridge(name string) error {
|
||||
return netlink.DeleteBridge(name)
|
||||
}
|
||||
|
||||
func CheckInterfaceExistence(name string) (res bool, err error) {
|
||||
_, err = net.InterfaceByName(name)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, err
|
||||
}
|
||||
|
||||
func NetworkLinkUp(name string) (err error) {
|
||||
iface, err := net.InterfaceByName(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = netlink.NetworkLinkUp(iface)
|
||||
return
|
||||
}
|
||||
|
||||
func AddInterfaceToBridgeIfExistent(bridgeName string, ifName string) (err error) {
|
||||
br, err := net.InterfaceByName(bridgeName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
iface, err := net.InterfaceByName(ifName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = netlink.AddToBridge(iface, br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("Interface %s added to bridge %s", ifName, bridgeName)
|
||||
return nil
|
||||
}
|
@ -15,28 +15,18 @@ import (
|
||||
type server struct{}
|
||||
|
||||
//Attach handler function implementing the "GetGadgetSettings" interface to server
|
||||
func (s *server) GetGadgetSettings(context.Context, *pb.Empty) (*pb.GadgetSettings, error) {
|
||||
usbset := &pb.GadgetSettings{
|
||||
Pid: "0x1337",
|
||||
Vid: "0x1222",
|
||||
Manufacturer: "MaMe82",
|
||||
Serial: "deadbeef13371337",
|
||||
Product: "P4wnP1 by MaMe82",
|
||||
Use_RNDIS: false,
|
||||
Use_CDC_ECM: true,
|
||||
Use_HID_KEYBOARD: false,
|
||||
Use_HID_MOUSE: false,
|
||||
Use_HID_RAW: false,
|
||||
Use_UMS: false,
|
||||
Use_SERIAL: false,
|
||||
func (s *server) GetGadgetSettings(context.Context, *pb.Empty) (usbset *pb.GadgetSettings, err error) {
|
||||
usbset, err = ParseGadgetState(USB_GADGET_NAME)
|
||||
|
||||
RndisSettings: &pb.GadgetSettingsEthernet{HostAddr: "11:22:33:44:55:66", DevAddr: "66:55:44:33:22:11"},
|
||||
CdcEcmSettings: &pb.GadgetSettingsEthernet{HostAddr: "11:22:33:54:76:98", DevAddr: "66:55:44:98:76:54"},
|
||||
if err == nil {
|
||||
j_usbset, _ := json.Marshal(usbset)
|
||||
log.Printf("Gadget settings requested %v", string(j_usbset))
|
||||
} else {
|
||||
log.Printf("Error parsing current gadget config: %v", err)
|
||||
}
|
||||
j_usbset, _ := json.Marshal(usbset)
|
||||
log.Printf("Gadget settings requested %v", string(j_usbset))
|
||||
|
||||
return usbset, nil
|
||||
|
||||
return usbset, err
|
||||
}
|
||||
|
||||
//Attach handler function implementing the "SetGadgetSettings" interface to server
|
||||
@ -68,7 +58,7 @@ func (s *server) SetLEDSettings(ctx context.Context, ledSettings *pb.LEDSettings
|
||||
func StartRpcServer(host string, port string) {
|
||||
listen_address := host + ":" + port
|
||||
//Open TCP listener
|
||||
log.Printf("P4wnP1 RPC server lsitening on " + listen_address)
|
||||
log.Printf("P4wnP1 RPC server listening on " + listen_address)
|
||||
lis, err := net.Listen("tcp", listen_address)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to listen: %v", err)
|
||||
|
196
core/usb.go
196
core/usb.go
@ -9,14 +9,16 @@ import (
|
||||
"strings"
|
||||
|
||||
pb "../proto"
|
||||
"time"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const (
|
||||
USB_GADGET_NAME = "mame82_gadget"
|
||||
USB_GADGET_DIR_BASE = "/sys/kernel/config/usb_gadget"
|
||||
USB_GADGET_DIR = USB_GADGET_DIR_BASE + "/mame82_gadget"
|
||||
USB_DEFAULT_SERIAL = "deadbeefdeadbeef"
|
||||
USB_DEFAULT_MANUFACTURER = "MaMe82"
|
||||
USB_DEFAULT_PRODUCT = "P4wnP1 by MaMe82"
|
||||
USB_GADGET_DIR = USB_GADGET_DIR_BASE + "/" + USB_GADGET_NAME
|
||||
|
||||
USB_ETHERNET_BRIDGE_NAME = "usbeth"
|
||||
|
||||
USB_bcdDevice = "0x0100" //Version 1.00
|
||||
USB_bcdUSB = "0x0200" //mode: USB 2.0
|
||||
@ -69,6 +71,47 @@ const (
|
||||
USB_FUNCTION_HID_RAW_name = "hid.raw"
|
||||
)
|
||||
|
||||
func addUSBEthernetBridge() {
|
||||
//Create the bridge
|
||||
CreateBridge(USB_ETHERNET_BRIDGE_NAME)
|
||||
|
||||
//add the interfaces
|
||||
if err := AddInterfaceToBridgeIfExistent(USB_ETHERNET_BRIDGE_NAME, "usb0"); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
if err := AddInterfaceToBridgeIfExistent(USB_ETHERNET_BRIDGE_NAME, "usb1"); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
//enable the bridge
|
||||
NetworkLinkUp(USB_ETHERNET_BRIDGE_NAME)
|
||||
}
|
||||
|
||||
func deleteUSBEthernetBridge() {
|
||||
//we ignore error results
|
||||
DeleteBridge(USB_ETHERNET_BRIDGE_NAME)
|
||||
}
|
||||
|
||||
/*
|
||||
Polls for presence of "usb0" / "usb1" till one of both is active or timeout is reached
|
||||
*/
|
||||
|
||||
func pollForUSBEthrnet(timeout time.Duration) error {
|
||||
for startTime := time.Now(); time.Since(startTime) < timeout; {
|
||||
if present, _ := CheckInterfaceExistence("usb0"); present {
|
||||
return nil
|
||||
}
|
||||
if present, _ := CheckInterfaceExistence("usb1"); present {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Take a breath
|
||||
time.Sleep(100*time.Millisecond)
|
||||
fmt.Print(".")
|
||||
}
|
||||
return errors.New(fmt.Sprintf("Timeout %v reached before usb0 or usb1 cam up"))
|
||||
}
|
||||
|
||||
func InitDefaultGadgetSettings() error {
|
||||
return InitGadget(CreateDefaultGadgetSettings())
|
||||
}
|
||||
@ -123,7 +166,125 @@ func CheckLibComposite() error {
|
||||
return err
|
||||
}
|
||||
|
||||
func ParseGadgetState(gadgetName string) (result *pb.GadgetSettings, err error) {
|
||||
err = nil
|
||||
result = &pb.GadgetSettings{}
|
||||
result.CdcEcmSettings = &pb.GadgetSettingsEthernet{}
|
||||
result.RndisSettings = &pb.GadgetSettingsEthernet{}
|
||||
|
||||
//gadget_root := "./test"
|
||||
gadget_dir := USB_GADGET_DIR_BASE + "/" + gadgetName
|
||||
|
||||
//check if root exists, return error otherwise
|
||||
if _, err = os.Stat(gadget_dir); os.IsNotExist(err) {
|
||||
err = errors.New(fmt.Sprintf("Gadget %s doesn't exist", gadgetName))
|
||||
result = nil
|
||||
return
|
||||
}
|
||||
|
||||
if res, err := ioutil.ReadFile(gadget_dir + "/idVendor"); err != nil {
|
||||
err1 := errors.New(fmt.Sprintf("Gadget %s error reading Vid", gadgetName))
|
||||
return nil, err1
|
||||
} else {
|
||||
result.Vid = strings.TrimSuffix(string(res), "\n")
|
||||
}
|
||||
|
||||
if res, err := ioutil.ReadFile(gadget_dir + "/idProduct"); err != nil {
|
||||
err1 := errors.New(fmt.Sprintf("Gadget %s error reading Pid", gadgetName))
|
||||
return nil, err1
|
||||
} else {
|
||||
result.Pid = strings.TrimSuffix(string(res), "\n")
|
||||
}
|
||||
|
||||
if res, err := ioutil.ReadFile(gadget_dir + "/strings/0x409/serialnumber"); err != nil {
|
||||
err1 := errors.New(fmt.Sprintf("Gadget %s error reading Serial", gadgetName))
|
||||
return nil, err1
|
||||
} else {
|
||||
result.Serial = strings.TrimSuffix(string(res), "\n")
|
||||
}
|
||||
|
||||
if res, err := ioutil.ReadFile(gadget_dir + "/strings/0x409/manufacturer"); err != nil {
|
||||
err1 := errors.New(fmt.Sprintf("Gadget %s error reading Manufacturer", gadgetName))
|
||||
return nil, err1
|
||||
} else {
|
||||
result.Manufacturer = strings.TrimSuffix(string(res), "\n")
|
||||
}
|
||||
|
||||
if res, err := ioutil.ReadFile(gadget_dir + "/strings/0x409/product"); err != nil {
|
||||
err1 := errors.New(fmt.Sprintf("Gadget %s error reading Product", gadgetName))
|
||||
return nil, err1
|
||||
} else {
|
||||
result.Product = strings.TrimSuffix(string(res), "\n")
|
||||
}
|
||||
|
||||
//Check enabled functions in configuration
|
||||
|
||||
//USB RNDIS
|
||||
if _, err1 := os.Stat(gadget_dir+"/configs/c.1/rndis.usb0"); !os.IsNotExist(err1) {
|
||||
result.Use_RNDIS = true
|
||||
|
||||
if res, err := ioutil.ReadFile(gadget_dir + "/functions/rndis.usb0/host_addr"); err != nil {
|
||||
err1 := errors.New(fmt.Sprintf("Gadget %s error reading RNDIS host_addr", gadgetName))
|
||||
return nil, err1
|
||||
} else {
|
||||
result.RndisSettings.HostAddr = strings.TrimSuffix(string(res), "\000\n")
|
||||
}
|
||||
|
||||
if res, err := ioutil.ReadFile(gadget_dir + "/functions/rndis.usb0/dev_addr"); err != nil {
|
||||
err1 := errors.New(fmt.Sprintf("Gadget %s error reading RNDIS dev_addr", gadgetName))
|
||||
return nil, err1
|
||||
} else {
|
||||
result.RndisSettings.DevAddr = strings.TrimSuffix(string(res), "\000\n")
|
||||
}
|
||||
}
|
||||
|
||||
//USB CDC ECM
|
||||
if _, err1 := os.Stat(gadget_dir+"/configs/c.1/ecm.usb1"); !os.IsNotExist(err1) {
|
||||
result.Use_CDC_ECM = true
|
||||
|
||||
if res, err := ioutil.ReadFile(gadget_dir + "/functions/ecm.usb1/host_addr"); err != nil {
|
||||
err1 := errors.New(fmt.Sprintf("Gadget %s error reading CDC ECM host_addr", gadgetName))
|
||||
return nil, err1
|
||||
} else {
|
||||
result.CdcEcmSettings.HostAddr = strings.TrimSuffix(string(res), "\000\n")
|
||||
}
|
||||
|
||||
if res, err := ioutil.ReadFile(gadget_dir + "/functions/ecm.usb1/dev_addr"); err != nil {
|
||||
err1 := errors.New(fmt.Sprintf("Gadget %s error reading CDC ECM dev_addr", gadgetName))
|
||||
return nil, err1
|
||||
} else {
|
||||
result.CdcEcmSettings.DevAddr = strings.TrimSuffix(string(res), "\000\n")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//USB serial
|
||||
if _, err1 := os.Stat(gadget_dir+"/configs/c.1/acm.GS0"); !os.IsNotExist(err1) {
|
||||
result.Use_SERIAL = true
|
||||
}
|
||||
|
||||
//USB HID Keyboard
|
||||
if _, err1 := os.Stat(gadget_dir+"/configs/c.1/"+USB_FUNCTION_HID_KEYBOARD_name); !os.IsNotExist(err1) {
|
||||
result.Use_HID_KEYBOARD = true
|
||||
}
|
||||
|
||||
//USB HID Mouse
|
||||
if _, err1 := os.Stat(gadget_dir+"/configs/c.1/"+USB_FUNCTION_HID_MOUSE_name); !os.IsNotExist(err1) {
|
||||
result.Use_HID_KEYBOARD = true
|
||||
}
|
||||
|
||||
//USB HID RAW
|
||||
if _, err1 := os.Stat(gadget_dir+"/configs/c.1/"+USB_FUNCTION_HID_RAW_name); !os.IsNotExist(err1) {
|
||||
result.Use_HID_RAW = true
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
func InitGadget(settings pb.GadgetSettings) error {
|
||||
var usesUSBEthernet bool
|
||||
|
||||
//gadget_root := "./test"
|
||||
gadget_root := USB_GADGET_DIR_BASE
|
||||
|
||||
@ -136,6 +297,8 @@ func InitGadget(settings pb.GadgetSettings) error {
|
||||
|
||||
//create gadget folder
|
||||
os.Mkdir(USB_GADGET_DIR, os.ModePerm)
|
||||
log.Printf("Creating composite gadget '%s'", USB_GADGET_NAME)
|
||||
|
||||
//set vendor ID, product ID
|
||||
ioutil.WriteFile(USB_GADGET_DIR+"/idVendor", []byte(settings.Vid), os.ModePerm)
|
||||
ioutil.WriteFile(USB_GADGET_DIR+"/idProduct", []byte(settings.Pid), os.ModePerm)
|
||||
@ -163,6 +326,8 @@ func InitGadget(settings pb.GadgetSettings) error {
|
||||
|
||||
// RNDIS has to be the first interface on Composite device for Windows (first function initialized)
|
||||
if settings.Use_RNDIS {
|
||||
log.Printf("... creating USB RNDIS function")
|
||||
usesUSBEthernet = true
|
||||
os.Mkdir(USB_GADGET_DIR+"/functions/rndis.usb0", os.ModePerm) //create RNDIS function
|
||||
ioutil.WriteFile(USB_GADGET_DIR+"/functions/rndis.usb0/host_addr", []byte(settings.RndisSettings.HostAddr), os.ModePerm)
|
||||
ioutil.WriteFile(USB_GADGET_DIR+"/functions/rndis.usb0/dev_addr", []byte(settings.RndisSettings.DevAddr), os.ModePerm)
|
||||
@ -205,6 +370,8 @@ func InitGadget(settings pb.GadgetSettings) error {
|
||||
}
|
||||
|
||||
if settings.Use_CDC_ECM {
|
||||
log.Printf("... creating USB CDC ECM function")
|
||||
usesUSBEthernet = true
|
||||
os.Mkdir(USB_GADGET_DIR+"/functions/ecm.usb1", os.ModePerm) //create CDC ECM function
|
||||
ioutil.WriteFile(USB_GADGET_DIR+"/functions/ecm.usb1/host_addr", []byte(settings.CdcEcmSettings.HostAddr), os.ModePerm)
|
||||
ioutil.WriteFile(USB_GADGET_DIR+"/functions/ecm.usb1/dev_addr", []byte(settings.CdcEcmSettings.DevAddr), os.ModePerm)
|
||||
@ -217,6 +384,7 @@ func InitGadget(settings pb.GadgetSettings) error {
|
||||
}
|
||||
|
||||
if settings.Use_SERIAL {
|
||||
log.Printf("... creating USB serial function")
|
||||
os.Mkdir(USB_GADGET_DIR+"/functions/acm.GS0", os.ModePerm) //create ACM function
|
||||
|
||||
//activate function by symlinking to config 1
|
||||
@ -228,6 +396,7 @@ func InitGadget(settings pb.GadgetSettings) error {
|
||||
}
|
||||
|
||||
if settings.Use_HID_KEYBOARD {
|
||||
log.Printf("... creating USB HID Keyboard function")
|
||||
funcdir := USB_GADGET_DIR + "/functions/" + USB_FUNCTION_HID_KEYBOARD_name
|
||||
os.Mkdir(funcdir, os.ModePerm) //create HID function for keyboard
|
||||
|
||||
@ -243,6 +412,7 @@ func InitGadget(settings pb.GadgetSettings) error {
|
||||
}
|
||||
|
||||
if settings.Use_HID_MOUSE {
|
||||
log.Printf("... creating USB HID Mouse function")
|
||||
funcdir := USB_GADGET_DIR + "/functions/" + USB_FUNCTION_HID_MOUSE_name
|
||||
os.Mkdir(funcdir, os.ModePerm) //create HID function for mouse
|
||||
|
||||
@ -258,6 +428,7 @@ func InitGadget(settings pb.GadgetSettings) error {
|
||||
}
|
||||
|
||||
if settings.Use_HID_RAW {
|
||||
log.Printf("... creating USB HID Generic device function")
|
||||
funcdir := USB_GADGET_DIR + "/functions/" + USB_FUNCTION_HID_RAW_name
|
||||
os.Mkdir(funcdir, os.ModePerm) //create HID function for mouse
|
||||
|
||||
@ -283,6 +454,23 @@ func InitGadget(settings pb.GadgetSettings) error {
|
||||
udc_name := files[0].Name()
|
||||
ioutil.WriteFile(USB_GADGET_DIR+"/UDC", []byte(udc_name), os.ModePerm)
|
||||
|
||||
|
||||
deleteUSBEthernetBridge() //delete former used bridge, if there's any
|
||||
//In case USB ethernet is uesd (RNDIS or CDC ECM), we add a bridge interface
|
||||
if usesUSBEthernet {
|
||||
//wait till "usb0" or "usb1" comes up
|
||||
err = pollForUSBEthrnet(10*time.Second)
|
||||
if err == nil {
|
||||
//add USBEthernet bridge including the usb interfaces
|
||||
log.Printf("... creating network bridge for USB ethernet devices")
|
||||
addUSBEthernetBridge()
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
log.Printf("... done")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
30
dependencies.sh
Executable file
30
dependencies.sh
Executable file
@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
# install dependencies
|
||||
# - dnsmasq for DHCP / DNS server
|
||||
# - bridge-utils for bonding CDC ECM + RNDIS interface toa single bridge
|
||||
# - hostapd for AP deployment
|
||||
# - screen to attach interactive processes to a detachable tty
|
||||
# - autossh for "reachback" SSH connections
|
||||
# - bluez (bluez-bleutooth, policykit-1) for access to Bluetooth / BLE stack (depends on DBUS systemd service)
|
||||
# - haveged as entropy daemon to get enough entropy for hostapd AP with WPA2
|
||||
# - iodine for DNS tunnel capbilities
|
||||
# - genisoimage to allow on-the-fly CD-Rom image creation for CD emulation
|
||||
|
||||
sudo apt-get -y install git screen hostapd autossh bluez bluez-tools bridge-utils policykit-1 genisoimage iodine haveged
|
||||
sudo apt-get -y install tcpdump
|
||||
sudo apt-get -y install python-pip python-dev
|
||||
|
||||
# before installing dnsmasq, the nameserver from /etc/resolv.conf should be saved
|
||||
# to restore after install (gets overwritten by dnsmasq package)
|
||||
cp /etc/resolv.conf /tmp/backup_resolv.conf
|
||||
sudo apt-get -y install dnsmasq
|
||||
sudo /bin/bash -c 'cat /tmp/backup_resolv.conf > /etc/resolv.conf'
|
||||
|
||||
|
||||
|
||||
# python dependencies for HIDbackdoor
|
||||
sudo pip install pycrypto # already present on stretch
|
||||
sudo pip install pydispatcher
|
||||
|
||||
|
@ -7,6 +7,14 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
/*
|
||||
if gadget, err := core.ParseGadgetState(core.USB_GADGET_NAME); err == nil {
|
||||
log.Printf("Gadget config: %+v", gadget)
|
||||
} else {
|
||||
log.Printf("Gadget %s couldn't be parsed: %s", core.USB_GADGET_NAME, err)
|
||||
}
|
||||
*/
|
||||
|
||||
var err error
|
||||
err = core.CheckLibComposite()
|
||||
if err != nil {
|
||||
@ -23,6 +31,7 @@ func main() {
|
||||
log.Fatalf("Error while setting up the default gadget: %v", err)
|
||||
}
|
||||
|
||||
|
||||
core.InitLed(false) //Set LED to manual triger
|
||||
//core.StartRpcServer("127.0.0.1", "50051") //start gRPC service
|
||||
core.StartRpcServer("", "50051") //start gRPC service
|
||||
|
Loading…
x
Reference in New Issue
Block a user