]> Sergey Matveev's repositories - btrtrc.git/commitdiff
iplist: Begin adding support for parsing CIDR lists
authorMatt Joiner <anacrolix@gmail.com>
Thu, 1 Dec 2016 04:41:52 +0000 (15:41 +1100)
committerMatt Joiner <anacrolix@gmail.com>
Thu, 1 Dec 2016 04:41:52 +0000 (15:41 +1100)
iplist/cidr.go [new file with mode: 0644]
iplist/cidr_test.go [new file with mode: 0644]

diff --git a/iplist/cidr.go b/iplist/cidr.go
new file mode 100644 (file)
index 0000000..e131964
--- /dev/null
@@ -0,0 +1,41 @@
+package iplist
+
+import (
+       "bufio"
+       "io"
+       "net"
+)
+
+func ParseCIDRListReader(r io.Reader) (ret []Range, err error) {
+       s := bufio.NewScanner(r)
+       for s.Scan() {
+               err = func() (err error) {
+                       _, in, err := net.ParseCIDR(s.Text())
+                       if err != nil {
+                               return
+                       }
+                       ret = append(ret, Range{
+                               First: in.IP,
+                               Last:  IPNetLast(in),
+                       })
+                       return
+               }()
+               if err != nil {
+                       return
+               }
+       }
+       return
+}
+
+// Returns the last, inclusive IP in a net.IPNet.
+func IPNetLast(in *net.IPNet) (last net.IP) {
+       n := len(in.IP)
+       if n != len(in.Mask) {
+               panic("wat")
+       }
+       last = make(net.IP, n)
+       for i := 0; i < n; i++ {
+               last[i] = in.IP[i] | ^in.Mask[i]
+       }
+       return
+}
diff --git a/iplist/cidr_test.go b/iplist/cidr_test.go
new file mode 100644 (file)
index 0000000..ad904f5
--- /dev/null
@@ -0,0 +1,41 @@
+package iplist
+
+import (
+       "bytes"
+       "net"
+       "testing"
+
+       "github.com/stretchr/testify/assert"
+       "github.com/stretchr/testify/require"
+)
+
+func TestIPNetLast(t *testing.T) {
+       _, in, err := net.ParseCIDR("138.255.252.0/22")
+       require.NoError(t, err)
+       assert.EqualValues(t, []byte{138, 255, 252, 0}, in.IP)
+       assert.EqualValues(t, []byte{255, 255, 252, 0}, in.Mask)
+       assert.EqualValues(t, []byte{138, 255, 255, 255}, IPNetLast(in))
+       _, in, err = net.ParseCIDR("2400:cb00::/31")
+       require.NoError(t, err)
+       assert.EqualValues(t, []byte{0x24, 0, 0xcb, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, in.IP)
+       assert.EqualValues(t, []byte{255, 255, 255, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, in.Mask)
+       assert.EqualValues(t, []byte{0x24, 0, 0xcb, 1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, IPNetLast(in))
+}
+
+func TestParseCIDRList(t *testing.T) {
+       r := bytes.NewBufferString(`2400:cb00::/32
+2405:8100::/32
+2405:b500::/32
+2606:4700::/32
+2803:f800::/32
+2c0f:f248::/32
+2a06:98c0::/29
+`)
+       rs, err := ParseCIDRListReader(r)
+       require.NoError(t, err)
+       require.Len(t, rs, 7)
+       assert.EqualValues(t, Range{
+               First: net.IP{0x28, 3, 0xf8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+               Last:  net.IP{0x28, 3, 0xf8, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+       }, rs[4])
+}