Files
golang.net/ipv4/control_linux.go
Mikio Hara 353547e1a2 go.net/ipv4: restructure sticky socket option handling
This CL chops existing sticky socket option handlers and puts them
into platform dependent sticky socket option binding table for
supporting multicast features such as source filtering for any-source
multicast, source-specific multicast.

Also adds tiny syscall shims to help to support solaris, to improve
existing platform support.

LGTM=iant
R=iant
CC=golang-codereviews
https://golang.org/cl/140640045
2014-10-04 08:12:41 +09:00

85 lines
2.0 KiB
Go

// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ipv4
import (
"syscall"
"unsafe"
)
func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
opt.Lock()
defer opt.Unlock()
if cf&FlagTTL != 0 {
if err := setInt(fd, &sockOpts[ssoReceiveTTL], boolint(on)); err != nil {
return err
}
if on {
opt.set(FlagTTL)
} else {
opt.clear(FlagTTL)
}
}
if cf&(FlagSrc|FlagDst|FlagInterface) != 0 {
if err := setInt(fd, &sockOpts[ssoPacketInfo], boolint(on)); err != nil {
return err
}
if on {
opt.set(cf & (FlagSrc | FlagDst | FlagInterface))
} else {
opt.clear(cf & (FlagSrc | FlagDst | FlagInterface))
}
}
return nil
}
func (opt *rawOpt) oobLen() (l int) {
if opt.isset(FlagTTL) {
l += syscall.CmsgSpace(1)
}
if opt.isset(FlagSrc | FlagDst | FlagInterface) {
l += syscall.CmsgSpace(sysSizeofInetPktinfo)
}
return
}
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 = sysIP_RECVTTL
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 = sysIP_PKTINFO
m.SetLen(syscall.CmsgLen(sysSizeofInetPktinfo))
off += syscall.CmsgSpace(sysSizeofInetPktinfo)
}
return
}
func (cm *ControlMessage) oobLen() (l int) {
if cm.Src.To4() != nil || cm.IfIndex != 0 {
l += syscall.CmsgSpace(sysSizeofInetPktinfo)
}
return
}
func (cm *ControlMessage) parseControlMessage(m *syscall.SocketControlMessage) {
switch m.Header.Type {
case sysIP_TTL:
cm.TTL = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
case sysIP_PKTINFO:
pi := (*sysInetPktinfo)(unsafe.Pointer(&m.Data[0]))
cm.IfIndex = int(pi.Ifindex)
cm.Dst = pi.Addr[:]
}
}