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 future communication to that server and RXRPC_UPGRADE_SERVICE should no
longer be set. 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 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 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. 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 SECURITY

View File

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

View File

@ -581,6 +581,34 @@ error:
return ret; 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 * permit an RxRPC socket to be polled
*/ */
@ -784,7 +812,7 @@ static const struct proto_ops rxrpc_rpc_ops = {
.listen = rxrpc_listen, .listen = rxrpc_listen,
.shutdown = rxrpc_shutdown, .shutdown = rxrpc_shutdown,
.setsockopt = rxrpc_setsockopt, .setsockopt = rxrpc_setsockopt,
.getsockopt = sock_no_getsockopt, .getsockopt = rxrpc_getsockopt,
.sendmsg = rxrpc_sendmsg, .sendmsg = rxrpc_sendmsg,
.recvmsg = rxrpc_recvmsg, .recvmsg = rxrpc_recvmsg,
.mmap = sock_no_mmap, .mmap = sock_no_mmap,