8 from conf
import config
9 from output
import logger
22 if not system
.as_root():
23 logger
.err("Must run as root", log
=False)
29 # make sure config file is protected from user access
30 mode
= os
.stat(config
.configfile
)[stat
.ST_MODE
]
31 if mode
& (stat
.S_IRWXG | stat
.S_IRWXO
):
33 "Config file %s should only be accessible by root (mode is: %s)"\
34 % (config
.configfile
, oct(stat
.S_IMODE(mode
))))
38 except Exception, msg
:
44 logger
.display("Checking for missing tools...", log
=False)
45 for cmd_name
in config
.tools
:
46 var_name
= cmd_name
.replace("-", "_")
47 path
= config
.__dict
__[var_name
]
48 if os
.path
.isabs(path
):
49 logger
.display(" [ok] %s" % path
, log
=False)
51 logger
.display(" [missing] %s" % cmd_name
, log
=False)
56 logger
.await("Checking for ip")
57 ips
= [(x
, y
) for (x
, y
) in
58 [(i
.interface
, network
.has_ip(i
.interface
))
59 for i
in config
.interfaces
]
60 if y
!= None] # (iface, ip) pairs where ip is set
63 reduce(lambda x
, y
: "%s %s" % (x
, y
),
64 map(lambda (x
, y
): "%s (%s)" % (y
, x
), ips
)))
71 logger
.await("Selecting preferred network medium")
72 iface
= config
.interfaces
.get_top()
73 logger
.result(iface
.medium
)
74 if iface
.medium
== "wired": return True
77 def check_wired_link():
78 logger
.await("Checking for wired link")
79 ifaces
= config
.interfaces
.get_all(pred
=lambda x
: x
.medium
== "wired")
80 connected
= [network
.wire_connected(i
.interface
) for i
in ifaces \
81 if network
.wire_connected(i
.interface
)]
83 logger
.result(reduce(lambda x
,y
: "%s %s" % (x
,y
),
84 map(lambda x
: "%s" % x
, connected
)))
87 logger
.result("none, use wireless")
90 def request_ip(iface
, net
=None, tries
=3):
93 n
= "%s (from %s)" % (n
, net
.essid
)
94 if not network
.setup_wifi(iface
.interface
, net
):
95 logger
.err("Failed to associate with access point for network %s"\
100 while attempt
< tries
:
102 logger
.await("(%d/%d) Request ip on %s" % (attempt
, tries
, n
))
104 start_time
= time
.time()
105 ip
= network
.request_ip(iface
.interface
)
106 stop_time
= time
.time()
107 duration
= stop_time
- start_time
110 logger
.result("%s (%ds)" % (ip
, duration
))
112 else: logger
.result("failed (%ds)" % duration
)
115 def scan_wifi_networks(iface
, wardrive
=None):
116 logger
.await("Scan for wireless networks")
117 nets
= network
.read_scan(network
.normal_scan(iface
.interface
))
118 nets
= config
.networks
.merge(nets
, 'essid')
119 f
= lambda x
: x
.priority
!= None and x
.signal
!= None
121 f
= lambda x
: x
.signal
!= None and x
.priority
== None\
122 and x
.encrypted
== None and x
.essid
!= "<hidden>"
123 nets
= nets
.sort(sort_key
='quality').get_all(pred
=f
)
125 logger
.result(reduce(lambda x
,y
: "%s %s" % (x
,y
),
126 map(lambda x
: "%s" % x
.essid
, nets
[:3])))
128 else: logger
.result("none")
131 def display_live_networks(nets
, field
=None, column
=None):
133 return "No networks detected"
135 keys
= ['bssid', 'essid', 'channel', 'bitrate', 'sec', 'signal', 'seen']
136 width
= 19; mw
= 6; sp
= 2 # width: max width mw : min width sp : separate
139 nets
= nets
.sort(sort_key
=field
)
140 elif column
and 0 < column
<= len(keys
):
141 nets
= nets
.sort(sort_key
=keys
[column
-1])
143 nets
= nets
.sort(sort_key
='signal')
145 def col_len(dcts
, key
):
146 "figure out column length to assign to fields based on content length"
149 # ugly special case for seen field
151 l
.append(len('seen'))
156 l
.append(len(val
)+sp
)
160 ws
= [max(min(max(col_len(nets
, k
)), width
), mw
) for k
in keys
]
162 def format_timespan(span
):
164 units
= ['s', 'm', 'h', 'd', 'w']
185 span
= int(round(span
))
186 return "%s%s%s" % (prefix
, span
, units
[unit_id
])
189 for (i
, key
) in enumerate(keys
):
190 s
+= ("%s" % key
[:ws
[i
]-sp
]).ljust(ws
[i
])
193 for (i
, key
) in enumerate(keys
):
196 # ugly special case for seen field
198 val
= "%s" % format_timespan(time
.time()-val
)
201 s
+= (val
[:ws
[i
]-sp
]).ljust(ws
[i
])
205 return s
+ "%d network(s) found" % len(nets
)
208 def curse(iface
, timeout
):
210 logger
.mute(quiet
=True)
212 scr
= curses
.initscr()
219 def curses_shutdown(scr
):
225 logger
.unmute(quiet
=True)
227 def display_list(scr
, header
, status
, list_s
):
229 ss
= list_s
.split("\n")
232 scr
.addstr(header
+ " / Ctrl+C to exit\n")
234 scr
.addstr(status
+ "\n")
235 scr
.addstr("\n"+ss
[0]+"\n", curses
.A_REVERSE
)
237 # add one by one until possible exception is thrown
238 # when the list is too long
245 def get_status(timeout
, t
):
247 return "-> scanning for %ds (-%ds)" % (timeout
, t
-time
.time())
251 t
= time
.time()+timeout
252 header
= "%s scanning for wireless networks (%s)" % \
253 (config
.program_name
, iface
)
254 status
= get_status(timeout
, t
)
258 display_list(scr
, header
, status
, display_live_networks(None))
261 status
= get_status(timeout
, t
)
263 if t
< time
.time(): break
265 scan_data
= network
.single_scan(iface
)
266 nets
= network
.read_scan(scan_data
)
267 list_s
= display_live_networks(nets
)
269 display_list(scr
, header
, status
, list_s
)
273 except KeyboardInterrupt:
277 traceback
.print_stack()
278 traceback
.print_exc()