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  }