Skip to content

Commit

Permalink
[DCCP]: Introduce CCID getsockopt for the CCIDs
Browse files Browse the repository at this point in the history
Allocation for the optnames is similar to the DCCP options, with a
range for rx and tx half connection CCIDs.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Arnaldo Carvalho de Melo authored and David S. Miller committed Sep 18, 2005
1 parent 561713c commit 88f964d
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 6 deletions.
2 changes: 2 additions & 0 deletions include/linux/dccp.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@ enum {
/* DCCP socket options */
#define DCCP_SOCKOPT_PACKET_SIZE 1
#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

Expand Down
31 changes: 31 additions & 0 deletions net/dccp/ccid.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*/

#include <net/sock.h>
#include <linux/compiler.h>
#include <linux/dccp.h>
#include <linux/list.h>
#include <linux/module.h>
Expand Down Expand Up @@ -54,6 +55,14 @@ struct ccid {
struct tcp_info *info);
void (*ccid_hc_tx_get_info)(struct sock *sk,
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);
Expand Down Expand Up @@ -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)
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 */
56 changes: 56 additions & 0 deletions net/dccp/ccids/ccid3.c
Original file line number Diff line number Diff line change
Expand Up @@ -1120,6 +1120,60 @@ static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info)
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 = {
.ccid_id = 3,
.ccid_name = "ccid3",
Expand All @@ -1139,6 +1193,8 @@ static struct ccid ccid3 = {
.ccid_hc_rx_packet_recv = ccid3_hc_rx_packet_recv,
.ccid_hc_rx_get_info = ccid3_hc_rx_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);
Expand Down
17 changes: 11 additions & 6 deletions net/dccp/proto.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,20 +325,25 @@ int dccp_getsockopt(struct sock *sk, int level, int optname,
if (get_user(len, optlen))
return -EFAULT;

if (optname == DCCP_SOCKOPT_SERVICE)
return dccp_getsockopt_service(sk, len,
(u32 __user *)optval, optlen);

len = min_t(unsigned int, len, sizeof(int));
if (len < 0)
if (len < sizeof(int))
return -EINVAL;

dp = dccp_sk(sk);

switch (optname) {
case DCCP_SOCKOPT_PACKET_SIZE:
val = dp->dccps_packet_size;
len = sizeof(dp->dccps_packet_size);
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:
return -ENOPROTOOPT;
}
Expand Down

0 comments on commit 88f964d

Please sign in to comment.