From 7936e63336a736ca7d857e4fb7578895b249382e Mon Sep 17 00:00:00 2001 From: Brandon Potter Date: Wed, 18 Apr 2018 15:00:14 -0400 Subject: [PATCH] sim-se: add ability to get/set sock metadata Add getsockopt, getsockname, setsockname, and getpeername system calls. Change-Id: Ifa1d9a95f15b4fb12859dbfd3c4bd248de2e3d32 Reviewed-on: https://gem5-review.googlesource.com/c/12116 Reviewed-by: Anthony Gutierrez Maintainer: Anthony Gutierrez --- src/arch/x86/linux/process.cc | 8 +- src/sim/syscall_emul.cc | 134 ++++++++++++++++++++++++++++++++++ src/sim/syscall_emul.hh | 16 ++++ 3 files changed, 154 insertions(+), 4 deletions(-) diff --git a/src/arch/x86/linux/process.cc b/src/arch/x86/linux/process.cc index 03a88fc6e..2fe99e0be 100644 --- a/src/arch/x86/linux/process.cc +++ b/src/arch/x86/linux/process.cc @@ -273,11 +273,11 @@ static SyscallDesc syscallDescs64[] = { /* 48 */ SyscallDesc("shutdown", shutdownFunc), /* 49 */ SyscallDesc("bind", bindFunc), /* 50 */ SyscallDesc("listen", listenFunc), - /* 51 */ SyscallDesc("getsockname", unimplementedFunc), - /* 52 */ SyscallDesc("getpeername", unimplementedFunc), + /* 51 */ SyscallDesc("getsockname", getsocknameFunc), + /* 52 */ SyscallDesc("getpeername", getpeernameFunc), /* 53 */ SyscallDesc("socketpair", socketpairFunc), - /* 54 */ SyscallDesc("setsockopt", unimplementedFunc), - /* 55 */ SyscallDesc("getsockopt", unimplementedFunc), + /* 54 */ SyscallDesc("setsockopt", setsockoptFunc), + /* 55 */ SyscallDesc("getsockopt", getsockoptFunc), /* 56 */ SyscallDesc("clone", cloneFunc), /* 57 */ SyscallDesc("fork", unimplementedFunc), /* 58 */ SyscallDesc("vfork", unimplementedFunc), diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index 74ca1e924..25e0b6856 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -1567,3 +1567,137 @@ sendmsgFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) return (sent_size < 0) ? -local_errno : sent_size; } +SyscallReturn +getsockoptFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) +{ + // union of all possible return value types from getsockopt + union val { + int i_val; + long l_val; + struct linger linger_val; + struct timeval timeval_val; + } val; + + int index = 0; + int tgt_fd = p->getSyscallArg(tc, index); + int level = p->getSyscallArg(tc, index); + int optname = p->getSyscallArg(tc, index); + Addr valPtr = p->getSyscallArg(tc, index); + Addr lenPtr = p->getSyscallArg(tc, index); + + auto sfdp = std::dynamic_pointer_cast((*p->fds)[tgt_fd]); + if (!sfdp) + return -EBADF; + int sim_fd = sfdp->getSimFD(); + + socklen_t len = sizeof(val); + int status = getsockopt(sim_fd, level, optname, &val, &len); + + if (status == -1) + return -errno; + + // copy val to valPtr and pass it on + BufferArg valBuf(valPtr, sizeof(val)); + memcpy(valBuf.bufferPtr(), &val, sizeof(val)); + valBuf.copyOut(tc->getMemProxy()); + + // copy len to lenPtr and pass it on + BufferArg lenBuf(lenPtr, sizeof(len)); + memcpy(lenBuf.bufferPtr(), &len, sizeof(len)); + lenBuf.copyOut(tc->getMemProxy()); + + return status; +} + +SyscallReturn +getsocknameFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) +{ + int index = 0; + int tgt_fd = p->getSyscallArg(tc, index); + Addr addrPtr = p->getSyscallArg(tc, index); + Addr lenPtr = p->getSyscallArg(tc, index); + + auto sfdp = std::dynamic_pointer_cast((*p->fds)[tgt_fd]); + if (!sfdp) + return -EBADF; + int sim_fd = sfdp->getSimFD(); + + // lenPtr is an in-out paramenter: + // sending the address length in, conveying the final length out + + // Read in the value of len from the passed pointer. + BufferArg lenBuf(lenPtr, sizeof(socklen_t)); + lenBuf.copyIn(tc->getMemProxy()); + socklen_t len = *(socklen_t *)lenBuf.bufferPtr(); + + struct sockaddr sa; + int status = getsockname(sim_fd, &sa, &len); + + if (status == -1) + return -errno; + + // Copy address to addrPtr and pass it on. + BufferArg addrBuf(addrPtr, sizeof(sa)); + memcpy(addrBuf.bufferPtr(), &sa, sizeof(sa)); + addrBuf.copyOut(tc->getMemProxy()); + + // Copy len to lenPtr and pass it on. + *(socklen_t *)lenBuf.bufferPtr() = len; + lenBuf.copyOut(tc->getMemProxy()); + + return status; +} + +SyscallReturn +getpeernameFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) +{ + int index = 0; + int tgt_fd = p->getSyscallArg(tc, index); + Addr sockAddrPtr = p->getSyscallArg(tc, index); + Addr addrlenPtr = p->getSyscallArg(tc, index); + + auto sfdp = std::dynamic_pointer_cast((*p->fds)[tgt_fd]); + if (!sfdp) + return -EBADF; + int sim_fd = sfdp->getSimFD(); + + BufferArg bufAddrlen(addrlenPtr, sizeof(unsigned)); + bufAddrlen.copyIn(tc->getMemProxy()); + BufferArg bufSock(sockAddrPtr, *(unsigned *)bufAddrlen.bufferPtr()); + + int retval = getpeername(sim_fd, + (struct sockaddr *)bufSock.bufferPtr(), + (unsigned *)bufAddrlen.bufferPtr()); + + if (retval != -1) { + bufSock.copyOut(tc->getMemProxy()); + bufAddrlen.copyOut(tc->getMemProxy()); + } + + return (retval == -1) ? -errno : retval; +} + +SyscallReturn +setsockoptFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) +{ + int index = 0; + int tgt_fd = p->getSyscallArg(tc, index); + int level = p->getSyscallArg(tc, index); + int optname = p->getSyscallArg(tc, index); + Addr valPtr = p->getSyscallArg(tc, index); + socklen_t len = p->getSyscallArg(tc, index); + + BufferArg valBuf(valPtr, len); + valBuf.copyIn(tc->getMemProxy()); + + auto sfdp = std::dynamic_pointer_cast((*p->fds)[tgt_fd]); + if (!sfdp) + return -EBADF; + int sim_fd = sfdp->getSimFD(); + + int status = setsockopt(sim_fd, level, optname, + (struct sockaddr *)valBuf.bufferPtr(), len); + + return (status == -1) ? -errno : status; +} + diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index 67fa9e3d3..c52589f3a 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -302,6 +302,10 @@ SyscallReturn pipeImpl(SyscallDesc *desc, int num, Process *p, SyscallReturn getpidFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc); +// Target getpeername() handler. +SyscallReturn getpeernameFunc(SyscallDesc *desc, int num, + Process *p, ThreadContext *tc); + // Target bind() handler. SyscallReturn bindFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc); @@ -369,6 +373,18 @@ SyscallReturn accessFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc, int index); +// Target getsockopt() handler. +SyscallReturn getsockoptFunc(SyscallDesc *desc, int num, + Process *p, ThreadContext *tc); + +// Target setsockopt() handler. +SyscallReturn setsockoptFunc(SyscallDesc *desc, int num, + Process *p, ThreadContext *tc); + +// Target getsockname() handler. +SyscallReturn getsocknameFunc(SyscallDesc *desc, int num, + Process *p, ThreadContext *tc); + /// Futex system call /// Implemented by Daniel Sanchez /// Used by printf's in multi-threaded apps -- 2.30.2