2020-07-18 09:19:27 +08:00
|
|
|
|
package zxipv6wry
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"encoding/binary"
|
|
|
|
|
"fmt"
|
2020-07-18 09:52:59 +08:00
|
|
|
|
"io/ioutil"
|
|
|
|
|
"log"
|
2020-07-18 09:19:27 +08:00
|
|
|
|
"math/big"
|
|
|
|
|
"net"
|
2020-07-18 09:52:59 +08:00
|
|
|
|
"os"
|
2020-07-18 09:19:27 +08:00
|
|
|
|
|
|
|
|
|
"github.com/zu1k/nali/pkg/common"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type ZXwry struct {
|
|
|
|
|
common.IPDB
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-18 09:52:59 +08:00
|
|
|
|
func NewZXwry(filePath string) ZXwry {
|
|
|
|
|
var tmpData []byte
|
|
|
|
|
var fileInfo common.FileInfo
|
|
|
|
|
|
|
|
|
|
// 判断文件是否存在
|
|
|
|
|
_, err := os.Stat(filePath)
|
|
|
|
|
if err != nil && os.IsNotExist(err) {
|
2020-07-18 09:59:48 +08:00
|
|
|
|
log.Println("文件不存在,请自行下载 ZX IPV6库,并保存在", filePath)
|
|
|
|
|
os.Exit(1)
|
2020-07-18 09:52:59 +08:00
|
|
|
|
} else {
|
|
|
|
|
// 打开文件句柄
|
|
|
|
|
fileInfo.FileBase, err = os.OpenFile(filePath, os.O_RDONLY, 0400)
|
|
|
|
|
if err != nil {
|
|
|
|
|
panic(err)
|
|
|
|
|
}
|
|
|
|
|
defer fileInfo.FileBase.Close()
|
|
|
|
|
|
|
|
|
|
tmpData, err = ioutil.ReadAll(fileInfo.FileBase)
|
|
|
|
|
if err != nil {
|
|
|
|
|
panic(err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fileInfo.Data = tmpData
|
|
|
|
|
|
|
|
|
|
return ZXwry{
|
|
|
|
|
IPDB: common.IPDB{
|
|
|
|
|
Data: &fileInfo,
|
|
|
|
|
IndexLen: 7,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-18 10:48:41 +08:00
|
|
|
|
func (db ZXwry) Find(ip string) (result string) {
|
|
|
|
|
db.Offset = 0
|
2020-07-18 09:19:27 +08:00
|
|
|
|
|
|
|
|
|
tp := big.NewInt(0)
|
|
|
|
|
op := big.NewInt(0)
|
|
|
|
|
tp.SetBytes(net.ParseIP(ip).To16())
|
|
|
|
|
op.SetString("18446744073709551616", 10)
|
|
|
|
|
op.Div(tp, op)
|
|
|
|
|
tp.SetString("FFFFFFFFFFFFFFFF", 16)
|
|
|
|
|
op.And(op, tp)
|
|
|
|
|
|
2020-07-18 10:48:41 +08:00
|
|
|
|
ipv6 := op.Uint64()
|
|
|
|
|
offset := db.searchIndex(ipv6)
|
|
|
|
|
country, area := db.getAddr(offset)
|
2020-07-18 09:19:27 +08:00
|
|
|
|
return fmt.Sprintf("%s %s", country, area)
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-18 10:48:41 +08:00
|
|
|
|
func (db *ZXwry) getAddr(offset uint32) (string, string) {
|
|
|
|
|
mode := db.ReadMode(offset)
|
2020-07-18 09:52:59 +08:00
|
|
|
|
if mode == common.RedirectMode1 {
|
2020-07-18 10:48:41 +08:00
|
|
|
|
offset = db.ReadUInt24()
|
|
|
|
|
return db.getAddr(offset)
|
2020-07-18 09:19:27 +08:00
|
|
|
|
}
|
2020-07-18 10:48:41 +08:00
|
|
|
|
_offset := db.Offset - 1
|
|
|
|
|
c1 := db.ReadArea(_offset)
|
2020-07-18 09:52:59 +08:00
|
|
|
|
if mode == common.RedirectMode2 {
|
2020-07-18 10:48:41 +08:00
|
|
|
|
db.Offset = 4 + _offset
|
2020-07-18 09:19:27 +08:00
|
|
|
|
} else {
|
2020-07-18 10:48:41 +08:00
|
|
|
|
db.Offset = _offset + uint32(1+len(c1))
|
2020-07-18 09:19:27 +08:00
|
|
|
|
}
|
2020-07-18 10:48:41 +08:00
|
|
|
|
c2 := db.ReadArea(db.Offset)
|
2020-07-18 09:19:27 +08:00
|
|
|
|
return string(c1), string(c2)
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-18 10:48:41 +08:00
|
|
|
|
func (db *ZXwry) searchIndex(ip uint64) uint32 {
|
|
|
|
|
db.ItemLen = 8
|
|
|
|
|
db.IndexLen = 11
|
2020-07-18 09:19:27 +08:00
|
|
|
|
|
2020-07-18 10:48:41 +08:00
|
|
|
|
header := db.Data.Data[8:24]
|
2020-07-18 09:52:59 +08:00
|
|
|
|
start := binary.LittleEndian.Uint32(header[8:])
|
2020-07-18 09:19:27 +08:00
|
|
|
|
counts := binary.LittleEndian.Uint32(header[:8])
|
2020-07-18 10:48:41 +08:00
|
|
|
|
end := start + counts*db.IndexLen
|
2020-07-18 09:19:27 +08:00
|
|
|
|
|
2020-07-18 10:48:41 +08:00
|
|
|
|
buf := make([]byte, db.IndexLen)
|
2020-07-18 09:19:27 +08:00
|
|
|
|
|
|
|
|
|
for {
|
2020-07-18 10:48:41 +08:00
|
|
|
|
mid := db.GetMiddleOffset(start, end)
|
|
|
|
|
buf = db.Data.Data[mid : mid+db.IndexLen]
|
|
|
|
|
_ip := binary.LittleEndian.Uint64(buf[:db.ItemLen])
|
2020-07-18 09:19:27 +08:00
|
|
|
|
|
2020-07-18 10:48:41 +08:00
|
|
|
|
if end-start == db.IndexLen {
|
|
|
|
|
if ip >= binary.LittleEndian.Uint64(db.Data.Data[end:end+db.ItemLen]) {
|
|
|
|
|
buf = db.Data.Data[end : end+db.IndexLen]
|
2020-07-18 09:19:27 +08:00
|
|
|
|
}
|
2020-07-18 10:48:41 +08:00
|
|
|
|
return common.ByteToUInt32(buf[db.ItemLen:])
|
2020-07-18 09:19:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if _ip > ip {
|
|
|
|
|
end = mid
|
|
|
|
|
} else if _ip < ip {
|
|
|
|
|
start = mid
|
|
|
|
|
} else if _ip == ip {
|
2020-07-18 10:48:41 +08:00
|
|
|
|
return common.ByteToUInt32(buf[db.ItemLen:])
|
2020-07-18 09:19:27 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|