浏览代码

go.net/ipv4: restructure ancillary data socket option handling

This CL chops existing ancillary data socket option handlers and
puts them into platform dependent ancillary data socket option
binding table for code readability.

Fixes golang/go#6710.

LGTM=iant
R=iant
CC=golang-codereviews
https://golang.org/cl/153860043
Mikio Hara 11 年之前
父节点
当前提交
edb50c0ae2
共有 12 个文件被更改,包括 219 次插入256 次删除
  1. 19 1
      ipv4/control.go
  2. 17 121
      ipv4/control_bsd.go
  3. 0 84
      ipv4/control_linux.go
  4. 0 11
      ipv4/control_nonpktinfo.go
  5. 15 10
      ipv4/control_pktinfo.go
  6. 125 4
      ipv4/control_unix.go
  7. 10 11
      ipv4/sys_bsd.go
  8. 14 1
      ipv4/sys_darwin.go
  9. 10 13
      ipv4/sys_freebsd.go
  10. 5 0
      ipv4/sys_linux.go
  11. 2 0
      ipv4/sys_stub.go
  12. 2 0
      ipv4/sys_windows.go

+ 19 - 1
ipv4/control.go

@@ -11,7 +11,7 @@ import (
 )
 
 type rawOpt struct {
-	sync.Mutex
+	sync.RWMutex
 	cflags ControlFlags
 }
 
@@ -50,3 +50,21 @@ func (cm *ControlMessage) String() string {
 	}
 	return fmt.Sprintf("ttl: %v, src: %v, dst: %v, ifindex: %v", cm.TTL, cm.Src, cm.Dst, cm.IfIndex)
 }
+
+// Ancillary data socket options
+const (
+	ctlTTL        = iota // header field
+	ctlSrc               // header field
+	ctlDst               // header field
+	ctlInterface         // inbound or outbound interface
+	ctlPacketInfo        // inbound or outbound packet path
+	ctlMax
+)
+
+// A ctlOpt represents a binding for ancillary data socket option.
+type ctlOpt struct {
+	name    int // option name, must be equal or greater than 1
+	length  int // option length
+	marshal func([]byte, *ControlMessage) []byte
+	parse   func(*ControlMessage, []byte)
+}

+ 17 - 121
ipv4/control_bsd.go

@@ -12,131 +12,27 @@ import (
 	"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 sockOpts[ssoPacketInfo].name > 0 {
-		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))
-
-			}
-		}
-	} else {
-		if cf&FlagDst != 0 {
-			if err := setInt(fd, &sockOpts[ssoReceiveDst], boolint(on)); err != nil {
-				return err
-			}
-			if on {
-				opt.set(FlagDst)
-			} else {
-				opt.clear(FlagDst)
-			}
-		}
-		if cf&FlagInterface != 0 {
-			if err := setInt(fd, &sockOpts[ssoReceiveInterface], boolint(on)); err != nil {
-				return err
-			}
-			if on {
-				opt.set(FlagInterface)
-			} else {
-				opt.clear(FlagInterface)
-			}
-		}
-	}
-	return nil
-}
-
-func (opt *rawOpt) oobLen() (l int) {
-	if opt.isset(FlagTTL) {
-		l += syscall.CmsgSpace(1)
-	}
-	if sockOpts[ssoPacketInfo].name > 0 {
-		if opt.isset(FlagSrc | FlagDst | FlagInterface) {
-			l += syscall.CmsgSpace(sysSizeofInetPktinfo)
-		}
-	} else {
-		if opt.isset(FlagDst) {
-			l += syscall.CmsgSpace(net.IPv4len)
-		}
-		if opt.isset(FlagInterface) {
-			l += syscall.CmsgSpace(syscall.SizeofSockaddrDatalink)
-		}
-	}
-	return
+func marshalDst(b []byte, cm *ControlMessage) []byte {
+	m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
+	m.Level = ianaProtocolIP
+	m.Type = sysIP_RECVDSTADDR
+	m.SetLen(syscall.CmsgLen(net.IPv4len))
+	return b[syscall.CmsgSpace(net.IPv4len):]
 }
 
-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 sockOpts[ssoPacketInfo].name > 0 {
-		if opt.isset(FlagSrc | FlagDst | FlagInterface) {
-			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
-			m.Level = ianaProtocolIP
-			m.Type = sysIP_PKTINFO
-			m.SetLen(syscall.CmsgLen(sysSizeofInetPktinfo))
-			off += syscall.CmsgSpace(sysSizeofInetPktinfo)
-		}
-	} else {
-		if opt.isset(FlagDst) {
-			m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
-			m.Level = ianaProtocolIP
-			m.Type = sysIP_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 = sysIP_RECVIF
-			m.SetLen(syscall.CmsgLen(syscall.SizeofSockaddrDatalink))
-			off += syscall.CmsgSpace(syscall.SizeofSockaddrDatalink)
-		}
-	}
-	return
+func parseDst(cm *ControlMessage, b []byte) {
+	cm.Dst = b[:net.IPv4len]
 }
 
-func (cm *ControlMessage) oobLen() (l int) {
-	if sockOpts[ssoPacketInfo].name > 0 && (cm.Src.To4() != nil || cm.IfIndex != 0) {
-		l += syscall.CmsgSpace(sysSizeofInetPktinfo)
-	}
-	return
+func marshalInterface(b []byte, cm *ControlMessage) []byte {
+	m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
+	m.Level = ianaProtocolIP
+	m.Type = sysIP_RECVIF
+	m.SetLen(syscall.CmsgLen(syscall.SizeofSockaddrDatalink))
+	return b[syscall.CmsgSpace(syscall.SizeofSockaddrDatalink):]
 }
 
-func (cm *ControlMessage) parseControlMessage(m *syscall.SocketControlMessage) {
-	switch m.Header.Type {
-	case sysIP_RECVTTL:
-		cm.TTL = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
-	case sysIP_RECVDSTADDR:
-		cm.Dst = m.Data[:net.IPv4len]
-	case sysIP_RECVIF:
-		sadl := (*syscall.SockaddrDatalink)(unsafe.Pointer(&m.Data[0]))
-		cm.IfIndex = int(sadl.Index)
-	case sysIP_PKTINFO:
-		pi := (*sysInetPktinfo)(unsafe.Pointer(&m.Data[0]))
-		cm.IfIndex = int(pi.Ifindex)
-		cm.Dst = pi.Addr[:]
-	}
+func parseInterface(cm *ControlMessage, b []byte) {
+	sadl := (*syscall.SockaddrDatalink)(unsafe.Pointer(&b[0]))
+	cm.IfIndex = int(sadl.Index)
 }

+ 0 - 84
ipv4/control_linux.go

@@ -1,84 +0,0 @@
-// 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[:]
-	}
-}

+ 0 - 11
ipv4/control_nonpktinfo.go

@@ -1,11 +0,0 @@
-// Copyright 2014 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.
-
-// +build !darwin,!linux
-
-package ipv4
-
-func (cm *ControlMessage) marshalPacketInfo() (oob []byte) {
-	return nil
-}

+ 15 - 10
ipv4/control_pktinfo.go

@@ -11,20 +11,25 @@ import (
 	"unsafe"
 )
 
-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 = sysIP_PKTINFO
-		m.SetLen(syscall.CmsgLen(sysSizeofInetPktinfo))
-		pi := (*sysInetPktinfo)(unsafe.Pointer(&oob[syscall.CmsgLen(0)]))
+func marshalPacketInfo(b []byte, cm *ControlMessage) []byte {
+	m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
+	m.Level = ianaProtocolIP
+	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.Addr[:], ip)
+			copy(pi.Spec_dst[:], ip)
 		}
 		if cm.IfIndex != 0 {
 			pi.setIfindex(cm.IfIndex)
 		}
 	}
-	return
+	return b[syscall.CmsgSpace(sysSizeofInetPktinfo):]
+}
+
+func parsePacketInfo(cm *ControlMessage, b []byte) {
+	pi := (*sysInetPktinfo)(unsafe.Pointer(&b[0]))
+	cm.IfIndex = int(pi.Ifindex)
+	cm.Dst = pi.Addr[:]
 }

+ 125 - 4
ipv4/control_unix.go

@@ -9,12 +9,97 @@ package ipv4
 import (
 	"os"
 	"syscall"
+	"unsafe"
 )
 
-func newControlMessage(opt *rawOpt) (oob []byte) {
+func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
 	opt.Lock()
 	defer opt.Unlock()
-	return opt.marshalControlMessage()
+	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 sockOpts[ssoPacketInfo].name > 0 {
+		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))
+			}
+		}
+	} else {
+		if cf&FlagDst != 0 {
+			if err := setInt(fd, &sockOpts[ssoReceiveDst], boolint(on)); err != nil {
+				return err
+			}
+			if on {
+				opt.set(FlagDst)
+			} else {
+				opt.clear(FlagDst)
+			}
+		}
+		if cf&FlagInterface != 0 {
+			if err := setInt(fd, &sockOpts[ssoReceiveInterface], boolint(on)); err != nil {
+				return err
+			}
+			if on {
+				opt.set(FlagInterface)
+			} else {
+				opt.clear(FlagInterface)
+			}
+		}
+	}
+	return nil
+}
+
+func newControlMessage(opt *rawOpt) (oob []byte) {
+	opt.RLock()
+	var l int
+	if opt.isset(FlagTTL) {
+		l += syscall.CmsgSpace(ctlOpts[ctlTTL].length)
+	}
+	if ctlOpts[ctlPacketInfo].name > 0 {
+		if opt.isset(FlagSrc | FlagDst | FlagInterface) {
+			l += syscall.CmsgSpace(ctlOpts[ctlPacketInfo].length)
+		}
+	} else {
+		if opt.isset(FlagDst) {
+			l += syscall.CmsgSpace(ctlOpts[ctlDst].length)
+		}
+		if opt.isset(FlagInterface) {
+			l += syscall.CmsgSpace(ctlOpts[ctlInterface].length)
+		}
+	}
+	if l > 0 {
+		oob = make([]byte, l)
+		b := oob
+		if opt.isset(FlagTTL) {
+			b = ctlOpts[ctlTTL].marshal(b, nil)
+		}
+		if ctlOpts[ctlPacketInfo].name > 0 {
+			if opt.isset(FlagSrc | FlagDst | FlagInterface) {
+				b = ctlOpts[ctlPacketInfo].marshal(b, nil)
+			}
+		} else {
+			if opt.isset(FlagDst) {
+				b = ctlOpts[ctlDst].marshal(b, nil)
+			}
+			if opt.isset(FlagInterface) {
+				b = ctlOpts[ctlInterface].marshal(b, nil)
+			}
+		}
+	}
+	opt.RUnlock()
+	return
 }
 
 func parseControlMessage(b []byte) (*ControlMessage, error) {
@@ -30,7 +115,16 @@ func parseControlMessage(b []byte) (*ControlMessage, error) {
 		if m.Header.Level != ianaProtocolIP {
 			continue
 		}
-		cm.parseControlMessage(&m)
+		switch int(m.Header.Type) {
+		case ctlOpts[ctlTTL].name:
+			ctlOpts[ctlTTL].parse(cm, m.Data[:])
+		case ctlOpts[ctlDst].name:
+			ctlOpts[ctlDst].parse(cm, m.Data[:])
+		case ctlOpts[ctlInterface].name:
+			ctlOpts[ctlInterface].parse(cm, m.Data[:])
+		case ctlOpts[ctlPacketInfo].name:
+			ctlOpts[ctlPacketInfo].parse(cm, m.Data[:])
+		}
 	}
 	return cm, nil
 }
@@ -39,5 +133,32 @@ func marshalControlMessage(cm *ControlMessage) (oob []byte) {
 	if cm == nil {
 		return nil
 	}
-	return cm.marshalPacketInfo()
+	var l int
+	if ctlOpts[ctlPacketInfo].name > 0 {
+		if cm.Src.To4() != nil || cm.IfIndex != 0 {
+			l += syscall.CmsgSpace(ctlOpts[ctlPacketInfo].length)
+		}
+	}
+	if l > 0 {
+		oob = make([]byte, l)
+		b := oob
+		if ctlOpts[ctlPacketInfo].name > 0 {
+			if cm.Src.To4() != nil || cm.IfIndex != 0 {
+				b = ctlOpts[ctlPacketInfo].marshal(b, cm)
+			}
+		}
+	}
+	return
+}
+
+func marshalTTL(b []byte, cm *ControlMessage) []byte {
+	m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
+	m.Level = ianaProtocolIP
+	m.Type = sysIP_RECVTTL
+	m.SetLen(syscall.CmsgLen(1))
+	return b[syscall.CmsgSpace(1):]
+}
+
+func parseTTL(cm *ControlMessage, b []byte) {
+	cm.TTL = int(*(*byte)(unsafe.Pointer(&b[:1][0])))
 }

+ 10 - 11
ipv4/sys_bsd.go

@@ -6,21 +6,20 @@
 
 package ipv4
 
-type sysSockoptLen int32
-
-const (
-	sysIP_PKTINFO = 0
-
-	sysSizeofInetPktinfo = 0xc
+import (
+	"net"
+	"syscall"
 )
 
-type sysInetPktinfo struct {
-	Ifindex  uint32
-	Spec_dst [4]byte /* in_addr */
-	Addr     [4]byte /* in_addr */
-}
+type sysSockoptLen int32
 
 var (
+	ctlOpts = [ctlMax]ctlOpt{
+		ctlTTL:       {sysIP_RECVTTL, 1, marshalTTL, parseTTL},
+		ctlDst:       {sysIP_RECVDSTADDR, net.IPv4len, marshalDst, parseDst},
+		ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface},
+	}
+
 	sockOpts = [ssoMax]sockOpt{
 		ssoTOS:                {sysIP_TOS, ssoTypeInt},
 		ssoTTL:                {sysIP_TTL, ssoTypeInt},

+ 14 - 1
ipv4/sys_darwin.go

@@ -4,11 +4,20 @@
 
 package ipv4
 
-import "syscall"
+import (
+	"net"
+	"syscall"
+)
 
 type sysSockoptLen int32
 
 var (
+	ctlOpts = [ctlMax]ctlOpt{
+		ctlTTL:       {sysIP_RECVTTL, 1, marshalTTL, parseTTL},
+		ctlDst:       {sysIP_RECVDSTADDR, net.IPv4len, marshalDst, parseDst},
+		ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface},
+	}
+
 	sockOpts = [ssoMax]sockOpt{
 		ssoTOS:                {sysIP_TOS, ssoTypeInt},
 		ssoTTL:                {sysIP_TTL, ssoTypeInt},
@@ -40,6 +49,10 @@ func init() {
 	// The IP_PKTINFO was introduced in OS X 10.7 (Darwin
 	// 11.0.0). See http://support.apple.com/kb/HT1633.
 	if i > 2 || i == 2 && osver[0] >= '1' && osver[1] >= '1' {
+		ctlOpts[ctlPacketInfo].name = sysIP_PKTINFO
+		ctlOpts[ctlPacketInfo].length = sysSizeofInetPktinfo
+		ctlOpts[ctlPacketInfo].marshal = marshalPacketInfo
+		ctlOpts[ctlPacketInfo].parse = parsePacketInfo
 		sockOpts[ssoPacketInfo].name = sysIP_RECVPKTINFO
 		sockOpts[ssoPacketInfo].typ = ssoTypeInt
 		sockOpts[ssoMulticastInterface].typ = ssoTypeIPMreqn

+ 10 - 13
ipv4/sys_freebsd.go

@@ -4,23 +4,20 @@
 
 package ipv4
 
-import "syscall"
-
-type sysSockoptLen int32
-
-const (
-	sysIP_PKTINFO = 0
-
-	sysSizeofInetPktinfo = 0xc
+import (
+	"net"
+	"syscall"
 )
 
-type sysInetPktinfo struct {
-	Ifindex  uint32
-	Spec_dst [4]byte /* in_addr */
-	Addr     [4]byte /* in_addr */
-}
+type sysSockoptLen int32
 
 var (
+	ctlOpts = [ctlMax]ctlOpt{
+		ctlTTL:       {sysIP_RECVTTL, 1, marshalTTL, parseTTL},
+		ctlDst:       {sysIP_RECVDSTADDR, net.IPv4len, marshalDst, parseDst},
+		ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface},
+	}
+
 	sockOpts = [ssoMax]sockOpt{
 		ssoTOS:                {sysIP_TOS, ssoTypeInt},
 		ssoTTL:                {sysIP_TTL, ssoTypeInt},

+ 5 - 0
ipv4/sys_linux.go

@@ -7,6 +7,11 @@ package ipv4
 type sysSockoptLen int32
 
 var (
+	ctlOpts = [ctlMax]ctlOpt{
+		ctlTTL:        {sysIP_TTL, 1, marshalTTL, parseTTL},
+		ctlPacketInfo: {sysIP_PKTINFO, sysSizeofInetPktinfo, marshalPacketInfo, parsePacketInfo},
+	}
+
 	sockOpts = [ssoMax]sockOpt{
 		ssoTOS:                {sysIP_TOS, ssoTypeInt},
 		ssoTTL:                {sysIP_TTL, ssoTypeInt},

+ 2 - 0
ipv4/sys_stub.go

@@ -9,5 +9,7 @@ package ipv4
 type sysSockoptLen int32
 
 var (
+	ctlOpts = [ctlMax]ctlOpt{}
+
 	sockOpts = [ssoMax]sockOpt{}
 )

+ 2 - 0
ipv4/sys_windows.go

@@ -43,6 +43,8 @@ type sysIPMreqSource struct {
 
 // See http://msdn.microsoft.com/en-us/library/windows/desktop/ms738586(v=vs.85).aspx
 var (
+	ctlOpts = [ctlMax]ctlOpt{}
+
 	sockOpts = [ssoMax]sockOpt{
 		ssoTOS:                {sysIP_TOS, ssoTypeInt},
 		ssoTTL:                {sysIP_TTL, ssoTypeInt},