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 }