2016-04-04 16:00:34 +03:00
/* AF_RXRPC local endpoint management
*
* Copyright ( C ) 2007 Red Hat , Inc . All Rights Reserved .
* Written by David Howells ( dhowells @ redhat . com )
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version
* 2 of the License , or ( at your option ) any later version .
*/
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
# include <linux/module.h>
# include <linux/net.h>
# include <linux/skbuff.h>
# include <linux/slab.h>
# include <net/sock.h>
# include <net/af_rxrpc.h>
# include <generated/utsrelease.h>
# include "ar-internal.h"
static const char rxrpc_version_string [ 65 ] = " linux- " UTS_RELEASE " AF_RXRPC " ;
/*
* Reply to a version request
*/
static void rxrpc_send_version_request ( struct rxrpc_local * local ,
struct rxrpc_host_header * hdr ,
struct sk_buff * skb )
{
struct rxrpc_wire_header whdr ;
struct rxrpc_skb_priv * sp = rxrpc_skb ( skb ) ;
2016-09-13 10:49:05 +03:00
struct sockaddr_rxrpc srx ;
2016-04-04 16:00:34 +03:00
struct msghdr msg ;
struct kvec iov [ 2 ] ;
size_t len ;
int ret ;
_enter ( " " ) ;
2016-09-13 10:49:05 +03:00
if ( rxrpc_extract_addr_from_skb ( & srx , skb ) < 0 )
return ;
2016-04-04 16:00:34 +03:00
2016-09-13 10:49:05 +03:00
msg . msg_name = & srx . transport ;
msg . msg_namelen = srx . transport_len ;
2016-04-04 16:00:34 +03:00
msg . msg_control = NULL ;
msg . msg_controllen = 0 ;
msg . msg_flags = 0 ;
whdr . epoch = htonl ( sp - > hdr . epoch ) ;
whdr . cid = htonl ( sp - > hdr . cid ) ;
whdr . callNumber = htonl ( sp - > hdr . callNumber ) ;
whdr . seq = 0 ;
whdr . serial = 0 ;
whdr . type = RXRPC_PACKET_TYPE_VERSION ;
whdr . flags = RXRPC_LAST_PACKET | ( ~ hdr - > flags & RXRPC_CLIENT_INITIATED ) ;
whdr . userStatus = 0 ;
whdr . securityIndex = 0 ;
whdr . _rsvd = 0 ;
whdr . serviceId = htons ( sp - > hdr . serviceId ) ;
iov [ 0 ] . iov_base = & whdr ;
iov [ 0 ] . iov_len = sizeof ( whdr ) ;
iov [ 1 ] . iov_base = ( char * ) rxrpc_version_string ;
iov [ 1 ] . iov_len = sizeof ( rxrpc_version_string ) ;
len = iov [ 0 ] . iov_len + iov [ 1 ] . iov_len ;
_proto ( " Tx VERSION (reply) " ) ;
ret = kernel_sendmsg ( local - > socket , & msg , iov , 2 , len ) ;
if ( ret < 0 )
_debug ( " sendmsg failed: %d " , ret ) ;
_leave ( " " ) ;
}
/*
* Process event packets targetted at a local endpoint .
*/
2016-04-04 16:00:35 +03:00
void rxrpc_process_local_events ( struct rxrpc_local * local )
2016-04-04 16:00:34 +03:00
{
struct sk_buff * skb ;
char v ;
_enter ( " " ) ;
2016-04-04 16:00:35 +03:00
skb = skb_dequeue ( & local - > event_queue ) ;
if ( skb ) {
2016-04-04 16:00:34 +03:00
struct rxrpc_skb_priv * sp = rxrpc_skb ( skb ) ;
2016-09-17 12:49:14 +03:00
rxrpc_see_skb ( skb , rxrpc_skb_rx_seen ) ;
2016-04-04 16:00:34 +03:00
_debug ( " {%d},{%u} " , local - > debug_id , sp - > hdr . type ) ;
switch ( sp - > hdr . type ) {
case RXRPC_PACKET_TYPE_VERSION :
2016-09-30 15:26:03 +03:00
if ( skb_copy_bits ( skb , sizeof ( struct rxrpc_wire_header ) ,
& v , 1 ) < 0 )
2016-04-04 16:00:34 +03:00
return ;
_proto ( " Rx VERSION { %02x } " , v ) ;
if ( v = = 0 )
rxrpc_send_version_request ( local , & sp - > hdr , skb ) ;
break ;
default :
/* Just ignore anything we don't understand */
break ;
}
2016-09-17 12:49:14 +03:00
rxrpc_free_skb ( skb , rxrpc_skb_rx_freed ) ;
2016-04-04 16:00:34 +03:00
}
_leave ( " " ) ;
}