#!/usr/bin/ruby -w =begin /*************************************************************************** * Copyright (C) 2008, Paul Lutus * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ =end # routines to convert between dotted strings <-> integer IPs def ip_to_int(ipstring) v = 0 ipstring.split(".").reverse.each do |s| v = (v << 8) + (s.to_i) end return v end def int_to_ip(v) array = [] n = 4 begin array << (v % 0x100).to_s v >>= 8 end while((n -= 1) > 0) return array.join(".") end # routine to convert string characters to int array # used in SSID encoding def string_to_int_array(s) return "[" + s.unpack("c*").join(",") + "]" end # check for the presence of a wireless NIC # users may want to add to the short list of applicable NIC types # or simply detect the word "wireless" and act accordingly def has_wireless(sys) data = `ssh #{sys} /sbin/lspci` [ "2200","3945","4965" ].each do |wi| if(data =~ /Wireless\s*#{wi}/i) return true end end return false end # get a list of local network host names and IPs # this could be replaced by any other way to # create a hostname/IP hash def get_ip_list(system_list) data = File.read("/etc/hosts") hash = {} system_list.each do |sys| addr = data.sub(%r{.*^([\d|\.]+)\s.*?#{sys}$.*}m,"\\1") hash[sys] = addr end return hash end # create a tagged type/value pair as a hash def type_value(type,value) return { "type" => type, "value" => value } end # various data set constructors def construct_ipv4_spec(ip,gateway,bits,dns_list,dns) hash = {} hash["addresses"] = type_value("list","[#{ip_to_int(ip)},#{bits},#{ip_to_int(gateway)}]") hash["dns"] = type_value("list",dns_list) if dns hash["method"] = type_value("string","manual") hash["name"] = type_value("string","ipv4") hash["routes"] = type_value("list","[]") return hash end def construct_connection_spec(id,autoconnect,type) hash = {} hash["autoconnect"] = type_value("booelan",autoconnect) hash["id"] = type_value("string",id) hash["type"] = type_value("string",type) hash["name"] = type_value("string","connection") return hash end def construct_wired_network_spec() hash = {} hash["duplex"] = type_value("string","full") hash["name"] = type_value("string","802-3-ethernet") return hash end def construct_wireless_network_spec(ssid,adhoc) hash = {} hash["mode"] = type_value("string",(adhoc)?"adhoc":"infrastructure") hash["name"] = type_value("string","802-11-wireless") hash["security"] = type_value("string","802-11-wireless-security") hash["ssid"] = type_value("list",string_to_int_array(ssid)) return hash end def construct_wireless_security_spec(adhoc) hash = {} if(adhoc) hash["key-mgmt"] = type_value("string","none") hash["auth_alg"] = type_value("string","open") else hash["key-mgmt"] = type_value("string","wpa-psk") end hash["name"] = type_value("string","802-11-wireless-security") return hash end def construct_wired_tree(sys,ip,gateway,bits,dns_list) hash = {} hash["ipv4"] = construct_ipv4_spec(ip,gateway,bits,dns_list,true) hash["connection"] = construct_connection_spec("Wired eth0",true,"802-3-ethernet") hash["802-3-ethernet"] = construct_wired_network_spec() return hash end def construct_wireless_tree(sys,ssid,ip,gateway,bits,dns_list,adhoc) hash = {} hash["ipv4"] = construct_ipv4_spec(ip,gateway,bits,dns_list,!adhoc) hash["connection"] = construct_connection_spec("Wireless " + ssid,false,"802-11-wireless") hash["802-11-wireless"] = construct_wireless_network_spec(ssid,adhoc) hash["802-11-wireless-security"] = construct_wireless_security_spec(adhoc) return hash end # debugging routines that print out the entire data tree def mktab(n) return "\t" * n end def show_tree(hash,tab = 0) hash.keys.sort.each do |key| if(hash[key].class == Hash) puts "#{mktab(tab)}#{key}" show_tree(hash[key],tab+1) else puts "#{mktab(tab)}#{key} = #{hash[key]}" end end end # build connection database def build_database(system_list,addr_hash,wap_list,dns_list,gateway,bits) hash = {} system_list.each do |sys| hash[sys] = {} ip = addr_hash[sys] hash[sys]["Wired_eth0"] = construct_wired_tree(sys,ip,gateway,bits,dns_list) if(has_wireless(sys)) wap_list.split("\s").each do |wap| hash[sys]["Wireless_" + wap] = construct_wireless_tree(sys,wap,ip,gateway,bits,dns_list,false) end hash[sys]["Wireless_pl-adhoc"] = construct_wireless_tree(sys,"pl-adhoc",ip,ip,bits,dns_list,true) end end return hash end # recursive tree traversal to build gconf definition paths def program_system_recursive(list,hash,path,n) hash.keys.sort.each do |key| if(n < 2) list = program_system_recursive(list,hash[key],path + "/" + key,n+1) else type,value = hash[key]["type"],hash[key]["value"] type_str = "--type #{type}" type_str += " --list-type int" if(type =~ /list/) arg = "gconftool-2 #{type_str} --set #{path}/#{key} '#{value}'" print "." list += "#{arg};" end end return list end # construct the paths and program the gconf database def program_network(tree,gcp) tree.keys.sort.each do |sys| # tell the user what's happening print "Programming #{sys} " # erase previous connection entries com_list = "gconftool-2 --recursive-unset #{gcp};" # create new entries as a data block com_list = program_system_recursive(com_list,tree[sys],gcp,0) puts "" # send the data block to the target machine `ssh #{sys} "#{com_list}"` end end # user actions print "Okay to program network with NetworkManager data (y/N):" reply = STDIN.readline.chomp if(reply != "y") exit 0 end # get a list of network host names # again, any way to create a list of hostnames # could be placed here system_list=`sysnames.sh`.chomp.split("\s") # create hash with hostname/IP key/value pairs addr_hash = get_ip_list(system_list) # local network specifications gateway = "192.168.0.96" dns1 = "xxx.xxx.xxx.xxx" dns2 = "xxx.xxx.xxx.xxx" dns3 = "xxx.xxx.xxx.xxx" bits = "24" dns_list = "[#{ip_to_int(dns1)},#{ip_to_int(dns2)},#{ip_to_int(dns3)}]" # wireless access point SSIDs wap_list= "pl-wireless-a pl-wireless-b pl-wireless-c" # build the tree of connection data data_tree = build_database(system_list,addr_hash,wap_list,dns_list,gateway,bits) # debug display, normally commented out # show_tree(data_tree) # base GConf path for NetworkManager gconf_path = "/system/networking/connections" # traverse the network, programming each machine program_network(data_tree,gconf_path) puts "Done."