From e184ef615835ccd10da36723ddcf948b78e5cbc3 Mon Sep 17 00:00:00 2001
From: Philippe PITTOLI
Date: Sun, 6 Oct 2019 19:34:54 +0200
Subject: [PATCH] meh, plein de trucs
---
src/main.cr | 250 ++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 223 insertions(+), 27 deletions(-)
diff --git a/src/main.cr b/src/main.cr
index 6e9403b..4b0fa0c 100644
--- a/src/main.cr
+++ b/src/main.cr
@@ -10,11 +10,19 @@ prefered_network_configuration_program = nil
prefered_wireless_configuration_program = nil
prefered_dhcp_client = nil
+print_autodetect = false
+
+command = "list"
+
OptionParser.parse! do |parser|
parser.on "-s", "--simulation", "Export the network configuration." do
simulation = true
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|
prefered_wireless_configuration_program = prog
end
@@ -36,6 +44,35 @@ OptionParser.parse! do |parser|
verbosity = optsn.to_i
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
puts parser
exit 0
@@ -61,12 +98,17 @@ class NotSetup
end
end
+class DHCP
+ def to_s(io : IO)
+ io << "dhcp"
+ end
+end
class NetworkCommands
class_property cmd_network_configuration : IfconfigCommand.class | IPCommand.class = IfconfigCommand
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
def self.get_ssid(ifname : String, ssid)
@@ -86,6 +128,16 @@ class NetworkCommands
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
def self.interface_exists(name : String)
Do.run("ifconfig", [ name ]).success?
@@ -236,6 +288,15 @@ end
class WirelessAPSetup
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
property security : WPA
@@ -246,6 +307,40 @@ class WirelessAPSetup
end
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
@@ -255,11 +350,6 @@ end
#
class InterfaceConfiguration
- class DHCP
- def to_s(io : IO)
- io << "dhcp"
- end
- end
property name : String
property up : Bool
@@ -302,7 +392,7 @@ class InterfaceConfiguration
str << "#{CRED}#{@name}#{CRESET}\n"
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"
@@ -325,6 +415,14 @@ class InterfaceConfiguration
str << "\talias6 #{a}\n"
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
@@ -440,9 +538,9 @@ class NetworkConfigurationParser
when /^inet6? dhcp/
# IPaddress is DHCP
if /^inet /.match(line)
- main_ip_v4 = InterfaceConfiguration::DHCP.new
+ main_ip_v4 = DHCP.new
else
- main_ip_v6 = InterfaceConfiguration::DHCP.new
+ main_ip_v6 = DHCP.new
end
when /^inet6 autoconf/
# IPaddress is autoconfigured
@@ -458,14 +556,98 @@ class NetworkConfigurationParser
else
main_ip_v6 = IPAddress.parse ipstr
end
- when /^join [^ ]+ wpakey .*/
+ when /^join [^ \t]+ wpakey .*/
# 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 .*/
- puts "TODO: network SSID inet IP/prefix"
+ if ssid.nil?
+ puts "wrong SSID in line: #{line}"
+ next
+ end
- when /^network [^ ]+ dhcp/
- puts "TODO: network SSID dhcp"
+ if wpakeystr.nil?
+ 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 (?[^ \t]+) inet6? (?[^ \t]+)/.match(line).try do |m|
+ ssid = m["ssid"]
+ ipstr = m["ip"]
+ end
+ # ssid = /^network ([^ \t]+)/.match(line).try &.[1]
+ # ipstr = /^network [^ \t]+ inet6? (?[^ \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 .*/
puts "TODO: network SSID dns"
@@ -491,18 +673,25 @@ class NetworkConfigurationParser
end
end
-def which(cmd : String)
- if Process.run("which", [ cmd ]).success?
- puts "#{cmd} installed"
- true
- else
- puts "#{cmd} not installed"
- false
+
+
+class Autodetect
+ class_property print_autodetect : Bool = false
+
+ def self.which(cmd : String)
+ 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
Do.simulation = simulation
+Autodetect.print_autodetect = print_autodetect
#
# discover available configuration commands
@@ -517,7 +706,8 @@ possible_network_configuration_cmds = {
# udhcpc = busybox dhcp client
possible_dhcp_clients = {
- "udhcpc" => NetworkCommands::UDHCPCCommand
+ "udhcpc" => NetworkCommands::UDHCPCCommand,
+ "dhclient" => NetworkCommands::DHClientCommand
}
# iw = linux
@@ -526,24 +716,30 @@ possible_wireless_configuration_cmds = {
}
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
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?
+key = possible_dhcp_clients.keys.find { |key| Autodetect.which(key) } if key.nil?
# should not crash if there is no
NetworkCommands.cmd_dhcp_client = possible_dhcp_clients[key] unless key.nil?
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
NetworkCommands.cmd_wireless_configuration = possible_wireless_configuration_cmds[key.not_nil!]
if file.nil?
- raise "Cannot choose files yet"
-else
+ raise "Cannot search for files yet"
+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
network_configuration = NetworkConfigurationParser.parse_file(file.not_nil!)
network_configuration.execute