Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 111462
b: refs/heads/master
c: 668144f
h: refs/heads/master
v: v3
  • Loading branch information
Gerrit Renker committed Sep 4, 2008
1 parent a7197dc commit 7991be9
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 106 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d4c8741c431e07cfc66eb2b4c3a17b8d4975d9c0
refs/heads/master: 668144f7b41716a9efe1b398e15ead32a26cd101
7 changes: 0 additions & 7 deletions trunk/include/linux/dccp.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,13 +193,6 @@ enum dccp_feature_numbers {
DCCPF_MAX_CCID_SPECIFIC = 255,
};

/* this structure is argument to DCCP_SOCKOPT_CHANGE_X */
struct dccp_so_feat {
__u8 dccpsf_feat;
__u8 __user *dccpsf_val;
__u8 dccpsf_len;
};

/* DCCP socket options */
#define DCCP_SOCKOPT_PACKET_SIZE 1 /* XXX deprecated, without effect */
#define DCCP_SOCKOPT_SERVICE 2
Expand Down
72 changes: 27 additions & 45 deletions trunk/net/dccp/feat.c
Original file line number Diff line number Diff line change
Expand Up @@ -393,53 +393,35 @@ static int __feat_register_sp(struct list_head *fn, u8 feat, u8 is_local,
return dccp_feat_push_change(fn, feat, is_local, mandatory, &fval);
}

int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature,
u8 *val, u8 len, gfp_t gfp)
{
struct dccp_opt_pend *opt;

dccp_feat_debug(type, feature, *val);

if (len > 3) {
DCCP_WARN("invalid length %d\n", len);
/**
* dccp_feat_register_sp - Register requests to change SP feature values
* @sk: client or listening socket
* @feat: one of %dccp_feature_numbers
* @is_local: whether the local (1) or remote (0) @feat is meant
* @list: array of preferred values, in descending order of preference
* @len: length of @list in bytes
*/
int dccp_feat_register_sp(struct sock *sk, u8 feat, u8 is_local,
u8 const *list, u8 len)
{ /* any changes must be registered before establishing the connection */
if (sk->sk_state != DCCP_CLOSED)
return -EISCONN;
if (dccp_feat_type(feat) != FEAT_SP)
return -EINVAL;
}
/* XXX add further sanity checks */

/* check if that feature is already being negotiated */
list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) {
/* ok we found a negotiation for this option already */
if (opt->dccpop_feat == feature && opt->dccpop_type == type) {
dccp_pr_debug("Replacing old\n");
/* replace */
BUG_ON(opt->dccpop_val == NULL);
kfree(opt->dccpop_val);
opt->dccpop_val = val;
opt->dccpop_len = len;
opt->dccpop_conf = 0;
return 0;
}
}

/* negotiation for a new feature */
opt = kmalloc(sizeof(*opt), gfp);
if (opt == NULL)
return -ENOMEM;

opt->dccpop_type = type;
opt->dccpop_feat = feature;
opt->dccpop_len = len;
opt->dccpop_val = val;
opt->dccpop_conf = 0;
opt->dccpop_sc = NULL;

BUG_ON(opt->dccpop_val == NULL);

list_add_tail(&opt->dccpop_node, &dmsk->dccpms_pending);
return 0;
return __feat_register_sp(&dccp_sk(sk)->dccps_featneg, feat, is_local,
0, list, len);
}

EXPORT_SYMBOL_GPL(dccp_feat_change);
/* Analogous to dccp_feat_register_sp(), but for non-negotiable values */
int dccp_feat_register_nn(struct sock *sk, u8 feat, u64 val)
{
/* any changes must be registered before establishing the connection */
if (sk->sk_state != DCCP_CLOSED)
return -EISCONN;
if (dccp_feat_type(feat) != FEAT_NN)
return -EINVAL;
return __feat_register_nn(&dccp_sk(sk)->dccps_featneg, feat, 0, val);
}

/*
* Tracking features whose value depend on the choice of CCID
Expand Down Expand Up @@ -1137,7 +1119,7 @@ int dccp_feat_init(struct sock *sk)

/* Ack ratio */
rc = __feat_register_nn(&dp->dccps_featneg, DCCPF_ACK_RATIO, 0,
dmsk->dccpms_ack_ratio);
dp->dccps_l_ack_ratio);
out:
return rc;
}
Expand Down
5 changes: 3 additions & 2 deletions trunk/net/dccp/feat.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,9 @@ static inline void dccp_feat_debug(const u8 type, const u8 feat, const u8 val)
#define dccp_feat_debug(type, feat, val)
#endif /* CONFIG_IP_DCCP_DEBUG */

extern int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature,
u8 *val, u8 len, gfp_t gfp);
extern int dccp_feat_register_sp(struct sock *sk, u8 feat, u8 is_local,
u8 const *list, u8 len);
extern int dccp_feat_register_nn(struct sock *sk, u8 feat, u64 val);
extern int dccp_feat_change_recv(struct sock *sk, u8 type, u8 feature,
u8 *val, u8 len);
extern int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature,
Expand Down
53 changes: 2 additions & 51 deletions trunk/net/dccp/proto.c
Original file line number Diff line number Diff line change
Expand Up @@ -470,44 +470,6 @@ static int dccp_setsockopt_service(struct sock *sk, const __be32 service,
return 0;
}

/* byte 1 is feature. the rest is the preference list */
static int dccp_setsockopt_change(struct sock *sk, int type,
struct dccp_so_feat __user *optval)
{
struct dccp_so_feat opt;
u8 *val;
int rc;

if (copy_from_user(&opt, optval, sizeof(opt)))
return -EFAULT;
/*
* rfc4340: 6.1. Change Options
*/
if (opt.dccpsf_len < 1)
return -EINVAL;

val = kmalloc(opt.dccpsf_len, GFP_KERNEL);
if (!val)
return -ENOMEM;

if (copy_from_user(val, opt.dccpsf_val, opt.dccpsf_len)) {
rc = -EFAULT;
goto out_free_val;
}

rc = dccp_feat_change(dccp_msk(sk), type, opt.dccpsf_feat,
val, opt.dccpsf_len, GFP_KERNEL);
if (rc)
goto out_free_val;

out:
return rc;

out_free_val:
kfree(val);
goto out;
}

static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, int optlen)
{
Expand All @@ -530,20 +492,9 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
err = 0;
break;
case DCCP_SOCKOPT_CHANGE_L:
if (optlen != sizeof(struct dccp_so_feat))
err = -EINVAL;
else
err = dccp_setsockopt_change(sk, DCCPO_CHANGE_L,
(struct dccp_so_feat __user *)
optval);
break;
case DCCP_SOCKOPT_CHANGE_R:
if (optlen != sizeof(struct dccp_so_feat))
err = -EINVAL;
else
err = dccp_setsockopt_change(sk, DCCPO_CHANGE_R,
(struct dccp_so_feat __user *)
optval);
DCCP_WARN("sockopt(CHANGE_L/R) is deprecated: fix your app\n");
err = 0;
break;
case DCCP_SOCKOPT_SERVER_TIMEWAIT:
if (dp->dccps_role != DCCP_ROLE_SERVER)
Expand Down

0 comments on commit 7991be9

Please sign in to comment.