Comments (6)
Thanks for the detailed report!
I like this approach the most:
- We could create a new type in chain.go, called
PolicyVerdict
, that would be auint32
. We also make two const,PolicyDrop
andPolicyAccept
, which would be defined as equal to iota (so 0 and 1, exactly the netfilter numbers for DROP and ACCEPT.
Wouldn’t we have the same problem that we currently have if DROP maps to 0? Shouldn’t we use 1+x as our value space to distinguish the empty value from an explicitly set value?
This solution makes things easily understandable without any extra import, allow additional documentation about the
Policy
field (currently there isn't any doc about that field beside its definition) but is kind of redundant with theVerdictKind
type already existing in expr submodule.
I’m not too worried about that redundancy. Verdicts are used in different contexts than Policies, so they can have a separate type.
from nftables.
You indeed have a point about DROP mapping to 0, which makes it impossible to make the difference between an explicitely defined DROP policy and an undefined one.
I personally dislike the "hacky" approach of +1/-1, as it tends to get confusing for the end user dev and also can cause problems if you forget for a minute that it's here while working onto improving the type.
I'd suggest making the Policy
field in Chain
a pointer upon our new type. It will come with the drawback that the user cannot simply use our new type constants directly, (because you'd need to take the address of the constant through &
, which isn't possible because of limitations of the language itself), but at the same time it'll ensure the difference between uninitialised Policy
field (which would be nil
) and initialised field set to DROP (which would be a pointer to a myType which value would be 0 after dereferencing it).
Also, for the sake of keeping the same formatting as other types in chain.go, I'll name the new type ChainPolicy
. It sounds better than PolicyVerdict
and fits the Chain_somethingsomething_
format that is already used.
Here's few snipets of how I imagine the changes in the existing code and how it'd impact the use
// ChainPolicy defines what this chain default policy will be.
type ChainPolicy uint32
// Possible ChainPolicy values.
const (
ChainPolicyDrop ChainPolicy = iota
ChainPolicyAccept
)
// A Chain contains Rules. See also
// https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains
type Chain struct {
Name string
Table *Table
Hooknum ChainHook
Priority ChainPriority
Type ChainType
Policy *ChainPolicy
}
That way we just have to check if it's nil
or not, and change the way Policy
is used in Chain
related functions so it dereferences the pointer when the value is needed.
Effectively, the user would have to create his chains that way with those modifications:
var defaultPolicy = nftables.ChainPolicyDrop
conn.AddTable(&nftables.Table{
Family: nftables.TableFamilyIPv4,
Name: "filter",
})
conn.AddChain(&nftables.Chain{
Name: "forward",
Table: filterTable,
Type: nftables.ChainTypeFilter,
Hooknum: nftables.ChainHookForward,
Priority: nftables.ChainPriorityFilter,
Policy: &defaultPolicy,
})
I don't see any other way to keep the user space values aligned with the kernel space values, while solving our undefined != defined at DROP issue.
Let me know if you have any other idea or feedback on this one.
from nftables.
I’m a bit torn on using pointers. We don’t consistently do that in our current data structures, so introducing that here creates a bit of a mismatch.
On the other hand, I understand your concern about the constants not matching, which can be very confusing when debugging, depending on how you print data/values.
Perhaps using a pointer is the lesser evil after all.
from nftables.
There could be another approach but it also has its own pros and cons.
The MySQL connector for go deals with non-nullable types by creating its own types, such has this NullInt32.
Pros:
- Structs have their fields initialised by their default values. In our case, the
uint32
would be initialised to 0, and thebool
to false, which makes the check of an explicitly defined policy very easy. - DROP will be equal to 0, ACCEPT to 1, so we don't need to use the +1/-1 solution.
- It won't use pointers, which, I agree, can get confusing on devs who come from more high level languages/networking world and have reduced knowledge on how (de)referencing works. It should save some of us a lot of headaches.
Cons:
- We can't create constant structs (language limitation) BUT there would be a workaround were we could call a function that returns us an ACCEPT/DROP struct (so we can imagine something like
nftables.ChainDefaultPolicy(nftables.ChainPolicyDrop)
that returns astruct
initialised withuint32
at 0 andbool
at true). - This approach is probably harder to understand at first even if its usability is better than pointers.
from nftables.
Thanks for the thorough research.
I think the pointer solution is the most appealing over all, if only because some of our tables already have a *Table
pointer field.
from nftables.
I'm closing this as PR has been merged.
from nftables.
Related Issues (20)
- How to add the anonymous set of hours ? HOT 2
- How to reject packets? HOT 3
- Anonymous time collection problem HOT 10
- Please consider create a release/tag HOT 1
- Alignment issues on 32-bit archs: TestAlignedBuff32 & TestAlignedBuffInt32 failures HOT 9
- Test failures on s390x: endianness problems? HOT 11
- Reason for not wrapping libnftnl/libmnl. HOT 1
- GetRules lost expr.Masq HOT 1
- nftables go dynset implementation will not work with libnftnl versions <1.1.9 HOT 1
- High
- Feature: add support for monitor HOT 6
- AddSet IPv4 wrong byte order on Ubuntu 22.04 HOT 8
- Rule Handle not updated after InsertRule even using Flush. HOT 4
- Not all response messages are received causing the receive buffer to overflow HOT 8
- Named quotas and their usage in map HOT 1
- BUG: block in Conn.Flush() HOT 4
- How to get an error when try to add an existed table?
- Adding rules in code produces different results and logs than the rules I added directly from the command line HOT 6
- Use a CIDR prefix as target in a NAT rule HOT 3
- Troubleshooting NFTables Table Creation with Go HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from nftables.