control_unix.go raw

   1  // Copyright 2012 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  //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
   6  
   7  package ipv4
   8  
   9  import (
  10  	"unsafe"
  11  
  12  	"golang.org/x/net/internal/iana"
  13  	"golang.org/x/net/internal/socket"
  14  
  15  	"golang.org/x/sys/unix"
  16  )
  17  
  18  func setControlMessage(c *socket.Conn, opt *rawOpt, cf ControlFlags, on bool) error {
  19  	opt.Lock()
  20  	defer opt.Unlock()
  21  	if so, ok := sockOpts[ssoReceiveTTL]; ok && cf&FlagTTL != 0 {
  22  		if err := so.SetInt(c, boolint(on)); err != nil {
  23  			return err
  24  		}
  25  		if on {
  26  			opt.set(FlagTTL)
  27  		} else {
  28  			opt.clear(FlagTTL)
  29  		}
  30  	}
  31  	if so, ok := sockOpts[ssoPacketInfo]; ok {
  32  		if cf&(FlagSrc|FlagDst|FlagInterface) != 0 {
  33  			if err := so.SetInt(c, boolint(on)); err != nil {
  34  				return err
  35  			}
  36  			if on {
  37  				opt.set(cf & (FlagSrc | FlagDst | FlagInterface))
  38  			} else {
  39  				opt.clear(cf & (FlagSrc | FlagDst | FlagInterface))
  40  			}
  41  		}
  42  	} else {
  43  		if so, ok := sockOpts[ssoReceiveDst]; ok && cf&FlagDst != 0 {
  44  			if err := so.SetInt(c, boolint(on)); err != nil {
  45  				return err
  46  			}
  47  			if on {
  48  				opt.set(FlagDst)
  49  			} else {
  50  				opt.clear(FlagDst)
  51  			}
  52  		}
  53  		if so, ok := sockOpts[ssoReceiveInterface]; ok && cf&FlagInterface != 0 {
  54  			if err := so.SetInt(c, boolint(on)); err != nil {
  55  				return err
  56  			}
  57  			if on {
  58  				opt.set(FlagInterface)
  59  			} else {
  60  				opt.clear(FlagInterface)
  61  			}
  62  		}
  63  	}
  64  	return nil
  65  }
  66  
  67  func marshalTTL(b []byte, cm *ControlMessage) []byte {
  68  	m := socket.ControlMessage(b)
  69  	m.MarshalHeader(iana.ProtocolIP, unix.IP_RECVTTL, 1)
  70  	return m.Next(1)
  71  }
  72  
  73  func parseTTL(cm *ControlMessage, b []byte) {
  74  	cm.TTL = int(*(*byte)(unsafe.Pointer(&b[:1][0])))
  75  }
  76