$search
00001 #! /usr/bin/env python 00002 00003 import urllib, urllib2, base64 00004 import string, re 00005 import math 00006 00007 import roslib; roslib.load_manifest('linksys_access_point') 00008 import rospy 00009 00010 import dynamic_reconfigure.server 00011 from access_point_control.cfg import ApControlConfig 00012 from ieee80211_channels.channels import IEEE80211_Channels 00013 00014 class LinksysWRT310NApControl: 00015 00016 def __init__(self, hostname, username, password, interface): 00017 self.hostname = hostname 00018 self.username = username 00019 self.password = password 00020 self.interface = interface 00021 00022 self.passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm() 00023 self.passmgr.add_password(realm=None, 00024 uri="http://%s/"%(hostname), 00025 user=username, 00026 passwd=password) 00027 self.auth_handler = urllib2.HTTPBasicAuthHandler(self.passmgr) 00028 self.opener = urllib2.build_opener(self.auth_handler) 00029 urllib2.install_opener(self.opener) 00030 00031 self.current_config = {} 00032 self.get_current_config() 00033 00034 self.set_req_args = {} 00035 self.set_req_args["action"] = "Apply" 00036 self.set_req_args["submit_type"] = "" 00037 self.set_req_args["change_action"] = "" 00038 self.set_req_args["change_status"] = "0" 00039 self.set_req_args["commit"] = "1" 00040 self.set_req_args["nvset_cgi"] = "wireless" 00041 self.set_req_args["next_page"] = "" 00042 00043 print self.current_config 00044 00045 node_name = rospy.get_name() 00046 for param_name in self.current_config: 00047 param_full_name = node_name + "/" + param_name 00048 if not rospy.has_param(param_full_name): 00049 rospy.set_param(param_full_name, self.current_config[param_name]) 00050 00051 def mw_to_dbm(self, mw): 00052 return int(10 * math.log10(float(mw)) + 0.5) 00053 00054 def apply_request(self, args, page): 00055 req = urllib2.Request("http://%s/apply.cgi"%(self.hostname)) 00056 00057 req_args = dict(self.set_req_args) 00058 if args: 00059 req_args.update(args) 00060 req_args["submit_button"] = page 00061 req.add_data(urllib.urlencode(req_args)) 00062 00063 auth = self.passmgr.find_user_password(None, "http://%s/apply.cgi"%(self.hostname)) 00064 base64string = base64.encodestring("%s:%s" % auth)[:-1] 00065 req.add_header("Authorization", "Basic %s" % base64string) 00066 req.add_header("Referer", "http://%s/%s.asp"%(self.hostname, page)) 00067 00068 lines = urllib2.urlopen(req) 00069 html = lines.read() 00070 00071 if string.find(html, "Invalid Value") != -1: 00072 self.current_config['status'] = "FAIL" 00073 self.current_config['errmsg'] += "Invalid value for param in page %s"%(page) 00074 if string.find(html, "Settings are successful") == -1: 00075 self.current_config['status'] = "FAIL" 00076 self.current_config['errmsg'] += "The request was not successful" 00077 00078 def get_page_info(self, page): 00079 req = urllib2.Request("http://%s/%s.asp"%(self.hostname, page)) 00080 auth = self.passmgr.find_user_password(None, "http://%s/%s.asp"%(self.hostname, page)) 00081 base64string = base64.encodestring("%s:%s" % auth)[:-1] 00082 req.add_header("Authorization", "Basic %s" % base64string) 00083 00084 lines = urllib2.urlopen(req) 00085 html = lines.read() 00086 00087 return html 00088 00089 00090 def get_wireless_basic_params(self): 00091 # mode & ssid & channel 00092 html = self.get_page_info("Wireless_Basic") 00093 00094 mode_out = re.findall("(?s)name=\"%s_net_mode.*?_net_mode = '(.*?)'"%(self.interface), html) 00095 ssid_out = re.findall("value='(.*)' name=\"%s_ssid\""%(self.interface), html) 00096 channel_out = re.findall("var %s_channel = '(\d+)'"%(self.interface), html) 00097 00098 if (not mode_out) or (not ssid_out) or (not channel_out): 00099 raise Exception("Could not read interface " + self.interface + " mode or ssid or channel. " + 00100 "Please check that the interface is set to Manual mode and not Wi-Fi Protected Setup") 00101 00102 return mode_out[0], ssid_out[0], int(channel_out[0]) 00103 00104 def get_wireless_advanced_params(self): 00105 # bitrate 00106 html = self.get_page_info("Wireless_Advanced") 00107 00108 bitrate_out = re.findall("(?s)name=\"%s_rate.*?value=\"(\d+)\" selected"%(self.interface), html) 00109 00110 return int(bitrate_out[0]) 00111 00112 def get_wireless_security_params(self): 00113 # encryption_mode | encryption_pass 00114 html = self.get_page_info("WL_WPATable") 00115 00116 encryption_mode_out = re.findall("var security_mode2 = '(.*?)'", html) 00117 00118 if re.search("wpa2?_personal", encryption_mode_out[0]): 00119 encryption_mode = re.findall("(.*)_.*", encryption_mode_out[0])[0] 00120 encryption_pass = re.findall("name=%s_wpa_psk value='(.*?)'"%(self.interface), html)[0] 00121 elif re.search("wpa2?_enterprise", encryption_mode_out[0]): 00122 encryption_mode = re.findall("(.*)_.*", encryption_mode_out[0])[0] + "_enterprise" 00123 encryption_pass = re.findall("name=%s_radius_key value='(.*?)'"%(self.interface), html)[0] 00124 elif encryption_mode_out[0].find("wep") > -1: 00125 encryption_mode = ApControlConfig.ApControl_wep 00126 encryption_pass = re.findall("name=%s_key1 value='(.*?)'"%(self.interface), html)[0] 00127 else: 00128 encryption_mode = ApControlConfig.ApControl_open 00129 encryption_pass = "" 00130 00131 return encryption_mode, encryption_pass 00132 00133 def get_qos_params(self): 00134 # wmm 00135 html = self.get_page_info("QoS") 00136 00137 wmm_out = re.findall("value=\"(.*?)\" name=wl_wme checked", html) 00138 00139 if wmm_out[0] == "on": 00140 return True 00141 else: 00142 return False 00143 00144 def get_current_config(self): 00145 mode, ssid, channel = self.get_wireless_basic_params() 00146 band = IEEE80211_Channels.BAND_2400_MHz 00147 00148 self.current_config['ssid'] = ssid 00149 self.current_config['freq'] = float(IEEE80211_Channels.get_freq(channel, band)) 00150 if mode == "disabled": 00151 self.current_config['enabled'] = False 00152 else: 00153 self.current_config['enabled'] = True 00154 if mode in ["a-only", "b-only", "g-only"]: 00155 self.current_config['mode'] = mode[0] 00156 self.current_config['ieee80211n'] = False 00157 elif mode == "bg-mixed": 00158 self.current_config['mode'] = "g" 00159 self.current_config['ieee80211n'] = False 00160 elif mode == "mixed" and band == IEEE80211_Channels.BAND_2400_MHz: 00161 self.current_config['mode'] = "g" 00162 self.current_config['ieee80211n'] = True 00163 elif mode == "mixed" and band == IEEE80211_Channels.BAND_5000_MHz: 00164 self.current_config['mode'] = "a" 00165 self.current_config['ieee80211n'] = True 00166 elif mode == "n-only": 00167 self.current_config['ieee80211n'] = True 00168 else: 00169 self.current_config['mode'] = "unknown" 00170 self.current_config['ieee80211n'] = False 00171 00172 self.current_config['bitrate'] = self.get_wireless_advanced_params() 00173 00174 self.current_config['txpower_auto'] = True 00175 self.current_config['txpower'] = 0 00176 00177 self.current_config['encryption_mode'], self.current_config['encryption_pass'] = \ 00178 self.get_wireless_security_params() 00179 00180 self.current_config['wmm'] = self.get_qos_params() 00181 00182 def set_wireless_basic(self, ssid, if_mode, channel): 00183 args = {} 00184 if ssid is not None: 00185 args["%s_ssid"%(self.interface)] = ssid 00186 args["%s_net_mode"%(self.interface)] = if_mode 00187 if channel is not None: 00188 args["%s_schannel"%(self.interface)] = channel 00189 args["%s_channel"%(self.interface)] = channel 00190 print args 00191 self.apply_request(args, "Wireless_Basic") 00192 00193 def set_wireless_advanced(self, bitrate): 00194 args = {} 00195 args["%s_rate"%(self.interface)] = bitrate 00196 self.apply_request(args, "Wireless_Advanced") 00197 00198 def set_wireless_security(self, encryption_mode, encryption_pass): 00199 args = {} 00200 00201 if encryption_mode == ApControlConfig.ApControl_open: 00202 args["security_mode2"] = "disabled" 00203 elif encryption_mode == ApControlConfig.ApControl_wep: 00204 args["security_mode2"] = "wep" 00205 args["%s_WEP_key"%(self.interface)] = "" 00206 args["%s_wep"%(self.interface)] = "restricted" 00207 args["%s_key"%(self.interface)] = "1" 00208 args["%s_wep_bit"%(self.interface)] = "64" # or "128" 00209 args["%s_key1"%(self.interface)] = encryption_pass 00210 elif encryption_mode in [ApControlConfig.ApControl_wpa,\ 00211 ApControlConfig.ApControl_wpa2]: 00212 if encryption_mode == ApControlConfig.ApControl_wpa: 00213 args["security_mode2"] = "wpa_personal" 00214 # args["%s_crypto"%(self.interface)] = "tkip" 00215 elif encryption_mode == ApControlConfig.ApControl_wpa2: 00216 args["security_mode2"] = "wpa2_personal" 00217 # args["%s_crypto"%(self.interface)] = "tkip" 00218 args["%s_wpa_gtk_rekey"%(self.interface)] = "3600" 00219 args["%s_wpa_psk"%(self.interface)] = encryption_pass 00220 elif encryption_mode in [ApControlConfig.ApControl_wpa_enterprise,\ 00221 ApControlConfig.ApControl_wpa2_enterprise]: 00222 if encryption_mode == ApControlConfig.ApControl_wpa_enterprise: 00223 args["security_mode2"] = "wpa_enterprise" 00224 else: 00225 args["security_mode2"] = "wpa2_enterprise" 00226 args["%s_wpa_gtk_rekey"%(self.interface)] = "3600" 00227 args["%s_radius_key"%(self.interface)] = encryption_pass 00228 elif encryption_mode == ApControlConfig.ApControl_wpa_wpa2: 00229 self.current_config['status'] = "FAIL" 00230 self.current_config['errmsg'] += "WPA & WPA2 encryption mode not supported" 00231 return 00232 self.apply_request(args, "WL_WPATable") 00233 00234 def set_wmm(self, wmm): 00235 args = {} 00236 if wmm: 00237 args["wl_wme"] = "on" 00238 else: 00239 args["wl_wme"] = "off" 00240 self.apply_request(args, "QoS") 00241 00242 def compare_configs(self, requested_config, read_config): 00243 if requested_config['enabled'] != read_config['enabled']: 00244 self.current_config['status'] = "FAIL" 00245 self.current_config['errmsg'] += "Could not set enabled status, wrote %s, read %s"% \ 00246 (requested_config['enabled'], read_config['enabled']) 00247 return 00248 00249 if read_config['enabled']: 00250 for prop in ['mode', 'ssid', 'freq', 'ieee80211n', 'bitrate', 'wmm', 'encryption_mode']: 00251 if requested_config[prop] != read_config[prop]: 00252 self.current_config['status'] = "FAIL" 00253 self.current_config['errmsg'] += "Could not set %s, wrote %s, read %s"% \ 00254 (prop, str(requested_config[prop]), str(read_config[prop])) 00255 00256 if read_config['encryption_mode'] != "open": 00257 if requested_config['encryption_pass'] != read_config['encryption_pass']: 00258 self.current_config['status'] = "FAIL" 00259 self.current_config['errmsg'] += "Could not set encryption pass, wrote %s, read %s"% \ 00260 (requested_config['encryption_pass'], read_config['encryption_pass']) 00261 00262 def reconfigure(self, config, level): 00263 self.current_config['status'] = "OK" 00264 self.current_config['errmsg'] = "" 00265 00266 change = False 00267 # enabled, ssid, freq, mode, ieee80211n 00268 if not config['enabled']: 00269 if self.current_config['enabled']: 00270 self.set_wireless_basic(None, "disabled", None) 00271 change = True 00272 else: 00273 if config['enabled'] != self.current_config['enabled'] or \ 00274 config['ssid'] != self.current_config['ssid'] or \ 00275 config['freq'] != self.current_config['freq'] or \ 00276 config['mode'] != self.current_config['mode'] or \ 00277 config['ieee80211n'] != self.current_config['ieee80211n']: 00278 new_channel = IEEE80211_Channels.get_channel(config['freq']) 00279 if not config['enabled']: 00280 new_mode = "disabled" 00281 elif config["ieee80211n"]: 00282 new_mode = "mixed" 00283 else: 00284 new_mode = config['mode'] + "-only" 00285 self.set_wireless_basic(config['ssid'], new_mode, new_channel) 00286 change = True 00287 00288 # bitrate & txpower 00289 if config['bitrate'] != self.current_config['bitrate']: 00290 self.set_wireless_advanced(config["bitrate"]) 00291 change = True 00292 00293 for prop in [ 'txpower', 'txpower_auto' ]: 00294 if config[prop] != self.current_config[prop]: 00295 self.current_config['status'] = "FAIL" 00296 self.current_config['errmsg'] = "WRT310N does not support TX power control" 00297 00298 # wmm 00299 if config['wmm'] != self.current_config['wmm']: 00300 self.set_wmm(config['wmm']) 00301 change = True 00302 00303 # security params: 00304 if config['encryption_mode'] != self.current_config['encryption_mode'] or \ 00305 (config['encryption_mode'] != "open" and 00306 config['encryption_pass'] != self.current_config['encryption_pass']): 00307 self.set_wireless_security(config['encryption_mode'], config['encryption_pass']) 00308 change = True 00309 00310 # verify config 00311 if change: 00312 self.get_current_config() 00313 self.compare_configs(config, self.current_config) 00314 00315 if self.current_config['enabled']: 00316 return self.current_config 00317 else: 00318 config['status'] = self.current_config['status'] 00319 config['errmsg'] = self.current_config['errmsg'] 00320 config['enabled'] = False 00321 return config 00322 00323 if __name__ == "__main__": 00324 rospy.init_node("linksys_apcontrol_node") 00325 00326 ip = rospy.get_param("~ip", "192.168.1.1") 00327 user = rospy.get_param("~user", "") 00328 password = rospy.get_param("~password", "admin") 00329 interface = rospy.get_param("~interface", "wl") 00330 00331 ap = LinksysWRT310NApControl(ip, user, password, interface) 00332 00333 dynamic_reconfigure.server.Server(ApControlConfig, ap.reconfigure) 00334 00335 rospy.spin()