aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/ipv4.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp/ipv4.c')
-rw-r--r--net/dccp/ipv4.c38
1 files changed, 33 insertions, 5 deletions
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 2afaa464e7f0..94a440b2685b 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -246,6 +246,9 @@ static int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr,
246 246
247 dp->dccps_role = DCCP_ROLE_CLIENT; 247 dp->dccps_role = DCCP_ROLE_CLIENT;
248 248
249 if (dccp_service_not_initialized(sk))
250 return -EPROTO;
251
249 if (addr_len < sizeof(struct sockaddr_in)) 252 if (addr_len < sizeof(struct sockaddr_in))
250 return -EINVAL; 253 return -EINVAL;
251 254
@@ -661,6 +664,16 @@ static inline u64 dccp_v4_init_sequence(const struct sock *sk,
661 dccp_hdr(skb)->dccph_sport); 664 dccp_hdr(skb)->dccph_sport);
662} 665}
663 666
667static inline int dccp_bad_service_code(const struct sock *sk,
668 const __u32 service)
669{
670 const struct dccp_sock *dp = dccp_sk(sk);
671
672 if (dp->dccps_service == service)
673 return 0;
674 return !dccp_list_has_service(dp->dccps_service_list, service);
675}
676
664int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) 677int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
665{ 678{
666 struct inet_request_sock *ireq; 679 struct inet_request_sock *ireq;
@@ -669,13 +682,22 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
669 struct dccp_request_sock *dreq; 682 struct dccp_request_sock *dreq;
670 const __u32 saddr = skb->nh.iph->saddr; 683 const __u32 saddr = skb->nh.iph->saddr;
671 const __u32 daddr = skb->nh.iph->daddr; 684 const __u32 daddr = skb->nh.iph->daddr;
685 const __u32 service = dccp_hdr_request(skb)->dccph_req_service;
686 struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
687 __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
672 struct dst_entry *dst = NULL; 688 struct dst_entry *dst = NULL;
673 689
674 /* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */ 690 /* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */
675 if (((struct rtable *)skb->dst)->rt_flags & 691 if (((struct rtable *)skb->dst)->rt_flags &
676 (RTCF_BROADCAST | RTCF_MULTICAST)) 692 (RTCF_BROADCAST | RTCF_MULTICAST)) {
693 reset_code = DCCP_RESET_CODE_NO_CONNECTION;
677 goto drop; 694 goto drop;
695 }
678 696
697 if (dccp_bad_service_code(sk, service)) {
698 reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
699 goto drop;
700 }
679 /* 701 /*
680 * TW buckets are converted to open requests without 702 * TW buckets are converted to open requests without
681 * limitations, they conserve resources and peer is 703 * limitations, they conserve resources and peer is
@@ -718,9 +740,9 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
718 * dccp_create_openreq_child. 740 * dccp_create_openreq_child.
719 */ 741 */
720 dreq = dccp_rsk(req); 742 dreq = dccp_rsk(req);
721 dreq->dreq_isr = DCCP_SKB_CB(skb)->dccpd_seq; 743 dreq->dreq_isr = dcb->dccpd_seq;
722 dreq->dreq_iss = dccp_v4_init_sequence(sk, skb); 744 dreq->dreq_iss = dccp_v4_init_sequence(sk, skb);
723 dreq->dreq_service = dccp_hdr_request(skb)->dccph_req_service; 745 dreq->dreq_service = service;
724 746
725 if (dccp_v4_send_response(sk, req, dst)) 747 if (dccp_v4_send_response(sk, req, dst))
726 goto drop_and_free; 748 goto drop_and_free;
@@ -735,6 +757,7 @@ drop_and_free:
735 __reqsk_free(req); 757 __reqsk_free(req);
736drop: 758drop:
737 DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS); 759 DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
760 dcb->dccpd_reset_code = reset_code;
738 return -1; 761 return -1;
739} 762}
740 763
@@ -1005,7 +1028,6 @@ int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
1005 return 0; 1028 return 0;
1006 1029
1007reset: 1030reset:
1008 DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION;
1009 dccp_v4_ctl_send_reset(skb); 1031 dccp_v4_ctl_send_reset(skb);
1010discard: 1032discard:
1011 kfree_skb(skb); 1033 kfree_skb(skb);
@@ -1280,6 +1302,7 @@ static int dccp_v4_init_sock(struct sock *sk)
1280 sk->sk_write_space = dccp_write_space; 1302 sk->sk_write_space = dccp_write_space;
1281 dp->dccps_mss_cache = 536; 1303 dp->dccps_mss_cache = 536;
1282 dp->dccps_role = DCCP_ROLE_UNDEFINED; 1304 dp->dccps_role = DCCP_ROLE_UNDEFINED;
1305 dp->dccps_service = DCCP_SERVICE_INVALID_VALUE;
1283 1306
1284 return 0; 1307 return 0;
1285} 1308}
@@ -1301,6 +1324,11 @@ static int dccp_v4_destroy_sock(struct sock *sk)
1301 if (inet_csk(sk)->icsk_bind_hash != NULL) 1324 if (inet_csk(sk)->icsk_bind_hash != NULL)
1302 inet_put_port(&dccp_hashinfo, sk); 1325 inet_put_port(&dccp_hashinfo, sk);
1303 1326
1327 if (dp->dccps_service_list != NULL) {
1328 kfree(dp->dccps_service_list);
1329 dp->dccps_service_list = NULL;
1330 }
1331
1304 ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk); 1332 ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk);
1305 ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk); 1333 ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk);
1306 dccp_ackpkts_free(dp->dccps_hc_rx_ackpkts); 1334 dccp_ackpkts_free(dp->dccps_hc_rx_ackpkts);