rxrpc: Provide a getsockopt call to query what cmsgs types are supported
authorDavid Howells <dhowells@redhat.com>
Wed, 7 Jun 2017 15:27:15 +0000 (16:27 +0100)
committerDavid Howells <dhowells@redhat.com>
Wed, 7 Jun 2017 16:15:46 +0000 (17:15 +0100)
Provide a getsockopt() call that can query what cmsg types are supported by
AF_RXRPC.

Documentation/networking/rxrpc.txt
include/linux/rxrpc.h
net/rxrpc/af_rxrpc.c

index 18078e630a6325abdd9746a7c385ec8867bcbd15..bce8e10a2a8e690819fe2d629a2c1c657d799922 100644 (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
index 707910c6c6c5ec0258e2d8377125b99a4fe7bb59..bdd3175b9a489298a89f10ef527df3c951f6292a 100644 (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
index 0c4dc4a7832c9fd7c1a45fd9a4d06860101c2205..44a52b82bb5dd08b27f0237108bc2b6ae84033e6 100644 (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,