segments iterate with CIDR supports

This commit is contained in:
lionsoul2014 2026-05-16 10:58:49 +08:00
parent f939363a19
commit 072b6fed24
4 changed files with 35 additions and 37 deletions

View File

@ -3,8 +3,16 @@
192.168.2.31|192.168.2.60|0|0|内网IP|办公室B
192.168.2.61|192.168.2.91|0|0|内网IP|办公室B
223.255.236.0|223.255.239.255|中国|上海|上海市|电信
# ipv4 cidr
14.32.46.0/24|3491 4766 9696|IGP
24.104.37.0/24|14537 174 7922 7016 401657 401657|IGP
45.15.32.0/22|14537 29119 206496 206496 206496 206496 206496 206496 206496 206496 206496|IGP
2c0f:fff1::|2c0f:ffff:ffff:ffff:ffff:ffff:ffff:ffff|毛里求斯|威廉平原区|卡特勒博尔纳|专线用户
2e00::|2fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff|德国|黑森|美因河畔法兰克福|专线用户
3000::|fbff:ffff:ffff:ffff:ffff:ffff:ffff:ffff|瑞士|弗里堡州||专线用户
fe00::|fe7f:ffff:ffff:ffff:ffff:ffff:ffff:ffff|瑞士|弗里堡州||专线用户
fe80::|febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff|瑞士|弗里堡州||专线用户
# ipv6 cidr
2c0f:fda8::/32|4635 6939 37662 37662 37035 37349|IGP
2c0f:fdb0::/32|3491 33765|IGP
2c0f:fe08:7::/48|2497 6939 36914|IGP

View File

@ -15,7 +15,7 @@ type Segment struct {
Region *Region
}
func SegmentFrom(seg string, cRegion func(string) *Region) (*Segment, error) {
func ParseSegment(seg string) ([]byte, []byte, string, error) {
var count = 0
var ps = StringTokenizer(strings.TrimSpace(seg), "|", func(s string, start int) bool {
// CIDR format
@ -36,36 +36,45 @@ func SegmentFrom(seg string, cRegion func(string) *Region) (*Segment, error) {
rIdx = 1
sip, eip, err = CIDR2Range(ps[0])
if err != nil {
return nil, fmt.Errorf("parse cidr: %s", err)
return nil, nil, "", fmt.Errorf("parse cidr: %s", err)
}
case 3:
// triditional ip range
rIdx = 2
sip, err = ParseIP(ps[0])
if err != nil {
return nil, fmt.Errorf("parse start ip `%s`: %s", ps[0], err)
return nil, nil, "", fmt.Errorf("parse start ip `%s`: %s", ps[0], err)
}
eip, err = ParseIP(ps[1])
if err != nil {
return nil, fmt.Errorf("check end ip `%s`: %s", ps[1], err)
return nil, nil, "", fmt.Errorf("check end ip `%s`: %s", ps[1], err)
}
default:
return nil, fmt.Errorf("invalid ip segment `%s`", seg)
return nil, nil, "", fmt.Errorf("invalid ip segment `%s`", seg)
}
if len(sip) != len(eip) {
return nil, fmt.Errorf("invalid ip segment line `%s`, sip/eip version not match", seg)
return nil, nil, "", fmt.Errorf("invalid ip segment line `%s`, sip/eip version not match", seg)
}
if IPCompare(sip, eip) > 0 {
return nil, fmt.Errorf("start ip(%s) should not be greater than end ip(%s)", ps[0], ps[1])
return nil, nil, "", fmt.Errorf("start ip(%s) should not be greater than end ip(%s)", ps[0], ps[1])
}
return sip, eip, ps[rIdx], nil
}
func SegmentFrom(seg string, cRegion func(string) *Region) (*Segment, error) {
sip, eip, region, err := ParseSegment(seg)
if err != nil {
return nil, err
}
return &Segment{
StartIP: sip,
EndIP: eip,
Region: cRegion(ps[rIdx]),
Region: cRegion(region),
}, nil
}

View File

@ -200,38 +200,14 @@ func IterateSegments(handle *os.File, autoMerge bool, before func(l string), fil
before(l)
}
var ps = strings.SplitN(l, "|", 3)
if len(ps) != 3 {
return totalCount, mergeCount, fmt.Errorf("invalid ip segment line `%s`", l)
}
sip, err := ParseIP(ps[0])
sip, eip, region, err := ParseSegment(l)
if err != nil {
return totalCount, mergeCount, fmt.Errorf("check start ip `%s`: %s", ps[0], err)
return totalCount, mergeCount, err
}
eip, err := ParseIP(ps[1])
if err != nil {
return totalCount, mergeCount, fmt.Errorf("check end ip `%s`: %s", ps[1], err)
}
if len(sip) != len(eip) {
return totalCount, mergeCount, fmt.Errorf("invalid ip segment line `%s`, sip/eip version not match", l)
}
if IPCompare(sip, eip) > 0 {
return totalCount, mergeCount, fmt.Errorf("start ip(%s) should not be greater than end ip(%s)", ps[0], ps[1])
}
// Allow empty region info since 2024/09/24
// if len(ps[2]) < 1 {
// return fmt.Errorf("empty region info in segment line `%s`", l)
// }
// check and do the region filter
var region = ps[2]
if filter != nil {
region, err = filter(ps[2])
region, err = filter(region)
if err != nil {
return totalCount, mergeCount, fmt.Errorf("failed to filter region `%s`: %s", region, err)
}

View File

@ -292,12 +292,17 @@ func TestIterateSegments(t *testing.T) {
t.Fatalf("failed to open tests file: %s", err)
}
_, _, _ = IterateSegments(handle, true, func(l string) {
total, merged, err := IterateSegments(handle, true, func(l string) {
// fmt.Printf("load segment: `%s`\n", l)
}, nil, NewRegion, func(seg *Segment) error {
fmt.Printf("get segment: `%s`\n", seg)
fmt.Printf("{%s, %s} -> `%s`\n", IP2String(seg.StartIP), IP2String(seg.EndIP), seg.Region)
return nil
})
if err != nil {
t.Fatalf("iterate error: %s", err)
}
fmt.Printf("done iterate -> total:%d, merged:%d\n", total, merged)
}
func TestStringTokenizer(t *testing.T) {