Signed-off-by: Tomas Krcka <tomas.kr...@gmail.com> --- linux-user/syscall.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 05f03919ff..88d4c85b70 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -56,6 +56,7 @@ #include <linux/wireless.h> #include <linux/icmp.h> #include <linux/icmpv6.h> +#include <linux/can/raw.h> #include <linux/errqueue.h> #include <linux/random.h> #ifdef CONFIG_TIMERFD @@ -2111,6 +2112,39 @@ static abi_long do_setsockopt(int sockfd, int level, int optname, goto unimplemented; } break; + case SOL_CAN_RAW: + switch (optname) { + case CAN_RAW_FILTER: + { + if (optlen % sizeof(struct can_filter) != 0) { + return -TARGET_EINVAL; + } + + struct can_filter *can_filters = NULL; + if (optlen != 0) { + can_filters = g_new0(struct can_filter, optlen); + + if (!can_filters) { + return -TARGET_ENOMEM; + } + if (copy_from_user(can_filters, optval_addr, optlen)) { + g_free(can_filters); + return -TARGET_EFAULT; + } + for (val = 0; val < optlen / sizeof(struct can_filter); val++) { + can_filters[val].can_id = tswap32(can_filters[val].can_id); + can_filters[val].can_mask = tswap32(can_filters[val].can_mask); + } + } + ret = get_errno(setsockopt(sockfd, level, optname, + can_filters, optlen)); + g_free(can_filters); + break; + } + default: + goto unimplemented; + } + break; case SOL_RAW: switch (optname) { case ICMP_FILTER: -- 2.17.1