meh, plein de trucs

This commit is contained in:
Philippe PITTOLI 2019-10-06 19:34:54 +02:00
parent edb7955f30
commit e184ef6158

View File

@ -10,11 +10,19 @@ prefered_network_configuration_program = nil
prefered_wireless_configuration_program = nil prefered_wireless_configuration_program = nil
prefered_dhcp_client = nil prefered_dhcp_client = nil
print_autodetect = false
command = "list"
OptionParser.parse! do |parser| OptionParser.parse! do |parser|
parser.on "-s", "--simulation", "Export the network configuration." do parser.on "-s", "--simulation", "Export the network configuration." do
simulation = true simulation = true
end end
parser.on "-a", "--print-autodetect", "Print autodetection of the installed programs." do
print_autodetect = true
end
parser.on "-w wireless-configuration-program", "--wireless wireless-configuration-program", "iw" do |prog| parser.on "-w wireless-configuration-program", "--wireless wireless-configuration-program", "iw" do |prog|
prefered_wireless_configuration_program = prog prefered_wireless_configuration_program = prog
end end
@ -36,6 +44,35 @@ OptionParser.parse! do |parser|
verbosity = optsn.to_i verbosity = optsn.to_i
end end
parser.missing_option do |opt|
STDERR.puts "You missed the argument for option #{opt}"
# TODO: explain the different arguments
exit 1
end
parser.invalid_option do |flag|
STDERR.puts "Error: #{flag} not a valid option"
exit 1
end
parser.unknown_args do |arg|
command = arg.shift
case command
when /^(list)/
STDERR.puts "TODO: list" unless arg.empty?
when /^(connect)/
STDERR.puts "TODO: connect" unless arg.empty?
else
STDERR.puts "Command #{command} not understood"
end
unless arg.empty?
STDERR.puts "unknown arg: #{arg}"
exit 1
end
end
parser.on "-h", "--help", "Show this help" do parser.on "-h", "--help", "Show this help" do
puts parser puts parser
exit 0 exit 0
@ -61,12 +98,17 @@ class NotSetup
end end
end end
class DHCP
def to_s(io : IO)
io << "dhcp"
end
end
class NetworkCommands class NetworkCommands
class_property cmd_network_configuration : IfconfigCommand.class | IPCommand.class = IfconfigCommand class_property cmd_network_configuration : IfconfigCommand.class | IPCommand.class = IfconfigCommand
class_property cmd_wireless_configuration : IWCommand.class | NotSetup.class = NotSetup class_property cmd_wireless_configuration : IWCommand.class | NotSetup.class = NotSetup
class_property cmd_dhcp_client : UDHCPCCommand.class | NotSetup.class = NotSetup class_property cmd_dhcp_client : UDHCPCCommand.class | DHClientCommand.class | NotSetup.class = NotSetup
class IWCommand class IWCommand
def self.get_ssid(ifname : String, ssid) def self.get_ssid(ifname : String, ssid)
@ -86,6 +128,16 @@ class NetworkCommands
end end
end end
class DHClientCommand
def self.run(ifname : String)
# TODO: verify which dhcp client is installed on the system
cmd = "udhcpc"
unless Do.run(cmd, [ name ]).success?
raise "(#{cmd}) dhcp failed on #{ifname}"
end
end
end
class IfconfigCommand class IfconfigCommand
def self.interface_exists(name : String) def self.interface_exists(name : String)
Do.run("ifconfig", [ name ]).success? Do.run("ifconfig", [ name ]).success?
@ -236,6 +288,15 @@ end
class WirelessAPSetup class WirelessAPSetup
property ssid : String property ssid : String
# This is a list of parameters that should be unique to each AP
property up : Bool
property description : String?
property mtu : Int32?
property main_ip_v4 : IPAddress | DHCP | NotSetup
property main_ip_v6 : IPAddress | DHCP | NotSetup
property aliasses_v4 : Array(IPAddress)
property aliasses_v6 : Array(IPAddress)
# we currently only support WPA2-PSK wireless security mechanism # we currently only support WPA2-PSK wireless security mechanism
property security : WPA property security : WPA
@ -246,6 +307,40 @@ class WirelessAPSetup
end end
def initialize(@ssid, @security) def initialize(@ssid, @security)
@main_ip_v4 = NotSetup.new
@main_ip_v6 = NotSetup.new
@aliasses_v4 = Array(IPAddress).new
@aliasses_v6 = Array(IPAddress).new
@up = true
end
def to_s(io : IO)
io << to_string
end
def to_string
String.build do |str|
str << "#{CBLUE}#{ssid}: {ssid}#{CRESET}\n"
str << "\t#description #{description.not_nil!}\n" unless description.nil?
str << "\t#{@up? "up" : "down"}\n"
str << "\tmtu #{mtu}\n" unless mtu.nil?
# ipv4
str << "\tinet #{@main_ip_v4}\n"
@aliasses_v4.each do |a|
str << "\talias #{a}\n"
end
# ipv6
str << "\tinet6 #{@main_ip_v6}\n"
unless @aliasses_v6.empty?
@aliasses_v6.each do |a|
str << "\talias6 #{a}\n"
end
end
end
end end
end end
@ -255,11 +350,6 @@ end
# #
class InterfaceConfiguration class InterfaceConfiguration
class DHCP
def to_s(io : IO)
io << "dhcp"
end
end
property name : String property name : String
property up : Bool property up : Bool
@ -302,7 +392,7 @@ class InterfaceConfiguration
str << "#{CRED}#{@name}#{CRESET}\n" str << "#{CRED}#{@name}#{CRESET}\n"
end end
str << "\t#description #{description.not_nil!}\n" unless description.nil? str << "\tdescription: '#{description.not_nil!}'\n" unless description.nil?
str << "\t#{@up? "up" : "down"}\n" str << "\t#{@up? "up" : "down"}\n"
@ -325,6 +415,14 @@ class InterfaceConfiguration
str << "\talias6 #{a}\n" str << "\talias6 #{a}\n"
end end
end end
if wireless_networks.empty?
puts "no wireless connection configured" if wireless
else
wireless_networks.each do |k,v|
puts v
end
end
end end
end end
@ -440,9 +538,9 @@ class NetworkConfigurationParser
when /^inet6? dhcp/ when /^inet6? dhcp/
# IPaddress is DHCP # IPaddress is DHCP
if /^inet /.match(line) if /^inet /.match(line)
main_ip_v4 = InterfaceConfiguration::DHCP.new main_ip_v4 = DHCP.new
else else
main_ip_v6 = InterfaceConfiguration::DHCP.new main_ip_v6 = DHCP.new
end end
when /^inet6 autoconf/ when /^inet6 autoconf/
# IPaddress is autoconfigured # IPaddress is autoconfigured
@ -458,14 +556,98 @@ class NetworkConfigurationParser
else else
main_ip_v6 = IPAddress.parse ipstr main_ip_v6 = IPAddress.parse ipstr
end end
when /^join [^ ]+ wpakey .*/ when /^join [^ \t]+ wpakey .*/
# WPA2-PSK, other security mechanisms are not supported, yet # WPA2-PSK, other security mechanisms are not supported, yet
ssid = /^join ([^ \t]+)/.match(line).try &.[1]
wpakeystr = /^join [^ \t]+ wpakey ([^ \t]+)/.match(line).try &.[1]
when /^network [^ ]+ inet .*/ if ssid.nil?
puts "TODO: network SSID inet IP/prefix" puts "wrong SSID in line: #{line}"
next
end
when /^network [^ ]+ dhcp/ if wpakeystr.nil?
puts "TODO: network SSID dhcp" puts "wrong wpa key in line: #{line}"
next
end
# TODO
new_ap = WirelessAPSetup.new ssid, WirelessAPSetup::WPA.new(wpakeystr)
wireless_networks[ssid] = new_ap
when /^network [^ \t]+ inet6 autoconf/
puts "TODO: network SSID inet6 autoconf"
ssid = /^network ([^ \t]+)/.match(line).try &.[1]
ipstr = /^network [^ \t]+ inet6? ([^ \t]+)/.match(line).try &.[1]
if ssid.nil?
puts "wrong SSID in line: #{line}"
next
end
if ipstr.nil?
puts "wrong ip address in line: #{line}"
next
end
# TODO
access_point = wireless_networks[ssid].not_nil!
when /^network [^ \t]+ inet6? .*/
ssid = nil
ipstr = nil
/^network (?<ssid>[^ \t]+) inet6? (?<ip>[^ \t]+)/.match(line).try do |m|
ssid = m["ssid"]
ipstr = m["ip"]
end
# ssid = /^network ([^ \t]+)/.match(line).try &.[1]
# ipstr = /^network [^ \t]+ inet6? (?<ip>[^ \t]+)/.match(line).try &.["ip"]
if ssid.nil?
puts "wrong SSID in line: #{line}"
next
end
if ipstr.nil?
puts "wrong ip address in line: #{line}"
next
end
# TODO
ipaddr = IPAddress.parse ipstr
# TODO
access_point = wireless_networks[ssid].not_nil!
if ipaddr.ipv4?
access_point.main_ip_v4 = ipaddr
elsif ipaddr.ipv6?
access_point.main_ip_v6 = ipaddr
else
puts "wrong ip address in line: #{line} (neither ipv4 or ipv6)"
end
when /^network [^ ]+ dhcp6?/
ssid = /^network ([^ \t]+)/.match(line).try &.[1]
if ssid.nil?
puts "wrong SSID in line: #{line}"
next
end
# TODO
access_point = wireless_networks[ssid].not_nil!
if /dhcp6/.match(line)
access_point.main_ip_v6 = DHCP.new
elsif /dhcp/.match(line)
access_point.main_ip_v4 = DHCP.new
else
puts "wrong dhcp instruction in line: #{line}"
end
when /^network [^ ]+ dns .*/ when /^network [^ ]+ dns .*/
puts "TODO: network SSID dns" puts "TODO: network SSID dns"
@ -491,18 +673,25 @@ class NetworkConfigurationParser
end end
end end
def which(cmd : String)
if Process.run("which", [ cmd ]).success?
puts "#{cmd} installed" class Autodetect
true class_property print_autodetect : Bool = false
else
puts "#{cmd} not installed" def self.which(cmd : String)
false if Process.run("which", [ cmd ]).success?
puts "#{cmd} installed" if print_autodetect
true
else
puts "#{cmd} not installed" if print_autodetect
false
end
end end
end end
Do.simulation = simulation Do.simulation = simulation
Autodetect.print_autodetect = print_autodetect
# #
# discover available configuration commands # discover available configuration commands
@ -517,7 +706,8 @@ possible_network_configuration_cmds = {
# udhcpc = busybox dhcp client # udhcpc = busybox dhcp client
possible_dhcp_clients = { possible_dhcp_clients = {
"udhcpc" => NetworkCommands::UDHCPCCommand "udhcpc" => NetworkCommands::UDHCPCCommand,
"dhclient" => NetworkCommands::DHClientCommand
} }
# iw = linux # iw = linux
@ -526,24 +716,30 @@ possible_wireless_configuration_cmds = {
} }
key = prefered_network_configuration_program key = prefered_network_configuration_program
key = possible_network_configuration_cmds.keys.find { |key| which(key) } if key.nil? key = possible_network_configuration_cmds.keys.find { |key| Autodetect.which(key) } if key.nil?
# should crash if there is no network command installed # should crash if there is no network command installed
NetworkCommands.cmd_network_configuration = possible_network_configuration_cmds[key.not_nil!] NetworkCommands.cmd_network_configuration = possible_network_configuration_cmds[key.not_nil!]
key = prefered_dhcp_client key = prefered_dhcp_client
key = possible_dhcp_clients.keys.find { |key| which(key) } if key.nil? key = possible_dhcp_clients.keys.find { |key| Autodetect.which(key) } if key.nil?
# should not crash if there is no # should not crash if there is no
NetworkCommands.cmd_dhcp_client = possible_dhcp_clients[key] unless key.nil? NetworkCommands.cmd_dhcp_client = possible_dhcp_clients[key] unless key.nil?
key = prefered_wireless_configuration_program key = prefered_wireless_configuration_program
key = possible_wireless_configuration_cmds.keys.find { |key| which(key) } if key.nil? key = possible_wireless_configuration_cmds.keys.find { |key| Autodetect.which(key) } if key.nil?
# should crash if there is no wireless command installed # should crash if there is no wireless command installed
NetworkCommands.cmd_wireless_configuration = possible_wireless_configuration_cmds[key.not_nil!] NetworkCommands.cmd_wireless_configuration = possible_wireless_configuration_cmds[key.not_nil!]
if file.nil? if file.nil?
raise "Cannot choose files yet" raise "Cannot search for files yet"
else end
case command
when "list"
# TODO: why having to force "not_nil!" ? Seems like a compiler bug
puts NetworkConfigurationParser.parse_file(file.not_nil!)
when "connect"
# TODO: why having to force "not_nil!" ? Seems like a compiler bug # TODO: why having to force "not_nil!" ? Seems like a compiler bug
network_configuration = NetworkConfigurationParser.parse_file(file.not_nil!) network_configuration = NetworkConfigurationParser.parse_file(file.not_nil!)
network_configuration.execute network_configuration.execute