Skip to content

Commit aa8348f

Browse files
authored
feat: add xt.Comment (google#260)
Signed-off-by: thediveo <[email protected]>
1 parent 20edd38 commit aa8348f

File tree

3 files changed

+99
-0
lines changed

3 files changed

+99
-0
lines changed

xt/comment.go

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package xt
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
)
7+
8+
// CommentSize is the fixed size of a comment info xt blob, see:
9+
// https://elixir.bootlin.com/linux/v6.8.7/source/include/uapi/linux/netfilter/xt_comment.h#L5
10+
const CommentSize = 256
11+
12+
// Comment gets marshalled and unmarshalled as a fixed-sized char array, filled
13+
// with zeros as necessary, see:
14+
// https://elixir.bootlin.com/linux/v6.8.7/source/include/uapi/linux/netfilter/xt_comment.h#L7
15+
type Comment string
16+
17+
func (c *Comment) marshal(fam TableFamily, rev uint32) ([]byte, error) {
18+
if len(*c) >= CommentSize {
19+
return nil, fmt.Errorf("comment must be less than %d bytes, got %d bytes",
20+
CommentSize, len(*c))
21+
}
22+
data := make([]byte, CommentSize)
23+
copy(data, []byte(*c))
24+
return data, nil
25+
}
26+
27+
func (c *Comment) unmarshal(fam TableFamily, rev uint32, data []byte) error {
28+
if len(data) != CommentSize {
29+
return fmt.Errorf("malformed comment: got %d bytes, expected exactly %d bytes",
30+
len(data), CommentSize)
31+
}
32+
*c = Comment(bytes.TrimRight(data, "\x00"))
33+
return nil
34+
}

xt/comment_test.go

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package xt
2+
3+
import (
4+
"reflect"
5+
"strings"
6+
"testing"
7+
)
8+
9+
func TestComment(t *testing.T) {
10+
t.Parallel()
11+
payload := Comment("The quick brown fox jumps over the lazy dog.")
12+
oversized := Comment(strings.Repeat("foobar", 100))
13+
tests := []struct {
14+
name string
15+
info InfoAny
16+
errmsg string
17+
}{
18+
{
19+
name: "un/marshal Comment round-trip",
20+
info: &payload,
21+
},
22+
{
23+
name: "marshal oversized Comment",
24+
info: &oversized,
25+
errmsg: "comment must be less than 256 bytes, got 600 bytes",
26+
},
27+
}
28+
29+
for _, tt := range tests {
30+
t.Run(tt.name, func(t *testing.T) {
31+
data, err := tt.info.marshal(0, 0)
32+
if err != nil {
33+
if tt.errmsg != "" && err.Error() == tt.errmsg {
34+
return
35+
}
36+
t.Fatalf("marshal error: %+v", err)
37+
38+
}
39+
if len(data) != CommentSize {
40+
t.Fatalf("marshal error: invalid size %d", len(data))
41+
}
42+
if data[len(data)-1] != 0 {
43+
t.Fatalf("marshal error: invalid termination")
44+
}
45+
var comment Comment
46+
var recoveredInfo InfoAny = &comment
47+
err = recoveredInfo.unmarshal(0, 0, data)
48+
if err != nil {
49+
t.Fatalf("unmarshal error: %+v", err)
50+
}
51+
if !reflect.DeepEqual(tt.info, recoveredInfo) {
52+
t.Fatalf("original %+v and recovered %+v are different", tt.info, recoveredInfo)
53+
}
54+
})
55+
}
56+
57+
oversizeddata := []byte(oversized)
58+
var comment Comment
59+
if err := (&comment).unmarshal(0, 0, oversizeddata); err == nil {
60+
t.Fatalf("unmarshal: expected error, but got nil")
61+
}
62+
}

xt/info.go

+3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ func Unmarshal(name string, fam TableFamily, rev uint32, data []byte) (InfoAny,
3434
case 1:
3535
i = &AddrTypeV1{}
3636
}
37+
case "comment":
38+
var c Comment
39+
i = &c
3740
case "conntrack":
3841
switch rev {
3942
case 1:

0 commit comments

Comments
 (0)