mirror of
https://github.com/adulau/aha.git
synced 2024-12-29 12:16:20 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: net: missing bits of net-namespace / sysctl ipcomp: Fix warnings after ipcomp consolidation. dccp: Add check for truncated ICMPv6 DCCP error packets dccp: Fix incorrect length check for ICMPv4 packets dccp: Add check for sequence number in ICMPv6 message dccp: Fix sequence number check for ICMPv4 packets dccp: Bug-Fix - AWL was never updated dccp: Allow to distinguish original and retransmitted packets
This commit is contained in:
commit
4f31f30809
7 changed files with 58 additions and 50 deletions
|
@ -226,7 +226,7 @@ static inline void dccp_csum_outgoing(struct sk_buff *skb)
|
|||
|
||||
extern void dccp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb);
|
||||
|
||||
extern int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb);
|
||||
extern int dccp_retransmit_skb(struct sock *sk);
|
||||
|
||||
extern void dccp_send_ack(struct sock *sk);
|
||||
extern void dccp_reqsk_send_ack(struct sk_buff *sk, struct request_sock *rsk);
|
||||
|
|
|
@ -196,8 +196,8 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk,
|
|||
static void dccp_v4_err(struct sk_buff *skb, u32 info)
|
||||
{
|
||||
const struct iphdr *iph = (struct iphdr *)skb->data;
|
||||
const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data +
|
||||
(iph->ihl << 2));
|
||||
const u8 offset = iph->ihl << 2;
|
||||
const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
|
||||
struct dccp_sock *dp;
|
||||
struct inet_sock *inet;
|
||||
const int type = icmp_hdr(skb)->type;
|
||||
|
@ -207,7 +207,8 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
|
|||
int err;
|
||||
struct net *net = dev_net(skb->dev);
|
||||
|
||||
if (skb->len < (iph->ihl << 2) + 8) {
|
||||
if (skb->len < offset + sizeof(*dh) ||
|
||||
skb->len < offset + __dccp_basic_hdr_len(dh)) {
|
||||
ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
|
||||
return;
|
||||
}
|
||||
|
@ -238,7 +239,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
|
|||
dp = dccp_sk(sk);
|
||||
seq = dccp_hdr_seq(dh);
|
||||
if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) &&
|
||||
!between48(seq, dp->dccps_swl, dp->dccps_swh)) {
|
||||
!between48(seq, dp->dccps_awl, dp->dccps_awh)) {
|
||||
NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -89,12 +89,19 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
|||
{
|
||||
struct ipv6hdr *hdr = (struct ipv6hdr *)skb->data;
|
||||
const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
|
||||
struct dccp_sock *dp;
|
||||
struct ipv6_pinfo *np;
|
||||
struct sock *sk;
|
||||
int err;
|
||||
__u64 seq;
|
||||
struct net *net = dev_net(skb->dev);
|
||||
|
||||
if (skb->len < offset + sizeof(*dh) ||
|
||||
skb->len < offset + __dccp_basic_hdr_len(dh)) {
|
||||
ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
|
||||
return;
|
||||
}
|
||||
|
||||
sk = inet6_lookup(net, &dccp_hashinfo,
|
||||
&hdr->daddr, dh->dccph_dport,
|
||||
&hdr->saddr, dh->dccph_sport, inet6_iif(skb));
|
||||
|
@ -116,6 +123,14 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
|||
if (sk->sk_state == DCCP_CLOSED)
|
||||
goto out;
|
||||
|
||||
dp = dccp_sk(sk);
|
||||
seq = dccp_hdr_seq(dh);
|
||||
if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) &&
|
||||
!between48(seq, dp->dccps_awl, dp->dccps_awh)) {
|
||||
NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
|
||||
goto out;
|
||||
}
|
||||
|
||||
np = inet6_sk(sk);
|
||||
|
||||
if (type == ICMPV6_PKT_TOOBIG) {
|
||||
|
@ -168,7 +183,6 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
|||
|
||||
icmpv6_err_convert(type, code, &err);
|
||||
|
||||
seq = dccp_hdr_seq(dh);
|
||||
/* Might be for an request_sock */
|
||||
switch (sk->sk_state) {
|
||||
struct request_sock *req, **prev;
|
||||
|
|
|
@ -53,8 +53,11 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
|
|||
dccp_packet_hdr_len(dcb->dccpd_type);
|
||||
int err, set_ack = 1;
|
||||
u64 ackno = dp->dccps_gsr;
|
||||
|
||||
dccp_inc_seqno(&dp->dccps_gss);
|
||||
/*
|
||||
* Increment GSS here already in case the option code needs it.
|
||||
* Update GSS for real only if option processing below succeeds.
|
||||
*/
|
||||
dcb->dccpd_seq = ADD48(dp->dccps_gss, 1);
|
||||
|
||||
switch (dcb->dccpd_type) {
|
||||
case DCCP_PKT_DATA:
|
||||
|
@ -66,6 +69,9 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
|
|||
|
||||
case DCCP_PKT_REQUEST:
|
||||
set_ack = 0;
|
||||
/* Use ISS on the first (non-retransmitted) Request. */
|
||||
if (icsk->icsk_retransmits == 0)
|
||||
dcb->dccpd_seq = dp->dccps_iss;
|
||||
/* fall through */
|
||||
|
||||
case DCCP_PKT_SYNC:
|
||||
|
@ -84,8 +90,6 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
|
|||
break;
|
||||
}
|
||||
|
||||
dcb->dccpd_seq = dp->dccps_gss;
|
||||
|
||||
if (dccp_insert_options(sk, skb)) {
|
||||
kfree_skb(skb);
|
||||
return -EPROTO;
|
||||
|
@ -103,7 +107,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
|
|||
/* XXX For now we're using only 48 bits sequence numbers */
|
||||
dh->dccph_x = 1;
|
||||
|
||||
dp->dccps_awh = dp->dccps_gss;
|
||||
dccp_update_gss(sk, dcb->dccpd_seq);
|
||||
dccp_hdr_set_seq(dh, dp->dccps_gss);
|
||||
if (set_ack)
|
||||
dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), ackno);
|
||||
|
@ -112,6 +116,11 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
|
|||
case DCCP_PKT_REQUEST:
|
||||
dccp_hdr_request(skb)->dccph_req_service =
|
||||
dp->dccps_service;
|
||||
/*
|
||||
* Limit Ack window to ISS <= P.ackno <= GSS, so that
|
||||
* only Responses to Requests we sent are considered.
|
||||
*/
|
||||
dp->dccps_awl = dp->dccps_iss;
|
||||
break;
|
||||
case DCCP_PKT_RESET:
|
||||
dccp_hdr_reset(skb)->dccph_reset_code =
|
||||
|
@ -284,14 +293,26 @@ void dccp_write_xmit(struct sock *sk, int block)
|
|||
}
|
||||
}
|
||||
|
||||
int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
|
||||
/**
|
||||
* dccp_retransmit_skb - Retransmit Request, Close, or CloseReq packets
|
||||
* There are only four retransmittable packet types in DCCP:
|
||||
* - Request in client-REQUEST state (sec. 8.1.1),
|
||||
* - CloseReq in server-CLOSEREQ state (sec. 8.3),
|
||||
* - Close in node-CLOSING state (sec. 8.3),
|
||||
* - Acks in client-PARTOPEN state (sec. 8.1.5, handled by dccp_delack_timer()).
|
||||
* This function expects sk->sk_send_head to contain the original skb.
|
||||
*/
|
||||
int dccp_retransmit_skb(struct sock *sk)
|
||||
{
|
||||
WARN_ON(sk->sk_send_head == NULL);
|
||||
|
||||
if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk) != 0)
|
||||
return -EHOSTUNREACH; /* Routing failure or similar. */
|
||||
|
||||
return dccp_transmit_skb(sk, (skb_cloned(skb) ?
|
||||
pskb_copy(skb, GFP_ATOMIC):
|
||||
skb_clone(skb, GFP_ATOMIC)));
|
||||
/* this count is used to distinguish original and retransmitted skb */
|
||||
inet_csk(sk)->icsk_retransmits++;
|
||||
|
||||
return dccp_transmit_skb(sk, skb_clone(sk->sk_send_head, GFP_ATOMIC));
|
||||
}
|
||||
|
||||
struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
|
||||
|
@ -437,19 +458,7 @@ static inline void dccp_connect_init(struct sock *sk)
|
|||
|
||||
dccp_sync_mss(sk, dst_mtu(dst));
|
||||
|
||||
/*
|
||||
* SWL and AWL are initially adjusted so that they are not less than
|
||||
* the initial Sequence Numbers received and sent, respectively:
|
||||
* SWL := max(GSR + 1 - floor(W/4), ISR),
|
||||
* AWL := max(GSS - W' + 1, ISS).
|
||||
* These adjustments MUST be applied only at the beginning of the
|
||||
* connection.
|
||||
*/
|
||||
dccp_update_gss(sk, dp->dccps_iss);
|
||||
dccp_set_seqno(&dp->dccps_awl, max48(dp->dccps_awl, dp->dccps_iss));
|
||||
|
||||
/* S.GAR - greatest valid acknowledgement number received on a non-Sync;
|
||||
* initialized to S.ISS (sec. 8.5) */
|
||||
/* Initialise GAR as per 8.5; AWL/AWH are set in dccp_transmit_skb() */
|
||||
dp->dccps_gar = dp->dccps_iss;
|
||||
|
||||
icsk->icsk_retransmits = 0;
|
||||
|
|
|
@ -98,22 +98,12 @@ static void dccp_retransmit_timer(struct sock *sk)
|
|||
goto backoff;
|
||||
}
|
||||
|
||||
/*
|
||||
* sk->sk_send_head has to have one skb with
|
||||
* DCCP_SKB_CB(skb)->dccpd_type set to one of the retransmittable DCCP
|
||||
* packet types. The only packets eligible for retransmission are:
|
||||
* -- Requests in client-REQUEST state (sec. 8.1.1)
|
||||
* -- Acks in client-PARTOPEN state (sec. 8.1.5)
|
||||
* -- CloseReq in server-CLOSEREQ state (sec. 8.3)
|
||||
* -- Close in node-CLOSING state (sec. 8.3) */
|
||||
WARN_ON(sk->sk_send_head == NULL);
|
||||
|
||||
/*
|
||||
* More than than 4MSL (8 minutes) has passed, a RESET(aborted) was
|
||||
* sent, no need to retransmit, this sock is dead.
|
||||
*/
|
||||
if (dccp_write_timeout(sk))
|
||||
goto out;
|
||||
return;
|
||||
|
||||
/*
|
||||
* We want to know the number of packets retransmitted, not the
|
||||
|
@ -122,30 +112,28 @@ static void dccp_retransmit_timer(struct sock *sk)
|
|||
if (icsk->icsk_retransmits == 0)
|
||||
DCCP_INC_STATS_BH(DCCP_MIB_TIMEOUTS);
|
||||
|
||||
if (dccp_retransmit_skb(sk, sk->sk_send_head) < 0) {
|
||||
if (dccp_retransmit_skb(sk) != 0) {
|
||||
/*
|
||||
* Retransmission failed because of local congestion,
|
||||
* do not backoff.
|
||||
*/
|
||||
if (icsk->icsk_retransmits == 0)
|
||||
if (--icsk->icsk_retransmits == 0)
|
||||
icsk->icsk_retransmits = 1;
|
||||
inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
|
||||
min(icsk->icsk_rto,
|
||||
TCP_RESOURCE_PROBE_INTERVAL),
|
||||
DCCP_RTO_MAX);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
backoff:
|
||||
icsk->icsk_backoff++;
|
||||
icsk->icsk_retransmits++;
|
||||
|
||||
icsk->icsk_rto = min(icsk->icsk_rto << 1, DCCP_RTO_MAX);
|
||||
inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto,
|
||||
DCCP_RTO_MAX);
|
||||
if (icsk->icsk_retransmits > sysctl_dccp_retries1)
|
||||
__sk_dst_reset(sk);
|
||||
out:;
|
||||
}
|
||||
|
||||
static void dccp_write_timer(unsigned long data)
|
||||
|
|
|
@ -104,9 +104,7 @@ out:
|
|||
|
||||
static int ipcomp4_init_state(struct xfrm_state *x)
|
||||
{
|
||||
int err;
|
||||
struct ipcomp_data *ipcd;
|
||||
struct xfrm_algo_desc *calg_desc;
|
||||
int err = -EINVAL;
|
||||
|
||||
x->props.header_len = 0;
|
||||
switch (x->props.mode) {
|
||||
|
|
|
@ -134,9 +134,7 @@ out:
|
|||
|
||||
static int ipcomp6_init_state(struct xfrm_state *x)
|
||||
{
|
||||
int err;
|
||||
struct ipcomp_data *ipcd;
|
||||
struct xfrm_algo_desc *calg_desc;
|
||||
int err = -EINVAL;
|
||||
|
||||
x->props.header_len = 0;
|
||||
switch (x->props.mode) {
|
||||
|
|
Loading…
Reference in a new issue