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

net: document possible networks for {Dialer,ListenConfig}.Control #69693

Open
favonia opened this issue Sep 28, 2024 · 2 comments
Open

net: document possible networks for {Dialer,ListenConfig}.Control #69693

favonia opened this issue Sep 28, 2024 · 2 comments

Comments

@favonia
Copy link
Contributor

favonia commented Sep 28, 2024

Go version

go version go1.23.1 linux/amd64

What did you do?

The Control function is useful for enforcing IPv4 or IPv6 on a dual-stack machine. The idea is to selectively reject IPv6 for IPv4-only connections and IPv4 for IPv6-only ones. However, in order to do so, it's crucial to identify known networks that could be sent to the Control function. A demonstration of the idea is at https://go.dev/play/p/ttwNDrCXpla

What did you see happen?

The current documentation says:

	// Network and address parameters passed to Control function are not
	// necessarily the ones passed to Dial. For example, passing "tcp" to Dial
	// will cause the Control function to be called with "tcp4" or "tcp6".

The documentation is uncommitted about the behavior in other scenarios, such as udp and ip:<protocol>.

What did you expect to see?

The source code (across all platforms) seems to indicate the following relation between Dial/Listen and Control:

Input network for Dial/Listen Possible network for Control
unix, unixgram, unixpacket, udp4, udp6, tcp4, tcp6 Same network value
udp udp4 or udp6 (but not udp)
tcp tcp4 or tcp6 (but not tcp)
ip4:<protocol> ip4
ip6:<protocol> ip6
ip:<protocol> ip4 or ip6 (but not ip)

If the table is accurate, I wonder if we can explicitly document it?

Edits (after some comments)

I did not mean we should literally document the whole table. Documenting the general rules behind the table is sufficient! My real question is, can we document the general rules and guarantee that they will be followed in the future?

@ianlancetaylor
Copy link
Contributor

Such a table risks going out of date. More importantly, I don't see what it adds. You will have to write your Control function to recognize all the networks you know about. If that goes out of date, the table you describe won't help.

@favonia
Copy link
Contributor Author

favonia commented Sep 29, 2024

@ianlancetaylor My primary objective is to enforce IPv4 or IPv6 exclusively on dual-stack machines. I agree the entire table might be excessive, but just a few additional assumptions can ensure the code's correctness. How about these two:

  1. Dual-stack networks (e.g., ip, udp, tcp) will not be passed to Control. The specific (single-stack) network will be determined before Control is invoked.
  2. When calling Dial/Listen with a network in the network:proto format (e.g., ip:icmp), the :proto part will not be passed to Control. Only the determined (single-stack) network type (e.g., ip4 or ip6) will be passed to Control.

These assumptions are essential for enforcing IPv4 or IPv6 using Control, which does not seem to be easy with the net package otherwise. (Another method is to intercept Dial/Listen, but that seems to rely on even more assumptions.)

The current documentation explicitly specifies the behavior for the tcp case. The first assumption extends it to cover other protocols, while the second assumption clarifies the :proto syntax. I believe these are reasonable or even implied assumptions that are unlikely to be violated, even as we introduce additional protocols like quic or sctp in the future. Using these two assumptions should also avoid the need to update a fixed table.


PS: I understand that, if the net package supports more networks in the future, my code at https://go.dev/play/p/ttwNDrCXpla will have to change to handle new networks, but the above two assumptions guarantee that there is always a way to do it! 😁

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

No branches or pull requests

3 participants