Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: add support for comments #118

Open
profawk opened this issue Apr 23, 2021 · 8 comments
Open

feature: add support for comments #118

profawk opened this issue Apr 23, 2021 · 8 comments

Comments

@profawk
Copy link

profawk commented Apr 23, 2021

When adding rules there could be an option to set the UserData field to a comment with a helper function maybe
Or maybe add a field, this however is not as good of an option IMO because when flushing the rule the library will need to override the UserData field.
I do not know if it is used for anything else currently, i have only looked it the nft and kernel impl of comments to see if I could do it alone 😄

@stapelberg
Copy link
Collaborator

The UserData field was last touched in commit 0b3d8b5 by @sbezverk — any comments on this?

@sbezverk
Copy link
Contributor

@profawk Here is an example how UserData is used: https://github.com/sbezverk/nftableslib/blob/master/nfrules.go#L244, please let me know if you have further questions.

@msdean
Copy link

msdean commented May 2, 2022

This features doesn't seem to work for me.
I can add a comment to a rule (with nft cmdline) and I do see it in the UserData field when printing out the rule content. So the "Read" direction works.

But when I try to add UserData to a rule, while it does seem to be added (I see the bytes in the rule dump), I don't see the comment when listing the ruleset with the nft cmdline tool.

Example:
This was added with the cmdline:

meta l4proto . ip6 saddr . ip6 daddr . th dport @ip6_rule_collection_2_drop jump drop_actions comment "test comment"

And this is the dump:

&nftables.Rule{..., UserData:[]uint8{0x0, 0xd, 0x74, 0x65, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0}}

So far so good.

And this is the other way around:

	rule := &nftables.Rule{...}
	rule.UserData = []byte("another test comment")
	c.AddRule(rule)
        c.Flush()

And this is the dump I get (also good):

&nftables.Rule{...UserData:[]uint8{0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x2, 0x2, 0x0, 0x0}}

Again, so far so good.

But when I list the ruleset with nft cmdline, I don't get a comment. I see the rule, but no comment at the end.

Also, unrelated but could be useful to also have UserData support for sets and set elements. Netlink obviously supports it, and implementation should be pretty similar to rule comments (or so I gather from the code, but I didn't deep dive), just use NFTA_SET_USERDATA/NFTA_SET_ELEM_USERDATA.

@stv0g
Copy link
Contributor

stv0g commented Oct 18, 2022

@msdean I seem to have the same issue as you.

@stv0g
Copy link
Contributor

stv0g commented Oct 18, 2022

Okay, I solved it:

libnftl uses TVLs to encode different types of fields in the UserData attribute.
This has been added via this patch: https://git.netfilter.org/libnftnl/commit/?id=5c3bc232dc9d1dd01d589fab096f67d944621fc2

Here is some quick example code to encode comments in the UserData:

package proxy

import "encoding/binary"

type NftablesUserDataType byte

const (
	NftablesUserDataTypeComment NftablesUserDataType = iota
	NftablesUserDataTypeRuleID  NftablesUserDataType = 100 // custom extension
)

func NftablesUserDataPut(udata []byte, typ NftablesUserDataType, data []byte) []byte {
	udata = append(udata, byte(typ), byte(len(data)))
	udata = append(udata, data...)

	return udata
}

func NftablesUserDataGet(udata []byte, styp NftablesUserDataType) []byte {
	for {
		if len(udata) < 2 {
			break
		}

		typ := NftablesUserDataType(udata[0])
		length := int(udata[1])
		data := udata[2 : 2+length]

		if styp == typ {
			return data
		}

		if len(udata) < 2+length {
			break
		} else {
			udata = udata[2+length:]
		}
	}

	return nil
}

func NftablesUserDataPutInt(udata []byte, typ NftablesUserDataType, num uint32) []byte {
	data := make([]byte, 4)
	binary.LittleEndian.PutUint32(data, num)

	return NftablesUserDataPut(udata, typ, data)
}

func NftablesUserDataGetInt(udata []byte, typ NftablesUserDataType) (uint32, bool) {
	data := NftablesUserDataGet(udata, typ)
	if data == nil {
		return 0, false
	}

	return binary.LittleEndian.Uint32(data), true
}

func NftablesUserDataPutString(udata []byte, typ NftablesUserDataType, str string) []byte {
	data := append([]byte(str), 0)
	return NftablesUserDataPut(udata, typ, data)
}

func NftablesUserDataGetString(udata []byte, typ NftablesUserDataType) (string, bool) {
	data := NftablesUserDataGet(udata, typ)
	if data == nil {
		return "", false
	}

	return string(data), true
}


func AddRule(r *nftables.Rule) {
	[...]
	r.UserData = NftablesUdataPutString(r.UserData, NftablesUserDataTypeComment, "this is my comment")
	r.UserData = NftablesUdataPutInt(r.UserData, NftablesUserDataTypeRuleId, uint32(1234))
	[...]
	ruleID, ok := NftablesUdataGetInt(r.UserData, NftablesUserDataTypeRuleId)
	comment, ok := NftablesUdataGetString(r.UserData, NftablesUserDataTypeComment)
}

@fungaren
Copy link

fungaren commented Apr 3, 2023

@stv0g Very nice code. I strongly recommend making a PR to add these methods to nftables.Rule struct.

@stv0g
Copy link
Contributor

stv0g commented Apr 15, 2023

I submitted a PR #221

@stv0g
Copy link
Contributor

stv0g commented Apr 15, 2023

Also related to #123?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants