networkctl/src/configuration.cr

337 lines
7.1 KiB
Crystal

class NotSetup
def to_s(io : IO)
io << "not setup"
end
end
class Autoconfiguration
def to_s(io : IO)
io << "autoconfiguration"
end
end
class DHCP
def to_s(io : IO)
io << "dhcp"
end
end
class WirelessAPSetup
property ifname : 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 | Autoconfiguration | NotSetup
property aliasses_v4 : Array(IPAddress)
property aliasses_v6 : Array(IPAddress)
property dns : NetworkCommands::DNS
# we currently only support WPA2-PSK wireless security mechanism
property security : WPA
class WPA
property key : String
def initialize(@key)
end
def to_s(io : IO)
io << "WPA access point, key #{key}"
end
end
def initialize(@ifname, @ssid, @security)
@main_ip_v4 = NotSetup.new
@main_ip_v6 = NotSetup.new
@aliasses_v4 = Array(IPAddress).new
@aliasses_v6 = Array(IPAddress).new
@up = true
@dns = NetworkCommands::DNS.new
end
def to_s(io : IO)
io << indent(1, to_string)
end
def to_string
String.build do |str|
str << "#{CBLUE}#{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
unless main_ip_v4.is_a?(NotSetup)
str << "\tinet #{main_ip_v4}\n"
aliasses_v4.each do |a|
str << "\talias #{a}\n"
end
end
# ipv6
unless main_ip_v6.is_a?(NotSetup)
str << "\tinet6 #{main_ip_v6}\n"
@aliasses_v6.each do |a|
str << "\talias6 #{a}\n"
end
end
str << indent(1, dns.to_s) unless dns.addresses.empty?
end
end
def store_access_point_keys
NetworkCommands.store_access_point_keys ssid, security
end
def execute
puts "TODO: wireless configuration"
NetworkCommands.wireless_access_point_connection ifname, ssid
# DNS configuration
dns.execute
end
end
#
# interface configuration
#
class InterfaceConfiguration
property name : String
property up : Bool
property description : String?
property mtu : Int32?
property main_ip_v4 : IPAddress | DHCP | NotSetup
property main_ip_v6 : IPAddress | Autoconfiguration | DHCP | NotSetup
property aliasses_v4 : Array(IPAddress)
property aliasses_v6 : Array(IPAddress)
property wireless_networks : Hash(String, WirelessAPSetup)
property dns : NetworkCommands::DNS
def initialize (@name, @up,
@description,
@mtu,
@main_ip_v4, @main_ip_v6, aliasses,
@wireless_networks,
@dns
)
@aliasses_v4 = Array(IPAddress).new
@aliasses_v6 = Array(IPAddress).new
aliasses.each do |ip|
if ip.ipv4?
aliasses_v4 << ip
else
aliasses_v6 << ip
end
end
end
def to_s(io : IO)
io << to_string
end
def to_string
String.build do |str|
if NetworkCommands.interface_exists(@name)
str << "#{CGREEN}#{@name}#{CRESET}\n"
else
str << "#{CRED}#{@name}#{CRESET}\n"
end
str << "\tdescription: '#{description.not_nil!}'\n" unless description.nil?
str << "\t#{@up? "up" : "down"}\n"
unless mtu.nil?
str << "\tmtu #{mtu}\n"
end
# ipv4
unless main_ip_v4.is_a?(NotSetup)
str << "\tinet #{main_ip_v4}\n"
aliasses_v4.each do |a|
str << "\talias #{a}\n"
end
end
# warning: alias but no main ip address
if main_ip_v4.is_a?(NotSetup) && ! aliasses_v4.empty?
str << "\t#{CRED}alias configured but no main ipv4 configuration.#{CRESET}\n"
str << "\t#{CRED}Should main ipv4 be obtained from DHCP? Static configuration?#{CRESET}\n"
end
# ipv6
unless main_ip_v6.is_a?(NotSetup)
str << "\tinet6 #{main_ip_v6}\n"
aliasses_v6.each do |a|
str << "\talias6 #{a}\n"
end
end
# warning: alias but no main ip address
if main_ip_v6.is_a?(NotSetup) && ! aliasses_v6.empty?
str << "\t#{CRED}alias6 configured but no main ipv6 configuration.#{CRESET}\n"
str << "\t#{CRED}Should main ipv6 be obtained from autoconfiguration? DHCP? Static configuration?#{CRESET}\n"
end
str << indent(1, dns.to_s) unless dns.addresses.empty?
unless wireless_networks.empty?
wireless_networks.each do |k,v|
str << v
end
end
end
end
def access_point_connection
ssid_list = NetworkCommands.scan name
if ssid_list.nil?
raise "no ssid scanned"
end
if wireless_networks.empty?
raise "no configured access point for interface #{name}, cannot connect"
end
wireless_networks.each do |k,v|
ssid_list.each do |ssid|
if k == ssid
puts "#{CGREEN}#{k} == #{ssid}#{CRESET}"
v.execute
end
end
end
# TODO: sleep for a second before testing the gateway?
# TODO: configuring the interface
puts "TODO: connectivity check with the gateway"
end
def store_access_point_keys
if wireless_networks.empty?
raise "no configured access point for interface #{name}"
end
wireless_networks.each do |ssid, wireless_configuration|
puts "#{CGREEN}storing access point key for #{ssid}#{CRESET}"
wireless_configuration.store_access_point_keys
end
end
# configure the interface
def execute
unless NetworkCommands.interface_exists(@name)
raise "The interface #{@name} doesn't exists, yet."
end
if up
NetworkCommands.up name
else
puts "not marked as 'up' -- ending here"
return
end
unless mtu.nil?
NetworkCommands.mtu name, mtu
end
unless description.nil?
NetworkCommands.description name, description.not_nil!
end
# TODO: treat differently wireless and non-wireless interfaces
if @wireless_networks.empty?
puts "interface #{name} is not wireless"
else
puts "interface #{name} is wireless: connection to the access point"
store_access_point_keys
access_point_connection
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
# do nothing
else
raise "ipv4 configuration: neither static nor dynamic"
end
# 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
# ipv6 configuration
main_ip_v6.tap do |ip|
case ip
when IPAddress
NetworkCommands.set_ip name, ip
when Autoconfiguration
NetworkCommands.autoconfiguration name
when DHCP
NetworkCommands.dhcp6 name
when NotSetup
# do nothing
else
raise "ipv6 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
# DNS configuration
dns.execute
end
def down
unless NetworkCommands.interface_exists(@name)
raise "The interface #{@name} doesn't exists or is already down."
end
NetworkCommands.flush name
NetworkCommands.down name
end
def scan
unless NetworkCommands.interface_exists(@name)
raise "The interface #{@name} doesn't exists or is already down."
end
ssid_list = NetworkCommands.scan name
pp! ssid_list
end
end