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

proposal: x/net/ipv4: add wrappers for Write/WriteToIP and Read/ReadFromIP #66461

Open
povsister opened this issue Mar 22, 2024 · 1 comment
Open
Labels
Milestone

Comments

@povsister
Copy link

povsister commented Mar 22, 2024

Brief for proposal

Add four wrapper function on ipv4.RawConn with detailed documentation.
Current doc is inferred from embed field, it is misleading even wrong in the context of ipv4.RawConn.

Described as below.

// Write writes a raw IPv4 datagram to the underlying socket.
// It will NOT prepend IPv4 header to the datagram, and it is caller's
// responsibility to provide correct IPv4 header on the wire per platform bias.
// See "x/net/ipv4/header.go" for details.
func (c *RawConn) Write(b []byte) (int, error) {
	// wrapper fn act same as before
}

// WriteToIP acts like Write but takes a *net.IPAddr as target for writing.
// It will NOT prepend IPv4 header to the datagram, and it is caller's
// responsibility to provide correct IPv4 header on the wire per platform bias.
// See "x/net/ipv4/header.go" for details.
func (c *RawConn) WriteToIP(b []byte, addr *net.IPAddr) (int, error) {
	// wrapper fn act same as before
}

// Read reads a raw IPv4 datagram into b, including IPv4 header, 
// returns the length read or an error.
// It's callers responsibility to parse IPv4 header per platform bias.
// See "x/net/ipv4/header.go" for details.
func (c *RawConn) Read(b []byte) (int, error) {
	// wrapper fn act same as before
}

// ReadFromIP reads an IPv4 datagram and write its payload into b,
// returns the length of payload and remote IPAddr.
func (c *RawConn) ReadFromIP(b []byte) (int, *net.IPAddr, error) {
	// wrapper fn act same as before
}

Proposal detail

Currently, functions on ipv4.RawConn are mostly provided by anonymous embed field, so with its doc.
I am confused with similar function names, but things they do completely different.

For example:
Read, ReadFrom and ReadFromIP.
Write, WriteTo and WriteToIP.
I just list fn signature and its doc below for quick reference.

Here is WHAT I HAVE OBSERVED

Read/Write is provided by *net.conn embed in field "packetHandler.IPConn"
ReadFrom/WriteTo is directly provided by embed field "packetHandler"
ReadFromIP/WriteToIP is provided by *net.IPConn embed in field "packetHandler"

The doc for ReadFromIP is not correct in the context of ipv4.RawConn, also the doc for Read is not very useful, and does not warn user that the wire format of IPv4 header may vary between platforms.
This is also true for Write*** situations.

eg: Some BSD-like systme including macOS have the ip_len and ip_off fields converted to host byte order after packets recived, and expcting host byte order for ip_len and ip_off fields while sending packets.
Those cases are already handled in x/net/ipv4/header.go, but we also should warn users about the differences while manipulating raw IPv4 datagrams.

type RawConn struct {
	genericOpt
	dgramOpt
	packetHandler
}

// Read implements the Conn Read method.
func (c *conn) Read(b []byte) (int, error)

// ReadFrom reads an IPv4 datagram from the endpoint c, copying the
// datagram into b. It returns the received datagram as the IPv4
// header h, the payload p and the control message cm.
func (c *packetHandler) ReadFrom(b []byte) (h *Header, p []byte, cm *ControlMessage, err error)

// ReadFromIP acts like ReadFrom but returns an IPAddr.
func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error)

// Write implements the Conn Write method.
func (c *conn) Write(b []byte) (int, error)

// WriteTo writes an IPv4 datagram through the endpoint c, copying the
// datagram from the IPv4 header h and the payload p. The control
// message cm allows the datagram path and the outgoing interface to be
// specified.  Currently only Darwin and Linux support this. The cm
// may be nil if control of the outgoing datagram is not required.
//
// The IPv4 header h must contain appropriate fields that include:
//
//	Version       = <must be specified>
//	Len           = <must be specified>
//	TOS           = <must be specified>
//	TotalLen      = <must be specified>
//	ID            = platform sets an appropriate value if ID is zero
//	FragOff       = <must be specified>
//	TTL           = <must be specified>
//	Protocol      = <must be specified>
//	Checksum      = platform sets an appropriate value if Checksum is zero
//	Src           = platform sets an appropriate value if Src is nil
//	Dst           = <must be specified>
//	Options       = optional
func (c *packetHandler) WriteTo(h *Header, p []byte, cm *ControlMessage) error

// WriteToIP acts like [IPConn.WriteTo] but takes an [IPAddr].
func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error)
@gopherbot gopherbot added this to the Proposal milestone Mar 22, 2024
@ianlancetaylor
Copy link
Contributor

CC @neild

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

No branches or pull requests

3 participants