diff options
| -rw-r--r-- | include/linux/dccp.h | 12 | ||||
| -rw-r--r-- | net/dccp/ccids/ccid2.c | 4 | ||||
| -rw-r--r-- | net/dccp/ccids/ccid3.c | 15 | ||||
| -rw-r--r-- | net/dccp/input.c | 48 | ||||
| -rw-r--r-- | net/dccp/ipv4.c | 6 | ||||
| -rw-r--r-- | net/dccp/ipv6.c | 4 | ||||
| -rw-r--r-- | net/dccp/options.c | 33 |
7 files changed, 79 insertions, 43 deletions
diff --git a/include/linux/dccp.h b/include/linux/dccp.h index f3fc4392e93d..333c3ea82a5d 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h | |||
| @@ -144,6 +144,8 @@ enum dccp_reset_codes { | |||
| 144 | DCCP_RESET_CODE_TOO_BUSY, | 144 | DCCP_RESET_CODE_TOO_BUSY, |
| 145 | DCCP_RESET_CODE_BAD_INIT_COOKIE, | 145 | DCCP_RESET_CODE_BAD_INIT_COOKIE, |
| 146 | DCCP_RESET_CODE_AGGRESSION_PENALTY, | 146 | DCCP_RESET_CODE_AGGRESSION_PENALTY, |
| 147 | |||
| 148 | DCCP_MAX_RESET_CODES /* Leave at the end! */ | ||
| 147 | }; | 149 | }; |
| 148 | 150 | ||
| 149 | /* DCCP options */ | 151 | /* DCCP options */ |
| @@ -270,10 +272,9 @@ static inline struct dccp_hdr *dccp_zeroed_hdr(struct sk_buff *skb, int headlen) | |||
| 270 | return memset(skb_transport_header(skb), 0, headlen); | 272 | return memset(skb_transport_header(skb), 0, headlen); |
| 271 | } | 273 | } |
| 272 | 274 | ||
| 273 | static inline struct dccp_hdr_ext *dccp_hdrx(const struct sk_buff *skb) | 275 | static inline struct dccp_hdr_ext *dccp_hdrx(const struct dccp_hdr *dh) |
| 274 | { | 276 | { |
| 275 | return (struct dccp_hdr_ext *)(skb_transport_header(skb) + | 277 | return (struct dccp_hdr_ext *)((unsigned char *)dh + sizeof(*dh)); |
| 276 | sizeof(struct dccp_hdr)); | ||
| 277 | } | 278 | } |
| 278 | 279 | ||
| 279 | static inline unsigned int __dccp_basic_hdr_len(const struct dccp_hdr *dh) | 280 | static inline unsigned int __dccp_basic_hdr_len(const struct dccp_hdr *dh) |
| @@ -287,13 +288,12 @@ static inline unsigned int dccp_basic_hdr_len(const struct sk_buff *skb) | |||
| 287 | return __dccp_basic_hdr_len(dh); | 288 | return __dccp_basic_hdr_len(dh); |
| 288 | } | 289 | } |
| 289 | 290 | ||
| 290 | static inline __u64 dccp_hdr_seq(const struct sk_buff *skb) | 291 | static inline __u64 dccp_hdr_seq(const struct dccp_hdr *dh) |
| 291 | { | 292 | { |
| 292 | const struct dccp_hdr *dh = dccp_hdr(skb); | ||
| 293 | __u64 seq_nr = ntohs(dh->dccph_seq); | 293 | __u64 seq_nr = ntohs(dh->dccph_seq); |
| 294 | 294 | ||
| 295 | if (dh->dccph_x != 0) | 295 | if (dh->dccph_x != 0) |
| 296 | seq_nr = (seq_nr << 32) + ntohl(dccp_hdrx(skb)->dccph_seq_low); | 296 | seq_nr = (seq_nr << 32) + ntohl(dccp_hdrx(dh)->dccph_seq_low); |
| 297 | else | 297 | else |
| 298 | seq_nr += (u32)dh->dccph_seq2 << 16; | 298 | seq_nr += (u32)dh->dccph_seq2 << 16; |
| 299 | 299 | ||
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 426008e3b7e3..d694656b8800 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c | |||
| @@ -750,20 +750,16 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) | |||
| 750 | */ | 750 | */ |
| 751 | hctx->ccid2hctx_ssthresh = ~0; | 751 | hctx->ccid2hctx_ssthresh = ~0; |
| 752 | hctx->ccid2hctx_numdupack = 3; | 752 | hctx->ccid2hctx_numdupack = 3; |
| 753 | hctx->ccid2hctx_seqbufc = 0; | ||
| 754 | 753 | ||
| 755 | /* XXX init ~ to window size... */ | 754 | /* XXX init ~ to window size... */ |
| 756 | if (ccid2_hc_tx_alloc_seq(hctx)) | 755 | if (ccid2_hc_tx_alloc_seq(hctx)) |
| 757 | return -ENOMEM; | 756 | return -ENOMEM; |
| 758 | 757 | ||
| 759 | hctx->ccid2hctx_sent = 0; | ||
| 760 | hctx->ccid2hctx_rto = 3 * HZ; | 758 | hctx->ccid2hctx_rto = 3 * HZ; |
| 761 | ccid2_change_srtt(hctx, -1); | 759 | ccid2_change_srtt(hctx, -1); |
| 762 | hctx->ccid2hctx_rttvar = -1; | 760 | hctx->ccid2hctx_rttvar = -1; |
| 763 | hctx->ccid2hctx_lastrtt = 0; | ||
| 764 | hctx->ccid2hctx_rpdupack = -1; | 761 | hctx->ccid2hctx_rpdupack = -1; |
| 765 | hctx->ccid2hctx_last_cong = jiffies; | 762 | hctx->ccid2hctx_last_cong = jiffies; |
| 766 | hctx->ccid2hctx_high_ack = 0; | ||
| 767 | 763 | ||
| 768 | hctx->ccid2hctx_rtotimer.function = &ccid2_hc_tx_rto_expire; | 764 | hctx->ccid2hctx_rtotimer.function = &ccid2_hc_tx_rto_expire; |
| 769 | hctx->ccid2hctx_rtotimer.data = (unsigned long)sk; | 765 | hctx->ccid2hctx_rtotimer.data = (unsigned long)sk; |
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 25772c326172..19b33586333d 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
| @@ -40,6 +40,8 @@ | |||
| 40 | #include "lib/tfrc.h" | 40 | #include "lib/tfrc.h" |
| 41 | #include "ccid3.h" | 41 | #include "ccid3.h" |
| 42 | 42 | ||
| 43 | #include <asm/unaligned.h> | ||
| 44 | |||
| 43 | #ifdef CONFIG_IP_DCCP_CCID3_DEBUG | 45 | #ifdef CONFIG_IP_DCCP_CCID3_DEBUG |
| 44 | static int ccid3_debug; | 46 | static int ccid3_debug; |
| 45 | #define ccid3_pr_debug(format, a...) DCCP_PR_DEBUG(ccid3_debug, format, ##a) | 47 | #define ccid3_pr_debug(format, a...) DCCP_PR_DEBUG(ccid3_debug, format, ##a) |
| @@ -544,6 +546,7 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, | |||
| 544 | const struct dccp_sock *dp = dccp_sk(sk); | 546 | const struct dccp_sock *dp = dccp_sk(sk); |
| 545 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); | 547 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); |
| 546 | struct ccid3_options_received *opt_recv; | 548 | struct ccid3_options_received *opt_recv; |
| 549 | __be32 opt_val; | ||
| 547 | 550 | ||
| 548 | opt_recv = &hctx->ccid3hctx_options_received; | 551 | opt_recv = &hctx->ccid3hctx_options_received; |
| 549 | 552 | ||
| @@ -563,8 +566,8 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, | |||
| 563 | dccp_role(sk), sk, len); | 566 | dccp_role(sk), sk, len); |
| 564 | rc = -EINVAL; | 567 | rc = -EINVAL; |
| 565 | } else { | 568 | } else { |
| 566 | opt_recv->ccid3or_loss_event_rate = | 569 | opt_val = get_unaligned((__be32 *)value); |
| 567 | ntohl(*(__be32 *)value); | 570 | opt_recv->ccid3or_loss_event_rate = ntohl(opt_val); |
| 568 | ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n", | 571 | ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n", |
| 569 | dccp_role(sk), sk, | 572 | dccp_role(sk), sk, |
| 570 | opt_recv->ccid3or_loss_event_rate); | 573 | opt_recv->ccid3or_loss_event_rate); |
| @@ -585,8 +588,8 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, | |||
| 585 | dccp_role(sk), sk, len); | 588 | dccp_role(sk), sk, len); |
| 586 | rc = -EINVAL; | 589 | rc = -EINVAL; |
| 587 | } else { | 590 | } else { |
| 588 | opt_recv->ccid3or_receive_rate = | 591 | opt_val = get_unaligned((__be32 *)value); |
| 589 | ntohl(*(__be32 *)value); | 592 | opt_recv->ccid3or_receive_rate = ntohl(opt_val); |
| 590 | ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n", | 593 | ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n", |
| 591 | dccp_role(sk), sk, | 594 | dccp_role(sk), sk, |
| 592 | opt_recv->ccid3or_receive_rate); | 595 | opt_recv->ccid3or_receive_rate); |
| @@ -601,8 +604,6 @@ static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk) | |||
| 601 | { | 604 | { |
| 602 | struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid); | 605 | struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid); |
| 603 | 606 | ||
| 604 | hctx->ccid3hctx_s = 0; | ||
| 605 | hctx->ccid3hctx_rtt = 0; | ||
| 606 | hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT; | 607 | hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT; |
| 607 | INIT_LIST_HEAD(&hctx->ccid3hctx_hist); | 608 | INIT_LIST_HEAD(&hctx->ccid3hctx_hist); |
| 608 | 609 | ||
| @@ -963,8 +964,6 @@ static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk) | |||
| 963 | INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist); | 964 | INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist); |
| 964 | hcrx->ccid3hcrx_tstamp_last_feedback = | 965 | hcrx->ccid3hcrx_tstamp_last_feedback = |
| 965 | hcrx->ccid3hcrx_tstamp_last_ack = ktime_get_real(); | 966 | hcrx->ccid3hcrx_tstamp_last_ack = ktime_get_real(); |
| 966 | hcrx->ccid3hcrx_s = 0; | ||
| 967 | hcrx->ccid3hcrx_rtt = 0; | ||
| 968 | return 0; | 967 | return 0; |
| 969 | } | 968 | } |
| 970 | 969 | ||
diff --git a/net/dccp/input.c b/net/dccp/input.c index 3560a2a875a0..1ce101062824 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c | |||
| @@ -58,6 +58,42 @@ static void dccp_rcv_closereq(struct sock *sk, struct sk_buff *skb) | |||
| 58 | dccp_send_close(sk, 0); | 58 | dccp_send_close(sk, 0); |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | static u8 dccp_reset_code_convert(const u8 code) | ||
| 62 | { | ||
| 63 | const u8 error_code[] = { | ||
| 64 | [DCCP_RESET_CODE_CLOSED] = 0, /* normal termination */ | ||
| 65 | [DCCP_RESET_CODE_UNSPECIFIED] = 0, /* nothing known */ | ||
| 66 | [DCCP_RESET_CODE_ABORTED] = ECONNRESET, | ||
| 67 | |||
| 68 | [DCCP_RESET_CODE_NO_CONNECTION] = ECONNREFUSED, | ||
| 69 | [DCCP_RESET_CODE_CONNECTION_REFUSED] = ECONNREFUSED, | ||
| 70 | [DCCP_RESET_CODE_TOO_BUSY] = EUSERS, | ||
| 71 | [DCCP_RESET_CODE_AGGRESSION_PENALTY] = EDQUOT, | ||
| 72 | |||
| 73 | [DCCP_RESET_CODE_PACKET_ERROR] = ENOMSG, | ||
| 74 | [DCCP_RESET_CODE_BAD_INIT_COOKIE] = EBADR, | ||
| 75 | [DCCP_RESET_CODE_BAD_SERVICE_CODE] = EBADRQC, | ||
| 76 | [DCCP_RESET_CODE_OPTION_ERROR] = EILSEQ, | ||
| 77 | [DCCP_RESET_CODE_MANDATORY_ERROR] = EOPNOTSUPP, | ||
| 78 | }; | ||
| 79 | |||
| 80 | return code >= DCCP_MAX_RESET_CODES ? 0 : error_code[code]; | ||
| 81 | } | ||
| 82 | |||
| 83 | static void dccp_rcv_reset(struct sock *sk, struct sk_buff *skb) | ||
| 84 | { | ||
| 85 | u8 err = dccp_reset_code_convert(dccp_hdr_reset(skb)->dccph_reset_code); | ||
| 86 | |||
| 87 | sk->sk_err = err; | ||
| 88 | |||
| 89 | /* Queue the equivalent of TCP fin so that dccp_recvmsg exits the loop */ | ||
| 90 | dccp_fin(sk, skb); | ||
| 91 | |||
| 92 | if (err && !sock_flag(sk, SOCK_DEAD)) | ||
| 93 | sk_wake_async(sk, 0, POLL_ERR); | ||
| 94 | dccp_time_wait(sk, DCCP_TIME_WAIT, 0); | ||
| 95 | } | ||
| 96 | |||
| 61 | static void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb) | 97 | static void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb) |
| 62 | { | 98 | { |
| 63 | struct dccp_sock *dp = dccp_sk(sk); | 99 | struct dccp_sock *dp = dccp_sk(sk); |
| @@ -191,9 +227,8 @@ static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb, | |||
| 191 | * S.state := TIMEWAIT | 227 | * S.state := TIMEWAIT |
| 192 | * Set TIMEWAIT timer | 228 | * Set TIMEWAIT timer |
| 193 | * Drop packet and return | 229 | * Drop packet and return |
| 194 | */ | 230 | */ |
| 195 | dccp_fin(sk, skb); | 231 | dccp_rcv_reset(sk, skb); |
| 196 | dccp_time_wait(sk, DCCP_TIME_WAIT, 0); | ||
| 197 | return 0; | 232 | return 0; |
| 198 | case DCCP_PKT_CLOSEREQ: | 233 | case DCCP_PKT_CLOSEREQ: |
| 199 | dccp_rcv_closereq(sk, skb); | 234 | dccp_rcv_closereq(sk, skb); |
| @@ -521,12 +556,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
| 521 | * Drop packet and return | 556 | * Drop packet and return |
| 522 | */ | 557 | */ |
| 523 | if (dh->dccph_type == DCCP_PKT_RESET) { | 558 | if (dh->dccph_type == DCCP_PKT_RESET) { |
| 524 | /* | 559 | dccp_rcv_reset(sk, skb); |
| 525 | * Queue the equivalent of TCP fin so that dccp_recvmsg | ||
| 526 | * exits the loop | ||
| 527 | */ | ||
| 528 | dccp_fin(sk, skb); | ||
| 529 | dccp_time_wait(sk, DCCP_TIME_WAIT, 0); | ||
| 530 | return 0; | 560 | return 0; |
| 531 | /* | 561 | /* |
| 532 | * Step 7: Check for unexpected packet types | 562 | * Step 7: Check for unexpected packet types |
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 222549ab274a..01a6a808bdb7 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
| @@ -241,8 +241,8 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) | |||
| 241 | goto out; | 241 | goto out; |
| 242 | 242 | ||
| 243 | dp = dccp_sk(sk); | 243 | dp = dccp_sk(sk); |
| 244 | seq = dccp_hdr_seq(skb); | 244 | seq = dccp_hdr_seq(dh); |
| 245 | if (sk->sk_state != DCCP_LISTEN && | 245 | if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) && |
| 246 | !between48(seq, dp->dccps_swl, dp->dccps_swh)) { | 246 | !between48(seq, dp->dccps_swl, dp->dccps_swh)) { |
| 247 | NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS); | 247 | NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS); |
| 248 | goto out; | 248 | goto out; |
| @@ -795,7 +795,7 @@ static int dccp_v4_rcv(struct sk_buff *skb) | |||
| 795 | 795 | ||
| 796 | dh = dccp_hdr(skb); | 796 | dh = dccp_hdr(skb); |
| 797 | 797 | ||
| 798 | DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb); | 798 | DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(dh); |
| 799 | DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type; | 799 | DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type; |
| 800 | 800 | ||
| 801 | dccp_pr_debug("%8.8s " | 801 | dccp_pr_debug("%8.8s " |
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index bbadd6681b83..62428ff137dd 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
| @@ -173,7 +173,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
| 173 | 173 | ||
| 174 | icmpv6_err_convert(type, code, &err); | 174 | icmpv6_err_convert(type, code, &err); |
| 175 | 175 | ||
| 176 | seq = DCCP_SKB_CB(skb)->dccpd_seq; | 176 | seq = dccp_hdr_seq(dh); |
| 177 | /* Might be for an request_sock */ | 177 | /* Might be for an request_sock */ |
| 178 | switch (sk->sk_state) { | 178 | switch (sk->sk_state) { |
| 179 | struct request_sock *req, **prev; | 179 | struct request_sock *req, **prev; |
| @@ -787,7 +787,7 @@ static int dccp_v6_rcv(struct sk_buff *skb) | |||
| 787 | 787 | ||
| 788 | dh = dccp_hdr(skb); | 788 | dh = dccp_hdr(skb); |
| 789 | 789 | ||
| 790 | DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb); | 790 | DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(dh); |
| 791 | DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type; | 791 | DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type; |
| 792 | 792 | ||
| 793 | if (dccp_packet_without_ack(skb)) | 793 | if (dccp_packet_without_ack(skb)) |
diff --git a/net/dccp/options.c b/net/dccp/options.c index d361b5533309..d286cffe2c49 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/dccp.h> | 14 | #include <linux/dccp.h> |
| 15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
| 17 | #include <asm/unaligned.h> | ||
| 17 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
| 18 | #include <linux/skbuff.h> | 19 | #include <linux/skbuff.h> |
| 19 | 20 | ||
| @@ -59,6 +60,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) | |||
| 59 | unsigned char opt, len; | 60 | unsigned char opt, len; |
| 60 | unsigned char *value; | 61 | unsigned char *value; |
| 61 | u32 elapsed_time; | 62 | u32 elapsed_time; |
| 63 | __be32 opt_val; | ||
| 62 | int rc; | 64 | int rc; |
| 63 | int mandatory = 0; | 65 | int mandatory = 0; |
| 64 | 66 | ||
| @@ -145,7 +147,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) | |||
| 145 | if (len != 4) | 147 | if (len != 4) |
| 146 | goto out_invalid_option; | 148 | goto out_invalid_option; |
| 147 | 149 | ||
| 148 | opt_recv->dccpor_timestamp = ntohl(*(__be32 *)value); | 150 | opt_val = get_unaligned((__be32 *)value); |
| 151 | opt_recv->dccpor_timestamp = ntohl(opt_val); | ||
| 149 | 152 | ||
| 150 | dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp; | 153 | dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp; |
| 151 | dp->dccps_timestamp_time = ktime_get_real(); | 154 | dp->dccps_timestamp_time = ktime_get_real(); |
| @@ -159,7 +162,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) | |||
| 159 | if (len != 4 && len != 6 && len != 8) | 162 | if (len != 4 && len != 6 && len != 8) |
| 160 | goto out_invalid_option; | 163 | goto out_invalid_option; |
| 161 | 164 | ||
| 162 | opt_recv->dccpor_timestamp_echo = ntohl(*(__be32 *)value); | 165 | opt_val = get_unaligned((__be32 *)value); |
| 166 | opt_recv->dccpor_timestamp_echo = ntohl(opt_val); | ||
| 163 | 167 | ||
| 164 | dccp_pr_debug("%s rx opt: TIMESTAMP_ECHO=%u, len=%d, " | 168 | dccp_pr_debug("%s rx opt: TIMESTAMP_ECHO=%u, len=%d, " |
| 165 | "ackno=%llu", dccp_role(sk), | 169 | "ackno=%llu", dccp_role(sk), |
| @@ -168,16 +172,20 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) | |||
| 168 | (unsigned long long) | 172 | (unsigned long long) |
| 169 | DCCP_SKB_CB(skb)->dccpd_ack_seq); | 173 | DCCP_SKB_CB(skb)->dccpd_ack_seq); |
| 170 | 174 | ||
| 175 | value += 4; | ||
| 171 | 176 | ||
| 172 | if (len == 4) { | 177 | if (len == 4) { /* no elapsed time included */ |
| 173 | dccp_pr_debug_cat("\n"); | 178 | dccp_pr_debug_cat("\n"); |
| 174 | break; | 179 | break; |
| 175 | } | 180 | } |
| 176 | 181 | ||
| 177 | if (len == 6) | 182 | if (len == 6) { /* 2-byte elapsed time */ |
| 178 | elapsed_time = ntohs(*(__be16 *)(value + 4)); | 183 | __be16 opt_val2 = get_unaligned((__be16 *)value); |
| 179 | else | 184 | elapsed_time = ntohs(opt_val2); |
| 180 | elapsed_time = ntohl(*(__be32 *)(value + 4)); | 185 | } else { /* 4-byte elapsed time */ |
| 186 | opt_val = get_unaligned((__be32 *)value); | ||
| 187 | elapsed_time = ntohl(opt_val); | ||
| 188 | } | ||
| 181 | 189 | ||
| 182 | dccp_pr_debug_cat(", ELAPSED_TIME=%u\n", elapsed_time); | 190 | dccp_pr_debug_cat(", ELAPSED_TIME=%u\n", elapsed_time); |
| 183 | 191 | ||
| @@ -192,10 +200,13 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) | |||
| 192 | if (pkt_type == DCCP_PKT_DATA) | 200 | if (pkt_type == DCCP_PKT_DATA) |
| 193 | continue; | 201 | continue; |
| 194 | 202 | ||
| 195 | if (len == 2) | 203 | if (len == 2) { |
| 196 | elapsed_time = ntohs(*(__be16 *)value); | 204 | __be16 opt_val2 = get_unaligned((__be16 *)value); |
| 197 | else | 205 | elapsed_time = ntohs(opt_val2); |
| 198 | elapsed_time = ntohl(*(__be32 *)value); | 206 | } else { |
| 207 | opt_val = get_unaligned((__be32 *)value); | ||
| 208 | elapsed_time = ntohl(opt_val); | ||
| 209 | } | ||
| 199 | 210 | ||
| 200 | if (elapsed_time > opt_recv->dccpor_elapsed_time) | 211 | if (elapsed_time > opt_recv->dccpor_elapsed_time) |
| 201 | opt_recv->dccpor_elapsed_time = elapsed_time; | 212 | opt_recv->dccpor_elapsed_time = elapsed_time; |
