X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fdccp%2Foutput.c;fp=net%2Fdccp%2Foutput.c;h=efd7ffb903a149a46d38d57e691b20bfba416c67;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=58669beee1329cde9edbe2eda112594917007b79;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/net/dccp/output.c b/net/dccp/output.c index 58669beee..efd7ffb90 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -10,6 +10,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include @@ -26,7 +27,7 @@ static inline void dccp_event_ack_sent(struct sock *sk) inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); } -static void dccp_skb_entail(struct sock *sk, struct sk_buff *skb) +static inline void dccp_skb_entail(struct sock *sk, struct sk_buff *skb) { skb_set_owner_w(skb, sk); WARN_ON(sk->sk_send_head); @@ -48,7 +49,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); struct dccp_hdr *dh; /* XXX For now we're using only 48 bits sequence numbers */ - const u32 dccp_header_size = sizeof(*dh) + + const int dccp_header_size = sizeof(*dh) + sizeof(struct dccp_hdr_ext) + dccp_packet_hdr_len(dcb->dccpd_type); int err, set_ack = 1; @@ -63,10 +64,6 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) case DCCP_PKT_DATAACK: break; - case DCCP_PKT_REQUEST: - set_ack = 0; - /* fall through */ - case DCCP_PKT_SYNC: case DCCP_PKT_SYNCACK: ackno = dcb->dccpd_seq; @@ -82,11 +79,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) } dcb->dccpd_seq = dp->dccps_gss; - - if (dccp_insert_options(sk, skb)) { - kfree_skb(skb); - return -EPROTO; - } + dccp_insert_options(sk, skb); skb->h.raw = skb_push(skb, dccp_header_size); dh = dccp_hdr(skb); @@ -282,16 +275,17 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, { struct dccp_hdr *dh; struct dccp_request_sock *dreq; - const u32 dccp_header_size = sizeof(struct dccp_hdr) + + const int dccp_header_size = sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_response); - struct sk_buff *skb = sock_wmalloc(sk, sk->sk_prot->max_header, 1, + struct sk_buff *skb = sock_wmalloc(sk, MAX_HEADER + DCCP_MAX_OPT_LEN + + dccp_header_size, 1, GFP_ATOMIC); if (skb == NULL) return NULL; /* Reserve space for headers. */ - skb_reserve(skb, sk->sk_prot->max_header); + skb_reserve(skb, MAX_HEADER + DCCP_MAX_OPT_LEN + dccp_header_size); skb->dst = dst_clone(dst); skb->csum = 0; @@ -299,11 +293,7 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, dreq = dccp_rsk(req); DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE; DCCP_SKB_CB(skb)->dccpd_seq = dreq->dreq_iss; - - if (dccp_insert_options(sk, skb)) { - kfree_skb(skb); - return NULL; - } + dccp_insert_options(sk, skb); skb->h.raw = skb_push(skb, dccp_header_size); @@ -320,28 +310,32 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dreq->dreq_isr); dccp_hdr_response(skb)->dccph_resp_service = dreq->dreq_service; + dh->dccph_checksum = dccp_v4_checksum(skb, inet_rsk(req)->loc_addr, + inet_rsk(req)->rmt_addr); + DCCP_INC_STATS(DCCP_MIB_OUTSEGS); return skb; } EXPORT_SYMBOL_GPL(dccp_make_response); -static struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst, - const enum dccp_reset_codes code) +struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst, + const enum dccp_reset_codes code) { struct dccp_hdr *dh; struct dccp_sock *dp = dccp_sk(sk); - const u32 dccp_header_size = sizeof(struct dccp_hdr) + + const int dccp_header_size = sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_reset); - struct sk_buff *skb = sock_wmalloc(sk, sk->sk_prot->max_header, 1, + struct sk_buff *skb = sock_wmalloc(sk, MAX_HEADER + DCCP_MAX_OPT_LEN + + dccp_header_size, 1, GFP_ATOMIC); if (skb == NULL) return NULL; /* Reserve space for headers. */ - skb_reserve(skb, sk->sk_prot->max_header); + skb_reserve(skb, MAX_HEADER + DCCP_MAX_OPT_LEN + dccp_header_size); skb->dst = dst_clone(dst); skb->csum = 0; @@ -351,11 +345,7 @@ static struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst, DCCP_SKB_CB(skb)->dccpd_reset_code = code; DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESET; DCCP_SKB_CB(skb)->dccpd_seq = dp->dccps_gss; - - if (dccp_insert_options(sk, skb)) { - kfree_skb(skb); - return NULL; - } + dccp_insert_options(sk, skb); skb->h.raw = skb_push(skb, dccp_header_size); @@ -372,34 +362,14 @@ static struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst, dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dp->dccps_gsr); dccp_hdr_reset(skb)->dccph_reset_code = code; - inet_csk(sk)->icsk_af_ops->send_check(sk, skb->len, skb); + + dh->dccph_checksum = dccp_v4_checksum(skb, inet_sk(sk)->saddr, + inet_sk(sk)->daddr); DCCP_INC_STATS(DCCP_MIB_OUTSEGS); return skb; } -int dccp_send_reset(struct sock *sk, enum dccp_reset_codes code) -{ - /* - * FIXME: what if rebuild_header fails? - * Should we be doing a rebuild_header here? - */ - int err = inet_sk_rebuild_header(sk); - - if (err == 0) { - struct sk_buff *skb = dccp_make_reset(sk, sk->sk_dst_cache, - code); - if (skb != NULL) { - memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); - err = inet_csk(sk)->icsk_af_ops->queue_xmit(skb, 0); - if (err == NET_XMIT_CN) - err = 0; - } - } - - return err; -} - /* * Do all connect socket setups that can be done AF independent. */ @@ -435,12 +405,12 @@ int dccp_connect(struct sock *sk) dccp_connect_init(sk); - skb = alloc_skb(sk->sk_prot->max_header, sk->sk_allocation); + skb = alloc_skb(MAX_DCCP_HEADER + 15, sk->sk_allocation); if (unlikely(skb == NULL)) return -ENOBUFS; /* Reserve space for headers. */ - skb_reserve(skb, sk->sk_prot->max_header); + skb_reserve(skb, MAX_DCCP_HEADER); DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST; skb->csum = 0; @@ -461,8 +431,7 @@ void dccp_send_ack(struct sock *sk) { /* If we have been reset, we may not send again. */ if (sk->sk_state != DCCP_CLOSED) { - struct sk_buff *skb = alloc_skb(sk->sk_prot->max_header, - GFP_ATOMIC); + struct sk_buff *skb = alloc_skb(MAX_DCCP_HEADER, GFP_ATOMIC); if (skb == NULL) { inet_csk_schedule_ack(sk); @@ -474,7 +443,7 @@ void dccp_send_ack(struct sock *sk) } /* Reserve space for headers */ - skb_reserve(skb, sk->sk_prot->max_header); + skb_reserve(skb, MAX_DCCP_HEADER); skb->csum = 0; DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_ACK; dccp_transmit_skb(sk, skb); @@ -521,14 +490,14 @@ void dccp_send_sync(struct sock *sk, const u64 seq, * dccp_transmit_skb() will set the ownership to this * sock. */ - struct sk_buff *skb = alloc_skb(sk->sk_prot->max_header, GFP_ATOMIC); + struct sk_buff *skb = alloc_skb(MAX_DCCP_HEADER, GFP_ATOMIC); if (skb == NULL) /* FIXME: how to make sure the sync is sent? */ return; /* Reserve space for headers and prepare control bits. */ - skb_reserve(skb, sk->sk_prot->max_header); + skb_reserve(skb, MAX_DCCP_HEADER); skb->csum = 0; DCCP_SKB_CB(skb)->dccpd_type = pkt_type; DCCP_SKB_CB(skb)->dccpd_seq = seq; @@ -536,8 +505,6 @@ void dccp_send_sync(struct sock *sk, const u64 seq, dccp_transmit_skb(sk, skb); } -EXPORT_SYMBOL_GPL(dccp_send_sync); - /* * Send a DCCP_PKT_CLOSE/CLOSEREQ. The caller locks the socket for us. This * cannot be allowed to fail queueing a DCCP_PKT_CLOSE/CLOSEREQ frame under