mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Add rpcinet support for control messages.
Add support for control messages, but at this time the only control message that the sentry will support here is SO_TIMESTAMP. PiperOrigin-RevId: 200922230 Change-Id: I63a852d9305255625d9df1d989bd46a66e93c446
This commit is contained in:
@@ -477,6 +477,37 @@ func rpcRecvMsg(t *kernel.Task, req *pb.SyscallRequest_Recvmsg) (*pb.RecvmsgResp
|
||||
return res.(*pb.RecvmsgResponse_Payload).Payload, nil
|
||||
}
|
||||
|
||||
// Because we only support SO_TIMESTAMP we will search control messages for
|
||||
// that value and set it if so, all other control messages will be ignored.
|
||||
func (s *socketOperations) extractControlMessages(payload *pb.RecvmsgResponse_ResultPayload) socket.ControlMessages {
|
||||
c := socket.ControlMessages{}
|
||||
if len(payload.GetCmsgData()) > 0 {
|
||||
// Parse the control messages looking for SO_TIMESTAMP.
|
||||
msgs, e := syscall.ParseSocketControlMessage(payload.GetCmsgData())
|
||||
if e != nil {
|
||||
return socket.ControlMessages{}
|
||||
}
|
||||
for _, m := range msgs {
|
||||
if m.Header.Level != linux.SOL_SOCKET || m.Header.Type != linux.SO_TIMESTAMP {
|
||||
continue
|
||||
}
|
||||
|
||||
// Let's parse the time stamp and set it.
|
||||
if len(m.Data) < linux.SizeOfTimeval {
|
||||
// Give up on locating the SO_TIMESTAMP option.
|
||||
return socket.ControlMessages{}
|
||||
}
|
||||
|
||||
var v linux.Timeval
|
||||
binary.Unmarshal(m.Data[:linux.SizeOfTimeval], usermem.ByteOrder, &v)
|
||||
c.IP.HasTimestamp = true
|
||||
c.IP.Timestamp = v.ToNsecCapped()
|
||||
break
|
||||
}
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// RecvMsg implements socket.Socket.RecvMsg.
|
||||
func (s *socketOperations) RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags int, haveDeadline bool, deadline ktime.Time, senderRequested bool, controlDataLen uint64) (int, interface{}, uint32, socket.ControlMessages, *syserr.Error) {
|
||||
req := &pb.SyscallRequest_Recvmsg{&pb.RecvmsgRequest{
|
||||
@@ -497,7 +528,8 @@ func (s *socketOperations) RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags
|
||||
panic("CopyOut failed to copy full buffer")
|
||||
}
|
||||
}
|
||||
return int(res.Length), res.Address.GetAddress(), res.Address.GetLength(), socket.ControlMessages{}, syserr.FromError(e)
|
||||
c := s.extractControlMessages(res)
|
||||
return int(res.Length), res.Address.GetAddress(), res.Address.GetLength(), c, syserr.FromError(e)
|
||||
}
|
||||
if err != syserr.ErrWouldBlock && err != syserr.ErrTryAgain || flags&linux.MSG_DONTWAIT != 0 {
|
||||
return 0, nil, 0, socket.ControlMessages{}, err
|
||||
@@ -520,7 +552,8 @@ func (s *socketOperations) RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags
|
||||
panic("CopyOut failed to copy full buffer")
|
||||
}
|
||||
}
|
||||
return int(res.Length), res.Address.GetAddress(), res.Address.GetLength(), socket.ControlMessages{}, syserr.FromError(e)
|
||||
c := s.extractControlMessages(res)
|
||||
return int(res.Length), res.Address.GetAddress(), res.Address.GetLength(), c, syserr.FromError(e)
|
||||
}
|
||||
if err != syserr.ErrWouldBlock && err != syserr.ErrTryAgain {
|
||||
return 0, nil, 0, socket.ControlMessages{}, err
|
||||
|
||||
@@ -40,6 +40,7 @@ message RecvmsgRequest {
|
||||
bool sender = 3;
|
||||
bool peek = 4;
|
||||
bool trunc = 5;
|
||||
uint32 cmsg_length = 6;
|
||||
}
|
||||
|
||||
message OpenRequest {
|
||||
@@ -110,6 +111,7 @@ message RecvmsgResponse {
|
||||
bytes data = 1 [ctype = CORD];
|
||||
AddressResponse address = 2;
|
||||
uint32 length = 3;
|
||||
bytes cmsg_data = 4;
|
||||
}
|
||||
oneof result {
|
||||
uint32 error_number = 1;
|
||||
|
||||
Reference in New Issue
Block a user