tochka 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 40dc9ab742d3ff31b82292795a7b905782210488
4
+ data.tar.gz: 771f090404e1262e0f0e174ac961e60f0cf099f9
5
+ SHA512:
6
+ metadata.gz: 4b6b2639eecb4a961fa4de138a456b71d0f03167e67549a37ed8e4a3a3697b85288295923ac1f24207e56e50d11005d1f566f654a98f04f41f4bd47f16d970ad
7
+ data.tar.gz: a7a73e80b4536856fdb045d4ab911f598a1f5acf28db7ea5a5676053970bb5d171ceecd401b88ae2909313fc8c6d3b54eebd72ea8855a0babe9d46b2b8df7dd4
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ before_install: gem install bundler -v 1.10.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in tochka.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # Tochka
2
+
3
+ "Tochka" is softwares to build Wi-Fi frame capturing box with Raspberry Pi + PiTFT.
4
+
5
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/tochka`. To experiment with that code, run `bin/console` for an interactive prompt.
6
+
7
+ TODO: Delete this and the text above, and describe your gem
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'tochka'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install tochka
24
+
25
+ ### install init.d scripts
26
+
27
+ 1. copy ext/tochkad, ext/tochka-miniui into /etc/init.d
28
+ 2. do chmod +x onto both
29
+ 3. do 'update-rc.d <name> defaults' to both
30
+
31
+ ## Usage
32
+
33
+ ### PiTFT UI
34
+
35
+ Tochka provides with user interface to start/stop capture on top of PiTFT.
36
+
37
+ ![tochka-miniui](http://amber.glenda9.org/~enukane/images/tochka-miniui.jpg)
38
+
39
+ TOUCHSCREEN is currently of NO USE. Just make yourself happy with moving cursor :).
40
+ Use buttons instead: 4 buttons are "START", "STOP", "MODE1", "MODE2".
41
+
42
+ ### Starting capture
43
+
44
+ Press "START" button and "State" turns into "running"
45
+
46
+ ### Stop capture
47
+
48
+ Press "STOP", "MODE1" and "MODE2" buttons in an order. Check that "stop count" is now 3.
49
+ Then press "STOP" button again will turn off capturing. The "State" will turn into "stop".
50
+
51
+ ### collecting captured data
52
+
53
+ Captured data (pcapng files) are stored in /cap directory
54
+
55
+ ## Development
56
+
57
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. Run `bundle exec tochka` to use the gem in this directory, ignoring other installed copies of this gem.
58
+
59
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
60
+
61
+ ## Contributing
62
+
63
+ Bug reports and pull requests are welcome on GitHub at https://github.com/enukane/tochka.
64
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "tochka"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
data/exe/tochka-miniui ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "tochka"
4
+ require "optparse"
5
+
6
+ opt = OptionParser.new
7
+ OPTS=Tochka::TochkaMiniUI.default_options
8
+
9
+ opt.on('-f', "--font [FONT_PATH]", "font to use (default: #{Tochka::TochkaMiniUI.default_options[:font_path]})") {|v|
10
+ OPTS[:font_path] = v
11
+ }
12
+
13
+ opt.on('-l', "--log-file [LOG_FILE=STDOUT]",
14
+ "log output file (accepts 'STDOUT', 'STDERR')") {|v|
15
+ OPTS[:log_file] = v
16
+ }
17
+
18
+ (class<<self;self;end).module_eval do
19
+ define_method(:usage) do |msg|
20
+ puts opt.to_s
21
+ puts "error: #{msg}" if msg
22
+ exit 1
23
+ end
24
+ end
25
+
26
+ begin
27
+ res = opt.parse(ARGV)
28
+ if res.length != 0
29
+ usage nil
30
+ end
31
+ rescue
32
+ usage $!.to_s
33
+ end
34
+
35
+ $log = Log.new(:output => OPTS[:log_file])
36
+ Tochka::TochkaMiniUI.new(OPTS[:font_path]).run
data/exe/tochkad ADDED
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "tochka"
4
+ require "optparse"
5
+
6
+ opt = OptionParser.new
7
+ OPTS=Tochka::Daemon.default_options
8
+
9
+ opt.on('-i', "--interface [IFNAME=#{Tochka::Daemon::DEFAULT_IFNAME}]",
10
+ "interface to capture") {|v|
11
+ OPTS[:ifname] = v || Tochka::Daemon::DEFAULT_IFNAME
12
+ }
13
+
14
+ opt.on('-c', "--cap-dir [CAP_PATH=#{Tochka::Daemon::DEFAULT_CAP_PATH}]",
15
+ "capture directory") {|v|
16
+ OPTS[:cap_path] = v || TOchka::Daemon::DEFAULT_CAP_PATH
17
+ }
18
+
19
+ opt.on('-l', "--log-file [LOG_FILE=STDOUT]",
20
+ "log output file (accepts 'STDOUT', 'STDERR')") {|v|
21
+ OPTS[:log_file] = v
22
+ }
23
+
24
+ (class<<self;self;end).module_eval do
25
+ define_method(:usage) do |msg|
26
+ puts opt.to_s
27
+ puts "error: #{msg}" if msg
28
+ exit 1
29
+ end
30
+ end
31
+
32
+ begin
33
+ rest = opt.parse(ARGV)
34
+ if rest.length != 0
35
+ usage nil
36
+ end
37
+ rescue
38
+ usage $!.to_s
39
+ end
40
+
41
+ # check root priviledge
42
+
43
+ $log = Log.new(:output => OPTS[:log_file])
44
+ Tochka::Daemon.new(OPTS[:ifname], OPTS[:cap_path]).run
data/ext/tochka-miniui ADDED
@@ -0,0 +1,62 @@
1
+ #!/bin/sh
2
+
3
+ ### BEGIN INIT INFO
4
+ # Provides: tochka-mini
5
+ # Required-Start: $remote_fs $syslog
6
+ # Required-Stop: $remote_fs $syslog
7
+ # Default-Start: 2 3 4 5
8
+ # Default-Stop: 0 1 6
9
+ # Short-Description: Put a short description of the service here
10
+ # Description: Put a long description of the service here
11
+ ### END INIT INFO
12
+
13
+ # Change the next 3 lines to suit where you install your script and what you want to call it
14
+ DIR=/usr/local/bin/
15
+ DAEMON=$DIR/tochka-miniui
16
+ DAEMON_NAME=tochka-miniui
17
+
18
+ # Add any command line options for your daemon here
19
+ DAEMON_OPTS="-l /tmp/hoge"
20
+
21
+ # This next line determines what user the script runs as.
22
+ # Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python.
23
+ DAEMON_USER=root
24
+
25
+ # The process ID of the script when it runs is stored here:
26
+ PIDFILE=/var/run/$DAEMON_NAME.pid
27
+
28
+ . /lib/lsb/init-functions
29
+
30
+ do_start () {
31
+ log_daemon_msg "Starting system $DAEMON_NAME daemon"
32
+ start-stop-daemon --start --background --pidfile $PIDFILE --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS
33
+ log_end_msg $?
34
+ }
35
+ do_stop () {
36
+ log_daemon_msg "Stopping system $DAEMON_NAME daemon"
37
+ start-stop-daemon --stop --pidfile $PIDFILE --retry 10
38
+ log_end_msg $?
39
+ }
40
+
41
+ case "$1" in
42
+
43
+ start|stop)
44
+ do_${1}
45
+ ;;
46
+
47
+ restart|reload|force-reload)
48
+ do_stop
49
+ do_start
50
+ ;;
51
+
52
+ status)
53
+ status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $?
54
+ ;;
55
+
56
+ *)
57
+ echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}"
58
+ exit 1
59
+ ;;
60
+
61
+ esac
62
+ exit 0
data/ext/tochkad ADDED
@@ -0,0 +1,62 @@
1
+ #!/bin/sh
2
+
3
+ ### BEGIN INIT INFO
4
+ # Provides: tochkad
5
+ # Required-Start: $remote_fs $syslog
6
+ # Required-Stop: $remote_fs $syslog
7
+ # Default-Start: 2 3 4 5
8
+ # Default-Stop: 0 1 6
9
+ # Short-Description: Put a short description of the service here
10
+ # Description: Put a long description of the service here
11
+ ### END INIT INFO
12
+
13
+ # Change the next 3 lines to suit where you install your script and what you want to call it
14
+ DIR=/usr/local/bin/
15
+ DAEMON=$DIR/tochkad
16
+ DAEMON_NAME=tochkad
17
+
18
+ # Add any command line options for your daemon here
19
+ DAEMON_OPTS=""
20
+
21
+ # This next line determines what user the script runs as.
22
+ # Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python.
23
+ DAEMON_USER=root
24
+
25
+ # The process ID of the script when it runs is stored here:
26
+ PIDFILE=/var/run/$DAEMON_NAME.pid
27
+
28
+ . /lib/lsb/init-functions
29
+
30
+ do_start () {
31
+ log_daemon_msg "Starting system $DAEMON_NAME daemon"
32
+ start-stop-daemon --start --background --pidfile $PIDFILE --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS
33
+ log_end_msg $?
34
+ }
35
+ do_stop () {
36
+ log_daemon_msg "Stopping system $DAEMON_NAME daemon"
37
+ start-stop-daemon --stop --pidfile $PIDFILE --retry 10
38
+ log_end_msg $?
39
+ }
40
+
41
+ case "$1" in
42
+
43
+ start|stop)
44
+ do_${1}
45
+ ;;
46
+
47
+ restart|reload|force-reload)
48
+ do_stop
49
+ do_start
50
+ ;;
51
+
52
+ status)
53
+ status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $?
54
+ ;;
55
+
56
+ *)
57
+ echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}"
58
+ exit 1
59
+ ;;
60
+
61
+ esac
62
+ exit 0
@@ -0,0 +1,116 @@
1
+ module Tochka
2
+ require "json"
3
+ require "socket"
4
+ require "tochka/log"
5
+
6
+ class Agent
7
+ attr_reader :state, :file_name, :file_size, :duration, :current_channel, :frame_count, :channel_walk, :utilization, :utilization_channel
8
+ SOCKPATH="/var/run/captured.sock"
9
+
10
+ CMD_GET_STATUS="get_status"
11
+ CMD_START_CAPTURE="start_capture"
12
+ CMD_STOP_CAPTURE="stop_capture"
13
+
14
+ STATE_INIT="init"
15
+ STATE_RUNNING="running"
16
+ STATE_STOP="stop"
17
+ STATE_UNKNOWN="unknown"
18
+
19
+ def initialize
20
+ @state = STATE_INIT
21
+ @file_name = "<None>"
22
+ @file_size = 0
23
+ @duration = 0
24
+ @current_channel = 0
25
+ @channel_walk = 0
26
+ @frame_count = 0
27
+ @utilization = 0
28
+ @utilization_channel = 0
29
+ end
30
+
31
+ def get_status
32
+ resp = do_rpc(get_msg(CMD_GET_STATUS))
33
+ if resp["state"] != nil
34
+ update_state(resp)
35
+ return resp
36
+ end
37
+
38
+ # not responded?
39
+ @state = STATE_UNKNOWN
40
+ return {}
41
+ rescue => e
42
+ $log.err("agent detected unknown error in get_status (#{e})")
43
+ return {}
44
+ end
45
+
46
+ def start_capture
47
+ $log.info("requesting start_capture")
48
+ resp = do_rpc(get_msg(CMD_START_CAPTURE))
49
+ resp = get_status()
50
+ if resp["state"] == STATE_RUNNING
51
+ update_state(resp)
52
+ return true
53
+ end
54
+
55
+ # not responded or failed
56
+ @state = STATE_UNKNOWN
57
+ return false
58
+ rescue => e
59
+ $log.err("agent detected unknown error in start_capture (#{e})")
60
+ return false
61
+ end
62
+
63
+ def stop_capture
64
+ $log.info("requesting stop_capture")
65
+ resp = do_rpc(get_msg(CMD_STOP_CAPTURE))
66
+ resp = get_status()
67
+ if resp["state"] == STATE_STOP
68
+ update_state(resp)
69
+ return true
70
+ end
71
+
72
+ return false
73
+ rescue => e
74
+ $log.err("agent detected unknown error in stop_capture (#{e})")
75
+ return false
76
+ end
77
+
78
+ private
79
+ def get_msg type=CMD_GET_STATUS
80
+ JSON.dump(
81
+ {"command"=> type}
82
+ )
83
+ end
84
+
85
+ def do_rpc req_json_msg
86
+ data = {}
87
+ UNIXSocket.open(SOCKPATH) do |sock|
88
+ sock.write(req_json_msg+"\n")
89
+ data = sock.gets
90
+ end
91
+ return JSON.parse(data)
92
+ rescue Errno::EPIPE => e
93
+ $log.err("RPC failed in do_rpc (EPIPE)")
94
+ return {}
95
+ rescue JSON::ParserError => e0
96
+ $log.err("RPC failed in do_rpc (JSON parser error)")
97
+ return {}
98
+ rescue Errno::ENOENT => e1
99
+ $log.err("RPC failed in do_rpc (no sock file, #{e1})")
100
+ return {}
101
+ end
102
+
103
+ def update_state msg
104
+ @state = msg["state"]
105
+ @file_name = msg["file_name"]
106
+ @file_size = msg["file_size"]
107
+ @duration = msg["duration"]
108
+ @current_channel = msg["current_channel"]
109
+ @channel_walk = msg["channel_walk"]
110
+ @frame_count = msg["frame_count"]
111
+ @utilization = msg["utilization"]
112
+ @utilization_channel = msg["utilization_channel"]
113
+ end
114
+ end
115
+
116
+ end
@@ -0,0 +1,109 @@
1
+ module Tochka
2
+ class Athsurvey
3
+ FREQ2CHAN = {
4
+ 0 => 0, # why radiotap.channel.freq can be 0?
5
+ # 2.4GHz
6
+ 2412 => 1,
7
+ 2417 => 2,
8
+ 2422 => 3,
9
+ 2427 => 4,
10
+ 2432 => 5,
11
+ 2437 => 6,
12
+ 2442 => 7,
13
+ 2447 => 8,
14
+ 2452 => 9,
15
+ 2457 => 10,
16
+ 2462 => 11,
17
+ 2467 => 12,
18
+ 2472 => 13,
19
+ 2484 => 14,
20
+
21
+ # japan client only
22
+ 5170 => 34,
23
+ 5190 => 38,
24
+ 5210 => 42,
25
+ 5230 => 46,
26
+
27
+ # W52
28
+ 5180 => 36,
29
+ 5200 => 40,
30
+ 5220 => 44,
31
+ 5240 => 48,
32
+
33
+ # W53
34
+ 5260 => 52,
35
+ 5280 => 56,
36
+ 5300 => 60,
37
+ 5320 => 64,
38
+
39
+ # W56
40
+ 5500 => 100,
41
+ 5520 => 104,
42
+ 5540 => 108,
43
+ 5560 => 112,
44
+ 5580 => 116,
45
+ 5600 => 120,
46
+ 5620 => 124,
47
+ 5640 => 128,
48
+ 5660 => 132,
49
+ 5680 => 136,
50
+ 5700 => 140,
51
+ 5745 => 149,
52
+ 5765 => 153,
53
+ 5785 => 157,
54
+ 5805 => 161,
55
+ 5825 => 165,
56
+
57
+
58
+ # 802.11j
59
+ 4920 => 184,
60
+ 4940 => 188,
61
+ 4960 => 192,
62
+ 4980 => 194,
63
+ }
64
+
65
+ REG_FREQ=/^\s*frequency:\s+(\d+) /
66
+ REG_ACTIVE=/^\s*channel active time:\s+(\d+) (|m)s$/
67
+ REG_BUSY=/^\s*channel busy time:\s+(\d+) (|m)s$/
68
+
69
+ def initialize ifname
70
+ @ifname = ifname
71
+ end
72
+
73
+ def current_data
74
+ str = get_survey_dump()
75
+ active = 0
76
+ busy = 0
77
+ channel = 0
78
+
79
+ str.split("\n").map{|line| line.strip}.each do |line|
80
+ case line
81
+ when REG_FREQ
82
+ channel = FREQ2CHAN[$1.to_i]
83
+ when REG_ACTIVE
84
+ active = $1.to_i
85
+ active *= 1000 if $2 != "m"
86
+ when REG_BUSY
87
+ busy = $1.to_i
88
+ busy *= 1000 if $2 != "m"
89
+ end
90
+ end
91
+ return [0, 0, 0, 0] if active == 0
92
+
93
+ return [channel, active, busy, fto2f(busy.to_f * 100 / active.to_f) ]
94
+ end
95
+
96
+ def get_survey_dump
97
+ return `iw #{@ifname} survey dump | grep -A 4 "in use"`
98
+ end
99
+
100
+ def fto2f f
101
+ return (f * 100).to_i.to_f / 100
102
+ end
103
+ end
104
+ end
105
+
106
+ if __FILE__ == $0
107
+ aths = Tochka::Athsurvey.new("wlan0")
108
+ p aths.current_data
109
+ end
@@ -0,0 +1,39 @@
1
+ module Tochka
2
+ require "socket"
3
+
4
+ class Channel
5
+ def initialize recv_handler, sock_data
6
+ end
7
+
8
+ def start
9
+ end
10
+
11
+ def stop
12
+ end
13
+ end
14
+
15
+ class UnixSocketChannel < Channel
16
+ SOCKPATH="/var/run/captured.sock"
17
+
18
+ def initialize recv_handler, sock_path=SOCKPATH
19
+ @recv_handler = recv_handler
20
+ @sock_path = sock_path || SOCKPATH
21
+ @th = nil
22
+ end
23
+
24
+ def start
25
+ @th = Thread.new do
26
+ Socket.unix_server_loop(@sock_path) do |sock, addr|
27
+ data = sock.gets
28
+ resp = @recv_handler.call(data)
29
+ sock.write(resp+"\n")
30
+ end
31
+ end
32
+ end
33
+
34
+ def stop
35
+ @th.kill
36
+ end
37
+ end
38
+
39
+ end