2019-05-19 16:51:43 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2011-07-02 02:31:36 +04:00
/*
* Copyright ( C ) 2011 Instituto Nokia de Tecnologia
*
* Authors :
* Aloisio Almeida Jr < aloisio . almeida @ openbossa . org >
* Lauro Ramos Venancio < lauro . venancio @ openbossa . org >
*/
2011-12-14 19:43:05 +04:00
# define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
2011-11-29 23:37:32 +04:00
2011-07-02 02:31:36 +04:00
# include <net/tcp_states.h>
# include <linux/nfc.h>
2011-07-15 19:47:34 +04:00
# include <linux/export.h>
2011-07-02 02:31:36 +04:00
# include "nfc.h"
2014-05-05 14:43:31 +04:00
static struct nfc_sock_list raw_sk_list = {
. lock = __RW_LOCK_UNLOCKED ( raw_sk_list . lock )
} ;
2014-05-26 02:53:10 +04:00
static void nfc_sock_link ( struct nfc_sock_list * l , struct sock * sk )
2014-05-05 14:43:31 +04:00
{
write_lock ( & l - > lock ) ;
sk_add_node ( sk , & l - > head ) ;
write_unlock ( & l - > lock ) ;
}
2014-05-26 02:53:10 +04:00
static void nfc_sock_unlink ( struct nfc_sock_list * l , struct sock * sk )
2014-05-05 14:43:31 +04:00
{
write_lock ( & l - > lock ) ;
sk_del_node_init ( sk ) ;
write_unlock ( & l - > lock ) ;
}
2011-07-02 02:31:36 +04:00
static void rawsock_write_queue_purge ( struct sock * sk )
{
2011-11-29 23:37:33 +04:00
pr_debug ( " sk=%p \n " , sk ) ;
2011-07-02 02:31:36 +04:00
spin_lock_bh ( & sk - > sk_write_queue . lock ) ;
__skb_queue_purge ( & sk - > sk_write_queue ) ;
nfc_rawsock ( sk ) - > tx_work_scheduled = false ;
spin_unlock_bh ( & sk - > sk_write_queue . lock ) ;
}
static void rawsock_report_error ( struct sock * sk , int err )
{
2011-11-29 23:37:33 +04:00
pr_debug ( " sk=%p err=%d \n " , sk , err ) ;
2011-07-02 02:31:36 +04:00
sk - > sk_shutdown = SHUTDOWN_MASK ;
sk - > sk_err = - err ;
sk - > sk_error_report ( sk ) ;
rawsock_write_queue_purge ( sk ) ;
}
static int rawsock_release ( struct socket * sock )
{
struct sock * sk = sock - > sk ;
2012-06-12 02:47:58 +04:00
pr_debug ( " sock=%p sk=%p \n " , sock , sk ) ;
if ( ! sk )
return 0 ;
2011-07-02 02:31:36 +04:00
2014-05-05 14:43:31 +04:00
if ( sock - > type = = SOCK_RAW )
nfc_sock_unlink ( & raw_sk_list , sk ) ;
2011-07-02 02:31:36 +04:00
sock_orphan ( sk ) ;
sock_put ( sk ) ;
return 0 ;
}
static int rawsock_connect ( struct socket * sock , struct sockaddr * _addr ,
2012-03-05 04:03:53 +04:00
int len , int flags )
2011-07-02 02:31:36 +04:00
{
struct sock * sk = sock - > sk ;
struct sockaddr_nfc * addr = ( struct sockaddr_nfc * ) _addr ;
struct nfc_dev * dev ;
int rc = 0 ;
2011-11-29 23:37:33 +04:00
pr_debug ( " sock=%p sk=%p flags=%d \n " , sock , sk , flags ) ;
2011-07-02 02:31:36 +04:00
if ( ! addr | | len < sizeof ( struct sockaddr_nfc ) | |
2012-03-05 04:03:53 +04:00
addr - > sa_family ! = AF_NFC )
2011-07-02 02:31:36 +04:00
return - EINVAL ;
2011-11-29 23:37:33 +04:00
pr_debug ( " addr dev_idx=%u target_idx=%u protocol=%u \n " ,
addr - > dev_idx , addr - > target_idx , addr - > nfc_protocol ) ;
2011-07-02 02:31:36 +04:00
lock_sock ( sk ) ;
if ( sock - > state = = SS_CONNECTED ) {
rc = - EISCONN ;
goto error ;
}
dev = nfc_get_device ( addr - > dev_idx ) ;
if ( ! dev ) {
rc = - ENODEV ;
goto error ;
}
2012-04-10 21:43:10 +04:00
if ( addr - > target_idx > dev - > target_next_idx - 1 | |
addr - > target_idx < dev - > target_next_idx - dev - > n_targets ) {
2012-04-10 21:43:09 +04:00
rc = - EINVAL ;
goto error ;
}
2011-07-02 02:31:36 +04:00
rc = nfc_activate_target ( dev , addr - > target_idx , addr - > nfc_protocol ) ;
if ( rc )
goto put_dev ;
nfc_rawsock ( sk ) - > dev = dev ;
nfc_rawsock ( sk ) - > target_idx = addr - > target_idx ;
sock - > state = SS_CONNECTED ;
sk - > sk_state = TCP_ESTABLISHED ;
sk - > sk_state_change ( sk ) ;
release_sock ( sk ) ;
return 0 ;
put_dev :
nfc_put_device ( dev ) ;
error :
release_sock ( sk ) ;
return rc ;
}
static int rawsock_add_header ( struct sk_buff * skb )
{
networking: make skb_push & __skb_push return void pointers
It seems like a historic accident that these return unsigned char *,
and in many places that means casts are required, more often than not.
Make these functions return void * and remove all the casts across
the tree, adding a (u8 *) cast only where the unsigned char pointer
was used directly, all done with the following spatch:
@@
expression SKB, LEN;
typedef u8;
identifier fn = { skb_push, __skb_push, skb_push_rcsum };
@@
- *(fn(SKB, LEN))
+ *(u8 *)fn(SKB, LEN)
@@
expression E, SKB, LEN;
identifier fn = { skb_push, __skb_push, skb_push_rcsum };
type T;
@@
- E = ((T *)(fn(SKB, LEN)))
+ E = fn(SKB, LEN)
@@
expression SKB, LEN;
identifier fn = { skb_push, __skb_push, skb_push_rcsum };
@@
- fn(SKB, LEN)[0]
+ *(u8 *)fn(SKB, LEN)
Note that the last part there converts from push(...)[0] to the
more idiomatic *(u8 *)push(...).
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:23 +03:00
* ( u8 * ) skb_push ( skb , NFC_HEADER_SIZE ) = 0 ;
2011-07-02 02:31:36 +04:00
return 0 ;
}
static void rawsock_data_exchange_complete ( void * context , struct sk_buff * skb ,
2012-03-05 04:03:53 +04:00
int err )
2011-07-02 02:31:36 +04:00
{
struct sock * sk = ( struct sock * ) context ;
BUG_ON ( in_irq ( ) ) ;
2011-11-29 23:37:33 +04:00
pr_debug ( " sk=%p err=%d \n " , sk , err ) ;
2011-07-02 02:31:36 +04:00
if ( err )
goto error ;
err = rawsock_add_header ( skb ) ;
if ( err )
2013-07-10 12:55:37 +04:00
goto error_skb ;
2011-07-02 02:31:36 +04:00
err = sock_queue_rcv_skb ( sk , skb ) ;
if ( err )
2013-07-10 12:55:37 +04:00
goto error_skb ;
2011-07-02 02:31:36 +04:00
spin_lock_bh ( & sk - > sk_write_queue . lock ) ;
if ( ! skb_queue_empty ( & sk - > sk_write_queue ) )
schedule_work ( & nfc_rawsock ( sk ) - > tx_work ) ;
else
nfc_rawsock ( sk ) - > tx_work_scheduled = false ;
spin_unlock_bh ( & sk - > sk_write_queue . lock ) ;
sock_put ( sk ) ;
return ;
2013-07-10 12:55:37 +04:00
error_skb :
kfree_skb ( skb ) ;
2011-07-02 02:31:36 +04:00
error :
rawsock_report_error ( sk , err ) ;
sock_put ( sk ) ;
}
static void rawsock_tx_work ( struct work_struct * work )
{
struct sock * sk = to_rawsock_sk ( work ) ;
struct nfc_dev * dev = nfc_rawsock ( sk ) - > dev ;
u32 target_idx = nfc_rawsock ( sk ) - > target_idx ;
struct sk_buff * skb ;
int rc ;
2011-11-29 23:37:33 +04:00
pr_debug ( " sk=%p target_idx=%u \n " , sk , target_idx ) ;
2011-07-02 02:31:36 +04:00
if ( sk - > sk_shutdown & SEND_SHUTDOWN ) {
rawsock_write_queue_purge ( sk ) ;
return ;
}
skb = skb_dequeue ( & sk - > sk_write_queue ) ;
sock_hold ( sk ) ;
rc = nfc_data_exchange ( dev , target_idx , skb ,
2012-03-05 04:03:53 +04:00
rawsock_data_exchange_complete , sk ) ;
2011-07-02 02:31:36 +04:00
if ( rc ) {
rawsock_report_error ( sk , rc ) ;
sock_put ( sk ) ;
}
}
2015-03-02 10:37:48 +03:00
static int rawsock_sendmsg ( struct socket * sock , struct msghdr * msg , size_t len )
2011-07-02 02:31:36 +04:00
{
struct sock * sk = sock - > sk ;
2011-08-19 17:47:11 +04:00
struct nfc_dev * dev = nfc_rawsock ( sk ) - > dev ;
2011-07-02 02:31:36 +04:00
struct sk_buff * skb ;
int rc ;
2011-11-29 23:37:33 +04:00
pr_debug ( " sock=%p sk=%p len=%zu \n " , sock , sk , len ) ;
2011-07-02 02:31:36 +04:00
if ( msg - > msg_namelen )
return - EOPNOTSUPP ;
if ( sock - > state ! = SS_CONNECTED )
return - ENOTCONN ;
2011-12-14 19:43:06 +04:00
skb = nfc_alloc_send_skb ( dev , sk , msg - > msg_flags , len , & rc ) ;
if ( skb = = NULL )
2011-07-02 02:31:36 +04:00
return rc ;
2014-04-07 05:25:44 +04:00
rc = memcpy_from_msg ( skb_put ( skb , len ) , msg , len ) ;
2011-07-02 02:31:36 +04:00
if ( rc < 0 ) {
kfree_skb ( skb ) ;
return rc ;
}
spin_lock_bh ( & sk - > sk_write_queue . lock ) ;
__skb_queue_tail ( & sk - > sk_write_queue , skb ) ;
if ( ! nfc_rawsock ( sk ) - > tx_work_scheduled ) {
schedule_work ( & nfc_rawsock ( sk ) - > tx_work ) ;
nfc_rawsock ( sk ) - > tx_work_scheduled = true ;
}
spin_unlock_bh ( & sk - > sk_write_queue . lock ) ;
return len ;
}
2015-03-02 10:37:48 +03:00
static int rawsock_recvmsg ( struct socket * sock , struct msghdr * msg , size_t len ,
int flags )
2011-07-02 02:31:36 +04:00
{
int noblock = flags & MSG_DONTWAIT ;
struct sock * sk = sock - > sk ;
struct sk_buff * skb ;
int copied ;
int rc ;
2011-11-29 23:37:33 +04:00
pr_debug ( " sock=%p sk=%p len=%zu flags=%d \n " , sock , sk , len , flags ) ;
2011-07-02 02:31:36 +04:00
skb = skb_recv_datagram ( sk , flags , noblock , & rc ) ;
if ( ! skb )
return rc ;
copied = skb - > len ;
if ( len < copied ) {
msg - > msg_flags | = MSG_TRUNC ;
copied = len ;
}
2014-11-06 00:46:40 +03:00
rc = skb_copy_datagram_msg ( skb , 0 , msg , copied ) ;
2011-07-02 02:31:36 +04:00
skb_free_datagram ( sk , skb ) ;
return rc ? : copied ;
}
static const struct proto_ops rawsock_ops = {
. family = PF_NFC ,
. owner = THIS_MODULE ,
. release = rawsock_release ,
. bind = sock_no_bind ,
. connect = rawsock_connect ,
. socketpair = sock_no_socketpair ,
. accept = sock_no_accept ,
. getname = sock_no_getname ,
2018-06-28 19:43:44 +03:00
. poll = datagram_poll ,
2011-07-02 02:31:36 +04:00
. ioctl = sock_no_ioctl ,
. listen = sock_no_listen ,
. shutdown = sock_no_shutdown ,
. setsockopt = sock_no_setsockopt ,
. getsockopt = sock_no_getsockopt ,
. sendmsg = rawsock_sendmsg ,
. recvmsg = rawsock_recvmsg ,
. mmap = sock_no_mmap ,
} ;
2014-05-05 14:43:31 +04:00
static const struct proto_ops rawsock_raw_ops = {
. family = PF_NFC ,
. owner = THIS_MODULE ,
. release = rawsock_release ,
. bind = sock_no_bind ,
. connect = sock_no_connect ,
. socketpair = sock_no_socketpair ,
. accept = sock_no_accept ,
. getname = sock_no_getname ,
2018-06-28 19:43:44 +03:00
. poll = datagram_poll ,
2014-05-05 14:43:31 +04:00
. ioctl = sock_no_ioctl ,
. listen = sock_no_listen ,
. shutdown = sock_no_shutdown ,
. setsockopt = sock_no_setsockopt ,
. getsockopt = sock_no_getsockopt ,
. sendmsg = sock_no_sendmsg ,
. recvmsg = rawsock_recvmsg ,
. mmap = sock_no_mmap ,
} ;
2011-07-02 02:31:36 +04:00
static void rawsock_destruct ( struct sock * sk )
{
2011-11-29 23:37:33 +04:00
pr_debug ( " sk=%p \n " , sk ) ;
2011-07-02 02:31:36 +04:00
if ( sk - > sk_state = = TCP_ESTABLISHED ) {
nfc_deactivate_target ( nfc_rawsock ( sk ) - > dev ,
2015-10-26 00:54:43 +03:00
nfc_rawsock ( sk ) - > target_idx ,
NFC_TARGET_MODE_IDLE ) ;
2011-07-02 02:31:36 +04:00
nfc_put_device ( nfc_rawsock ( sk ) - > dev ) ;
}
skb_queue_purge ( & sk - > sk_receive_queue ) ;
if ( ! sock_flag ( sk , SOCK_DEAD ) ) {
2011-11-29 23:37:32 +04:00
pr_err ( " Freeing alive NFC raw socket %p \n " , sk ) ;
2011-07-02 02:31:36 +04:00
return ;
}
}
static int rawsock_create ( struct net * net , struct socket * sock ,
2015-05-09 05:09:13 +03:00
const struct nfc_protocol * nfc_proto , int kern )
2011-07-02 02:31:36 +04:00
{
struct sock * sk ;
2011-11-29 23:37:33 +04:00
pr_debug ( " sock=%p \n " , sock ) ;
2011-07-02 02:31:36 +04:00
2014-05-05 14:43:31 +04:00
if ( ( sock - > type ! = SOCK_SEQPACKET ) & & ( sock - > type ! = SOCK_RAW ) )
2011-07-02 02:31:36 +04:00
return - ESOCKTNOSUPPORT ;
2014-05-05 14:43:31 +04:00
if ( sock - > type = = SOCK_RAW )
sock - > ops = & rawsock_raw_ops ;
else
sock - > ops = & rawsock_ops ;
2011-07-02 02:31:36 +04:00
2015-05-09 05:09:13 +03:00
sk = sk_alloc ( net , PF_NFC , GFP_ATOMIC , nfc_proto - > proto , kern ) ;
2011-07-02 02:31:36 +04:00
if ( ! sk )
return - ENOMEM ;
sock_init_data ( sock , sk ) ;
sk - > sk_protocol = nfc_proto - > id ;
sk - > sk_destruct = rawsock_destruct ;
sock - > state = SS_UNCONNECTED ;
2014-05-05 14:43:31 +04:00
if ( sock - > type = = SOCK_RAW )
nfc_sock_link ( & raw_sk_list , sk ) ;
else {
INIT_WORK ( & nfc_rawsock ( sk ) - > tx_work , rawsock_tx_work ) ;
nfc_rawsock ( sk ) - > tx_work_scheduled = false ;
}
2011-07-02 02:31:36 +04:00
return 0 ;
}
2014-05-05 14:43:31 +04:00
void nfc_send_to_raw_sock ( struct nfc_dev * dev , struct sk_buff * skb ,
u8 payload_type , u8 direction )
{
struct sk_buff * skb_copy = NULL , * nskb ;
struct sock * sk ;
u8 * data ;
read_lock ( & raw_sk_list . lock ) ;
sk_for_each ( sk , & raw_sk_list . head ) {
if ( ! skb_copy ) {
2014-06-12 02:36:26 +04:00
skb_copy = __pskb_copy_fclone ( skb , NFC_RAW_HEADER_SIZE ,
GFP_ATOMIC , true ) ;
2014-05-05 14:43:31 +04:00
if ( ! skb_copy )
continue ;
data = skb_push ( skb_copy , NFC_RAW_HEADER_SIZE ) ;
data [ 0 ] = dev ? dev - > idx : 0xFF ;
data [ 1 ] = direction & 0x01 ;
data [ 1 ] | = ( payload_type < < 1 ) ;
}
nskb = skb_clone ( skb_copy , GFP_ATOMIC ) ;
if ( ! nskb )
continue ;
if ( sock_queue_rcv_skb ( sk , nskb ) )
kfree_skb ( nskb ) ;
}
read_unlock ( & raw_sk_list . lock ) ;
kfree_skb ( skb_copy ) ;
}
EXPORT_SYMBOL ( nfc_send_to_raw_sock ) ;
2011-07-02 02:31:36 +04:00
static struct proto rawsock_proto = {
. name = " NFC_RAW " ,
. owner = THIS_MODULE ,
. obj_size = sizeof ( struct nfc_rawsock ) ,
} ;
static const struct nfc_protocol rawsock_nfc_proto = {
. id = NFC_SOCKPROTO_RAW ,
. proto = & rawsock_proto ,
. owner = THIS_MODULE ,
. create = rawsock_create
} ;
int __init rawsock_init ( void )
{
int rc ;
rc = nfc_proto_register ( & rawsock_nfc_proto ) ;
return rc ;
}
void rawsock_exit ( void )
{
nfc_proto_unregister ( & rawsock_nfc_proto ) ;
}