Skip to content

Commit

Permalink
chinaip
Browse files Browse the repository at this point in the history
  • Loading branch information
DarienRaymond committed Dec 8, 2015
1 parent 0ccce0f commit c19341f
Show file tree
Hide file tree
Showing 9 changed files with 12,895 additions and 6,344 deletions.
6,354 changes: 6,354 additions & 0 deletions app/router/rules/json/chinaip.go

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions app/router/rules/json/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ func parseRule(msg json.RawMessage) rules.Rule {
}
return fieldrule
}
if rule.Type == "chinaip" {
chinaiprule := new(ChinaIPRule)
if err := json.Unmarshal(msg, chinaiprule); err != nil {
log.Error("Invalid chinaip rule: %v", err)
return nil
}
return chinaiprule
}
log.Error("Unknown router rule type: %s", rule.Type)
return nil
}
Expand Down
97 changes: 97 additions & 0 deletions common/net/ipnet.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package net

import (
"net"
)

var (
onesCount = make(map[byte]byte)
)

type IPNet struct {
cache map[uint32]byte
}

func NewIPNet() *IPNet {
return NewIPNetInitialValue(make(map[uint32]byte, 1024))
}

func NewIPNetInitialValue(data map[uint32]byte) *IPNet {
return &IPNet{
cache: data,
}
}

func ipToUint32(ip net.IP) uint32 {
value := uint32(0)
for _, b := range []byte(ip) {
value <<= 8
value += uint32(b)
}
return value
}

func ipMaskToByte(mask net.IPMask) byte {
value := byte(0)
for _, b := range []byte(mask) {
value += onesCount[b]
}
return value
}

func (this *IPNet) Add(ipNet *net.IPNet) {
ipv4 := ipNet.IP.To4()
if ipv4 == nil {
// For now, we don't support IPv6
return
}
value := ipToUint32(ipv4)
mask := ipMaskToByte(ipNet.Mask)
existing, found := this.cache[value]
if !found || existing > mask {
this.cache[value] = mask
}
}

func (this *IPNet) Contains(ip net.IP) bool {
ipv4 := ip.To4()
if ipv4 == nil {
return false
}
originalValue := ipToUint32(ipv4)

if entry, found := this.cache[originalValue]; found {
if entry == 0 {
return true
}
}

mask := uint32(0)
for maskbit := byte(1); maskbit <= 32; maskbit++ {
mask += 1 << uint32(32-maskbit)

maskedValue := originalValue & mask
if entry, found := this.cache[maskedValue]; found {
if entry == maskbit {
return true
}
}
}
return false
}

func (this *IPNet) Serialize() []uint32 {
content := make([]uint32, 0, 2*len(this.cache))
for key, value := range this.cache {
content = append(content, uint32(key), uint32(value))
}
return content
}

func init() {
value := byte(0)
for mask := byte(1); mask <= 8; mask++ {
value += 1 << byte(8-mask)
onesCount[value] = mask
}
}
42 changes: 42 additions & 0 deletions common/net/ipnet_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package net_test

import (
"net"
"testing"

. "github.com/v2ray/v2ray-core/common/net"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)

func parseCIDR(str string) *net.IPNet {
_, ipNet, err := net.ParseCIDR(str)
assert.Error(err).IsNil()
return ipNet
}

func TestIPNet(t *testing.T) {
v2testing.Current(t)

ipNet := NewIPNet()
ipNet.Add(parseCIDR(("0.0.0.0/8")))
ipNet.Add(parseCIDR(("10.0.0.0/8")))
ipNet.Add(parseCIDR(("100.64.0.0/10")))
ipNet.Add(parseCIDR(("127.0.0.0/8")))
ipNet.Add(parseCIDR(("169.254.0.0/16")))
ipNet.Add(parseCIDR(("172.16.0.0/12")))
ipNet.Add(parseCIDR(("192.0.0.0/24")))
ipNet.Add(parseCIDR(("192.0.2.0/24")))
ipNet.Add(parseCIDR(("192.168.0.0/16")))
ipNet.Add(parseCIDR(("198.18.0.0/15")))
ipNet.Add(parseCIDR(("198.51.100.0/24")))
ipNet.Add(parseCIDR(("203.0.113.0/24")))
ipNet.Add(parseCIDR(("8.8.8.8/32")))
assert.Bool(ipNet.Contains(net.ParseIP("192.168.1.1"))).IsTrue()
assert.Bool(ipNet.Contains(net.ParseIP("192.0.0.0"))).IsTrue()
assert.Bool(ipNet.Contains(net.ParseIP("192.0.1.0"))).IsFalse()
assert.Bool(ipNet.Contains(net.ParseIP("0.1.0.0"))).IsTrue()
assert.Bool(ipNet.Contains(net.ParseIP("1.0.0.1"))).IsFalse()
assert.Bool(ipNet.Contains(net.ParseIP("8.8.8.7"))).IsFalse()
assert.Bool(ipNet.Contains(net.ParseIP("8.8.8.8"))).IsTrue()
}
Loading

0 comments on commit c19341f

Please sign in to comment.