Skip to content

proposal: x/sys/unix: add AppendSocketControlMessage #65775

@neild

Description

@neild

Proposal Details

I propose adding this function to golang.org/x/net/sys/unix:

// AppendSocketControlMessage appends a single socket control message to b,
// returning a new slice and the subslice of the message data.
func AppendSocketControlMessage(b []byte, level, typ int32, size int) (_, data []byte) {
        off := len(b)
        b = append(b, make([]byte, unix.CmsgSpace(size))...)
        h := (*unix.Cmsghdr)(unsafe.Pointer(&b[off]))
        h.Level = level
        h.Type = typ
        h.SetLen(unix.CmsgLen(size))
        return b, b[off+unix.CmsgSpace(0):][:size]
}

Sample usage:

var control []byte
control, data = AppendSocketControlMessage(control, unix.IPPROTO_IP, unix.IP_TOS)
data[0] = 0b000000_01 // set ECN field to ECT1
conn.WriteMessageUDPAddrPort(datagram, control, address)

Background and motivation:

The golang.org/x/net/sys/unix.ParseOneSocketControlMessage function parses a socket control message.

The unix package contains functions that can be used to create specific control messages, such as unix.PktInfo4. There are also functions which can be used to construct a control message, but they are ill-documented and cumbersome to use. For example, the implementation of PktInfo4 is:

func PktInfo4(info *Inet4Pktinfo) []byte {
        b := make([]byte, CmsgSpace(SizeofInet4Pktinfo))
        h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
        h.Level = SOL_IP
        h.Type = IP_PKTINFO
        h.SetLen(CmsgLen(SizeofInet4Pktinfo))
        *(*Inet4Pktinfo)(h.data(0)) = *info
        return b
}

Note that this uses the unexported function Cmsghdr.data. One can achieve the same effect with exported functions (unix.CmsgSpace(0) will give the offset to the data section), but there is still no convenient inverse to ParseOneSocketControlMessage.

AppendSocketControlMessage provides that inverse, giving a simple way to construct control messages for use with sendmsg.

As another example of usage, PktInfo4 rewritten in terms of AppendSocketControlMessage:

func PktInfo4(info *Inet4Pktinfo) []byte {
        b, data := AppendSocketControlMessage(nil, SOL_IP, IP_PKTINFO, SizeofInet4Pktinfo)
        *(*Inet4Pktinfo)(unsafe.Pointer(&data[0])) = *info
        return b
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Proposalcompiler/runtimeIssues related to the Go compiler and/or runtime.

    Type

    No type

    Projects

    Status

    Todo

    Status

    Incoming

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions