1
0
mirror of https://github.com/zu1k/nali.git synced 2025-01-22 21:29:02 +08:00
nali/pkg/zxipv6wry/zxipv6wry.go

129 lines
2.6 KiB
Go
Raw Normal View History

2020-07-18 09:19:27 +08:00
package zxipv6wry
import (
"encoding/binary"
2021-08-02 12:01:25 +08:00
"errors"
2020-07-18 09:19:27 +08:00
"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-19 07:41:58 +08:00
"strings"
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 {
2020-07-20 20:31:12 +08:00
var fileData []byte
2020-07-18 14:18:54 +08:00
var fileInfo common.FileData
2020-07-18 09:52:59 +08:00
_, err := os.Stat(filePath)
if err != nil && os.IsNotExist(err) {
2020-07-20 20:31:12 +08:00
log.Println("文件不存在尝试从网络获取最新ZX IPv6数据库")
fileData, err = Download(filePath)
if err != nil {
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()
2020-07-20 20:31:12 +08:00
fileData, err = ioutil.ReadAll(fileInfo.FileBase)
2020-07-18 09:52:59 +08:00
if err != nil {
panic(err)
}
}
2020-07-20 20:31:12 +08:00
fileInfo.Data = fileData
2020-07-18 09:52:59 +08:00
return ZXwry{
IPDB: common.IPDB{
2020-07-22 06:45:58 +08:00
Data: &fileInfo,
2020-07-18 09:52:59 +08:00
},
}
}
2021-08-02 12:01:25 +08:00
func (db ZXwry) Find(query string, params ...string) (result fmt.Stringer, err error) {
ip := net.ParseIP(query)
if ip == nil {
return nil, errors.New("Query should be IPv6")
}
ip6 := ip.To16()
if ip6 == nil {
return nil, errors.New("Query should be IPv6")
}
2020-07-18 09:19:27 +08:00
tp := big.NewInt(0)
op := big.NewInt(0)
2021-08-02 12:01:25 +08:00
tp.SetBytes(ip6)
2020-07-18 09:19:27 +08:00
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-19 07:41:58 +08:00
2021-08-02 12:01:25 +08:00
result = common.Result{
Country: strings.ReplaceAll(country, " CZ88.NET", ""),
Area: strings.ReplaceAll(area, " CZ88.NET", ""),
}
return result, nil
2020-07-18 09:19:27 +08:00
}
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-19 19:51:54 +08:00
realOffset := db.Offset - 1
c1 := db.ReadArea(realOffset)
2020-07-18 09:52:59 +08:00
if mode == common.RedirectMode2 {
2020-07-19 19:51:54 +08:00
db.Offset = 4 + realOffset
2020-07-18 09:19:27 +08:00
} else {
2020-07-19 19:51:54 +08:00
db.Offset = realOffset + 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 {
2020-07-19 19:51:54 +08:00
header := db.ReadData(16, 8)
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-22 06:45:58 +08:00
end := start + counts*11
2020-07-18 09:19:27 +08:00
2020-07-22 06:45:58 +08:00
buf := make([]byte, 11)
2020-07-18 09:19:27 +08:00
for {
2020-07-22 06:45:58 +08:00
mid := common.GetMiddleOffset(start, end, 11)
2020-07-19 19:51:54 +08:00
buf = db.ReadData(11, mid)
ipBytes := binary.LittleEndian.Uint64(buf[:8])
2020-07-18 09:19:27 +08:00
2020-07-22 06:45:58 +08:00
if end-start == 11 {
2020-07-19 19:51:54 +08:00
if ip >= binary.LittleEndian.Uint64(db.ReadData(8, end)) {
buf = db.ReadData(11, end)
2020-07-18 09:19:27 +08:00
}
2020-07-19 19:51:54 +08:00
return common.ByteToUInt32(buf[8:])
2020-07-18 09:19:27 +08:00
}
2020-07-19 19:51:54 +08:00
if ipBytes > ip {
2020-07-18 09:19:27 +08:00
end = mid
2020-07-19 19:51:54 +08:00
} else if ipBytes < ip {
2020-07-18 09:19:27 +08:00
start = mid
2020-07-19 19:51:54 +08:00
} else if ipBytes == ip {
return common.ByteToUInt32(buf[8:])
2020-07-18 09:19:27 +08:00
}
}
}