mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Allow dual stack sockets to operate on AF_INET
Fixes #1490 Fixes #1495 PiperOrigin-RevId: 289523250
This commit is contained in:
committed by
gVisor bot
parent
fff0476951
commit
debd213da6
@@ -324,22 +324,15 @@ func bytesToIPAddress(addr []byte) tcpip.Address {
|
||||
// converts it to the FullAddress format. It supports AF_UNIX, AF_INET,
|
||||
// AF_INET6, and AF_PACKET addresses.
|
||||
//
|
||||
// strict indicates whether addresses with the AF_UNSPEC family are accepted of not.
|
||||
//
|
||||
// AddressAndFamily returns an address and its family.
|
||||
func AddressAndFamily(sfamily int, addr []byte, strict bool) (tcpip.FullAddress, uint16, *syserr.Error) {
|
||||
func AddressAndFamily(addr []byte) (tcpip.FullAddress, uint16, *syserr.Error) {
|
||||
// Make sure we have at least 2 bytes for the address family.
|
||||
if len(addr) < 2 {
|
||||
return tcpip.FullAddress{}, 0, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
family := usermem.ByteOrder.Uint16(addr)
|
||||
if family != uint16(sfamily) && (strict || family != linux.AF_UNSPEC) {
|
||||
return tcpip.FullAddress{}, family, syserr.ErrAddressFamilyNotSupported
|
||||
}
|
||||
|
||||
// Get the rest of the fields based on the address family.
|
||||
switch family {
|
||||
switch family := usermem.ByteOrder.Uint16(addr); family {
|
||||
case linux.AF_UNIX:
|
||||
path := addr[2:]
|
||||
if len(path) > linux.UnixPathMax {
|
||||
@@ -638,10 +631,40 @@ func (s *SocketOperations) Readiness(mask waiter.EventMask) waiter.EventMask {
|
||||
return r
|
||||
}
|
||||
|
||||
func (s *SocketOperations) checkFamily(family uint16, exact bool) *syserr.Error {
|
||||
if family == uint16(s.family) {
|
||||
return nil
|
||||
}
|
||||
if !exact && family == linux.AF_INET && s.family == linux.AF_INET6 {
|
||||
v, err := s.Endpoint.GetSockOptBool(tcpip.V6OnlyOption)
|
||||
if err != nil {
|
||||
return syserr.TranslateNetstackError(err)
|
||||
}
|
||||
if !v {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
// mapFamily maps the AF_INET ANY address to the IPv4-mapped IPv6 ANY if the
|
||||
// receiver's family is AF_INET6.
|
||||
//
|
||||
// This is a hack to work around the fact that both IPv4 and IPv6 ANY are
|
||||
// represented by the empty string.
|
||||
//
|
||||
// TODO(gvisor.dev/issues/1556): remove this function.
|
||||
func (s *SocketOperations) mapFamily(addr tcpip.FullAddress, family uint16) tcpip.FullAddress {
|
||||
if len(addr.Addr) == 0 && s.family == linux.AF_INET6 && family == linux.AF_INET {
|
||||
addr.Addr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00"
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
||||
// Connect implements the linux syscall connect(2) for sockets backed by
|
||||
// tpcip.Endpoint.
|
||||
func (s *SocketOperations) Connect(t *kernel.Task, sockaddr []byte, blocking bool) *syserr.Error {
|
||||
addr, family, err := AddressAndFamily(s.family, sockaddr, false /* strict */)
|
||||
addr, family, err := AddressAndFamily(sockaddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -653,6 +676,12 @@ func (s *SocketOperations) Connect(t *kernel.Task, sockaddr []byte, blocking boo
|
||||
}
|
||||
return syserr.TranslateNetstackError(err)
|
||||
}
|
||||
|
||||
if err := s.checkFamily(family, false /* exact */); err != nil {
|
||||
return err
|
||||
}
|
||||
addr = s.mapFamily(addr, family)
|
||||
|
||||
// Always return right away in the non-blocking case.
|
||||
if !blocking {
|
||||
return syserr.TranslateNetstackError(s.Endpoint.Connect(addr))
|
||||
@@ -681,10 +710,14 @@ func (s *SocketOperations) Connect(t *kernel.Task, sockaddr []byte, blocking boo
|
||||
// Bind implements the linux syscall bind(2) for sockets backed by
|
||||
// tcpip.Endpoint.
|
||||
func (s *SocketOperations) Bind(t *kernel.Task, sockaddr []byte) *syserr.Error {
|
||||
addr, _, err := AddressAndFamily(s.family, sockaddr, true /* strict */)
|
||||
addr, family, err := AddressAndFamily(sockaddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.checkFamily(family, true /* exact */); err != nil {
|
||||
return err
|
||||
}
|
||||
addr = s.mapFamily(addr, family)
|
||||
|
||||
// Issue the bind request to the endpoint.
|
||||
return syserr.TranslateNetstackError(s.Endpoint.Bind(addr))
|
||||
@@ -2080,8 +2113,8 @@ func ConvertAddress(family int, addr tcpip.FullAddress) (linux.SockAddr, uint32)
|
||||
|
||||
case linux.AF_INET6:
|
||||
var out linux.SockAddrInet6
|
||||
if len(addr.Addr) == 4 {
|
||||
// Copy address is v4-mapped format.
|
||||
if len(addr.Addr) == header.IPv4AddressSize {
|
||||
// Copy address in v4-mapped format.
|
||||
copy(out.Addr[12:], addr.Addr)
|
||||
out.Addr[10] = 0xff
|
||||
out.Addr[11] = 0xff
|
||||
@@ -2395,10 +2428,14 @@ func (s *SocketOperations) SendMsg(t *kernel.Task, src usermem.IOSequence, to []
|
||||
|
||||
var addr *tcpip.FullAddress
|
||||
if len(to) > 0 {
|
||||
addrBuf, _, err := AddressAndFamily(s.family, to, true /* strict */)
|
||||
addrBuf, family, err := AddressAndFamily(to)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err := s.checkFamily(family, false /* exact */); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
addrBuf = s.mapFamily(addrBuf, family)
|
||||
|
||||
addr = &addrBuf
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user