X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fdccp%2Finput.c;h=565bc80557ceb79139ea96c930652def3a56237d;hb=refs%2Fheads%2Fvserver;hp=b6cba72b44e84e723b397969c4704a880c671f50;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/net/dccp/input.c b/net/dccp/input.c index b6cba72b4..565bc8055 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -1,6 +1,6 @@ /* * net/dccp/input.c - * + * * An implementation of the DCCP protocol * Arnaldo Carvalho de Melo * @@ -10,7 +10,6 @@ * 2 of the License, or (at your option) any later version. */ -#include #include #include @@ -32,7 +31,7 @@ static void dccp_fin(struct sock *sk, struct sk_buff *skb) static void dccp_rcv_close(struct sock *sk, struct sk_buff *skb) { - dccp_v4_send_reset(sk, DCCP_RESET_CODE_CLOSED); + dccp_send_reset(sk, DCCP_RESET_CODE_CLOSED); dccp_fin(sk, skb); dccp_set_state(sk, DCCP_CLOSED); sk_wake_async(sk, 1, POLL_HUP); @@ -56,11 +55,11 @@ static void dccp_rcv_closereq(struct sock *sk, struct sk_buff *skb) dccp_send_close(sk, 0); } -static inline 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); - if (dp->dccps_options.dccpo_send_ack_vector) + if (dccp_msk(sk)->dccpms_send_ack_vector) dccp_ackvec_check_rcv_ackno(dp->dccps_hc_rx_ackvec, sk, DCCP_SKB_CB(skb)->dccpd_ack_seq); } @@ -83,7 +82,7 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) * Otherwise, * Drop packet and return */ - if (dh->dccph_type == DCCP_PKT_SYNC || + if (dh->dccph_type == DCCP_PKT_SYNC || dh->dccph_type == DCCP_PKT_SYNCACK) { if (between48(DCCP_SKB_CB(skb)->dccpd_ack_seq, dp->dccps_awl, dp->dccps_awh) && @@ -129,21 +128,18 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) DCCP_PKT_WITHOUT_ACK_SEQ)) dp->dccps_gar = DCCP_SKB_CB(skb)->dccpd_ack_seq; } else { - LIMIT_NETDEBUG(KERN_WARNING "DCCP: Step 6 failed for %s packet, " - "(LSWL(%llu) <= P.seqno(%llu) <= S.SWH(%llu)) and " - "(P.ackno %s or LAWL(%llu) <= P.ackno(%llu) <= S.AWH(%llu), " - "sending SYNC...\n", - dccp_packet_name(dh->dccph_type), - (unsigned long long) lswl, - (unsigned long long) - DCCP_SKB_CB(skb)->dccpd_seq, - (unsigned long long) dp->dccps_swh, - (DCCP_SKB_CB(skb)->dccpd_ack_seq == + DCCP_WARN("DCCP: Step 6 failed for %s packet, " + "(LSWL(%llu) <= P.seqno(%llu) <= S.SWH(%llu)) and " + "(P.ackno %s or LAWL(%llu) <= P.ackno(%llu) <= S.AWH(%llu), " + "sending SYNC...\n", dccp_packet_name(dh->dccph_type), + (unsigned long long) lswl, + (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq, + (unsigned long long) dp->dccps_swh, + (DCCP_SKB_CB(skb)->dccpd_ack_seq == DCCP_PKT_WITHOUT_ACK_SEQ) ? "doesn't exist" : "exists", - (unsigned long long) lawl, - (unsigned long long) - DCCP_SKB_CB(skb)->dccpd_ack_seq, - (unsigned long long) dp->dccps_awh); + (unsigned long long) lawl, + (unsigned long long) DCCP_SKB_CB(skb)->dccpd_ack_seq, + (unsigned long long) dp->dccps_awh); dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_PKT_SYNC); return -1; } @@ -151,9 +147,8 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) return 0; } -static inline int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb, - const struct dccp_hdr *dh, - const unsigned len) +static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb, + const struct dccp_hdr *dh, const unsigned len) { struct dccp_sock *dp = dccp_sk(sk); @@ -190,8 +185,8 @@ static inline int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb, dccp_rcv_close(sk, skb); return 0; case DCCP_PKT_REQUEST: - /* Step 7 - * or (S.is_server and P.type == Response) + /* Step 7 + * or (S.is_server and P.type == Response) * or (S.is_client and P.type == Request) * or (S.state >= OPEN and P.type == Request * and P.seqno >= S.OSR) @@ -218,11 +213,11 @@ send_sync: dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_PKT_SYNCACK); /* - * From the draft: + * From RFC 4340, sec. 5.7 * * As with DCCP-Ack packets, DCCP-Sync and DCCP-SyncAck packets * MAY have non-zero-length application data areas, whose - * contents * receivers MUST ignore. + * contents receivers MUST ignore. */ goto discard; } @@ -247,14 +242,24 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) dccp_event_ack_recv(sk, skb); - if (dp->dccps_options.dccpo_send_ack_vector && + if (dccp_msk(sk)->dccpms_send_ack_vector && dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_ACKVEC_STATE_RECEIVED)) goto discard; - ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); - ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); + /* + * Deliver to the CCID module in charge. + * FIXME: Currently DCCP operates one-directional only, i.e. a listening + * server is not at the same time a connecting client. There is + * not much sense in delivering to both rx/tx sides at the moment + * (only one is active at a time); when moving to bidirectional + * service, this needs to be revised. + */ + if (dccp_sk(sk)->dccps_role == DCCP_ROLE_SERVER) + ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); + else + ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); return __dccp_rcv_established(sk, skb, dh, len); discard: @@ -269,7 +274,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, const struct dccp_hdr *dh, const unsigned len) { - /* + /* * Step 4: Prepare sequence numbers in REQUEST * If S.state == REQUEST, * If (P.type == Response or P.type == Reset) @@ -300,7 +305,10 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, goto out_invalid_packet; } - if (dp->dccps_options.dccpo_send_ack_vector && + if (dccp_parse_options(sk, skb)) + goto out_invalid_packet; + + if (dccp_msk(sk)->dccpms_send_ack_vector && dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_ACKVEC_STATE_RECEIVED)) @@ -321,14 +329,6 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, dccp_set_seqno(&dp->dccps_swl, max48(dp->dccps_swl, dp->dccps_isr)); - if (ccid_hc_rx_init(dp->dccps_hc_rx_ccid, sk) != 0 || - ccid_hc_tx_init(dp->dccps_hc_tx_ccid, sk) != 0) { - ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk); - ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk); - /* FIXME: send appropriate RESET code */ - goto out_invalid_packet; - } - dccp_sync_mss(sk, icsk->icsk_pmtu_cookie); /* @@ -342,7 +342,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, * from the Response * / * S.state := PARTOPEN * Set PARTOPEN timer - * Continue with S.state == PARTOPEN + * Continue with S.state == PARTOPEN * / * Step 12 will send the Ack completing the * three-way handshake * / */ @@ -373,7 +373,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, */ __kfree_skb(skb); return 0; - } + } dccp_send_ack(sk); return -1; } @@ -381,7 +381,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, out_invalid_packet: /* dccp_v4_do_rcv will send a reset */ DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR; - return 1; + return 1; } static int dccp_rcv_respond_partopen_state_process(struct sock *sk, @@ -438,29 +438,25 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, /* * Step 3: Process LISTEN state - * (Continuing from dccp_v4_do_rcv and dccp_v6_do_rcv) * * If S.state == LISTEN, - * If P.type == Request or P contains a valid Init Cookie - * option, - * * Must scan the packet's options to check for an Init - * Cookie. Only the Init Cookie is processed here, - * however; other options are processed in Step 8. This - * scan need only be performed if the endpoint uses Init - * Cookies * - * * Generate a new socket and switch to that socket * - * Set S := new socket for this port pair - * S.state = RESPOND - * Choose S.ISS (initial seqno) or set from Init Cookie - * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie - * Continue with S.state == RESPOND - * * A Response packet will be generated in Step 11 * - * Otherwise, - * Generate Reset(No Connection) unless P.type == Reset - * Drop packet and return - * - * NOTE: the check for the packet types is done in - * dccp_rcv_state_process + * If P.type == Request or P contains a valid Init Cookie option, + * (* Must scan the packet's options to check for Init + * Cookies. Only Init Cookies are processed here, + * however; other options are processed in Step 8. This + * scan need only be performed if the endpoint uses Init + * Cookies *) + * (* Generate a new socket and switch to that socket *) + * Set S := new socket for this port pair + * S.state = RESPOND + * Choose S.ISS (initial seqno) or set from Init Cookies + * Initialize S.GAR := S.ISS + * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init + * Cookies Continue with S.state == RESPOND + * (* A Response packet will be generated in Step 11 *) + * Otherwise, + * Generate Reset(No Connection) unless P.type == Reset + * Drop packet and return */ if (sk->sk_state == DCCP_LISTEN) { if (dh->dccph_type == DCCP_PKT_REQUEST) { @@ -492,14 +488,17 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) dccp_event_ack_recv(sk, skb); - if (dp->dccps_options.dccpo_send_ack_vector && + if (dccp_msk(sk)->dccpms_send_ack_vector && dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, - DCCP_SKB_CB(skb)->dccpd_seq, - DCCP_ACKVEC_STATE_RECEIVED)) - goto discard; + DCCP_SKB_CB(skb)->dccpd_seq, + DCCP_ACKVEC_STATE_RECEIVED)) + goto discard; - ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); - ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); + /* XXX see the comments in dccp_rcv_established about this */ + if (dccp_sk(sk)->dccps_role == DCCP_ROLE_SERVER) + ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); + else + ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); } /* @@ -581,7 +580,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, } } - if (!queued) { + if (!queued) { discard: __kfree_skb(skb); }