aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2010-09-19 14:06:50 -0400
committerGerrit Renker <gerrit@erg.abdn.ac.uk>2010-09-21 06:14:25 -0400
commit4874c131d79695e3d372042781a408a1a8a762d8 (patch)
treee3c6bf89f191b47e019f063d16c3e5d6c4fc0623 /net
parent462fb2af9788a82a534f8184abfde31574e1cfa0 (diff)
dccp: Add packet type information to CCID-specific option parsing
This 1. adds packet type information to ccid_hc_{rx,tx}_parse_options(). This is necessary, since table 3 in RFC 4340, 5.8 leaves it to the CCIDs to state which options may (not) appear on what packet type. 2. adds such a check for CCID-3's {Loss Event, Receive} Rate as specified in RFC 4340 8.3 ("Receive Rate options MUST NOT be sent on DCCP-Data packets") and 8.5 ("Loss Event Rate options MUST NOT be sent on DCCP-Data packets"). 3. removes an unused argument `idx' from ccid_hc_{rx,tx}_parse_options(). This is also no longer necessary, since the CCID-specific option-parsing routines are passed every single parameter of the type-length-value option encoding. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Diffstat (limited to 'net')
-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 6df6f8ac9636..6d16a9070ff0 100644
--- a/net/dccp/ccid.h
+++ b/net/dccp/ccid.h
@@ -62,18 +62,14 @@ struct ccid_operations {
62 void (*ccid_hc_tx_exit)(struct sock *sk); 62 void (*ccid_hc_tx_exit)(struct sock *sk);
63 void (*ccid_hc_rx_packet_recv)(struct sock *sk, 63 void (*ccid_hc_rx_packet_recv)(struct sock *sk,
64 struct sk_buff *skb); 64 struct sk_buff *skb);
65 int (*ccid_hc_rx_parse_options)(struct sock *sk, 65 int (*ccid_hc_rx_parse_options)(struct sock *sk, u8 pkt,
66 unsigned char option, 66 u8 opt, u8 *val, u8 len);
67 unsigned char len, u16 idx,
68 unsigned char* value);
69 int (*ccid_hc_rx_insert_options)(struct sock *sk, 67 int (*ccid_hc_rx_insert_options)(struct sock *sk,
70 struct sk_buff *skb); 68 struct sk_buff *skb);
71 void (*ccid_hc_tx_packet_recv)(struct sock *sk, 69 void (*ccid_hc_tx_packet_recv)(struct sock *sk,
72 struct sk_buff *skb); 70 struct sk_buff *skb);
73 int (*ccid_hc_tx_parse_options)(struct sock *sk, 71 int (*ccid_hc_tx_parse_options)(struct sock *sk, u8 pkt,
74 unsigned char option, 72 u8 opt, u8 *val, u8 len);
75 unsigned char len, u16 idx,
76 unsigned char* value);
77 int (*ccid_hc_tx_send_packet)(struct sock *sk, 73 int (*ccid_hc_tx_send_packet)(struct sock *sk,
78 struct sk_buff *skb); 74 struct sk_buff *skb);
79 void (*ccid_hc_tx_packet_sent)(struct sock *sk, 75 void (*ccid_hc_tx_packet_sent)(struct sock *sk,
@@ -168,27 +164,31 @@ static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk,
168 ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb); 164 ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb);
169} 165}
170 166
167/**
168 * ccid_hc_tx_parse_options - Parse CCID-specific options sent by the receiver
169 * @pkt: type of packet that @opt appears on (RFC 4340, 5.1)
170 * @opt: the CCID-specific option type (RFC 4340, 5.8 and 10.3)
171 * @val: value of @opt
172 * @len: length of @val in bytes
173 */
171static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk, 174static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
172 unsigned char option, 175 u8 pkt, u8 opt, u8 *val, u8 len)
173 unsigned char len, u16 idx,
174 unsigned char* value)
175{ 176{
176 int rc = 0; 177 if (ccid->ccid_ops->ccid_hc_tx_parse_options == NULL)
177 if (ccid->ccid_ops->ccid_hc_tx_parse_options != NULL) 178 return 0;
178 rc = ccid->ccid_ops->ccid_hc_tx_parse_options(sk, option, len, idx, 179 return ccid->ccid_ops->ccid_hc_tx_parse_options(sk, pkt, opt, val, len);
179 value);
180 return rc;
181} 180}
182 181
182/**
183 * ccid_hc_rx_parse_options - Parse CCID-specific options sent by the sender
184 * Arguments are analogous to ccid_hc_tx_parse_options()
185 */
183static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk, 186static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
184 unsigned char option, 187 u8 pkt, u8 opt, u8 *val, u8 len)
185 unsigned char len, u16 idx,
186 unsigned char* value)
187{ 188{
188 int rc = 0; 189 if (ccid->ccid_ops->ccid_hc_rx_parse_options == NULL)
189 if (ccid->ccid_ops->ccid_hc_rx_parse_options != NULL) 190 return 0;
190 rc = ccid->ccid_ops->ccid_hc_rx_parse_options(sk, option, len, idx, value); 191 return ccid->ccid_ops->ccid_hc_rx_parse_options(sk, pkt, opt, val, len);
191 return rc;
192} 192}
193 193
194static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk, 194static 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 ce8059130070..be1b8baaf298 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -481,9 +481,8 @@ done_computing_x:
481 jiffies + usecs_to_jiffies(t_nfb)); 481 jiffies + usecs_to_jiffies(t_nfb));
482} 482}
483 483
484static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, 484static int ccid3_hc_tx_parse_options(struct sock *sk, u8 packet_type,
485 unsigned char len, u16 idx, 485 u8 option, u8 *optval, u8 optlen)
486 unsigned char *value)
487{ 486{
488 struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk); 487 struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
489 struct ccid3_options_received *opt_recv = &hc->tx_options_received; 488 struct ccid3_options_received *opt_recv = &hc->tx_options_received;
@@ -492,12 +491,15 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
492 switch (option) { 491 switch (option) {
493 case TFRC_OPT_RECEIVE_RATE: 492 case TFRC_OPT_RECEIVE_RATE:
494 case TFRC_OPT_LOSS_EVENT_RATE: 493 case TFRC_OPT_LOSS_EVENT_RATE:
495 if (unlikely(len != 4)) { 494 /* Must be ignored on Data packets, cf. RFC 4342 8.3 and 8.5 */
495 if (packet_type == DCCP_PKT_DATA)
496 break;
497 if (unlikely(optlen != 4)) {
496 DCCP_WARN("%s(%p), invalid len %d for %u\n", 498 DCCP_WARN("%s(%p), invalid len %d for %u\n",
497 dccp_role(sk), sk, len, option); 499 dccp_role(sk), sk, optlen, option);
498 return -EINVAL; 500 return -EINVAL;
499 } 501 }
500 opt_val = ntohl(get_unaligned((__be32 *)value)); 502 opt_val = ntohl(get_unaligned((__be32 *)optval));
501 503
502 if (option == TFRC_OPT_RECEIVE_RATE) { 504 if (option == TFRC_OPT_RECEIVE_RATE) {
503 opt_recv->ccid3or_receive_rate = opt_val; 505 opt_recv->ccid3or_receive_rate = opt_val;
diff --git a/net/dccp/options.c b/net/dccp/options.c
index bfda087bd90d..e4983e3d2616 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 "