aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/dccp/ccid.h46
-rw-r--r--net/dccp/ccids/ccid3.c14
-rw-r--r--net/dccp/options.c16
3 files changed, 35 insertions, 41 deletions
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h
index 20ba066b2775..bce517c99996 100644
--- a/net/dccp/ccid.h
+++ b/net/dccp/ccid.h
@@ -60,18 +60,14 @@ struct ccid_operations {
60 void (*ccid_hc_tx_exit)(struct sock *sk); 60 void (*ccid_hc_tx_exit)(struct sock *sk);
61 void (*ccid_hc_rx_packet_recv)(struct sock *sk, 61 void (*ccid_hc_rx_packet_recv)(struct sock *sk,
62 struct sk_buff *skb); 62 struct sk_buff *skb);
63 int (*ccid_hc_rx_parse_options)(struct sock *sk, 63 int (*ccid_hc_rx_parse_options)(struct sock *sk, u8 pkt,
64 unsigned char option, 64 u8 opt, u8 *val, u8 len);
65 unsigned char len, u16 idx,
66 unsigned char* value);
67 int (*ccid_hc_rx_insert_options)(struct sock *sk, 65 int (*ccid_hc_rx_insert_options)(struct sock *sk,
68 struct sk_buff *skb); 66 struct sk_buff *skb);
69 void (*ccid_hc_tx_packet_recv)(struct sock *sk, 67 void (*ccid_hc_tx_packet_recv)(struct sock *sk,
70 struct sk_buff *skb); 68 struct sk_buff *skb);
71 int (*ccid_hc_tx_parse_options)(struct sock *sk, 69 int (*ccid_hc_tx_parse_options)(struct sock *sk, u8 pkt,
72 unsigned char option, 70 u8 opt, u8 *val, u8 len);
73 unsigned char len, u16 idx,
74 unsigned char* value);
75 int (*ccid_hc_tx_send_packet)(struct sock *sk, 71 int (*ccid_hc_tx_send_packet)(struct sock *sk,
76 struct sk_buff *skb); 72 struct sk_buff *skb);
77 void (*ccid_hc_tx_packet_sent)(struct sock *sk, 73 void (*ccid_hc_tx_packet_sent)(struct sock *sk,
@@ -163,27 +159,31 @@ static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk,
163 ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb); 159 ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb);
164} 160}
165 161
162/**
163 * ccid_hc_tx_parse_options - Parse CCID-specific options sent by the receiver
164 * @pkt: type of packet that @opt appears on (RFC 4340, 5.1)
165 * @opt: the CCID-specific option type (RFC 4340, 5.8 and 10.3)
166 * @val: value of @opt
167 * @len: length of @val in bytes
168 */
166static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk, 169static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
167 unsigned char option, 170 u8 pkt, u8 opt, u8 *val, u8 len)
168 unsigned char len, u16 idx,
169 unsigned char* value)
170{ 171{
171 int rc = 0; 172 if (ccid->ccid_ops->ccid_hc_tx_parse_options == NULL)
172 if (ccid->ccid_ops->ccid_hc_tx_parse_options != NULL) 173 return 0;
173 rc = ccid->ccid_ops->ccid_hc_tx_parse_options(sk, option, len, idx, 174 return ccid->ccid_ops->ccid_hc_tx_parse_options(sk, pkt, opt, val, len);
174 value);
175 return rc;
176} 175}
177 176
177/**
178 * ccid_hc_rx_parse_options - Parse CCID-specific options sent by the sender
179 * Arguments are analogous to ccid_hc_tx_parse_options()
180 */
178static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk, 181static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
179 unsigned char option, 182 u8 pkt, u8 opt, u8 *val, u8 len)
180 unsigned char len, u16 idx,
181 unsigned char* value)
182{ 183{
183 int rc = 0; 184 if (ccid->ccid_ops->ccid_hc_rx_parse_options == NULL)
184 if (ccid->ccid_ops->ccid_hc_rx_parse_options != NULL) 185 return 0;
185 rc = ccid->ccid_ops->ccid_hc_rx_parse_options(sk, option, len, idx, value); 186 return ccid->ccid_ops->ccid_hc_rx_parse_options(sk, pkt, opt, val, len);
186 return rc;
187} 187}
188 188
189static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk, 189static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 12b601f11bfd..4c422fb2189f 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -483,9 +483,8 @@ done_computing_x:
483 jiffies + usecs_to_jiffies(t_nfb)); 483 jiffies + usecs_to_jiffies(t_nfb));
484} 484}
485 485
486static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, 486static int ccid3_hc_tx_parse_options(struct sock *sk, u8 packet_type,
487 unsigned char len, u16 idx, 487 u8 option, u8 *optval, u8 optlen)
488 unsigned char *value)
489{ 488{
490 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); 489 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
491 struct ccid3_options_received *opt_recv = &hctx->options_received; 490 struct ccid3_options_received *opt_recv = &hctx->options_received;
@@ -494,12 +493,15 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
494 switch (option) { 493 switch (option) {
495 case TFRC_OPT_RECEIVE_RATE: 494 case TFRC_OPT_RECEIVE_RATE:
496 case TFRC_OPT_LOSS_EVENT_RATE: 495 case TFRC_OPT_LOSS_EVENT_RATE:
497 if (unlikely(len != 4)) { 496 /* Must be ignored on Data packets, cf. RFC 4342 8.3 and 8.5 */
497 if (packet_type == DCCP_PKT_DATA)
498 break;
499 if (unlikely(optlen != 4)) {
498 DCCP_WARN("%s(%p), invalid len %d for %u\n", 500 DCCP_WARN("%s(%p), invalid len %d for %u\n",
499 dccp_role(sk), sk, len, option); 501 dccp_role(sk), sk, optlen, option);
500 return -EINVAL; 502 return -EINVAL;
501 } 503 }
502 opt_val = ntohl(get_unaligned((__be32 *)value)); 504 opt_val = ntohl(get_unaligned((__be32 *)optval));
503 505
504 if (option == TFRC_OPT_RECEIVE_RATE) { 506 if (option == TFRC_OPT_RECEIVE_RATE) {
505 opt_recv->ccid3or_receive_rate = opt_val; 507 opt_recv->ccid3or_receive_rate = opt_val;
diff --git a/net/dccp/options.c b/net/dccp/options.c
index fd51cc70c63e..b102774694c6 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -226,23 +226,15 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
226 dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n", 226 dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n",
227 dccp_role(sk), elapsed_time); 227 dccp_role(sk), elapsed_time);
228 break; 228 break;
229 case 128 ... 191: { 229 case 128 ... 191:
230 const u16 idx = value - options;
231
232 if (ccid_hc_rx_parse_options(dp->dccps_hc_rx_ccid, sk, 230 if (ccid_hc_rx_parse_options(dp->dccps_hc_rx_ccid, sk,
233 opt, len, idx, 231 pkt_type, opt, value, len))
234 value) != 0)
235 goto out_invalid_option; 232 goto out_invalid_option;
236 }
237 break; 233 break;
238 case 192 ... 255: { 234 case 192 ... 255:
239 const u16 idx = value - options;
240
241 if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk, 235 if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk,
242 opt, len, idx, 236 pkt_type, opt, value, len))
243 value) != 0)
244 goto out_invalid_option; 237 goto out_invalid_option;
245 }
246 break; 238 break;
247 default: 239 default:
248 DCCP_CRIT("DCCP(%p): option %d(len=%d) not " 240 DCCP_CRIT("DCCP(%p): option %d(len=%d) not "