github.com/osrg/gobgp@v2.0.0+incompatible/pkg/server/sockopt_linux.go (about)

     1  // Copyright (C) 2016 Nippon Telegraph and Telephone Corporation.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    12  // implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  // +build linux
    16  
    17  package server
    18  
    19  import (
    20  	"net"
    21  	"os"
    22  	"syscall"
    23  	"unsafe"
    24  )
    25  
    26  const (
    27  	tcpMD5SIG       = 14 // TCP MD5 Signature (RFC2385)
    28  	ipv6MinHopCount = 73 // Generalized TTL Security Mechanism (RFC5082)
    29  )
    30  
    31  type tcpmd5sig struct {
    32  	ss_family uint16
    33  	ss        [126]byte
    34  	// padding the struct
    35  	_      uint16
    36  	keylen uint16
    37  	// padding the struct
    38  	_   uint32
    39  	key [80]byte
    40  }
    41  
    42  func buildTcpMD5Sig(address, key string) (tcpmd5sig, error) {
    43  	t := tcpmd5sig{}
    44  	addr := net.ParseIP(address)
    45  	if addr.To4() != nil {
    46  		t.ss_family = syscall.AF_INET
    47  		copy(t.ss[2:], addr.To4())
    48  	} else {
    49  		t.ss_family = syscall.AF_INET6
    50  		copy(t.ss[6:], addr.To16())
    51  	}
    52  
    53  	t.keylen = uint16(len(key))
    54  	copy(t.key[0:], []byte(key))
    55  
    56  	return t, nil
    57  }
    58  
    59  func setTCPMD5SigSockopt(l *net.TCPListener, address string, key string) error {
    60  	t, err := buildTcpMD5Sig(address, key)
    61  	if err != nil {
    62  		return err
    63  	}
    64  	b := *(*[unsafe.Sizeof(t)]byte)(unsafe.Pointer(&t))
    65  
    66  	sc, err := l.SyscallConn()
    67  	if err != nil {
    68  		return err
    69  	}
    70  	return setsockOptString(sc, syscall.IPPROTO_TCP, tcpMD5SIG, string(b[:]))
    71  }
    72  
    73  func setListenTCPTTLSockopt(l *net.TCPListener, ttl int) error {
    74  	family := extractFamilyFromTCPListener(l)
    75  	sc, err := l.SyscallConn()
    76  	if err != nil {
    77  		return err
    78  	}
    79  	return setsockoptIpTtl(sc, family, ttl)
    80  }
    81  
    82  func setTCPTTLSockopt(conn *net.TCPConn, ttl int) error {
    83  	family := extractFamilyFromTCPConn(conn)
    84  	sc, err := conn.SyscallConn()
    85  	if err != nil {
    86  		return err
    87  	}
    88  	return setsockoptIpTtl(sc, family, ttl)
    89  }
    90  
    91  func setTCPMinTTLSockopt(conn *net.TCPConn, ttl int) error {
    92  	family := extractFamilyFromTCPConn(conn)
    93  	sc, err := conn.SyscallConn()
    94  	if err != nil {
    95  		return err
    96  	}
    97  	level := syscall.IPPROTO_IP
    98  	name := syscall.IP_MINTTL
    99  	if family == syscall.AF_INET6 {
   100  		level = syscall.IPPROTO_IPV6
   101  		name = ipv6MinHopCount
   102  	}
   103  	return setsockOptInt(sc, level, name, ttl)
   104  }
   105  
   106  func dialerControl(network, address string, c syscall.RawConn, ttl, minTtl uint8, password string) error {
   107  	family := syscall.AF_INET
   108  	raddr, _ := net.ResolveTCPAddr("tcp", address)
   109  	if raddr.IP.To4() == nil {
   110  		family = syscall.AF_INET6
   111  	}
   112  
   113  	var sockerr error
   114  	if password != "" {
   115  		addr, _, _ := net.SplitHostPort(address)
   116  		t, err := buildTcpMD5Sig(addr, password)
   117  		if err != nil {
   118  			return err
   119  		}
   120  		b := *(*[unsafe.Sizeof(t)]byte)(unsafe.Pointer(&t))
   121  		if err := c.Control(func(fd uintptr) {
   122  			sockerr = os.NewSyscallError("setsockopt", syscall.SetsockoptString(int(fd), syscall.IPPROTO_TCP, tcpMD5SIG, string(b[:])))
   123  		}); err != nil {
   124  			return err
   125  		}
   126  		if sockerr != nil {
   127  			return sockerr
   128  		}
   129  	}
   130  
   131  	if ttl != 0 {
   132  		if err := c.Control(func(fd uintptr) {
   133  			level := syscall.IPPROTO_IP
   134  			name := syscall.IP_TTL
   135  			if family == syscall.AF_INET6 {
   136  				level = syscall.IPPROTO_IPV6
   137  				name = syscall.IPV6_UNICAST_HOPS
   138  			}
   139  			sockerr = os.NewSyscallError("setsockopt", syscall.SetsockoptInt(int(fd), level, name, int(ttl)))
   140  		}); err != nil {
   141  			return err
   142  		}
   143  		if sockerr != nil {
   144  			return sockerr
   145  		}
   146  	}
   147  
   148  	if minTtl != 0 {
   149  		if err := c.Control(func(fd uintptr) {
   150  			level := syscall.IPPROTO_IP
   151  			name := syscall.IP_MINTTL
   152  			if family == syscall.AF_INET6 {
   153  				level = syscall.IPPROTO_IPV6
   154  				name = ipv6MinHopCount
   155  			}
   156  			sockerr = os.NewSyscallError("setsockopt", syscall.SetsockoptInt(int(fd), level, name, int(minTtl)))
   157  		}); err != nil {
   158  			return err
   159  		}
   160  		if sockerr != nil {
   161  			return sockerr
   162  		}
   163  	}
   164  	return nil
   165  }