mirror of
https://github.com/RoganDawes/P4wnP1_aloa.git
synced 2025-03-17 21:31:56 +01:00
CLI client supports setting up DHCP server or client on an interface
This commit is contained in:
parent
604e7d7073
commit
c3771a5069
@ -7,6 +7,9 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"google.golang.org/grpc/status"
|
||||
"../service"
|
||||
"strings"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
//Empty settings used to store cobra flags
|
||||
@ -16,6 +19,9 @@ var (
|
||||
tmpStrAddress4 string = ""
|
||||
tmpStrNetmask4 string = ""
|
||||
tmpDisabled bool = false
|
||||
tmpDHCPSrvOptions []string = []string{}
|
||||
tmpDHCPSrvRanges []string = []string{}
|
||||
|
||||
)
|
||||
|
||||
/*
|
||||
@ -78,7 +84,7 @@ func cobraNetSetManual(cmd *cobra.Command, args []string) {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("Deployin ethernet inteface settings:\n\t%v\n", settings)
|
||||
fmt.Printf("Deploying ethernet inteface settings:\n\t%v\n", settings)
|
||||
|
||||
err = ClientDeployEthernetInterfaceSettings(StrRemoteHost, StrRemotePort, settings)
|
||||
if err != nil {
|
||||
@ -88,11 +94,37 @@ func cobraNetSetManual(cmd *cobra.Command, args []string) {
|
||||
}
|
||||
|
||||
func cobraNetSetDHCPClient(cmd *cobra.Command, args []string) {
|
||||
settings, err := createDHCPClientSettings(tmpStrInterface, tmpDisabled)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("Deploying ethernet inteface settings:\n\t%v\n", settings)
|
||||
|
||||
err = ClientDeployEthernetInterfaceSettings(StrRemoteHost, StrRemotePort, settings)
|
||||
if err != nil {
|
||||
fmt.Println(status.Convert(err).Message())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func cobraNetSetDHCPServer(cmd *cobra.Command, args []string) {
|
||||
settings, err := createDHCPServerSettings(tmpStrInterface, tmpStrAddress4, tmpStrNetmask4, tmpDisabled, tmpDHCPSrvRanges, tmpDHCPSrvOptions)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("Deploying ethernet inteface settings:\n\t%v\n", settings)
|
||||
|
||||
err = ClientDeployEthernetInterfaceSettings(StrRemoteHost, StrRemotePort, settings)
|
||||
if err != nil {
|
||||
fmt.Println(status.Convert(err).Message())
|
||||
}
|
||||
return
|
||||
|
||||
|
||||
}
|
||||
|
||||
func createManualSettings(iface string, ip4 string, mask4 string, disabled bool) (settings *pb.EthernetInterfaceSettings, err error) {
|
||||
@ -113,6 +145,112 @@ func createManualSettings(iface string, ip4 string, mask4 string, disabled bool)
|
||||
return
|
||||
}
|
||||
|
||||
func parseDhcpServerOptions(strOptions []string) (options map[uint32]string, err error) {
|
||||
options = map[uint32]string{}
|
||||
for _, strOpt := range strOptions {
|
||||
splOpt := strings.SplitN(strOpt,":", 2)
|
||||
if len(splOpt) == 0 {
|
||||
return nil,errors.New(fmt.Sprintf("Invalid DHCP option: %s\nOption format is \"<DHCPOptionNumber>:[DHCPOptionValue]\"", strOpt))
|
||||
}
|
||||
optNum, err := strconv.Atoi(splOpt[0])
|
||||
if err != nil || optNum < 0 {
|
||||
return nil,errors.New(fmt.Sprintf("Invalid DHCP option Number: %s\nOption format is \"<DHCPOptionNumber>:[DHCPOptionValue]\"", splOpt[0]))
|
||||
}
|
||||
uOptNum := uint32(optNum)
|
||||
if len(splOpt) == 1 {
|
||||
options[uOptNum] = ""
|
||||
// fmt.Printf("Setting DHCP server option %d to empty value (disabeling option %d)\n", uOptNum, uOptNum)
|
||||
} else {
|
||||
//Replace '|' with ',' (a comma couldn't be used as it'd be interpreted as slice delimiter)
|
||||
strOptNew := strings.Replace(splOpt[1], "|", ",",-1)
|
||||
|
||||
options[uOptNum] = strOptNew
|
||||
// fmt.Printf("Setting DHCP server option %d to '%s'\n", uOptNum, splOpt[1])
|
||||
}
|
||||
}
|
||||
|
||||
return options,nil
|
||||
}
|
||||
|
||||
func parseDhcpServerRanges(strRanges []string) (ranges []*pb.DHCPServerRange, err error) {
|
||||
ranges = []*pb.DHCPServerRange{}
|
||||
for _,strRange := range strRanges {
|
||||
splRange := strings.Split(strRange, "|")
|
||||
if len(splRange) != 3 && len(splRange) != 2 {
|
||||
return nil,errors.New(fmt.Sprintf("Invalid DHCP range: %s\nOption format is \"<first IPv4>|<last IPv4>[|leaseTime]\"", strRange))
|
||||
}
|
||||
|
||||
if net.ParseIP(splRange[0]) == nil {
|
||||
return nil, errors.New(fmt.Sprintf("%s in range '%s' is no valid IP address", splRange[0], strRange))
|
||||
}
|
||||
if net.ParseIP(splRange[1]) == nil {
|
||||
return nil, errors.New(fmt.Sprintf("%s in range '%s' is no valid IP address", splRange[1], strRange))
|
||||
}
|
||||
pRange := &pb.DHCPServerRange{
|
||||
RangeLower: splRange[0],
|
||||
RangeUpper: splRange[1],
|
||||
}
|
||||
if len(splRange) > 2 {
|
||||
//ToDo: Regex check lease time to be valid [0-9]+[mh]
|
||||
pRange.LeaseTime = splRange[2]
|
||||
}
|
||||
|
||||
ranges = append(ranges, pRange)
|
||||
}
|
||||
return ranges,nil
|
||||
}
|
||||
|
||||
|
||||
func createDHCPServerSettings(iface string, ip4 string, mask4 string, disabled bool, strRanges []string, strOptions []string) (settings *pb.EthernetInterfaceSettings, err error) {
|
||||
if len(iface) == 0 { return nil,errors.New("Please provide a network interface name") }
|
||||
err = checkIPv4(ip4)
|
||||
if err != nil { return nil,errors.New("Please provide a valid IPv4 address for the interface") }
|
||||
err = checkIPv4(mask4)
|
||||
if err != nil { return nil,errors.New("Please provide a valid IPv4 netmask for the interface") }
|
||||
|
||||
|
||||
options, err := parseDhcpServerOptions(strOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ranges, err := parseDhcpServerRanges(strRanges)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
settings = &pb.EthernetInterfaceSettings {
|
||||
Mode: pb.EthernetInterfaceSettings_DHCP_SERVER,
|
||||
Name: iface,
|
||||
IpAddress4: ip4,
|
||||
Netmask4: mask4,
|
||||
Enabled: !disabled,
|
||||
DhcpServerSettings: &pb.DHCPServerSettings{
|
||||
ListenInterface:iface,
|
||||
LeaseFile: service.NameLeaseFileDHCPSrv(iface),
|
||||
CallbackScript: "",
|
||||
ListenPort: 0, //Disable DNS
|
||||
DoNotBindInterface: false, //only listen on given interface
|
||||
NotAuthoritative: false, // be authoritative
|
||||
Ranges: ranges,
|
||||
Options: options,
|
||||
},
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func createDHCPClientSettings(iface string, disabled bool) (settings *pb.EthernetInterfaceSettings, err error) {
|
||||
if len(iface) == 0 { return nil,errors.New("Please provide a network interface name") }
|
||||
|
||||
settings = &pb.EthernetInterfaceSettings {
|
||||
Mode: pb.EthernetInterfaceSettings_DHCP_CLIENT,
|
||||
Name: iface,
|
||||
Enabled: !disabled,
|
||||
DhcpServerSettings: nil,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func checkIPv4(ip4 string) error {
|
||||
ip := net.ParseIP(ip4)
|
||||
if ip == nil {
|
||||
@ -139,4 +277,6 @@ func init() {
|
||||
netSetManualCmd.Flags().StringVarP(&tmpStrNetmask4, "netmask","m", "", "The IPv4 netmask to use for the interface")
|
||||
netSetDHCPServerCmd.Flags().StringVarP(&tmpStrAddress4, "address","a", "", "The IPv4 address to use for the interface")
|
||||
netSetDHCPServerCmd.Flags().StringVarP(&tmpStrNetmask4, "netmask","m", "", "The IPv4 netmask to use for the interface")
|
||||
netSetDHCPServerCmd.Flags().StringSliceVarP(&tmpDHCPSrvRanges, "range", "r",[]string{""}, "A DHCP Server range in form \"<lowest IPv4>|<highest IPv4>[|lease time]\" (the flag could be used multiple times)")
|
||||
netSetDHCPServerCmd.Flags().StringSliceVarP(&tmpDHCPSrvOptions, "option", "o",[]string{""}, "A DHCP Server option in form \"<option number>:<value1|value2>\" (Option values have to be separated by '|' not by ','. The flag could be used multiple times)")
|
||||
}
|
||||
|
@ -128,6 +128,7 @@ func ClientSetLED(host string, port string, ls pb.LEDSettings) (err error) {
|
||||
}
|
||||
|
||||
func ClientDeployEthernetInterfaceSettings(host string, port string, settings *pb.EthernetInterfaceSettings) (err error) {
|
||||
//ToDo: set longer context deadline
|
||||
conn, client, ctx, cancel, err := ClientConnectServer(host, port)
|
||||
defer conn.Close()
|
||||
defer cancel()
|
||||
|
23
examples.sh
Normal file
23
examples.sh
Normal file
@ -0,0 +1,23 @@
|
||||
# Update USB gadget configuration (enable RNDIS, disable CDC ECM, enable HID Keyboard)
|
||||
P4wnP1_cli USB set -r1 -e0 -k1
|
||||
|
||||
# Set new network configuration for "usbeth" (the interface is present when USB RNDIS, CDC ECM or both are enabled)
|
||||
# - "server" means a DHCP server is started for the interface "usbeth"
|
||||
# - set the address of the interface to 172.16.0.1 (-a flag)
|
||||
# - set the netmask of the interface to 255.255.255.252 (-m flag)
|
||||
# - add a range 127.16.0.2 to 172.16.0.2 to the DHCP server with leastime 3 minutes (-r flag, could be used multiple times to add more ranges)
|
||||
# - add option 3 (ROUTER) to the DHCP server, but don't provide a value to disable sending a gateway entry (-o flag)
|
||||
# - add option 6 (NAMESERVER) to the DHCP server, but don't provide a value to disable sending a DNS entry (-o flag, again)
|
||||
# - add option 252 (WPAD) to DHCP server with value 'http://172.16.0.1/wpad.dat' (-o flag, again)
|
||||
P4wnP1_cli NET set server -i usbeth -a 172.16.0.1 -m 255.255.255.252 -r "172.16.0.2|172.16.0.2|3m" -o "3:" -o "6:" -o "252:http://172.16.0.1/wpad.dat"
|
||||
|
||||
# Note: valid DHCP options are defined in RFC 2132 and additional RFCs (f.e. draft-ietf-wrec-wpad-01 defines WPAD)
|
||||
# Note 2: some option values are lists with comma, f.e option 121 (static route) "121:10.0.0.0/8,10.0.0.1,11.0.0.0,10.0.0.1"
|
||||
# as the comma "," is already used as delimiter for multiple options, it has to be replaced by a pipe operator "|"
|
||||
# and the option has to be provided like this:
|
||||
# -o "121:10.0.0.0/8|10.0.0.1|11.0.0.0/8|10.0.0.1"
|
||||
|
||||
|
||||
|
||||
# Start a DHCP Client for interface wlan0
|
||||
P4wnP1_cli NET set client -i wlan0
|
@ -29,7 +29,11 @@ func pidFileDHCPClient(nameIface string) string {
|
||||
}
|
||||
|
||||
func leaseFileDHCPSrv(s *pb.DHCPServerSettings) (lf string) {
|
||||
return fmt.Sprintf("/tmp/dnsmasq_%s.leases", s.ListenInterface) //default lease file
|
||||
return NameLeaseFileDHCPSrv(s.ListenInterface) //default lease file
|
||||
}
|
||||
|
||||
func NameLeaseFileDHCPSrv(nameIface string) (lf string) {
|
||||
return fmt.Sprintf("/tmp/dnsmasq_%s.leases", nameIface)
|
||||
}
|
||||
|
||||
|
||||
@ -214,6 +218,7 @@ func DHCPCreateConfigFile(s *pb.DHCPServerSettings, filename string) (err error)
|
||||
file_content, err := DHCPCreateConfigFileString(s)
|
||||
if err != nil {return}
|
||||
err = ioutil.WriteFile(filename, []byte(file_content), os.ModePerm)
|
||||
//ToDo: test config with `dnsmasq -C configfile --test`
|
||||
return
|
||||
}
|
||||
|
||||
@ -232,7 +237,15 @@ func DHCPCreateConfigFileString(s *pb.DHCPServerSettings) (config string, err er
|
||||
|
||||
//Iterate over Ranges
|
||||
for _, pRange := range s.Ranges {
|
||||
config += fmt.Sprintf("dhcp-range=%s,%s,%s\n", pRange.RangeLower, pRange.RangeUpper, pRange.LeaseTime)
|
||||
//ToDo: regex check for leaseTime
|
||||
//ToDo: check rangeLower + rangeUpper to be valid IP addresses
|
||||
if len(pRange.LeaseTime) > 0 {
|
||||
config += fmt.Sprintf("dhcp-range=%s,%s,%s\n", pRange.RangeLower, pRange.RangeUpper, pRange.LeaseTime)
|
||||
} else {
|
||||
//default to 5 minute lease
|
||||
config += fmt.Sprintf("dhcp-range=%s,%s,5m\n", pRange.RangeLower, pRange.RangeUpper)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Iterate over options
|
||||
@ -254,6 +267,7 @@ func DHCPCreateConfigFileString(s *pb.DHCPServerSettings) (config string, err er
|
||||
config += fmt.Sprintf("log-dhcp\n") //extensive logging by default
|
||||
if (!s.NotAuthoritative) { config += fmt.Sprintf("dhcp-authoritative\n") }
|
||||
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user