Commit 88f964db authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo Committed by David S. Miller

[DCCP]: Introduce CCID getsockopt for the CCIDs

Allocation for the optnames is similar to the DCCP options, with a
range for rx and tx half connection CCIDs.
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@mandriva.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 561713cf
...@@ -179,6 +179,8 @@ enum { ...@@ -179,6 +179,8 @@ enum {
/* DCCP socket options */ /* DCCP socket options */
#define DCCP_SOCKOPT_PACKET_SIZE 1 #define DCCP_SOCKOPT_PACKET_SIZE 1
#define DCCP_SOCKOPT_SERVICE 2 #define DCCP_SOCKOPT_SERVICE 2
#define DCCP_SOCKOPT_CCID_RX_INFO 128
#define DCCP_SOCKOPT_CCID_TX_INFO 192
#define DCCP_SERVICE_LIST_MAX_LEN 32 #define DCCP_SERVICE_LIST_MAX_LEN 32
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
*/ */
#include <net/sock.h> #include <net/sock.h>
#include <linux/compiler.h>
#include <linux/dccp.h> #include <linux/dccp.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -54,6 +55,14 @@ struct ccid { ...@@ -54,6 +55,14 @@ struct ccid {
struct tcp_info *info); struct tcp_info *info);
void (*ccid_hc_tx_get_info)(struct sock *sk, void (*ccid_hc_tx_get_info)(struct sock *sk,
struct tcp_info *info); struct tcp_info *info);
int (*ccid_hc_rx_getsockopt)(struct sock *sk,
const int optname, int len,
u32 __user *optval,
int __user *optlen);
int (*ccid_hc_tx_getsockopt)(struct sock *sk,
const int optname, int len,
u32 __user *optval,
int __user *optlen);
}; };
extern int ccid_register(struct ccid *ccid); extern int ccid_register(struct ccid *ccid);
...@@ -177,4 +186,26 @@ static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk, ...@@ -177,4 +186,26 @@ static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk,
if (ccid->ccid_hc_tx_get_info != NULL) if (ccid->ccid_hc_tx_get_info != NULL)
ccid->ccid_hc_tx_get_info(sk, info); ccid->ccid_hc_tx_get_info(sk, info);
} }
static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk,
const int optname, int len,
u32 __user *optval, int __user *optlen)
{
int rc = -ENOPROTOOPT;
if (ccid->ccid_hc_rx_getsockopt != NULL)
rc = ccid->ccid_hc_rx_getsockopt(sk, optname, len,
optval, optlen);
return rc;
}
static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk,
const int optname, int len,
u32 __user *optval, int __user *optlen)
{
int rc = -ENOPROTOOPT;
if (ccid->ccid_hc_tx_getsockopt != NULL)
rc = ccid->ccid_hc_tx_getsockopt(sk, optname, len,
optval, optlen);
return rc;
}
#endif /* _CCID_H */ #endif /* _CCID_H */
...@@ -1120,6 +1120,60 @@ static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info) ...@@ -1120,6 +1120,60 @@ static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info)
info->tcpi_rtt = hctx->ccid3hctx_rtt; info->tcpi_rtt = hctx->ccid3hctx_rtt;
} }
static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len,
u32 __user *optval, int __user *optlen)
{
const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
const void *val;
/* Listen socks doesn't have a private CCID block */
if (sk->sk_state == DCCP_LISTEN)
return -EINVAL;
switch (optname) {
case DCCP_SOCKOPT_CCID_RX_INFO:
if (len < sizeof(hcrx->ccid3hcrx_tfrc))
return -EINVAL;
len = sizeof(hcrx->ccid3hcrx_tfrc);
val = &hcrx->ccid3hcrx_tfrc;
break;
default:
return -ENOPROTOOPT;
}
if (put_user(len, optlen) || copy_to_user(optval, val, len))
return -EFAULT;
return 0;
}
static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len,
u32 __user *optval, int __user *optlen)
{
const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
const void *val;
/* Listen socks doesn't have a private CCID block */
if (sk->sk_state == DCCP_LISTEN)
return -EINVAL;
switch (optname) {
case DCCP_SOCKOPT_CCID_TX_INFO:
if (len < sizeof(hctx->ccid3hctx_tfrc))
return -EINVAL;
len = sizeof(hctx->ccid3hctx_tfrc);
val = &hctx->ccid3hctx_tfrc;
break;
default:
return -ENOPROTOOPT;
}
if (put_user(len, optlen) || copy_to_user(optval, val, len))
return -EFAULT;
return 0;
}
static struct ccid ccid3 = { static struct ccid ccid3 = {
.ccid_id = 3, .ccid_id = 3,
.ccid_name = "ccid3", .ccid_name = "ccid3",
...@@ -1139,6 +1193,8 @@ static struct ccid ccid3 = { ...@@ -1139,6 +1193,8 @@ static struct ccid ccid3 = {
.ccid_hc_rx_packet_recv = ccid3_hc_rx_packet_recv, .ccid_hc_rx_packet_recv = ccid3_hc_rx_packet_recv,
.ccid_hc_rx_get_info = ccid3_hc_rx_get_info, .ccid_hc_rx_get_info = ccid3_hc_rx_get_info,
.ccid_hc_tx_get_info = ccid3_hc_tx_get_info, .ccid_hc_tx_get_info = ccid3_hc_tx_get_info,
.ccid_hc_rx_getsockopt = ccid3_hc_rx_getsockopt,
.ccid_hc_tx_getsockopt = ccid3_hc_tx_getsockopt,
}; };
module_param(ccid3_debug, int, 0444); module_param(ccid3_debug, int, 0444);
......
...@@ -325,12 +325,7 @@ int dccp_getsockopt(struct sock *sk, int level, int optname, ...@@ -325,12 +325,7 @@ int dccp_getsockopt(struct sock *sk, int level, int optname,
if (get_user(len, optlen)) if (get_user(len, optlen))
return -EFAULT; return -EFAULT;
if (optname == DCCP_SOCKOPT_SERVICE) if (len < sizeof(int))
return dccp_getsockopt_service(sk, len,
(u32 __user *)optval, optlen);
len = min_t(unsigned int, len, sizeof(int));
if (len < 0)
return -EINVAL; return -EINVAL;
dp = dccp_sk(sk); dp = dccp_sk(sk);
...@@ -338,7 +333,17 @@ int dccp_getsockopt(struct sock *sk, int level, int optname, ...@@ -338,7 +333,17 @@ int dccp_getsockopt(struct sock *sk, int level, int optname,
switch (optname) { switch (optname) {
case DCCP_SOCKOPT_PACKET_SIZE: case DCCP_SOCKOPT_PACKET_SIZE:
val = dp->dccps_packet_size; val = dp->dccps_packet_size;
len = sizeof(dp->dccps_packet_size);
break; break;
case DCCP_SOCKOPT_SERVICE:
return dccp_getsockopt_service(sk, len,
(u32 __user *)optval, optlen);
case 128 ... 191:
return ccid_hc_rx_getsockopt(dp->dccps_hc_rx_ccid, sk, optname,
len, (u32 __user *)optval, optlen);
case 192 ... 255:
return ccid_hc_tx_getsockopt(dp->dccps_hc_tx_ccid, sk, optname,
len, (u32 __user *)optval, optlen);
default: default:
return -ENOPROTOOPT; return -ENOPROTOOPT;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment