-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
300 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
Network configuration and the concerto-netconfig script | ||
|
||
Since Concerto clients must support a wide variety of networking environments, | ||
and network settings should be configurable through a graphical user interface, | ||
a piece of software is needed to translate a "user-friendly" network | ||
configuration (wired/wireless, static/dynamic IP) into the detailed | ||
configuration files required by the operating system. This job is carried out | ||
by concerto-netconfig, a simple Ruby script to parse a set of network | ||
details in JSON format and generate the necessary configuration. | ||
|
||
The netconfig script considers a network connection as two pieces. | ||
First is the physical connection: what port do I use? what wireless network | ||
do I authenticate to and how? This is the connection method. Second is the | ||
type of addressing to use (static or dynamic, maybe someday stateless-v6 | ||
only :). This is called the addressing method. The various connection | ||
and addressing methods we need to support are implemented as Ruby classes. | ||
These classes are instantiated using parameters supplied in the JSON input. | ||
|
||
The connection method object returns the name of a physical interface to use, | ||
and potentially some extra lines for /etc/network/interfaces needed to make | ||
the connection (as in the case of wireless networks). Likewise, the addressing | ||
method returns the name of the (OS-level) addressing method to use (static, | ||
dhcp, or whatever else) and may also add some lines to the interface files | ||
if necessary (e.g. static address data). Each of these objects also has the | ||
opportunity to write additional configuration files if needed. It's unlikely, | ||
but conflict may arise between the connection and addressing methods with | ||
respect to a configuration file other than /etc/network/interfaces. There | ||
is currently no mechanism in place to avoid or resolve such conflict. | ||
|
||
Examples: | ||
An unsecured wireless connection with DHCP: | ||
{ | ||
"connection_method":"WirelessConnection", | ||
"connection_method_args": | ||
{ | ||
"ssid":"SomeNetwork" | ||
}, | ||
"addressing_method":"DHCPAddressing", | ||
"addressing_method_args":{} | ||
} | ||
|
||
A wired connection with a static address: | ||
{ | ||
"connection_method":"WiredConnection", | ||
"connection_method_args":{}, | ||
"addressing_method":"StaticAddressing", | ||
"addressing_method_args": | ||
{ | ||
"address":"192.168.0.99", | ||
"gateway":"192.168.0.1", | ||
"netmask":"255.255.255.0", | ||
"nameservers":["192.168.0.2","192.168.0.3"] | ||
} | ||
} | ||
|
||
I think this will map nicely onto a web-based UI, basically we're just | ||
serializing a couple of forms into JSON. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/bin/sh | ||
|
||
gem install json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#!/bin/sh | ||
### BEGIN INIT INFO | ||
# Provides: concerto-netconfig | ||
# Required-Start: udev | ||
# Required-Stop: | ||
# Should-Start: | ||
# Should-Stop: | ||
# X-Start-Before: networking | ||
# Default-Start: S | ||
# Default-Stop: | ||
# Short-Description: Create Debian network config files | ||
# Description: Parse user configuration data and generate Debian | ||
# network config files as needed | ||
### END INIT INFO | ||
|
||
NAME=concerto-netconfig | ||
NETCONFIG=/usr/local/bin/concerto-netconfig | ||
|
||
test -x $NETCONFIG || exit 0 | ||
|
||
. /lib/lsb/init-functions | ||
|
||
run_netconfig() | ||
{ | ||
log_daemon_msg "Creating network configuration files" "$NAME" | ||
$NETCONFIG < /etc/netconfig.json > /etc/network/interfaces | ||
log_end_msg $? | ||
} | ||
|
||
case "$1" in | ||
start) | ||
run_netconfig | ||
;; | ||
stop) | ||
# do nothing | ||
;; | ||
*) | ||
echo "Usage: /etc/init.d/$NAME [start|stop]" | ||
exit 2 | ||
;; | ||
esac |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"connection_method":"WiredConnection", | ||
"connection_method_args":{}, | ||
"addressing_method":"DHCPAddressing", | ||
"addressing_method_args":{} | ||
} |
190 changes: 190 additions & 0 deletions
190
config/includes.chroot/usr/local/bin/concerto-netconfig
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
require 'rubygems' | ||
require 'json' | ||
|
||
def read_sysfs(iface, var) | ||
# Read a sysfs variable (/sys/class/net/iface/var). | ||
path = "/sys/class/net/#{iface}/#{var}" | ||
IO.read(path).chomp | ||
end | ||
|
||
class WiredConnection | ||
def initialize(args) | ||
if args['interface_name'] | ||
@ifname = args['interface_name'] | ||
end | ||
end | ||
|
||
# Write any necessary auxiliary configuration files | ||
def write_configs | ||
# We don't need any. | ||
end | ||
|
||
# Return the name of the interface to be configured. | ||
def interface_name | ||
if @ifname | ||
# the user has specified an interface to use | ||
@ifname | ||
else | ||
# scan for the first wired interface that has media | ||
scan_interfaces | ||
end | ||
end | ||
|
||
# Return any additional lines needed in the interfaces file | ||
# e.g. referencing WPA config files... | ||
def interfaces_lines | ||
# Nothing special needed for wired connections. | ||
[] | ||
end | ||
|
||
private | ||
def wired_interfaces | ||
# This is somewhat Linux specific, and may not be all encompassing. | ||
devices = Dir.glob('/sys/class/net/eth*') | ||
devices.map { |d| File.basename(d) } | ||
end | ||
|
||
def scan_interfaces | ||
wired_interfaces.each do |iface| | ||
# bring up interface if it was down | ||
if (read_sysfs(iface, 'operstate') != 'up') | ||
system "ifconfig #{iface} up" | ||
sleep 0.1 | ||
end | ||
# check if cable is connected | ||
carrier = read_sysfs(iface, 'carrier') | ||
# bring interface back down | ||
system "ifconfig #{iface} down" | ||
|
||
if carrier == '1' | ||
return iface | ||
end | ||
end | ||
|
||
# if we get here no interface was found with a cable attached | ||
# default to eth0 and hope for the best | ||
STDERR.puts "warning: no suitable interface found, defaulting to eth0" | ||
'eth0' | ||
end | ||
end | ||
|
||
class WirelessConnection | ||
def initialize(args) | ||
@ssid = args['ssid'] | ||
@force_iface = args['iface'] if args['iface'] | ||
@wpa_config_file = '/tmp/wpa_supplicant.concerto.conf' | ||
end | ||
|
||
def interface_name | ||
# If the user has requested a specific interface, use it. | ||
# Otherwise, just pick the first wlan interface, assuming | ||
# it works and all wlan interfaces have approximately equal | ||
# reception. When this assumption is wrong the user must force. | ||
@force_iface || wireless_interfaces[0] | ||
end | ||
|
||
def write_configs | ||
# Write a wpa_supplicant.conf file for an unsecured network. | ||
File.open(@wpa_config_file, 'w') do |wpaconf| | ||
# long lines, sorry! | ||
wpaconf.puts "ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=wheel" | ||
wpaconf.puts "network={" | ||
wpaconf.puts "ssid=\"#{@ssid}\"" | ||
wpaconf.puts "scan_ssid=1" | ||
wpaconf.puts "key_mgmt=NONE" | ||
wpaconf.puts "}" | ||
end | ||
end | ||
|
||
def interfaces_lines | ||
["wpa-conf #{@wpa_config_file}"] | ||
end | ||
|
||
private | ||
|
||
def wireless_interfaces | ||
# This is somewhat Linux specific, and may not be all encompassing. | ||
devices = Dir.glob('/sys/class/net/{ath,wlan}*') | ||
devices.map { |d| File.basename(d) } | ||
end | ||
end | ||
|
||
class StaticAddressing | ||
def initialize(args) | ||
@nameservers = args['nameservers'] | ||
@addr = args['address'] | ||
@mask = args['netmask'] | ||
@gateway = args['gateway'] | ||
end | ||
|
||
def addressing_type | ||
'static' | ||
end | ||
|
||
def interfaces_lines | ||
[ | ||
"address #{@addr}", | ||
"netmask #{@mask}", | ||
"gateway #{@gateway}" | ||
] | ||
end | ||
|
||
def write_configs | ||
File.open('/etc/resolv.conf','w') do |resolvconf| | ||
@nameservers.each do |nameserver| | ||
resolvconf.puts("nameserver #{nameserver}"); | ||
end | ||
end | ||
end | ||
end | ||
|
||
class DHCPAddressing | ||
def initialize(args) | ||
# we accept no args | ||
end | ||
|
||
def addressing_type | ||
'dhcp' | ||
end | ||
|
||
def interfaces_lines | ||
# DHCP needs no additional interfaces args from the addressing side | ||
[] | ||
end | ||
|
||
def write_configs | ||
# dhclient will write our resolv.conf so we do not need to do anything | ||
end | ||
end | ||
|
||
input = STDIN.read | ||
args = JSON.parse(input) | ||
|
||
connection_method_class = Object.const_get(args['connection_method']) | ||
addressing_method_class = Object.const_get(args['addressing_method']) | ||
|
||
connection_method = connection_method_class.new( | ||
args['connection_method_args'] | ||
) | ||
|
||
addressing_method = addressing_method_class.new( | ||
args['addressing_method_args'] | ||
) | ||
|
||
ifname = connection_method.interface_name | ||
|
||
puts "# Concerto Live network configuration" | ||
puts "# Generated by netconfig.rb" | ||
puts "# Changes will be lost on reboot" | ||
puts "auto #{ifname}" | ||
puts "iface #{ifname} inet #{addressing_method.addressing_type}" | ||
|
||
addressing_method.interfaces_lines.each do |line| | ||
puts "\t#{line}" | ||
end | ||
|
||
connection_method.interfaces_lines.each do |line| | ||
puts "\t#{line}" | ||
end | ||
|
||
connection_method.write_configs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,3 +14,6 @@ firmware-libertas | |
firmware-ralink | ||
firmware-realtek | ||
|
||
ruby | ||
rubygems | ||
vim |