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.c101
1 files changed, 47 insertions, 54 deletions
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 2afaa464e7f0..40fe6afacde6 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -23,6 +23,7 @@
23#include <net/tcp_states.h> 23#include <net/tcp_states.h>
24#include <net/xfrm.h> 24#include <net/xfrm.h>
25 25
26#include "ackvec.h"
26#include "ccid.h" 27#include "ccid.h"
27#include "dccp.h" 28#include "dccp.h"
28 29
@@ -246,6 +247,9 @@ static int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr,
246 247
247 dp->dccps_role = DCCP_ROLE_CLIENT; 248 dp->dccps_role = DCCP_ROLE_CLIENT;
248 249
250 if (dccp_service_not_initialized(sk))
251 return -EPROTO;
252
249 if (addr_len < sizeof(struct sockaddr_in)) 253 if (addr_len < sizeof(struct sockaddr_in))
250 return -EINVAL; 254 return -EINVAL;
251 255
@@ -661,6 +665,16 @@ static inline u64 dccp_v4_init_sequence(const struct sock *sk,
661 dccp_hdr(skb)->dccph_sport); 665 dccp_hdr(skb)->dccph_sport);
662} 666}
663 667
668static inline int dccp_bad_service_code(const struct sock *sk,
669 const __u32 service)
670{
671 const struct dccp_sock *dp = dccp_sk(sk);
672
673 if (dp->dccps_service == service)
674 return 0;
675 return !dccp_list_has_service(dp->dccps_service_list, service);
676}
677
664int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) 678int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
665{ 679{
666 struct inet_request_sock *ireq; 680 struct inet_request_sock *ireq;
@@ -669,13 +683,22 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
669 struct dccp_request_sock *dreq; 683 struct dccp_request_sock *dreq;
670 const __u32 saddr = skb->nh.iph->saddr; 684 const __u32 saddr = skb->nh.iph->saddr;
671 const __u32 daddr = skb->nh.iph->daddr; 685 const __u32 daddr = skb->nh.iph->daddr;
686 const __u32 service = dccp_hdr_request(skb)->dccph_req_service;
687 struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
688 __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
672 struct dst_entry *dst = NULL; 689 struct dst_entry *dst = NULL;
673 690
674 /* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */ 691 /* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */
675 if (((struct rtable *)skb->dst)->rt_flags & 692 if (((struct rtable *)skb->dst)->rt_flags &
676 (RTCF_BROADCAST | RTCF_MULTICAST)) 693 (RTCF_BROADCAST | RTCF_MULTICAST)) {
694 reset_code = DCCP_RESET_CODE_NO_CONNECTION;
677 goto drop; 695 goto drop;
696 }
678 697
698 if (dccp_bad_service_code(sk, service)) {
699 reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
700 goto drop;
701 }
679 /* 702 /*
680 * TW buckets are converted to open requests without 703 * TW buckets are converted to open requests without
681 * limitations, they conserve resources and peer is 704 * limitations, they conserve resources and peer is
@@ -718,9 +741,9 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
718 * dccp_create_openreq_child. 741 * dccp_create_openreq_child.
719 */ 742 */
720 dreq = dccp_rsk(req); 743 dreq = dccp_rsk(req);
721 dreq->dreq_isr = DCCP_SKB_CB(skb)->dccpd_seq; 744 dreq->dreq_isr = dcb->dccpd_seq;
722 dreq->dreq_iss = dccp_v4_init_sequence(sk, skb); 745 dreq->dreq_iss = dccp_v4_init_sequence(sk, skb);
723 dreq->dreq_service = dccp_hdr_request(skb)->dccph_req_service; 746 dreq->dreq_service = service;
724 747
725 if (dccp_v4_send_response(sk, req, dst)) 748 if (dccp_v4_send_response(sk, req, dst))
726 goto drop_and_free; 749 goto drop_and_free;
@@ -735,6 +758,7 @@ drop_and_free:
735 __reqsk_free(req); 758 __reqsk_free(req);
736drop: 759drop:
737 DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS); 760 DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
761 dcb->dccpd_reset_code = reset_code;
738 return -1; 762 return -1;
739} 763}
740 764
@@ -1005,7 +1029,6 @@ int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
1005 return 0; 1029 return 0;
1006 1030
1007reset: 1031reset:
1008 DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION;
1009 dccp_v4_ctl_send_reset(skb); 1032 dccp_v4_ctl_send_reset(skb);
1010discard: 1033discard:
1011 kfree_skb(skb); 1034 kfree_skb(skb);
@@ -1090,45 +1113,7 @@ int dccp_v4_rcv(struct sk_buff *skb)
1090 goto discard_it; 1113 goto discard_it;
1091 1114
1092 dh = dccp_hdr(skb); 1115 dh = dccp_hdr(skb);
1093#if 0
1094 /*
1095 * Use something like this to simulate some DATA/DATAACK loss to test
1096 * dccp_ackpkts_add, you'll get something like this on a session that
1097 * sends 10 DATA/DATAACK packets:
1098 *
1099 * ackpkts_print: 281473596467422 |0,0|3,0|0,0|3,0|0,0|3,0|0,0|3,0|0,1|
1100 *
1101 * 0, 0 means: DCCP_ACKPKTS_STATE_RECEIVED, RLE == just this packet
1102 * 0, 1 means: DCCP_ACKPKTS_STATE_RECEIVED, RLE == two adjacent packets
1103 * with the same state
1104 * 3, 0 means: DCCP_ACKPKTS_STATE_NOT_RECEIVED, RLE == just this packet
1105 *
1106 * So...
1107 *
1108 * 281473596467422 was received
1109 * 281473596467421 was not received
1110 * 281473596467420 was received
1111 * 281473596467419 was not received
1112 * 281473596467418 was received
1113 * 281473596467417 was not received
1114 * 281473596467416 was received
1115 * 281473596467415 was not received
1116 * 281473596467414 was received
1117 * 281473596467413 was received (this one was the 3way handshake
1118 * RESPONSE)
1119 *
1120 */
1121 if (dh->dccph_type == DCCP_PKT_DATA ||
1122 dh->dccph_type == DCCP_PKT_DATAACK) {
1123 static int discard = 0;
1124 1116
1125 if (discard) {
1126 discard = 0;
1127 goto discard_it;
1128 }
1129 discard = 1;
1130 }
1131#endif
1132 DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb); 1117 DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb);
1133 DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type; 1118 DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type;
1134 1119
@@ -1242,11 +1227,9 @@ static int dccp_v4_init_sock(struct sock *sk)
1242 do_gettimeofday(&dp->dccps_epoch); 1227 do_gettimeofday(&dp->dccps_epoch);
1243 1228
1244 if (dp->dccps_options.dccpo_send_ack_vector) { 1229 if (dp->dccps_options.dccpo_send_ack_vector) {
1245 dp->dccps_hc_rx_ackpkts = 1230 dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(DCCP_MAX_ACKVEC_LEN,
1246 dccp_ackpkts_alloc(DCCP_MAX_ACK_VECTOR_LEN, 1231 GFP_KERNEL);
1247 GFP_KERNEL); 1232 if (dp->dccps_hc_rx_ackvec == NULL)
1248
1249 if (dp->dccps_hc_rx_ackpkts == NULL)
1250 return -ENOMEM; 1233 return -ENOMEM;
1251 } 1234 }
1252 1235
@@ -1258,16 +1241,18 @@ static int dccp_v4_init_sock(struct sock *sk)
1258 * setsockopt(CCIDs-I-want/accept). -acme 1241 * setsockopt(CCIDs-I-want/accept). -acme
1259 */ 1242 */
1260 if (likely(!dccp_ctl_socket_init)) { 1243 if (likely(!dccp_ctl_socket_init)) {
1261 dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_ccid, 1244 dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_rx_ccid,
1262 sk); 1245 sk);
1263 dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_ccid, 1246 dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_tx_ccid,
1264 sk); 1247 sk);
1265 if (dp->dccps_hc_rx_ccid == NULL || 1248 if (dp->dccps_hc_rx_ccid == NULL ||
1266 dp->dccps_hc_tx_ccid == NULL) { 1249 dp->dccps_hc_tx_ccid == NULL) {
1267 ccid_exit(dp->dccps_hc_rx_ccid, sk); 1250 ccid_exit(dp->dccps_hc_rx_ccid, sk);
1268 ccid_exit(dp->dccps_hc_tx_ccid, sk); 1251 ccid_exit(dp->dccps_hc_tx_ccid, sk);
1269 dccp_ackpkts_free(dp->dccps_hc_rx_ackpkts); 1252 if (dp->dccps_options.dccpo_send_ack_vector) {
1270 dp->dccps_hc_rx_ackpkts = NULL; 1253 dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
1254 dp->dccps_hc_rx_ackvec = NULL;
1255 }
1271 dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; 1256 dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
1272 return -ENOMEM; 1257 return -ENOMEM;
1273 } 1258 }
@@ -1280,6 +1265,7 @@ static int dccp_v4_init_sock(struct sock *sk)
1280 sk->sk_write_space = dccp_write_space; 1265 sk->sk_write_space = dccp_write_space;
1281 dp->dccps_mss_cache = 536; 1266 dp->dccps_mss_cache = 536;
1282 dp->dccps_role = DCCP_ROLE_UNDEFINED; 1267 dp->dccps_role = DCCP_ROLE_UNDEFINED;
1268 dp->dccps_service = DCCP_SERVICE_INVALID_VALUE;
1283 1269
1284 return 0; 1270 return 0;
1285} 1271}
@@ -1301,10 +1287,17 @@ static int dccp_v4_destroy_sock(struct sock *sk)
1301 if (inet_csk(sk)->icsk_bind_hash != NULL) 1287 if (inet_csk(sk)->icsk_bind_hash != NULL)
1302 inet_put_port(&dccp_hashinfo, sk); 1288 inet_put_port(&dccp_hashinfo, sk);
1303 1289
1290 if (dp->dccps_service_list != NULL) {
1291 kfree(dp->dccps_service_list);
1292 dp->dccps_service_list = NULL;
1293 }
1294
1304 ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk); 1295 ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk);
1305 ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk); 1296 ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk);
1306 dccp_ackpkts_free(dp->dccps_hc_rx_ackpkts); 1297 if (dp->dccps_options.dccpo_send_ack_vector) {
1307 dp->dccps_hc_rx_ackpkts = NULL; 1298 dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
1299 dp->dccps_hc_rx_ackvec = NULL;
1300 }
1308 ccid_exit(dp->dccps_hc_rx_ccid, sk); 1301 ccid_exit(dp->dccps_hc_rx_ccid, sk);
1309 ccid_exit(dp->dccps_hc_tx_ccid, sk); 1302 ccid_exit(dp->dccps_hc_tx_ccid, sk);
1310 dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; 1303 dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;