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 }