Skip to content

Commit d876b14

Browse files
committed
Initial commit.
1 parent 64d0c76 commit d876b14

File tree

4 files changed

+310
-0
lines changed

4 files changed

+310
-0
lines changed

.travis.yml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
language: go
2+
3+
go:
4+
- 1.2
5+
- 1.3.3
6+
- 1.4.2
7+
- 1.5
8+
- tip
9+
10+
script:
11+
- go test -v ./...

README.md

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# go-ipset
2+
3+
[![Build Status](https://api.travis-ci.org/gmccue/go-ipset.png?branch=master)](https://travis-ci.org/gmccue/go-ipset)
4+
[![GoDoc](https://godoc.org/github.com/gmccue/go-ipset?status.svg)](https://godoc.org/github.com/gmccue/go-ipset)
5+
6+
go-ipset provides basic bindings for the [ipset kernel utility](http://ipset.netfilter.org/).
7+
8+
## Installation
9+
```go
10+
go get github.com/gmccue/go-ipset
11+
```
12+
13+
## Usage
14+
The following are some basic usage examples for go-iptables. For more information, please [checkout the godoc](https://godoc.org/github.com/gmccue/go-ipset).
15+
16+
```go
17+
import "github.com/gmccue/ipset"
18+
19+
// Construct a new ipset instance
20+
ipset, err := ipset.New()
21+
if err != nil {
22+
// Your custom error handling here.
23+
}
24+
25+
// Create a new set
26+
err := ipset.Create("my_set", "hash:ip")
27+
if err != nil {
28+
// Your custom error handling here.
29+
}
30+
```
31+
32+
### Adding an entry to an ipset
33+
```go
34+
// Add a new entry to your ipset
35+
err := ipset.Add("my_set", "127.0.0.1")
36+
if err != nil {
37+
// Your custom error handling here.
38+
}
39+
```
40+
41+
### Removing an entry from an ipset
42+
```go
43+
err := ipset.Delete("my_set", "127.0.0.1")
44+
if err != nil {
45+
// Your custom error handling here.
46+
}
47+
```
48+
49+
### Save your ipset to a file
50+
```go
51+
err := ipset.Save("my_set", "/tmp/my_set.txt")
52+
if err != nil {
53+
// Your custom error handling here.
54+
}
55+
```
56+
57+
### Restore your ipset from a file
58+
```go
59+
err := ipset.Restore("/tmp/my_set.txt")
60+
if err != nil {
61+
// Your custom error handling here.
62+
}
63+
```

ipset.go

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Package ipset provides a basic wrapper to the ipset utility for IPTables.
2+
// More information about ipset can be found at:
3+
// http://ipset.netfilter.org/index.html
4+
package ipset
5+
6+
import (
7+
"bytes"
8+
"errors"
9+
"os/exec"
10+
)
11+
12+
type IPSet struct {
13+
Path string
14+
Options []string
15+
}
16+
17+
func New() (*IPSet, error) {
18+
binPath, err := exec.LookPath("ipset")
19+
if err != nil {
20+
return nil, err
21+
}
22+
23+
return &IPSet{binPath, []string{}}, nil
24+
}
25+
26+
// Create creates a new ipset with a given name and type.
27+
// For more on set types, please see:
28+
// http://ipset.netfilter.org/ipset.man.html#lbAT.
29+
// Additional options can be passed to the Create() command. These options must
30+
// be passed in a sequential key, value order.
31+
// For example, ipset.Create("test", "hash:ip", "timeout", "300") will add a
32+
// new set with the timeout option set to a value of 300.
33+
func (set *IPSet) Create(name string, typ string, options ...string) error {
34+
return set.run(append([]string{"create", name, typ}, options...)...)
35+
}
36+
37+
// Add adds a new entry to the named set.
38+
func (set *IPSet) Add(name string, entry string, options ...string) error {
39+
return set.run(append([]string{"add", name, entry}, options...)...)
40+
}
41+
42+
// AddUnique adds a new entry to the named set, if it does not already exist.
43+
func (set *IPSet) AddUnique(name, entry string, options ...string) error {
44+
return set.run(append([]string{"add", name, entry, "-exist"}, options...)...)
45+
}
46+
47+
// Delete removes an entry from the named set.
48+
func (set *IPSet) Delete(name string, entry string, options ...string) error {
49+
return set.run(append([]string{"del", name, entry}, options...)...)
50+
}
51+
52+
// Test tests if an entry exists in the named set.
53+
// The exit status is zero if the tested entry is in the set, and nonzero if
54+
// it is missing from the set.
55+
func (set *IPSet) Test(name string, entry string, options ...string) error {
56+
return set.run(append([]string{"test", name, entry}, options...)...)
57+
}
58+
59+
// Destroy destroys a named set, or all sets.
60+
func (set *IPSet) Destroy(name string) error {
61+
return set.run("destroy", name)
62+
}
63+
64+
// Save saves the named set or all sets to the given file.
65+
func (set *IPSet) Save(name string, filename string) error {
66+
return set.run("save", name, "-file", filename)
67+
}
68+
69+
// Restore restores a saved set from the given file.
70+
func (set *IPSet) Restore(filename string) error {
71+
return set.run("restore", "-file", filename)
72+
}
73+
74+
// Flush removes all entries from a named set.
75+
func (set *IPSet) Flush(name string) error {
76+
return set.run("flush", name)
77+
}
78+
79+
// Rename changes a set name from one value to another.
80+
func (set *IPSet) Rename(from string, to string) error {
81+
return set.run("rename", from, to)
82+
}
83+
84+
// Swap swaps the content of two existing sets.
85+
func (set *IPSet) Swap(from string, to string) error {
86+
return set.run("swap", from, to)
87+
}
88+
89+
func (set *IPSet) run(args ...string) error {
90+
var stderr bytes.Buffer
91+
cmd := exec.Cmd{
92+
Path: set.Path,
93+
Args: append([]string{set.Path}, args...),
94+
Stderr: &stderr,
95+
}
96+
97+
if err := cmd.Run(); err != nil {
98+
return errors.New(stderr.String())
99+
}
100+
101+
return nil
102+
}

ipset_test.go

+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
package ipset
2+
3+
import (
4+
"flag"
5+
"log"
6+
"os"
7+
"testing"
8+
)
9+
10+
var (
11+
ipset IPSet
12+
testSet = "test"
13+
testIP = "192.168.1.100"
14+
testOutfile = "./ipset.txt"
15+
)
16+
17+
// Perform test setup and teardown functions.
18+
func TestMain(m *testing.M) {
19+
flag.Parse()
20+
21+
set, err := New()
22+
if err != nil {
23+
log.Fatal("Could not setup the tests. Is ipset installed? Message:", err)
24+
}
25+
26+
ipset = *set
27+
28+
os.Exit(m.Run())
29+
}
30+
31+
func TestNewIPSet(t *testing.T) {
32+
_, err := New()
33+
if err != nil {
34+
t.Error("Could not construct a new set. Error was:", err)
35+
}
36+
}
37+
38+
func TestCreate(t *testing.T) {
39+
err := ipset.Create(testSet, "hash:ip", "timeout", "300")
40+
if err != nil {
41+
t.Error("Could not create a new set. Error was:", err)
42+
}
43+
}
44+
45+
func TestAdd(t *testing.T) {
46+
err := ipset.Add(testSet, testIP)
47+
if err != nil {
48+
t.Error("Could not add an entry to the test set. Error was:", err)
49+
}
50+
}
51+
52+
func TestAddUnique(t *testing.T) {
53+
err := ipset.AddUnique(testSet, testIP)
54+
if err != nil {
55+
t.Error("Could not add a unique entry to the test set. Error was:", err)
56+
}
57+
}
58+
59+
func TestTest(t *testing.T) {
60+
err := ipset.Test(testSet, testIP)
61+
if err != nil {
62+
t.Error("Error while testing for a set entry. Error was:", err)
63+
}
64+
65+
// The following IP should not exist in the set, so we expect an error.
66+
nonexistErr := ipset.Test(testSet, "192.168.100.1")
67+
if nonexistErr == nil {
68+
t.Error("Error while testing for a non-existent set entry. Error was:", err)
69+
}
70+
}
71+
72+
func TestDelete(t *testing.T) {
73+
err := ipset.Delete(testSet, testIP)
74+
if err != nil {
75+
t.Error("Could not delete an entry from the test set. Error was:", err)
76+
}
77+
}
78+
79+
func TestSave(t *testing.T) {
80+
err := ipset.Save(testSet, testOutfile)
81+
if err != nil {
82+
t.Error("Could not save the test set. Error was:", err)
83+
}
84+
}
85+
86+
func TestRestore(t *testing.T) {
87+
destroyErr := ipset.Destroy(testSet)
88+
if destroyErr != nil {
89+
t.Error("Could not destroy the set. Error was:", destroyErr)
90+
}
91+
92+
err := ipset.Restore(testOutfile)
93+
if err != nil {
94+
t.Error("Could not restore the set from a file. Error was:", err)
95+
}
96+
}
97+
98+
func TestFlush(t *testing.T) {
99+
err := ipset.Flush(testSet)
100+
if err != nil {
101+
t.Error("Could not flush the test set. Error was:", err)
102+
}
103+
}
104+
105+
func TestRename(t *testing.T) {
106+
err := ipset.Rename(testSet, "renamedSet")
107+
if err != nil {
108+
t.Error("Could not rename the test set. Error was:", err)
109+
}
110+
}
111+
112+
func TestSwap(t *testing.T) {
113+
newsetErr := ipset.Create(testSet, "hash:ip")
114+
if newsetErr != nil {
115+
t.Error("Could not create a new set for swapping. Error was:", newsetErr)
116+
}
117+
118+
err := ipset.Swap("renamedSet", testSet)
119+
if err != nil {
120+
t.Error("Could not swap sets. Error was:", err)
121+
}
122+
}
123+
124+
func TestDestroy(t *testing.T) {
125+
destErr := ipset.Destroy("renamedSet")
126+
if destErr != nil {
127+
t.Error("Could not destroy the copied set. Error was:", destErr)
128+
}
129+
130+
err := ipset.Destroy(testSet)
131+
if err != nil {
132+
t.Error("Could not destroy the test set. Error was:", err)
133+
}
134+
}

0 commit comments

Comments
 (0)