Commit 8c56a347 authored by David S. Miller's avatar David S. Miller

Merge master.kernel.org:/pub/scm/linux/kernel/git/acme/net-2.6

parents d892afe2 24c667db
...@@ -144,6 +144,8 @@ enum dccp_reset_codes { ...@@ -144,6 +144,8 @@ enum dccp_reset_codes {
DCCP_RESET_CODE_TOO_BUSY, DCCP_RESET_CODE_TOO_BUSY,
DCCP_RESET_CODE_BAD_INIT_COOKIE, DCCP_RESET_CODE_BAD_INIT_COOKIE,
DCCP_RESET_CODE_AGGRESSION_PENALTY, DCCP_RESET_CODE_AGGRESSION_PENALTY,
DCCP_MAX_RESET_CODES /* Leave at the end! */
}; };
/* DCCP options */ /* DCCP options */
...@@ -270,10 +272,9 @@ static inline struct dccp_hdr *dccp_zeroed_hdr(struct sk_buff *skb, int headlen) ...@@ -270,10 +272,9 @@ static inline struct dccp_hdr *dccp_zeroed_hdr(struct sk_buff *skb, int headlen)
return memset(skb_transport_header(skb), 0, headlen); return memset(skb_transport_header(skb), 0, headlen);
} }
static inline struct dccp_hdr_ext *dccp_hdrx(const struct sk_buff *skb) static inline struct dccp_hdr_ext *dccp_hdrx(const struct dccp_hdr *dh)
{ {
return (struct dccp_hdr_ext *)(skb_transport_header(skb) + return (struct dccp_hdr_ext *)((unsigned char *)dh + sizeof(*dh));
sizeof(struct dccp_hdr));
} }
static inline unsigned int __dccp_basic_hdr_len(const struct dccp_hdr *dh) 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,13 +288,12 @@ static inline unsigned int dccp_basic_hdr_len(const struct sk_buff *skb)
return __dccp_basic_hdr_len(dh); return __dccp_basic_hdr_len(dh);
} }
static inline __u64 dccp_hdr_seq(const struct sk_buff *skb) static inline __u64 dccp_hdr_seq(const struct dccp_hdr *dh)
{ {
const struct dccp_hdr *dh = dccp_hdr(skb);
__u64 seq_nr = ntohs(dh->dccph_seq); __u64 seq_nr = ntohs(dh->dccph_seq);
if (dh->dccph_x != 0) if (dh->dccph_x != 0)
seq_nr = (seq_nr << 32) + ntohl(dccp_hdrx(skb)->dccph_seq_low); seq_nr = (seq_nr << 32) + ntohl(dccp_hdrx(dh)->dccph_seq_low);
else else
seq_nr += (u32)dh->dccph_seq2 << 16; seq_nr += (u32)dh->dccph_seq2 << 16;
......
...@@ -750,20 +750,16 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) ...@@ -750,20 +750,16 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
*/ */
hctx->ccid2hctx_ssthresh = ~0; hctx->ccid2hctx_ssthresh = ~0;
hctx->ccid2hctx_numdupack = 3; hctx->ccid2hctx_numdupack = 3;
hctx->ccid2hctx_seqbufc = 0;
/* XXX init ~ to window size... */ /* XXX init ~ to window size... */
if (ccid2_hc_tx_alloc_seq(hctx)) if (ccid2_hc_tx_alloc_seq(hctx))
return -ENOMEM; return -ENOMEM;
hctx->ccid2hctx_sent = 0;
hctx->ccid2hctx_rto = 3 * HZ; hctx->ccid2hctx_rto = 3 * HZ;
ccid2_change_srtt(hctx, -1); ccid2_change_srtt(hctx, -1);
hctx->ccid2hctx_rttvar = -1; hctx->ccid2hctx_rttvar = -1;
hctx->ccid2hctx_lastrtt = 0;
hctx->ccid2hctx_rpdupack = -1; hctx->ccid2hctx_rpdupack = -1;
hctx->ccid2hctx_last_cong = jiffies; hctx->ccid2hctx_last_cong = jiffies;
hctx->ccid2hctx_high_ack = 0;
hctx->ccid2hctx_rtotimer.function = &ccid2_hc_tx_rto_expire; hctx->ccid2hctx_rtotimer.function = &ccid2_hc_tx_rto_expire;
hctx->ccid2hctx_rtotimer.data = (unsigned long)sk; hctx->ccid2hctx_rtotimer.data = (unsigned long)sk;
......
...@@ -40,6 +40,8 @@ ...@@ -40,6 +40,8 @@
#include "lib/tfrc.h" #include "lib/tfrc.h"
#include "ccid3.h" #include "ccid3.h"
#include <asm/unaligned.h>
#ifdef CONFIG_IP_DCCP_CCID3_DEBUG #ifdef CONFIG_IP_DCCP_CCID3_DEBUG
static int ccid3_debug; static int ccid3_debug;
#define ccid3_pr_debug(format, a...) DCCP_PR_DEBUG(ccid3_debug, format, ##a) #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,6 +546,7 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
const struct dccp_sock *dp = dccp_sk(sk); const struct dccp_sock *dp = dccp_sk(sk);
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
struct ccid3_options_received *opt_recv; struct ccid3_options_received *opt_recv;
__be32 opt_val;
opt_recv = &hctx->ccid3hctx_options_received; opt_recv = &hctx->ccid3hctx_options_received;
...@@ -563,8 +566,8 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, ...@@ -563,8 +566,8 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
dccp_role(sk), sk, len); dccp_role(sk), sk, len);
rc = -EINVAL; rc = -EINVAL;
} else { } else {
opt_recv->ccid3or_loss_event_rate = opt_val = get_unaligned((__be32 *)value);
ntohl(*(__be32 *)value); opt_recv->ccid3or_loss_event_rate = ntohl(opt_val);
ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n", ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n",
dccp_role(sk), sk, dccp_role(sk), sk,
opt_recv->ccid3or_loss_event_rate); opt_recv->ccid3or_loss_event_rate);
...@@ -585,8 +588,8 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, ...@@ -585,8 +588,8 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
dccp_role(sk), sk, len); dccp_role(sk), sk, len);
rc = -EINVAL; rc = -EINVAL;
} else { } else {
opt_recv->ccid3or_receive_rate = opt_val = get_unaligned((__be32 *)value);
ntohl(*(__be32 *)value); opt_recv->ccid3or_receive_rate = ntohl(opt_val);
ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n", ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n",
dccp_role(sk), sk, dccp_role(sk), sk,
opt_recv->ccid3or_receive_rate); opt_recv->ccid3or_receive_rate);
...@@ -601,8 +604,6 @@ static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk) ...@@ -601,8 +604,6 @@ static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk)
{ {
struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid); struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid);
hctx->ccid3hctx_s = 0;
hctx->ccid3hctx_rtt = 0;
hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT; hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;
INIT_LIST_HEAD(&hctx->ccid3hctx_hist); INIT_LIST_HEAD(&hctx->ccid3hctx_hist);
...@@ -963,8 +964,6 @@ static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk) ...@@ -963,8 +964,6 @@ static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)
INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist); INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist);
hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_feedback =
hcrx->ccid3hcrx_tstamp_last_ack = ktime_get_real(); hcrx->ccid3hcrx_tstamp_last_ack = ktime_get_real();
hcrx->ccid3hcrx_s = 0;
hcrx->ccid3hcrx_rtt = 0;
return 0; return 0;
} }
......
...@@ -58,6 +58,42 @@ static void dccp_rcv_closereq(struct sock *sk, struct sk_buff *skb) ...@@ -58,6 +58,42 @@ static void dccp_rcv_closereq(struct sock *sk, struct sk_buff *skb)
dccp_send_close(sk, 0); dccp_send_close(sk, 0);
} }
static u8 dccp_reset_code_convert(const u8 code)
{
const u8 error_code[] = {
[DCCP_RESET_CODE_CLOSED] = 0, /* normal termination */
[DCCP_RESET_CODE_UNSPECIFIED] = 0, /* nothing known */
[DCCP_RESET_CODE_ABORTED] = ECONNRESET,
[DCCP_RESET_CODE_NO_CONNECTION] = ECONNREFUSED,
[DCCP_RESET_CODE_CONNECTION_REFUSED] = ECONNREFUSED,
[DCCP_RESET_CODE_TOO_BUSY] = EUSERS,
[DCCP_RESET_CODE_AGGRESSION_PENALTY] = EDQUOT,
[DCCP_RESET_CODE_PACKET_ERROR] = ENOMSG,
[DCCP_RESET_CODE_BAD_INIT_COOKIE] = EBADR,
[DCCP_RESET_CODE_BAD_SERVICE_CODE] = EBADRQC,
[DCCP_RESET_CODE_OPTION_ERROR] = EILSEQ,
[DCCP_RESET_CODE_MANDATORY_ERROR] = EOPNOTSUPP,
};
return code >= DCCP_MAX_RESET_CODES ? 0 : error_code[code];
}
static void dccp_rcv_reset(struct sock *sk, struct sk_buff *skb)
{
u8 err = dccp_reset_code_convert(dccp_hdr_reset(skb)->dccph_reset_code);
sk->sk_err = err;
/* Queue the equivalent of TCP fin so that dccp_recvmsg exits the loop */
dccp_fin(sk, skb);
if (err && !sock_flag(sk, SOCK_DEAD))
sk_wake_async(sk, 0, POLL_ERR);
dccp_time_wait(sk, DCCP_TIME_WAIT, 0);
}
static void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb) static void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb)
{ {
struct dccp_sock *dp = dccp_sk(sk); struct dccp_sock *dp = dccp_sk(sk);
...@@ -192,8 +228,7 @@ static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb, ...@@ -192,8 +228,7 @@ static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
* Set TIMEWAIT timer * Set TIMEWAIT timer
* Drop packet and return * Drop packet and return
*/ */
dccp_fin(sk, skb); dccp_rcv_reset(sk, skb);
dccp_time_wait(sk, DCCP_TIME_WAIT, 0);
return 0; return 0;
case DCCP_PKT_CLOSEREQ: case DCCP_PKT_CLOSEREQ:
dccp_rcv_closereq(sk, skb); dccp_rcv_closereq(sk, skb);
...@@ -521,12 +556,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, ...@@ -521,12 +556,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
* Drop packet and return * Drop packet and return
*/ */
if (dh->dccph_type == DCCP_PKT_RESET) { if (dh->dccph_type == DCCP_PKT_RESET) {
/* dccp_rcv_reset(sk, skb);
* Queue the equivalent of TCP fin so that dccp_recvmsg
* exits the loop
*/
dccp_fin(sk, skb);
dccp_time_wait(sk, DCCP_TIME_WAIT, 0);
return 0; return 0;
/* /*
* Step 7: Check for unexpected packet types * Step 7: Check for unexpected packet types
......
...@@ -241,8 +241,8 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) ...@@ -241,8 +241,8 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
goto out; goto out;
dp = dccp_sk(sk); dp = dccp_sk(sk);
seq = dccp_hdr_seq(skb); seq = dccp_hdr_seq(dh);
if (sk->sk_state != DCCP_LISTEN && if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) &&
!between48(seq, dp->dccps_swl, dp->dccps_swh)) { !between48(seq, dp->dccps_swl, dp->dccps_swh)) {
NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS); NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
goto out; goto out;
...@@ -795,7 +795,7 @@ static int dccp_v4_rcv(struct sk_buff *skb) ...@@ -795,7 +795,7 @@ static int dccp_v4_rcv(struct sk_buff *skb)
dh = dccp_hdr(skb); dh = dccp_hdr(skb);
DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb); DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(dh);
DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type; DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type;
dccp_pr_debug("%8.8s " dccp_pr_debug("%8.8s "
......
...@@ -173,7 +173,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, ...@@ -173,7 +173,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
icmpv6_err_convert(type, code, &err); icmpv6_err_convert(type, code, &err);
seq = DCCP_SKB_CB(skb)->dccpd_seq; seq = dccp_hdr_seq(dh);
/* Might be for an request_sock */ /* Might be for an request_sock */
switch (sk->sk_state) { switch (sk->sk_state) {
struct request_sock *req, **prev; struct request_sock *req, **prev;
...@@ -787,7 +787,7 @@ static int dccp_v6_rcv(struct sk_buff *skb) ...@@ -787,7 +787,7 @@ static int dccp_v6_rcv(struct sk_buff *skb)
dh = dccp_hdr(skb); dh = dccp_hdr(skb);
DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb); DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(dh);
DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type; DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type;
if (dccp_packet_without_ack(skb)) if (dccp_packet_without_ack(skb))
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/dccp.h> #include <linux/dccp.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/types.h> #include <linux/types.h>
#include <asm/unaligned.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
...@@ -59,6 +60,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) ...@@ -59,6 +60,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
unsigned char opt, len; unsigned char opt, len;
unsigned char *value; unsigned char *value;
u32 elapsed_time; u32 elapsed_time;
__be32 opt_val;
int rc; int rc;
int mandatory = 0; int mandatory = 0;
...@@ -145,7 +147,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) ...@@ -145,7 +147,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
if (len != 4) if (len != 4)
goto out_invalid_option; goto out_invalid_option;
opt_recv->dccpor_timestamp = ntohl(*(__be32 *)value); opt_val = get_unaligned((__be32 *)value);
opt_recv->dccpor_timestamp = ntohl(opt_val);
dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp; dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp;
dp->dccps_timestamp_time = ktime_get_real(); dp->dccps_timestamp_time = ktime_get_real();
...@@ -159,7 +162,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) ...@@ -159,7 +162,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
if (len != 4 && len != 6 && len != 8) if (len != 4 && len != 6 && len != 8)
goto out_invalid_option; goto out_invalid_option;
opt_recv->dccpor_timestamp_echo = ntohl(*(__be32 *)value); opt_val = get_unaligned((__be32 *)value);
opt_recv->dccpor_timestamp_echo = ntohl(opt_val);
dccp_pr_debug("%s rx opt: TIMESTAMP_ECHO=%u, len=%d, " dccp_pr_debug("%s rx opt: TIMESTAMP_ECHO=%u, len=%d, "
"ackno=%llu", dccp_role(sk), "ackno=%llu", dccp_role(sk),
...@@ -168,16 +172,20 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) ...@@ -168,16 +172,20 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
(unsigned long long) (unsigned long long)
DCCP_SKB_CB(skb)->dccpd_ack_seq); DCCP_SKB_CB(skb)->dccpd_ack_seq);
value += 4;
if (len == 4) { if (len == 4) { /* no elapsed time included */
dccp_pr_debug_cat("\n"); dccp_pr_debug_cat("\n");
break; break;
} }
if (len == 6) if (len == 6) { /* 2-byte elapsed time */
elapsed_time = ntohs(*(__be16 *)(value + 4)); __be16 opt_val2 = get_unaligned((__be16 *)value);
else elapsed_time = ntohs(opt_val2);
elapsed_time = ntohl(*(__be32 *)(value + 4)); } else { /* 4-byte elapsed time */
opt_val = get_unaligned((__be32 *)value);
elapsed_time = ntohl(opt_val);
}
dccp_pr_debug_cat(", ELAPSED_TIME=%u\n", elapsed_time); dccp_pr_debug_cat(", ELAPSED_TIME=%u\n", elapsed_time);
...@@ -192,10 +200,13 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) ...@@ -192,10 +200,13 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
if (pkt_type == DCCP_PKT_DATA) if (pkt_type == DCCP_PKT_DATA)
continue; continue;
if (len == 2) if (len == 2) {
elapsed_time = ntohs(*(__be16 *)value); __be16 opt_val2 = get_unaligned((__be16 *)value);
else elapsed_time = ntohs(opt_val2);
elapsed_time = ntohl(*(__be32 *)value); } else {
opt_val = get_unaligned((__be32 *)value);
elapsed_time = ntohl(opt_val);
}
if (elapsed_time > opt_recv->dccpor_elapsed_time) if (elapsed_time > opt_recv->dccpor_elapsed_time)
opt_recv->dccpor_elapsed_time = elapsed_time; opt_recv->dccpor_elapsed_time = elapsed_time;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment