From f441648d9730e3c869049aef3f0f6ff952097db5 Mon Sep 17 00:00:00 2001
From: Philippe PITTOLI
Date: Fri, 4 Oct 2019 15:59:58 +0200
Subject: [PATCH] configuration
---
src/main.cr | 229 +++++++++++++++++++++++++++++++++-------------------
1 file changed, 146 insertions(+), 83 deletions(-)
diff --git a/src/main.cr b/src/main.cr
index 8e04f1f..0d5160d 100644
--- a/src/main.cr
+++ b/src/main.cr
@@ -6,11 +6,22 @@ require "./colors"
simulation = false
file = nil
+prefered_network_configuration_program = nil
+prefered_dhcp_client = nil
+
OptionParser.parse! do |parser|
parser.on "-s", "--simulation", "Export the network configuration." do
simulation = true
end
+ parser.on "-n network-configuration-program", "--net-conf network-configuration-program", "ifconfig | ip" do |prog|
+ prefered_network_configuration_program = prog
+ end
+
+ parser.on "-d dhcp-client-program", "--dhcp-client dhcp-client-program", "udhcpc" do |prog|
+ prefered_dhcp_client = prog
+ end
+
parser.on "-f file", "--file file", "Parse a configuration file." do |optsn|
file = optsn
end
@@ -39,10 +50,20 @@ class Do < Process
end
end
+class NotSetup
+ def to_s(io : IO)
+ io << "not setup"
+ end
+end
+
+
class NetworkCommands
- class DHCPCommands
- def self.dhcp(ifname : String)
+ class_property cmd_network_configuration : IfconfigCommand.class | IPCommand.class = IfconfigCommand
+ class_property cmd_dhcp_client : UDHCPCCommand.class | NotSetup.class = NotSetup
+
+ class UDHCPCCommand
+ def self.run(ifname : String)
# TODO: verify which dhcp client is installed on the system
cmd = "udhcpc"
unless Do.run(cmd, [ name ]).success?
@@ -51,14 +72,11 @@ class NetworkCommands
end
end
- def self.which(cmd : String)
- Do.run("which", [ cmd ]).success?
- end
-
class IfconfigCommand
- def self.interface_exists?(name : String)
+ def self.interface_exists(name : String)
Do.run("ifconfig", [ name ]).success?
end
+
def self.up_or_down(name : String, updown : String)
unless Do.run("ifconfig", [ name, updown ]).success?
raise "(ifconfig) Cannot set #{updown} link name #{name}"
@@ -72,14 +90,25 @@ class NetworkCommands
end
def self.set_ip(name : String, ip : IPAddress)
- puts "(ip) setup static IP address"
+ unless Do.run("ifconfig", [ name, "add", ip.to_string ]).success?
+ raise "(ifconfig) Cannot set ip address #{ip.to_string} for #{name}"
+ end
+ end
+
+ # currently, aliasses with ifconfig: ifconfig add ip/mask
+ # same command as the ip setup
+ def self.set_alias(name : String, ip : IPAddress)
+ unless Do.run("ifconfig", [ name, "add", ip.to_string ]).success?
+ raise "(ifconfig) Cannot set ip address alias #{ip.to_string} for #{name}"
+ end
end
end
class IPCommand
- def self.interface_exists?(name : String)
+ def self.interface_exists(name : String)
Do.run("ip", [ "link", "show", "dev", name ]).success?
end
+
def self.up_or_down(name : String, updown : String)
unless Do.run("ip", [ "link", "set", updown, "dev", name ]).success?
raise "(ip) Cannot set #{updown} link name #{name}"
@@ -93,43 +122,47 @@ class NetworkCommands
end
def self.set_ip(name : String, ip : IPAddress)
- puts "(ip) setup static IP address"
+ unless Do.run("ip", [ "address", "add", ip.to_string, "dev", name ]).success?
+ raise "(ip) Cannot add ip address #{ip.to_string} to #{name}"
+ end
+ end
+
+ def self.set_alias(name : String, ip : IPAddress)
+ unless Do.run("ip", [ "address", "add", ip.to_string, "dev", name ]).success?
+ raise "(ip) Cannot add ip address alias #{ip.to_string} to #{name}"
+ end
end
end
- def self.choose_command : IfconfigCommand.class | IPCommand.class
- if self.which("ifconfig")
- IfconfigCommand
- elsif self.which("ip")
- IPCommand
- else
- raise "Neither ifconfig or ip commands exists on this system"
- end
- end
-
- def self.interface_exists?(name : String)
- cmd = self.choose_command
- cmd.interface_exists?(name)
+ def self.interface_exists(name : String)
+ @@cmd_network_configuration.interface_exists(name)
end
def self.up(ifname : String)
- cmd = self.choose_command
- cmd.up(ifname)
+ @@cmd_network_configuration.up(ifname)
end
def self.down(ifname : String)
- cmd = self.choose_command
- cmd.up(ifname)
+ @@cmd_network_configuration.up(ifname)
end
def self.set_ip(name : String, ip : IPAddress)
- puts "(ip) setup static IP address"
+ @@cmd_network_configuration.set_ip name, ip
end
def self.dhcp(name : String)
- puts "(ip) setup dynamic IP address"
- DHCPCommands.dhcp name
+ cmd = @@cmd_dhcp_client
+ case cmd
+ when NotSetup
+ puts "no dhcp client: cannot perform dhcp on #{name}"
+ when UDHCPCCommand
+ cmd.run name
+ end
+ end
+
+ def self.set_alias(name : String, ip : IPAddress)
+ @@cmd_network_configuration.set_alias name, ip
end
end
@@ -139,12 +172,6 @@ end
#
class InterfaceConfiguration
- class NotSetup
- def to_s(io : IO)
- io << "not setup"
- end
- end
-
class DHCP
def to_s(io : IO)
io << "dhcp"
@@ -177,7 +204,7 @@ class InterfaceConfiguration
def to_string
String.build do |str|
- if NetworkCommands.interface_exists?(@name)
+ if NetworkCommands.interface_exists(@name)
str << "#{CGREEN}#{@name}#{CRESET}\n"
else
str << "#{CRED}#{@name}#{CRESET}\n"
@@ -204,13 +231,10 @@ class InterfaceConfiguration
# configure the interface
def execute
- unless NetworkCommands.interface_exists?(@name)
+ unless NetworkCommands.interface_exists(@name)
raise "The interface #{@name} doesn't exists, yet."
end
- puts "OK on va configurer ça"
- puts "#{self}"
-
if @up
NetworkCommands.up @name
else
@@ -218,50 +242,50 @@ class InterfaceConfiguration
return
end
+ # ipv4 configuration
+ @main_ip_v4.tap do |ip|
+ case ip
+ when IPAddress
+ NetworkCommands.set_ip @name, ip
+ when DHCP
+ NetworkCommands.dhcp @name
+ when NotSetup
+ puts "no ipv4"
+ else
+ raise "ipv4 configuration: neither static nor dynamic"
+ end
- case main_ip_v4 = @main_ip_v4
- when IPAddress
- NetworkCommands.set_ip @name, main_ip_v4
- when DHCP
- NetworkCommands.dhcp @name
- when NotSetup
- puts "no ipv4"
- else
- raise "ipv4 configuration: neither static nor dynamic"
+ # We wont setup aliasses unless there is an actual IP address
+ if ip != NotSetup
+ @aliasses_v4.each do |ip_alias|
+ NetworkCommands.set_alias @name, ip_alias
+ end
+ end
end
- case main_ip_v6 = @main_ip_v6
- when IPAddress
- NetworkCommands.set_ip @name, main_ip_v6
- # TODO
- #when Autoconfiguration
- # NetworkCommands.autoconfiguration @name
- #when DHCP
- # NetworkCommands.dhcp6 @name
- when NotSetup
- puts "no ipv4"
- else
- raise "ipv4 configuration: neither static nor dynamic"
+ # ipv6 configuration
+ @main_ip_v6.tap do |ip|
+ case ip
+ when IPAddress
+ NetworkCommands.set_ip @name, ip
+ # TODO
+ #when Autoconfiguration
+ # NetworkCommands.autoconfiguration @name
+ #when DHCP
+ # NetworkCommands.dhcp6 @name
+ when NotSetup
+ puts "no ipv6"
+ else
+ raise "ipv4 configuration: neither static nor dynamic"
+ end
+
+ # We wont setup aliasses unless there is an actual IP address
+ if ip != NotSetup
+ @aliasses_v6.each do |ip_alias|
+ NetworkCommands.set_alias @name, ip_alias
+ end
+ end
end
-
-
- # str << "\tinet #{@main_ip_v4}\n"
-
- # str << "\t#{@up? "up" : "down"}\n"
- # str << "\tinet #{@main_ip_v4}\n"
-
- # unless @aliasses_v4.empty?
- # @aliasses_v4.each do |a|
- # str << "\talias #{a}\n"
- # end
- # end
-
- # str << "\tinet6 #{@main_ip_v6}\n"
-
- # @aliasses_v6.each do |a|
- # str << "\talias6 #{a}\n"
- # end
- # alias execution: only when the main ip address is setup
end
end
@@ -275,8 +299,8 @@ class NetworkConfigurationParser
def self.parse (ifname : String, data : String) : InterfaceConfiguration
up = false
- main_ip_v4 = InterfaceConfiguration::NotSetup.new
- main_ip_v6 = InterfaceConfiguration::NotSetup.new
+ main_ip_v4 = NotSetup.new
+ main_ip_v6 = NotSetup.new
aliasses = [] of IPAddress
@@ -320,6 +344,45 @@ end
Do.simulation = simulation
+def which(cmd : String)
+ if Process.run("which", [ cmd ]).success?
+ puts "#{cmd} installed"
+ true
+ else
+ puts "#{cmd} not installed"
+ false
+ end
+end
+
+
+#
+# discover available configuration commands
+#
+
+# ifconfig = *bsd and some linux
+# ip = linux
+possible_network_configuration_cmds = {
+ "ifconfig" => NetworkCommands::IfconfigCommand,
+ "ip" => NetworkCommands::IPCommand
+}
+
+# udhcpc = busybox dhcp client
+possible_dhcp_clients = {
+ "udhcpc" => NetworkCommands::UDHCPCCommand
+}
+
+
+key = prefered_network_configuration_program
+key = possible_network_configuration_cmds.keys.find { |key| which(key) } if key.nil?
+# should crash if there is no network command installed
+NetworkCommands.cmd_network_configuration = possible_network_configuration_cmds[key.not_nil!]
+
+key = prefered_dhcp_client
+key = possible_dhcp_clients.keys.find { |key| which(key) } if key.nil?
+# should not crash if there is no
+NetworkCommands.cmd_dhcp_client = possible_dhcp_clients[key] unless key.nil?
+
+
if file.nil?
raise "Cannot choose files yet"
else