P4wnP1_aloa/cli_client/cmd_net.go
2018-12-07 00:59:54 +01:00

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)")
}