golang.org/x/sys@v0.20.1-0.20240517151509-673e0f94c16d/unix/sockcmsg_linux.go (about)

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Socket control messages
     6  
     7  package unix
     8  
     9  import "unsafe"
    10  
    11  // UnixCredentials encodes credentials into a socket control message
    12  // for sending to another process. This can be used for
    13  // authentication.
    14  func UnixCredentials(ucred *Ucred) []byte {
    15  	b := make([]byte, CmsgSpace(SizeofUcred))
    16  	h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
    17  	h.Level = SOL_SOCKET
    18  	h.Type = SCM_CREDENTIALS
    19  	h.SetLen(CmsgLen(SizeofUcred))
    20  	*(*Ucred)(h.data(0)) = *ucred
    21  	return b
    22  }
    23  
    24  // ParseUnixCredentials decodes a socket control message that contains
    25  // credentials in a Ucred structure. To receive such a message, the
    26  // SO_PASSCRED option must be enabled on the socket.
    27  func ParseUnixCredentials(m *SocketControlMessage) (*Ucred, error) {
    28  	if m.Header.Level != SOL_SOCKET {
    29  		return nil, EINVAL
    30  	}
    31  	if m.Header.Type != SCM_CREDENTIALS {
    32  		return nil, EINVAL
    33  	}
    34  	ucred := *(*Ucred)(unsafe.Pointer(&m.Data[0]))
    35  	return &ucred, nil
    36  }
    37  
    38  // PktInfo4 encodes Inet4Pktinfo into a socket control message of type IP_PKTINFO.
    39  func PktInfo4(info *Inet4Pktinfo) []byte {
    40  	b := make([]byte, CmsgSpace(SizeofInet4Pktinfo))
    41  	h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
    42  	h.Level = SOL_IP
    43  	h.Type = IP_PKTINFO
    44  	h.SetLen(CmsgLen(SizeofInet4Pktinfo))
    45  	*(*Inet4Pktinfo)(h.data(0)) = *info
    46  	return b
    47  }
    48  
    49  // PktInfo6 encodes Inet6Pktinfo into a socket control message of type IPV6_PKTINFO.
    50  func PktInfo6(info *Inet6Pktinfo) []byte {
    51  	b := make([]byte, CmsgSpace(SizeofInet6Pktinfo))
    52  	h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
    53  	h.Level = SOL_IPV6
    54  	h.Type = IPV6_PKTINFO
    55  	h.SetLen(CmsgLen(SizeofInet6Pktinfo))
    56  	*(*Inet6Pktinfo)(h.data(0)) = *info
    57  	return b
    58  }
    59  
    60  // ParseOrigDstAddr decodes a socket control message containing the original
    61  // destination address. To receive such a message the IP_RECVORIGDSTADDR or
    62  // IPV6_RECVORIGDSTADDR option must be enabled on the socket.
    63  func ParseOrigDstAddr(m *SocketControlMessage) (Sockaddr, error) {
    64  	switch {
    65  	case m.Header.Level == SOL_IP && m.Header.Type == IP_ORIGDSTADDR:
    66  		pp := (*RawSockaddrInet4)(unsafe.Pointer(&m.Data[0]))
    67  		sa := new(SockaddrInet4)
    68  		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
    69  		sa.Port = int(p[0])<<8 + int(p[1])
    70  		sa.Addr = pp.Addr
    71  		return sa, nil
    72  
    73  	case m.Header.Level == SOL_IPV6 && m.Header.Type == IPV6_ORIGDSTADDR:
    74  		pp := (*RawSockaddrInet6)(unsafe.Pointer(&m.Data[0]))
    75  		sa := new(SockaddrInet6)
    76  		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
    77  		sa.Port = int(p[0])<<8 + int(p[1])
    78  		sa.ZoneId = pp.Scope_id
    79  		sa.Addr = pp.Addr
    80  		return sa, nil
    81  
    82  	default:
    83  		return nil, EINVAL
    84  	}
    85  }