networkctl/src/network_configuration_parse...

206 lines
4.5 KiB
Crystal

class NetworkConfigurationParser
def self.parse_file(file_name : String) : InterfaceConfiguration
content = File.read(file_name)
content = content.rchop
ifname = /.([a-zA-Z0-9]+)$/.match(file_name).try &.[1]
if ifname.nil?
raise "The interface name is not known from the filename: '#{file_name}'"
end
self.parse(ifname.not_nil!, content)
end
def self.parse (ifname : String, data : String) : InterfaceConfiguration
up = false
description = nil
mtu = nil
main_ip_v4 = NotSetup.new
main_ip_v6 = NotSetup.new
dns = NetworkCommands::DNS.new
aliasses = [] of IPAddress
command_lines = [] of String
wireless_networks = {} of String => WirelessAPSetup
data.split("\n").each do |line|
case line
when /^up/
up = true
when /^description/
description = /^description (.+)/.match(line).try &.[1]
when /^inet6? alias (?<ip>[a-f0-9:.\/]+)/
ipstr = $~["ip"]
if ipstr.nil?
puts "wrong IP address alias, line #{line}"
next
end
aliasses.push IPAddress.parse(ipstr)
when /^inet6? dhcp/
# IP address is DHCP
if /^inet /.match(line)
main_ip_v4 = DHCP.new
else
main_ip_v6 = DHCP.new
end
when /^inet6 autoconf/
# IP address is autoconfigured
main_ip_v6 = Autoconfiguration.new
when /^inet6? (?<ip>[a-f0-9:.\/]+)/
ipstr = $~["ip"]
if ipstr.nil?
puts "wrong IP address, line #{line}"
next
end
if /^inet /.match(line)
main_ip_v4 = IPAddress.parse ipstr
else
main_ip_v6 = IPAddress.parse ipstr
end
when /^join (?<ssid>[^ \t]+) wpakey (?<wpakey>[^ \t]+)/
# WPA2-PSK, other security mechanisms are not supported, yet
ssid = $~["ssid"]
wpakeystr = $~["wpakey"]
if ssid.nil?
puts "wrong SSID in line: #{line}"
next
end
if wpakeystr.nil?
puts "wrong wpa key in line: #{line}"
next
end
new_ap = WirelessAPSetup.new ifname, ssid, WirelessAPSetup::WPA.new(wpakeystr)
wireless_networks[ssid] = new_ap
when /^network (?<ssid>[^ \t]+) inet6 autoconf/
ssid = $~["ssid"]
if ssid.nil?
puts "wrong SSID in line: #{line}"
next
end
access_point = wireless_networks[ssid].not_nil!
access_point.main_ip_v6 = Autoconfiguration.new
when /^network (?<ssid>[^ \t]+) inet6? (?<ip>[^ \t]+)/
ssid = $~["ssid"]
ipstr = $~["ip"]
if ssid.nil?
puts "wrong SSID in line: #{line}"
next
end
if ipstr.nil?
puts "wrong ip address in line: #{line}"
next
end
ipaddr = IPAddress.parse ipstr
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 (?<ssid>[^ \t]+) dhcp6?/
ssid = $~["ssid"]
if ssid.nil?
puts "wrong SSID in line: #{line}"
next
end
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 (?<ssid>[^ \t]+) dns (?<ip>[^ \t]+)/
ssid = $~["ssid"]
ipstr = $~["ip"]
if ssid.nil?
puts "wrong SSID in line: #{line}"
next
end
if ipstr.nil?
puts "wrong ip address in line: #{line}"
next
end
access_point = wireless_networks[ssid].not_nil!
ipaddr = IPAddress.parse ipstr
access_point.dns.addresses << ipaddr.to_s
when /^mtu (?<mtu>[0-9]+)/
mtu = $~["mtu"].to_i
when /^dns (?<ip>[^ \t]+)/
ipstr = $~["ip"]
if ipstr.nil?
puts "wrong ip address in line: #{line}"
next
end
ipaddr = IPAddress.parse ipstr
dns.addresses << ipaddr.to_s
when /^!(?<cmd>.*)/
cmd = $~["cmd"].not_nil!
command_lines << cmd
puts "new command: #{cmd}"
when /^#.*$/
# simple comment
when /^[ \t]*$/
# empty line
else
raise "Cannot parse: #{line}"
end
end
iface_conf = InterfaceConfiguration.new(ifname)
iface_conf.up = up
iface_conf.description = description
iface_conf.mtu = mtu
iface_conf.main_ip_v4 = main_ip_v4
iface_conf.main_ip_v6 = main_ip_v6
aliasses.each do |ip|
if ip.ipv4?
iface_conf.aliasses_v4 << ip
else
iface_conf.aliasses_v6 << ip
end
end
iface_conf.wireless_networks = wireless_networks
iface_conf.dns = dns
iface_conf.command_lines = command_lines
iface_conf
end
end