-
Notifications
You must be signed in to change notification settings - Fork 18
Canonicalize IPv4 addresses #27
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -818,8 +818,13 @@ func TestTreeByIP(t *testing.T) { | |
| } | ||
|
|
||
| func TestIPv4NetToUint32(t *testing.T) { | ||
| key, bits := iPv4NetToUint32(&net.IPNet{IP: net.IPv4zero, Mask: iPv4MaxMask}) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here you create If you try
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The 16-byte IPv4 mask case is explicitly incorrect, an explicit user error. The 16-byte IPv4 case, on the other hand, is expected behavior, and is part of the STL API. |
||
| if key != 0 || bits != 32 { | ||
| t.Errorf("Expected 0x0, 32 pair but got 0x%08x, %d", key, bits) | ||
| } | ||
|
|
||
| _, n, _ := net.ParseCIDR("192.0.2.0/24") | ||
| key, bits := iPv4NetToUint32(n) | ||
| key, bits = iPv4NetToUint32(n) | ||
| if key != 0xc0000200 || bits != 24 { | ||
| t.Errorf("Expected 0xc0000200, 24 pair but got 0x%08x, %d", key, bits) | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
normally,
IPNetshould have bothIPandMaskfields of the same size - either 4 or 16 bytes. It you successfully convert 16-bytesIPto 4-bytes here, theMaskwill still remain 16 bytes. Which willreturn 0, -1later.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is super easy to pass a 16-byte address and a 4-byte mask (as specified in the tests, when using the default IPv4s exposed by the STL), it is not a user error to do so, the IP struct explicitly has a To4 method to normalize an IPv4.
The IPMask, however, does not support IPv4 masks contained in 16-byte arrays, as is obvious by the fact that it has no associated To4 method.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, it's super easy in general to craft incorrect IPNets, e.g. 5-bytes IP and 7-bytes Mask, or just regular (not convertible to IPv4) 16-bytes IP and 4-bytes mask. The question is why do you pass such odd IPNets as input parameters?
In you external code, just make sure that the size of IP and Mask is the same. As you mentioned in another PR (in coredns project)
ParseCIDR()returns correctIPNets in all cases, i.e. IP and Mask are of the same size.If you create the
IPNets arguments by your own, the sizes of these two fields are also under your control. For example, you may want to convert IP to 4-bytes (if possible) and then initialize theIPNetwith 4-bytesIPand 4-bytesMaskIt is possible to create 16-bytes mask, as I mentioned in my comment to your test change. Mask is just a mask, it is a sequence of
1bits followed by sequence of0bits. Each bit in mask corresponds to one bit in IP. Method likeTo4()doesn't make sense for mask.Alternatively, this lib provides public methods taking IP as parameter. Such methods convert IPv4 from 16-bytes to 4-bytes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because something as trivial as
net.IPNet{IP: net.IPv4zero, Mask: iPv4MaxMask}isn't immediately obvious to be wrong.If you take
net.IPv4zero, which is a public STL constant representing an IPv4, you would expect it to contain an IPv4, but the library treats it as an IPv6 address, because it doesn't account for 16-byte IPv4 addresses due to this quirk in the STL.