diff mbox series

[1/2] linux-user: add do_setsockopt SOL_CAN_RAW CAN_RAW_FILTER support

Message ID 20200506132114.76406-1-tomas.krcka@gmail.com
State New
Headers show
Series [1/2] linux-user: add do_setsockopt SOL_CAN_RAW CAN_RAW_FILTER support | expand

Commit Message

Tomas Krcka May 6, 2020, 1:21 p.m. UTC
Signed-off-by: Tomas Krcka <tomas.krcka@gmail.com>
---
 linux-user/syscall.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)
diff mbox series

Patch

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: