control_linux.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  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. package ipv4
  5. import (
  6. "syscall"
  7. "unsafe"
  8. )
  9. func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
  10. opt.Lock()
  11. defer opt.Unlock()
  12. if cf&FlagTTL != 0 {
  13. if err := setInt(fd, &sockOpts[ssoReceiveTTL], boolint(on)); err != nil {
  14. return err
  15. }
  16. if on {
  17. opt.set(FlagTTL)
  18. } else {
  19. opt.clear(FlagTTL)
  20. }
  21. }
  22. if cf&(FlagSrc|FlagDst|FlagInterface) != 0 {
  23. if err := setInt(fd, &sockOpts[ssoPacketInfo], boolint(on)); err != nil {
  24. return err
  25. }
  26. if on {
  27. opt.set(cf & (FlagSrc | FlagDst | FlagInterface))
  28. } else {
  29. opt.clear(cf & (FlagSrc | FlagDst | FlagInterface))
  30. }
  31. }
  32. return nil
  33. }
  34. func (opt *rawOpt) oobLen() (l int) {
  35. if opt.isset(FlagTTL) {
  36. l += syscall.CmsgSpace(1)
  37. }
  38. if opt.isset(FlagSrc | FlagDst | FlagInterface) {
  39. l += syscall.CmsgSpace(sysSizeofInetPktinfo)
  40. }
  41. return
  42. }
  43. func (opt *rawOpt) marshalControlMessage() (oob []byte) {
  44. var off int
  45. oob = make([]byte, opt.oobLen())
  46. if opt.isset(FlagTTL) {
  47. m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
  48. m.Level = ianaProtocolIP
  49. m.Type = sysIP_RECVTTL
  50. m.SetLen(syscall.CmsgLen(1))
  51. off += syscall.CmsgSpace(1)
  52. }
  53. if opt.isset(FlagSrc | FlagDst | FlagInterface) {
  54. m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[0]))
  55. m.Level = ianaProtocolIP
  56. m.Type = sysIP_PKTINFO
  57. m.SetLen(syscall.CmsgLen(sysSizeofInetPktinfo))
  58. off += syscall.CmsgSpace(sysSizeofInetPktinfo)
  59. }
  60. return
  61. }
  62. func (cm *ControlMessage) oobLen() (l int) {
  63. if cm.Src.To4() != nil || cm.IfIndex != 0 {
  64. l += syscall.CmsgSpace(sysSizeofInetPktinfo)
  65. }
  66. return
  67. }
  68. func (cm *ControlMessage) parseControlMessage(m *syscall.SocketControlMessage) {
  69. switch m.Header.Type {
  70. case sysIP_TTL:
  71. cm.TTL = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
  72. case sysIP_PKTINFO:
  73. pi := (*sysInetPktinfo)(unsafe.Pointer(&m.Data[0]))
  74. cm.IfIndex = int(pi.Ifindex)
  75. cm.Dst = pi.Addr[:]
  76. }
  77. }