/* 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<X86Linux64>),
- /* 54 */ SyscallDesc("setsockopt", unimplementedFunc),
- /* 55 */ SyscallDesc("getsockopt", unimplementedFunc),
+ /* 54 */ SyscallDesc("setsockopt", setsockoptFunc),
+ /* 55 */ SyscallDesc("getsockopt", getsockoptFunc),
/* 56 */ SyscallDesc("clone", cloneFunc<X86Linux64>),
/* 57 */ SyscallDesc("fork", unimplementedFunc),
/* 58 */ SyscallDesc("vfork", unimplementedFunc),
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<SocketFDEntry>((*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<SocketFDEntry>((*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<SocketFDEntry>((*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<SocketFDEntry>((*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;
+}
+
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);
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