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 7package unix 8 9import "unsafe" 10 11// UnixCredentials encodes credentials into a socket control message 12// for sending to another process. This can be used for 13// authentication. 14func 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. 27func 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. 39func 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. 50func 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. 63func 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 for i := 0; i < len(sa.Addr); i++ { 71 sa.Addr[i] = pp.Addr[i] 72 } 73 return sa, nil 74 75 case m.Header.Level == SOL_IPV6 && m.Header.Type == IPV6_ORIGDSTADDR: 76 pp := (*RawSockaddrInet6)(unsafe.Pointer(&m.Data[0])) 77 sa := new(SockaddrInet6) 78 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 79 sa.Port = int(p[0])<<8 + int(p[1]) 80 sa.ZoneId = pp.Scope_id 81 for i := 0; i < len(sa.Addr); i++ { 82 sa.Addr[i] = pp.Addr[i] 83 } 84 return sa, nil 85 86 default: 87 return nil, EINVAL 88 } 89} 90