#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <linux/wireless.h>
+#include <linux/icmp.h>
#include "qemu-common.h"
#ifdef TARGET_GPROF
#include <sys/gmon.h>
return 0;
}
-/* ??? Should this also swap msgh->name? */
static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
struct target_msghdr *target_msgh)
{
return 0;
}
-/* ??? Should this also swap msgh->name? */
static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
struct msghdr *msgh)
{
target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(len));
- if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
- gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
- memcpy(target_data, data, len);
- } else {
+ if ((cmsg->cmsg_level == TARGET_SOL_SOCKET) &&
+ (cmsg->cmsg_type == SCM_RIGHTS)) {
int *fd = (int *)data;
int *target_fd = (int *)target_data;
int i, numfds = len / sizeof(int);
for (i = 0; i < numfds; i++)
target_fd[i] = tswap32(fd[i]);
+ } else if ((cmsg->cmsg_level == TARGET_SOL_SOCKET) &&
+ (cmsg->cmsg_type == SO_TIMESTAMP) &&
+ (len == sizeof(struct timeval))) {
+ /* copy struct timeval to target */
+ struct timeval *tv = (struct timeval *)data;
+ struct target_timeval *target_tv =
+ (struct target_timeval *)target_data;
+
+ target_tv->tv_sec = tswapal(tv->tv_sec);
+ target_tv->tv_usec = tswapal(tv->tv_usec);
+ } else {
+ gemu_log("Unsupported ancillary data: %d/%d\n",
+ cmsg->cmsg_level, cmsg->cmsg_type);
+ memcpy(target_data, data, len);
}
cmsg = CMSG_NXTHDR(msgh, cmsg);
unlock_user (ip_mreq_source, optval_addr, 0);
break;
+ default:
+ goto unimplemented;
+ }
+ break;
+ case SOL_RAW:
+ switch (optname) {
+ case ICMP_FILTER:
+ /* struct icmp_filter takes an u32 value */
+ if (optlen < sizeof(uint32_t)) {
+ return -TARGET_EINVAL;
+ }
+
+ if (get_user_u32(val, optval_addr)) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(setsockopt(sockfd, level, optname,
+ &val, sizeof(val)));
+ break;
+
default:
goto unimplemented;
}
if (!is_error(ret)) {
len = ret;
ret = host_to_target_cmsg(msgp, &msg);
- if (!is_error(ret))
+ if (!is_error(ret)) {
+ msgp->msg_namelen = tswap32(msg.msg_namelen);
+ if (msg.msg_name != NULL) {
+ ret = host_to_target_sockaddr(tswapal(msgp->msg_name),
+ msg.msg_name, msg.msg_namelen);
+ if (ret) {
+ goto out;
+ }
+ }
+
ret = len;
+ }
}
}
+
+out:
unlock_iovec(vec, target_vec, count, !send);
unlock_user_struct(msgp, target_msg, send ? 0 : 1);
return ret;
if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
return -TARGET_EFAULT;
- host_mb = malloc(msgsz+sizeof(long));
+ host_mb = g_malloc(msgsz+sizeof(long));
ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapal(msgtyp), msgflg));
if (ret > 0) {
}
target_mb->mtype = tswapal(host_mb->mtype);
- free(host_mb);
end:
if (target_mb)
unlock_user_struct(target_mb, msgp, 1);
+ g_free(host_mb);
return ret;
}
#undef STRUCT
#undef STRUCT_SPECIAL
+ /* Build target_to_host_errno_table[] table from
+ * host_to_target_errno_table[]. */
+ for (i = 0; i < ERRNO_TABLE_SIZE; i++) {
+ target_to_host_errno_table[host_to_target_errno_table[i]] = i;
+ }
+
/* we patch the ioctl size if necessary. We rely on the fact that
no ioctl has all the bits at '1' in the size field */
ie = ioctl_entries;
(size << TARGET_IOC_SIZESHIFT);
}
- /* Build target_to_host_errno_table[] table from
- * host_to_target_errno_table[]. */
- for (i=0; i < ERRNO_TABLE_SIZE; i++)
- target_to_host_errno_table[host_to_target_errno_table[i]] = i;
-
/* automatic consistency check if same arch */
#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
(defined(__x86_64__) && defined(TARGET_X86_64))
tde = target_dirp;
while (len > 0) {
reclen = de->d_reclen;
- treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
+ tnamelen = reclen - offsetof(struct linux_dirent, d_name);
+ assert(tnamelen >= 0);
+ treclen = tnamelen + offsetof(struct target_dirent, d_name);
+ assert(count1 + treclen <= count);
tde->d_reclen = tswap16(treclen);
tde->d_ino = tswapal(de->d_ino);
tde->d_off = tswapal(de->d_off);
- tnamelen = treclen - (2 * sizeof(abi_long) + 2);
- if (tnamelen > 256)
- tnamelen = 256;
- /* XXX: may not be correct */
- pstrcpy(tde->d_name, tnamelen, de->d_name);
+ memcpy(tde->d_name, de->d_name, tnamelen);
de = (struct linux_dirent *)((char *)de + reclen);
len -= reclen;
tde = (struct target_dirent *)((char *)tde + treclen);