mirror of
https://github.com/RoganDawes/P4wnP1_aloa.git
synced 2025-03-17 13:21:50 +01:00
290 lines
9.0 KiB
Go
290 lines
9.0 KiB
Go
package cli_client
|
|
|
|
import (
|
|
"github.com/spf13/cobra"
|
|
pb "github.com/mame82/P4wnP1_aloa/proto"
|
|
"net"
|
|
"errors"
|
|
"fmt"
|
|
"google.golang.org/grpc/status"
|
|
//"github.com/mame82/P4wnP1_aloa/service"
|
|
"strings"
|
|
"strconv"
|
|
"github.com/mame82/P4wnP1_aloa/common_web"
|
|
)
|
|
|
|
//Empty settings used to store cobra flags
|
|
var (
|
|
|
|
tmpStrInterface string = ""
|
|
tmpStrAddress4 string = ""
|
|
tmpStrNetmask4 string = ""
|
|
tmpDisabled bool = false
|
|
tmpDHCPSrvOptions []string = []string{}
|
|
tmpDHCPSrvRanges []string = []string{}
|
|
|
|
)
|
|
|
|
/*
|
|
func init(){
|
|
//Configure spew for struct deep printing (disable using printer interface for gRPC structs)
|
|
spew.Config.Indent="\t"
|
|
spew.Config.DisableMethods = true
|
|
spew.Config.DisablePointerAddresses = true
|
|
}
|
|
*/
|
|
|
|
var netCmd = &cobra.Command{
|
|
Use: "net",
|
|
Short: "Configure Network settings of ethernet interfaces (including USB ethernet if enabled)",
|
|
}
|
|
|
|
var netSetCmd = &cobra.Command{
|
|
Use: "set",
|
|
Short: "set ethernet settings",
|
|
Long: ``,
|
|
}
|
|
|
|
var netSetManualCmd = &cobra.Command{
|
|
Use: "manual",
|
|
Short: "Configure given interface manually",
|
|
Long: ``,
|
|
Run: cobraNetSetManual,
|
|
}
|
|
|
|
|
|
var netSetDHCPClientCmd = &cobra.Command{
|
|
Use: "client",
|
|
Short: "Configure given interface to run a DHCP client",
|
|
Long: ``,
|
|
Run: cobraNetSetDHCPClient,
|
|
}
|
|
|
|
var netSetDHCPServerCmd = &cobra.Command{
|
|
Use: "server",
|
|
Short: "Configure given interface to run a DHCP server",
|
|
Long: ``,
|
|
Run: cobraNetSetDHCPServer,
|
|
}
|
|
var netGetCmd = &cobra.Command{
|
|
Use: "get",
|
|
Short: "get ethernet settings",
|
|
Long: ``,
|
|
Run: cobraNetGet,
|
|
}
|
|
|
|
func cobraNetGet(cmd *cobra.Command, args []string) {
|
|
return
|
|
}
|
|
|
|
func cobraNetSetManual(cmd *cobra.Command, args []string) {
|
|
settings, err := createManualSettings(tmpStrInterface, tmpStrAddress4, tmpStrNetmask4, 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 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) {
|
|
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") }
|
|
|
|
settings = &pb.EthernetInterfaceSettings {
|
|
Mode: pb.EthernetInterfaceSettings_MANUAL,
|
|
Name: iface,
|
|
IpAddress4: ip4,
|
|
Netmask4: mask4,
|
|
Enabled: !disabled,
|
|
DhcpServerSettings: nil,
|
|
}
|
|
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))
|
|
//ignore empty options
|
|
continue
|
|
}
|
|
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{}
|
|
if len(strRanges) == 0 {
|
|
return nil,errors.New(fmt.Sprintf("Missing DHCP range: At least one range should be provided to allow assigning IP addresses to clients\n"))
|
|
}
|
|
|
|
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\nformat 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: common_web.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 {
|
|
return errors.New(fmt.Sprintf("Error parsing IP address '%s'\n",ip4))
|
|
}
|
|
if ip.To4() == nil {
|
|
return errors.New(fmt.Sprintf("Not an IPv4 address '%s'\n",ip4))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
|
|
func init() {
|
|
rootCmd.AddCommand(netCmd)
|
|
// netCmd.AddCommand(netGetCmd)
|
|
netCmd.AddCommand(netSetCmd)
|
|
netSetCmd.AddCommand(netSetManualCmd)
|
|
netSetCmd.AddCommand(netSetDHCPClientCmd)
|
|
netSetCmd.AddCommand(netSetDHCPServerCmd)
|
|
|
|
netSetCmd.PersistentFlags().StringVarP(&tmpStrInterface, "interface","i", "", "The name of the ethernet interface to work on")
|
|
netSetCmd.PersistentFlags().BoolVarP(&tmpDisabled, "disable","d", false, "The flag disables the given interface (omitting the flag enables the interface")
|
|
netSetManualCmd.Flags().StringVarP(&tmpStrAddress4, "address","a", "", "The IPv4 address to use for the interface")
|
|
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)")
|
|
}
|