From ee118a497fe1520aec44787f4a3e1abfefb22a55 Mon Sep 17 00:00:00 2001
From: Philippe PITTOLI
Date: Wed, 30 Oct 2019 16:02:57 +0100
Subject: [PATCH] OpenBSD operating system is now autodetected
---
src/autodetect_environment.cr | 10 +++++
src/cli.cr | 36 ++++++++++-------
src/context.cr | 2 +
src/do.cr | 4 +-
src/network_commands.cr | 73 +++++++++++++++++++++++++++++------
5 files changed, 99 insertions(+), 26 deletions(-)
diff --git a/src/autodetect_environment.cr b/src/autodetect_environment.cr
index 014ca85..5a7a5ff 100644
--- a/src/autodetect_environment.cr
+++ b/src/autodetect_environment.cr
@@ -1,5 +1,15 @@
class Autodetect
+ def self.uname
+ os = nil : String?
+ Do.run("uname") do |p|
+ p.output.each_line do |line|
+ os = line
+ end
+ end
+
+ os
+ end
class_property print_autodetect : Bool = false
def self.which(cmd : String)
diff --git a/src/cli.cr b/src/cli.cr
index a758cc3..cdc100c 100644
--- a/src/cli.cr
+++ b/src/cli.cr
@@ -105,22 +105,32 @@ possible_wireless_configuration_cmds = {
"ifconfig" => NetworkCommands::IfconfigCommand
}
-key = Context.prefered_network_configuration_program
-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!]
+# first, check if we are on OpenBSD
+Context.os = Autodetect.uname
-key = Context.prefered_dhcp_client
-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 = Context.prefered_wireless_configuration_program
-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!]
+case Context.os
+when "Linux"
+ key = Context.prefered_network_configuration_program
+ 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 = Context.prefered_wireless_configuration_program
+ 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!]
+ key = Context.prefered_dhcp_client
+ key = possible_dhcp_clients.keys.find { |key| Autodetect.which(key) } if key.nil?
+ # should not crash if there is no dhcp client on the system
+ NetworkCommands.cmd_dhcp_client = possible_dhcp_clients[key] unless key.nil?
+ NetworkCommands.cmd_sysctl = NetworkCommands::SysctlCommand
+when "OpenBSD"
+ NetworkCommands.cmd_network_configuration = NetworkCommands::OpenBSDIfconfigCommand
+ NetworkCommands.cmd_wireless_configuration = NetworkCommands::OpenBSDIfconfigCommand
+ NetworkCommands.cmd_dhcp_client = NetworkCommands::OpenBSDDHClientCommand
+ NetworkCommands.cmd_sysctl = NetworkCommands::OpenBSDSysctlCommand
+end
files = Array(String).new
Dir.children("#{Context.root}/etc/").each do |f|
diff --git a/src/context.cr b/src/context.cr
index 503e420..d660cdb 100644
--- a/src/context.cr
+++ b/src/context.cr
@@ -2,6 +2,8 @@
class Context
class_property root : String = "/"
+ class_property os : String?
+
class_property keydir : String = "/etc/network/keydir"
class_property simulation = false
diff --git a/src/do.cr b/src/do.cr
index 6a2ed9c..f8db0a5 100644
--- a/src/do.cr
+++ b/src/do.cr
@@ -2,7 +2,7 @@
class Do < Process
class_property simulation = false
- def self.run(cmd : String, params : Array(String) = nil)
+ def self.run(cmd : String, params = [] of String)
if @@simulation
puts "simulation, do: #{cmd} #{params.join(" ")}"
Process::Status.new 0
@@ -11,7 +11,7 @@ class Do < Process
end
end
- def self.run(cmd : String, params : Array(String) = nil, &block : Process -> _)
+ def self.run(cmd : String, params = [] of String, &block : Process -> _)
if @@simulation
puts "simulation, do: #{cmd} #{params.join(" ")}"
Process::Status.new 0
diff --git a/src/network_commands.cr b/src/network_commands.cr
index 9c8cf3c..42c788d 100644
--- a/src/network_commands.cr
+++ b/src/network_commands.cr
@@ -1,12 +1,13 @@
# TODO: OpenBSD: no '-w' parameter for sysctl
-# TODO: OpenBSD: ifconfig scan
+# TODO: OpenBSD: test scanning for wireless AP with ifconfig
# TODO: Linux: description with ip-* command family
class NetworkCommands
class_property cmd_network_configuration : IfconfigCommand.class | IPCommand.class = IfconfigCommand
class_property cmd_wireless_configuration : IfconfigCommand.class | IWCommand.class | NotSetup.class = NotSetup
class_property cmd_dhcp_client : UDHCPCCommand.class | DHClientCommand.class | NotSetup.class = NotSetup
+ class_property cmd_sysctl : SysctlCommand.class | OpenBSDSysctlCommand.class | NotSetup.class = NotSetup
class DNS
property addresses : Array(String)
@@ -136,6 +137,12 @@ class NetworkCommands
end
end
+ class OpenBSDDHClientCommand < DHClientCommand
+ def self.dhcp6(ifname : String)
+ puts "TODO: dhcp6 on OpenBSD"
+ end
+ end
+
class IfconfigCommand
def self.interface_exists(name : String)
Do.run("ifconfig", [ name ]).success?
@@ -193,7 +200,36 @@ class NetworkCommands
# ifconfig also performs wireless configuration on some OSs
def self.scan(name : String)
- puts "TODO: (ifconfig) ifconfig ifname scan | grep SSID"
+ puts "TODO: (ifconfig) cannot get SSID with ifconfig on Linux"
+ end
+ end
+
+ class OpenBSDIfconfigCommand < IfconfigCommand
+ # get the available SSID
+ def self.scan(ifname : String) : Array(String)
+ ssids = Array(String).new
+
+ Do.run("ifconfig", [ ifname, "scan" ]) do |p|
+ p.output.each_line do |line|
+ ssid = /nwid (?[a-zA-Z0-9_-]+)/.match(line).try &.["ssid"]
+
+ unless ssid.nil?
+ ssids << ssid
+ end
+ end
+ end
+
+ if ssids.empty?
+ raise "(openbsd ifconfig) cannot get ssid list from #{ifname}"
+ end
+
+ ssids
+ end
+
+ def self.autoconfiguration(ifname : String)
+ unless Do.run("ifconfig", [ ifname, "inet6", "autoconf" ]).success?
+ raise "(openbsd ifconfig) Cannot set IPv6 autoconfiguration on #{ifname}"
+ end
end
end
@@ -246,9 +282,24 @@ class NetworkCommands
def self.description(name : String, description : String)
puts "TODO: (ip) setup description '#{description}' to interface #{name}"
- # unless Do.run("ip", [ "link", "set", "description", description, "dev", name ]).success?
- # raise "(ip) Cannot set description #{description} to #{name}"
- # end
+ end
+ end
+
+ class SysctlCommand
+ def self.autoconfiguration(ifname : String)
+ unless Do.run("sysctl", [ "-w", "net.ipv6.conf.#{ifname}.autoconf=1" ]).success?
+ raise "(sysctl) cannot set 'net.ipv6.conf.#{ifname}.autoconf=1'"
+ end
+
+ unless Do.run("sysctl", [ "-w", "net.ipv6.conf.#{ifname}.accept_ra=1" ]).success?
+ raise "(sysctl) cannot set 'net.ipv6.conf.#{ifname}.accept_ra=1'"
+ end
+ end
+ end
+
+ class OpenBSDSysctlCommand
+ def self.autoconfiguration(ifname : String)
+ OpenBSDIfconfigCommand.autoconfiguration ifname
end
end
@@ -309,13 +360,13 @@ class NetworkCommands
end
def self.autoconfiguration(ifname : String)
- # TODO: no '-w' option on openbsd
- unless Do.run("sysctl", [ "-w", "net.ipv6.conf.#{ifname}.autoconf=1" ]).success?
- raise "(sysctl) cannot set 'net.ipv6.conf.#{ifname}.autoconf=1'"
- end
+ cmd = @@cmd_sysctl
- unless Do.run("sysctl", [ "-w", "net.ipv6.conf.#{ifname}.accept_ra=1" ]).success?
- raise "(sysctl) cannot set 'net.ipv6.conf.#{ifname}.accept_ra=1'"
+ case cmd
+ when NotSetup.class
+ raise "cannot autoconfigure IPv6"
+ else
+ cmd.autoconfiguration ifname
end
end