rxrpc: Provide a getsockopt call to query what cmsgs types are supported

Provide a getsockopt() call that can query what cmsg types are supported by
AF_RXRPC.
This commit is contained in:
David Howells 2017-06-07 16:27:15 +01:00
parent 216fe8f021
commit 515559ca21
3 changed files with 52 additions and 11 deletions

View File

@ -406,6 +406,10 @@ calls, to invoke certain actions and to report certain conditions. These are:
future communication to that server and RXRPC_UPGRADE_SERVICE should no
longer be set.
The symbol RXRPC__SUPPORTED is defined as one more than the highest control
message type supported. At run time this can be queried by means of the
RXRPC_SUPPORTED_CMSG socket option (see below).
==============
SOCKET OPTIONS
@ -459,6 +463,11 @@ AF_RXRPC sockets support a few socket options at the SOL_RXRPC level:
must point to an array of two unsigned short ints. The first is the
service ID to upgrade from and the second the service ID to upgrade to.
(*) RXRPC_SUPPORTED_CMSG
This is a read-only option that writes an int into the buffer indicating
the highest control message type supported.
========
SECURITY

View File

@ -38,6 +38,7 @@ struct sockaddr_rxrpc {
#define RXRPC_EXCLUSIVE_CONNECTION 3 /* Deprecated; use RXRPC_EXCLUSIVE_CALL instead */
#define RXRPC_MIN_SECURITY_LEVEL 4 /* minimum security level */
#define RXRPC_UPGRADEABLE_SERVICE 5 /* Upgrade service[0] -> service[1] */
#define RXRPC_SUPPORTED_CMSG 6 /* Get highest supported control message type */
/*
* RxRPC control messages
@ -45,16 +46,19 @@ struct sockaddr_rxrpc {
* - terminal messages mean that a user call ID tag can be recycled
* - s/r/- indicate whether these are applicable to sendmsg() and/or recvmsg()
*/
#define RXRPC_USER_CALL_ID 1 /* sr: user call ID specifier */
#define RXRPC_ABORT 2 /* sr: abort request / notification [terminal] */
#define RXRPC_ACK 3 /* -r: [Service] RPC op final ACK received [terminal] */
#define RXRPC_NET_ERROR 5 /* -r: network error received [terminal] */
#define RXRPC_BUSY 6 /* -r: server busy received [terminal] */
#define RXRPC_LOCAL_ERROR 7 /* -r: local error generated [terminal] */
#define RXRPC_NEW_CALL 8 /* -r: [Service] new incoming call notification */
#define RXRPC_ACCEPT 9 /* s-: [Service] accept request */
#define RXRPC_EXCLUSIVE_CALL 10 /* s-: Call should be on exclusive connection */
#define RXRPC_UPGRADE_SERVICE 11 /* s-: Request service upgrade for client call */
enum rxrpc_cmsg_type {
RXRPC_USER_CALL_ID = 1, /* sr: user call ID specifier */
RXRPC_ABORT = 2, /* sr: abort request / notification [terminal] */
RXRPC_ACK = 3, /* -r: [Service] RPC op final ACK received [terminal] */
RXRPC_NET_ERROR = 5, /* -r: network error received [terminal] */
RXRPC_BUSY = 6, /* -r: server busy received [terminal] */
RXRPC_LOCAL_ERROR = 7, /* -r: local error generated [terminal] */
RXRPC_NEW_CALL = 8, /* -r: [Service] new incoming call notification */
RXRPC_ACCEPT = 9, /* s-: [Service] accept request */
RXRPC_EXCLUSIVE_CALL = 10, /* s-: Call should be on exclusive connection */
RXRPC_UPGRADE_SERVICE = 11, /* s-: Request service upgrade for client call */
RXRPC__SUPPORTED
};
/*
* RxRPC security levels

View File

@ -581,6 +581,34 @@ error:
return ret;
}
/*
* Get socket options.
*/
static int rxrpc_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *_optlen)
{
int optlen;
if (level != SOL_RXRPC)
return -EOPNOTSUPP;
if (get_user(optlen, _optlen))
return -EFAULT;
switch (optname) {
case RXRPC_SUPPORTED_CMSG:
if (optlen < sizeof(int))
return -ETOOSMALL;
if (put_user(RXRPC__SUPPORTED - 1, (int __user *)optval) ||
put_user(sizeof(int), _optlen))
return -EFAULT;
return 0;
default:
return -EOPNOTSUPP;
}
}
/*
* permit an RxRPC socket to be polled
*/
@ -784,7 +812,7 @@ static const struct proto_ops rxrpc_rpc_ops = {
.listen = rxrpc_listen,
.shutdown = rxrpc_shutdown,
.setsockopt = rxrpc_setsockopt,
.getsockopt = sock_no_getsockopt,
.getsockopt = rxrpc_getsockopt,
.sendmsg = rxrpc_sendmsg,
.recvmsg = rxrpc_recvmsg,
.mmap = sock_no_mmap,