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 }