sns_utils 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6a569b79f304d0060cd3d6c21898000777995042
4
+ data.tar.gz: b15db537d09f79751fdca09d94474a90e185fb76
5
+ SHA512:
6
+ metadata.gz: a6f4bb613fd181471772a0a60886d5d09332724a3a1b29c014a0fea132b6273f68456a3233945fb26bffbe836737682e34592ed7784ce01fbae8ed35e4ab9da9
7
+ data.tar.gz: ca7c31915d5669691554b0d46cd6ae448ffef1dc528274a078dc03a8dd09c89d40b805d962fad3e52e1c3d327faf70da91ac968498255ffb40ff966b9ad82219
data/.gitignore ADDED
@@ -0,0 +1,23 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ spec/fixtures/xlarge.log
19
+ mac_addrs.txt
20
+ ip_addrs.txt
21
+ SOLUTION.txt
22
+ .idea
23
+ *.iml
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sns_utils.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 sahglie
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # SnsUtils
2
+
3
+ Find and extract IP and MAC addresses in FILE based on repeated occurrences.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'sns_utils'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install sns_utils
18
+
19
+ ## Usage
20
+ $ gem install gem-man (if you haven't already)
21
+ $ gem man sns_utils
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
30
+
31
+
32
+ ## Performance Notes
33
+
34
+ ### Grep Baseline Perf
35
+
36
+ xlarge.log is 5GB with 50 million lines
37
+
38
+ time grep -c -E '(?:[0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}' spec/fixtures/xlarge.log
39
+ => real 12m0.658s
40
+ user 11m59.672s
41
+ sys 0m0.991s
42
+
43
+
44
+ xlarge.log is 514MB with 5 million lines
45
+
46
+ time grep -c -E '(?:[0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}' spec/fixtures/xlarge.log
47
+ => real 1m12.063s
48
+ user 1m11.956s
49
+ sys 0m0.108s
50
+
51
+ ## ip_extract
52
+
53
+ xlarge.log is 514MB with 5 million lines
54
+
55
+ ip_extract spec/fixtures/xlarge.log
56
+ => real 2m18.938s
57
+ user 2m18.356s
58
+ sys 0m0.578s
59
+
60
+
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ require "bundler/gem_tasks"
2
+ require 'ronn'
3
+
4
+
5
+ namespace :man do
6
+ directory "man"
7
+
8
+ Dir["man/*.ronn"].each do |ronn|
9
+ basename = File.basename(ronn, ".ronn")
10
+ roff = "man/#{basename}"
11
+
12
+ file roff => ["man", ronn] do
13
+ sh "#{Gem.ruby} -S ronn --roff --pipe #{ronn} > #{roff}"
14
+ end
15
+
16
+ file "#{roff}.txt" => roff do
17
+ sh "groff -Wall -mtty-char -mandoc -Tascii #{roff} | col -b > #{roff}.txt"
18
+ end
19
+
20
+ task :build_all_pages => "#{roff}.txt"
21
+ end
22
+
23
+ desc "Build the man pages"
24
+ task :build => "man:build_all_pages"
25
+
26
+ desc "Clean up from the built man pages"
27
+ task :clean do
28
+ rm "man/ipex.1"
29
+ rm "man/ipex.1.txt"
30
+ end
31
+ end
32
+
33
+ task :build => ["man:clean", "man:build"]
34
+ task :release => ["man:clean", "man:build"]
data/bin/ipex ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Exit cleanly from an early interrupt
4
+ Signal.trap("INT") { exit 1 }
5
+
6
+ require_relative "../lib/sns_utils"
7
+
8
+ begin
9
+ SnsUtils::IpExtractor.new(ARGV).run
10
+ rescue Errno::ENOENT => err
11
+ abort "ipex: #{err.message}"
12
+ rescue OptionParser::InvalidOption, OptionParser::InvalidArgument => err
13
+ abort "usage: ipex FILE [-m MAC_THRESHOLD] [-i IP_THRESHOLD] [-d OUTPUT_DIR]"
14
+ end
@@ -0,0 +1,88 @@
1
+ module SnsUtils
2
+ class IpExtractor
3
+ attr_accessor :file, :options
4
+ attr_accessor :ip_addrs, :ip_addrs_log, :mac_addrs, :mac_addrs_log
5
+
6
+ IPV4_REGEX = ::SnsUtils::IPv4::REGEX
7
+ IPV6_REGEX = ::SnsUtils::IPv6::REGEX
8
+ MAC_REGEX = ::SnsUtils::MAC::REGEX
9
+ IP_REGEX = / ((?: ^|\s) (?: #{IPV6_REGEX} | #{IPV4_REGEX} | #{MAC_REGEX}) (?: \s|$)) /xi
10
+
11
+ def initialize(argv)
12
+ @file, @options = parse_options(argv)
13
+ self.ip_addrs = {}
14
+ self.mac_addrs = {}
15
+ end
16
+
17
+ def run
18
+ extract_addresses
19
+ log_ip_addrs
20
+ log_mac_addrs
21
+ self
22
+ end
23
+
24
+ private
25
+
26
+ def extract_addresses
27
+ File.open(file, 'r').each do |line|
28
+ line.scan(IP_REGEX).each { |md| log_addr(md[0].to_s.strip!) }
29
+ end
30
+ end
31
+
32
+ def log_ip_addrs
33
+ self.ip_addrs_log = ip_addrs.select { |_, count| count >= options.ip_threshold }.keys
34
+ write_file(::SnsUtils.ip_out_file, ip_addrs_log)
35
+ end
36
+
37
+ def log_mac_addrs
38
+ self.mac_addrs_log = mac_addrs.select { |_, count| count >= options.mac_threshold }.keys
39
+ write_file(::SnsUtils.mac_out_file, mac_addrs_log)
40
+ end
41
+
42
+ def write_file(file, entries)
43
+ file_path = output_dir(options.output_dir, file)
44
+ File.open(file_path, "w+") do |f|
45
+ entries.each { |e| f.puts(e) }
46
+ end
47
+ end
48
+
49
+ def output_dir(dir, file)
50
+ dir ? File.expand_path(File.join(dir, file)) : file
51
+ end
52
+
53
+ def log_addr(ip)
54
+ key = IPAddr.new(ip).to_string
55
+ ip_addrs[key] ||= 0
56
+ ip_addrs[key] += 1
57
+ rescue IPAddr::InvalidAddressError => e
58
+ mac_addrs[ip] ||= 0
59
+ mac_addrs[ip] += 1
60
+ end
61
+
62
+ def parse_options(argv)
63
+ options = OpenStruct.new
64
+ options.mac_threshold = 8
65
+ options.ip_threshold = 10
66
+ options.output_dir = nil
67
+
68
+ parser = OptionParser.new do |opts|
69
+ opts.on("-m N", Integer, "MAC address threshold, logs entries with N <= occurrences") do |n|
70
+ options.mac_threshold = Integer(n).abs
71
+ end
72
+
73
+ opts.on("-i N", Integer, "IP address threshold, logs entries with N =< occurrences") do |n|
74
+ options.ip_threshold = Integer(n).abs
75
+ end
76
+
77
+ opts.on("-d OUTPUT_DIR", String, "Dir used to write output files") do |dir|
78
+ options.output_dir = dir
79
+ end
80
+ end
81
+
82
+ parser.parse(argv)
83
+
84
+ file = argv[0] || raise(OptionParser::InvalidOption.new)
85
+ [file, options]
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,12 @@
1
+ module SnsUtils
2
+ # NOTE: the regexes are from Resolv::IPv4 in ruby's stdlib. They were copied here because we
3
+ # need to match IPs in the context of a large string and the Resolv regex has string start
4
+ # and string end anchors which don't allow this.
5
+ module IPv4
6
+ REGEX_256 = /0
7
+ |1(?:[0-9][0-9]?)?
8
+ |2(?:[0-4][0-9]?|5[0-5]?|[6-9])?
9
+ |[3-9][0-9]?/x
10
+ REGEX = /#{REGEX_256}\.#{REGEX_256}\.#{REGEX_256}\.#{REGEX_256}/x
11
+ end
12
+ end
@@ -0,0 +1,44 @@
1
+ module SnsUtils
2
+ # NOTE: the regexes are from Resolv::IPv4 in ruby's stdlib. They were copied here because we
3
+ # need to match IPs in the context of a large string and the Resolv regex has string start
4
+ # and string end anchors which don't allow this.
5
+ module IPv6
6
+ ##
7
+ # IPv6 address format a:b:c:d:e:f:g:h
8
+ REGEX_8HEX = /
9
+ (?:[0-9A-Fa-f]{1,4}:){7}
10
+ [0-9A-Fa-f]{1,4}
11
+ /x
12
+
13
+ ##
14
+ # Compressed IPv6 address format a::b
15
+ REGEX_COMPRESSEDHEX = /
16
+ (?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)? ::
17
+ (?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?
18
+ /x
19
+
20
+ ##
21
+ # IPv4 mapped IPv6 address format a:b:c:d:e:f:w.x.y.z
22
+ REGEX_6HEX4DEC = /
23
+ (?:[0-9A-Fa-f]{1,4}:){6,6}
24
+ \d+\.\d+\.\d+\.\d+
25
+ /x
26
+
27
+ ##
28
+ # Compressed IPv4 mapped IPv6 address format a::b:w.x.y.z
29
+ REGEX_COMPRESSEDHEX4DEC = /
30
+ (?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)? ::
31
+ (?:[0-9A-Fa-f]{1,4}:)*
32
+ \d+\.\d+\.\d+\.\d+
33
+ /x
34
+
35
+ ##
36
+ # A composite IPv6 address Regexp.
37
+ REGEX = /
38
+ (?:#{REGEX_8HEX}) |
39
+ (?:#{REGEX_COMPRESSEDHEX}) |
40
+ (?:#{REGEX_6HEX4DEC}) |
41
+ (?:#{REGEX_COMPRESSEDHEX4DEC})
42
+ /x
43
+ end
44
+ end
@@ -0,0 +1,5 @@
1
+ module SnsUtils
2
+ module MAC
3
+ REGEX = / (?: [0-9a-fA-F]{2}[:-]){5} [0-9a-fA-F]{2} /xi
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module SnsUtils
2
+ VERSION = "0.0.1"
3
+ end
data/lib/sns_utils.rb ADDED
@@ -0,0 +1,46 @@
1
+ require 'pp'
2
+ require "strscan"
3
+ require 'ipaddr'
4
+ require "optparse"
5
+ require 'ostruct'
6
+
7
+ require_relative 'sns_utils/ipv4'
8
+ require_relative 'sns_utils/ipv6'
9
+ require_relative 'sns_utils/mac'
10
+ require_relative "sns_utils/ip_extractor"
11
+ require_relative "sns_utils/version"
12
+
13
+
14
+ module SnsUtils
15
+ def self.root
16
+ @root ||= File.expand_path(File.join(File.dirname(__FILE__), ".."))
17
+ end
18
+
19
+ def self.ip_out_file
20
+ "ip_addrs.txt"
21
+ end
22
+
23
+ def self.mac_out_file
24
+ "mac_addrs.txt"
25
+ end
26
+
27
+ def self.create_test_log(line, rep=1_000)
28
+ File.open("#{::SnsUtils.root}/spec/fixtures/xlarge.log", "w+") do |f|
29
+ rep.times do
30
+ f.puts("2013-08-20 16:05:06,975 [http-8082-3] INFO - Rendered text template (0.0ms)")
31
+ f.puts("2013-08-20 16:05:06,975 [http-8082-3] INFO - Completed 200 OK in 5295ms (Views: 1.0ms | ActiveRecord: 0.0ms)")
32
+ f.puts(line)
33
+ f.puts("2013-08-20 16:08:39,281 [http-8082-3] INFO - Redirected to https://apsearch-qa.berkeley.edu/login")
34
+ f.puts("169.229.216.83 - - [25/Aug/2013:07:02:29 -0700] \"GET / HTTP/1.0\" 302 303 \"-\" \"check_http/v2053 (nagios-plugins 1.4.13)")
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+
41
+
42
+ if $PROGRAM_NAME == __FILE__
43
+ line = "9.9.9 blah blah blah VALID 0.0.0.0 xxxx<<> 2001:0000:1234:0000:0000:C1C0:ABCD:0876 VALID >>> blah blah blah VALID 00:A0:C9:14:C8:29"
44
+ ::SnsUtils.create_test_log(line, 1_000_000)
45
+ end
46
+
data/man/ipex.1 ADDED
@@ -0,0 +1,56 @@
1
+ .\" generated with Ronn/v0.7.3
2
+ .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
+ .
4
+ .TH "IPEX" "1" "August 2013" "" ""
5
+ .
6
+ .SH "NAME"
7
+ \fBipex\fR \- IP/Mac Address Extractor
8
+ .
9
+ .SH "SYNOPSIS"
10
+ \fBipex FILE [\-m THRESHOLD] [\-i THRESHOLD] [\-d OUTPUT_DIR]\fR
11
+ .
12
+ .SH "DESCRIPTION"
13
+ Find and extract IP and MAC addresses in FILE\. Addresses with repeat occurrences greater than or equal to a given threshold are logged to ip_addrs\.txt and mac_addrs\.txt respectively\. By default, MAC addresses that occur at least 8 times are logged and IP addresses that occur at least 10 times are logged\. All matches are performed as case insensitive\.
14
+ .
15
+ .SH "OPTIONS"
16
+ .
17
+ .TP
18
+ \fB\-m\fR
19
+ Set the MAC address threshold, defaults to 8
20
+ .
21
+ .TP
22
+ \fB\-i\fR
23
+ Set the IP address threshold, defaults to 10
24
+ .
25
+ .TP
26
+ \fB\-d\fR
27
+ Specify directory where MAC and IP output files are written to, defaults to current directory
28
+ .
29
+ .SH "FORMATS"
30
+ Matches the following address formats:
31
+ .
32
+ .IP "\(bu" 4
33
+ IPv4: standard format a\.b\.c\.d
34
+ .
35
+ .IP "\(bu" 4
36
+ IPv6: canonical format a:b:c:d:e:f:g:h
37
+ .
38
+ .IP "\(bu" 4
39
+ IPv6: compressed format a::b
40
+ .
41
+ .IP "\(bu" 4
42
+ IPv6: IPv4 mapped IPv6 format a:b:c:d:e:f:w\.x\.y\.z
43
+ .
44
+ .IP "\(bu" 4
45
+ IPv6: compressed IPv4 mapped IPv6 format a::b:w\.x\.y\.z
46
+ .
47
+ .IP "\(bu" 4
48
+ MAC: Separated by \'\-\' aa\-bb\-cc\-dd\-ee\-ff
49
+ .
50
+ .IP "\(bu" 4
51
+ MAC: Separated by \':\' aa:bb:cc:dd:ee:ff
52
+ .
53
+ .IP "" 0
54
+ .
55
+ .SH "NOTE ON LARGE FILES"
56
+ Depending on how large the file is, this utility can take a long time to complete: for a 512MB file with (5 million) entries it took just over 2 min \-\- YMMV depending on your hardware
data/man/ipex.1.ronn ADDED
@@ -0,0 +1,43 @@
1
+ ipex(1) -- IP/Mac Address Extractor
2
+ =======================================
3
+
4
+ ## SYNOPSIS
5
+
6
+ `ipex FILE [-m THRESHOLD] [-i THRESHOLD] [-d OUTPUT_DIR]`
7
+
8
+ ## DESCRIPTION
9
+
10
+ Find and extract IP and MAC addresses in FILE. Addresses with repeat occurrences
11
+ greater than or equal to a given threshold are logged to ip_addrs.txt and mac_addrs.txt
12
+ respectively. By default, MAC addresses that occur at least 8 times are logged
13
+ and IP addresses that occur at least 10 times are logged. All matches are performed
14
+ as case insensitive.
15
+
16
+ ## OPTIONS
17
+
18
+ * `-m`:
19
+ Set the MAC address threshold, defaults to 8
20
+
21
+ * `-i`:
22
+ Set the IP address threshold, defaults to 10
23
+
24
+ * `-d`:
25
+ Specify directory where MAC and IP output files are written to, defaults to
26
+ current directory
27
+
28
+ ## FORMATS
29
+ Matches the following address formats:
30
+
31
+ * IPv4: standard format a.b.c.d
32
+ * IPv6: canonical format a:b:c:d:e:f:g:h
33
+ * IPv6: compressed format a::b
34
+ * IPv6: IPv4 mapped IPv6 format a:b:c:d:e:f:w.x.y.z
35
+ * IPv6: compressed IPv4 mapped IPv6 format a::b:w.x.y.z
36
+ * MAC: Separated by '-' aa-bb-cc-dd-ee-ff
37
+ * MAC: Separated by ':' aa:bb:cc:dd:ee:ff
38
+
39
+ ## NOTE ON LARGE FILES
40
+ Depending on how large the file is, this utility can take a long time to
41
+ complete: for a 512MB file with (5 million) entries it took just over 2 min
42
+ -- YMMV depending on your hardware
43
+
data/man/ipex.1.txt ADDED
@@ -0,0 +1,53 @@
1
+ IPEX(1) IPEX(1)
2
+
3
+
4
+
5
+ NAME
6
+ ipex - IP/Mac Address Extractor
7
+
8
+ SYNOPSIS
9
+ ipex FILE [-m THRESHOLD] [-i THRESHOLD] [-d OUTPUT_DIR]
10
+
11
+ DESCRIPTION
12
+ Find and extract IP and MAC addresses in FILE. Addresses with repeat
13
+ occurrences greater than or equal to a given threshold are logged to
14
+ ip_addrs.txt and mac_addrs.txt respectively. By default, MAC addresses
15
+ that occur at least 8 times are logged and IP addresses that occur at
16
+ least 10 times are logged. All matches are performed as case insensi-
17
+ tive.
18
+
19
+ OPTIONS
20
+ -m Set the MAC address threshold, defaults to 8
21
+
22
+ -i Set the IP address threshold, defaults to 10
23
+
24
+ -d Specify directory where MAC and IP output files are written to,
25
+ defaults to current directory
26
+
27
+ FORMATS
28
+ Matches the following address formats:
29
+
30
+ o IPv4: standard format a.b.c.d
31
+
32
+ o IPv6: canonical format a:b:c:d:e:f:g:h
33
+
34
+ o IPv6: compressed format a::b
35
+
36
+ o IPv6: IPv4 mapped IPv6 format a:b:c:d:e:f:w.x.y.z
37
+
38
+ o IPv6: compressed IPv4 mapped IPv6 format a::b:w.x.y.z
39
+
40
+ o MAC: Separated by '-' aa-bb-cc-dd-ee-ff
41
+
42
+ o MAC: Separated by ':' aa:bb:cc:dd:ee:ff
43
+
44
+
45
+
46
+ NOTE ON LARGE FILES
47
+ Depending on how large the file is, this utility can take a long time
48
+ to complete: for a 512MB file with (5 million) entries it took just
49
+ over 2 min -- YMMV depending on your hardware
50
+
51
+
52
+
53
+ August 2013 IPEX(1)
data/sns_utils.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sns_utils/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "sns_utils"
8
+ spec.version = SnsUtils::VERSION
9
+ spec.authors = ["sahglie"]
10
+ spec.email = ["sahglie@gmail.com"]
11
+ spec.description = %q{Find and extract IP and MAC addresses in FILE}
12
+ spec.summary = %q{Find and extract IP and MAC addresses in FILE}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.files += Dir.glob('man/*')
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_runtime_dependency "ronn"
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rspec", "~> 2.7"
25
+ spec.add_development_dependency "rake"
26
+ end
@@ -0,0 +1,4 @@
1
+ # blah blah blah VALID 0.0.0.0 xxxx<<> 2001:0000:1234:0000:0000:C1C0:ABCD:0876 VALID >>>
2
+ # 3ffe:0b00:0000:0000:0001:0000:0000:000a VALID <<<<<<<<<< INVALID 1.1.1.
3
+ # blah blah blah VALID 99.1.1.1 xxxx<<> VALID FF02:0000:0000:0000:0000:0000:0000:0001 >>>
4
+ # blah blah blah INVALID a5::91::7 xxxx<<> VALID 00:A0:C9:14:C8:29 >>>
@@ -0,0 +1,12 @@
1
+ #
2
+ # valid 0.0.0.0
3
+ # valid 1.1.1.1
4
+ # valid 111.111.111.111
5
+ # valid 111.111.111.1
6
+ # valid 99.1.1.1
7
+
8
+ # invalid 1.1.1
9
+ # invalid 1
10
+ # invalid 1.1
11
+ # invalid 192.168.1.500
12
+ # invalid 999.1.1.1
@@ -0,0 +1,172 @@
1
+ # NOTE, some of the following IPs are duplicates, just in
2
+ # a different format so the 81 valid ips map to 61 valid
3
+ # ips.
4
+
5
+ # valid 2001:0000:1234:0000:0000:C1C0:ABCD:0876
6
+ # valid 3ffe:0b00:0000:0000:0001:0000:0000:000a
7
+ # valid FF02:0000:0000:0000:0000:0000:0000:0001
8
+ # valid 0000:0000:0000:0000:0000:0000:0000:0001
9
+ # valid 0000:0000:0000:0000:0000:0000:0000:0000
10
+ # valid ::ffff:192.168.1.26
11
+ # valid 2::10
12
+ # valid ff02::1
13
+ # valid fe80::
14
+ # valid 2002::
15
+ # valid 2001:db8::
16
+ # valid 2001:0db8:1234::
17
+ # valid ::ffff:0:0
18
+ # valid ::1
19
+ # valid ::ffff:192.168.1.1
20
+ # valid 1:2:3:4:5:6:7:8
21
+ # valid 1:2:3:4:5:6::8
22
+ # valid 1:2:3:4:5::8
23
+ # valid 1:2:3:4::8
24
+ # valid 1:2:3::8
25
+ # valid 1:2::8
26
+ # valid 1::8
27
+ # valid 1::2:3:4:5:6:7
28
+ # valid 1::2:3:4:5:6
29
+ # valid 1::2:3:4:5
30
+ # valid 1::2:3:4
31
+ # valid 1::2:3
32
+ # valid 1::8
33
+ # valid ::2:3:4:5:6:7:8
34
+ # valid ::2:3:4:5:6:7
35
+ # valid ::2:3:4:5:6
36
+ # valid ::2:3:4:5
37
+ # valid ::2:3:4
38
+ # valid ::2:3
39
+ # valid ::8
40
+ # valid 1:2:3:4:5:6::
41
+ # valid 1:2:3:4:5::
42
+ # valid 1:2:3:4::
43
+ # valid 1:2:3::
44
+ # valid 1:2::
45
+ # valid 1::
46
+ # valid 1:2:3:4:5::7:8
47
+ # valid 1:2:3:4::7:8
48
+ # valid 1:2:3::7:8
49
+ # valid 1:2::7:8
50
+ # valid 1::7:8
51
+ # valid 1:2:3:4:5:6:1.2.3.4
52
+ # valid 1:2:3:4:5::1.2.3.4
53
+ # valid 1:2:3:4::1.2.3.4
54
+ # valid 1:2:3::1.2.3.4
55
+ # valid 1:2::1.2.3.4
56
+ # valid 1::1.2.3.4
57
+ # valid 1:2:3:4::5:1.2.3.4
58
+ # valid 1:2:3::5:1.2.3.4
59
+ # valid 1:2::5:1.2.3.4
60
+ # valid 1::5:1.2.3.4
61
+ # valid 1::5:11.22.33.44
62
+ # valid 2001:0000:1234:0000:0000:C1C0:ABCD:0876
63
+ # valid 2001:0000:1234:0000:0000:C1C0:ABCD:0876
64
+ # valid fe80::217:f2ff:254.7.237.98
65
+ # valid fe80::217:f2ff:fe07:ed62
66
+ # valid 2001:DB8:0:0:8:800:200C:417A # unicast, full
67
+ # valid FF01:0:0:0:0:0:0:101 # multicast, full
68
+ # valid 0:0:0:0:0:0:0:1 # loopback, full
69
+ # valid 0:0:0:0:0:0:0:0 # unspecified, full
70
+ # valid 2001:DB8::8:800:200C:417A # unicast, compressed
71
+ # valid FF01::101 # multicast, compressed
72
+ # valid ::1 # loopback, compressed, non-routable
73
+ # valid :: # unspecified, compressed, non-routable
74
+ # valid 0:0:0:0:0:0:13.1.68.3 # IPv4-compatible IPv6 address, full, deprecated
75
+ # valid 0:0:0:0:0:FFFF:129.144.52.38 # IPv4-mapped IPv6 address, full
76
+ # valid ::13.1.68.3 # IPv4-compatible IPv6 address, compressed, deprecated
77
+ # valid ::FFFF:129.144.52.38 # IPv4-mapped IPv6 address, compressed
78
+ # valid fe80:0000:0000:0000:0204:61ff:fe9d:f156
79
+ # valid fe80:0:0:0:204:61ff:fe9d:f156
80
+ # valid fe80::204:61ff:fe9d:f156
81
+ # valid fe80:0:0:0:204:61ff:254.157.241.86
82
+ # valid fe80::204:61ff:254.157.241.86
83
+ # valid ::1
84
+ # valid fe80::
85
+ # valid fe80::1
86
+
87
+ # not valid 02001:0000:1234:0000:0000:C1C0:ABCD:0876 # extra 0 not allowed!
88
+ # not valid 2001:0000:1234:0000:00001:C1C0:ABCD:0876 # extra 0 not allowed!
89
+ # not valid 2001:0000:1234:0000:0000:C1C0:ABCD:0876 0
90
+ # not valid 2001:0000:1234: 0000:0000:C1C0:ABCD:0876
91
+ # not valid 3ffe:0b00:0000:0001:0000:0000:000a
92
+ # not valid FF02:0000:0000:0000:0000:0000:0000:0000:0001
93
+ # not valid 3ffe:b00::1::a
94
+ # not valid ::1111:2222:3333:4444:5555:6666::
95
+ # not valid 1:2:3::4:5::7:8
96
+ # not valid 12345::6:7:8
97
+ # not valid 1::5:400.2.3.4
98
+ # not valid 1::5:260.2.3.4
99
+ # not valid 1::5:256.2.3.4
100
+ # not valid 1::5:1.256.3.4
101
+ # not valid 1::5:1.2.256.4
102
+ # not valid 1::5:1.2.3.256
103
+ # not valid 1::5:300.2.3.4
104
+ # not valid 1::5:1.300.3.4
105
+ # not valid 1::5:1.2.300.4
106
+ # not valid 1::5:1.2.3.300
107
+ # not valid 1::5:900.2.3.4
108
+ # not valid 1::5:1.900.3.4
109
+ # not valid 1::5:1.2.900.4
110
+ # not valid 1::5:1.2.3.900
111
+ # not valid 1::5:300.300.300.300
112
+ # not valid 1::5:3000.30.30.30
113
+ # not valid 1::400.2.3.4
114
+ # not valid 1::260.2.3.4
115
+ # not valid 1::256.2.3.4
116
+ # not valid 1::1.256.3.4
117
+ # not valid 1::1.2.256.4
118
+ # not valid 1::1.2.3.256
119
+ # not valid 1::300.2.3.4
120
+ # not valid 1::1.300.3.4
121
+ # not valid 1::1.2.300.4
122
+ # not valid 1::1.2.3.300
123
+ # not valid 1::900.2.3.4
124
+ # not valid 1::1.900.3.4
125
+ # not valid 1::1.2.900.4
126
+ # not valid 1::1.2.3.900
127
+ # not valid 1::300.300.300.300
128
+ # not valid 1::3000.30.30.30
129
+ # not valid ::400.2.3.4
130
+ # not valid ::260.2.3.4
131
+ # not valid ::256.2.3.4
132
+ # not valid ::1.256.3.4
133
+ # not valid ::1.2.256.4
134
+ # not valid ::1.2.3.256
135
+ # not valid ::300.2.3.4
136
+ # not valid ::1.300.3.4
137
+ # not valid ::1.2.300.4
138
+ # not valid ::1.2.3.300
139
+ # not valid ::900.2.3.4
140
+ # not valid ::1.900.3.4
141
+ # not valid ::1.2.900.4
142
+ # not valid ::1.2.3.900
143
+ # not valid ::300.300.300.300
144
+ # not valid ::3000.30.30.30
145
+ # not valid 2001:DB8:0:0:8:800:200C:417A:221 # unicast, full
146
+ # not valid FF01::101::2 # multicast, compressed
147
+ # not valid # nothing
148
+ # Not sure about this one; apparently some systems treat the leading "0" in ".086" as the start of an octal number
149
+ # not valid fe80:0000:0000:0000:0204:61ff:254.157.241.086
150
+ # not valid :
151
+ # not valid 1111:2222:3333:4444::5555:
152
+ # not valid 1111:2222:3333::5555:
153
+ # not valid 1111:2222::5555:
154
+ # not valid 1111::5555:
155
+ # not valid ::5555:
156
+ # not valid :::
157
+ # not valid 1111:
158
+ # not valid :
159
+ # not valid :1111:2222:3333:4444::5555
160
+ # not valid :1111:2222:3333::5555
161
+ # not valid :1111:2222::5555
162
+ # not valid :1111::5555
163
+ # not valid :::5555
164
+ # not valid :::
165
+ # not valid 1.2.3.4:1111:2222:3333:4444::5555
166
+ # not valid 1.2.3.4:1111:2222:3333::5555
167
+ # not valid 1.2.3.4:1111:2222::5555
168
+ # not valid 1.2.3.4:1111::5555
169
+ # not valid 1.2.3.4::5555
170
+ # not valid 1.2.3.4::
171
+ # not valid 2001:1:1:1:1:1:255Z255X255Y255
172
+ # not valid ::ffff:192x168.1.26
@@ -0,0 +1,6 @@
1
+ # valid 00:A0:C9:14:C8:29
2
+ # valid 00:00:00:00:00:00
3
+
4
+ # invalid 00:00:00:00:00
5
+ # invalid A0:C9:14:C8:29
6
+ # invalid 00:A:C9:14:C8:29
@@ -0,0 +1,35 @@
1
+ # IPv4 occurs 10 times
2
+ # valid 1.1.1.1
3
+ # valid 1.1.1.1
4
+ # valid 1.1.1.1
5
+ # valid 1.1.1.1
6
+ # valid 1.1.1.1
7
+ # valid 1.1.1.1
8
+ # valid 1.1.1.1
9
+ # valid 1.1.1.1
10
+ # valid 1.1.1.1
11
+ # valid 1.1.1.1
12
+
13
+ # MAC occurs 8 times
14
+ # valid 00:A0:C9:14:C8:29
15
+ # valid 00:A0:C9:14:C8:29
16
+ # valid 00:A0:C9:14:C8:29
17
+ # valid 00:A0:C9:14:C8:29
18
+ # valid 00:A0:C9:14:C8:29
19
+ # valid 00:A0:C9:14:C8:29
20
+ # valid 00:A0:C9:14:C8:29
21
+ # valid 00:A0:C9:14:C8:29
22
+
23
+ # IPv4 occurs 5 times
24
+ # 0.0.0.0
25
+ # 0.0.0.0
26
+ # 0.0.0.0
27
+ # 0.0.0.0
28
+ # 0.0.0.0
29
+
30
+ # IPv6 occurs 5 times
31
+ # valid 00:00:00:00:00:00
32
+ # valid 00:00:00:00:00:00
33
+ # valid 00:00:00:00:00:00
34
+ # valid 00:00:00:00:00:00
35
+ # valid 00:00:00:00:00:00
@@ -0,0 +1,103 @@
1
+ require_relative "../spec_helper"
2
+
3
+ describe SnsUtils::IpExtractor do
4
+ context "extracting IPv4 ips" do
5
+ let(:file) { fixture_path("ipv4_simple.log") }
6
+
7
+ it "finds valid entries" do
8
+ extractor = SnsUtils::IpExtractor.new([file]).run
9
+ extractor.ip_addrs.should have(5).entries
10
+ end
11
+ end
12
+
13
+ context "extracting IPv6 ips" do
14
+ let(:file) { fixture_path("ipv6_simple.log") }
15
+
16
+ it "finds valid entries" do
17
+ extractor = SnsUtils::IpExtractor.new([file]).run
18
+ extractor.ip_addrs.should have(61).entries
19
+ end
20
+ end
21
+
22
+ context "extracting MAC addresses" do
23
+ let(:file) { fixture_path("mac_simple.log") }
24
+
25
+ it "finds valid entries" do
26
+ extractor = SnsUtils::IpExtractor.new([file]).run
27
+ extractor.mac_addrs.should have(2).entries
28
+ end
29
+ end
30
+
31
+ context "extracting IPv4, IPv6, and MACs" do
32
+ let(:file) { fixture_path("ipv4_ipv6_mac.log") }
33
+
34
+ it "finds valid entries" do
35
+ extractor = SnsUtils::IpExtractor.new([file]).run
36
+ extractor.ip_addrs.should have(5).entries
37
+ extractor.mac_addrs.should have(1).entry
38
+ end
39
+ end
40
+
41
+ context "Occurrence threshold options" do
42
+ let(:file) { fixture_path("thresholds.log") }
43
+
44
+ it "raises error for invalid thresholds" do
45
+ expect { SnsUtils::IpExtractor.new([file, "-i", "x"]) }.to \
46
+ raise_error(OptionParser::InvalidArgument)
47
+
48
+ expect { SnsUtils::IpExtractor.new([file, "-m", "x"]) }.to \
49
+ raise_error(OptionParser::InvalidArgument)
50
+ end
51
+
52
+ it "has default IP and MAC threshold" do
53
+ extractor = SnsUtils::IpExtractor.new([file])
54
+ extractor.options.mac_threshold.should eql(8)
55
+ extractor.options.ip_threshold.should eql(10)
56
+ end
57
+
58
+ it "uses default IP and MAC threshold" do
59
+ extractor = SnsUtils::IpExtractor.new([file])
60
+ extractor.run
61
+
62
+ extractor.ip_addrs_log.should have(1).entry
63
+ extractor.mac_addrs_log.should have(1).entry
64
+ end
65
+
66
+ it "adjusts default IP and MAC threshold" do
67
+ extractor = SnsUtils::IpExtractor.new([file, "-i", "5", "-m", "4"])
68
+ extractor.options.mac_threshold.should eql(4)
69
+ extractor.options.ip_threshold.should eql(5)
70
+ end
71
+
72
+ it "uses adjusted IP and MAC threshold" do
73
+ extractor = SnsUtils::IpExtractor.new([file, "-i", "5", "-m", "5"]).run
74
+ extractor.ip_addrs_log.should have(2).entries
75
+ extractor.mac_addrs_log.should have(2).entries
76
+
77
+ extractor = SnsUtils::IpExtractor.new([file, "-i", "11", "-m", "11"]).run
78
+ extractor.ip_addrs_log.should be_empty
79
+ extractor.mac_addrs_log.should be_empty
80
+ end
81
+ end
82
+
83
+ context "Output dir option" do
84
+ let(:file) { fixture_path("ipv4_simple.log") }
85
+ let(:tmp_dir) { "#{::SnsUtils.root}/tmp" }
86
+
87
+ after(:all) do
88
+ File.delete("#{tmp_dir}/#{::SnsUtils.ip_out_file}")
89
+ File.delete("#{tmp_dir}/#{::SnsUtils.mac_out_file}")
90
+ end
91
+
92
+ it "configures custom output directory" do
93
+ options = SnsUtils::IpExtractor.new([file, "-d", tmp_dir]).options
94
+ options.output_dir.should eql(tmp_dir)
95
+ end
96
+
97
+ it "writes to custom output directory" do
98
+ SnsUtils::IpExtractor.new([file, "-d", tmp_dir]).run
99
+ File.exists?("#{tmp_dir}/#{::SnsUtils.ip_out_file}").should be_true
100
+ File.exists?("#{tmp_dir}/#{::SnsUtils.mac_out_file}").should be_true
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,8 @@
1
+ require_relative '../lib/sns_utils'
2
+
3
+ RSpec.configure do |config|
4
+ end
5
+
6
+ def fixture_path(file)
7
+ File.expand_path(File.join(SnsUtils.root, "spec", "fixtures", file))
8
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sns_utils
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - sahglie
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-08-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ronn
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '2.7'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '2.7'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Find and extract IP and MAC addresses in FILE
70
+ email:
71
+ - sahglie@gmail.com
72
+ executables:
73
+ - ipex
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - .gitignore
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - bin/ipex
83
+ - lib/sns_utils.rb
84
+ - lib/sns_utils/ip_extractor.rb
85
+ - lib/sns_utils/ipv4.rb
86
+ - lib/sns_utils/ipv6.rb
87
+ - lib/sns_utils/mac.rb
88
+ - lib/sns_utils/version.rb
89
+ - man/ipex.1
90
+ - man/ipex.1.ronn
91
+ - man/ipex.1.txt
92
+ - sns_utils.gemspec
93
+ - spec/fixtures/ipv4_ipv6_mac.log
94
+ - spec/fixtures/ipv4_simple.log
95
+ - spec/fixtures/ipv6_simple.log
96
+ - spec/fixtures/mac_simple.log
97
+ - spec/fixtures/thresholds.log
98
+ - spec/sns_utils/ip_extractor_spec.rb
99
+ - spec/spec_helper.rb
100
+ homepage: ''
101
+ licenses:
102
+ - MIT
103
+ metadata: {}
104
+ post_install_message:
105
+ rdoc_options: []
106
+ require_paths:
107
+ - lib
108
+ required_ruby_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - '>='
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ required_rubygems_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ requirements: []
119
+ rubyforge_project:
120
+ rubygems_version: 2.0.3
121
+ signing_key:
122
+ specification_version: 4
123
+ summary: Find and extract IP and MAC addresses in FILE
124
+ test_files:
125
+ - spec/fixtures/ipv4_ipv6_mac.log
126
+ - spec/fixtures/ipv4_simple.log
127
+ - spec/fixtures/ipv6_simple.log
128
+ - spec/fixtures/mac_simple.log
129
+ - spec/fixtures/thresholds.log
130
+ - spec/sns_utils/ip_extractor_spec.rb
131
+ - spec/spec_helper.rb
132
+ has_rdoc: