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.
 
      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
 
 ==============
 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.
 
      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
 
 ========
 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_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
 
 /*
  * 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()
  */
  * - 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
 
 /*
  * RxRPC security levels
index 0c4dc4a7832c9fd7c1a45fd9a4d06860101c2205..44a52b82bb5dd08b27f0237108bc2b6ae84033e6 100644 (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,
        .shutdown       = rxrpc_shutdown,
        .setsockopt     = rxrpc_setsockopt,
        .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,
        .sendmsg        = rxrpc_sendmsg,
        .recvmsg        = rxrpc_recvmsg,
        .mmap           = sock_no_mmap,