-
Notifications
You must be signed in to change notification settings - Fork 0
/
loadparseprint.go
125 lines (102 loc) · 3.02 KB
/
loadparseprint.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package main
import (
"bufio"
"fmt"
"log"
"net"
"os"
"strings"
"sync"
geoip2 "github.com/oschwald/geoip2-golang"
)
var (
// embedded values are generated by init.sh in init.go
dbASN = newgeoip2Reader(embeddedASN)
dbCountry = newgeoip2Reader(embeddedCountry)
)
// newgeoip2Reader wrapper from []byte to *geoip2.Reader
func newgeoip2Reader(Asset []byte) *geoip2.Reader {
db, err := geoip2.FromBytes(Asset)
if err != nil {
log.Fatal("ERR geoip2.FromBytes() ", err)
}
return db
}
// parseandprint return string with ASN and Country from ip string
func parseandprint(ips string) string {
const format = "%s (%s / AS%d %s)"
return parseandprintgen(ips, format)
}
// parseandprint return string with ASN and Country from ip string for SED format
func parseandprintSED(ips string) string {
const format = "s/\"%s\"/\"%s AS%d %s\"/g"
return parseandprintgen(ips, format)
}
// parseandprint return string with ASN and Country from ip string for JSON format
func parseandprintJSON(ips string) string {
// const format = "{\"ip\":\"%s\",\"country\":\"%s\",\"AS\":\"AS%d %s\"}"
const format = "{ \"ip\":\"%s\", \"geoip\": { \"country\":\"%s\",\"AS\":\"AS%d %s\"} }"
// better ?
// { ip: "91.67.155.106" ,
// "geoip": { "country":"Germany",
// "AS":"AS3209 Vodafone GmbH", },
// }
// {"user":"[email protected]","ip":"176.134.198.13"}
return parseandprintgen(ips, format)
}
// Generic parseandprint with format as argument
func parseandprintgen(ips, format string) string {
ip := net.ParseIP(ips)
if ip == nil {
return fmt.Sprintf(format,
ips, "ERROR", 0, "Error net.parseIP")
}
record, err := dbCountry.Country(ip)
if err != nil || record.Country.Names["en"] == "" {
return fmt.Sprintf(format,
ips, "ERROR", 0, "Error db.Country")
}
ASN, err := dbASN.ASN(ip)
if err != nil {
return fmt.Sprintf(format,
ips, "ERROR", 0, "Error db.ASN")
}
// special caracters are problematic for JSON output
change := strings.NewReplacer("&", " and ",
"'", " ",
"\\", " ")
properASN := change.Replace(ASN.AutonomousSystemOrganization)
return fmt.Sprintf(format,
ips, record.Country.Names["en"],
ASN.AutonomousSystemNumber, properASN)
}
// Trying ot pass a generic ParsePrint function to readandprintbulk
type FuncStringtoString func(string) string
// readandprintbulk read stdin and printout results
// channel was used when old parseandprint resolved ip to name
// wg was used to limit concurrent requests
func readandprintbulk(doit FuncStringtoString) {
var line string
var wg sync.WaitGroup
var limitChan = make(chan bool, maxrequests)
cached := make(map[string]bool)
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
line = strings.TrimSpace(scanner.Text())
if cached[line] {
continue
}
cached[line] = true
wg.Add(1)
limitChan <- true // will block after maxrequests
go func(myline string, mywg *sync.WaitGroup, mychan chan bool) {
out := doit(myline)
if len(out) > 0 {
fmt.Printf("%s\n", out)
}
<-mychan
mywg.Done()
}(line, &wg, limitChan)
}
wg.Wait()
}