mirror of
https://github.com/fail0verflow/switch-linux.git
synced 2025-05-04 02:34:21 -04:00
[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: Arnaldo Carvalho de Melo <acme@mandriva.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
561713cf47
commit
88f964db6e
4 changed files with 100 additions and 6 deletions
|
@ -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 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#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 {
|
||||||
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,
|
||||||
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)
|
||||||
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 = {
|
||||||
.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,
|
||||||
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,
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue