sns_utils 0.0.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: 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: