func newControlMessage(opt *rawOpt) (oob []byte) {
	opt.Lock()
	defer opt.Unlock()
	l, off := 0, 0
	if opt.isset(FlagHopLimit) {
		l += syscall.CmsgSpace(4)
	}
	if opt.isset(pktinfo) {
		l += syscall.CmsgSpace(sysSizeofPacketInfo)
	}
	if l > 0 {
		oob = make([]byte, l)
		if opt.isset(FlagHopLimit) {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIPv6
			m.Type = sysSockopt2292HopLimit
			m.SetLen(syscall.CmsgLen(4))
			off += syscall.CmsgSpace(4)
		}
		if opt.isset(pktinfo) {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIPv6
			m.Type = sysSockopt2292PacketInfo
			m.SetLen(syscall.CmsgLen(sysSizeofPacketInfo))
			off += syscall.CmsgSpace(sysSizeofPacketInfo)
		}
	}
	return
}
Beispiel #2
0
func newControlMessage(opt *rawOpt) (oob []byte) {
	opt.Lock()
	defer opt.Unlock()
	l, off := 0, 0
	if opt.isset(FlagTTL) {
		l += syscall.CmsgSpace(1)
	}
	if opt.isset(pktinfo) {
		l += syscall.CmsgSpace(syscall.SizeofInet4Pktinfo)
	}
	if l > 0 {
		oob = make([]byte, l)
		if opt.isset(FlagTTL) {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIP
			m.Type = syscall.IP_RECVTTL
			m.SetLen(syscall.CmsgLen(1))
			off += syscall.CmsgSpace(1)
		}
		if opt.isset(pktinfo) {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIP
			m.Type = syscall.IP_PKTINFO
			m.SetLen(syscall.CmsgLen(syscall.SizeofInet4Pktinfo))
			off += syscall.CmsgSpace(syscall.SizeofInet4Pktinfo)
		}
	}
	return
}
Beispiel #3
0
func marshalControlMessage(cm *ControlMessage) (oob []byte) {
	if cm == nil {
		return
	}
	l, off := 0, 0
	pion := false
	if cm.Src.To4() != nil || cm.IfIndex != 0 {
		pion = true
		l += syscall.CmsgSpace(syscall.SizeofInet4Pktinfo)
	}
	if l > 0 {
		oob = make([]byte, l)
		if pion {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIP
			m.Type = syscall.IP_PKTINFO
			m.SetLen(syscall.CmsgLen(syscall.SizeofInet4Pktinfo))
			pi := (*syscall.Inet4Pktinfo)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
			if ip := cm.Src.To4(); ip != nil {
				copy(pi.Addr[:], ip)
			}
			if cm.IfIndex != 0 {
				pi.Ifindex = int32(cm.IfIndex)
			}
			off += syscall.CmsgSpace(syscall.SizeofInet4Pktinfo)
		}
	}
	return
}
Beispiel #4
0
func newControlMessage(opt *rawOpt) (oob []byte) {
	opt.lock()
	defer opt.unlock()
	if opt.isset(FlagTTL) {
		b := make([]byte, syscall.CmsgSpace(1))
		cmsg := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
		cmsg.Level = ianaProtocolIP
		cmsg.Type = syscall.IP_RECVTTL
		cmsg.SetLen(syscall.CmsgLen(1))
		oob = append(oob, b...)
	}
	if opt.isset(FlagDst) {
		b := make([]byte, syscall.CmsgSpace(net.IPv4len))
		cmsg := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
		cmsg.Level = ianaProtocolIP
		cmsg.Type = syscall.IP_RECVDSTADDR
		cmsg.SetLen(syscall.CmsgLen(net.IPv4len))
		oob = append(oob, b...)
	}
	if opt.isset(FlagInterface) {
		b := make([]byte, syscall.CmsgSpace(syscall.SizeofSockaddrDatalink))
		cmsg := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
		cmsg.Level = ianaProtocolIP
		cmsg.Type = syscall.IP_RECVIF
		cmsg.SetLen(syscall.CmsgLen(syscall.SizeofSockaddrDatalink))
		oob = append(oob, b...)
	}
	return
}
Beispiel #5
0
func marshalControlMessage(cm *ControlMessage) (oob []byte) {
	if cm == nil {
		return
	}
	pi := &syscall.Inet4Pktinfo{}
	pion := false
	if ip := cm.Src.To4(); ip != nil {
		copy(pi.Spec_dst[:], ip[:net.IPv4len])
		pion = true
	}
	if cm.IfIndex != 0 {
		pi.Ifindex = int32(cm.IfIndex)
		pion = true
	}
	if pion {
		b := make([]byte, syscall.CmsgSpace(syscall.SizeofInet4Pktinfo))
		cmsg := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
		cmsg.Level = ianaProtocolIP
		cmsg.Type = syscall.IP_PKTINFO
		cmsg.SetLen(syscall.CmsgLen(syscall.SizeofInet4Pktinfo))
		data := b[syscall.CmsgLen(0):]
		copy(data[:syscall.SizeofInet4Pktinfo], (*[syscall.SizeofInet4Pktinfo]byte)(unsafe.Pointer(pi))[:syscall.SizeofInet4Pktinfo])
		oob = append(oob, b...)
	}
	return
}
func marshalHopLimit(b []byte, cm *ControlMessage) []byte {
	m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
	m.Level = iana.ProtocolIPv6
	m.Type = sysIPV6_HOPLIMIT
	m.SetLen(syscall.CmsgLen(4))
	if cm != nil {
		data := b[syscall.CmsgLen(0):]
		nativeEndian.PutUint32(data[:4], uint32(cm.HopLimit))
	}
	return b[syscall.CmsgSpace(4):]
}
func marshalNextHop(b []byte, cm *ControlMessage) []byte {
	m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
	m.Level = iana.ProtocolIPv6
	m.Type = sysIPV6_NEXTHOP
	m.SetLen(syscall.CmsgLen(sysSizeofSockaddrInet6))
	if cm != nil {
		sa := (*sysSockaddrInet6)(unsafe.Pointer(&b[syscall.CmsgLen(0)]))
		sa.setSockaddr(cm.NextHop, cm.IfIndex)
	}
	return b[syscall.CmsgSpace(sysSizeofSockaddrInet6):]
}
func marshal2292HopLimit(b []byte, cm *ControlMessage) []byte {
	m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
	m.Level = ianaProtocolIPv6
	m.Type = sysIPV6_2292HOPLIMIT
	m.SetLen(syscall.CmsgLen(4))
	if cm != nil {
		data := b[syscall.CmsgLen(0):]
		*(*int32)(unsafe.Pointer(&data[:4][0])) = int32(cm.HopLimit)
	}
	return b[syscall.CmsgSpace(4):]
}
func marshalHopLimit(b []byte, cm *ControlMessage) []byte {
	m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
	m.Level = iana.ProtocolIPv6
	m.Type = sysIPV6_HOPLIMIT
	m.SetLen(syscall.CmsgLen(4))
	if cm != nil {
		data := b[syscall.CmsgLen(0):]
		// TODO(mikio): fix potential misaligned memory access
		*(*int32)(unsafe.Pointer(&data[:4][0])) = int32(cm.HopLimit)
	}
	return b[syscall.CmsgSpace(4):]
}
Beispiel #10
0
func newControlMessage(opt *rawOpt) (oob []byte) {
	opt.Lock()
	defer opt.Unlock()
	l, off := 0, 0
	if opt.isset(FlagTrafficClass) {
		l += syscall.CmsgSpace(4)
	}
	if opt.isset(FlagHopLimit) {
		l += syscall.CmsgSpace(4)
	}
	if opt.isset(pktinfo) {
		l += syscall.CmsgSpace(syscall.SizeofInet6Pktinfo)
	}
	if opt.isset(FlagPathMTU) {
		l += syscall.CmsgSpace(syscall.SizeofIPv6MTUInfo)
	}
	if l > 0 {
		oob = make([]byte, l)
		if opt.isset(FlagTrafficClass) {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIPv6
			m.Type = syscall.IPV6_RECVTCLASS
			m.SetLen(syscall.CmsgLen(4))
			off += syscall.CmsgSpace(4)
		}
		if opt.isset(FlagHopLimit) {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIPv6
			m.Type = syscall.IPV6_RECVHOPLIMIT
			m.SetLen(syscall.CmsgLen(4))
			off += syscall.CmsgSpace(4)
		}
		if opt.isset(pktinfo) {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIPv6
			m.Type = syscall.IPV6_RECVPKTINFO
			m.SetLen(syscall.CmsgLen(syscall.SizeofInet6Pktinfo))
			off += syscall.CmsgSpace(syscall.SizeofInet6Pktinfo)
		}
		if opt.isset(FlagPathMTU) {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIPv6
			m.Type = syscall.IPV6_RECVPATHMTU
			m.SetLen(syscall.CmsgLen(syscall.SizeofIPv6MTUInfo))
			off += syscall.CmsgSpace(syscall.SizeofIPv6MTUInfo)
		}
	}
	return
}
Beispiel #11
0
func marshalTTL(b []byte, cm *ControlMessage) []byte {
	m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
	m.Level = iana.ProtocolIP
	m.Type = sysIP_RECVTTL
	m.SetLen(syscall.CmsgLen(1))
	return b[syscall.CmsgSpace(1):]
}
func marshal2292PacketInfo(b []byte, cm *ControlMessage) []byte {
	m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
	m.Level = iana.ProtocolIPv6
	m.Type = sysIPV6_2292PKTINFO
	m.SetLen(syscall.CmsgLen(sizeofInet6Pktinfo))
	if cm != nil {
		pi := (*inet6Pktinfo)(unsafe.Pointer(&b[syscall.CmsgLen(0)]))
		if ip := cm.Src.To16(); ip != nil && ip.To4() == nil {
			copy(pi.Addr[:], ip)
		}
		if cm.IfIndex > 0 {
			pi.setIfindex(cm.IfIndex)
		}
	}
	return b[syscall.CmsgSpace(sizeofInet6Pktinfo):]
}
Beispiel #13
0
func marshalPacketInfo(b []byte, cm *ControlMessage) []byte {
	m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
	m.Level = iana.ProtocolIP
	m.Type = sysIP_PKTINFO
	m.SetLen(syscall.CmsgLen(sysSizeofInetPktinfo))
	if cm != nil {
		pi := (*sysInetPktinfo)(unsafe.Pointer(&b[syscall.CmsgLen(0)]))
		if ip := cm.Src.To4(); ip != nil {
			copy(pi.Spec_dst[:], ip)
		}
		if cm.IfIndex > 0 {
			pi.setIfindex(cm.IfIndex)
		}
	}
	return b[syscall.CmsgSpace(sysSizeofInetPktinfo):]
}
Beispiel #14
0
func marshalInterface(b []byte, cm *ControlMessage) []byte {
	m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
	m.Level = iana.ProtocolIP
	m.Type = sysIP_RECVIF
	m.SetLen(syscall.CmsgLen(syscall.SizeofSockaddrDatalink))
	return b[syscall.CmsgSpace(syscall.SizeofSockaddrDatalink):]
}
Beispiel #15
0
func marshalDst(b []byte, cm *ControlMessage) []byte {
	m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
	m.Level = iana.ProtocolIP
	m.Type = sysIP_RECVDSTADDR
	m.SetLen(syscall.CmsgLen(net.IPv4len))
	return b[syscall.CmsgSpace(net.IPv4len):]
}
func marshalPathMTU(b []byte, cm *ControlMessage) []byte {
	m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
	m.Level = iana.ProtocolIPv6
	m.Type = sysIPV6_PATHMTU
	m.SetLen(syscall.CmsgLen(sysSizeofIPv6Mtuinfo))
	return b[syscall.CmsgSpace(sysSizeofIPv6Mtuinfo):]
}
func (cm *ControlMessage) marshalPacketInfo() (oob []byte) {
	if l := cm.oobLen(); l > 0 {
		oob = make([]byte, l)
		m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[0]))
		m.Level = ianaProtocolIP
		m.Type = sysSockoptPacketInfo
		m.SetLen(syscall.CmsgLen(sysSizeofPacketInfo))
		pi := (*sysPacketInfo)(unsafe.Pointer(&oob[syscall.CmsgLen(0)]))
		if ip := cm.Src.To4(); ip != nil {
			copy(pi.IP[:], ip)
		}
		if cm.IfIndex != 0 {
			pi.IfIndex = int32(cm.IfIndex)
		}
	}
	return
}
// http://golang.org/src/pkg/syscall/sockcmsg_linux.go
// UnixCredentials encodes credentials into a socket control message
// for sending to another process. This can be used for
// authentication.
func UnixCredentials(ucred *Ucred) []byte {
	b := make([]byte, syscall.CmsgSpace(SizeofUcred))
	h := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
	h.Level = syscall.SOL_SOCKET
	h.Type = syscall.SCM_CREDS
	h.SetLen(syscall.CmsgLen(SizeofUcred))
	*((*Ucred)(cmsgData(h))) = *ucred
	return b
}
Beispiel #19
0
func (opt *rawOpt) marshalControlMessage() (oob []byte) {
	var off int
	oob = make([]byte, opt.oobLen())
	if opt.isset(FlagTTL) {
		m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
		m.Level = ianaProtocolIP
		m.Type = sysSockoptReceiveTTL
		m.SetLen(syscall.CmsgLen(1))
		off += syscall.CmsgSpace(1)
	}
	if opt.isset(FlagSrc | FlagDst | FlagInterface) {
		m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[0]))
		m.Level = ianaProtocolIP
		m.Type = sysSockoptPacketInfo
		m.SetLen(syscall.CmsgLen(sysSizeofPacketInfo))
		off += syscall.CmsgSpace(sysSizeofPacketInfo)
	}
	return
}
Beispiel #20
0
func newControlMessage(opt *rawOpt) (oob []byte) {
	opt.lock()
	defer opt.unlock()
	if opt.isset(FlagTTL) {
		b := make([]byte, syscall.CmsgSpace(1))
		cmsg := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
		cmsg.Level = ianaProtocolIP
		cmsg.Type = syscall.IP_RECVTTL
		cmsg.SetLen(syscall.CmsgLen(1))
		oob = append(oob, b...)
	}
	if opt.isset(pktinfo) {
		b := make([]byte, syscall.CmsgSpace(syscall.SizeofInet4Pktinfo))
		cmsg := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
		cmsg.Level = ianaProtocolIP
		cmsg.Type = syscall.IP_PKTINFO
		cmsg.SetLen(syscall.CmsgLen(syscall.SizeofInet4Pktinfo))
		oob = append(oob, b...)
	}
	return
}
Beispiel #21
0
func newControlMessage(opt *rawOpt) (oob []byte) {
	opt.Lock()
	defer opt.Unlock()
	l, off := 0, 0
	if opt.isset(FlagTTL) {
		l += syscall.CmsgSpace(1)
	}
	if opt.isset(FlagDst) {
		l += syscall.CmsgSpace(net.IPv4len)
	}
	if opt.isset(FlagInterface) {
		l += syscall.CmsgSpace(syscall.SizeofSockaddrDatalink)
	}
	if l > 0 {
		oob = make([]byte, l)
		if opt.isset(FlagTTL) {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIP
			m.Type = syscall.IP_RECVTTL
			m.SetLen(syscall.CmsgLen(1))
			off += syscall.CmsgSpace(1)
		}
		if opt.isset(FlagDst) {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIP
			m.Type = syscall.IP_RECVDSTADDR
			m.SetLen(syscall.CmsgLen(net.IPv4len))
			off += syscall.CmsgSpace(net.IPv4len)
		}
		if opt.isset(FlagInterface) {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIP
			m.Type = syscall.IP_RECVIF
			m.SetLen(syscall.CmsgLen(syscall.SizeofSockaddrDatalink))
			off += syscall.CmsgSpace(syscall.SizeofSockaddrDatalink)
		}
	}
	return
}
Beispiel #22
0
func (opt *rawOpt) marshalControlMessage() (oob []byte) {
	var off int
	oob = make([]byte, opt.oobLen())
	if opt.isset(FlagTTL) {
		m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
		m.Level = ianaProtocolIP
		m.Type = sysSockoptReceiveTTL
		m.SetLen(syscall.CmsgLen(1))
		off += syscall.CmsgSpace(1)
	}
	if supportsPacketInfo {
		if opt.isset(FlagSrc | FlagDst | FlagInterface) {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIP
			m.Type = sysSockoptPacketInfo
			m.SetLen(syscall.CmsgLen(sysSizeofPacketInfo))
			off += syscall.CmsgSpace(sysSizeofPacketInfo)
		}
	} else {
		if opt.isset(FlagDst) {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIP
			m.Type = sysSockoptReceiveDst
			m.SetLen(syscall.CmsgLen(net.IPv4len))
			off += syscall.CmsgSpace(net.IPv4len)
		}
		if opt.isset(FlagInterface) {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIP
			m.Type = sysSockoptReceiveInterface
			m.SetLen(syscall.CmsgLen(syscall.SizeofSockaddrDatalink))
			off += syscall.CmsgSpace(syscall.SizeofSockaddrDatalink)
		}
	}
	return
}
func marshalControlMessage(cm *ControlMessage) (oob []byte) {
	if cm == nil {
		return
	}
	l, off := 0, 0
	if cm.HopLimit > 0 {
		l += syscall.CmsgSpace(4)
	}
	pion := false
	if cm.Src.To4() == nil && cm.Src.To16() != nil || cm.IfIndex != 0 {
		pion = true
		l += syscall.CmsgSpace(sysSizeofPacketInfo)
	}
	if len(cm.NextHop) == net.IPv6len {
		l += syscall.CmsgSpace(syscall.SizeofSockaddrInet6)
	}
	if l > 0 {
		oob = make([]byte, l)
		if cm.HopLimit > 0 {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIPv6
			m.Type = sysSockopt2292HopLimit
			m.SetLen(syscall.CmsgLen(4))
			data := oob[off+syscall.CmsgLen(0):]
			*(*byte)(unsafe.Pointer(&data[:1][0])) = byte(cm.HopLimit)
			off += syscall.CmsgSpace(4)
		}
		if pion {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIPv6
			m.Type = sysSockopt2292PacketInfo
			m.SetLen(syscall.CmsgLen(sysSizeofPacketInfo))
			pi := (*sysPacketInfo)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
			if ip := cm.Src.To16(); ip != nil && ip.To4() == nil {
				copy(pi.IP[:], ip)
			}
			if cm.IfIndex != 0 {
				pi.IfIndex = uint32(cm.IfIndex)
			}
			off += syscall.CmsgSpace(sysSizeofPacketInfo)
		}
		if len(cm.NextHop) == net.IPv6len {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIPv6
			m.Type = sysSockopt2292NextHop
			m.SetLen(syscall.CmsgLen(syscall.SizeofSockaddrInet6))
			sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
			sa.Len = syscall.SizeofSockaddrInet6
			sa.Family = syscall.AF_INET6
			copy(sa.Addr[:], cm.NextHop)
			off += syscall.CmsgSpace(syscall.SizeofSockaddrInet6)
		}
	}
	return
}
Beispiel #24
0
// TestUnixRightsRoundtrip tests that UnixRights, ParseSocketControlMessage,
// and ParseUnixRights are able to successfully round-trip lists of file descriptors.
func TestUnixRightsRoundtrip(t *testing.T) {
	testCases := [...][][]int{
		{{42}},
		{{1, 2}},
		{{3, 4, 5}},
		{{}},
		{{1, 2}, {3, 4, 5}, {}, {7}},
	}
	for _, testCase := range testCases {
		b := []byte{}
		var n int
		for _, fds := range testCase {
			// Last assignment to n wins
			n = len(b) + syscall.CmsgLen(4*len(fds))
			b = append(b, syscall.UnixRights(fds...)...)
		}
		// Truncate b
		b = b[:n]

		scms, err := syscall.ParseSocketControlMessage(b)
		if err != nil {
			t.Fatalf("ParseSocketControlMessage: %v", err)
		}
		if len(scms) != len(testCase) {
			t.Fatalf("expected %v SocketControlMessage; got scms = %#v", len(testCase), scms)
		}
		for i, scm := range scms {
			gotFds, err := syscall.ParseUnixRights(&scm)
			if err != nil {
				t.Fatalf("ParseUnixRights: %v", err)
			}
			wantFds := testCase[i]
			if len(gotFds) != len(wantFds) {
				t.Fatalf("expected %v fds, got %#v", len(wantFds), gotFds)
			}
			for j, fd := range gotFds {
				if fd != wantFds[j] {
					t.Fatalf("expected fd %v, got %v", wantFds[j], fd)
				}
			}
		}
	}
}
Beispiel #25
0
func marshalControlMessage(cm *ControlMessage) (oob []byte) {
	if cm == nil {
		return
	}
	l, off := 0, 0
	if cm.TrafficClass > 0 {
		l += syscall.CmsgSpace(4)
	}
	if cm.HopLimit > 0 {
		l += syscall.CmsgSpace(4)
	}
	pion := false
	if cm.Src.To4() == nil && cm.Src.To16() != nil || cm.IfIndex != 0 {
		pion = true
		l += syscall.CmsgSpace(syscall.SizeofInet6Pktinfo)
	}
	if len(cm.NextHop) == net.IPv6len {
		l += syscall.CmsgSpace(syscall.SizeofSockaddrInet6)
	}
	if l > 0 {
		oob = make([]byte, l)
		if cm.TrafficClass > 0 {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIPv6
			m.Type = syscall.IPV6_TCLASS
			m.SetLen(syscall.CmsgLen(4))
			data := oob[off+syscall.CmsgLen(0):]
			*(*byte)(unsafe.Pointer(&data[:1][0])) = byte(cm.TrafficClass)
			off += syscall.CmsgSpace(4)
		}
		if cm.HopLimit > 0 {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIPv6
			m.Type = syscall.IPV6_HOPLIMIT
			m.SetLen(syscall.CmsgLen(4))
			data := oob[off+syscall.CmsgLen(0):]
			*(*byte)(unsafe.Pointer(&data[:1][0])) = byte(cm.HopLimit)
			off += syscall.CmsgSpace(4)
		}
		if pion {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIPv6
			m.Type = syscall.IPV6_PKTINFO
			m.SetLen(syscall.CmsgLen(syscall.SizeofInet6Pktinfo))
			pi := (*syscall.Inet6Pktinfo)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
			if ip := cm.Src.To16(); ip != nil && ip.To4() == nil {
				copy(pi.Addr[:], ip)
			}
			if cm.IfIndex != 0 {
				pi.Ifindex = uint32(cm.IfIndex)
			}
			off += syscall.CmsgSpace(syscall.SizeofInet6Pktinfo)
		}
		if len(cm.NextHop) == net.IPv6len {
			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
			m.Level = ianaProtocolIPv6
			m.Type = syscall.IPV6_NEXTHOP
			m.SetLen(syscall.CmsgLen(syscall.SizeofSockaddrInet6))
			sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
			sa.Len = syscall.SizeofSockaddrInet6
			sa.Family = syscall.AF_INET6
			copy(sa.Addr[:], cm.NextHop)
			sa.Scope_id = uint32(cm.IfIndex)
			off += syscall.CmsgSpace(syscall.SizeofSockaddrInet6)
		}
	}
	return
}