Skip to content

Instantly share code, notes, and snippets.

@Snawoot
Created June 26, 2015 14:05
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save Snawoot/d205958d57691d49f99b to your computer and use it in GitHub Desktop.
package main
import (
"errors"
"fmt"
geoip2 "github.com/oschwald/geoip2-golang"
"log"
"net"
"os"
"regexp"
)
func usage() {
fmt.Fprintf(os.Stderr, "Usage: %s <mmdb-file> <start-ip> <end-ip>\n", os.Args[0])
os.Exit(1)
}
func IP2Long(ip net.IP) (uint32, error) {
ip_byte := ip.To4()
if ip_byte == nil {
return 0, errors.New("Not an IPv4 address.")
}
return uint32(ip_byte[0])<<24 | uint32(ip_byte[1])<<16 |
uint32(ip_byte[2])<<8 | uint32(ip_byte[3]),
nil
}
func Long2IP(long uint32) net.IP {
return net.IPv4(byte(long>>24), byte(long>>16), byte(long>>8), byte(long))
}
func main() {
if len(os.Args) != 4 {
usage()
}
mmdb, startIPStr, endIPStr := os.Args[1], os.Args[2], os.Args[3]
startIP, endIP := net.ParseIP(startIPStr), net.ParseIP(endIPStr)
if startIP == nil || endIP == nil {
fmt.Fprintf(os.Stderr, "IP address specification is incorrect.\n")
os.Exit(2)
}
startLong, err := IP2Long(startIP)
if err != nil {
log.Fatal(err)
os.Exit(2)
}
endLong, err := IP2Long(endIP)
if err != nil {
log.Fatal(err)
os.Exit(2)
}
if startLong > endLong {
fmt.Fprintf(os.Stderr, "End IP must be greater than start IP.\n")
os.Exit(2)
}
db, err := geoip2.Open(mmdb)
if err != nil {
log.Fatal(err)
}
rangeStart := startLong
record, err := db.City(Long2IP(rangeStart))
lastIsoCode := ""
if err == nil {
lastIsoCode = record.Country.IsoCode
}
r, _ := regexp.Compile("(?i)Crimea|Sevastopol|Simferopol|Kerch|Evpatori|Yalta|Feodosi|Inkerman")
for i := startLong; i <= endLong; i++ {
ip := Long2IP(i)
record, err := db.City(ip)
code := ""
if err == nil {
code = record.Country.IsoCode
}
if code == "UA" && len(record.Subdivisions) > 0 && r.MatchString(record.Subdivisions[0].Names["en"]) {
code = "RU"
}
if code != lastIsoCode {
if lastIsoCode != "" {
fmt.Printf("%s-%s %s;\n", Long2IP(rangeStart).String(), Long2IP(i-1).String(), lastIsoCode)
}
lastIsoCode = code
rangeStart = i
}
}
if lastIsoCode != "" {
fmt.Printf("%s-%s %s;\n", Long2IP(rangeStart).String(), Long2IP(endLong).String(), lastIsoCode)
}
os.Exit(0)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment