-
-
Notifications
You must be signed in to change notification settings - Fork 14.4k
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
Add network library #299409
base: master
Are you sure you want to change the base?
Add network library #299409
Conversation
Added the first exposed function that creates IPv4Address structures from CIDR strings. Added basic tests to check the exposed function.
…om a CIDR and added more tests.
… a subnet mask and added tests.
…from an address and prefix length.
…ddress attrset. Specifying that it takes a string allows for other ingestion methods in the future.
@djacu in your previous PR you included a for example... let
droplet = ...; # JSON information from my vps provider
in
{
networking.interfaces.eth0.ipv4 = {
addresses = [
{
address = droplet.public.ipv4.ip_address;
prefixLength = with net.ipv4; subnetMaskToBitMask (cidrToIpAddress droplet.public.ipv4.netmask);
}
];
};
} |
@aanderse yes! The plan is incrementally add many of the features in the previous PR and some new ones I found while looking at other implementations. |
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.
A few suggestions. I haven't reviewed the IPv4 logic itself too thoroughly, and I think it'd be great if someone with more day to day exposure to these concepts could review that.
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.
This is going in the right direction!
lib/network/internal.nix
Outdated
*/ | ||
_encode = | ||
num: | ||
if num < 0 then |
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.
With the _parseCIDR
approach detailed above, this function won't have to check bounds anymore, since you can internally guarantee it won't be called with invalid arguments.
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.
For the time being this is true, but I have plans to add things in the future where having the bounds check will be necessary. Currently, the only part that requires it is subnet mask and I've already removed that per your other suggestion. So I'll remove this for now and we can hash it out in a future PR when subnet mask comes back in.
Sound good?
_parse "192.168.0.1/24" | ||
=> { | ||
address = "192.168.0.1"; | ||
cidr = "192.168.0.1/24"; |
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.
cidr = "192.168.0.1/24"; |
Doesn't seem to be in the result.
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.
You sure? I just created a test that fails to check the _parse
function and it definitely is in there.
:!./tests.sh
test case at ./tests.sh:138 failed: internal.ipv4._parse "192.168.0.1" "24" should have evaluated to "192.168.0.1":
"192.168.0.1"
but it evaluated to
{ address = "192.168.0.1"; cidr = "192.168.0.1/24"; prefixLength = "24"; subnetMask = "255.255.255.0"; }
shell returned 1
```nix | ||
_parse "192.168.0.1/24" | ||
=> { | ||
address = "192.168.0.1"; |
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.
Shouldn't this return something like [ 192 168 0 1 ]
, such that other functions can more easily work with the data instead of having to re-parse it?
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.
After thinking about it, that is a good idea. But I think this should be stored in an internal variable like _address
with the string representation stored in address
. The reason being that the general use case for the IP address is in it's string representation. But yeah having the internal representation as a list of ints is probably the best state to store it internally.
=> { | ||
address = "192.168.0.1"; | ||
cidr = "192.168.0.1/24"; | ||
prefixLength = "24"; |
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.
prefixLength = "24"; | |
prefixLength = 24; |
Similarly
Update upper bound check for ipv4 range Co-authored-by: Silvan Mosberger <github@infinisil.com>
…the default.nix file.
… which has been removed for now.
So this is the line in
I think it is because it the |
I may have found out why -> https://matrix.to/#/!avYyleMexqjFHoqrME:nixos.org/$L7FoTeNQhJOOeZRdrv-kWY4IEe2_FBALlI7f8BX2qOw?via=nixos.org&via=matrix.org&via=nixos.dev It seems at the moment, function references can't be nested. |
They can, but you need to use Line 447 in f8e37ff
|
@infinisil I've responded to you comments/suggestions. Not everything is resolved as I need more feedback from you. Can you take a look when you have a chance? |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/announcing-our-google-summer-of-code-participants/44618/3 |
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.
This doesn't parse IPv4, but a subset of IPv4: 192.1
is not valid with this parser, though, it's a valid IP address.
Please provide sources next time. This is a deep rabbit hole of of RFCs and specifications. RFC 791 specifies "Addresses are fixed length of four octets (32 bits)." in Section 2.3. RFC 6943 Section 3.1.1 also defines an address this way. It also references RFC3493 Section 6.1 and several functions from IEEE 1003.1 for alternative implementations including octal and hexadecimal representations as well as representations with less than 4 parts. However, it categorizes these short hand forms as "loose" forms and mentions their issues with ambiguity and security. This ambiguity would have to be resolved before an implementation could be submitted. Additionally, I referenced Python, Rust, and Haskell as references. As far as I can tell, none of them implement this short hand notation and only parse addresses where all 4 octets are present. Finally, this is a MVP version of #258250 which was reduced in size and scope at @infinisil's request (and came with some design improvements). Adding short hand IP address parsing should not be included at this time to keep the scope small. It could be added as a feature in the future after a design has been submitted to mitigate the ambiguities. However, since 3 other major languages don't implement this, I don't see why we should either. |
hey @djacu 👋 thank you for all of the work you have put into this! it looks like a fair bit of effort on your part to address all the helpful comments from @infinisil and @roberth! ❤️ i also appreciate the research you did in order to respond to @RaitoBezarius! it seems like you covered the concern quite well and have demonstrated established norms, all of which make sense to me from my years of experience is everyone happy with merging this? i think it would be very helpful to have this PR merged so it doesn't cause any problems for the GSoC student who intends to continue with the great work you've started here ... i would hate to see a GSoC student or Dan do a bunch of redundant work @infinisil - all good? 🙂 |
hey @aanderse I think there is still a bunch of improvements that should be made in this pr. You can see a rough timeline here: https://summerofcode.withgoogle.com/organizations/nixos-foundation/programs/2024/timeline |
@Janik-Haag awesome to hear! thanks for the update, i'm looking forward to tracking this |
Apologies, I lack of time these last days.
I do not think that 3 major languages not implementing this is ground enough for rejection, my rationale is that any parser we should have in lib should always be liberal in the inputs and strict in the output. A program that is known to handle this is We could adopt I didn't understand this was an MVP, I will retract my feedback then. |
thought it was a complete library; it's only a MVP
- `prefixLength`: A prefix length. | ||
- `subnetMask`: A subnet mask. | ||
|
||
- [`lib.network.ipv4.fromCidrString`](#function-library-lib.network.ipv4.fromCidrString): |
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.
I am not really familiar with the documentation syntax, but it looks like L19-21 content redundant with documentation of function below... Does it really need to be duplicated?
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.
Does this comment even get rendered?
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.
I think fromCidrString
was not meant to be part of the above list.
- `prefixLength`: A prefix length. | ||
- `subnetMask`: A subnet mask. | ||
|
||
- [`lib.network.ipv4.fromCidrString`](#function-library-lib.network.ipv4.fromCidrString): |
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.
Does this comment even get rendered?
- `prefixLength`: A prefix length. | ||
- `subnetMask`: A subnet mask. | ||
|
||
- [`lib.network.ipv4.fromCidrString`](#function-library-lib.network.ipv4.fromCidrString): |
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.
I think fromCidrString
was not meant to be part of the above list.
prefixLength | ||
]; | ||
inherit address prefixLength; | ||
}; |
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.
Consider setting _type = "ipv4Address";
for runtime type checking. This can improve error messages when addresses end up in wrong places; useful even if this library doesn't check _type
.
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.
This also reminds me that a type in the module system would be nice (for later perhaps).
It could parse both stringly definitions and pass through _type
-ed definitions.
Description of changes
See #258250 for discussion about why this would be beneficial to nixpkgs.
This PR was created at the request of @infinisil to be smaller and include a design document.
The design document is fairly terse. Any comments or feedback are welcome to help improve it.
Considerations for this PR and differences from the previous PR.
IPv4Address
attrsets will be exposed.IPv4Address
attrset is limited to keep the PR small. More attributes will be implemented in the future.Things done
Add a 👍 reaction to pull requests you find important.