diff options
Diffstat (limited to 'net/dccp/minisocks.c')
-rw-r--r-- | net/dccp/minisocks.c | 87 |
1 files changed, 64 insertions, 23 deletions
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index f4d9c8f60ede..b2804e2d1b8c 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c | |||
@@ -42,6 +42,16 @@ struct inet_timewait_death_row dccp_death_row = { | |||
42 | 42 | ||
43 | EXPORT_SYMBOL_GPL(dccp_death_row); | 43 | EXPORT_SYMBOL_GPL(dccp_death_row); |
44 | 44 | ||
45 | void dccp_minisock_init(struct dccp_minisock *dmsk) | ||
46 | { | ||
47 | dmsk->dccpms_sequence_window = sysctl_dccp_feat_sequence_window; | ||
48 | dmsk->dccpms_rx_ccid = sysctl_dccp_feat_rx_ccid; | ||
49 | dmsk->dccpms_tx_ccid = sysctl_dccp_feat_tx_ccid; | ||
50 | dmsk->dccpms_ack_ratio = sysctl_dccp_feat_ack_ratio; | ||
51 | dmsk->dccpms_send_ack_vector = sysctl_dccp_feat_send_ack_vector; | ||
52 | dmsk->dccpms_send_ndp_count = sysctl_dccp_feat_send_ndp_count; | ||
53 | } | ||
54 | |||
45 | void dccp_time_wait(struct sock *sk, int state, int timeo) | 55 | void dccp_time_wait(struct sock *sk, int state, int timeo) |
46 | { | 56 | { |
47 | struct inet_timewait_sock *tw = NULL; | 57 | struct inet_timewait_sock *tw = NULL; |
@@ -102,9 +112,10 @@ struct sock *dccp_create_openreq_child(struct sock *sk, | |||
102 | struct sock *newsk = inet_csk_clone(sk, req, GFP_ATOMIC); | 112 | struct sock *newsk = inet_csk_clone(sk, req, GFP_ATOMIC); |
103 | 113 | ||
104 | if (newsk != NULL) { | 114 | if (newsk != NULL) { |
105 | struct dccp_request_sock *dreq = dccp_rsk(req); | 115 | const struct dccp_request_sock *dreq = dccp_rsk(req); |
106 | struct inet_connection_sock *newicsk = inet_csk(newsk); | 116 | struct inet_connection_sock *newicsk = inet_csk(newsk); |
107 | struct dccp_sock *newdp = dccp_sk(newsk); | 117 | struct dccp_sock *newdp = dccp_sk(newsk); |
118 | struct dccp_minisock *newdmsk = dccp_msk(newsk); | ||
108 | 119 | ||
109 | newdp->dccps_role = DCCP_ROLE_SERVER; | 120 | newdp->dccps_role = DCCP_ROLE_SERVER; |
110 | newdp->dccps_hc_rx_ackvec = NULL; | 121 | newdp->dccps_hc_rx_ackvec = NULL; |
@@ -114,32 +125,65 @@ struct sock *dccp_create_openreq_child(struct sock *sk, | |||
114 | newdp->dccps_timestamp_time = dreq->dreq_timestamp_time; | 125 | newdp->dccps_timestamp_time = dreq->dreq_timestamp_time; |
115 | newicsk->icsk_rto = DCCP_TIMEOUT_INIT; | 126 | newicsk->icsk_rto = DCCP_TIMEOUT_INIT; |
116 | 127 | ||
117 | INIT_LIST_HEAD(&newdp->dccps_featneg); | 128 | if (dccp_feat_clone(sk, newsk)) |
129 | goto out_free; | ||
130 | |||
131 | if (newdmsk->dccpms_send_ack_vector) { | ||
132 | newdp->dccps_hc_rx_ackvec = | ||
133 | dccp_ackvec_alloc(GFP_ATOMIC); | ||
134 | if (unlikely(newdp->dccps_hc_rx_ackvec == NULL)) | ||
135 | goto out_free; | ||
136 | } | ||
137 | |||
138 | newdp->dccps_hc_rx_ccid = | ||
139 | ccid_hc_rx_new(newdmsk->dccpms_rx_ccid, | ||
140 | newsk, GFP_ATOMIC); | ||
141 | newdp->dccps_hc_tx_ccid = | ||
142 | ccid_hc_tx_new(newdmsk->dccpms_tx_ccid, | ||
143 | newsk, GFP_ATOMIC); | ||
144 | if (unlikely(newdp->dccps_hc_rx_ccid == NULL || | ||
145 | newdp->dccps_hc_tx_ccid == NULL)) { | ||
146 | dccp_ackvec_free(newdp->dccps_hc_rx_ackvec); | ||
147 | ccid_hc_rx_delete(newdp->dccps_hc_rx_ccid, newsk); | ||
148 | ccid_hc_tx_delete(newdp->dccps_hc_tx_ccid, newsk); | ||
149 | out_free: | ||
150 | /* It is still raw copy of parent, so invalidate | ||
151 | * destructor and make plain sk_free() */ | ||
152 | newsk->sk_destruct = NULL; | ||
153 | sk_free(newsk); | ||
154 | return NULL; | ||
155 | } | ||
156 | |||
118 | /* | 157 | /* |
119 | * Step 3: Process LISTEN state | 158 | * Step 3: Process LISTEN state |
120 | * | 159 | * |
121 | * Choose S.ISS (initial seqno) or set from Init Cookies | 160 | * Choose S.ISS (initial seqno) or set from Init Cookies |
122 | * Initialize S.GAR := S.ISS | 161 | * Initialize S.GAR := S.ISS |
123 | * Set S.ISR, S.GSR from packet (or Init Cookies) | 162 | * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookies |
124 | * | ||
125 | * Setting AWL/AWH and SWL/SWH happens as part of the feature | ||
126 | * activation below, as these windows all depend on the local | ||
127 | * and remote Sequence Window feature values (7.5.2). | ||
128 | */ | 163 | */ |
129 | newdp->dccps_gss = newdp->dccps_iss = dreq->dreq_iss; | 164 | |
130 | newdp->dccps_gar = newdp->dccps_iss; | 165 | /* See dccp_v4_conn_request */ |
131 | newdp->dccps_gsr = newdp->dccps_isr = dreq->dreq_isr; | 166 | newdmsk->dccpms_sequence_window = req->rcv_wnd; |
167 | |||
168 | newdp->dccps_gar = newdp->dccps_iss = dreq->dreq_iss; | ||
169 | dccp_update_gss(newsk, dreq->dreq_iss); | ||
170 | |||
171 | newdp->dccps_isr = dreq->dreq_isr; | ||
172 | dccp_update_gsr(newsk, dreq->dreq_isr); | ||
132 | 173 | ||
133 | /* | 174 | /* |
134 | * Activate features: initialise CCIDs, sequence windows etc. | 175 | * SWL and AWL are initially adjusted so that they are not less than |
176 | * the initial Sequence Numbers received and sent, respectively: | ||
177 | * SWL := max(GSR + 1 - floor(W/4), ISR), | ||
178 | * AWL := max(GSS - W' + 1, ISS). | ||
179 | * These adjustments MUST be applied only at the beginning of the | ||
180 | * connection. | ||
135 | */ | 181 | */ |
136 | if (dccp_feat_activate_values(newsk, &dreq->dreq_featneg)) { | 182 | dccp_set_seqno(&newdp->dccps_swl, |
137 | /* It is still raw copy of parent, so invalidate | 183 | max48(newdp->dccps_swl, newdp->dccps_isr)); |
138 | * destructor and make plain sk_free() */ | 184 | dccp_set_seqno(&newdp->dccps_awl, |
139 | newsk->sk_destruct = NULL; | 185 | max48(newdp->dccps_awl, newdp->dccps_iss)); |
140 | sk_free(newsk); | 186 | |
141 | return NULL; | ||
142 | } | ||
143 | dccp_init_xmit_timers(newsk); | 187 | dccp_init_xmit_timers(newsk); |
144 | 188 | ||
145 | DCCP_INC_STATS_BH(DCCP_MIB_PASSIVEOPENS); | 189 | DCCP_INC_STATS_BH(DCCP_MIB_PASSIVEOPENS); |
@@ -260,17 +304,14 @@ void dccp_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, | |||
260 | 304 | ||
261 | EXPORT_SYMBOL_GPL(dccp_reqsk_send_ack); | 305 | EXPORT_SYMBOL_GPL(dccp_reqsk_send_ack); |
262 | 306 | ||
263 | int dccp_reqsk_init(struct request_sock *req, | 307 | void dccp_reqsk_init(struct request_sock *req, struct sk_buff *skb) |
264 | struct dccp_sock const *dp, struct sk_buff const *skb) | ||
265 | { | 308 | { |
266 | struct dccp_request_sock *dreq = dccp_rsk(req); | 309 | struct dccp_request_sock *dreq = dccp_rsk(req); |
267 | 310 | ||
268 | inet_rsk(req)->rmt_port = dccp_hdr(skb)->dccph_sport; | 311 | inet_rsk(req)->rmt_port = dccp_hdr(skb)->dccph_sport; |
269 | inet_rsk(req)->acked = 0; | 312 | inet_rsk(req)->acked = 0; |
313 | req->rcv_wnd = sysctl_dccp_feat_sequence_window; | ||
270 | dreq->dreq_timestamp_echo = 0; | 314 | dreq->dreq_timestamp_echo = 0; |
271 | |||
272 | /* inherit feature negotiation options from listening socket */ | ||
273 | return dccp_feat_clone_list(&dp->dccps_featneg, &dreq->dreq_featneg); | ||
274 | } | 315 | } |
275 | 316 | ||
276 | EXPORT_SYMBOL_GPL(dccp_reqsk_init); | 317 | EXPORT_SYMBOL_GPL(dccp_reqsk_init); |