github.com/osrg/gobgp/v3@v3.30.0/pkg/server/sockopt_openbsd.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  //go:build openbsd
    16  // +build openbsd
    17  
    18  package server
    19  
    20  import (
    21  	"encoding/binary"
    22  	"fmt"
    23  	"net"
    24  	"os"
    25  	"syscall"
    26  	"unsafe"
    27  
    28  	"github.com/osrg/gobgp/v3/pkg/log"
    29  )
    30  
    31  const (
    32  	PF_KEY_V2 = 2
    33  
    34  	SADB_X_SATYPE_TCPSIGNATURE = 8
    35  
    36  	SADB_EXT_SA          = 1
    37  	SADB_EXT_ADDRESS_SRC = 5
    38  	SADB_EXT_ADDRESS_DST = 6
    39  	SADB_EXT_KEY_AUTH    = 8
    40  	SADB_EXT_SPIRANGE    = 16
    41  
    42  	SADB_GETSPI = 1
    43  	SADB_UPDATE = 2
    44  	SADB_DELETE = 4
    45  
    46  	SADB_X_EALG_AES = 12
    47  
    48  	SADB_SASTATE_MATURE = 1
    49  )
    50  
    51  type sadbMsg struct {
    52  	sadbMsgVersion  uint8
    53  	sadbMsgType     uint8
    54  	sadbMsgErrno    uint8
    55  	sadbMsgSatype   uint8
    56  	sadbMsgLen      uint16
    57  	sadbMsgReserved uint16
    58  	sadbMsgSeq      uint32
    59  	sadbMsgPid      uint32
    60  }
    61  
    62  func (s *sadbMsg) DecodeFromBytes(data []byte) error {
    63  	if len(data) < SADB_MSG_SIZE {
    64  		return fmt.Errorf("too short for sadbMsg %d", len(data))
    65  	}
    66  	s.sadbMsgVersion = data[0]
    67  	s.sadbMsgType = data[1]
    68  	s.sadbMsgErrno = data[2]
    69  	s.sadbMsgSatype = data[3]
    70  	s.sadbMsgLen = binary.LittleEndian.Uint16(data[4:6])
    71  	s.sadbMsgSeq = binary.LittleEndian.Uint32(data[8:12])
    72  	s.sadbMsgPid = binary.LittleEndian.Uint32(data[12:16])
    73  	return nil
    74  }
    75  
    76  type sadbSpirange struct {
    77  	sadbSpirangeLen      uint16
    78  	sadbSpirangeExttype  uint16
    79  	sadbSpirangeMin      uint32
    80  	sadbSpirangeMax      uint32
    81  	sadbSpirangeReserved uint32
    82  }
    83  
    84  type sadbAddress struct {
    85  	sadbAddressLen      uint16
    86  	sadbAddressExttype  uint16
    87  	sadbAddressReserved uint32
    88  }
    89  
    90  type sadbExt struct {
    91  	sadbExtLen  uint16
    92  	sadbExtType uint16
    93  }
    94  
    95  type sadbSa struct {
    96  	sadbSaLen     uint16
    97  	sadbSaExttype uint16
    98  	sadbSaSpi     uint32
    99  	sadbSaReplay  uint8
   100  	sadbSaState   uint8
   101  	sadbSaAuth    uint8
   102  	sadbSaEncrypt uint8
   103  	sadbSaFlags   uint32
   104  }
   105  
   106  type sadbKey struct {
   107  	sadbKeyLen      uint16
   108  	sadbKeyExttype  uint16
   109  	sadbKeyBits     uint16
   110  	sadbKeyReserved uint16
   111  }
   112  
   113  const (
   114  	SADB_MSG_SIZE      = int(unsafe.Sizeof(sadbMsg{}))
   115  	SADB_SPIRANGE_SIZE = int(unsafe.Sizeof(sadbSpirange{}))
   116  	SADB_ADDRESS_SIZE  = int(unsafe.Sizeof(sadbAddress{}))
   117  	SADB_SA_SIZE       = int(unsafe.Sizeof(sadbSa{}))
   118  	SADB_KEY_SIZE      = int(unsafe.Sizeof(sadbKey{}))
   119  )
   120  
   121  type sockaddrIn struct {
   122  	ssLen    uint8
   123  	ssFamily uint8
   124  	ssPort   uint16
   125  	ssAddr   uint32
   126  	pad      [8]byte
   127  }
   128  
   129  func newSockaddrIn(addr string) sockaddrIn {
   130  	if len(addr) == 0 {
   131  		return sockaddrIn{
   132  			ssLen: 16,
   133  		}
   134  	}
   135  	v := net.ParseIP(addr).To4()
   136  	return sockaddrIn{
   137  		ssAddr:   uint32(v[3])<<24 | uint32(v[2])<<16 | uint32(v[1])<<8 | uint32(v[0]),
   138  		ssLen:    16,
   139  		ssFamily: syscall.AF_INET,
   140  	}
   141  }
   142  
   143  func roundUp(v int) int {
   144  	if v%8 != 0 {
   145  		v += 8 - v%8
   146  	}
   147  	return v
   148  }
   149  
   150  func b(p unsafe.Pointer, length int) []byte {
   151  	buf := make([]byte, length)
   152  	for i := 0; i < length; i++ {
   153  		buf[i] = *(*byte)(p)
   154  		p = unsafe.Pointer(uintptr(p) + 1)
   155  	}
   156  	return buf
   157  }
   158  
   159  var seq uint32
   160  var fd int
   161  
   162  var spiInMap map[string]uint32 = map[string]uint32{}
   163  var spiOutMap map[string]uint32 = map[string]uint32{}
   164  
   165  func pfkeyReply() (spi uint32, err error) {
   166  	buf := make([]byte, SADB_MSG_SIZE)
   167  	if count, _, _, _, _ := syscall.Recvmsg(fd, buf, nil, syscall.MSG_PEEK); count != len(buf) {
   168  		return spi, fmt.Errorf("incomplete sadb msg %d %d", len(buf), count)
   169  	}
   170  	h := sadbMsg{}
   171  	h.DecodeFromBytes(buf)
   172  	if h.sadbMsgErrno != 0 {
   173  		return spi, fmt.Errorf("sadb msg reply error %d", h.sadbMsgErrno)
   174  	}
   175  
   176  	if h.sadbMsgSeq != seq {
   177  		return spi, fmt.Errorf("sadb msg sequence doesn't match %d %d", h.sadbMsgSeq, seq)
   178  	}
   179  
   180  	if h.sadbMsgPid != uint32(os.Getpid()) {
   181  		return spi, fmt.Errorf("sadb msg pid doesn't match %d %d", h.sadbMsgPid, os.Getpid())
   182  	}
   183  
   184  	buf = make([]byte, int(8*h.sadbMsgLen))
   185  	if count, _, _, _, _ := syscall.Recvmsg(fd, buf, nil, 0); count != len(buf) {
   186  		return spi, fmt.Errorf("incomplete sadb msg body %d %d", len(buf), count)
   187  	}
   188  
   189  	buf = buf[SADB_MSG_SIZE:]
   190  
   191  	for len(buf) >= 4 {
   192  		l := binary.LittleEndian.Uint16(buf[0:2]) * 8
   193  		t := binary.LittleEndian.Uint16(buf[2:4])
   194  		if t == SADB_EXT_SA {
   195  			return binary.LittleEndian.Uint32(buf[4:8]), nil
   196  		}
   197  
   198  		if len(buf) <= int(l) {
   199  			break
   200  		}
   201  		buf = buf[l:]
   202  	}
   203  	return spi, err
   204  }
   205  
   206  func sendSadbMsg(msg *sadbMsg, body []byte) (err error) {
   207  	if fd == 0 {
   208  		fd, err = syscall.Socket(syscall.AF_KEY, syscall.SOCK_RAW, PF_KEY_V2)
   209  		if err != nil {
   210  			return err
   211  		}
   212  	}
   213  
   214  	seq++
   215  	msg.sadbMsgSeq = seq
   216  	msg.sadbMsgLen = uint16((len(body) + SADB_MSG_SIZE) / 8)
   217  
   218  	buf := append(b(unsafe.Pointer(msg), SADB_MSG_SIZE), body...)
   219  
   220  	r, err := syscall.Write(fd, buf)
   221  	if r != len(buf) {
   222  		return fmt.Errorf("short write %d %d", r, len(buf))
   223  	}
   224  	return err
   225  }
   226  
   227  func rfkeyRequest(msgType uint8, src, dst string, spi uint32, key string) error {
   228  	h := sadbMsg{
   229  		sadbMsgVersion: PF_KEY_V2,
   230  		sadbMsgType:    msgType,
   231  		sadbMsgSatype:  SADB_X_SATYPE_TCPSIGNATURE,
   232  		sadbMsgPid:     uint32(os.Getpid()),
   233  	}
   234  
   235  	ssrc := newSockaddrIn(src)
   236  	sa_src := sadbAddress{
   237  		sadbAddressExttype: SADB_EXT_ADDRESS_SRC,
   238  		sadbAddressLen:     uint16(SADB_ADDRESS_SIZE+roundUp(int(ssrc.ssLen))) / 8,
   239  	}
   240  
   241  	sdst := newSockaddrIn(dst)
   242  	sa_dst := sadbAddress{
   243  		sadbAddressExttype: SADB_EXT_ADDRESS_DST,
   244  		sadbAddressLen:     uint16(SADB_ADDRESS_SIZE+roundUp(int(sdst.ssLen))) / 8,
   245  	}
   246  
   247  	buf := make([]byte, 0)
   248  	switch msgType {
   249  	case SADB_UPDATE, SADB_DELETE:
   250  		sa := sadbSa{
   251  			sadbSaLen:     uint16(SADB_SA_SIZE / 8),
   252  			sadbSaExttype: SADB_EXT_SA,
   253  			sadbSaSpi:     spi,
   254  			sadbSaState:   SADB_SASTATE_MATURE,
   255  			sadbSaEncrypt: SADB_X_EALG_AES,
   256  		}
   257  		buf = append(buf, b(unsafe.Pointer(&sa), SADB_SA_SIZE)...)
   258  	case SADB_GETSPI:
   259  		spirange := sadbSpirange{
   260  			sadbSpirangeLen:     uint16(SADB_SPIRANGE_SIZE) / 8,
   261  			sadbSpirangeExttype: SADB_EXT_SPIRANGE,
   262  			sadbSpirangeMin:     0x100,
   263  			sadbSpirangeMax:     0xffffffff,
   264  		}
   265  		buf = append(buf, b(unsafe.Pointer(&spirange), SADB_SPIRANGE_SIZE)...)
   266  	}
   267  
   268  	buf = append(buf, b(unsafe.Pointer(&sa_dst), SADB_ADDRESS_SIZE)...)
   269  	buf = append(buf, b(unsafe.Pointer(&sdst), roundUp(int(sdst.ssLen)))...)
   270  	buf = append(buf, b(unsafe.Pointer(&sa_src), SADB_ADDRESS_SIZE)...)
   271  	buf = append(buf, b(unsafe.Pointer(&ssrc), roundUp(int(ssrc.ssLen)))...)
   272  
   273  	switch msgType {
   274  	case SADB_UPDATE:
   275  		keylen := roundUp(len(key))
   276  		sa_akey := sadbKey{
   277  			sadbKeyLen:     uint16((SADB_KEY_SIZE + keylen) / 8),
   278  			sadbKeyExttype: SADB_EXT_KEY_AUTH,
   279  			sadbKeyBits:    uint16(len(key) * 8),
   280  		}
   281  		k := []byte(key)
   282  		if pad := keylen - len(k); pad != 0 {
   283  			k = append(k, make([]byte, pad)...)
   284  		}
   285  		buf = append(buf, b(unsafe.Pointer(&sa_akey), SADB_KEY_SIZE)...)
   286  		buf = append(buf, k...)
   287  	}
   288  
   289  	return sendSadbMsg(&h, buf)
   290  }
   291  
   292  func saAdd(address, key string) error {
   293  	f := func(src, dst string) error {
   294  		if err := rfkeyRequest(SADB_GETSPI, src, dst, 0, ""); err != nil {
   295  			return err
   296  		}
   297  		spi, err := pfkeyReply()
   298  		if err != nil {
   299  			return err
   300  		}
   301  		if src == "" {
   302  			spiOutMap[address] = spi
   303  		} else {
   304  			spiInMap[address] = spi
   305  		}
   306  
   307  		if err := rfkeyRequest(SADB_UPDATE, src, dst, spi, key); err != nil {
   308  			return err
   309  		}
   310  		_, err = pfkeyReply()
   311  		return err
   312  	}
   313  
   314  	if err := f(address, ""); err != nil {
   315  		return err
   316  	}
   317  
   318  	return f("", address)
   319  }
   320  
   321  func saDelete(address string) error {
   322  	if spi, y := spiInMap[address]; y {
   323  		if err := rfkeyRequest(SADB_DELETE, address, "", spi, ""); err != nil {
   324  			return fmt.Errorf("failed to delete md5 for incoming: %s", err)
   325  		}
   326  	} else {
   327  		return fmt.Errorf("can't find spi for md5 for incoming")
   328  	}
   329  
   330  	if spi, y := spiOutMap[address]; y {
   331  		if err := rfkeyRequest(SADB_DELETE, "", address, spi, ""); err != nil {
   332  			return fmt.Errorf("failed to delete md5 for outgoing: %s", err)
   333  		}
   334  	} else {
   335  		return fmt.Errorf("can't find spi for md5 for outgoing")
   336  	}
   337  	return nil
   338  }
   339  
   340  const (
   341  	tcpMD5SIG       = 0x4 // TCP MD5 Signature (RFC2385)
   342  	ipv6MinHopCount = 73  // Generalized TTL Security Mechanism (RFC5082)
   343  )
   344  
   345  func setsockoptTcpMD5Sig(sc syscall.RawConn, address string, key string) error {
   346  	if err := setsockOptInt(sc, syscall.IPPROTO_TCP, tcpMD5SIG, 1); err != nil {
   347  		return err
   348  	}
   349  	if len(key) > 0 {
   350  		return saAdd(address, key)
   351  	}
   352  	return saDelete(address)
   353  }
   354  
   355  func setTCPMD5SigSockopt(l *net.TCPListener, address string, key string) error {
   356  	sc, err := l.SyscallConn()
   357  	if err != nil {
   358  		return err
   359  	}
   360  	return setsockoptTcpMD5Sig(sc, address, key)
   361  }
   362  
   363  func setTCPTTLSockopt(conn *net.TCPConn, ttl int) error {
   364  	family := extractFamilyFromTCPConn(conn)
   365  	sc, err := conn.SyscallConn()
   366  	if err != nil {
   367  		return err
   368  	}
   369  	return setsockoptIpTtl(sc, family, ttl)
   370  }
   371  
   372  func setTCPMinTTLSockopt(conn *net.TCPConn, ttl int) error {
   373  	family := extractFamilyFromTCPConn(conn)
   374  	sc, err := conn.SyscallConn()
   375  	if err != nil {
   376  		return err
   377  	}
   378  	level := syscall.IPPROTO_IP
   379  	name := syscall.IP_MINTTL
   380  	if family == syscall.AF_INET6 {
   381  		level = syscall.IPPROTO_IPV6
   382  		name = ipv6MinHopCount
   383  	}
   384  	return setsockOptInt(sc, level, name, ttl)
   385  }
   386  
   387  func setTCPMSSSockopt(conn *net.TCPConn, mss uint16) error {
   388  	family := extractFamilyFromTCPConn(conn)
   389  	sc, err := conn.SyscallConn()
   390  	if err != nil {
   391  		return err
   392  	}
   393  	return setsockoptTcpMss(sc, family, mss)
   394  }
   395  
   396  func setBindToDevSockopt(sc syscall.RawConn, device string) error {
   397  	return fmt.Errorf("binding connection to a device is not supported")
   398  }
   399  
   400  func dialerControl(logger log.Logger, network, address string, c syscall.RawConn, ttl, minTtl uint8, mss uint16, password string, bindInterface string) error {
   401  	if password != "" {
   402  		logger.Warn("setting md5 for active connection is not supported",
   403  			log.Fields{
   404  				"Topic": "Peer",
   405  				"Key":   address})
   406  	}
   407  	if ttl != 0 {
   408  		logger.Warn("setting ttl for active connection is not supported",
   409  			log.Fields{
   410  				"Topic": "Peer",
   411  				"Key":   address})
   412  	}
   413  	if minTtl != 0 {
   414  		logger.Warn("setting min ttl for active connection is not supported",
   415  			log.Fields{
   416  				"Topic": "Peer",
   417  				"Key":   address})
   418  	}
   419  	var sockerr error
   420  	if mss != 0 {
   421  		if err := c.Control(func(fd uintptr) {
   422  			level := syscall.IPPROTO_TCP
   423  			name := syscall.TCP_MAXSEG
   424  			sockerr = os.NewSyscallError("setsockopt", syscall.SetsockoptInt(int(fd), level, name, int(mss)))
   425  		}); err != nil {
   426  			return err
   427  		}
   428  		if sockerr != nil {
   429  			return sockerr
   430  		}
   431  	}
   432  	return nil
   433  }