github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/socket/netstack/stack.go (about) 1 // Copyright 2018 The gVisor Authors. 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 implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package netstack 16 17 import ( 18 "fmt" 19 20 "github.com/SagerNet/gvisor/pkg/abi/linux" 21 "github.com/SagerNet/gvisor/pkg/errors/linuxerr" 22 "github.com/SagerNet/gvisor/pkg/log" 23 "github.com/SagerNet/gvisor/pkg/sentry/inet" 24 "github.com/SagerNet/gvisor/pkg/syserr" 25 "github.com/SagerNet/gvisor/pkg/tcpip" 26 "github.com/SagerNet/gvisor/pkg/tcpip/header" 27 "github.com/SagerNet/gvisor/pkg/tcpip/network/ipv4" 28 "github.com/SagerNet/gvisor/pkg/tcpip/network/ipv6" 29 "github.com/SagerNet/gvisor/pkg/tcpip/stack" 30 "github.com/SagerNet/gvisor/pkg/tcpip/transport/tcp" 31 ) 32 33 // Stack implements inet.Stack for netstack/tcpip/stack.Stack. 34 // 35 // +stateify savable 36 type Stack struct { 37 Stack *stack.Stack `state:"manual"` 38 } 39 40 // SupportsIPv6 implements Stack.SupportsIPv6. 41 func (s *Stack) SupportsIPv6() bool { 42 return s.Stack.CheckNetworkProtocol(ipv6.ProtocolNumber) 43 } 44 45 // Converts Netstack's ARPHardwareType to equivalent linux constants. 46 func toLinuxARPHardwareType(t header.ARPHardwareType) uint16 { 47 switch t { 48 case header.ARPHardwareNone: 49 return linux.ARPHRD_NONE 50 case header.ARPHardwareLoopback: 51 return linux.ARPHRD_LOOPBACK 52 case header.ARPHardwareEther: 53 return linux.ARPHRD_ETHER 54 default: 55 panic(fmt.Sprintf("unknown ARPHRD type: %d", t)) 56 } 57 } 58 59 // Interfaces implements inet.Stack.Interfaces. 60 func (s *Stack) Interfaces() map[int32]inet.Interface { 61 is := make(map[int32]inet.Interface) 62 for id, ni := range s.Stack.NICInfo() { 63 is[int32(id)] = inet.Interface{ 64 Name: ni.Name, 65 Addr: []byte(ni.LinkAddress), 66 Flags: uint32(nicStateFlagsToLinux(ni.Flags)), 67 DeviceType: toLinuxARPHardwareType(ni.ARPHardwareType), 68 MTU: ni.MTU, 69 } 70 } 71 return is 72 } 73 74 // InterfaceAddrs implements inet.Stack.InterfaceAddrs. 75 func (s *Stack) InterfaceAddrs() map[int32][]inet.InterfaceAddr { 76 nicAddrs := make(map[int32][]inet.InterfaceAddr) 77 for id, ni := range s.Stack.NICInfo() { 78 var addrs []inet.InterfaceAddr 79 for _, a := range ni.ProtocolAddresses { 80 var family uint8 81 switch a.Protocol { 82 case ipv4.ProtocolNumber: 83 family = linux.AF_INET 84 case ipv6.ProtocolNumber: 85 family = linux.AF_INET6 86 default: 87 log.Warningf("Unknown network protocol in %+v", a) 88 continue 89 } 90 91 addrs = append(addrs, inet.InterfaceAddr{ 92 Family: family, 93 PrefixLen: uint8(a.AddressWithPrefix.PrefixLen), 94 Addr: []byte(a.AddressWithPrefix.Address), 95 // TODO(b/68878065): Other fields. 96 }) 97 } 98 nicAddrs[int32(id)] = addrs 99 } 100 return nicAddrs 101 } 102 103 // convertAddr converts an InterfaceAddr to a ProtocolAddress. 104 func convertAddr(addr inet.InterfaceAddr) (tcpip.ProtocolAddress, error) { 105 var ( 106 protocol tcpip.NetworkProtocolNumber 107 address tcpip.Address 108 protocolAddress tcpip.ProtocolAddress 109 ) 110 switch addr.Family { 111 case linux.AF_INET: 112 if len(addr.Addr) != header.IPv4AddressSize { 113 return protocolAddress, linuxerr.EINVAL 114 } 115 if addr.PrefixLen > header.IPv4AddressSize*8 { 116 return protocolAddress, linuxerr.EINVAL 117 } 118 protocol = ipv4.ProtocolNumber 119 address = tcpip.Address(addr.Addr) 120 case linux.AF_INET6: 121 if len(addr.Addr) != header.IPv6AddressSize { 122 return protocolAddress, linuxerr.EINVAL 123 } 124 if addr.PrefixLen > header.IPv6AddressSize*8 { 125 return protocolAddress, linuxerr.EINVAL 126 } 127 protocol = ipv6.ProtocolNumber 128 address = tcpip.Address(addr.Addr) 129 default: 130 return protocolAddress, linuxerr.ENOTSUP 131 } 132 133 protocolAddress = tcpip.ProtocolAddress{ 134 Protocol: protocol, 135 AddressWithPrefix: tcpip.AddressWithPrefix{ 136 Address: address, 137 PrefixLen: int(addr.PrefixLen), 138 }, 139 } 140 return protocolAddress, nil 141 } 142 143 // AddInterfaceAddr implements inet.Stack.AddInterfaceAddr. 144 func (s *Stack) AddInterfaceAddr(idx int32, addr inet.InterfaceAddr) error { 145 protocolAddress, err := convertAddr(addr) 146 if err != nil { 147 return err 148 } 149 150 // Attach address to interface. 151 nicID := tcpip.NICID(idx) 152 if err := s.Stack.AddProtocolAddressWithOptions(nicID, protocolAddress, stack.CanBePrimaryEndpoint); err != nil { 153 return syserr.TranslateNetstackError(err).ToError() 154 } 155 156 // Add route for local network if it doesn't exist already. 157 localRoute := tcpip.Route{ 158 Destination: protocolAddress.AddressWithPrefix.Subnet(), 159 Gateway: "", // No gateway for local network. 160 NIC: nicID, 161 } 162 163 for _, rt := range s.Stack.GetRouteTable() { 164 if rt.Equal(localRoute) { 165 return nil 166 } 167 } 168 169 // Local route does not exist yet. Add it. 170 s.Stack.AddRoute(localRoute) 171 172 return nil 173 } 174 175 // RemoveInterfaceAddr implements inet.Stack.RemoveInterfaceAddr. 176 func (s *Stack) RemoveInterfaceAddr(idx int32, addr inet.InterfaceAddr) error { 177 protocolAddress, err := convertAddr(addr) 178 if err != nil { 179 return err 180 } 181 182 // Remove addresses matching the address and prefix. 183 nicID := tcpip.NICID(idx) 184 if err := s.Stack.RemoveAddress(nicID, protocolAddress.AddressWithPrefix.Address); err != nil { 185 return syserr.TranslateNetstackError(err).ToError() 186 } 187 188 // Remove the corresponding local network route if it exists. 189 localRoute := tcpip.Route{ 190 Destination: protocolAddress.AddressWithPrefix.Subnet(), 191 Gateway: "", // No gateway for local network. 192 NIC: nicID, 193 } 194 s.Stack.RemoveRoutes(func(rt tcpip.Route) bool { 195 return rt.Equal(localRoute) 196 }) 197 198 return nil 199 } 200 201 // TCPReceiveBufferSize implements inet.Stack.TCPReceiveBufferSize. 202 func (s *Stack) TCPReceiveBufferSize() (inet.TCPBufferSize, error) { 203 var rs tcpip.TCPReceiveBufferSizeRangeOption 204 err := s.Stack.TransportProtocolOption(tcp.ProtocolNumber, &rs) 205 return inet.TCPBufferSize{ 206 Min: rs.Min, 207 Default: rs.Default, 208 Max: rs.Max, 209 }, syserr.TranslateNetstackError(err).ToError() 210 } 211 212 // SetTCPReceiveBufferSize implements inet.Stack.SetTCPReceiveBufferSize. 213 func (s *Stack) SetTCPReceiveBufferSize(size inet.TCPBufferSize) error { 214 rs := tcpip.TCPReceiveBufferSizeRangeOption{ 215 Min: size.Min, 216 Default: size.Default, 217 Max: size.Max, 218 } 219 return syserr.TranslateNetstackError(s.Stack.SetTransportProtocolOption(tcp.ProtocolNumber, &rs)).ToError() 220 } 221 222 // TCPSendBufferSize implements inet.Stack.TCPSendBufferSize. 223 func (s *Stack) TCPSendBufferSize() (inet.TCPBufferSize, error) { 224 var ss tcpip.TCPSendBufferSizeRangeOption 225 err := s.Stack.TransportProtocolOption(tcp.ProtocolNumber, &ss) 226 return inet.TCPBufferSize{ 227 Min: ss.Min, 228 Default: ss.Default, 229 Max: ss.Max, 230 }, syserr.TranslateNetstackError(err).ToError() 231 } 232 233 // SetTCPSendBufferSize implements inet.Stack.SetTCPSendBufferSize. 234 func (s *Stack) SetTCPSendBufferSize(size inet.TCPBufferSize) error { 235 ss := tcpip.TCPSendBufferSizeRangeOption{ 236 Min: size.Min, 237 Default: size.Default, 238 Max: size.Max, 239 } 240 return syserr.TranslateNetstackError(s.Stack.SetTransportProtocolOption(tcp.ProtocolNumber, &ss)).ToError() 241 } 242 243 // TCPSACKEnabled implements inet.Stack.TCPSACKEnabled. 244 func (s *Stack) TCPSACKEnabled() (bool, error) { 245 var sack tcpip.TCPSACKEnabled 246 err := s.Stack.TransportProtocolOption(tcp.ProtocolNumber, &sack) 247 return bool(sack), syserr.TranslateNetstackError(err).ToError() 248 } 249 250 // SetTCPSACKEnabled implements inet.Stack.SetTCPSACKEnabled. 251 func (s *Stack) SetTCPSACKEnabled(enabled bool) error { 252 opt := tcpip.TCPSACKEnabled(enabled) 253 return syserr.TranslateNetstackError(s.Stack.SetTransportProtocolOption(tcp.ProtocolNumber, &opt)).ToError() 254 } 255 256 // TCPRecovery implements inet.Stack.TCPRecovery. 257 func (s *Stack) TCPRecovery() (inet.TCPLossRecovery, error) { 258 var recovery tcpip.TCPRecovery 259 if err := s.Stack.TransportProtocolOption(tcp.ProtocolNumber, &recovery); err != nil { 260 return 0, syserr.TranslateNetstackError(err).ToError() 261 } 262 return inet.TCPLossRecovery(recovery), nil 263 } 264 265 // SetTCPRecovery implements inet.Stack.SetTCPRecovery. 266 func (s *Stack) SetTCPRecovery(recovery inet.TCPLossRecovery) error { 267 opt := tcpip.TCPRecovery(recovery) 268 return syserr.TranslateNetstackError(s.Stack.SetTransportProtocolOption(tcp.ProtocolNumber, &opt)).ToError() 269 } 270 271 // Statistics implements inet.Stack.Statistics. 272 func (s *Stack) Statistics(stat interface{}, arg string) error { 273 switch stats := stat.(type) { 274 case *inet.StatDev: 275 for _, ni := range s.Stack.NICInfo() { 276 if ni.Name != arg { 277 continue 278 } 279 // TODO(github.com/SagerNet/issue/2103) Support stubbed stats. 280 *stats = inet.StatDev{ 281 // Receive section. 282 ni.Stats.Rx.Bytes.Value(), // bytes. 283 ni.Stats.Rx.Packets.Value(), // packets. 284 0, // errs. 285 0, // drop. 286 0, // fifo. 287 0, // frame. 288 0, // compressed. 289 0, // multicast. 290 // Transmit section. 291 ni.Stats.Tx.Bytes.Value(), // bytes. 292 ni.Stats.Tx.Packets.Value(), // packets. 293 0, // errs. 294 0, // drop. 295 0, // fifo. 296 0, // colls. 297 0, // carrier. 298 0, // compressed. 299 } 300 break 301 } 302 case *inet.StatSNMPIP: 303 ip := Metrics.IP 304 // TODO(github.com/SagerNet/issue/969) Support stubbed stats. 305 *stats = inet.StatSNMPIP{ 306 0, // Ip/Forwarding. 307 0, // Ip/DefaultTTL. 308 ip.PacketsReceived.Value(), // InReceives. 309 0, // Ip/InHdrErrors. 310 ip.InvalidDestinationAddressesReceived.Value(), // InAddrErrors. 311 0, // Ip/ForwDatagrams. 312 0, // Ip/InUnknownProtos. 313 0, // Ip/InDiscards. 314 ip.PacketsDelivered.Value(), // InDelivers. 315 ip.PacketsSent.Value(), // OutRequests. 316 ip.OutgoingPacketErrors.Value(), // OutDiscards. 317 0, // Ip/OutNoRoutes. 318 0, // Support Ip/ReasmTimeout. 319 0, // Support Ip/ReasmReqds. 320 0, // Support Ip/ReasmOKs. 321 0, // Support Ip/ReasmFails. 322 0, // Support Ip/FragOKs. 323 0, // Support Ip/FragFails. 324 0, // Support Ip/FragCreates. 325 } 326 case *inet.StatSNMPICMP: 327 in := Metrics.ICMP.V4.PacketsReceived.ICMPv4PacketStats 328 out := Metrics.ICMP.V4.PacketsSent.ICMPv4PacketStats 329 // TODO(github.com/SagerNet/issue/969) Support stubbed stats. 330 *stats = inet.StatSNMPICMP{ 331 0, // Icmp/InMsgs. 332 Metrics.ICMP.V4.PacketsSent.Dropped.Value(), // InErrors. 333 0, // Icmp/InCsumErrors. 334 in.DstUnreachable.Value(), // InDestUnreachs. 335 in.TimeExceeded.Value(), // InTimeExcds. 336 in.ParamProblem.Value(), // InParmProbs. 337 in.SrcQuench.Value(), // InSrcQuenchs. 338 in.Redirect.Value(), // InRedirects. 339 in.EchoRequest.Value(), // InEchos. 340 in.EchoReply.Value(), // InEchoReps. 341 in.Timestamp.Value(), // InTimestamps. 342 in.TimestampReply.Value(), // InTimestampReps. 343 in.InfoRequest.Value(), // InAddrMasks. 344 in.InfoReply.Value(), // InAddrMaskReps. 345 0, // Icmp/OutMsgs. 346 Metrics.ICMP.V4.PacketsReceived.Invalid.Value(), // OutErrors. 347 out.DstUnreachable.Value(), // OutDestUnreachs. 348 out.TimeExceeded.Value(), // OutTimeExcds. 349 out.ParamProblem.Value(), // OutParmProbs. 350 out.SrcQuench.Value(), // OutSrcQuenchs. 351 out.Redirect.Value(), // OutRedirects. 352 out.EchoRequest.Value(), // OutEchos. 353 out.EchoReply.Value(), // OutEchoReps. 354 out.Timestamp.Value(), // OutTimestamps. 355 out.TimestampReply.Value(), // OutTimestampReps. 356 out.InfoRequest.Value(), // OutAddrMasks. 357 out.InfoReply.Value(), // OutAddrMaskReps. 358 } 359 case *inet.StatSNMPTCP: 360 tcp := Metrics.TCP 361 // RFC 2012 (updates 1213): SNMPv2-MIB-TCP. 362 *stats = inet.StatSNMPTCP{ 363 1, // RtoAlgorithm. 364 200, // RtoMin. 365 120000, // RtoMax. 366 (1<<64 - 1), // MaxConn. 367 tcp.ActiveConnectionOpenings.Value(), // ActiveOpens. 368 tcp.PassiveConnectionOpenings.Value(), // PassiveOpens. 369 tcp.FailedConnectionAttempts.Value(), // AttemptFails. 370 tcp.EstablishedResets.Value(), // EstabResets. 371 tcp.CurrentEstablished.Value(), // CurrEstab. 372 tcp.ValidSegmentsReceived.Value(), // InSegs. 373 tcp.SegmentsSent.Value(), // OutSegs. 374 tcp.Retransmits.Value(), // RetransSegs. 375 tcp.InvalidSegmentsReceived.Value(), // InErrs. 376 tcp.ResetsSent.Value(), // OutRsts. 377 tcp.ChecksumErrors.Value(), // InCsumErrors. 378 } 379 case *inet.StatSNMPUDP: 380 udp := Metrics.UDP 381 // TODO(github.com/SagerNet/issue/969) Support stubbed stats. 382 *stats = inet.StatSNMPUDP{ 383 udp.PacketsReceived.Value(), // InDatagrams. 384 udp.UnknownPortErrors.Value(), // NoPorts. 385 0, // Udp/InErrors. 386 udp.PacketsSent.Value(), // OutDatagrams. 387 udp.ReceiveBufferErrors.Value(), // RcvbufErrors. 388 0, // Udp/SndbufErrors. 389 udp.ChecksumErrors.Value(), // Udp/InCsumErrors. 390 0, // Udp/IgnoredMulti. 391 } 392 default: 393 return syserr.ErrEndpointOperation.ToError() 394 } 395 return nil 396 } 397 398 // RouteTable implements inet.Stack.RouteTable. 399 func (s *Stack) RouteTable() []inet.Route { 400 var routeTable []inet.Route 401 402 for _, rt := range s.Stack.GetRouteTable() { 403 var family uint8 404 switch len(rt.Destination.ID()) { 405 case header.IPv4AddressSize: 406 family = linux.AF_INET 407 case header.IPv6AddressSize: 408 family = linux.AF_INET6 409 default: 410 log.Warningf("Unknown network protocol in route %+v", rt) 411 continue 412 } 413 414 routeTable = append(routeTable, inet.Route{ 415 Family: family, 416 DstLen: uint8(rt.Destination.Prefix()), // The CIDR prefix for the destination. 417 418 // Always return unspecified protocol since we have no notion of 419 // protocol for routes. 420 Protocol: linux.RTPROT_UNSPEC, 421 // Set statically to LINK scope for now. 422 // 423 // TODO(github.com/SagerNet/issue/595): Set scope for routes. 424 Scope: linux.RT_SCOPE_LINK, 425 Type: linux.RTN_UNICAST, 426 427 DstAddr: []byte(rt.Destination.ID()), 428 OutputInterface: int32(rt.NIC), 429 GatewayAddr: []byte(rt.Gateway), 430 }) 431 } 432 433 return routeTable 434 } 435 436 // IPTables returns the stack's iptables. 437 func (s *Stack) IPTables() (*stack.IPTables, error) { 438 return s.Stack.IPTables(), nil 439 } 440 441 // Resume implements inet.Stack.Resume. 442 func (s *Stack) Resume() { 443 s.Stack.Resume() 444 } 445 446 // RegisteredEndpoints implements inet.Stack.RegisteredEndpoints. 447 func (s *Stack) RegisteredEndpoints() []stack.TransportEndpoint { 448 return s.Stack.RegisteredEndpoints() 449 } 450 451 // CleanupEndpoints implements inet.Stack.CleanupEndpoints. 452 func (s *Stack) CleanupEndpoints() []stack.TransportEndpoint { 453 return s.Stack.CleanupEndpoints() 454 } 455 456 // RestoreCleanupEndpoints implements inet.Stack.RestoreCleanupEndpoints. 457 func (s *Stack) RestoreCleanupEndpoints(es []stack.TransportEndpoint) { 458 s.Stack.RestoreCleanupEndpoints(es) 459 } 460 461 // SetForwarding implements inet.Stack.SetForwarding. 462 func (s *Stack) SetForwarding(protocol tcpip.NetworkProtocolNumber, enable bool) error { 463 if err := s.Stack.SetForwardingDefaultAndAllNICs(protocol, enable); err != nil { 464 return fmt.Errorf("SetForwardingDefaultAndAllNICs(%d, %t): %s", protocol, enable, err) 465 } 466 return nil 467 } 468 469 // PortRange implements inet.Stack.PortRange. 470 func (s *Stack) PortRange() (uint16, uint16) { 471 return s.Stack.PortRange() 472 } 473 474 // SetPortRange implements inet.Stack.SetPortRange. 475 func (s *Stack) SetPortRange(start uint16, end uint16) error { 476 return syserr.TranslateNetstackError(s.Stack.SetPortRange(start, end)).ToError() 477 }