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