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