You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/06/15 14:07:30 UTC

[incubator-nuttx] 01/04: net: Add SocketCAN support

This is an automated email from the ASF dual-hosted git repository.

gnutt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 55d9e5f7af05e75ca62f57863b880d723aa83c56
Author: Peter van der Perk <pe...@nxp.com>
AuthorDate: Mon Jun 15 10:23:25 2020 +0200

    net: Add SocketCAN support
---
 fs/vfs/fs_write.c                                  |   9 +-
 include/net/if.h                                   |  19 +-
 include/netpacket/can.h                            | 140 ++++
 include/nuttx/can.h                                | 319 ++++++++
 include/nuttx/can/error.h                          | 129 ++++
 include/nuttx/mm/iob.h                             |  10 +-
 include/nuttx/net/can.h                            | 122 +++
 include/nuttx/net/ioctl.h                          |   8 +
 include/nuttx/net/net.h                            |  31 +-
 include/nuttx/wqueue.h                             |   3 +-
 include/sys/socket.h                               |  13 +
 libs/libc/net/lib_recvmsg.c                        |   7 +-
 libs/libc/net/lib_sendmsg.c                        |   4 +-
 net/Kconfig                                        |   1 +
 net/Makefile                                       |   1 +
 net/bluetooth/bluetooth_sockif.c                   |  38 +-
 net/can/Kconfig                                    |  97 +++
 net/can/Make.defs                                  |  48 ++
 net/can/can.h                                      | 385 ++++++++++
 net/can/can_callback.c                             | 242 ++++++
 net/can/can_conn.c                                 | 223 ++++++
 net/can/can_getsockopt.c                           | 220 ++++++
 net/can/can_input.c                                | 204 +++++
 .../net/lib_recvmsg.c => net/can/can_notifier.c    |  56 +-
 net/can/can_poll.c                                 |  88 +++
 net/can/can_recvfrom.c                             | 838 +++++++++++++++++++++
 net/can/can_send.c                                 | 441 +++++++++++
 net/can/can_setsockopt.c                           | 177 +++++
 net/{netlink/netlink_sockif.c => can/can_sockif.c} | 723 +++++++++---------
 net/devif/Make.defs                                |   4 +
 net/devif/devif.h                                  | 112 +--
 .../local_sendpacket.c => devif/devif_cansend.c}   | 124 +--
 net/devif/devif_poll.c                             |  48 ++
 net/icmp/icmp_sockif.c                             |  18 +-
 net/icmpv6/icmpv6_sockif.c                         |  32 +-
 net/ieee802154/ieee802154_sockif.c                 |  47 +-
 net/inet/inet_sockif.c                             |   4 +
 net/local/local_sendpacket.c                       |   1 +
 net/local/local_sockif.c                           |  12 +-
 net/net_initialize.c                               |   7 +
 net/netdev/Kconfig                                 |   8 +
 net/netdev/netdev_ioctl.c                          |  48 ++
 net/netdev/netdev_register.c                       |  12 +
 net/netlink/netlink_sockif.c                       |   4 +
 net/pkt/pkt_sockif.c                               |   4 +
 net/socket/Kconfig                                 |  24 +
 net/socket/Make.defs                               |   6 +
 net/socket/getsockopt.c                            |  19 +
 net/socket/net_sockif.c                            |   7 +
 net/socket/recvmsg.c                               | 244 ++++++
 net/socket/sendmsg.c                               | 243 ++++++
 net/socket/setsockopt.c                            |  29 +
 net/socket/socket.h                                |   2 +-
 net/utils/net_lock.c                               |  51 ++
 54 files changed, 5085 insertions(+), 621 deletions(-)

diff --git a/fs/vfs/fs_write.c b/fs/vfs/fs_write.c
index 6e9a379..d1b7f03 100644
--- a/fs/vfs/fs_write.c
+++ b/fs/vfs/fs_write.c
@@ -86,7 +86,8 @@
  *
  ****************************************************************************/
 
-ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes)
+ssize_t file_write(FAR struct file *filep, FAR const void *buf,
+                   size_t nbytes)
 {
   FAR struct inode *inode;
 
@@ -149,8 +150,10 @@ ssize_t nx_write(int fd, FAR const void *buf, size_t nbytes)
 
   if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
     {
-#ifdef CONFIG_NET_TCP
-      /* Write to a socket descriptor is equivalent to send with flags == 0. */
+#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_CAN)
+      /* Write to a socket descriptor is equivalent to
+       * send with flags == 0.
+       */
 
       ret = nx_send(fd, buf, nbytes, 0);
 #else
diff --git a/include/net/if.h b/include/net/if.h
index 0b90045..0332ab7 100644
--- a/include/net/if.h
+++ b/include/net/if.h
@@ -136,6 +136,18 @@ struct mii_ioctl_data_s
   uint16_t val_out;     /* PHY output data */
 };
 
+/* Structure passed to get or set the CAN bitrate
+ * SIOCxCANBITRATE ioctl commands.
+ */
+
+struct can_ioctl_data_s
+{
+  uint16_t arbi_bitrate; /* Classic CAN / Arbitration phase bitrate kbit/s */
+  uint16_t arbi_samplep; /* Classic CAN / Arbitration phase input % */
+  uint16_t data_bitrate; /* Data phase bitrate kbit/s */
+  uint16_t data_samplep; /* Data phase sample point % */
+};
+
 /* There are two forms of the I/F request structure.  One for IPv6 and one for IPv4.
  * Notice that they are (and must be) cast compatible and really different only
  * in the size of the structure allocation.
@@ -158,6 +170,7 @@ struct lifreq
     uint8_t                   lifru_flags;              /* Interface flags */
     struct mii_ioctl_notify_s llfru_mii_notify;         /* PHY event notification */
     struct mii_ioctl_data_s   lifru_mii_data;           /* MII request data */
+    struct can_ioctl_data_s   lifru_can_data;           /* CAN bitrate request data */
   } lifr_ifru;
 };
 
@@ -196,6 +209,9 @@ struct lifconf
 struct ifreq
 {
   char                        ifr_name[IFNAMSIZ];       /* Network device name (e.g. "eth0") */
+#ifdef CONFIG_NETDEV_IFINDEX
+  int16_t                     ifr_ifindex;              /* Interface index */
+#endif
   union
   {
     struct sockaddr           ifru_addr;                /* IP Address */
@@ -208,6 +224,7 @@ struct ifreq
     uint8_t                   ifru_flags;               /* Interface flags */
     struct mii_ioctl_notify_s ifru_mii_notify;          /* PHY event notification */
     struct mii_ioctl_data_s   ifru_mii_data;            /* MII request data */
+    struct can_ioctl_data_s   ifru_can_data;            /* CAN bitrate request data */
   } ifr_ifru;
 };
 
@@ -226,7 +243,7 @@ struct ifreq
 #define ifr_mii_val_in        ifr_ifru.ifru_mii_data.val_in  /* PHY input data */
 #define ifr_mii_val_out       ifr_ifru.ifru_mii_data.val_out /* PHY output data */
 
-/* Used only with the SIOCGIFCONF IOCTL command*/
+/* Used only with the SIOCGIFCONF IOCTL command */
 
 struct ifconf
 {
diff --git a/include/netpacket/can.h b/include/netpacket/can.h
new file mode 100644
index 0000000..4ee6645
--- /dev/null
+++ b/include/netpacket/can.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+ * include/netpacket/can.h
+ * Definitions for use with AF_PACKET sockets
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NETPACKET_CAN_H
+#define __INCLUDE_NETPACKET_CAN_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Special address description flags for the CAN_ID */
+
+#define CAN_EFF_FLAG 0x80000000  /* EFF/SFF is set in the MSB */
+#define CAN_RTR_FLAG 0x40000000  /* Remote transmission request */
+#define CAN_ERR_FLAG 0x20000000  /* Error message frame */
+
+/* Valid bits in CAN ID for frame formats */
+
+#define CAN_SFF_MASK 0x000007ff  /* Standard frame format (SFF) */
+#define CAN_EFF_MASK 0x1fffffff  /* Extended frame format (EFF) */
+#define CAN_ERR_MASK 0x1fffffff  /* Omit EFF, RTR, ERR flags */
+
+#define CAN_MTU		(sizeof(struct can_frame))
+#define CANFD_MTU	(sizeof(struct canfd_frame))
+
+/* PF_CAN protocols */
+
+#define CAN_RAW      1           /* RAW sockets */
+#define CAN_BCM      2           /* Broadcast Manager */
+#define CAN_TP16     3           /* VAG Transport Protocol v1.6 */
+#define CAN_TP20     4           /* VAG Transport Protocol v2.0 */
+#define CAN_MCNET    5           /* Bosch MCNet */
+#define CAN_ISOTP    6           /* ISO 15765-2 Transport Protocol */
+#define CAN_J1939    7           /* SAE J1939 */
+#define CAN_NPROTO   8
+
+/* CAN_RAW socket options */
+
+#define CAN_RAW_FILTER         (__SO_PROTOCOL + 0)     
+                                 /* set 0 .. n can_filter(s) */
+#define CAN_RAW_ERR_FILTER     (__SO_PROTOCOL + 1)      
+                                 /* set filter for error frames */
+#define CAN_RAW_LOOPBACK       (__SO_PROTOCOL + 2)      
+                                 /* local loopback (default:on) */
+#define CAN_RAW_RECV_OWN_MSGS  (__SO_PROTOCOL + 3)	     
+                                 /* receive my own msgs (default:off) */
+#define CAN_RAW_FD_FRAMES      (__SO_PROTOCOL + 4)      
+                                 /* allow CAN FD frames (default:off) */
+#define CAN_RAW_JOIN_FILTERS   (__SO_PROTOCOL + 5)     
+                                 /* all filters must match to trigger */
+#define CAN_RAW_TX_DEADLINE    (__SO_PROTOCOL + 6)
+                                 /* Abort frame when deadline passed */
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* Controller Area Network Identifier structure
+ *
+ *   Bit 0-28: CAN identifier (11/29 bit)
+ *   Bit 29:   Error message frame flag (0 = data frame, 1 = error message)
+ *   Bit 30:   Remote transmission request flag (1 = rtr frame)
+ *   Bit 31:   Frame format flag (0 = standard 11 bit, 1 = extended 29 bit)
+ */
+
+typedef uint32_t canid_t;
+
+/* The sockaddr structure for CAN sockets
+ *
+ *   can_family:  Address family number AF_CAN.
+ *   can_ifindex: CAN network interface index.
+ *   can_addr:    Protocol specific address information
+ */
+
+struct sockaddr_can
+{
+  sa_family_t can_family;
+  int16_t     can_ifindex;
+  union
+  {
+    /* Transport protocol class address information */
+
+    struct
+    {
+      canid_t rx_id;
+      canid_t tx_id;
+    } tp;
+
+    /* J1939 address information */
+
+    struct
+    {
+      /* 8 byte name when using dynamic addressing */
+
+      uint64_t name;
+
+      /* pgn:
+       *   8 bit: PS in PDU2 case, else 0
+       *   8 bit: PF
+       *   1 bit: DP
+       *   1 bit: reserved
+       */
+
+      uint32_t pgn;
+
+      /* 1 byte address */
+
+      uint8_t addr;
+    } j1939;
+  } can_addr;
+};
+
+#endif /* __INCLUDE_NETPACKET_CAN_H */
diff --git a/include/nuttx/can.h b/include/nuttx/can.h
new file mode 100644
index 0000000..c681b32
--- /dev/null
+++ b/include/nuttx/can.h
@@ -0,0 +1,319 @@
+/************************************************************************************
+ * include/nuttx/can/can.h
+ *
+ *   Copyright (C) 2008, 2009, 2011-2012, 2015-2017, 2019 Gregory Nutt. All rights
+ *     reserved.
+ *   Author: Gregory Nutt <gn...@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_CAN_CAN_H
+#define __INCLUDE_NUTTX_CAN_CAN_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#ifdef CONFIG_CAN_TXREADY
+#  include <nuttx/wqueue.h>
+#endif
+
+#include <queue.h>
+
+#ifdef CONFIG_NET_CAN
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Ioctl Commands *******************************************************************/
+
+/* Ioctl commands supported by the upper half CAN driver.
+ *
+ * CANIOC_RTR:
+ *   Description:  Send the remote transmission request and wait for the response.
+ *   Argument:     A reference to struct canioc_rtr_s
+ *
+ * Ioctl commands that may or may not be supported by the lower half CAN driver.
+ *
+ * CANIOC_ADD_STDFILTER:
+ *   Description:    Add an address filter for a standard 11 bit address.
+ *   Argument:       A reference to struct canioc_stdfilter_s
+ *   Returned Value: A non-negative filter ID is returned on success.
+ *                   Otherwise -1 (ERROR) is returned with the errno
+ *                   variable set to indicate the nature of the error.
+ *   Dependencies:   None
+ *
+ * CANIOC_ADD_EXTFILTER:
+ *   Description:    Add an address filter for a extended 29 bit address.
+ *   Argument:       A reference to struct canioc_extfilter_s
+ *   Returned Value: A non-negative filter ID is returned on success.
+ *                   Otherwise -1 (ERROR) is returned with the errno
+ *                   variable set to indicate the nature of the error.
+ *   Dependencies:   Requires CONFIG_CAN_EXTID=y
+ *
+ * CANIOC_DEL_STDFILTER:
+ *   Description:    Remove an address filter for a standard 11 bit address.
+ *   Argument:       The filter index previously returned by the
+ *                   CANIOC_ADD_STDFILTER command
+ *   Returned Value: Zero (OK) is returned on success.  Otherwise -1 (ERROR)
+ *                   is returned with the errno variable set to indicate the
+ *                   nature of the error.
+ *   Dependencies:   None
+ *
+ * CANIOC_DEL_EXTFILTER:
+ *   Description:    Remove an address filter for a standard 29 bit address.
+ *   Argument:       The filter index previously returned by the
+ *                   CANIOC_ADD_EXTFILTER command
+ *   Returned Value: Zero (OK) is returned on success.  Otherwise -1 (ERROR)
+ *                   is returned with the errno variable set to indicate the
+ *                   nature of the error.
+ *   Dependencies:   Requires CONFIG_CAN_EXTID=y
+ *
+ * CANIOC_GET_BITTIMING:
+ *   Description:    Return the current bit timing settings
+ *   Argument:       A pointer to a write-able instance of struct
+ *                   canioc_bittiming_s in which current bit timing values
+ *                   will be returned.
+ *   Returned Value: Zero (OK) is returned on success.  Otherwise -1 (ERROR)
+ *                   is returned with the errno variable set to indicate the
+ *                   nature of the error.
+ *   Dependencies:   None
+ *
+ * CANIOC_SET_BITTIMING:
+ *   Description:    Set new current bit timing values
+ *   Argument:       A pointer to a read-able instance of struct
+ *                   canioc_bittiming_s in which the new bit timing values
+ *                   are provided.
+ *   Returned Value: Zero (OK) is returned on success.  Otherwise -1 (ERROR)
+ *                   is returned with the errno variable set to indicate the
+ *                   nature of the error.
+ *   Dependencies:   None
+ *
+ * CANIOC_GET_CONNMODES:
+ *   Description:    Get the current bus connection modes
+ *   Argument:       A pointer to a write-able instance of struct
+ *                   canioc_connmodes_s in which the new bus modes will be returned.
+ *   Returned Value: Zero (OK) is returned on success.  Otherwise -1 (ERROR)
+ *                   is returned with the errno variable set to indicate the
+ *                   nature of the error.
+ *   Dependencies:   None
+ *
+ * CANIOC_SET_CONNMODES:
+ *   Description:    Set new bus connection modes values
+ *   Argument:       A pointer to a read-able instance of struct
+ *                   canioc_connmodes_s in which the new bus modes are provided.
+ *   Returned Value: Zero (OK) is returned on success.  Otherwise -1 (ERROR)
+ *                   is returned with the errno variable set to indicate the
+ *                   nature of the error.
+ *   Dependencies:   None
+ *
+ * CANIOC_BUSOFF_RECOVERY:
+ *   Description:    Initiates the BUS-OFF recovery sequence
+ *   Argument:       None
+ *   Returned Value: Zero (OK) is returned on success.  Otherwise -1 (ERROR)
+ *                   is returned with the errno variable set to indicate the
+ *                   nature of the error.
+ *   Dependencies:   None
+ */
+
+#define CANIOC_RTR                _CANIOC(1)
+#define CANIOC_GET_BITTIMING      _CANIOC(2)
+#define CANIOC_SET_BITTIMING      _CANIOC(3)
+#define CANIOC_ADD_STDFILTER      _CANIOC(4)
+#define CANIOC_ADD_EXTFILTER      _CANIOC(5)
+#define CANIOC_DEL_STDFILTER      _CANIOC(6)
+#define CANIOC_DEL_EXTFILTER      _CANIOC(7)
+#define CANIOC_GET_CONNMODES      _CANIOC(8)
+#define CANIOC_SET_CONNMODES      _CANIOC(9)
+#define CANIOC_BUSOFF_RECOVERY    _CANIOC(10)
+
+#define CAN_FIRST                 0x0001         /* First common command */
+#define CAN_NCMDS                 10             /* Ten common commands */
+
+/* User defined ioctl commands are also supported. These will be forwarded
+ * by the upper-half CAN driver to the lower-half CAN driver via the co_ioctl()
+ * method fo the CAN lower-half interface.  However, the lower-half driver
+ * must reserve a block of commands as follows in order prevent IOCTL
+ * command numbers from overlapping.
+ *
+ * This is generally done as follows.  The first reservation for CAN driver A would
+ * look like:
+ *
+ *   CAN_A_FIRST                 (CAN_FIRST + CAN_NCMDS)     <- First command
+ *   CAN_A_NCMDS                 42                          <- Number of commands
+ *
+ * IOCTL commands for CAN driver A would then be defined in a CAN A header file like:
+ *
+ *   CANIOC_A_CMD1               _CANIOC(CAN_A_FIRST+0)
+ *   CANIOC_A_CMD2               _CANIOC(CAN_A_FIRST+1)
+ *   CANIOC_A_CMD3               _CANIOC(CAN_A_FIRST+2)
+ *   ...
+ *   CANIOC_A_CMD42              _CANIOC(CAN_A_FIRST+41)
+ *
+ * The next reservation would look like:
+ *
+ *   CAN_B_FIRST                 (CAN_A_FIRST + CAN_A_NCMDS) <- Next command
+ *   CAN_B_NCMDS                 77                          <- Number of commands
+ */
+
+/* CAN payload length and DLC definitions according to ISO 11898-1 */
+
+#define CAN_MAX_DLC 8
+#define CAN_MAX_DLEN 8
+
+/* CAN FD payload length and DLC definitions according to ISO 11898-7 */
+
+#define CANFD_MAX_DLC 15
+#define CANFD_MAX_DLEN 64
+
+/* Defined bits for canfd_frame.flags
+ *
+ * The use of struct canfd_frame implies the Extended Data Length (EDL) bit to
+ * be set in the CAN frame bitstream on the wire. The EDL bit switch turns
+ * the CAN controllers bitstream processor into the CAN FD mode which creates
+ * two new options within the CAN FD frame specification:
+ *
+ * Bit Rate Switch - to indicate a second bitrate is/was used for the payload
+ * Error State Indicator - represents the error state of the transmitting node
+ *
+ * As the CANFD_ESI bit is internally generated by the transmitting CAN
+ * controller only the CANFD_BRS bit is relevant for real CAN controllers when
+ * building a CAN FD frame for transmission. Setting the CANFD_ESI bit can make
+ * sense for virtual CAN interfaces to test applications with echoed frames.
+ */
+
+#define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */
+#define CANFD_ESI 0x02 /* error state indicator of the transmitting node */
+
+#define CAN_INV_FILTER     0x20000000U /* to be set in can_filter.can_id */
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+typedef FAR void *CAN_HANDLE;
+
+struct can_response_s
+{
+  sq_entry_t flink;
+
+  /* Message-specific data may follow */
+}; /* FIXME remove */
+
+typedef uint32_t canid_t;
+
+/* Controller Area Network Error Message Frame Mask structure
+ *
+ * bit 0-28  : error class mask (see include/uapi/linux/can/error.h)
+ * bit 29-31 : set to zero
+ */
+
+typedef uint32_t can_err_mask_t;
+
+/* struct can_frame - basic CAN frame structure
+ * can_id:  CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition
+ * can_dlc: frame payload length in byte (0 .. 8) aka data length code
+ *          N.B. the DLC field from ISO 11898-1 Chapter 8.4.2.3 has a 1:1
+ *          mapping of the 'data length code' to the real payload length
+ * __pad:   padding
+ * __res0:  reserved / padding
+ * __res1:  reserved / padding
+ * data:    CAN frame payload (up to 8 byte)
+ */
+
+struct can_frame
+{
+  canid_t can_id;   /* 32 bit CAN_ID + EFF/RTR/ERR flags */
+  uint8_t  can_dlc; /* frame payload length in byte (0 .. CAN_MAX_DLEN) */
+  uint8_t  __pad;   /* padding */
+  uint8_t  __res0;  /* reserved / padding */
+  uint8_t  __res1;  /* reserved / padding */
+  uint8_t  data[CAN_MAX_DLEN] __attribute__((aligned(8)));
+};
+
+/* struct canfd_frame - CAN flexible data rate frame structure
+ * can_id: CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition
+ * len:    frame payload length in byte (0 .. CANFD_MAX_DLEN)
+ * flags:  additional flags for CAN FD
+ * __res0: reserved / padding
+ * __res1: reserved / padding
+ * data:   CAN FD frame payload (up to CANFD_MAX_DLEN byte)
+ */
+
+struct canfd_frame
+{
+  canid_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */
+  uint8_t len;     /* frame payload length in byte */
+  uint8_t flags;   /* additional flags for CAN FD */
+  uint8_t __res0;  /* reserved / padding */
+  uint8_t __res1;  /* reserved / padding */
+  uint8_t data[CANFD_MAX_DLEN] __attribute__((aligned(8)));
+};
+
+/* struct can_filter - CAN ID based filter in can_register().
+ * can_id:   relevant bits of CAN ID which are not masked out.
+ * can_mask: CAN mask (see description)
+ *
+ * Description:
+ * A filter matches, when
+ *
+ *   <received_can_id> & mask == can_id & mask
+ *
+ * The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can
+ * filter for error message frames (CAN_ERR_FLAG bit set in mask).
+ */
+
+struct can_filter
+{
+  canid_t can_id;
+  canid_t can_mask;
+};
+
+/************************************************************************************
+ * Public Function Prototypes
+ ************************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* CONFIG_CAN */
+#endif /* __INCLUDE_NUTTX_CAN_CAN_H */
diff --git a/include/nuttx/can/error.h b/include/nuttx/can/error.h
new file mode 100644
index 0000000..cf5fec6
--- /dev/null
+++ b/include/nuttx/can/error.h
@@ -0,0 +1,129 @@
+/* SPDX-License-Identifier: ((GPL-2.0-only WITH Linux-syscall-note) OR BSD-3-Clause) */
+
+/************************************************************************************
+ * linux/can/error.h
+ *
+ * Definitions of the CAN error messages to be filtered and passed to the
+ * user.
+ *
+ * Author: Oliver Hartkopp <ol...@volkswagen.de>
+ * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Volkswagen nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * Alternatively, provided that this notice is retained in full, this
+ * software may be distributed under the terms of the GNU General
+ * Public License ("GPL") version 2, in which case the provisions of the
+ * GPL apply INSTEAD OF those given above.
+ *
+ * The provided data structures and external interfaces from this code
+ * are not restricted to be used by modules with a GPL compatible license.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ ************************************************************************************/
+
+#ifndef _UAPI_CAN_ERROR_H
+#define _UAPI_CAN_ERROR_H
+
+#define CAN_ERR_DLC 8 /* dlc for error message frames */
+
+/* error class (mask) in can_id */
+#define CAN_ERR_TX_TIMEOUT   0x00000001U /* TX timeout (by netdevice driver) */
+#define CAN_ERR_LOSTARB      0x00000002U /* lost arbitration    / data[0]    */
+#define CAN_ERR_CRTL         0x00000004U /* controller problems / data[1]    */
+#define CAN_ERR_PROT         0x00000008U /* protocol violations / data[2..3] */
+#define CAN_ERR_TRX          0x00000010U /* transceiver status  / data[4]    */
+#define CAN_ERR_ACK          0x00000020U /* received no ACK on transmission */
+#define CAN_ERR_BUSOFF       0x00000040U /* bus off */
+#define CAN_ERR_BUSERROR     0x00000080U /* bus error (may flood!) */
+#define CAN_ERR_RESTARTED    0x00000100U /* controller restarted */
+
+/* arbitration lost in bit ... / data[0] */
+#define CAN_ERR_LOSTARB_UNSPEC   0x00 /* unspecified */
+
+/* else bit number in bitstream */
+
+/* error status of CAN-controller / data[1] */
+#define CAN_ERR_CRTL_UNSPEC      0x00 /* unspecified */
+#define CAN_ERR_CRTL_RX_OVERFLOW 0x01 /* RX buffer overflow */
+#define CAN_ERR_CRTL_TX_OVERFLOW 0x02 /* TX buffer overflow */
+#define CAN_ERR_CRTL_RX_WARNING  0x04 /* reached warning level for RX errors */
+#define CAN_ERR_CRTL_TX_WARNING  0x08 /* reached warning level for TX errors */
+#define CAN_ERR_CRTL_RX_PASSIVE  0x10 /* reached error passive status RX */
+#define CAN_ERR_CRTL_TX_PASSIVE  0x20 /* reached error passive status TX */
+                                      /* (at least one error counter exceeds */
+                                      /* the protocol-defined level of 127)  */
+#define CAN_ERR_CRTL_ACTIVE      0x40 /* recovered to error active state */
+
+/* error in CAN protocol (type) / data[2] */
+#define CAN_ERR_PROT_UNSPEC      0x00 /* unspecified */
+#define CAN_ERR_PROT_BIT         0x01 /* single bit error */
+#define CAN_ERR_PROT_FORM        0x02 /* frame format error */
+#define CAN_ERR_PROT_STUFF       0x04 /* bit stuffing error */
+#define CAN_ERR_PROT_BIT0        0x08 /* unable to send dominant bit */
+#define CAN_ERR_PROT_BIT1        0x10 /* unable to send recessive bit */
+#define CAN_ERR_PROT_OVERLOAD    0x20 /* bus overload */
+#define CAN_ERR_PROT_ACTIVE      0x40 /* active error announcement */
+#define CAN_ERR_PROT_TX          0x80 /* error occurred on transmission */
+
+/* error in CAN protocol (location) / data[3] */
+#define CAN_ERR_PROT_LOC_UNSPEC  0x00 /* unspecified */
+#define CAN_ERR_PROT_LOC_SOF     0x03 /* start of frame */
+#define CAN_ERR_PROT_LOC_ID28_21 0x02 /* ID bits 28 - 21 (SFF: 10 - 3) */
+#define CAN_ERR_PROT_LOC_ID20_18 0x06 /* ID bits 20 - 18 (SFF: 2 - 0 )*/
+#define CAN_ERR_PROT_LOC_SRTR    0x04 /* substitute RTR (SFF: RTR) */
+#define CAN_ERR_PROT_LOC_IDE     0x05 /* identifier extension */
+#define CAN_ERR_PROT_LOC_ID17_13 0x07 /* ID bits 17-13 */
+#define CAN_ERR_PROT_LOC_ID12_05 0x0f /* ID bits 12-5 */
+#define CAN_ERR_PROT_LOC_ID04_00 0x0e /* ID bits 4-0 */
+#define CAN_ERR_PROT_LOC_RTR     0x0c /* RTR */
+#define CAN_ERR_PROT_LOC_RES1    0x0d /* reserved bit 1 */
+#define CAN_ERR_PROT_LOC_RES0    0x09 /* reserved bit 0 */
+#define CAN_ERR_PROT_LOC_DLC     0x0b /* data length code */
+#define CAN_ERR_PROT_LOC_DATA    0x0a /* data section */
+#define CAN_ERR_PROT_LOC_CRC_SEQ 0x08 /* CRC sequence */
+#define CAN_ERR_PROT_LOC_CRC_DEL 0x18 /* CRC delimiter */
+#define CAN_ERR_PROT_LOC_ACK     0x19 /* ACK slot */
+#define CAN_ERR_PROT_LOC_ACK_DEL 0x1b /* ACK delimiter */
+#define CAN_ERR_PROT_LOC_EOF     0x1a /* end of frame */
+#define CAN_ERR_PROT_LOC_INTERM  0x12 /* intermission */
+
+/* error status of CAN-transceiver / data[4] */
+
+                                            /* CANH CANL */
+#define CAN_ERR_TRX_UNSPEC             0x00 /* 0000 0000 */
+#define CAN_ERR_TRX_CANH_NO_WIRE       0x04 /* 0000 0100 */
+#define CAN_ERR_TRX_CANH_SHORT_TO_BAT  0x05 /* 0000 0101 */
+#define CAN_ERR_TRX_CANH_SHORT_TO_VCC  0x06 /* 0000 0110 */
+#define CAN_ERR_TRX_CANH_SHORT_TO_GND  0x07 /* 0000 0111 */
+#define CAN_ERR_TRX_CANL_NO_WIRE       0x40 /* 0100 0000 */
+#define CAN_ERR_TRX_CANL_SHORT_TO_BAT  0x50 /* 0101 0000 */
+#define CAN_ERR_TRX_CANL_SHORT_TO_VCC  0x60 /* 0110 0000 */
+#define CAN_ERR_TRX_CANL_SHORT_TO_GND  0x70 /* 0111 0000 */
+#define CAN_ERR_TRX_CANL_SHORT_TO_CANH 0x80 /* 1000 0000 */
+
+/* controller specific additional information / data[5..7] */
+
+#endif /* _UAPI_CAN_ERROR_H */
diff --git a/include/nuttx/mm/iob.h b/include/nuttx/mm/iob.h
index 8984af6..32c0bfd 100644
--- a/include/nuttx/mm/iob.h
+++ b/include/nuttx/mm/iob.h
@@ -54,6 +54,7 @@
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
+
 /* Configuration ************************************************************/
 
 /* I/O buffer allocation logic supports a throttle value for read-ahead
@@ -220,6 +221,9 @@ enum iob_user_e
 #ifdef CONFIG_WIRELESS_BLUETOOTH
   IOBUSER_WIRELESS_BLUETOOTH,
 #endif
+#ifdef CONFIG_NET_CAN
+  IOBUSER_NET_CAN_READAHEAD,
+#endif
   IOBUSER_GLOBAL,
   IOBUSER_NENTRIES /* MUST BE LAST ENTRY */
 };
@@ -248,7 +252,8 @@ void iob_initialize(void);
  * Name: iob_alloc
  *
  * Description:
- *   Allocate an I/O buffer by taking the buffer at the head of the free list.
+ *   Allocate an I/O buffer by taking the buffer at the head of the free
+ *   list.
  *
  ****************************************************************************/
 
@@ -586,7 +591,8 @@ void iob_dump(FAR const char *msg, FAR struct iob_s *iob, unsigned int len,
  * Name: iob_getuserstats
  *
  * Description:
- *   Return a reference to the IOB usage statistics for the IOB consumer/producer
+ *   Return a reference to the IOB usage statistics for the IOB
+ *   consumer/producer
  *
  * Input Parameters:
  *   userid - id representing the IOB producer/consumer
diff --git a/include/nuttx/net/can.h b/include/nuttx/net/can.h
new file mode 100644
index 0000000..f9cbe93
--- /dev/null
+++ b/include/nuttx/net/can.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+ * include/nuttx/net/can.h
+ * Macros and definitions for the CAN link layer.
+ *
+ *   Copyright (C) 2007, 2009-2012, 2015 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <gn...@nuttx.org>
+ *
+ * Derived from uIP with has a similar BSD-styple license:
+ *
+ *   Author: Adam Dunkels <ad...@dunkels.com>
+ *   Copyright (c) 2001-2003, Adam Dunkels.
+ *   All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_NET_CAN_H
+#define __INCLUDE_NUTTX_NET_CAN_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/can.h>
+#include <stdint.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+#ifdef CONFIG_NET_CAN_CANFD
+#define NET_CAN_PKTSIZE sizeof(struct canfd_frame)
+#else
+#define NET_CAN_PKTSIZE sizeof(struct can_frame)
+#endif
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_CAN_CANFD
+
+/* Lookup tables convert can_dlc <-> payload len */
+
+extern const uint8_t can_dlc_to_len[16];
+extern const uint8_t len_to_can_dlc[65];
+
+#endif
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: can_input
+ *
+ * Description:
+ *   Handle incoming CAN frame input
+ *
+ *   This function provides the interface between CAN device drivers and
+ *   SocketCAN logic.  All frames that are received should be provided to
+ *   can_input() prior to other routing.
+ *
+ * Input Parameters:
+ *   dev - The device driver structure containing the received packet
+ *
+ * Returned Value:
+ *   OK    The packet has been processed  and can be deleted
+ *   ERROR There is a matching connection, but could not dispatch the packet
+ *         yet.  Useful when a packet arrives before a recv call is in
+ *         place.
+ *
+ * Assumptions:
+ *   Called from the CAN device diver with the network locked.
+ *
+ ****************************************************************************/
+
+struct net_driver_s; /* Forward reference */
+int can_input(FAR struct net_driver_s *dev);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_NUTTX_NET_CAN_H */
diff --git a/include/nuttx/net/ioctl.h b/include/nuttx/net/ioctl.h
index 4717542..6f2f20e 100644
--- a/include/nuttx/net/ioctl.h
+++ b/include/nuttx/net/ioctl.h
@@ -85,6 +85,9 @@
 #define SIOCGIFCONF      _SIOC(0x0018)  /* Return an interface list (IPv4) */
 #define SIOCGLIFCONF     _SIOC(0x0019)  /* Return an interface list (IPv6) */
 
+#define SIOCGIFNAME      _SIOC(0x002A)  /* Get interface name string */
+#define SIOCGIFINDEX     _SIOC(0x002B)  /* Get index based name string */
+
 /* Interface flags */
 
 #define SIOCSIFFLAGS     _SIOC(0x001a)  /* Sets the interface flags */
@@ -122,6 +125,11 @@
 #define SIOCTELNET       _SIOC(0x0029)  /* Create a Telnet sessions.
                                          * See include/nuttx/net/telnet.h */
 
+/* SocketCAN ****************************************************************/
+
+#define SIOCGCANBITRATE  _SIOC(0x002C)  /* Get bitrate from a CAN controller */
+#define SIOCSCANBITRATE  _SIOC(0x002D)  /* Set bitrate of a CAN controller */
+
 /****************************************************************************
  * Public Type Definitions
  ****************************************************************************/
diff --git a/include/nuttx/net/net.h b/include/nuttx/net/net.h
index c2cbb93..836edbf 100644
--- a/include/nuttx/net/net.h
+++ b/include/nuttx/net/net.h
@@ -156,7 +156,8 @@ enum net_lltype_e
   NET_LL_IEEE80211,    /* IEEE 802.11 */
   NET_LL_IEEE802154,   /* IEEE 802.15.4 MAC */
   NET_LL_PKTRADIO,     /* Non-standard packet radio */
-  NET_LL_MBIM          /* CDC-MBIM USB host driver */
+  NET_LL_MBIM,         /* CDC-MBIM USB host driver */
+  NET_LL_CAN           /* CAN bus */
 };
 
 /* This defines a bitmap big enough for one bit for each socket option */
@@ -215,6 +216,12 @@ struct sock_intf_s
   CODE ssize_t    (*si_recvfrom)(FAR struct socket *psock, FAR void *buf,
                     size_t len, int flags, FAR struct sockaddr *from,
                     FAR socklen_t *fromlen);
+#ifdef CONFIG_NET_CMSG
+  CODE ssize_t    (*si_recvmsg)(FAR struct socket *psock,
+    FAR struct msghdr *msg, int flags);
+  CODE ssize_t    (*si_sendmsg)(FAR struct socket *psock,
+    FAR struct msghdr *msg, int flags);
+#endif
   CODE int        (*si_close)(FAR struct socket *psock);
 #ifdef CONFIG_NET_USRSOCK
   CODE int        (*si_ioctl)(FAR struct socket *psock, int cmd,
@@ -271,6 +278,9 @@ struct socket
 #ifdef CONFIG_NET_SOLINGER
   socktimeo_t   s_linger;    /* Linger timeout value (in deciseconds) */
 #endif
+#ifdef CONFIG_NET_TIMESTAMP
+  int32_t       s_timestamp; /* Socket timestamp enabled/disabled */
+#endif
 #endif
 
   FAR void     *s_conn;      /* Connection inherits from struct socket_conn_s */
@@ -371,6 +381,25 @@ void net_initialize(void);
 int net_lock(void);
 
 /****************************************************************************
+ * Name: net_trylock
+ *
+ * Description:
+ *   Try to take the network lock only when it is currently not locked.
+ *   Otherwise, it locks the semaphore.  In either
+ *   case, the call returns without blocking.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success; a negated errno value is returned on
+ *   failured (probably -EAGAIN).
+ *
+ ****************************************************************************/
+
+int net_trylock(void);
+
+/****************************************************************************
  * Name: net_unlock
  *
  * Description:
diff --git a/include/nuttx/wqueue.h b/include/nuttx/wqueue.h
index d353772..ea7563c 100644
--- a/include/nuttx/wqueue.h
+++ b/include/nuttx/wqueue.h
@@ -280,7 +280,8 @@ enum work_evtype_e
   WORK_TCP_DISCONNECT,   /* Notify loss of TCP connection */
   WORK_UDP_READAHEAD,    /* Notify that UDP read-ahead data is available */
   WORK_UDP_WRITEBUFFER,  /* Notify that UDP write buffer is empty */
-  WORK_NETLINK_RESPONSE  /* Notify that Netlink response is available */
+  WORK_NETLINK_RESPONSE, /* Notify that Netlink response is available */
+  WORK_CAN_READAHEAD     /* Notify that CAN read-ahead data is available */
 };
 
 /* This structure describes one notification and is provided as input to
diff --git a/include/sys/socket.h b/include/sys/socket.h
index b940126..e8eca51 100644
--- a/include/sys/socket.h
+++ b/include/sys/socket.h
@@ -62,6 +62,7 @@
 #define PF_NETLINK    16         /* Netlink IPC socket */
 #define PF_ROUTE      PF_NETLINK /* 4.4BSD Compatibility*/
 #define PF_PACKET     17         /* Low level packet interface */
+#define PF_CAN        29         /* Controller Area Network (SocketCAN) */
 #define PF_BLUETOOTH  31         /* Bluetooth sockets */
 #define PF_IEEE802154 36         /* Low level IEEE 802.15.4 radio frame interface */
 #define PF_PKTRADIO   64         /* Low level packet radio interface */
@@ -78,6 +79,7 @@
 #define AF_NETLINK     PF_NETLINK
 #define AF_ROUTE       PF_ROUTE
 #define AF_PACKET      PF_PACKET
+#define AF_CAN         PF_CAN
 #define AF_BLUETOOTH   PF_BLUETOOTH
 #define AF_IEEE802154  PF_IEEE802154
 #define AF_PKTRADIO    PF_PKTRADIO
@@ -199,6 +201,16 @@
 #define SO_TYPE         15 /* Reports the socket type (get only).
                             * return: int
                             */
+#define SO_TIMESTAMP    16 /* Generates a timestamp for each incoming packet
+                            * arg: integer value
+                            */
+
+/* The options are unsupported but included for compatibility
+ * and portability
+ */
+#define SO_SNDBUFFORCE  32
+#define SO_RCVBUFFORCE  33
+#define SO_RXQ_OVFL     40
 
 /* Protocol-level socket operations. */
 
@@ -210,6 +222,7 @@
 #define SOL_L2CAP       6 /* See options in include/netpacket/bluetooth.h */
 #define SOL_SCO         7 /* See options in include/netpacket/bluetooth.h */
 #define SOL_RFCOMM      8 /* See options in include/netpacket/bluetooth.h */
+#define SOL_CAN_RAW     9 /* See options in include/netpacket/can.h */
 
 /* Protocol-level socket options may begin with this value */
 
diff --git a/libs/libc/net/lib_recvmsg.c b/libs/libc/net/lib_recvmsg.c
index 984a16f..071c189 100644
--- a/libs/libc/net/lib_recvmsg.c
+++ b/libs/libc/net/lib_recvmsg.c
@@ -39,7 +39,7 @@
 
 #include <nuttx/config.h>
 
-#ifdef CONFIG_NET
+#if defined(CONFIG_NET) && !defined(CONFIG_NET_CMSG)
 
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -53,7 +53,8 @@
  * Function: recvmsg
  *
  * Description:
- *   The recvmsg() call is identical to recvfrom() with a NULL from parameter.
+ *   The recvmsg() call is identical to recvfrom() with a NULL from
+ *   parameter.
  *
  * Parameters:
  *   sockfd   Socket descriptor of socket
@@ -86,4 +87,4 @@ ssize_t recvmsg(int sockfd, FAR struct msghdr *msg, int flags)
     }
 }
 
-#endif /* CONFIG_NET */
+#endif /* CONFIG_NET && !CONFIG_NET_CMSG */
diff --git a/libs/libc/net/lib_sendmsg.c b/libs/libc/net/lib_sendmsg.c
index 0d09faa..9f98e51 100644
--- a/libs/libc/net/lib_sendmsg.c
+++ b/libs/libc/net/lib_sendmsg.c
@@ -39,7 +39,7 @@
 
 #include <nuttx/config.h>
 
-#ifdef CONFIG_NET
+#if defined(CONFIG_NET) && !defined(CONFIG_NET_CMSG)
 
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -86,4 +86,4 @@ ssize_t sendmsg(int sockfd, FAR struct msghdr *msg, int flags)
     }
 }
 
-#endif /* CONFIG_NET */
+#endif /* CONFIG_NET && !CONFIG_NET_CMSG */
diff --git a/net/Kconfig b/net/Kconfig
index bedf933..80fe919 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -349,6 +349,7 @@ source "net/socket/Kconfig"
 source "net/inet/Kconfig"
 source "net/pkt/Kconfig"
 source "net/local/Kconfig"
+source "net/can/Kconfig"
 source "net/netlink/Kconfig"
 source "net/tcp/Kconfig"
 source "net/udp/Kconfig"
diff --git a/net/Makefile b/net/Makefile
index 077d035..f8ffe85 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -52,6 +52,7 @@ include igmp/Make.defs
 include pkt/Make.defs
 include local/Make.defs
 include mld/Make.defs
+include can/Make.defs
 include netlink/Make.defs
 include tcp/Make.defs
 include udp/Make.defs
diff --git a/net/bluetooth/bluetooth_sockif.c b/net/bluetooth/bluetooth_sockif.c
index 41bcafa..4057d93 100644
--- a/net/bluetooth/bluetooth_sockif.c
+++ b/net/bluetooth/bluetooth_sockif.c
@@ -106,9 +106,13 @@ const struct sock_intf_s g_bluetooth_sockif =
   bluetooth_send,        /* si_send */
   bluetooth_sendto,      /* si_sendto */
 #ifdef CONFIG_NET_SENDFILE
-  NULL,                   /* si_sendfile */
+  NULL,                  /* si_sendfile */
 #endif
   bluetooth_recvfrom,    /* si_recvfrom */
+#ifdef CONFIG_NET_CMSG
+  NULL,                  /* si_recvmsg */
+  NULL,                  /* si_sendmsg */
+#endif
   bluetooth_close        /* si_close */
 };
 
@@ -243,10 +247,10 @@ static void bluetooth_addref(FAR struct socket *psock)
  * Name: bluetooth_connect
  *
  * Description:
- *   bluetooth_connect() connects the local socket referred to by the structure
- *   'psock' to the address specified by 'addr'. The addrlen argument
- *   specifies the size of 'addr'.  The format of the address in 'addr' is
- *   determined by the address space of the socket 'psock'.
+ *   bluetooth_connect() connects the local socket referred to by the
+ *   structure 'psock' to the address specified by 'addr'. The addrlen
+ *   argument specifies the size of 'addr'.  The format of the address in
+ *   'addr' is determined by the address space of the socket 'psock'.
  *
  *   Generally, connection-based protocol sockets may successfully
  *   bluetooth_connect() only once; connectionless protocol sockets may use
@@ -330,7 +334,8 @@ static int bluetooth_connect(FAR struct socket *psock,
  * Input Parameters:
  *   psock    Reference to the listening socket structure
  *   addr     Receives the address of the connecting client
- *   addrlen  Input: allocated size of 'addr', Return: returned size of 'addr'
+ *   addrlen  Input: allocated size of 'addr',
+ *            Return: returned size of 'addr'
  *   newsock  Location to return the accepted socket information.
  *
  * Returned Value:
@@ -372,7 +377,7 @@ static int bluetooth_accept(FAR struct socket *psock,
  ****************************************************************************/
 
 static int bluetooth_bind(FAR struct socket *psock,
-                           FAR const struct sockaddr *addr, socklen_t addrlen)
+                          FAR const struct sockaddr *addr, socklen_t addrlen)
 {
   FAR const struct sockaddr_bt_s *iaddr;
   FAR struct radio_driver_s *radio;
@@ -439,10 +444,10 @@ static int bluetooth_bind(FAR struct socket *psock,
  * Name: bluetooth_getsockname
  *
  * Description:
- *   The bluetooth_getsockname() function retrieves the locally-bound name of the
- *   specified packet socket, stores this address in the sockaddr structure
- *   pointed to by the 'addr' argument, and stores the length of this
- *   address in the object pointed to by the 'addrlen' argument.
+ *   The bluetooth_getsockname() function retrieves the locally-bound name of
+ *   the specified packet socket, stores this address in the sockaddr
+ *   structure pointed to by the 'addr' argument, and stores the length of
+ *   this address in the object pointed to by the 'addrlen' argument.
  *
  *   If the actual length of the address is greater than the length of the
  *   supplied sockaddr structure, the stored address will be truncated.
@@ -501,8 +506,8 @@ static int bluetooth_getsockname(FAR struct socket *psock,
  * Name: bluetooth_getpeername
  *
  * Description:
- *   The bluetooth_getpeername() function retrieves the remote-connected name of
- *   the specified local socket, stores this address in the sockaddr
+ *   The bluetooth_getpeername() function retrieves the remote-connected name
+ *   of the specified local socket, stores this address in the sockaddr
  *   structure pointed to by the 'addr' argument, and stores the length of
  *   this address in the object pointed to by the 'addrlen' argument.
  *
@@ -705,9 +710,10 @@ static ssize_t bluetooth_send(FAR struct socket *psock, FAR const void *buf,
  *
  ****************************************************************************/
 
-static ssize_t bluetooth_sendto(FAR struct socket *psock, FAR const void *buf,
-                                 size_t len, int flags,
-                                 FAR const struct sockaddr *to, socklen_t tolen)
+static ssize_t bluetooth_sendto(FAR struct socket *psock,
+                                FAR const void *buf, size_t len, int flags,
+                                FAR const struct sockaddr *to,
+                                socklen_t tolen)
 {
   ssize_t ret;
 
diff --git a/net/can/Kconfig b/net/can/Kconfig
new file mode 100644
index 0000000..e84c99d
--- /dev/null
+++ b/net/can/Kconfig
@@ -0,0 +1,97 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+menu "SocketCAN Support"
+
+config NET_CAN
+	bool "SocketCAN support"
+	default n
+	select NET_READAHEAD
+	depends on NET
+	---help---
+		Enable support for SocketCAN sockets that will permit.
+
+		This logic is a WIP.  Currently only fragmentary support is
+		available, not enough to actually do anything of consequence.
+
+if NET_CAN
+
+config NET_CAN_HAVE_TX_DEADLINE
+	bool
+	default n
+	
+config NET_CAN_HAVE_CANFD
+	bool
+	default n
+
+config CAN_CONNS
+	int "Number of CAN connections"
+	default 4
+	---help---
+		Maximum number of CAN connections (all tasks).
+		
+config NET_CAN_CANFD
+	bool "Enable CAN FD support"
+	default y
+	depends on NET_CAN_HAVE_CANFD
+	---help---
+		Enable CAN FD support in SocketCAN stack
+		
+config NET_CAN_SOCK_OPTS
+	bool "sockopt support"
+	default n
+	select NET_SOCKOPTS
+	select NET_CANPROTO_OPTIONS
+	---help---
+		Enable support for the CAN socket options
+				
+config NET_CAN_RAW_TX_DEADLINE
+	bool "TX deadline sockopt"
+	default n
+	depends on NET_CAN_SOCK_OPTS && NET_CAN_HAVE_TX_DEADLINE
+	select NET_CMSG
+	---help---
+	    Note: Non-standard SocketCAN sockopt, but this options helps us in
+	    real-time use cases.
+	    
+		When the CAN_RAW_TX_DEADLINE sockopt is enabled. The user can send 
+		CAN frames using sendmsg() function and add a deadline timespec 
+		value in the CMSG data. When the deadline has been passed and the
+		CAN frame is still in the HW TX mailbox then the CAN driver will 
+		discard the CAN frame automatically.
+		
+config NET_CAN_RAW_DEFAULT_TX_DEADLINE
+	int "Default TX deadline when no deadline is given (us)"
+	default 0
+	depends on NET_CAN_RAW_TX_DEADLINE
+	---help---
+		Some applications may not use the NET_CAN_RAW_TX_DEADLINE flag.
+		By default their deadline becomes 0 which means it becomes infinite.
+		This would mean that packets from applications without the 
+		NET_CAN_RAW_TX_DEADLINE flag, can block the TX mailboxes forever.
+		This config can set the default deadline when no deadline has been 
+		given.
+		
+config NET_CAN_RAW_FILTER_MAX
+	int "CAN_RAW_FILTER max filter count"
+	default 32
+	depends on NET_CAN_SOCK_OPTS
+	---help---
+		Maximum number of CAN_RAW filters that can be set per CAN connection.
+		
+config NET_CAN_NOTIFIER
+	bool "Support CAN notifications"
+	default n
+	depends on SCHED_WORKQUEUE
+	select WQUEUE_NOTIFIER
+	---help---
+		Enable building of CAN notifier logic that will execute a worker
+		function on the low priority work queue when read-ahead data
+		is available or when a CAN connection is lost.  This is is a general
+		purpose notifier, but was developed specifically to support poll()
+		logic where the poll must wait for these events.
+
+endif # NET_CAN
+endmenu # CAN Socket Support
diff --git a/net/can/Make.defs b/net/can/Make.defs
new file mode 100644
index 0000000..3204b3b
--- /dev/null
+++ b/net/can/Make.defs
@@ -0,0 +1,48 @@
+############################################################################
+# net/can/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+# Logic specific to SocketCAN socket support
+
+ifeq ($(CONFIG_NET_CAN),y)
+
+# Socket layer
+
+SOCK_CSRCS += can_sockif.c
+SOCK_CSRCS += can_send.c
+SOCK_CSRCS += can_recvfrom.c
+
+ifeq ($(CONFIG_NET_CAN_NOTIFIER),y)
+SOCK_CSRCS += can_notifier.c
+endif
+
+ifeq ($(CONFIG_NET_CANPROTO_OPTIONS),y)
+SOCK_CSRCS += can_setsockopt.c can_getsockopt.c
+endif
+
+NET_CSRCS += can_conn.c
+NET_CSRCS += can_input.c
+NET_CSRCS += can_callback.c
+NET_CSRCS += can_poll.c
+
+# Include can build support
+
+DEPPATH += --dep-path can
+VPATH += :can
+endif # CONFIG_NET_CAN
diff --git a/net/can/can.h b/net/can/can.h
new file mode 100644
index 0000000..cae3eb4
--- /dev/null
+++ b/net/can/can.h
@@ -0,0 +1,385 @@
+/****************************************************************************
+ * net/can/can.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __NET_CAN_CAN_H
+#define __NET_CAN_CAN_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <poll.h>
+
+#include <netpacket/can.h>
+#include <nuttx/semaphore.h>
+#include <nuttx/can.h>
+#include <nuttx/net/netdev.h>
+
+#include "devif/devif.h"
+#include "socket/socket.h"
+
+#ifdef CONFIG_NET_CAN_NOTIFIER
+#  include <nuttx/wqueue.h>
+#endif
+
+#ifdef CONFIG_NET_CAN
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Allocate a new packet socket data callback */
+
+#define can_callback_alloc(dev,conn) \
+  devif_callback_alloc(dev, &conn->list)
+#define can_callback_free(dev,conn,cb) \
+  devif_conn_callback_free(dev, cb, &conn->list)
+
+/****************************************************************************
+ * Public Type Definitions
+ ****************************************************************************/
+
+/* This is a container that holds the poll-related information */
+
+struct can_poll_s
+{
+  FAR struct socket *psock;        /* Needed to handle loss of connection */
+  FAR struct net_driver_s *dev;    /* Needed to free the callback structure */
+  struct pollfd *fds;              /* Needed to handle poll events */
+  FAR struct devif_callback_s *cb; /* Needed to teardown the poll */
+};
+
+/* This "connection" structure describes the underlying state of the socket */
+
+struct can_conn_s
+{
+  /* Common prologue of all connection structures. */
+
+  dq_entry_t node;                   /* Supports a doubly linked list */
+
+  /* This is a list of NetLink connection callbacks.  Each callback
+   * represents a thread that is stalled, waiting for a device-specific
+   * event.
+   */
+
+  FAR struct devif_callback_s *list; /* NetLink callbacks */
+
+  FAR struct net_driver_s *dev;      /* Reference to CAN device */
+
+  /* Read-ahead buffering.
+   *
+   *   readahead - A singly linked list of type struct iob_qentry_s
+   *               where the CAN/IP read-ahead data is retained.
+   */
+
+  struct iob_queue_s readahead;      /* remove Read-ahead buffering */
+
+  /* CAN-specific content follows */
+
+  uint8_t protocol;                  /* Selected CAN protocol */
+  int16_t crefs;                     /* Reference count */
+
+  /* The following is a list of poll structures of threads waiting for
+   * socket events.
+   */
+
+  struct can_poll_s pollinfo[4]; /* FIXME make dynamic */
+
+#ifdef CONFIG_NET_CANPROTO_OPTIONS
+  int32_t loopback;
+  int32_t recv_own_msgs;
+#ifdef CONFIG_NET_CAN_CANFD
+  int32_t fd_frames;
+#endif
+  struct can_filter filters[CONFIG_NET_CAN_RAW_FILTER_MAX];
+  int32_t filter_count;
+# ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE
+  int32_t tx_deadline;
+# endif
+#endif
+
+#ifdef CONFIG_NET_TIMESTAMP
+  FAR struct socket *psock; /* Needed to get SO_TIMESTAMP value */
+#endif
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#  define EXTERN extern "C"
+extern "C"
+{
+#else
+#  define EXTERN extern
+#endif
+
+EXTERN const struct sock_intf_s g_can_sockif;
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+struct sockaddr_can;  /* Forward reference */
+
+/****************************************************************************
+ * Name: can_initialize()
+ *
+ * Description:
+ *   Initialize the NetLink connection structures.  Called once and only
+ *   from the networking layer.
+ *
+ ****************************************************************************/
+
+void can_initialize(void);
+
+/****************************************************************************
+ * Name: can_alloc()
+ *
+ * Description:
+ *   Allocate a new, uninitialized NetLink connection structure.  This is
+ *   normally something done by the implementation of the socket() API
+ *
+ ****************************************************************************/
+
+FAR struct can_conn_s *can_alloc(void);
+
+/****************************************************************************
+ * Name: can_free()
+ *
+ * Description:
+ *   Free a NetLink connection structure that is no longer in use. This
+ *   should be done by the implementation of close().
+ *
+ ****************************************************************************/
+
+void can_free(FAR struct can_conn_s *conn);
+
+/****************************************************************************
+ * Name: can_nextconn()
+ *
+ * Description:
+ *   Traverse the list of allocated NetLink connections
+ *
+ * Assumptions:
+ *   This function is called from NetLink device logic.
+ *
+ ****************************************************************************/
+
+FAR struct can_conn_s *can_nextconn(FAR struct can_conn_s *conn);
+
+/****************************************************************************
+ * Name: can_callback
+ *
+ * Description:
+ *   Inform the application holding the packet socket of a change in state.
+ *
+ * Returned Value:
+ *   OK if packet has been processed, otherwise ERROR.
+ *
+ * Assumptions:
+ *   This function is called from network logic at with the network locked.
+ *
+ ****************************************************************************/
+
+uint16_t can_callback(FAR struct net_driver_s *dev,
+                      FAR struct can_conn_s *conn, uint16_t flags);
+
+/****************************************************************************
+ * Name: can_datahandler
+ *
+ * Description:
+ *   Handle data that is not accepted by the application.  This may be called
+ *   either (1) from the data receive logic if it cannot buffer the data, or
+ *   (2) from the CAN event logic is there is no listener in place ready to
+ *   receive the data.
+ *
+ * Input Parameters:
+ *   conn - A pointer to the CAN connection structure
+ *   buffer - A pointer to the buffer to be copied to the read-ahead
+ *     buffers
+ *   buflen - The number of bytes to copy to the read-ahead buffer.
+ *
+ * Returned Value:
+ *   The number of bytes actually buffered is returned.  This will be either
+ *   zero or equal to buflen; partial packets are not buffered.
+ *
+ * Assumptions:
+ * - The caller has checked that CAN_NEWDATA is set in flags and that is no
+ *   other handler available to process the incoming data.
+ * - Called from network stack logic with the network stack locked
+ *
+ ****************************************************************************/
+
+uint16_t can_datahandler(FAR struct can_conn_s *conn, FAR uint8_t *buffer,
+                         uint16_t buflen);
+
+/****************************************************************************
+ * Name: can_recvfrom
+ *
+ * Description:
+ *   Implements the socket recvfrom interface pkt_recvfrom() receives
+ *   messages from a socket, and may be used to receive data on a socket
+ *   whether or not it is connection-oriented.
+ *
+ * Input Parameters:
+ *   psock    A pointer to a NuttX-specific, internal socket structure
+ *   buf      Buffer to receive data
+ *   len      Length of buffer
+ *   flags    Receive flags
+ *   from     Address of source (may be NULL)
+ *   fromlen  The length of the address structure
+ *
+ * Returned Value:
+ *   On success, returns the number of characters received.  If no data is
+ *   available to be received and the peer has performed an orderly shutdown,
+ *   recv() will return 0.  Otherwise, on errors, a negated errno value is
+ *   returned (see recvfrom() for the list of appropriate error values).
+ *
+ ****************************************************************************/
+
+ssize_t can_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
+                     int flags, FAR struct sockaddr *from,
+                     FAR socklen_t *fromlen);
+
+/****************************************************************************
+ * Name: can_recvmsg
+ *
+ * Description:
+ *   recvmsg() receives messages from a socket, and may be used to receive
+ *   data on a socket whether or not it is connection-oriented.
+ *
+ *   If from is not NULL, and the underlying protocol provides the source
+ *   address, this source address is filled in. The argument 'fromlen'
+ *   initialized to the size of the buffer associated with from, and modified
+ *   on return to indicate the actual size of the address stored there.
+ *
+ * Input Parameters:
+ *   psock    A pointer to a NuttX-specific, internal socket structure
+ *   msg      Buffer to receive msg
+ *   flags    Receive flags (ignored)
+ *
+ ****************************************************************************/
+#ifdef CONFIG_NET_CMSG
+ssize_t can_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
+                    int flags);
+#endif
+
+/****************************************************************************
+ * Name: can_poll
+ *
+ * Description:
+ *   Poll a CAN connection structure for availability of TX data
+ *
+ * Input Parameters:
+ *   dev - The device driver structure to use in the send operation
+ *   conn - The CAN "connection" to poll for TX data
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Called from network stack logic with the network stack locked
+ *
+ ****************************************************************************/
+
+void can_poll(FAR struct net_driver_s *dev, FAR struct can_conn_s *conn);
+
+/****************************************************************************
+ * Name: psock_can_send
+ *
+ * Description:
+ *   The psock_can_send() call may be used only when the packet socket is in
+ *   a connected state (so that the intended recipient is known).
+ *
+ * Input Parameters:
+ *   psock    An instance of the internal socket structure.
+ *   buf      Data to send
+ *   len      Length of data to send
+ *
+ * Returned Value:
+ *   On success, returns the number of characters sent.  On  error,
+ *   a negated errno value is returned.  See send() for the complete list
+ *   of return values.
+ *
+ ****************************************************************************/
+
+struct socket;
+ssize_t psock_can_send(FAR struct socket *psock, FAR const void *buf,
+                       size_t len);
+
+/****************************************************************************
+ * Name: psock_can_sendmsg
+ *
+ * Description:
+ *   The psock_can_sendmsg() call may be used only when the packet socket is
+ *   in a connected state (so that the intended recipient is known).
+ *
+ * Input Parameters:
+ *   psock    An instance of the internal socket structure.
+ *   msg      msg to send
+ *
+ * Returned Value:
+ *   On success, returns the number of characters sent.  On  error,
+ *   a negated errno value is returned.  See send() for the complete list
+ *   of return values.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_CMSG
+ssize_t psock_can_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg);
+#endif
+
+/****************************************************************************
+ * Name: can_readahead_signal
+ *
+ * Description:
+ *   Read-ahead data has been buffered.  Signal all threads waiting for
+ *   read-ahead data to become available.
+ *
+ *   When read-ahead data becomes available, *all* of the workers waiting
+ *   for read-ahead data will be executed.  If there are multiple workers
+ *   waiting for read-ahead data then only the first to execute will get the
+ *   data.  Others will need to call can_readahead_notifier_setup() once
+ *   again.
+ *
+ * Input Parameters:
+ *   conn  - The CAN connection where read-ahead data was just buffered.
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_CAN_NOTIFIER
+void can_readahead_signal(FAR struct can_conn_s *conn);
+#endif
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_NET_CAN */
+#endif /* __NET_CAN_CAN_H */
diff --git a/net/can/can_callback.c b/net/can/can_callback.c
new file mode 100644
index 0000000..f8f0fae
--- /dev/null
+++ b/net/can/can_callback.c
@@ -0,0 +1,242 @@
+/****************************************************************************
+ * net/pkt/pkt_callback.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_CAN)
+
+#include <stdint.h>
+#include <debug.h>
+
+#include <nuttx/net/netconfig.h>
+#include <nuttx/net/netdev.h>
+#include <nuttx/mm/iob.h>
+
+#include "devif/devif.h"
+#include "can/can.h"
+
+#ifdef CONFIG_NET_TIMESTAMP
+#include <sys/time.h>
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: can_data_event
+ *
+ * Description:
+ *   Handle data that is not accepted by the application because there is no
+ *   listener in place ready to receive the data.
+ *
+ * Assumptions:
+ * - The caller has checked that CAN_NEWDATA is set in flags and that is no
+ *   other handler available to process the incoming data.
+ * - This function must be called with the network locked.
+ *
+ ****************************************************************************/
+
+static inline uint16_t
+can_data_event(FAR struct net_driver_s *dev, FAR struct can_conn_s *conn,
+               uint16_t flags)
+{
+  uint16_t ret;
+  FAR uint8_t *buffer = dev->d_appdata;
+  int buflen = dev->d_len;
+  uint16_t recvlen;
+
+  ret = (flags & ~CAN_NEWDATA);
+
+  /* Save as the packet data as in the read-ahead buffer.  NOTE that
+   * partial packets will not be buffered.
+   */
+
+  recvlen = can_datahandler(conn, buffer, buflen);
+  if (recvlen < buflen)
+    {
+      /* There is no handler to receive new data and there are no free
+       * read-ahead buffers to retain the data -- drop the packet.
+       */
+
+      ninfo("Dropped %d bytes\n", dev->d_len);
+
+#ifdef CONFIG_NET_STATISTICS
+      /* No support CAN net statistics yet */
+
+      /* g_netstats.tcp.drop++; */
+
+#endif
+    }
+
+  /* In any event, the new data has now been handled */
+
+  dev->d_len = 0;
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: can_callback
+ *
+ * Description:
+ *   Inform the application holding the packet socket of a change in state.
+ *
+ * Returned Value:
+ *   OK if packet has been processed, otherwise ERROR.
+ *
+ * Assumptions:
+ *   This function can be called from an interrupt.
+ *
+ ****************************************************************************/
+
+uint16_t can_callback(FAR struct net_driver_s *dev,
+                      FAR struct can_conn_s *conn, uint16_t flags)
+{
+  /* Some sanity checking */
+
+  if (conn)
+    {
+#ifdef CONFIG_NET_TIMESTAMP
+      /* TIMESTAMP sockopt is activated, create timestamp and copy to iob */
+
+      if (conn->psock->s_timestamp)
+        {
+          struct timespec *ts = (struct timespec *)
+                                                &dev->d_appdata[dev->d_len];
+          struct timeval *tv = (struct timeval *)
+                                                &dev->d_appdata[dev->d_len];
+          dev->d_len += sizeof(struct timeval);
+          clock_systime_timespec(ts);
+          tv->tv_usec = ts->tv_nsec / 1000;
+        }
+#endif
+
+      /* Try to lock the network when successfull send data to the listener */
+
+      if (net_trylock() == OK)
+        {
+          flags = devif_conn_event(dev, conn, flags, conn->list);
+          net_unlock();
+        }
+
+      /* Either we did not get the lock or there is no application listening
+       * If we did not get a lock we store the frame in the read-ahead buffer
+       */
+
+      if ((flags & CAN_NEWDATA) != 0)
+        {
+          /* Data was not handled.. dispose of it appropriately */
+
+          flags = can_data_event(dev, conn, flags);
+        }
+    }
+
+  return flags;
+}
+
+/****************************************************************************
+ * Name: can_datahandler
+ *
+ * Description:
+ *   Handle data that is not accepted by the application.  This may be called
+ *   either (1) from the data receive logic if it cannot buffer the data, or
+ *   (2) from the CAN event logic is there is no listener in place ready to
+ *   receive the data.
+ *
+ * Input Parameters:
+ *   conn - A pointer to the CAN connection structure
+ *   buffer - A pointer to the buffer to be copied to the read-ahead
+ *     buffers
+ *   buflen - The number of bytes to copy to the read-ahead buffer.
+ *
+ * Returned Value:
+ *   The number of bytes actually buffered is returned.  This will be either
+ *   zero or equal to buflen; partial packets are not buffered.
+ *
+ * Assumptions:
+ * - The caller has checked that CAN_NEWDATA is set in flags and that is no
+ *   other handler available to process the incoming data.
+ * - This function must be called with the network locked.
+ *
+ ****************************************************************************/
+
+uint16_t can_datahandler(FAR struct can_conn_s *conn, FAR uint8_t *buffer,
+                         uint16_t buflen)
+{
+  FAR struct iob_s *iob;
+  int ret;
+
+  /* Try to allocate on I/O buffer to start the chain without waiting (and
+   * throttling as necessary).  If we would have to wait, then drop the
+   * packet.
+   */
+
+  iob = iob_tryalloc(true, IOBUSER_NET_CAN_READAHEAD);
+  if (iob == NULL)
+    {
+      nerr("ERROR: Failed to create new I/O buffer chain\n");
+      return 0;
+    }
+
+  /* Copy the new appdata into the I/O buffer chain (without waiting) */
+
+  ret = iob_trycopyin(iob, buffer, buflen, 0, true,
+                      IOBUSER_NET_CAN_READAHEAD);
+  if (ret < 0)
+    {
+      /* On a failure, iob_copyin return a negated error value but does
+       * not free any I/O buffers.
+       */
+
+      nerr("ERROR: Failed to add data to the I/O buffer chain: %d\n", ret);
+      iob_free_chain(iob, IOBUSER_NET_CAN_READAHEAD);
+      return 0;
+    }
+
+  /* Add the new I/O buffer chain to the tail of the read-ahead queue (again
+   * without waiting).
+   */
+
+  ret = iob_tryadd_queue(iob, &conn->readahead);
+  if (ret < 0)
+    {
+      nerr("ERROR: Failed to queue the I/O buffer chain: %d\n", ret);
+      iob_free_chain(iob, IOBUSER_NET_CAN_READAHEAD);
+      return 0;
+    }
+
+#ifdef CONFIG_NET_CAN_NOTIFIER
+  /* Provide notification(s) that additional CAN read-ahead data is
+   * available.
+   */
+
+  can_readahead_signal(conn);
+#endif
+  return buflen;
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_CAN */
diff --git a/net/can/can_conn.c b/net/can/can_conn.c
new file mode 100644
index 0000000..574796c
--- /dev/null
+++ b/net/can/can_conn.c
@@ -0,0 +1,223 @@
+/****************************************************************************
+ * net/can/can_conn.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <queue.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <arch/irq.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/semaphore.h>
+#include <nuttx/net/netconfig.h>
+#include <nuttx/net/net.h>
+
+#include "utils/utils.h"
+#include "can/can.h"
+
+#ifdef CONFIG_NET_CAN
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* The array containing all NetLink connections. */
+
+static struct can_conn_s g_can_connections[CONFIG_CAN_CONNS];
+
+/* A list of all free NetLink connections */
+
+static dq_queue_t g_free_can_connections;
+static sem_t g_free_sem;
+
+/* A list of all allocated NetLink connections */
+
+static dq_queue_t g_active_can_connections;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: _can_semtake() and _can_semgive()
+ *
+ * Description:
+ *   Take/give semaphore
+ *
+ ****************************************************************************/
+
+static void _can_semtake(FAR sem_t *sem)
+{
+  net_lockedwait_uninterruptible(sem);
+}
+
+static void _can_semgive(FAR sem_t *sem)
+{
+  nxsem_post(sem);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: can_initialize()
+ *
+ * Description:
+ *   Initialize the User Socket connection structures.  Called once and only
+ *   from the networking layer.
+ *
+ ****************************************************************************/
+
+void can_initialize(void)
+{
+  int i;
+
+  /* Initialize the queues */
+
+  dq_init(&g_free_can_connections);
+  dq_init(&g_active_can_connections);
+  nxsem_init(&g_free_sem, 0, 1);
+
+  for (i = 0; i < CONFIG_CAN_CONNS; i++)
+    {
+      FAR struct can_conn_s *conn = &g_can_connections[i];
+
+      /* Mark the connection closed and move it to the free list */
+
+      memset(conn, 0, sizeof(*conn));
+      dq_addlast(&conn->node, &g_free_can_connections);
+    }
+}
+
+/****************************************************************************
+ * Name: can_alloc()
+ *
+ * Description:
+ *   Allocate a new, uninitialized NetLink connection structure.  This is
+ *   normally something done by the implementation of the socket() API
+ *
+ ****************************************************************************/
+
+FAR struct can_conn_s *can_alloc(void)
+{
+  FAR struct can_conn_s *conn;
+
+  /* The free list is protected by a semaphore (that behaves like a mutex). */
+
+  _can_semtake(&g_free_sem);
+  conn = (FAR struct can_conn_s *)dq_remfirst(&g_free_can_connections);
+  if (conn != NULL)
+    {
+      /* Make sure that the connection is marked as uninitialized */
+
+      memset(conn, 0, sizeof(*conn));
+
+      /* FIXME SocketCAN default behavior enables loopback */
+
+#ifdef CONFIG_NET_CANPROTO_OPTIONS
+      /* By default the filter is configured to catch all,
+       * this is done in commented filter code below:
+       *
+       * struct can_filter_t catchall_filter;
+       * filter.can_id = 0;
+       * filter.can_mask = 0;
+       * conn->filters[0] = catchall_filter;
+       *
+       * However memset already sets the filter to 0
+       * therefore we only have to set the filter count to 1
+       */
+
+      conn->filter_count = 1;
+#endif
+
+      /* Enqueue the connection into the active list */
+
+      dq_addlast(&conn->node, &g_active_can_connections);
+    }
+
+  _can_semgive(&g_free_sem);
+  return conn;
+}
+
+/****************************************************************************
+ * Name: can_free()
+ *
+ * Description:
+ *   Free a NetLink connection structure that is no longer in use. This
+ *   should be done by the implementation of close().
+ *
+ ****************************************************************************/
+
+void can_free(FAR struct can_conn_s *conn)
+{
+  /* The free list is protected by a semaphore (that behaves like a mutex). */
+
+  DEBUGASSERT(conn->crefs == 0);
+
+  _can_semtake(&g_free_sem);
+
+  /* Remove the connection from the active list */
+
+  dq_rem(&conn->node, &g_active_can_connections);
+
+  /* Reset structure */
+
+  memset(conn, 0, sizeof(*conn));
+
+  /* Free the connection */
+
+  dq_addlast(&conn->node, &g_free_can_connections);
+  _can_semgive(&g_free_sem);
+}
+
+/****************************************************************************
+ * Name: can_nextconn()
+ *
+ * Description:
+ *   Traverse the list of allocated NetLink connections
+ *
+ * Assumptions:
+ *   This function is called from NetLink device logic.
+ *
+ ****************************************************************************/
+
+FAR struct can_conn_s *can_nextconn(FAR struct can_conn_s *conn)
+{
+  if (conn == NULL)
+    {
+      return (FAR struct can_conn_s *)g_active_can_connections.head;
+    }
+  else
+    {
+      return (FAR struct can_conn_s *)conn->node.flink;
+    }
+}
+
+#endif /* CONFIG_NET_CAN */
diff --git a/net/can/can_getsockopt.c b/net/can/can_getsockopt.c
new file mode 100644
index 0000000..df6d0c9
--- /dev/null
+++ b/net/can/can_getsockopt.c
@@ -0,0 +1,220 @@
+/****************************************************************************
+ * net/can/can_setsockopt.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/time.h>
+#include <stdint.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <netpacket/can.h>
+
+#include <nuttx/net/net.h>
+#include <nuttx/net/can.h>
+
+#include "socket/socket.h"
+#include "utils/utils.h"
+#include "can/can.h"
+
+#ifdef CONFIG_NET_CANPROTO_OPTIONS
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: can_getsockopt
+ *
+ * Description:
+ *   can_getsockopt() retrieves the value for the option specified by the
+ *   'option' argument for the socket specified by the 'psock' argument.  If
+ *   the size of the option value is greater than 'value_len', the value
+ *   stored in the object pointed to by the 'value' argument will be silently
+ *   truncated. Otherwise, the length pointed to by the 'value_len' argument
+ *   will be modified to indicate the actual length of the 'value'.
+ *
+ *   See <sys/socket.h> a complete list of values for the socket-level
+ *   'option' argument.  Protocol-specific options are are protocol specific
+ *   header files (such as netpacket/can.h for the case of the CAN protocol).
+ *
+ * Input Parameters:
+ *   psock     Socket structure of the socket to query
+ *   level     Protocol level to set the option
+ *   option    identifies the option to get
+ *   value     Points to the argument value
+ *   value_len The length of the argument value
+ *
+ * Returned Value:
+ *   Returns zero (OK) on success.  On failure, it returns a negated errno
+ *   value to indicate the nature of the error.  See psock_getsockopt() for
+ *   the complete list of appropriate return error codes.
+ *
+ ****************************************************************************/
+
+int can_getsockopt(FAR struct socket *psock, int option,
+                   FAR void *value, FAR socklen_t *value_len)
+{
+  FAR struct can_conn_s *conn;
+  int ret;
+
+  DEBUGASSERT(psock != NULL && value != NULL && value_len != NULL &&
+              psock->s_conn != NULL);
+  conn = (FAR struct can_conn_s *)psock->s_conn;
+
+  if (psock->s_type != SOCK_RAW)
+    {
+      nerr("ERROR:  Not a RAW CAN socket\n");
+      return -ENOTCONN;
+    }
+
+  switch (option)
+    {
+      case CAN_RAW_FILTER:
+        if (*value_len % sizeof(struct can_filter) != 0)
+          {
+            ret = -EINVAL;
+          }
+        else if (*value_len > CONFIG_NET_CAN_RAW_FILTER_MAX *
+                   sizeof(struct can_filter))
+          {
+            ret = -EINVAL;
+          }
+        else
+          {
+            int count = conn->filter_count;
+
+          if (*value_len < count * sizeof(struct can_filter))
+              {
+                count = *value_len / sizeof(struct can_filter);
+              }
+          else
+            {
+              *value_len = count * sizeof(struct can_filter);
+            }
+
+            for (int i = 0; i < count; i++)
+              {
+                ((struct can_filter *)value)[i] = conn->filters[i];
+              }
+
+            ret = OK;
+          }
+        break;
+
+      case CAN_RAW_ERR_FILTER:
+        break;
+
+      case CAN_RAW_LOOPBACK:
+        if (*value_len < sizeof(conn->loopback))
+          {
+            /* REVISIT: POSIX says that we should truncate the value if it
+             * is larger than value_len.   That just doesn't make sense
+             * to me in this case.
+             */
+
+            ret              = -EINVAL;
+          }
+        else
+          {
+            FAR int *loopback  = (FAR int32_t *)value;
+            *loopback          = conn->loopback;
+            *value_len         = sizeof(conn->loopback);
+            ret                = OK;
+          }
+        break;
+
+      case CAN_RAW_RECV_OWN_MSGS:
+        if (*value_len < sizeof(conn->recv_own_msgs))
+          {
+            /* REVISIT: POSIX says that we should truncate the value if it
+             * is larger than value_len.   That just doesn't make sense
+             * to me in this case.
+             */
+
+            ret              = -EINVAL;
+          }
+        else
+          {
+            FAR int *recv_own_msgs = (FAR int32_t *)value;
+            *recv_own_msgs         = conn->recv_own_msgs;
+            *value_len             = sizeof(conn->recv_own_msgs);
+            ret                    = OK;
+          }
+        break;
+
+      case CAN_RAW_FD_FRAMES:
+        if (*value_len < sizeof(conn->fd_frames))
+          {
+            /* REVISIT: POSIX says that we should truncate the value if it
+             * is larger than value_len.   That just doesn't make sense
+             * to me in this case.
+             */
+
+            ret              = -EINVAL;
+          }
+        else
+          {
+            FAR int *fd_frames = (FAR int32_t *)value;
+            *fd_frames         = conn->fd_frames;
+            *value_len         = sizeof(conn->fd_frames);
+            ret                = OK;
+          }
+        break;
+
+      case CAN_RAW_JOIN_FILTERS:
+        break;
+
+#ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE
+      case CAN_RAW_TX_DEADLINE:
+        if (*value_len < sizeof(conn->tx_deadline))
+          {
+            /* REVISIT: POSIX says that we should truncate the value if it
+             * is larger than value_len.   That just doesn't make sense
+             * to me in this case.
+             */
+
+            ret              = -EINVAL;
+          }
+        else
+          {
+            FAR int *tx_deadline = (FAR int32_t *)value;
+            *tx_deadline         = conn->tx_deadline;
+            *value_len         = sizeof(conn->tx_deadline);
+            ret                = OK;
+          }
+        break;
+#endif
+
+      default:
+        nerr("ERROR: Unrecognized RAW CAN socket option: %d\n", option);
+        ret = -ENOPROTOOPT;
+        break;
+    }
+
+  return ret;
+}
+
+#endif /* CONFIG_NET_CANPROTO_OPTIONS */
diff --git a/net/can/can_input.c b/net/can/can_input.c
new file mode 100644
index 0000000..024bb9a
--- /dev/null
+++ b/net/can/can_input.c
@@ -0,0 +1,204 @@
+/****************************************************************************
+ * net/can/can_input.c
+ * Handling incoming packet input
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_CAN)
+
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/net/netdev.h>
+#include <nuttx/net/can.h>
+
+#include "devif/devif.h"
+#include "can/can.h"
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+const uint8_t can_dlc_to_len[16] =
+{
+    0,
+    1,
+    2,
+    3,
+    4,
+    5,
+    6,
+    7,
+    8,
+    12,
+    16,
+    20,
+    24,
+    32,
+    48,
+    64,
+};
+const uint8_t len_to_can_dlc[65] =
+{
+    0,
+    1,
+    2,
+    3,
+    4,
+    5,
+    6,
+    7,
+    8,
+    9,
+    9,
+    9,
+    9,
+    10,
+    10,
+    10,
+    10,
+    11,
+    11,
+    11,
+    11,
+    12,
+    12,
+    12,
+    12,
+    13,
+    13,
+    13,
+    13,
+    13,
+    13,
+    13,
+    13,
+    14,
+    14,
+    14,
+    14,
+    14,
+    14,
+    14,
+    14,
+    14,
+    14,
+    14,
+    14,
+    14,
+    14,
+    14,
+    14,
+    15,
+    15,
+    15,
+    15,
+    15,
+    15,
+    15,
+    15,
+    15,
+    15,
+    15,
+    15,
+    15,
+    15,
+    15,
+    15,
+};
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: can_input
+ *
+ * Description:
+ *   Handle incoming packet input
+ *
+ * Input Parameters:
+ *   dev - The device driver structure containing the received packet
+ *
+ * Returned Value:
+ *   OK     The packet has been processed  and can be deleted
+ *  -EAGAIN There is a matching connection, but could not dispatch the packet
+ *          yet.  Useful when a packet arrives before a recv call is in
+ *          place.
+ *
+ * Assumptions:
+ *   This function can be called from an interrupt.
+ *
+ ****************************************************************************/
+
+int can_input(struct net_driver_s *dev)
+{
+  FAR struct can_conn_s *conn = NULL;
+  int ret = OK;
+
+  do
+    {
+      /* FIXME Support for multiple sockets??? */
+
+      conn = can_nextconn(conn);
+    }
+  while (conn && conn->dev != 0 && dev != conn->dev);
+
+  if (conn)
+    {
+      uint16_t flags;
+
+      /* Setup for the application callback */
+
+      dev->d_appdata = dev->d_buf;
+      dev->d_sndlen  = 0;
+
+      /* Perform the application callback */
+
+      flags = can_callback(dev, conn, CAN_NEWDATA);
+
+      /* If the operation was successful, the CAN_NEWDATA flag is removed
+       * and thus the packet can be deleted (OK will be returned).
+       */
+
+      if ((flags & CAN_NEWDATA) != 0)
+        {
+          /* No.. the packet was not processed now.  Return -EAGAIN so
+           * that the driver may retry again later.  We still need to
+           * set d_len to zero so that the driver is aware that there
+           * is nothing to be sent.
+           */
+
+           nwarn("WARNING: Packet not processed\n");
+           ret = -EAGAIN;
+        }
+    }
+  else
+    {
+      ninfo("No CAN listener\n");
+    }
+
+  return ret;
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_CAN */
diff --git a/libs/libc/net/lib_recvmsg.c b/net/can/can_notifier.c
similarity index 70%
copy from libs/libc/net/lib_recvmsg.c
copy to net/can/can_notifier.c
index 984a16f..f4c7b1e 100644
--- a/libs/libc/net/lib_recvmsg.c
+++ b/net/can/can_notifier.c
@@ -1,7 +1,7 @@
 /****************************************************************************
- * libc/net/lib_recvmsg.c
+ * net/can/can_notifier.c
  *
- *   Copyright (C) 2007, 2008, 2012, 2008 Gregory Nutt. All rights reserved.
+ *   Copyright (C) 2018 Gregory Nutt. All rights reserved.
  *   Author: Gregory Nutt <gn...@nuttx.org>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -39,51 +39,45 @@
 
 #include <nuttx/config.h>
 
-#ifdef CONFIG_NET
-
 #include <sys/types.h>
-#include <sys/socket.h>
-#include <errno.h>
+#include <assert.h>
+
+#include <nuttx/wqueue.h>
+
+#include "can/can.h"
+
+#ifdef CONFIG_NET_CAN_NOTIFIER
 
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
 /****************************************************************************
- * Function: recvmsg
+ * Name: can_readahead_signal
  *
  * Description:
- *   The recvmsg() call is identical to recvfrom() with a NULL from parameter.
+ *   Read-ahead data has been buffered.  Signal all threads waiting for
+ *   read-ahead data to become available.
  *
- * Parameters:
- *   sockfd   Socket descriptor of socket
- *   buf      Buffer to receive data
- *   len      Length of buffer
- *   flags    Receive flags
+ *   When read-ahead data becomes available, *all* of the workers waiting
+ *   for read-ahead data will be executed.  If there are multiple workers
+ *   waiting for read-ahead data then only the first to execute will get the
+ *   data.  Others will need to call can_readahead_notifier_setup() once
+ *   again.
  *
- * Returned Value:
- *  (see recvfrom)
+ * Input Parameters:
+ *   conn  - The CAN connection where read-ahead data was just buffered.
  *
- * Assumptions:
+ * Returned Value:
+ *   None.
  *
  ****************************************************************************/
 
-ssize_t recvmsg(int sockfd, FAR struct msghdr *msg, int flags)
+void can_readahead_signal(FAR struct can_conn_s *conn)
 {
-  FAR void *buf             = msg->msg_iov->iov_base;
-  FAR struct sockaddr *from = msg->msg_name;
-  FAR socklen_t *fromlen    = (FAR socklen_t *)&msg->msg_namelen;
-  size_t len                = msg->msg_iov->iov_len;
+  /* This is just a simple wrapper around work_notifier_signal(). */
 
-  if (msg->msg_iovlen == 1)
-    {
-      return recvfrom(sockfd, buf, len, flags, from, fromlen);
-    }
-  else
-    {
-      set_errno(ENOTSUP);
-      return ERROR;
-    }
+  work_notifier_signal(WORK_CAN_READAHEAD, conn);
 }
 
-#endif /* CONFIG_NET */
+#endif /* CONFIG_NET_CAN_NOTIFIER */
diff --git a/net/can/can_poll.c b/net/can/can_poll.c
new file mode 100644
index 0000000..2163242
--- /dev/null
+++ b/net/can/can_poll.c
@@ -0,0 +1,88 @@
+/****************************************************************************
+ * net/pkt/pkt_poll.c
+ * Poll for the availability of packet TX data
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_CAN)
+
+#include <debug.h>
+
+#include <nuttx/net/netconfig.h>
+#include <nuttx/net/netdev.h>
+
+#include "devif/devif.h"
+#include "can/can.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: can_poll
+ *
+ * Description:
+ *   Poll a packet "connection" structure for availability of TX data
+ *
+ * Input Parameters:
+ *   dev - The device driver structure to use in the send operation
+ *   conn - The packet "connection" to poll for TX data
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   The network is locked.
+ *
+ ****************************************************************************/
+
+void can_poll(FAR struct net_driver_s *dev, FAR struct can_conn_s *conn)
+{
+  /* Verify that the packet connection is valid */
+
+  if (conn != NULL)
+    {
+      /* Setup for the application callback */
+
+      dev->d_appdata = &dev->d_buf[NET_LL_HDRLEN(dev)];
+      dev->d_len     = 0;
+      dev->d_sndlen  = 0;
+
+      /* Perform the application callback */
+
+      can_callback(dev, conn, CAN_POLL);
+
+      /* Check if the application has data to send */
+
+      if (dev->d_sndlen > 0)
+        {
+          return;
+        }
+    }
+
+  /* Make sure that d_len is zero meaning that there is nothing to be sent */
+
+  dev->d_len = 0;
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_CAN */
diff --git a/net/can/can_recvfrom.c b/net/can/can_recvfrom.c
new file mode 100644
index 0000000..bbea9c3
--- /dev/null
+++ b/net/can/can_recvfrom.c
@@ -0,0 +1,838 @@
+/****************************************************************************
+ * net/can/can_recvfrom.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef CONFIG_NET_CAN
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <debug.h>
+#include <assert.h>
+
+#include <arch/irq.h>
+
+#include <nuttx/semaphore.h>
+#include <nuttx/net/net.h>
+#include <nuttx/net/netdev.h>
+
+#include "netdev/netdev.h"
+#include "devif/devif.h"
+#include "can/can.h"
+#include "socket/socket.h"
+#include <netpacket/packet.h>
+
+#ifdef CONFIG_NET_TIMESTAMP
+#include <sys/time.h>
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct can_recvfrom_s
+{
+  FAR struct socket *pr_sock;          /* The parent socket structure */
+  FAR struct devif_callback_s *pr_cb;  /* Reference to callback instance */
+  sem_t        pr_sem;                 /* Semaphore signals recv completion */
+  size_t       pr_buflen;              /* Length of receive buffer */
+  FAR uint8_t *pr_buffer;              /* Pointer to receive buffer */
+  ssize_t      pr_recvlen;             /* The received length */
+#ifdef CONFIG_NET_CMSG
+  size_t       pr_msglen;              /* Length of msg buffer */
+  FAR uint8_t *pr_msgbuf;              /* Pointer to msg buffer */
+#endif
+  int          pr_result;              /* Success:OK, failure:negated errno */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: can_add_recvlen
+ *
+ * Description:
+ *   Update information about space available for new data and update size
+ *   of data in buffer,  This logic accounts for the case where
+ *   recvfrom_udpreadahead() sets state.pr_recvlen == -1 .
+ *
+ * Input Parameters:
+ *   pstate   recvfrom state structure
+ *   recvlen  size of new data appended to buffer
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static inline void can_add_recvlen(FAR struct can_recvfrom_s *pstate,
+                                   size_t recvlen)
+{
+  if (pstate->pr_recvlen < 0)
+    {
+      pstate->pr_recvlen = 0;
+    }
+
+  pstate->pr_recvlen += recvlen;
+  pstate->pr_buffer  += recvlen;
+  pstate->pr_buflen  -= recvlen;
+}
+
+/****************************************************************************
+ * Name: can_recvfrom_newdata
+ *
+ * Description:
+ *   Copy the read data from the packet
+ *
+ * Input Parameters:
+ *   dev      The structure of the network driver that caused the event.
+ *   pstate   recvfrom state structure
+ *
+ * Returned Value:
+ *   None.
+ *
+ * Assumptions:
+ *   The network is locked.
+ *
+ ****************************************************************************/
+
+static size_t can_recvfrom_newdata(FAR struct net_driver_s *dev,
+                                 FAR struct can_recvfrom_s *pstate)
+{
+  size_t recvlen;
+
+  if (dev->d_len > pstate->pr_buflen)
+    {
+      recvlen = pstate->pr_buflen;
+    }
+  else
+    {
+      recvlen = dev->d_len;
+    }
+
+  /* Copy the new packet data into the user buffer */
+
+  memcpy(pstate->pr_buffer, dev->d_buf, recvlen);
+
+  /* Update the accumulated size of the data read */
+
+  can_add_recvlen(pstate, recvlen);
+
+  return recvlen;
+}
+
+/****************************************************************************
+ * Name: can_newdata
+ *
+ * Description:
+ *   Copy the read data from the packet
+ *
+ * Input Parameters:
+ *   dev      The structure of the network driver that generated the event
+ *   pstate   recvfrom state structure
+ *
+ * Returned Value:
+ *   None.
+ *
+ * Assumptions:
+ *   The network is locked.
+ *
+ ****************************************************************************/
+
+static inline void can_newdata(FAR struct net_driver_s *dev,
+                               FAR struct can_recvfrom_s *pstate)
+{
+  /* Take as much data from the packet as we can */
+
+  size_t recvlen = can_recvfrom_newdata(dev, pstate);
+
+  /* If there is more data left in the packet that we could not buffer, then
+   * add it to the read-ahead buffers.
+   */
+
+  if (recvlen < dev->d_len)
+    {
+      FAR struct can_conn_s *conn =
+        (FAR struct can_conn_s *)pstate->pr_sock->s_conn;
+      FAR uint8_t *buffer = (FAR uint8_t *)dev->d_appdata + recvlen;
+      uint16_t buflen = dev->d_len - recvlen;
+#ifdef CONFIG_DEBUG_NET
+      uint16_t nsaved;
+
+      nsaved = can_datahandler(conn, buffer, buflen);
+#else
+      can_datahandler(conn, buffer, buflen);
+#endif
+
+      /* There are complicated buffering issues that are not addressed fully
+       * here.  For example, what if up_datahandler() cannot buffer the
+       * remainder of the packet?  In that case, the data will be dropped but
+       * still ACKed.  Therefore it would not be resent.
+       *
+       * This is probably not an issue here because we only get here if the
+       * read-ahead buffers are empty and there would have to be something
+       * serioulsy wrong with the configuration not to be able to buffer a
+       * partial packet in this context.
+       */
+
+#ifdef CONFIG_DEBUG_NET
+      if (nsaved < buflen)
+        {
+          nerr("ERROR: packet data not saved (%d bytes)\n", buflen - nsaved);
+        }
+#endif
+    }
+
+  /* Indicate no data in the buffer */
+
+  dev->d_len = 0;
+}
+
+/****************************************************************************
+ * Name: can_readahead
+ *
+ * Description:
+ *   Copy the read-ahead data from the packet
+ *
+ * Input Parameters:
+ *   pstate   recvfrom state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   The network is locked.
+ *
+ ****************************************************************************/
+
+static inline int can_readahead(struct can_recvfrom_s *pstate)
+{
+  FAR struct can_conn_s *conn =
+    (FAR struct can_conn_s *) pstate->pr_sock->s_conn;
+  FAR struct iob_s *iob;
+  int recvlen;
+
+  /* Check there is any CAN data already buffered in a read-ahead
+   * buffer.
+   */
+
+  pstate->pr_recvlen = -1;
+
+  if ((iob = iob_peek_queue(&conn->readahead)) != NULL &&
+      pstate->pr_buflen > 0)
+    {
+      DEBUGASSERT(iob->io_pktlen > 0);
+
+      /* Transfer that buffered data from the I/O buffer chain into
+       * the user buffer.
+       */
+
+      recvlen = iob_copyout(pstate->pr_buffer, iob, pstate->pr_buflen, 0);
+
+      /* If we took all of the data from the I/O buffer chain is empty, then
+       * release it.  If there is still data available in the I/O buffer
+       * chain, then just trim the data that we have taken from the
+       * beginning of the I/O buffer chain.
+       */
+
+      if (recvlen >= iob->io_pktlen)
+        {
+          FAR struct iob_s *tmp;
+
+          /* Remove the I/O buffer chain from the head of the read-ahead
+           * buffer queue.
+           */
+
+          tmp = iob_remove_queue(&conn->readahead);
+          DEBUGASSERT(tmp == iob);
+          UNUSED(tmp);
+
+          /* And free the I/O buffer chain */
+
+          iob_free_chain(iob, IOBUSER_NET_CAN_READAHEAD);
+        }
+      else
+        {
+          /* The bytes that we have received from the head of the I/O
+           * buffer chain (probably changing the head of the I/O
+           * buffer queue).
+           */
+
+          iob_trimhead_queue(&conn->readahead, recvlen,
+                             IOBUSER_NET_CAN_READAHEAD);
+        }
+
+      /* do not pass frames with DLC > 8 to a legacy socket */
+#if defined(CONFIG_NET_CANPROTO_OPTIONS) && defined(CONFIG_NET_CAN_CANFD)
+      if (!conn->fd_frames)
+#endif
+        {
+          if (recvlen > sizeof(struct can_frame))
+            {
+              return 0;
+            }
+        }
+
+      return recvlen;
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: can_readahead
+ *
+ * Description:
+ *   Copy the read-ahead data from the packet
+ *
+ * Input Parameters:
+ *   pstate   recvfrom state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   The network is locked.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_TIMESTAMP
+static inline int can_readahead_timestamp(struct can_conn_s *conn,
+                                          FAR uint8_t *buffer)
+{
+  FAR struct iob_s *iob;
+  int recvlen;
+
+  if ((iob = iob_peek_queue(&conn->readahead)) != NULL)
+    {
+      DEBUGASSERT(iob->io_pktlen > 0);
+
+      /* Transfer that buffered data from the I/O buffer chain into
+       * the user buffer.
+       */
+
+      recvlen = iob_copyout(buffer, iob, sizeof(struct timeval), 0);
+
+      /* If we took all of the data from the I/O buffer chain is empty, then
+       * release it.  If there is still data available in the I/O buffer
+       * chain, then just trim the data that we have taken from the
+       * beginning of the I/O buffer chain.
+       */
+
+      if (recvlen >= iob->io_pktlen)
+        {
+          FAR struct iob_s *tmp;
+
+          /* Remove the I/O buffer chain from the head of the read-ahead
+           * buffer queue.
+           */
+
+          tmp = iob_remove_queue(&conn->readahead);
+          DEBUGASSERT(tmp == iob);
+          UNUSED(tmp);
+
+          /* And free the I/O buffer chain */
+
+          iob_free_chain(iob, IOBUSER_NET_CAN_READAHEAD);
+        }
+      else
+        {
+          /* The bytes that we have received from the head of the I/O
+           * buffer chain (probably changing the head of the I/O
+           * buffer queue).
+           */
+
+          iob_trimhead_queue(&conn->readahead, recvlen,
+                             IOBUSER_NET_CAN_READAHEAD);
+        }
+
+      return recvlen;
+    }
+
+  return 0;
+}
+#endif
+
+#ifdef CONFIG_NET_CANPROTO_OPTIONS
+static int can_recv_filter(struct can_conn_s *conn, canid_t id)
+{
+  for (int i = 0; i < conn->filter_count; i++)
+    {
+      if (conn->filters[i].can_id & CAN_INV_FILTER)
+        {
+          if ((id & conn->filters[i].can_mask) !=
+                ((conn->filters[i].can_id & ~CAN_INV_FILTER) &
+                conn->filters[i].can_mask))
+            {
+              return 1;
+            }
+        }
+      else
+        {
+          if ((id & conn->filters[i].can_mask) ==
+                (conn->filters[i].can_id & conn->filters[i].can_mask))
+            {
+              return 1;
+            }
+        }
+    }
+
+  return 0;
+}
+#endif
+
+static uint16_t can_recvfrom_eventhandler(FAR struct net_driver_s *dev,
+                                          FAR void *pvconn,
+                                          FAR void *pvpriv, uint16_t flags)
+{
+  struct can_recvfrom_s *pstate = (struct can_recvfrom_s *)pvpriv;
+  struct can_conn_s *conn = (struct can_conn_s *)pstate->pr_sock->s_conn;
+
+  /* 'priv' might be null in some race conditions (?) */
+
+  if (pstate)
+    {
+      if ((flags & CAN_NEWDATA) != 0)
+        {
+          /* If a new packet is available, check receive filters
+           * when is valid then complete the read action.
+           */
+#ifdef CONFIG_NET_CANPROTO_OPTIONS
+          if (can_recv_filter(conn, (canid_t) *dev->d_appdata) == 0)
+            {
+              flags &= ~CAN_NEWDATA;
+              return flags;
+            }
+#endif
+
+          /* do not pass frames with DLC > 8 to a legacy socket */
+#if defined(CONFIG_NET_CANPROTO_OPTIONS) && defined(CONFIG_NET_CAN_CANFD)
+          if (!conn->fd_frames)
+#endif
+            {
+              if (dev->d_len > sizeof(struct can_frame))
+                {
+                  /* DO WE NEED TO CLEAR FLAGS?? */
+
+                  flags &= ~CAN_NEWDATA;
+                  return flags;
+                }
+            }
+
+          /* Copy the packet */
+
+          can_newdata(dev, pstate);
+
+#ifdef CONFIG_NET_TIMESTAMP
+          if (pstate->pr_sock->s_timestamp)
+            {
+              if (pstate->pr_msglen == sizeof(struct timeval))
+                {
+                  can_readahead_timestamp(conn, pstate->pr_msgbuf);
+                }
+              else
+                {
+                  /* We still have to consume the data
+                   * otherwise IOB gets full
+                   */
+
+                  uint8_t dummy_buf[sizeof(struct timeval)];
+                  can_readahead_timestamp(conn, (uint8_t *)&dummy_buf);
+                }
+            }
+#endif
+
+          /* We are finished. */
+
+          /* Don't allow any further call backs. */
+
+          pstate->pr_cb->flags   = 0;
+          pstate->pr_cb->priv    = NULL;
+          pstate->pr_cb->event   = NULL;
+
+          /* indicate that the data has been consumed */
+
+          flags &= ~CAN_NEWDATA;
+
+          /* Wake up the waiting thread, returning the number of bytes
+           * actually read.
+           */
+
+          nxsem_post(&pstate->pr_sem);
+        }
+    }
+
+  return flags;
+}
+
+/****************************************************************************
+ * Name: can_recvfrom_result
+ *
+ * Description:
+ *   Evaluate the result of the recv operations
+ *
+ * Input Parameters:
+ *   result   The result of the net_lockedwait operation (may indicate EINTR)
+ *   pstate   A pointer to the state structure to be initialized
+ *
+ * Returned Value:
+ *   The result of the recv operation with errno set appropriately
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static ssize_t can_recvfrom_result(int result,
+                                   FAR struct can_recvfrom_s *pstate)
+{
+  /* Check for a error/timeout detected by the event handler.  Errors are
+   * signaled by negative errno values for the rcv length
+   */
+
+  if (pstate->pr_result < 0)
+    {
+      /* This might return EAGAIN on a timeout */
+
+      return pstate->pr_result;
+    }
+
+  /* If net_lockedwait failed, then we were probably reawakened by a signal.
+   * In this case, net_lockedwait will have returned negated errno
+   * appropriately.
+   */
+
+  if (result < 0)
+    {
+      return result;
+    }
+
+  return pstate->pr_recvlen;
+}
+
+/****************************************************************************
+ * Name: can_recvfrom
+ *
+ * Description:
+ *   recvfrom() receives messages from a socket, and may be used to receive
+ *   data on a socket whether or not it is connection-oriented.
+ *
+ *   If from is not NULL, and the underlying protocol provides the source
+ *   address, this source address is filled in. The argument 'fromlen'
+ *   initialized to the size of the buffer associated with from, and modified
+ *   on return to indicate the actual size of the address stored there.
+ *
+ * Input Parameters:
+ *   psock    A pointer to a NuttX-specific, internal socket structure
+ *   buf      Buffer to receive data
+ *   len      Length of buffer
+ *   flags    Receive flags (ignored)
+ *   from     Address of source (may be NULL)
+ *   fromlen  The length of the address structure
+ *
+ ****************************************************************************/
+
+ssize_t can_recvfrom(FAR struct socket *psock, FAR void *buf,
+                                size_t len, int flags,
+                                FAR struct sockaddr *from,
+                                FAR socklen_t *fromlen)
+{
+  FAR struct can_conn_s *conn;
+  FAR struct net_driver_s *dev;
+  struct can_recvfrom_s state;
+  int ret;
+
+  DEBUGASSERT(psock != NULL && psock->s_conn != NULL && buf != NULL);
+  DEBUGASSERT(from == NULL ||
+              (fromlen != NULL && *fromlen >= sizeof(struct sockaddr_can)));
+
+  conn = (FAR struct can_conn_s *)psock->s_conn;
+
+  if (psock->s_type != SOCK_RAW)
+    {
+      nerr("ERROR: Unsupported socket type: %d\n", psock->s_type);
+      ret = -ENOSYS;
+    }
+
+  net_lock();
+
+  /* Initialize the state structure. */
+
+  memset(&state, 0, sizeof(struct can_recvfrom_s));
+
+  /* This semaphore is used for signaling and, hence, should not have
+   * priority inheritance enabled.
+   */
+
+  nxsem_init(&state.pr_sem, 0, 0); /* Doesn't really fail */
+  nxsem_set_protocol(&state.pr_sem, SEM_PRIO_NONE);
+
+  state.pr_buflen = len;
+  state.pr_buffer = buf;
+  state.pr_sock   = psock;
+
+  /* Handle any any CAN data already buffered in a read-ahead buffer.  NOTE
+   * that there may be read-ahead data to be retrieved even after the
+   * socket has been disconnected.
+   */
+
+  ret = can_readahead(&state);
+  if (ret > 0)
+    {
+      goto errout_with_state;
+    }
+
+  ret = state.pr_recvlen;
+
+  /* Handle non-blocking CAN sockets */
+
+  if (_SS_ISNONBLOCK(psock->s_flags) || (flags & MSG_DONTWAIT) != 0)
+    {
+      /* Return the number of bytes read from the read-ahead buffer if
+       * something was received (already in 'ret'); EAGAIN if not.
+       */
+
+      if (ret < 0)
+        {
+          /* Nothing was received */
+
+          ret = -EAGAIN;
+          goto errout_with_state;
+        }
+    }
+
+  /* Get the device driver that will service this transfer */
+
+  dev  = conn->dev;
+  if (dev == NULL)
+    {
+      ret = -ENODEV;
+      goto errout_with_state;
+    }
+
+  /* Set up the callback in the connection */
+
+  state.pr_cb = can_callback_alloc(dev, conn);
+  if (state.pr_cb)
+    {
+      state.pr_cb->flags  = (CAN_NEWDATA | CAN_POLL);
+      state.pr_cb->priv   = (FAR void *)&state;
+      state.pr_cb->event  = can_recvfrom_eventhandler;
+
+      /* Wait for either the receive to complete or for an error/timeout to
+       * occur. NOTES:  (1) net_lockedwait will also terminate if a signal
+       * is received, (2) the network is locked!  It will be un-locked while
+       * the task sleeps and automatically re-locked when the task restarts.
+       */
+
+      ret = net_lockedwait(&state.pr_sem);
+
+      /* Make sure that no further events are processed */
+
+      can_callback_free(dev, conn, state.pr_cb);
+      ret = can_recvfrom_result(ret, &state);
+    }
+  else
+    {
+      ret = -EBUSY;
+    }
+
+errout_with_state:
+  net_unlock();
+  nxsem_destroy(&state.pr_sem);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: can_recvmsg
+ *
+ * Description:
+ *   recvmsg() receives messages from a socket, and may be used to receive
+ *   data on a socket whether or not it is connection-oriented.
+ *
+ *   If from is not NULL, and the underlying protocol provides the source
+ *   address, this source address is filled in. The argument 'fromlen'
+ *   initialized to the size of the buffer associated with from, and modified
+ *   on return to indicate the actual size of the address stored there.
+ *
+ * Input Parameters:
+ *   psock    A pointer to a NuttX-specific, internal socket structure
+ *   msg      Buffer to receive msg
+ *   flags    Receive flags (ignored)
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_CMSG
+ssize_t can_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
+                    int flags)
+{
+  FAR struct can_conn_s *conn;
+  FAR struct net_driver_s *dev;
+  struct can_recvfrom_s state;
+  int ret;
+
+  DEBUGASSERT(psock != NULL && psock->s_conn != NULL && msg != NULL);
+
+  conn = (FAR struct can_conn_s *)psock->s_conn;
+
+  if (psock->s_type != SOCK_RAW)
+    {
+      nerr("ERROR: Unsupported socket type: %d\n", psock->s_type);
+      ret = -ENOSYS;
+    }
+
+  net_lock();
+
+  /* Initialize the state structure. */
+
+  memset(&state, 0, sizeof(struct can_recvfrom_s));
+
+  /* This semaphore is used for signaling and, hence, should not have
+   * priority inheritance enabled.
+   */
+
+  nxsem_init(&state.pr_sem, 0, 0); /* Doesn't really fail */
+  nxsem_set_protocol(&state.pr_sem, SEM_PRIO_NONE);
+
+  state.pr_buflen = msg->msg_iov->iov_len;
+  state.pr_buffer = msg->msg_iov->iov_base;
+
+#ifdef CONFIG_NET_TIMESTAMP
+  if (psock->s_timestamp && msg->msg_controllen >=
+        (sizeof(struct cmsghdr) + sizeof(struct timeval)))
+    {
+      struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg);
+      state.pr_msglen = sizeof(struct timeval);
+      state.pr_msgbuf = CMSG_DATA(cmsg);
+      cmsg->cmsg_level = SOL_SOCKET;
+      cmsg->cmsg_type = SO_TIMESTAMP;
+      cmsg->cmsg_len = state.pr_msglen;
+      msg->msg_controllen = sizeof(struct cmsghdr) + sizeof(struct timeval);
+    }
+  else
+    {
+      /* Expected behavior is that the msg_controllen becomes 0,
+       * otherwise CMSG_NXTHDR will go into a infinite loop
+       */
+
+      msg->msg_controllen = 0;
+    }
+#endif
+
+  state.pr_sock   = psock;
+
+  /* Handle any any CAN data already buffered in a read-ahead buffer.  NOTE
+   * that there may be read-ahead data to be retrieved even after the
+   * socket has been disconnected.
+   */
+
+  ret = can_readahead(&state);
+  if (ret > 0)
+    {
+#ifdef CONFIG_NET_TIMESTAMP
+      if (psock->s_timestamp)
+        {
+          if (state.pr_msglen == sizeof(struct timeval))
+            {
+              can_readahead_timestamp(conn, state.pr_msgbuf);
+            }
+          else
+            {
+              /* We still have to consume the data otherwise IOB gets full */
+
+              uint8_t dummy_buf[sizeof(struct timeval)];
+              can_readahead_timestamp(conn, (uint8_t *)&dummy_buf);
+            }
+        }
+#endif
+
+      goto errout_with_state;
+    }
+
+  ret = state.pr_recvlen;
+
+  /* Handle non-blocking CAN sockets */
+
+  if (_SS_ISNONBLOCK(psock->s_flags) || (flags & MSG_DONTWAIT) != 0)
+    {
+      /* Return the number of bytes read from the read-ahead buffer if
+       * something was received (already in 'ret'); EAGAIN if not.
+       */
+
+      if (ret < 0)
+        {
+          /* Nothing was received */
+
+          ret = -EAGAIN;
+          goto errout_with_state;
+        }
+    }
+
+  /* Get the device driver that will service this transfer */
+
+  dev  = conn->dev;
+  if (dev == NULL)
+    {
+      ret = -ENODEV;
+      goto errout_with_state;
+    }
+
+  /* Set up the callback in the connection */
+
+  state.pr_cb = can_callback_alloc(dev, conn);
+  if (state.pr_cb)
+    {
+      state.pr_cb->flags  = (CAN_NEWDATA | CAN_POLL);
+      state.pr_cb->priv   = (FAR void *)&state;
+      state.pr_cb->event  = can_recvfrom_eventhandler;
+
+      /* Wait for either the receive to complete or for an error/timeout to
+       * occur. NOTES:  (1) net_lockedwait will also terminate if a signal
+       * is received, (2) the network is locked!  It will be un-locked while
+       * the task sleeps and automatically re-locked when the task restarts.
+       */
+
+      ret = net_lockedwait(&state.pr_sem);
+
+      /* Make sure that no further events are processed */
+
+      can_callback_free(dev, conn, state.pr_cb);
+      ret = can_recvfrom_result(ret, &state);
+    }
+  else
+    {
+      ret = -EBUSY;
+    }
+
+errout_with_state:
+  net_unlock();
+  nxsem_destroy(&state.pr_sem);
+  return ret;
+}
+#endif
+
+#endif /* CONFIG_NET_CAN */
diff --git a/net/can/can_send.c b/net/can/can_send.c
new file mode 100644
index 0000000..3c01684
--- /dev/null
+++ b/net/can/can_send.c
@@ -0,0 +1,441 @@
+/****************************************************************************
+ * net/can/can_send.c
+ *
+ *   Copyright (C) 2014, 2016-2017 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <gn...@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_CAN)
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <arch/irq.h>
+
+#include <nuttx/semaphore.h>
+#include <nuttx/net/netdev.h>
+#include <nuttx/net/net.h>
+#include <nuttx/net/ip.h>
+
+#include "netdev/netdev.h"
+#include "devif/devif.h"
+#include "socket/socket.h"
+#include "can/can.h"
+
+#ifdef CONFIG_NET_CMSG
+#include <sys/time.h>
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure holds the state of the send operation until it can be
+ * operated upon by the event handler.
+ */
+
+struct send_s
+{
+  FAR struct socket      *snd_sock;    /* Points to the parent socket structure */
+  FAR struct devif_callback_s *snd_cb; /* Reference to callback instance */
+  sem_t                   snd_sem;     /* Used to wake up the waiting thread */
+  FAR const uint8_t      *snd_buffer;  /* Points to the buffer of data to send */
+  size_t                  snd_buflen;  /* Number of bytes in the buffer to send */
+#ifdef CONFIG_NET_CMSG
+  size_t                  pr_msglen;   /* Length of msg buffer */
+  FAR uint8_t            *pr_msgbuf;   /* Pointer to msg buffer */
+#endif
+  ssize_t                 snd_sent;    /* The number of bytes sent */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: psock_send_eventhandler
+ ****************************************************************************/
+
+static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev,
+                                        FAR void *pvconn,
+                                        FAR void *pvpriv, uint16_t flags)
+{
+  FAR struct send_s *pstate = (FAR struct send_s *)pvpriv;
+
+  if (pstate)
+    {
+      /* Check if the outgoing packet is available. It may have been claimed
+       * by a send event handler serving a different thread -OR- if the
+       * output buffer currently contains unprocessed incoming data. In
+       * these cases we will just have to wait for the next polling cycle.
+       */
+
+      if (dev->d_sndlen > 0 || (flags & CAN_NEWDATA) != 0)
+        {
+          /* Another thread has beat us sending data or the buffer is busy,
+           * Check for a timeout. If not timed out, wait for the next
+           * polling cycle and check again.
+           */
+
+          /* No timeout. Just wait for the next polling cycle */
+
+          return flags;
+        }
+
+      /* It looks like we are good to send the data */
+
+      else
+        {
+          /* Copy the packet data into the device packet buffer and send it */
+
+          devif_can_send(dev, pstate->snd_buffer, pstate->snd_buflen);
+          pstate->snd_sent = pstate->snd_buflen;
+#ifdef CONFIG_NET_CMSG
+          if (pstate->pr_msglen > 0) /* concat cmsg data after packet */
+            {
+              memcpy(dev->d_buf + pstate->snd_buflen, pstate->pr_msgbuf,
+                      pstate->pr_msglen);
+              dev->d_sndlen = pstate->snd_buflen + pstate->pr_msglen;
+            }
+#endif
+        }
+
+      /* Don't allow any further call backs. */
+
+      pstate->snd_cb->flags    = 0;
+      pstate->snd_cb->priv     = NULL;
+      pstate->snd_cb->event    = NULL;
+
+      /* Wake up the waiting thread */
+
+      nxsem_post(&pstate->snd_sem);
+    }
+
+  return flags;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: psock_can_send
+ *
+ * Description:
+ *   The psock_can_send() call may be used only when the packet socket is in
+ *   a connected state (so that the intended recipient is known).
+ *
+ * Input Parameters:
+ *   psock    An instance of the internal socket structure.
+ *   buf      Data to send
+ *   len      Length of data to send
+ *
+ * Returned Value:
+ *   On success, returns the number of characters sent.  On  error,
+ *   a negated errno value is retruend.  See send() for the complete list
+ *   of return values.
+ *
+ ****************************************************************************/
+
+ssize_t psock_can_send(FAR struct socket *psock, FAR const void *buf,
+                       size_t len)
+{
+  FAR struct net_driver_s *dev;
+  FAR struct can_conn_s *conn;
+  struct send_s state;
+  int ret = OK;
+
+  conn = (FAR struct can_conn_s *)psock->s_conn;
+
+  /* Verify that the sockfd corresponds to valid, allocated socket */
+
+  if (!psock || psock->s_crefs <= 0)
+    {
+      return -EBADF;
+    }
+
+  /* Get the device driver that will service this transfer */
+
+  dev = conn->dev;
+  if (dev == NULL)
+    {
+      return -ENODEV;
+    }
+#if defined(CONFIG_NET_CANPROTO_OPTIONS) && defined(CONFIG_NET_CAN_CANFD)
+
+  if (conn->fd_frames)
+    {
+      if (len != CANFD_MTU && len != CAN_MTU)
+        {
+          return -EINVAL;
+        }
+    }
+#endif
+  else
+    {
+      if (len != CAN_MTU)
+        {
+          return -EINVAL;
+        }
+    }
+
+  /* Perform the send operation */
+
+  /* Initialize the state structure. This is done with the network locked
+   * because we don't want anything to happen until we are ready.
+   */
+
+  net_lock();
+  memset(&state, 0, sizeof(struct send_s));
+
+  /* This semaphore is used for signaling and, hence, should not have
+   * priority inheritance enabled.
+   */
+
+  nxsem_init(&state.snd_sem, 0, 0); /* Doesn't really fail */
+  nxsem_set_protocol(&state.snd_sem, SEM_PRIO_NONE);
+
+  state.snd_sock      = psock;          /* Socket descriptor to use */
+  state.snd_buflen    = len;            /* Number of bytes to send */
+  state.snd_buffer    = buf;            /* Buffer to send from */
+
+  /* Allocate resource to receive a callback */
+
+  state.snd_cb = can_callback_alloc(dev, conn);
+  if (state.snd_cb)
+    {
+      /* Set up the callback in the connection */
+
+      state.snd_cb->flags = CAN_POLL;
+      state.snd_cb->priv  = (FAR void *)&state;
+      state.snd_cb->event = psock_send_eventhandler;
+
+      /* Notify the device driver that new TX data is available. */
+
+      netdev_txnotify_dev(dev);
+
+      /* Wait for the send to complete or an error to occur.
+       * net_lockedwait will also terminate if a signal is received.
+       */
+
+      ret = net_lockedwait(&state.snd_sem);
+
+      /* Make sure that no further events are processed */
+
+      can_callback_free(dev, conn, state.snd_cb);
+    }
+
+  nxsem_destroy(&state.snd_sem);
+  net_unlock();
+
+  /* Check for a errors, Errors are signalled by negative errno values
+   * for the send length
+   */
+
+  if (state.snd_sent < 0)
+    {
+      return state.snd_sent;
+    }
+
+  /* If net_lockedwait failed, then we were probably reawakened by a signal.
+   * In this case, net_lockedwait will have returned negated errno
+   * appropriately.
+   */
+
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* Return the number of bytes actually sent */
+
+  return state.snd_sent;
+}
+
+/****************************************************************************
+ * Name: psock_can_sendmsg
+ *
+ * Description:
+ *   The psock_can_sendmsg() call may be used only when the packet socket is
+ *   in a connected state (so that the intended recipient is known).
+ *
+ * Input Parameters:
+ *   psock    An instance of the internal socket structure.
+ *   msg      msg to send
+ *
+ * Returned Value:
+ *   On success, returns the number of characters sent.  On  error,
+ *   a negated errno value is retruend.  See send() for the complete list
+ *   of return values.
+ *
+ ****************************************************************************/
+
+ssize_t psock_can_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg)
+{
+  FAR struct net_driver_s *dev;
+  FAR struct can_conn_s *conn;
+  struct send_s state;
+  int ret = OK;
+
+  conn = (FAR struct can_conn_s *)psock->s_conn;
+
+  /* Verify that the sockfd corresponds to valid, allocated socket */
+
+  if (!psock || psock->s_crefs <= 0)
+    {
+      return -EBADF;
+    }
+
+  /* Get the device driver that will service this transfer */
+
+  dev = conn->dev;
+  if (dev == NULL)
+    {
+      return -ENODEV;
+    }
+
+#if defined(CONFIG_NET_CANPROTO_OPTIONS) && defined(CONFIG_NET_CAN_CANFD)
+  if (conn->fd_frames)
+    {
+      if (msg->msg_iov->iov_len != CANFD_MTU
+              && msg->msg_iov->iov_len != CAN_MTU)
+        {
+          return -EINVAL;
+        }
+    }
+  else
+#endif
+    {
+      if (msg->msg_iov->iov_len != CAN_MTU)
+        {
+          return -EINVAL;
+        }
+    }
+
+  /* Perform the send operation */
+
+  /* Initialize the state structure. This is done with the network locked
+   * because we don't want anything to happen until we are ready.
+   */
+
+  net_lock();
+  memset(&state, 0, sizeof(struct send_s));
+
+  /* This semaphore is used for signaling and, hence, should not have
+   * priority inheritance enabled.
+   */
+
+  nxsem_init(&state.snd_sem, 0, 0); /* Doesn't really fail */
+  nxsem_set_protocol(&state.snd_sem, SEM_PRIO_NONE);
+
+  state.snd_sock      = psock;                  /* Socket descriptor */
+  state.snd_buflen    = msg->msg_iov->iov_len;  /* bytes to send */
+  state.snd_buffer    = msg->msg_iov->iov_base; /* Buffer to send from */
+
+#ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE
+  if (msg->msg_controllen > sizeof(struct cmsghdr))
+    {
+      struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg);
+      if (conn->tx_deadline && cmsg->cmsg_level == SOL_CAN_RAW
+              && cmsg->cmsg_type == CAN_RAW_TX_DEADLINE
+              && cmsg->cmsg_len == sizeof(struct timeval))
+        {
+          state.pr_msgbuf     = CMSG_DATA(cmsg); /* Buffer to cmsg data */
+          state.pr_msglen     = cmsg->cmsg_len;  /* len of cmsg data */
+        }
+    }
+#endif
+
+  /* Allocate resource to receive a callback */
+
+  state.snd_cb = can_callback_alloc(dev, conn);
+  if (state.snd_cb)
+    {
+      /* Set up the callback in the connection */
+
+      state.snd_cb->flags = CAN_POLL;
+      state.snd_cb->priv  = (FAR void *)&state;
+      state.snd_cb->event = psock_send_eventhandler;
+
+      /* Notify the device driver that new TX data is available. */
+
+      netdev_txnotify_dev(dev);
+
+      /* Wait for the send to complete or an error to occur.
+       * net_lockedwait will also terminate if a signal is received.
+       */
+
+      ret = net_lockedwait(&state.snd_sem);
+
+      /* Make sure that no further events are processed */
+
+      can_callback_free(dev, conn, state.snd_cb);
+    }
+
+  nxsem_destroy(&state.snd_sem);
+  net_unlock();
+
+  /* Check for a errors, Errors are signalled by negative errno values
+   * for the send length
+   */
+
+  if (state.snd_sent < 0)
+    {
+      return state.snd_sent;
+    }
+
+  /* If net_lockedwait failed, then we were probably reawakened by a signal.
+   * In this case, net_lockedwait will have returned negated errno
+   * appropriately.
+   */
+
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* Return the number of bytes actually sent */
+
+  return state.snd_sent;
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_CAN */
diff --git a/net/can/can_setsockopt.c b/net/can/can_setsockopt.c
new file mode 100644
index 0000000..3359e40
--- /dev/null
+++ b/net/can/can_setsockopt.c
@@ -0,0 +1,177 @@
+/****************************************************************************
+ * net/can/can_setsockopt.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/time.h>
+#include <stdint.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <netpacket/can.h>
+
+#include <nuttx/net/net.h>
+#include <nuttx/net/can.h>
+
+#include "socket/socket.h"
+#include "utils/utils.h"
+#include "can/can.h"
+
+#ifdef CONFIG_NET_CANPROTO_OPTIONS
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: can_setsockopt
+ *
+ * Description:
+ *   can_setsockopt() sets the CAN-protocol option specified by the
+ *   'option' argument to the value pointed to by the 'value' argument for
+ *   the socket specified by the 'psock' argument.
+ *
+ *   See <netinet/can.h> for the a complete list of values of CAN protocol
+ *   options.
+ *
+ * Input Parameters:
+ *   psock     Socket structure of socket to operate on
+ *   option    identifies the option to set
+ *   value     Points to the argument value
+ *   value_len The length of the argument value
+ *
+ * Returned Value:
+ *   Returns zero (OK) on success.  On failure, it returns a negated errno
+ *   value to indicate the nature of the error.  See psock_setcockopt() for
+ *   the list of possible error values.
+ *
+ ****************************************************************************/
+
+int can_setsockopt(FAR struct socket *psock, int option,
+                   FAR const void *value, socklen_t value_len)
+{
+  FAR struct can_conn_s *conn;
+  int ret;
+  int count = 0;
+
+  DEBUGASSERT(psock != NULL && value != NULL && psock->s_conn != NULL);
+  conn = (FAR struct can_conn_s *)psock->s_conn;
+
+  if (psock->s_type != SOCK_RAW)
+    {
+      nerr("ERROR:  Not a RAW CAN socket\n");
+      return -ENOTCONN;
+    }
+
+  switch (option)
+    {
+      case CAN_RAW_FILTER:
+        if (value_len == 0)
+          {
+            conn->filter_count = 0;
+            ret = OK;
+          }
+        else if (value_len % sizeof(struct can_filter) != 0)
+          {
+            ret = -EINVAL;
+          }
+        else if (value_len > CONFIG_NET_CAN_RAW_FILTER_MAX *
+                   sizeof(struct can_filter))
+          {
+            ret = -EINVAL;
+          }
+        else
+          {
+        count = value_len / sizeof(struct can_filter);
+
+        for (int i = 0; i < count; i++)
+          {
+        conn->filters[i] = ((struct can_filter *)value)[i];
+          }
+
+        conn->filter_count = count;
+
+            ret = OK;
+          }
+        break;
+
+      case CAN_RAW_ERR_FILTER:
+        break;
+
+      case CAN_RAW_LOOPBACK:
+        if (value_len != sizeof(conn->loopback))
+          {
+            return -EINVAL;
+          }
+
+        conn->loopback = *(FAR int32_t *)value;
+
+        break;
+
+      case CAN_RAW_RECV_OWN_MSGS:
+        if (value_len != sizeof(conn->recv_own_msgs))
+          {
+            return -EINVAL;
+          }
+
+        conn->recv_own_msgs = *(FAR int32_t *)value;
+
+        break;
+
+      case CAN_RAW_FD_FRAMES:
+        if (value_len != sizeof(conn->fd_frames))
+          {
+            return -EINVAL;
+          }
+
+          conn->fd_frames = *(FAR int32_t *)value;
+
+          break;
+
+      case CAN_RAW_JOIN_FILTERS:
+        break;
+
+#ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE
+      case CAN_RAW_TX_DEADLINE:
+        if (value_len != sizeof(conn->tx_deadline))
+          {
+            return -EINVAL;
+          }
+
+        conn->tx_deadline = *(FAR int32_t *)value;
+
+        break;
+#endif
+
+      default:
+        nerr("ERROR: Unrecognized CAN option: %d\n", option);
+        ret = -ENOPROTOOPT;
+        break;
+    }
+
+  return ret;
+}
+
+#endif /* CONFIG_NET_CANPROTO_OPTIONS */
diff --git a/net/netlink/netlink_sockif.c b/net/can/can_sockif.c
similarity index 52%
copy from net/netlink/netlink_sockif.c
copy to net/can/can_sockif.c
index 577d520..d39934f 100644
--- a/net/netlink/netlink_sockif.c
+++ b/net/can/can_sockif.c
@@ -1,35 +1,20 @@
 /****************************************************************************
- * net/netlink/netlink_sockif.c
- *
- *   Copyright (C) 2018-2019 Gregory Nutt. All rights reserved.
- *   Author: Gregory Nutt <gn...@nuttx.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- *    used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * net/can/can_sockif.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
  *
  ****************************************************************************/
 
@@ -54,64 +39,69 @@
 #include <nuttx/wqueue.h>
 #include <nuttx/net/net.h>
 
-#include "netlink/netlink.h"
+#include "can/can.h"
+#include "netdev/netdev.h"
 
-#ifdef CONFIG_NET_NETLINK
+#ifdef CONFIG_NET_CAN
 
 /****************************************************************************
  * Private Function Prototypes
  ****************************************************************************/
 
-static int  netlink_setup(FAR struct socket *psock, int protocol);
-static sockcaps_t netlink_sockcaps(FAR struct socket *psock);
-static void netlink_addref(FAR struct socket *psock);
-static int  netlink_bind(FAR struct socket *psock,
+static int  can_setup(FAR struct socket *psock, int protocol);
+static sockcaps_t can_sockcaps(FAR struct socket *psock);
+static void can_addref(FAR struct socket *psock);
+static int  can_bind(FAR struct socket *psock,
               FAR const struct sockaddr *addr, socklen_t addrlen);
-static int  netlink_getsockname(FAR struct socket *psock,
+static int  can_getsockname(FAR struct socket *psock,
               FAR struct sockaddr *addr, FAR socklen_t *addrlen);
-static int  netlink_getpeername(FAR struct socket *psock,
+static int  can_getpeername(FAR struct socket *psock,
               FAR struct sockaddr *addr, FAR socklen_t *addrlen);
-static int  netlink_listen(FAR struct socket *psock, int backlog);
-static int  netlink_connect(FAR struct socket *psock,
+static int  can_listen(FAR struct socket *psock, int backlog);
+static int  can_connect(FAR struct socket *psock,
               FAR const struct sockaddr *addr, socklen_t addrlen);
-static int  netlink_accept(FAR struct socket *psock,
-              FAR struct sockaddr *addr, FAR socklen_t *addrlen,
-              FAR struct socket *newsock);
-static int  netlink_poll(FAR struct socket *psock, FAR struct pollfd *fds,
+static int  can_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
+              FAR socklen_t *addrlen, FAR struct socket *newsock);
+static int  can_poll_local(FAR struct socket *psock, FAR struct pollfd *fds,
               bool setup);
-static ssize_t netlink_send(FAR struct socket *psock,
+static ssize_t can_send(FAR struct socket *psock,
               FAR const void *buf, size_t len, int flags);
-static ssize_t netlink_sendto(FAR struct socket *psock, FAR const void *buf,
+static ssize_t can_sendto(FAR struct socket *psock, FAR const void *buf,
               size_t len, int flags, FAR const struct sockaddr *to,
               socklen_t tolen);
-static ssize_t netlink_recvfrom(FAR struct socket *psock, FAR void *buf,
-              size_t len, int flags, FAR struct sockaddr *from,
-              FAR socklen_t *fromlen);
-static int netlink_close(FAR struct socket *psock);
+#ifdef CONFIG_NET_CMSG
+static ssize_t can_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
+                    int flags);
+#endif
+static int can_close(FAR struct socket *psock);
 
 /****************************************************************************
  * Public Data
  ****************************************************************************/
 
-const struct sock_intf_s g_netlink_sockif =
+const struct sock_intf_s g_can_sockif =
 {
-  netlink_setup,        /* si_setup */
-  netlink_sockcaps,     /* si_sockcaps */
-  netlink_addref,       /* si_addref */
-  netlink_bind,         /* si_bind */
-  netlink_getsockname,  /* si_getsockname */
-  netlink_getpeername,  /* si_getpeername */
-  netlink_listen,       /* si_listen */
-  netlink_connect,      /* si_connect */
-  netlink_accept,       /* si_accept */
-  netlink_poll,         /* si_poll */
-  netlink_send,         /* si_send */
-  netlink_sendto,       /* si_sendto */
+  can_setup,        /* si_setup */
+  can_sockcaps,     /* si_sockcaps */
+  can_addref,       /* si_addref */
+  can_bind,         /* si_bind */
+  can_getsockname,  /* si_getsockname */
+  can_getpeername,  /* si_getpeername */
+  can_listen,       /* si_listen */
+  can_connect,      /* si_connect */
+  can_accept,       /* si_accept */
+  can_poll_local,   /* si_poll */
+  can_send,         /* si_send */
+  can_sendto,       /* si_sendto */
 #ifdef CONFIG_NET_SENDFILE
-  NULL,                 /* si_sendfile */
+  NULL,             /* si_sendfile */
+#endif
+  can_recvfrom,     /* si_recvfrom */
+#ifdef CONFIG_NET_CMSG
+  can_recvmsg,      /* si_recvmsg */
+  can_sendmsg,      /* si_sendmsg */
 #endif
-  netlink_recvfrom,     /* si_recvfrom */
-  netlink_close         /* si_close */
+  can_close         /* si_close */
 };
 
 /****************************************************************************
@@ -119,7 +109,77 @@ const struct sock_intf_s g_netlink_sockif =
  ****************************************************************************/
 
 /****************************************************************************
- * Name: netlink_setup
+ * Name: can_poll_eventhandler
+ *
+ * Description:
+ *   This function is called to perform the actual CAN receive operation
+ *   via the device interface layer. from can_input()
+ *
+ * Input Parameters:
+ *   dev      The structure of the network driver that caused the event
+ *   conn     The connection structure associated with the socket
+ *   flags    Set of events describing why the callback was invoked
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   This function must be called with the network locked.
+ *
+ ****************************************************************************/
+
+static uint16_t can_poll_eventhandler(FAR struct net_driver_s *dev,
+                                      FAR void *conn,
+                                      FAR void *pvpriv, uint16_t flags)
+{
+  FAR struct can_poll_s *info = (FAR struct can_poll_s *)pvpriv;
+
+  DEBUGASSERT(!info || (info->psock && info->fds));
+
+  /* 'priv' might be null in some race conditions (?) */
+
+  if (info)
+    {
+      pollevent_t eventset = 0;
+
+      /* Check for data or connection availability events. */
+
+      if ((flags & CAN_NEWDATA) != 0)
+        {
+          eventset |= (POLLIN & info->fds->events);
+        }
+
+      /* Check for loss of connection events. */
+
+      if ((flags & NETDEV_DOWN) != 0)
+        {
+          eventset |= (POLLHUP | POLLERR);
+        }
+
+#if 0
+      /* A poll is a sign that we are free to send data. */
+
+      else if ((flags & CAN_POLL) != 0 &&
+                 psock_udp_cansend(info->psock) >= 0)
+        {
+          eventset |= (POLLOUT & info->fds->events);
+        }
+#endif
+
+      /* Awaken the caller of poll() is requested event occurred. */
+
+      if (eventset)
+        {
+          info->fds->revents |= eventset;
+          nxsem_post(info->fds->sem);
+        }
+    }
+
+  return flags;
+}
+
+/****************************************************************************
+ * Name: can_setup
  *
  * Description:
  *   Called for socket() to verify that the provided socket type and
@@ -137,7 +197,7 @@ const struct sock_intf_s g_netlink_sockif =
  *
  ****************************************************************************/
 
-static int netlink_setup(FAR struct socket *psock, int protocol)
+static int can_setup(FAR struct socket *psock, int protocol)
 {
   int domain = psock->s_domain;
   int type = psock->s_type;
@@ -148,24 +208,29 @@ static int netlink_setup(FAR struct socket *psock, int protocol)
 
   switch (protocol)
     {
-#ifdef CONFIG_NETLINK_ROUTE
-      case NETLINK_ROUTE:
+      case 0:            /* INET subsystem for netlib_ifup */
+      case CAN_RAW:      /* RAW sockets */
+      case CAN_BCM:      /* Broadcast Manager */
+      case CAN_TP16:     /* VAG Transport Protocol v1.6 */
+      case CAN_TP20:     /* VAG Transport Protocol v2.0 */
+      case CAN_MCNET:    /* Bosch MCNet */
+      case CAN_ISOTP:    /* ISO 15765-2 Transport Protocol */
+      case CAN_J1939:    /* SAE J1939 */
         break;
-#endif
 
       default:
         return -EPROTONOSUPPORT;
     }
 
-  /* Verify the socket type (domain should always be PF_NETLINK here) */
+  /* Verify the socket type (domain should always be PF_CAN here) */
 
-  if (domain == PF_NETLINK && (type == SOCK_RAW || type == SOCK_DGRAM))
+  if (domain == PF_CAN && (type == SOCK_RAW || type == SOCK_DGRAM))
     {
       /* Allocate the NetLink socket connection structure and save it in the
        * new socket instance.
        */
 
-      FAR struct netlink_conn_s *conn = netlink_alloc();
+      FAR struct can_conn_s *conn = can_alloc();
       if (conn == NULL)
         {
           /* Failed to reserve a connection structure */
@@ -173,6 +238,12 @@ static int netlink_setup(FAR struct socket *psock, int protocol)
           return -ENOMEM;
         }
 
+#ifdef CONFIG_NET_TIMESTAMP
+      /* Store psock in conn se we can read the SO_TIMESTAMP value */
+
+      conn->psock = psock;
+#endif
+
       /* Initialize the connection instance */
 
       conn->protocol = (uint8_t)protocol;
@@ -194,7 +265,7 @@ static int netlink_setup(FAR struct socket *psock, int protocol)
 }
 
 /****************************************************************************
- * Name: netlink_sockcaps
+ * Name: can_sockcaps
  *
  * Description:
  *   Return the bit encoded capabilities of this socket.
@@ -208,7 +279,7 @@ static int netlink_setup(FAR struct socket *psock, int protocol)
  *
  ****************************************************************************/
 
-static sockcaps_t netlink_sockcaps(FAR struct socket *psock)
+static sockcaps_t can_sockcaps(FAR struct socket *psock)
 {
   /* Permit vfcntl to set socket to non-blocking */
 
@@ -216,7 +287,7 @@ static sockcaps_t netlink_sockcaps(FAR struct socket *psock)
 }
 
 /****************************************************************************
- * Name: netlink_addref
+ * Name: can_addref
  *
  * Description:
  *   Increment the reference count on the underlying connection structure.
@@ -230,9 +301,9 @@ static sockcaps_t netlink_sockcaps(FAR struct socket *psock)
  *
  ****************************************************************************/
 
-static void netlink_addref(FAR struct socket *psock)
+static void can_addref(FAR struct socket *psock)
 {
-  FAR struct netlink_conn_s *conn;
+  FAR struct can_conn_s *conn;
 
   DEBUGASSERT(psock != NULL && psock->s_conn != NULL);
 
@@ -242,10 +313,10 @@ static void netlink_addref(FAR struct socket *psock)
 }
 
 /****************************************************************************
- * Name: netlink_bind
+ * Name: can_bind
  *
  * Description:
- *   netlink_bind() gives the socket 'conn' the local address 'addr'. 'addr'
+ *   can_bind() gives the socket 'conn' the local address 'addr'. 'addr'
  *   is 'addrlen' bytes long. Traditionally, this is called "assigning a name
  *   to a socket." When a socket is created with socket, it exists in a name
  *   space (address family) but has no name assigned.
@@ -271,28 +342,34 @@ static void netlink_addref(FAR struct socket *psock)
  *
  ****************************************************************************/
 
-static int netlink_bind(FAR struct socket *psock,
-                        FAR const struct sockaddr *addr, socklen_t addrlen)
+static int can_bind(FAR struct socket *psock,
+                    FAR const struct sockaddr *addr, socklen_t addrlen)
 {
-  FAR struct sockaddr_nl *nladdr;
-  FAR struct netlink_conn_s *conn;
-
+  FAR struct sockaddr_can *canaddr;
+  FAR struct can_conn_s *conn;
   DEBUGASSERT(psock != NULL && psock->s_conn != NULL && addr != NULL &&
-              addrlen >= sizeof(struct sockaddr_nl));
+              addrlen >= sizeof(struct sockaddr_can));
 
   /* Save the address information in the connection structure */
 
-  nladdr = (FAR struct sockaddr_nl *)addr;
-  conn   = (FAR struct netlink_conn_s *)psock->s_conn;
+  canaddr = (FAR struct sockaddr_can *)addr;
+  conn    = (FAR struct can_conn_s *)psock->s_conn;
+
+  /* Bind CAN device to socket */
 
-  conn->pid    = nladdr->nl_pid ? nladdr->nl_pid : getpid();
-  conn->groups = nladdr->nl_groups;
+#ifdef CONFIG_NETDEV_IFINDEX
+  conn->dev = netdev_findbyindex(canaddr->can_ifindex);
+#else
+  char netdev_name[5] = "can0";
+  netdev_name[3] += canaddr->can_ifindex;
+  conn->dev = netdev_findbyname((const char *)&netdev_name);
+#endif
 
   return OK;
 }
 
 /****************************************************************************
- * Name: netlink_getsockname
+ * Name: can_getsockname
  *
  * Description:
  *   The getsockname() function retrieves the locally-bound name of the
@@ -313,36 +390,18 @@ static int netlink_bind(FAR struct socket *psock,
  *
  ****************************************************************************/
 
-static int netlink_getsockname(FAR struct socket *psock,
-                               FAR struct sockaddr *addr,
-                               FAR socklen_t *addrlen)
+static int can_getsockname(FAR struct socket *psock,
+                           FAR struct sockaddr *addr,
+                           FAR socklen_t *addrlen)
 {
-  FAR struct sockaddr_nl *nladdr;
-  FAR struct netlink_conn_s *conn;
-
-  DEBUGASSERT(psock != NULL && psock->s_conn != NULL && addr != NULL &&
-              addrlen != NULL && *addrlen >= sizeof(struct sockaddr_nl));
-
-  conn = (FAR struct netlink_conn_s *)psock->s_conn;
-
-  /* Return the address information in the address structure */
-
-  nladdr = (FAR struct sockaddr_nl *)addr;
-  memset(nladdr, 0, sizeof(struct sockaddr_nl));
-
-  nladdr->nl_family = AF_NETLINK;
-  nladdr->nl_pid    = conn->pid;
-  nladdr->nl_groups = conn->groups;
-
-  *addrlen = sizeof(struct sockaddr_nl);
-  return OK;
+  return -EAFNOSUPPORT;
 }
 
 /****************************************************************************
- * Name: netlink_getpeername
+ * Name: can_getpeername
  *
  * Description:
- *   The netlink_getpeername() function retrieves the remote-connected name
+ *   The can_getpeername() function retrieves the remote-connected name
  *   of the specified packet socket, stores this address in the sockaddr
  *   structure pointed to by the 'addr' argument, and stores the length of
  *   this address in the object pointed to by the 'addrlen' argument.
@@ -366,33 +425,15 @@ static int netlink_getsockname(FAR struct socket *psock,
  *
  ****************************************************************************/
 
-static int netlink_getpeername(FAR struct socket *psock,
-                               FAR struct sockaddr *addr,
-                               FAR socklen_t *addrlen)
+static int can_getpeername(FAR struct socket *psock,
+                           FAR struct sockaddr *addr,
+                           FAR socklen_t *addrlen)
 {
-  FAR struct sockaddr_nl *nladdr;
-  FAR struct netlink_conn_s *conn;
-
-  DEBUGASSERT(psock != NULL && psock->s_conn != NULL && addr != NULL &&
-              addrlen != NULL && *addrlen >= sizeof(struct sockaddr_nl));
-
-  conn = (FAR struct netlink_conn_s *)psock->s_conn;
-
-  /* Return the address information in the address structure */
-
-  nladdr = (FAR struct sockaddr_nl *)addr;
-  memset(nladdr, 0, sizeof(struct sockaddr_nl));
-
-  nladdr->nl_family = AF_NETLINK;
-  nladdr->nl_pid    = conn->dst_pid;
-  nladdr->nl_groups = conn->dst_groups;
-
-  *addrlen = sizeof(struct sockaddr_nl);
-  return OK;
+  return -EOPNOTSUPP;
 }
 
 /****************************************************************************
- * Name: netlink_listen
+ * Name: can_listen
  *
  * Description:
  *   To accept connections, a socket is first created with psock_socket(), a
@@ -417,19 +458,20 @@ static int netlink_getpeername(FAR struct socket *psock,
  *
  ****************************************************************************/
 
-static int netlink_listen(FAR struct socket *psock, int backlog)
+static int can_listen(FAR struct socket *psock, int backlog)
 {
   return -EOPNOTSUPP;
 }
 
 /****************************************************************************
- * Name: netlink_connect
+ * Name: can_connect
  *
  * Description:
- *   Perform a netlink connection
+ *   Perform a can connection
  *
  * Input Parameters:
- *   psock   A reference to the structure of the socket to be connected
+ *   psock   A reference to the socket structure of the socket
+ *           to be connected
  *   addr    The address of the remote server to connect to
  *   addrlen Length of address buffer
  *
@@ -440,32 +482,18 @@ static int netlink_listen(FAR struct socket *psock, int backlog)
  *
  ****************************************************************************/
 
-static int netlink_connect(FAR struct socket *psock,
-                           FAR const struct sockaddr *addr,
-                           socklen_t addrlen)
+static int can_connect(FAR struct socket *psock,
+                       FAR const struct sockaddr *addr,
+                       socklen_t addrlen)
 {
-  FAR struct sockaddr_nl *nladdr;
-  FAR struct netlink_conn_s *conn;
-
-  DEBUGASSERT(psock != NULL && psock->s_conn != NULL && addr != NULL &&
-              addrlen >= sizeof(struct sockaddr_nl));
-
-  /* Save the address information in the connection structure */
-
-  nladdr = (FAR struct sockaddr_nl *)addr;
-  conn   = (FAR struct netlink_conn_s *)psock->s_conn;
-
-  conn->dst_pid    = nladdr->nl_pid;
-  conn->dst_groups = nladdr->nl_groups;
-
-  return OK;
+  return -EOPNOTSUPP;
 }
 
 /****************************************************************************
- * Name: netlink_accept
+ * Name: can_accept
  *
  * Description:
- *   The netlink_accept function is used with connection-based socket
+ *   The can_accept function is used with connection-based socket
  *   types (SOCK_STREAM, SOCK_SEQPACKET and SOCK_RDM). It extracts the first
  *   connection request on the queue of pending connections, creates a new
  *   connected socket with mostly the same properties as 'sockfd', and
@@ -484,7 +512,7 @@ static int netlink_connect(FAR struct socket *psock,
  *   actual length of the address returned.
  *
  *   If no pending connections are present on the queue, and the socket is
- *   not marked as non-blocking, accept blocks the caller until a
+ *   not marked as non-blocking, inet_accept blocks the caller until a
  *   connection is present. If the socket is marked non-blocking and no
  *   pending connections are present on the queue, inet_accept returns
  *   EAGAIN.
@@ -505,63 +533,14 @@ static int netlink_connect(FAR struct socket *psock,
  *
  ****************************************************************************/
 
-static int netlink_accept(FAR struct socket *psock,
-                          FAR struct sockaddr *addr, FAR socklen_t *addrlen,
-                          FAR struct socket *newsock)
+static int can_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
+                      FAR socklen_t *addrlen, FAR struct socket *newsock)
 {
   return -EOPNOTSUPP;
 }
 
 /****************************************************************************
- * Name: netlink_response_available
- *
- * Description:
- *   Handle a Netlink response available notification.
- *
- * Input Parameters:
- *   Standard work handler parameters
- *
- * Returned Value:
- *   None
- *
- ****************************************************************************/
-
-static void netlink_response_available(FAR void *arg)
-{
-  FAR struct netlink_conn_s *conn = arg;
-
-  DEBUGASSERT(conn != NULL);
-
-  /* The following should always be true ... but maybe not in some race
-   * condition?
-   */
-
-  sched_lock();
-  net_lock();
-
-  if (conn->pollsem != NULL && conn->pollevent != NULL)
-    {
-      /* Wake up the poll() with POLLIN */
-
-       *conn->pollevent |= POLLIN;
-       nxsem_post(conn->pollsem);
-    }
-  else
-    {
-      nwarn("WARNING: Missing references in connection.\n");
-    }
-
-  /* Allow another poll() */
-
-  conn->pollsem   = NULL;
-  conn->pollevent = NULL;
-
-  net_unlock();
-  sched_unlock();
-}
-
-/****************************************************************************
- * Name: netlink_poll
+ * Name: can_poll_local
  *
  * Description:
  *   The standard poll() operation redirects operations on socket descriptors
@@ -583,97 +562,124 @@ static void netlink_response_available(FAR void *arg)
  *
  ****************************************************************************/
 
-static int netlink_poll(FAR struct socket *psock, FAR struct pollfd *fds,
-                        bool setup)
+static int can_poll_local(FAR struct socket *psock, FAR struct pollfd *fds,
+                          bool setup)
 {
-  FAR struct netlink_conn_s *conn;
+  FAR struct can_conn_s *conn;
+  FAR struct can_poll_s *info;
+  FAR struct devif_callback_s *cb;
   int ret = OK;
 
   DEBUGASSERT(psock != NULL && psock->s_conn != NULL);
-  conn = (FAR struct netlink_conn_s *)psock->s_conn;
+  conn = (FAR struct can_conn_s *)psock->s_conn;
+  info = conn->pollinfo;
+
+  /* FIXME add NETDEV_DOWN support */
 
   /* Check if we are setting up or tearing down the poll */
 
   if (setup)
     {
-      /* If POLLOUT is selected, return immediately (maybe) */
+      net_lock();
+
+      info->dev = conn->dev;
+
+      cb = can_callback_alloc(info->dev, conn);
+      if (cb == NULL)
+        {
+          ret = -EBUSY;
+          goto errout_with_lock;
+        }
+
+      /* Initialize the poll info container */
 
-      pollevent_t revents = POLLOUT;
+      info->psock  = psock;
+      info->fds    = fds;
+      info->cb     = cb;
 
-      /* If POLLIN is selected and a response is available, return
-       * immediately (maybe).
+      /* Initialize the callback structure.  Save the reference to the info
+       * structure as callback private data so that it will be available
+       * during callback processing.
        */
 
-      net_lock();
-      if (netlink_check_response(conn))
+      cb->flags    = NETDEV_DOWN;
+      cb->priv     = (FAR void *)info;
+      cb->event    = can_poll_eventhandler;
+
+      if ((fds->events & POLLOUT) != 0)
+        {
+          cb->flags |= CAN_POLL;
+        }
+
+      if ((fds->events & POLLIN) != 0)
         {
-          revents |= POLLIN;
+          cb->flags |= CAN_NEWDATA;
         }
 
-      /* But return ONLY if POLLIN and/or POLLIN are included in the
-       * requested event set.
+      /* Save the reference in the poll info structure as fds private as well
+       * for use during poll teardown as well.
        */
 
-      revents &= fds->events;
-      if (revents != 0)
+      fds->priv = (FAR void *)info;
+
+      /* Check for read data availability now */
+
+      if (!IOB_QEMPTY(&conn->readahead))
         {
-          fds->revents = revents;
-          nxsem_post(fds->sem);
-          net_unlock();
-          return OK;
+          /* Normal data may be read without blocking. */
+
+          fds->revents |= (POLLRDNORM & fds->events);
         }
 
-      /* Set up to be notified when a response is available if POLLIN is
-       * requested.
-       */
+    #if 0
+      if (psock_udp_cansend(psock) >= 0)
+        {
+          /* Normal data may be sent without blocking (at least one byte). */
 
-      if ((fds->events & POLLIN) != 0)
+          fds->revents |= (POLLWRNORM & fds->events);
+        }
+    #endif
+
+      /* Check if any requested events are already in effect */
+
+      if (fds->revents != 0)
         {
-          /* Some limitations:  There can be only a single outstanding POLLIN
-           * on the Netlink connection.
-           */
-
-          if (conn->pollsem != NULL || conn->pollevent != NULL)
-            {
-              nerr("ERROR: Multiple polls() on socket not supported.\n");
-              net_unlock();
-              return -EBUSY;
-            }
-
-          /* Set up the notification */
-
-          conn->pollsem    = fds->sem;
-          conn->pollevent  = &fds->revents;
-
-          ret = netlink_notifier_setup(netlink_response_available,
-                                       conn, conn);
-          if (ret < 0)
-            {
-              nerr("ERROR: netlink_notifier_setup() failed: %d\n", ret);
-              conn->pollsem   = NULL;
-              conn->pollevent = NULL;
-            }
+          /* Yes.. then signal the poll logic */
+
+          nxsem_post(fds->sem);
         }
 
+errout_with_lock:
       net_unlock();
     }
   else
     {
-      /* Cancel any response notifications */
+      info = (FAR struct can_poll_s *)fds->priv;
 
-      ret = netlink_notifier_teardown(conn);
-      conn->pollsem   = NULL;
-      conn->pollevent = NULL;
+      if (info != NULL)
+        {
+          /* Cancel any response notifications */
+
+          can_callback_free(info->dev, conn, info->cb);
+
+          /* Release the poll/select data slot */
+
+          info->fds->priv = NULL;
+
+          /* Then free the poll info container */
+
+          info->psock = NULL;
+        }
     }
 
   return ret;
 }
 
 /****************************************************************************
- * Name: netlink_send
+ * Name: can_send
  *
  * Description:
- *   The netlink_send() call may be used only when the socket is in
+ *   The can_send() call may be used only when the socket is in
  *   a connected state  (so that the intended recipient is known).
  *
  * Input Parameters:
@@ -689,34 +695,33 @@ static int netlink_poll(FAR struct socket *psock, FAR struct pollfd *fds,
  *
  ****************************************************************************/
 
-static ssize_t netlink_send(FAR struct socket *psock, FAR const void *buf,
-                            size_t len, int flags)
+static ssize_t can_send(FAR struct socket *psock, FAR const void *buf,
+                        size_t len, int flags)
 {
-  FAR struct netlink_conn_s *conn;
-  struct sockaddr_nl nladdr;
-
-  DEBUGASSERT(psock != NULL && psock->s_conn != NULL && buf != NULL);
-
-  /* Get the underlying connection structure */
+  ssize_t ret;
 
-  conn = (FAR struct netlink_conn_s *)psock->s_conn;
+  /* Only SOCK_RAW is supported */
 
-  /* Format the address */
+  if (psock->s_type == SOCK_RAW)
+    {
+      /* Raw packet send */
 
-  nladdr.nl_family = AF_NETLINK;
-  nladdr.nl_pad    = 0;
-  nladdr.nl_pid    = conn->dst_pid;
-  nladdr.nl_groups = conn->dst_groups;
+      ret = psock_can_send(psock, buf, len);
+    }
+  else
+    {
+      /* EDESTADDRREQ.  Signifies that the socket is not connection-mode and
+       * no peer address is set.
+       */
 
-  /* Then let sendto() perform the actual send operation */
+      ret = -EDESTADDRREQ;
+    }
 
-  return netlink_sendto(psock, buf, len, flags,
-                        (FAR const struct sockaddr *)&nladdr,
-                        sizeof(struct sockaddr_nl));
+  return ret;
 }
 
 /****************************************************************************
- * Name: netlink_sendto
+ * Name: can_sendto
  *
  * Description:
  *   If sendto() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET)
@@ -725,7 +730,8 @@ static ssize_t netlink_send(FAR struct socket *psock, FAR const void *buf,
  *   returned when the socket was not actually connected.
  *
  * Input Parameters:
- *   psock    A reference to the structure of the socket to be connected
+ *   psock    A reference to the socket structure of the socket
+ *            to be connected
  *   buf      Data to send
  *   len      Length of data to send
  *   flags    Send flags (ignored)
@@ -739,119 +745,60 @@ static ssize_t netlink_send(FAR struct socket *psock, FAR const void *buf,
  *
  ****************************************************************************/
 
-static ssize_t netlink_sendto(FAR struct socket *psock, FAR const void *buf,
-                              size_t len, int flags,
-                              FAR const struct sockaddr *to, socklen_t tolen)
+static ssize_t can_sendto(FAR struct socket *psock, FAR const void *buf,
+                          size_t len, int flags,
+                          FAR const struct sockaddr *to, socklen_t tolen)
 {
-  FAR struct netlink_conn_s *conn;
-  FAR struct nlmsghdr *nlmsg;
-  int ret;
-
-  DEBUGASSERT(psock != NULL && psock->s_conn != NULL && buf != NULL &&
-              to != NULL && tolen >= sizeof(struct sockaddr_nl));
-
-  conn = (FAR struct netlink_conn_s *)psock->s_conn;
-
-  /* Get a reference to the netlink message */
-
-  nlmsg = (FAR struct nlmsghdr *)buf;
-  DEBUGASSERT(nlmsg->nlmsg_len >= sizeof(struct nlmsghdr));
-
-  switch (conn->protocol)
-    {
-#ifdef CONFIG_NETLINK_ROUTE
-      case NETLINK_ROUTE:
-        ret = netlink_route_sendto(conn, nlmsg, len, flags,
-                                   (FAR struct sockaddr_nl *)to,
-                                   tolen);
-        break;
-#endif
-
-      default:
-       ret = -EOPNOTSUPP;
-       break;
-    }
-
-  return ret;
+  nerr("ERROR: sendto() not supported for raw packet sockets\n");
+  return -EAFNOSUPPORT;
 }
 
 /****************************************************************************
- * Name: netlink_recvfrom
+ * Name: can_sendmsg
  *
  * Description:
- *   recvfrom() receives messages from a socket, and may be used to receive
- *   data on a socket whether or not it is connection-oriented.
- *
- *   If from is not NULL, and the underlying protocol provides the source
- *   address, this source address is filled in. The argument 'fromlen'
- *   initialized to the size of the buffer associated with from, and modified
- *   on return to indicate the actual size of the address stored there.
+ *   The can_sendmsg() send a CAN frame to psock
  *
  * Input Parameters:
- *   psock    A pointer to a NuttX-specific, internal socket structure
- *   buf      Buffer to receive data
- *   len      Length of buffer
- *   flags    Receive flags (ignored)
- *   from     Address of source (may be NULL)
- *   fromlen  The length of the address structure
+ *   psock - An instance of the internal socket structure.
+ *   msg   - CAN frame and optional CMSG
+ *   flags - Send flags (ignored)
+ *
+ * Returned Value:
+ *   On success, returns the number of characters sent.  On  error, a negated
+ *   errno value is returned (see send() for the list of appropriate error
+ *   values.
  *
  ****************************************************************************/
-
-static ssize_t netlink_recvfrom(FAR struct socket *psock, FAR void *buf,
-                                size_t len, int flags,
-                                FAR struct sockaddr *from,
-                                FAR socklen_t *fromlen)
+#ifdef CONFIG_NET_CMSG
+static ssize_t can_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
+                    int flags)
 {
-  FAR struct netlink_response_s *entry;
-
-  DEBUGASSERT(psock != NULL && psock->s_conn != NULL && buf != NULL);
-  DEBUGASSERT(from == NULL ||
-              (fromlen != NULL && *fromlen >= sizeof(struct sockaddr_nl)));
+  ssize_t ret;
 
-  /* Find the response to this message.  The return value */
+  /* Only SOCK_RAW is supported */
 
-  entry = netlink_tryget_response(psock->s_conn);
-  if (entry == NULL)
+  if (psock->s_type == SOCK_RAW)
     {
-      /* No response is variable, but presumably, one is expected.  Check
-       * if the socket has been configured for non-blocking operation.
-       */
+      /* Raw packet send */
 
-      if (_SS_ISNONBLOCK(psock->s_flags) || (flags & MSG_DONTWAIT) != 0)
-        {
-          return -EAGAIN;
-        }
-
-      /* Wait for the response.  This should always succeed. */
-
-      entry = netlink_get_response(psock->s_conn);
-      DEBUGASSERT(entry != NULL);
-      if (entry == NULL)
-        {
-          return -EPIPE;
-        }
+      ret = psock_can_sendmsg(psock, msg);
     }
-
-  if (len > entry->msg.nlmsg_len)
+  else
     {
-      len = entry->msg.nlmsg_len;
-    }
-
-  /* Copy the payload to the user buffer */
-
-  memcpy(buf, &entry->msg, len);
-  kmm_free(entry);
+      /* EDESTADDRREQ.  Signifies that the socket is not connection-mode and
+       * no peer address is set.
+       */
 
-  if (from != NULL)
-    {
-      netlink_getpeername(psock, from, fromlen);
+      ret = -EDESTADDRREQ;
     }
 
-  return len;
+  return ret;
 }
+#endif
 
 /****************************************************************************
- * Name: netlink_close
+ * Name: can_close
  *
  * Description:
  *   Performs the close operation on a NetLink socket instance
@@ -866,12 +813,12 @@ static ssize_t netlink_recvfrom(FAR struct socket *psock, FAR void *buf,
  *
  ****************************************************************************/
 
-static int netlink_close(FAR struct socket *psock)
+static int can_close(FAR struct socket *psock)
 {
-  FAR struct netlink_conn_s *conn = psock->s_conn;
+  FAR struct can_conn_s *conn = psock->s_conn;
   int ret = OK;
 
-  /* Perform some pre-close operations for the NETLINK socket type. */
+  /* Perform some pre-close operations for the CAN socket type. */
 
   /* Is this the last reference to the connection structure (there
    * could be more if the socket was dup'ed).
@@ -879,16 +826,20 @@ static int netlink_close(FAR struct socket *psock)
 
   if (conn->crefs <= 1)
     {
+      /* Yes... inform user-space daemon of socket close. */
+
+#warning Missing logic
+
       /* Free the connection structure */
 
       conn->crefs = 0;
-      netlink_free(psock->s_conn);
+      can_free(psock->s_conn);
 
       if (ret < 0)
         {
           /* Return with error code, but free resources. */
 
-          nerr("ERROR: netlink_close failed: %d\n", ret);
+          nerr("ERROR: can_close failed: %d\n", ret);
           return ret;
         }
     }
@@ -902,4 +853,4 @@ static int netlink_close(FAR struct socket *psock)
   return ret;
 }
 
-#endif /* CONFIG_NET_NETLINK */
+#endif /* CONFIG_NET_CAN */
diff --git a/net/devif/Make.defs b/net/devif/Make.defs
index 714a0ce..492c7d8 100644
--- a/net/devif/Make.defs
+++ b/net/devif/Make.defs
@@ -66,6 +66,10 @@ ifeq ($(CONFIG_NET_PKT),y)
 NET_CSRCS += devif_pktsend.c
 endif
 
+ifeq ($(CONFIG_NET_CAN),y)
+NET_CSRCS += devif_cansend.c
+endif
+
 # Include network device interface build support
 
 DEPPATH += --dep-path devif
diff --git a/net/devif/devif.h b/net/devif/devif.h
index cbe1a00..1a95011 100644
--- a/net/devif/devif.h
+++ b/net/devif/devif.h
@@ -68,31 +68,32 @@
  *
  *   TCP_ACKDATA      IN: Signifies that the outstanding data was ACKed and
  *                        the socket layer should send out new data instead
- *                        of retransmitting the last data (TCP only)
+ *                        of retransmitting the last data. (TCP only)
  *                   OUT: Input state must be preserved on output.
  *
  *   TCP_NEWDATA      IN: Set to indicate that the peer has sent us new data.
- *   UDP_NEWDATA     OUT: Cleared (only) by the socket layer logic to indicate
- *   ICMP_NEWDATA         that the new data was consumed, suppressing further
- *   ICMPv6_NEWDATA       attempts to process the new data.
- *   PKT_NEWDATA
+ *   UDP_NEWDATA     OUT: Cleared (only) by the socket layer logic to
+ *   ICMP_NEWDATA         indicate that the new data was consumed,
+ *   ICMPv6_NEWDATA       suppressing further attempts to process the new
+ *   PKT_NEWDATA          data.
  *   BLUETOOTH_NEWDATA
  *   IEEE802154_NEWDATA
  *
  *   TCP_SNDACK       IN: Not used; always zero
- *                   OUT: Set by the socket layer if the new data was consumed
- *                        and an ACK should be sent in the response. (TCP only)
+ *                   OUT: Set by the socket layer if the new data was
+ *                        consumed and an ACK should be sent in the response.
+ *                        (TCP only)
  *
  *   TCP_REXMIT       IN: Tells the socket layer to retransmit the data that
  *                        was last sent. (TCP only)
  *                   OUT: Not used
  *
- *   TCP_POLL        IN:  Used for polling the socket layer.  This is provided
- *   UDP_POLL             periodically from the drivers to support (1) timed
- *   PKT_POLL             operations, and (2) to check if the socket layer has
- *   BLUETOOTH_POLL       data that it wants to send.  These are socket oriented
- *   IEEE802154_POLL      callbacks where the context depends on the specific
- *                        set
+ *   TCP_POLL        IN:  Used for polling the socket layer.  This is
+ *   UDP_POLL             provided periodically from the drivers to support
+ *   PKT_POLL             (1) timed operations, and (2) to check if the
+ *   BLUETOOTH_POLL       socket layer has data that it wants to send.
+ *   IEEE802154_POLL      These are socket oriented callbacks where the
+ *                        context depends on the specific set.
  *                   OUT: Not used
  *
  *   TCP_BACKLOG      IN: There is a new connection in the backlog list set
@@ -104,14 +105,15 @@
  *                   OUT: The socket layer signals that it wants to close the
  *                        connection. (TCP only)
  *
- *   TCP_ABORT        IN: The remote host has aborted the connection, thus the
- *                        connection has gone away. (TCP only)
+ *   TCP_ABORT        IN: The remote host has aborted the connection, thus
+ *                        the connection has gone away. (TCP only)
  *                   OUT: The socket layer signals that it wants to abort the
  *                        connection. (TCP only)
  *
- *   TCP_CONNECTED    IN: We have got a connection from a remote host and have
- *                        set up a new connection for it, or an active connection
- *                        has been successfully established. (TCP only)
+ *   TCP_CONNECTED    IN: We have got a connection from a remote host and
+ *                        have set up a new connection for it, or an active
+ *                        connection has been successfully established.
+ *                        (TCP only)
  *                   OUT: Not used
  *
  *   TCP_TIMEDOUT     IN: The connection has been aborted due to too many
@@ -121,37 +123,38 @@
  * Device Specific Events:  These are events that may be notified through
  * callback lists residing in the network device structure.
  *
- *   ARP_POLL         IN: Used for polling the socket layer.  This is provided
- *                        periodically from the drivers to support (1) timed
- *                        operations, and (2) to check if the ARP layer needs
- *                        to send an ARP request.  This is a device oriented
- *                        event, not associated with a socket.
+ *   ARP_POLL         IN: Used for polling the socket layer.  This is
+ *                        provided periodically from the drivers to support
+ *                        (1) timed operations, and (2) to check if the ARP
+ *                        layer needs to send an ARP request.  This is a
+ *                        device oriented event, not associated with a
+ *                        socket.
  *                   OUT: Not used
  *
- *   ICMP_POLL        IN: Used for polling the socket layer.  This is provided
- *                        periodically from the drivers to support (1) timed
- *                        operations, and (2) to check if the ICMP layer needs
- *                        to send an ARP request.  This is a device oriented
- *                        event, not associated with a socket.  This differs
- *                        from ICMPv6_POLL only in that the appdata pointer
- *                        is set differently
+ *   ICMP_POLL        IN: Used for polling the socket layer.  This is
+ *                        provided periodically from the drivers to support
+ *                        (1) timed operations, and (2) to check if the ICMP
+ *                        layer needs to send an ARP request.  This is a
+ *                        device oriented event, not associated with a
+ *                        socket.  This differs from ICMPv6_POLL only in that
+ *                        the appdata pointer is set differently.
  *                   OUT: Not used
  *
- *   ICMPv6_POLL      IN: Used for polling the socket layer.  This is provided
- *                        periodically from the drivers to support (1) timed
- *                        operations, and (2) to check if the ICMP layer needs
- *                        to send an ARP request.  This is a device oriented
- *                        event, not associated with a socket.  This differs
- *                        from ICMP_POLL only in that the appdata pointer
- *                        is set differently
+ *   ICMPv6_POLL      IN: Used for polling the socket layer.  This is
+ *                        provided periodically from the drivers to support
+ *                        (1) timed operations, and (2) to check if the ICMP
+ *                        layer needs to send an ARP request.  This is a
+ *                        device oriented event, not associated with a
+ *                        socket.  This differs from ICMP_POLL only in that
+ *                        the appdata pointer is set differently.
  *                   OUT: Not used
  *
  *   IPFWD_POLL       IN: Used for polling for forwarded packets layer.  This
- *                        is provided periodically from the drivers to support
- *                        to check if there is a packet waiting to be forward
- *                        on the device.  This is a device oriented event,
- *                        not associated with a socket.  The appdata pointer
- *                        The appdata pointer is not used in this case.
+ *                        is provided periodically from the drivers to
+ *                        support to check if there is a packet waiting to be
+ *                        forward on the device.  This is a device oriented
+ *                        event, not associated with a socket.  The appdata
+ *                        pointer is not used in this case.
  *                   OUT: Not used
  *
  *   NETDEV_DOWN:     IN: The network device has been taken down.
@@ -168,6 +171,7 @@
 #define BLUETOOTH_NEWDATA  TCP_NEWDATA
 #define IEEE802154_NEWDATA TCP_NEWDATA
 #define PKT_NEWDATA        TCP_NEWDATA
+#define CAN_NEWDATA        TCP_NEWDATA
 #define WPAN_NEWDATA       TCP_NEWDATA
 #define IPFWD_NEWDATA      TCP_NEWDATA
 #define TCP_SNDACK         (1 << 2)
@@ -175,6 +179,7 @@
 #define TCP_POLL           (1 << 4)
 #define UDP_POLL           TCP_POLL
 #define PKT_POLL           TCP_POLL
+#define CAN_POLL           TCP_POLL
 #define BLUETOOTH_POLL     TCP_POLL
 #define IEEE802154_POLL    TCP_POLL
 #define WPAN_POLL          TCP_POLL
@@ -492,11 +497,32 @@ void devif_iob_send(FAR struct net_driver_s *dev, FAR struct iob_s *buf,
  *
  ****************************************************************************/
 
-#ifdef CONFIG_NET_PKT
+#if defined(CONFIG_NET_PKT)
 void devif_pkt_send(FAR struct net_driver_s *dev, FAR const void *buf,
                     unsigned int len);
 #endif
 
+/****************************************************************************
+ * Name: devif_can_send
+ *
+ * Description:
+ *   Called from socket logic in order to send a raw packet in response to
+ *   an xmit or poll request from the network interface driver.
+ *
+ *   This is almost identical to calling devif_send() except that the data to
+ *   be sent is copied into dev->d_buf (vs. dev->d_appdata), since there is
+ *   no header on the data.
+ *
+ * Assumptions:
+ *   This function must be called with the network locked.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_CAN)
+void devif_can_send(FAR struct net_driver_s *dev, FAR const void *buf,
+                    unsigned int len);
+#endif
+
 #undef EXTERN
 #ifdef __cplusplus
 }
diff --git a/net/local/local_sendpacket.c b/net/devif/devif_cansend.c
similarity index 55%
copy from net/local/local_sendpacket.c
copy to net/devif/devif_cansend.c
index 68dfac6..43570f2 100644
--- a/net/local/local_sendpacket.c
+++ b/net/devif/devif_cansend.c
@@ -1,7 +1,7 @@
 /****************************************************************************
- * net/local/local_sendpacket.c
+ * net/devif/devif_cansend.c
  *
- *   Copyright (C) 2015, 2017 Gregory Nutt. All rights reserved.
+ *   Copyright (C) 2014 Gregory Nutt. All rights reserved.
  *   Author: Gregory Nutt <gn...@nuttx.org>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -39,131 +39,75 @@
 
 #include <nuttx/config.h>
 
-#include <sys/types.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <errno.h>
+#include <string.h>
 #include <assert.h>
 #include <debug.h>
 
-#include <nuttx/fs/fs.h>
+#include <nuttx/net/netdev.h>
 
-#include "local/local.h"
-
-#if defined(CONFIG_NET) && defined(CONFIG_NET_LOCAL)
+#if defined(CONFIG_NET_CAN)
 
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
 
-#define LOCAL_PREAMBLE_SIZE 8
+/****************************************************************************
+ * Private Type Declarations
+ ****************************************************************************/
 
 /****************************************************************************
- * Private Data
+ * Private Function Prototypes
  ****************************************************************************/
 
-static const uint8_t g_preamble[LOCAL_PREAMBLE_SIZE] =
-{
-  LOCAL_SYNC_BYTE, LOCAL_SYNC_BYTE, LOCAL_SYNC_BYTE, LOCAL_SYNC_BYTE,
-  LOCAL_SYNC_BYTE, LOCAL_SYNC_BYTE, LOCAL_SYNC_BYTE, LOCAL_END_BYTE
-};
+/****************************************************************************
+ * Public Constant Data
+ ****************************************************************************/
 
 /****************************************************************************
- * Private Functions
+ * Public Data
  ****************************************************************************/
 
 /****************************************************************************
- * Name: local_fifo_write
- *
- * Description:
- *   Write a data on the write-only FIFO.
- *
- * Input Parameters:
- *   filep    File structure of write-only FIFO.
- *   buf      Data to send
- *   len      Length of data to send
- *
- * Returned Value:
- *   Zero is returned on success; a negated errno value is returned on any
- *   failure.
- *
+ * Private Constant Data
  ****************************************************************************/
 
-static int local_fifo_write(FAR struct file *filep, FAR const uint8_t *buf,
-                            size_t len)
-{
-  ssize_t nwritten;
-
-  while (len > 0)
-    {
-      nwritten = file_write(filep, buf, len);
-      if (nwritten < 0)
-        {
-          if (nwritten != -EINTR)
-            {
-              nerr("ERROR: nx_write failed: %d\n", nwritten);
-              return (int)nwritten;
-            }
-
-          ninfo("Ignoring signal\n");
-        }
-      else
-        {
-          DEBUGASSERT(nwritten > 0 && nwritten <= len);
-          len -= nwritten;
-          buf += nwritten;
-        }
-    }
-
-  return OK;
-}
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
 
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
 /****************************************************************************
- * Name: local_send_packet
+ * Name: devif_can_send
  *
  * Description:
- *   Send a packet on the write-only FIFO.
+ *   Called from socket logic in order to send a can packet in response to
+ *   an xmit or poll request from the network interface driver.
  *
- * Input Parameters:
- *   filep    File structure of write-only FIFO.
- *   buf      Data to send
- *   len      Length of data to send
+ *   This is almost identical to calling devif_send() except that the data to
+ *   be sent is copied into dev->d_buf (vs. dev->d_appdata), since there is
+ *   no header on the data.
  *
- * Returned Value:
- *   Zero is returned on success; a negated errno value is returned on any
- *   failure.
+ * Assumptions:
+ *   Called with the network locked.
  *
  ****************************************************************************/
 
-int local_send_packet(FAR struct file *filep, FAR const uint8_t *buf,
-                      size_t len)
+void devif_can_send(FAR struct net_driver_s *dev, FAR const void *buf,
+                    unsigned int len)
 {
-  uint16_t len16;
-  int ret;
-
-  /* Send the packet preamble */
+  DEBUGASSERT(dev && len > 0 && len < NETDEV_PKTSIZE(dev));
 
-  ret = local_fifo_write(filep, g_preamble, LOCAL_PREAMBLE_SIZE);
-  if (ret == OK)
-    {
-      /* Send the packet length */
+  /* Copy the data into the device packet buffer */
 
-      len16 = len;
-      ret = local_fifo_write(filep, (FAR const uint8_t *)&len16,
-                             sizeof(uint16_t));
-      if (ret == OK)
-        {
-          /* Send the packet data */
+  memcpy(dev->d_buf, buf, len);
 
-          ret = local_fifo_write(filep, buf, len);
-        }
-    }
+  /* Set the number of bytes to send */
 
-  return ret;
+  dev->d_len    = len;
+  dev->d_sndlen = len;
 }
 
-#endif /* CONFIG_NET && CONFIG_NET_LOCAL */
+#endif /* CONFIG_NET_CAN */
diff --git a/net/devif/devif_poll.c b/net/devif/devif_poll.c
index 7c4fd04..ffffed4 100644
--- a/net/devif/devif_poll.c
+++ b/net/devif/devif_poll.c
@@ -50,6 +50,7 @@
 
 #include "devif/devif.h"
 #include "arp/arp.h"
+#include "can/can.h"
 #include "tcp/tcp.h"
 #include "udp/udp.h"
 #include "pkt/pkt.h"
@@ -233,6 +234,44 @@ static int devif_poll_pkt_connections(FAR struct net_driver_s *dev,
 #endif /* CONFIG_NET_PKT */
 
 /****************************************************************************
+ * Name: devif_poll_pkt_connections
+ *
+ * Description:
+ *   Poll all packet connections for available packets to send.
+ *
+ * Assumptions:
+ *   This function is called from the MAC device driver with the network
+ *   locked.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_CAN
+static int devif_poll_can_connections(FAR struct net_driver_s *dev,
+                                      devif_poll_callback_t callback)
+{
+  FAR struct can_conn_s *can_conn = NULL;
+  int bstop = 0;
+
+  /* Traverse all of the allocated packet connections and
+   * perform the poll action
+   */
+
+  while (!bstop && (can_conn = can_nextconn(can_conn)))
+    {
+      /* Perform the packet TX poll */
+
+      can_poll(dev, can_conn);
+
+      /* Call back into the driver */
+
+      bstop = callback(dev);
+    }
+
+  return bstop;
+}
+#endif /* CONFIG_NET_PKT */
+
+/****************************************************************************
  * Name: devif_poll_bluetooth_connections
  *
  * Description:
@@ -646,6 +685,15 @@ int devif_poll(FAR struct net_driver_s *dev, devif_poll_callback_t callback)
 
   if (!bstop)
 #endif
+#ifdef CONFIG_NET_CAN
+    {
+      /* Check for pending packet socket transfer */
+
+      bstop = devif_poll_can_connections(dev, callback);
+    }
+
+  if (!bstop)
+#endif
 #ifdef CONFIG_NET_BLUETOOTH
     {
       /* Check for pending PF_BLUETOOTH socket transfer */
diff --git a/net/icmp/icmp_sockif.c b/net/icmp/icmp_sockif.c
index 983eb71..2b1e179 100644
--- a/net/icmp/icmp_sockif.c
+++ b/net/icmp/icmp_sockif.c
@@ -102,6 +102,10 @@ const struct sock_intf_s g_icmp_sockif =
   NULL,             /* si_sendfile */
 #endif
   icmp_recvfrom,    /* si_recvfrom */
+#ifdef CONFIG_NET_CMSG
+  NULL,             /* si_recvmsg */
+  NULL,             /* si_sendmsg */
+#endif
   icmp_close        /* si_close */
 };
 
@@ -280,7 +284,8 @@ static int icmp_connect(FAR struct socket *psock,
  * Input Parameters:
  *   psock    Reference to the listening socket structure
  *   addr     Receives the address of the connecting client
- *   addrlen  Input: allocated size of 'addr', Return: returned size of 'addr'
+ *   addrlen  Input: allocated size of 'addr',
+ *            Return: returned size of 'addr'
  *   newsock  Location to return the accepted socket information.
  *
  * Returned Value:
@@ -318,7 +323,8 @@ static int icmp_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
  *
  ****************************************************************************/
 
-static int icmp_bind(FAR struct socket *psock, FAR const struct sockaddr *addr,
+static int icmp_bind(FAR struct socket *psock,
+                     FAR const struct sockaddr *addr,
                      socklen_t addrlen)
 {
   /* An ICMP socket cannot be bound to a local address */
@@ -364,10 +370,10 @@ static int icmp_getsockname(FAR struct socket *psock,
  * Name: icmp_getpeername
  *
  * Description:
- *   The icmp_getpeername() function retrieves the remote-connected name of the
- *   specified packet socket, stores this address in the sockaddr structure
- *   pointed to by the 'addr' argument, and stores the length of this
- *   address in the object pointed to by the 'addrlen' argument.
+ *   The icmp_getpeername() function retrieves the remote-connected name of
+ *   the specified packet socket, stores this address in the sockaddr
+ *   structure pointed to by the 'addr' argument, and stores the length of
+ *   this address in the object pointed to by the 'addrlen' argument.
  *
  *   If the actual length of the address is greater than the length of the
  *   supplied sockaddr structure, the stored address will be truncated.
diff --git a/net/icmpv6/icmpv6_sockif.c b/net/icmpv6/icmpv6_sockif.c
index c99d184..3dbb5c8 100644
--- a/net/icmpv6/icmpv6_sockif.c
+++ b/net/icmpv6/icmpv6_sockif.c
@@ -102,6 +102,10 @@ const struct sock_intf_s g_icmpv6_sockif =
   NULL,               /* si_sendfile */
 #endif
   icmpv6_recvfrom,    /* si_recvfrom */
+#ifdef CONFIG_NET_CMSG
+  NULL,               /* si_recvmsg */
+  NULL,               /* si_sendmsg */
+#endif
   icmpv6_close        /* si_close */
 };
 
@@ -280,7 +284,8 @@ static int icmpv6_connect(FAR struct socket *psock,
  * Input Parameters:
  *   psock    Reference to the listening socket structure
  *   addr     Receives the address of the connecting client
- *   addrlen  Input: allocated size of 'addr', Return: returned size of 'addr'
+ *   addrlen  Input: allocated size of 'addr',
+ *            Return: returned size of 'addr'
  *   newsock  Location to return the accepted socket information.
  *
  * Returned Value:
@@ -318,8 +323,9 @@ static int icmpv6_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
  *
  ****************************************************************************/
 
-static int icmpv6_bind(FAR struct socket *psock, FAR const struct sockaddr *addr,
-                     socklen_t addrlen)
+static int icmpv6_bind(FAR struct socket *psock,
+                       FAR const struct sockaddr *addr,
+                       socklen_t addrlen)
 {
   /* An ICMPv6 socket cannot be bound to a local address */
 
@@ -330,10 +336,10 @@ static int icmpv6_bind(FAR struct socket *psock, FAR const struct sockaddr *addr
  * Name: icmpv6_getsockname
  *
  * Description:
- *   The icmpv6_getsockname() function retrieves the locally-bound name of the
- *   specified packet socket, stores this address in the sockaddr structure
- *   pointed to by the 'addr' argument, and stores the length of this
- *   address in the object pointed to by the 'addrlen' argument.
+ *   The icmpv6_getsockname() function retrieves the locally-bound name of
+ *   the specified packet socket, stores this address in the sockaddr
+ *   structure pointed to by the 'addr' argument, and stores the length of
+ *   this address in the object pointed to by the 'addrlen' argument.
  *
  *   If the actual length of the address is greater than the length of the
  *   supplied sockaddr structure, the stored address will be truncated.
@@ -364,10 +370,10 @@ static int icmpv6_getsockname(FAR struct socket *psock,
  * Name: icmpv6_getpeername
  *
  * Description:
- *   The icmpv6_getpeername() function retrieves the remote-connected name of the
- *   specified packet socket, stores this address in the sockaddr structure
- *   pointed to by the 'addr' argument, and stores the length of this
- *   address in the object pointed to by the 'addrlen' argument.
+ *   The icmpv6_getpeername() function retrieves the remote-connected name of
+ *   the specified packet socket, stores this address in the sockaddr
+ *   structure pointed to by the 'addr' argument, and stores the length of
+ *   this address in the object pointed to by the 'addrlen' argument.
  *
  *   If the actual length of the address is greater than the length of the
  *   supplied sockaddr structure, the stored address will be truncated.
@@ -483,8 +489,8 @@ static int icmpv6_netpoll(FAR struct socket *psock, FAR struct pollfd *fds,
 static ssize_t icmpv6_send(FAR struct socket *psock, FAR const void *buf,
                         size_t len, int flags)
 {
-  /* ICMPv6 sockets cannot be bound and, hence, cannot support any connection-
-   * oriented data transfer.
+  /* ICMPv6 sockets cannot be bound and, hence, cannot support any
+   * connection-oriented data transfer.
    */
 
   return -EDESTADDRREQ;
diff --git a/net/ieee802154/ieee802154_sockif.c b/net/ieee802154/ieee802154_sockif.c
index 216264a..eb5d6e5 100644
--- a/net/ieee802154/ieee802154_sockif.c
+++ b/net/ieee802154/ieee802154_sockif.c
@@ -107,6 +107,10 @@ const struct sock_intf_s g_ieee802154_sockif =
   NULL,                   /* si_sendfile */
 #endif
   ieee802154_recvfrom,    /* si_recvfrom */
+#ifdef CONFIG_NET_CMSG
+  NULL,                   /* si_recvmsg */
+  NULL,                   /* si_sendmsg */
+#endif
   ieee802154_close        /* si_close */
 };
 
@@ -241,10 +245,10 @@ static void ieee802154_addref(FAR struct socket *psock)
  * Name: ieee802154_connect
  *
  * Description:
- *   ieee802154_connect() connects the local socket referred to by the structure
- *   'psock' to the address specified by 'addr'. The addrlen argument
- *   specifies the size of 'addr'.  The format of the address in 'addr' is
- *   determined by the address space of the socket 'psock'.
+ *   ieee802154_connect() connects the local socket referred to by the
+ *   structure 'psock' to the address specified by 'addr'. The addrlen
+ *   argument specifies the size of 'addr'.  The format of the address in
+ *   'addr' is determined by the address space of the socket 'psock'.
  *
  *   If the socket 'psock' is of type SOCK_DGRAM then 'addr' is the address
  *   to which datagrams are sent by default, and the only address from which
@@ -307,8 +311,8 @@ static int ieee802154_connect(FAR struct socket *psock,
  * Name: ieee802154_accept
  *
  * Description:
- *   The ieee802154_accept function is used with connection-based socket types
- *   (SOCK_STREAM, SOCK_SEQPACKET and SOCK_RDM). It extracts the first
+ *   The ieee802154_accept function is used with connection-based socket
+ *   types (SOCK_STREAM, SOCK_SEQPACKET and SOCK_RDM). It extracts the first
  *   connection request on the queue of pending connections, creates a new
  *   connected socket with mostly the same properties as 'sockfd', and
  *   allocates a new socket descriptor for the socket, which is returned. The
@@ -334,7 +338,8 @@ static int ieee802154_connect(FAR struct socket *psock,
  * Input Parameters:
  *   psock    Reference to the listening socket structure
  *   addr     Receives the address of the connecting client
- *   addrlen  Input: allocated size of 'addr', Return: returned size of 'addr'
+ *   addrlen  Input: allocated size of 'addr',
+ *            Return: returned size of 'addr'
  *   newsock  Location to return the accepted socket information.
  *
  * Returned Value:
@@ -376,7 +381,8 @@ static int ieee802154_accept(FAR struct socket *psock,
  ****************************************************************************/
 
 static int ieee802154_bind(FAR struct socket *psock,
-                           FAR const struct sockaddr *addr, socklen_t addrlen)
+                           FAR const struct sockaddr *addr,
+                           socklen_t addrlen)
 {
   FAR const struct sockaddr_ieee802154_s *iaddr;
   FAR struct radio_driver_s *radio;
@@ -446,10 +452,10 @@ static int ieee802154_bind(FAR struct socket *psock,
  * Name: ieee802154_getsockname
  *
  * Description:
- *   The ieee802154_getsockname() function retrieves the locally-bound name of the
- *   specified packet socket, stores this address in the sockaddr structure
- *   pointed to by the 'addr' argument, and stores the length of this
- *   address in the object pointed to by the 'addrlen' argument.
+ *   The ieee802154_getsockname() function retrieves the locally-bound name
+ *   of the specified packet socket, stores this address in the sockaddr
+ *   structure pointed to by the 'addr' argument, and stores the length of
+ *   this address in the object pointed to by the 'addrlen' argument.
  *
  *   If the actual length of the address is greater than the length of the
  *   supplied sockaddr structure, the stored address will be truncated.
@@ -508,10 +514,10 @@ static int ieee802154_getsockname(FAR struct socket *psock,
  * Name: ieee802154_getpeername
  *
  * Description:
- *   The ieee802154_getpeername() function retrieves the remote-connectd name of the
- *   specified packet socket, stores this address in the sockaddr structure
- *   pointed to by the 'addr' argument, and stores the length of this
- *   address in the object pointed to by the 'addrlen' argument.
+ *   The ieee802154_getpeername() function retrieves the remote-connectd name
+ *   of the specified packet socket, stores this address in the sockaddr
+ *   structure pointed to by the 'addr' argument, and stores the length of
+ *   this address in the object pointed to by the 'addrlen' argument.
  *
  *   If the actual length of the address is greater than the length of the
  *   supplied sockaddr structure, the stored address will be truncated.
@@ -676,7 +682,8 @@ static ssize_t ieee802154_send(FAR struct socket *psock, FAR const void *buf,
 
           ret = psock_ieee802154_sendto(psock, buf, len, flags,
                                         (FAR const struct sockaddr *)&to,
-                                        sizeof(struct sockaddr_ieee802154_s));
+                                        sizeof(
+                                          struct sockaddr_ieee802154_s));
         }
     }
   else
@@ -713,9 +720,11 @@ static ssize_t ieee802154_send(FAR struct socket *psock, FAR const void *buf,
  *
  ****************************************************************************/
 
-static ssize_t ieee802154_sendto(FAR struct socket *psock, FAR const void *buf,
+static ssize_t ieee802154_sendto(FAR struct socket *psock,
+                                 FAR const void *buf,
                                  size_t len, int flags,
-                                 FAR const struct sockaddr *to, socklen_t tolen)
+                                 FAR const struct sockaddr *to,
+                                 socklen_t tolen)
 {
   ssize_t ret;
 
diff --git a/net/inet/inet_sockif.c b/net/inet/inet_sockif.c
index 9456510..488f2d1 100644
--- a/net/inet/inet_sockif.c
+++ b/net/inet/inet_sockif.c
@@ -117,6 +117,10 @@ static const struct sock_intf_s g_inet_sockif =
   inet_sendfile,    /* si_sendfile */
 #endif
   inet_recvfrom,    /* si_recvfrom */
+#ifdef CONFIG_NET_CMSG
+  NULL,             /* si_recvmsg */
+  NULL,             /* si_sendmsg */
+#endif
   inet_close        /* si_close */
 };
 
diff --git a/net/local/local_sendpacket.c b/net/local/local_sendpacket.c
index 68dfac6..644dd31 100644
--- a/net/local/local_sendpacket.c
+++ b/net/local/local_sendpacket.c
@@ -47,6 +47,7 @@
 #include <debug.h>
 
 #include <nuttx/fs/fs.h>
+#include "devif/devif.h"
 
 #include "local/local.h"
 
diff --git a/net/local/local_sockif.c b/net/local/local_sockif.c
index f2bbcb1..c4f7531 100644
--- a/net/local/local_sockif.c
+++ b/net/local/local_sockif.c
@@ -110,6 +110,10 @@ const struct sock_intf_s g_local_sockif =
   NULL,              /* si_sendfile */
 #endif
   local_recvfrom,    /* si_recvfrom */
+#ifdef CONFIG_NET_CMSG
+  NULL,              /* si_recvmsg */
+  NULL,              /* si_sendmsg */
+#endif
   local_close        /* si_close */
 };
 
@@ -161,7 +165,8 @@ static int local_sockif_alloc(FAR struct socket *psock)
  *   specific socket fields.
  *
  * Input Parameters:
- *   psock    A pointer to a user allocated socket structure to be initialized.
+ *   psock    A pointer to a user allocated socket structure
+ *            to be initialized.
  *   protocol (see sys/socket.h)
  *
  * Returned Value:
@@ -590,7 +595,8 @@ static int local_connect(FAR struct socket *psock,
  * Input Parameters:
  *   psock    Reference to the listening socket structure
  *   addr     Receives the address of the connecting client
- *   addrlen  Input: allocated size of 'addr', Return: returned size of 'addr'
+ *   addrlen  Input: allocated size of 'addr',
+ *            Return: returned size of 'addr'
  *   newsock  Location to return the accepted socket information.
  *
  * Returned Value:
@@ -717,7 +723,7 @@ static ssize_t local_send(FAR struct socket *psock, FAR const void *buf,
  * Name: local_sendto
  *
  * Description:
- *   Implements the sendto() operation for the case of the local, Unix socket.
+ *   Implements the sendto() operation for the case of the local Unix socket.
  *
  * Input Parameters:
  *   psock    A pointer to a NuttX-specific, internal socket structure
diff --git a/net/net_initialize.c b/net/net_initialize.c
index eb82777..bedc4e3 100644
--- a/net/net_initialize.c
+++ b/net/net_initialize.c
@@ -59,6 +59,7 @@
 #include "bluetooth/bluetooth.h"
 #include "ieee802154/ieee802154.h"
 #include "local/local.h"
+#include "can/can.h"
 #include "netlink/netlink.h"
 #include "igmp/igmp.h"
 #include "route/route.h"
@@ -158,6 +159,12 @@ void net_initialize(void)
   local_initialize();
 #endif
 
+#ifdef CONFIG_NET_CAN
+  /* Initialize SocketCAN support */
+
+  can_initialize();
+#endif
+
 #ifdef CONFIG_NET_NETLINK
   /* Initialize the Netlink IPC support */
 
diff --git a/net/netdev/Kconfig b/net/netdev/Kconfig
index 2b3f905..ce51c1f 100644
--- a/net/netdev/Kconfig
+++ b/net/netdev/Kconfig
@@ -16,6 +16,14 @@ config NETDEV_PHY_IOCTL
 	---help---
 		Enable support for ioctl() commands to access PHY registers
 
+config NETDEV_CAN_BITRATE_IOCTL
+	bool "Enable CAN bitrate ioctl()"
+	default n
+	select NETDEV_IOCTL
+	depends on NET_CAN
+	---help---
+		Enable support for ioctl() commands to change CAN bitrate
+		
 config NETDEV_WIRELESS_IOCTL
 	bool "Enable Wireless ioctl()"
 	default n
diff --git a/net/netdev/netdev_ioctl.c b/net/netdev/netdev_ioctl.c
index 04c9b51..c169503 100644
--- a/net/netdev/netdev_ioctl.c
+++ b/net/netdev/netdev_ioctl.c
@@ -1088,6 +1088,54 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd,
             }
         }
         break;
+#endif  
+
+#if defined(CONFIG_NETDEV_IOCTL) && defined(CONFIG_NETDEV_CAN_BITRATE_IOCTL)
+      case SIOCGCANBITRATE:  /* Get bitrate from a CAN controller */
+      case SIOCSCANBITRATE:  /* Set bitrate of a CAN controller */
+        {
+          dev = netdev_ifr_dev(req);
+          if (dev && dev->d_ioctl)
+            {
+              struct can_ioctl_data_s *can_bitrate_data =
+                            &req->ifr_ifru.ifru_can_data;
+              ret = dev->d_ioctl(dev, cmd,
+                            (unsigned long)(uintptr_t)can_bitrate_data);
+            }
+        }
+        break;
+#endif
+
+#ifdef CONFIG_NETDEV_IFINDEX
+      case SIOCGIFNAME:  /* Get interface name */
+        {
+          struct net_driver_s *dev = netdev_findbyindex(req->ifr_ifindex);
+          if (dev != NULL)
+            {
+              strncpy(req->ifr_name, dev->d_ifname, IFNAMSIZ);
+              ret = OK;
+            }
+          else
+            {
+              ret = -ENODEV;
+            }
+        }
+        break;
+
+      case SIOCGIFINDEX:  /* Index to name mapping */
+        {
+          struct net_driver_s *dev = netdev_findbyname(req->ifr_name);
+          if (dev != NULL)
+            {
+              req->ifr_ifindex = dev->d_ifindex;
+              ret = OK;
+            }
+          else
+            {
+              ret = -ENODEV;
+            }
+        }
+        break;
 #endif
 
       default:
diff --git a/net/netdev/netdev_register.c b/net/netdev/netdev_register.c
index 4b08efa..3694db5 100644
--- a/net/netdev/netdev_register.c
+++ b/net/netdev/netdev_register.c
@@ -37,6 +37,7 @@
 #include <nuttx/net/netdev.h>
 #include <nuttx/net/ethernet.h>
 #include <nuttx/net/bluetooth.h>
+#include <nuttx/net/can.h>
 
 #include "utils/utils.h"
 #include "igmp/igmp.h"
@@ -56,6 +57,7 @@
 #define NETDEV_WLAN_FORMAT  "wlan%d"
 #define NETDEV_WPAN_FORMAT  "wpan%d"
 #define NETDEV_WWAN_FORMAT  "wwan%d"
+#define NETDEV_CAN_FORMAT   "can%d"
 
 #if defined(CONFIG_DRIVERS_IEEE80211) /* Usually also has CONFIG_NET_ETHERNET */
 #  define NETDEV_DEFAULT_FORMAT NETDEV_WLAN_FORMAT
@@ -67,6 +69,8 @@
 #  define NETDEV_DEFAULT_FORMAT NETDEV_SLIP_FORMAT
 #elif defined(CONFIG_NET_TUN)
 #  define NETDEV_DEFAULT_FORMAT NETDEV_TUN_FORMAT
+#elif defined(CONFIG_NET_CAN)
+#  define NETDEV_DEFAULT_FORMAT NETDEV_CAN_FORMAT
 #else /* if defined(CONFIG_NET_LOOPBACK) */
 #  define NETDEV_DEFAULT_FORMAT NETDEV_LO_FORMAT
 #endif
@@ -277,6 +281,14 @@ int netdev_register(FAR struct net_driver_s *dev, enum net_lltype_e lltype)
             break;
 #endif
 
+#ifdef CONFIG_NET_CAN
+          case NET_LL_CAN:  /* CAN bus */
+            dev->d_llhdrlen = 0;
+            dev->d_pktsize  = NET_CAN_PKTSIZE;
+            devfmt          = NETDEV_CAN_FORMAT;
+            break;
+#endif
+
 #ifdef CONFIG_NET_BLUETOOTH
           case NET_LL_BLUETOOTH:              /* Bluetooth */
             llhdrlen = BLUETOOTH_MAX_HDRLEN;  /* Determined at runtime */
diff --git a/net/netlink/netlink_sockif.c b/net/netlink/netlink_sockif.c
index 577d520..34b011a 100644
--- a/net/netlink/netlink_sockif.c
+++ b/net/netlink/netlink_sockif.c
@@ -111,6 +111,10 @@ const struct sock_intf_s g_netlink_sockif =
   NULL,                 /* si_sendfile */
 #endif
   netlink_recvfrom,     /* si_recvfrom */
+#ifdef CONFIG_NET_CMSG
+  NULL,                 /* si_recvmsg */
+  NULL,                 /* si_sendmsg */
+#endif
   netlink_close         /* si_close */
 };
 
diff --git a/net/pkt/pkt_sockif.c b/net/pkt/pkt_sockif.c
index e189ddc..dbf3e3c 100644
--- a/net/pkt/pkt_sockif.c
+++ b/net/pkt/pkt_sockif.c
@@ -108,6 +108,10 @@ const struct sock_intf_s g_pkt_sockif =
   NULL,            /* si_sendfile */
 #endif
   pkt_recvfrom,    /* si_recvfrom */
+#ifdef CONFIG_NET_CMSG
+  NULL,            /* si_recvmsg */
+  NULL,            /* si_sendmsg */
+#endif
   pkt_close        /* si_close */
 };
 
diff --git a/net/socket/Kconfig b/net/socket/Kconfig
index c627ea5..f13e22d 100644
--- a/net/socket/Kconfig
+++ b/net/socket/Kconfig
@@ -37,6 +37,12 @@ config NET_UDPPROTO_OPTIONS
 	---help---
 		Enable or disable support for UDP protocol level socket options.
 
+config NET_CANPROTO_OPTIONS
+	bool
+	default n
+	---help---
+		Enable or disable support for CAN protocol level socket option
+
 if NET_SOCKOPTS
 
 config NET_SOLINGER
@@ -49,5 +55,23 @@ config NET_SOLINGER
 		Enable or disable support for the SO_LINGER socket option.  Requires
 		write buffer support.
 
+config NET_TIMESTAMP
+	bool "SO_TIMESTAMP socket option"
+	default n
+	depends on NET_CAN
+	select NET_CMSG
+	---help---
+		Enable or disable support for the SO_TIMESTAMP socket option. Currently only tested & implemented in SocketCAN but should work on all sockets
+
 endif # NET_SOCKOPTS
+
+config NET_CMSG
+	bool "Control messages (CMSG) support"
+	default n
+	---help---
+		Enable or disable support for control messages in the recvmsg() and
+		sendmsg() function. Control messages (also defined in POSIX 1003.1g 
+		as ancillary data object information). Includes additional 
+		information on the packet received or to be transmitted.
+
 endmenu # Socket Support
diff --git a/net/socket/Make.defs b/net/socket/Make.defs
index 47fb4d2..6bf79ed 100644
--- a/net/socket/Make.defs
+++ b/net/socket/Make.defs
@@ -74,3 +74,9 @@ endif
 
 DEPPATH += --dep-path socket
 VPATH += :socket
+
+# Support for control messages (CMSG)
+ifeq ($(CONFIG_NET_CMSG),y)
+SOCK_CSRCS += recvmsg.c
+SOCK_CSRCS += sendmsg.c
+endif
diff --git a/net/socket/getsockopt.c b/net/socket/getsockopt.c
index e7474ad..581edc0 100644
--- a/net/socket/getsockopt.c
+++ b/net/socket/getsockopt.c
@@ -278,6 +278,19 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
         }
         break;
 
+#ifdef CONFIG_NET_TIMESTAMP
+      case SO_TIMESTAMP:
+        {
+          if (*value_len != sizeof(int))
+            {
+              return -EINVAL;
+            }
+
+          *(FAR int *)value = (int)psock->s_timestamp;
+        }
+        break;
+#endif
+
       /* The following are not yet implemented
        * (return values other than {0,1})
        */
@@ -371,6 +384,12 @@ int psock_getsockopt(FAR struct socket *psock, int level, int option,
        break;
 #endif
 
+      case SOL_CAN_RAW:/* CAN protocol socket options (see include/netpacket/can.h) */
+#ifdef CONFIG_NET_CANPROTO_OPTIONS
+       ret = can_getsockopt(psock, option, value, value_len);
+#endif
+       break;
+
       /* These levels are defined in sys/socket.h, but are not yet
        * implemented.
        */
diff --git a/net/socket/net_sockif.c b/net/socket/net_sockif.c
index 01e8368..cc956d8 100644
--- a/net/socket/net_sockif.c
+++ b/net/socket/net_sockif.c
@@ -47,6 +47,7 @@
 
 #include "inet/inet.h"
 #include "local/local.h"
+#include "can/can.h"
 #include "netlink/netlink.h"
 #include "pkt/pkt.h"
 #include "bluetooth/bluetooth.h"
@@ -104,6 +105,12 @@ net_sockif(sa_family_t family, int type, int protocol)
       break;
 #endif
 
+#ifdef CONFIG_NET_CAN
+    case PF_CAN:
+      sockif = &g_can_sockif;
+      break;
+#endif
+
 #ifdef CONFIG_NET_NETLINK
     case PF_NETLINK:
       sockif = &g_netlink_sockif;
diff --git a/net/socket/recvmsg.c b/net/socket/recvmsg.c
new file mode 100644
index 0000000..9ba5de3
--- /dev/null
+++ b/net/socket/recvmsg.c
@@ -0,0 +1,244 @@
+/****************************************************************************
+ * net/socket/recvmsg.c
+ *
+ *   Copyright (C) 2007-2009, 2011-2017, 2019 Gregory Nutt. All rights
+ *     reserved.
+ *   Author: Gregory Nutt <gn...@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <assert.h>
+#include <errno.h>
+
+#include <nuttx/cancelpt.h>
+#include <nuttx/net/net.h>
+
+#include "socket/socket.h"
+
+#ifdef CONFIG_NET_CMSG
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: psock_recvmsg
+ *
+ * Description:
+ *   psock_recvfrom() receives messages from a socket, and may be used to
+ *   receive data on a socket whether or not it is connection-oriented.
+ *   This is an internal OS interface.  It is functionally equivalent to
+ *   recvfrom() except that:
+ *
+ *   - It is not a cancellation point,
+ *   - It does not modify the errno variable, and
+ *   - I accepts the internal socket structure as an input rather than an
+ *     task-specific socket descriptor.
+ *
+ * Input Parameters:
+ *   psock   - A pointer to a NuttX-specific, internal socket structure
+ *   msg      Buffer to receive msg
+ *   len     - Length of buffer
+ *   flags   - Receive flags
+ *
+ * Returned Value:
+ *   On success, returns the number of characters sent.  If no data is
+ *   available to be received and the peer has performed an orderly shutdown,
+ *   recv() will return 0.  Otherwise, on any failure, a negated errno value
+ *   is returned (see comments with send() for a list of appropriate errno
+ *   values).
+ *
+ ****************************************************************************/
+
+ssize_t psock_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
+                       int flags)
+{
+  /* Verify that non-NULL pointers were passed */
+
+  if (msg == NULL)
+    {
+      return -EINVAL;
+    }
+
+  if (msg->msg_iovlen != 1)
+    {
+      return -ENOTSUP;
+    }
+
+  /* Verify that the sockfd corresponds to valid, allocated socket */
+
+  if (psock == NULL || psock->s_crefs <= 0)
+    {
+      return -EBADF;
+    }
+
+  /* Let logic specific to this address family handle the recvfrom()
+   * operation.
+   */
+
+  DEBUGASSERT(psock->s_sockif != NULL &&
+              (psock->s_sockif->si_recvmsg != NULL ||
+               psock->s_sockif->si_recvfrom != NULL));
+
+  if (psock->s_sockif->si_recvmsg != NULL)
+    {
+      return psock->s_sockif->si_recvmsg(psock, msg, flags);
+    }
+  else
+    {
+      /* Socket doesn't implement si_recvmsg fallback to si_recvfrom */
+
+      FAR void *buf             = msg->msg_iov->iov_base;
+      FAR struct sockaddr *from = msg->msg_name;
+      FAR socklen_t *fromlen    = (FAR socklen_t *)&msg->msg_namelen;
+      size_t len                = msg->msg_iov->iov_len;
+
+      return psock->s_sockif->si_recvfrom(psock, buf, len, flags, from,
+                                          fromlen);
+    }
+}
+
+/****************************************************************************
+ * Name: nx_recvfrom
+ *
+ * Description:
+ *   nx_recvfrom() receives messages from a socket, and may be used to
+ *   receive data on a socket whether or not it is connection-oriented.
+ *   This is an internal OS interface.  It is functionally equivalent to
+ *   recvfrom() except that:
+ *
+ *   - It is not a cancellation point, and
+ *   - It does not modify the errno variable.
+ *
+ * Input Parameters:
+ *   sockfd  - Socket descriptor of socket
+ *   msg      Buffer to receive msg
+ *   len     - Length of buffer
+ *   flags   - Receive flags
+ *
+ * Returned Value:
+ *   On success, returns the number of characters sent.  If no data is
+ *   available to be received and the peer has performed an orderly shutdown,
+ *   recv() will return 0.  Otherwise, on any failure, a negated errno value
+ *   is returned (see comments with send() for a list of appropriate errno
+ *   values).
+ *
+ ****************************************************************************/
+
+ssize_t nx_recvmsg(int sockfd, FAR struct msghdr *msg, int flags)
+{
+  FAR struct socket *psock;
+
+  /* Get the underlying socket structure */
+
+  psock = sockfd_socket(sockfd);
+
+  /* Then let psock_recvmsg() do all of the work */
+
+  return psock_recvmsg(psock, msg, flags);
+}
+
+/****************************************************************************
+ * Function: recvmsg
+ *
+ * Description:
+ *   The recvmsg() call is identical to recvfrom() with a NULL from
+ *   parameter.
+ *
+ * Parameters:
+ *   sockfd   Socket descriptor of socket
+ *   msg      Buffer to receive msg
+ *   len      Length of buffer
+ *   flags    Receive flags
+ *
+ * Returned Value:
+ *   On success, returns the number of characters received.  On  error,
+ *   -1 is returned, and errno is set appropriately:
+ *
+ *   EAGAIN
+ *     The socket is marked non-blocking and the receive operation would
+ *     block, or a receive timeout had been set and the timeout expired
+ *     before data was received.
+ *   EBADF
+ *     The argument sockfd is an invalid descriptor.
+ *   ECONNREFUSED
+ *     A remote host refused to allow the network connection (typically
+ *     because it is not running the requested service).
+ *   EFAULT
+ *     The receive buffer pointer(s) point outside the process's address
+ *     space.
+ *   EINTR
+ *     The receive was interrupted by delivery of a signal before any data
+ *     were available.
+ *   EINVAL
+ *     Invalid argument passed.
+ *   ENOMEM
+ *     Could not allocate memory.
+ *   ENOTCONN
+ *     The socket is associated with a connection-oriented protocol and has
+ *     not been connected.
+ *   ENOTSOCK
+ *     The argument sockfd does not refer to a socket.
+ *
+ ****************************************************************************/
+
+ssize_t recvmsg(int sockfd, FAR struct msghdr *msg, int flags)
+{
+  FAR struct socket *psock;
+  ssize_t ret;
+
+  /* recvfrom() is a cancellation point */
+
+  enter_cancellation_point();
+
+  /* Get the underlying socket structure */
+
+  psock = sockfd_socket(sockfd);
+
+  /* Let psock_recvfrom() do all of the work */
+
+  ret = psock_recvmsg(psock, msg, flags);
+  if (ret < 0)
+    {
+      _SO_SETERRNO(psock, -ret);
+      ret = ERROR;
+    }
+
+  leave_cancellation_point();
+  return ret;
+}
+
+#endif /* CONFIG_NET_CMSG */
diff --git a/net/socket/sendmsg.c b/net/socket/sendmsg.c
new file mode 100644
index 0000000..a188b3a
--- /dev/null
+++ b/net/socket/sendmsg.c
@@ -0,0 +1,243 @@
+/****************************************************************************
+ * net/socket/sendmsg.c
+ *
+ *   Copyright (C) 2007-2009, 2011-2017, 2019 Gregory Nutt. All rights
+ *     reserved.
+ *   Author: Gregory Nutt <gn...@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <assert.h>
+#include <errno.h>
+
+#include <nuttx/cancelpt.h>
+#include <nuttx/net/net.h>
+
+#include "socket/socket.h"
+
+#ifdef CONFIG_NET_CMSG
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: psock_sendmsg
+ *
+ * Description:
+ *   psock_sendfrom() sends messages to a socket, and may be used to
+ *   send data on a socket whether or not it is connection-oriented.
+ *   This is an internal OS interface.  It is functionally equivalent to
+ *   sendfrom() except that:
+ *
+ *   - It is not a cancellation point,
+ *   - It does not modify the errno variable, and
+ *   - I accepts the internal socket structure as an input rather than an
+ *     task-specific socket descriptor.
+ *
+ * Input Parameters:
+ *   psock   - A pointer to a NuttX-specific, internal socket structure
+ *   msg     - Buffer to of the msg
+ *   len     - Length of buffer
+ *   flags   - Receive flags
+ *
+ * Returned Value:
+ *   On success, returns the number of characters sent.  If no data is
+ *   available to be received and the peer has performed an orderly shutdown,
+ *   send() will return 0.  Otherwise, on any failure, a negated errno value
+ *   is returned (see comments with send() for a list of appropriate errno
+ *   values).
+ *
+ ****************************************************************************/
+
+ssize_t psock_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
+                       int flags)
+{
+  /* Verify that non-NULL pointers were passed */
+
+  if (msg == NULL)
+    {
+      return -EINVAL;
+    }
+
+  if (msg->msg_iovlen != 1)
+    {
+      return -ENOTSUP;
+    }
+
+  /* Verify that the sockfd corresponds to valid, allocated socket */
+
+  if (psock == NULL || psock->s_crefs <= 0)
+    {
+      return -EBADF;
+    }
+
+  /* Let logic specific to this address family handle the sendfrom()
+   * operation.
+   */
+
+  DEBUGASSERT(psock->s_sockif != NULL &&
+              (psock->s_sockif->si_sendmsg != NULL ||
+               psock->s_sockif->si_sendto != NULL));
+
+  if (psock->s_sockif->si_sendmsg != NULL)
+    {
+      return psock->s_sockif->si_sendmsg(psock, msg, flags);
+    }
+  else
+    {
+      /* Socket doesn't implement si_sendmsg fallback to si_sendto */
+
+      FAR void *buf           = msg->msg_iov->iov_base;
+      FAR struct sockaddr *to = msg->msg_name;
+      socklen_t tolen         = msg->msg_namelen;
+      size_t len              = msg->msg_iov->iov_len;
+
+      return psock->s_sockif->si_sendto(psock, buf, len, flags, to, tolen);
+    }
+}
+
+/****************************************************************************
+ * Name: nx_sendfrom
+ *
+ * Description:
+ *   nx_sendfrom() receives messages from a socket, and may be used to
+ *   receive data on a socket whether or not it is connection-oriented.
+ *   This is an internal OS interface.  It is functionally equivalent to
+ *   sendfrom() except that:
+ *
+ *   - It is not a cancellation point, and
+ *   - It does not modify the errno variable.
+ *
+ * Input Parameters:
+ *   sockfd  - Socket descriptor of socket
+ *   msg      Buffer to receive msg
+ *   len     - Length of buffer
+ *   flags   - Receive flags
+ *
+ * Returned Value:
+ *   On success, returns the number of characters sent.  If no data is
+ *   available to be received and the peer has performed an orderly shutdown,
+ *   send() will return 0.  Otherwise, on any failure, a negated errno value
+ *   is returned (see comments with send() for a list of appropriate errno
+ *   values).
+ *
+ ****************************************************************************/
+
+ssize_t nx_sendmsg(int sockfd, FAR struct msghdr *msg, int flags)
+{
+  FAR struct socket *psock;
+
+  /* Get the underlying socket structure */
+
+  psock = sockfd_socket(sockfd);
+
+  /* Then let psock_sendmsg() do all of the work */
+
+  return psock_sendmsg(psock, msg, flags);
+}
+
+/****************************************************************************
+ * Function: sendmsg
+ *
+ * Description:
+ *   The sendmsg() call is identical to sendfrom() with a NULL from
+ *   parameter.
+ *
+ * Parameters:
+ *   sockfd   Socket descriptor of socket
+ *   msg      Buffer to receive msg
+ *   len      Length of buffer
+ *   flags    Receive flags
+ *
+ * Returned Value:
+ *   On success, returns the number of characters received.  On  error,
+ *   -1 is returned, and errno is set appropriately:
+ *
+ *   EAGAIN
+ *     The socket is marked non-blocking and the receive operation would
+ *     block, or a receive timeout had been set and the timeout expired
+ *     before data was received.
+ *   EBADF
+ *     The argument sockfd is an invalid descriptor.
+ *   ECONNREFUSED
+ *     A remote host refused to allow the network connection (typically
+ *     because it is not running the requested service).
+ *   EFAULT
+ *     The receive buffer pointer(s) point outside the process's address
+ *     space.
+ *   EINTR
+ *     The receive was interrupted by delivery of a signal before any data
+ *     were available.
+ *   EINVAL
+ *     Invalid argument passed.
+ *   ENOMEM
+ *     Could not allocate memory.
+ *   ENOTCONN
+ *     The socket is associated with a connection-oriented protocol and has
+ *     not been connected.
+ *   ENOTSOCK
+ *     The argument sockfd does not refer to a socket.
+ *
+ ****************************************************************************/
+
+ssize_t sendmsg(int sockfd, FAR struct msghdr *msg, int flags)
+{
+  FAR struct socket *psock;
+  ssize_t ret;
+
+  /* sendfrom() is a cancellation point */
+
+  enter_cancellation_point();
+
+  /* Get the underlying socket structure */
+
+  psock = sockfd_socket(sockfd);
+
+  /* Let psock_sendfrom() do all of the work */
+
+  ret = psock_sendmsg(psock, msg, flags);
+  if (ret < 0)
+    {
+      _SO_SETERRNO(psock, -ret);
+      ret = ERROR;
+    }
+
+  leave_cancellation_point();
+  return ret;
+}
+
+#endif /* CONFIG_NET_CMSG */
diff --git a/net/socket/setsockopt.c b/net/socket/setsockopt.c
index 211a1df..da4b923 100644
--- a/net/socket/setsockopt.c
+++ b/net/socket/setsockopt.c
@@ -279,6 +279,29 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
         }
         break;
 #endif
+
+#ifdef CONFIG_NET_TIMESTAMP
+      case SO_TIMESTAMP:  /* Generates a timestamp for each incoming packet */
+        {
+          /* Verify that option is at least the size of an integer. */
+
+          if (value_len < sizeof(FAR int32_t))
+            {
+              return -EINVAL;
+            }
+
+          /* Lock the network so that we have exclusive access to the socket
+           * options.
+           */
+
+          net_lock();
+
+          psock->s_timestamp = *((FAR int32_t *)value);
+
+          net_unlock();
+        }
+        break;
+#endif
       /* The following are not yet implemented */
 
       case SO_RCVBUF:     /* Sets receive buffer size */
@@ -399,6 +422,12 @@ int psock_setsockopt(FAR struct socket *psock, int level, int option,
         break;
 #endif
 
+#ifdef CONFIG_NET_CANPROTO_OPTIONS
+      case SOL_CAN_RAW:   /* CAN protocol socket options (see include/netpacket/can.h) */
+        ret = can_setsockopt(psock, option, value, value_len);
+        break;
+#endif
+
       default:         /* The provided level is invalid */
         ret = -EINVAL;
         break;
diff --git a/net/socket/socket.h b/net/socket/socket.h
index 0f809ac..bd2a0ea 100644
--- a/net/socket/socket.h
+++ b/net/socket/socket.h
@@ -80,7 +80,7 @@
 
 /* This is the largest option value.  REVISIT: belongs in sys/socket.h */
 
-#define _SO_MAXOPT       (15)
+#define _SO_MAXOPT       (16)
 
 /* Macros to set, test, clear options */
 
diff --git a/net/utils/net_lock.c b/net/utils/net_lock.c
index da6784d..645a5cc 100644
--- a/net/utils/net_lock.c
+++ b/net/utils/net_lock.c
@@ -229,6 +229,57 @@ int net_lock(void)
 }
 
 /****************************************************************************
+ * Name: net_trylock
+ *
+ * Description:
+ *   Try to take the network lock only when it is currently not locked.
+ *   Otherwise, it locks the semaphore.  In either
+ *   case, the call returns without blocking.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success; a negated errno value is returned on
+ *   failured (probably -EAGAIN).
+ *
+ ****************************************************************************/
+
+int net_trylock(void)
+{
+#ifdef CONFIG_SMP
+  irqstate_t flags = enter_critical_section();
+#endif
+  pid_t me = getpid();
+  int ret = OK;
+
+  /* Does this thread already hold the semaphore? */
+
+  if (g_holder == me)
+    {
+      /* Yes.. just increment the reference count */
+
+      g_count++;
+    }
+  else
+    {
+      ret = nxsem_trywait(&g_netlock);
+      if (ret >= 0)
+        {
+          /* Now this thread holds the semaphore */
+
+          g_holder = me;
+          g_count  = 1;
+        }
+    }
+
+#ifdef CONFIG_SMP
+  leave_critical_section(flags);
+#endif
+  return ret;
+}
+
+/****************************************************************************
  * Name: net_unlock
  *
  * Description: