aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-01-19 19:53:02 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-01-19 19:53:02 -0500
commitcf9e50a920be24b734fb91f19b8844f8509cb981 (patch)
treea077c31bcfe9844bcfa7ff1fe07364b5b7958622 /net
parent0f36b018b2e314d45af86449f1a97facb1fbe300 (diff)
parenta7d1f1b66c05ef4ebb58a34be7caad9af15546a4 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/sridhar/lksctp-2.6
Diffstat (limited to 'net')
-rw-r--r--net/sctp/input.c75
-rw-r--r--net/sctp/inqueue.c4
-rw-r--r--net/sctp/proc.c32
-rw-r--r--net/sctp/sm_make_chunk.c16
-rw-r--r--net/sctp/sm_sideeffect.c4
-rw-r--r--net/sctp/sm_statefuns.c2
-rw-r--r--net/sctp/socket.c6
-rw-r--r--net/sctp/sysctl.c7
-rw-r--r--net/sctp/transport.c2
9 files changed, 102 insertions, 46 deletions
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 4aa6fc60357c..cb78b50868ee 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -257,20 +257,26 @@ int sctp_rcv(struct sk_buff *skb)
257 */ 257 */
258 sctp_bh_lock_sock(sk); 258 sctp_bh_lock_sock(sk);
259 259
260 /* It is possible that the association could have moved to a different
261 * socket if it is peeled off. If so, update the sk.
262 */
263 if (sk != rcvr->sk) {
264 sctp_bh_lock_sock(rcvr->sk);
265 sctp_bh_unlock_sock(sk);
266 sk = rcvr->sk;
267 }
268
260 if (sock_owned_by_user(sk)) 269 if (sock_owned_by_user(sk))
261 sk_add_backlog(sk, skb); 270 sk_add_backlog(sk, skb);
262 else 271 else
263 sctp_backlog_rcv(sk, skb); 272 sctp_backlog_rcv(sk, skb);
264 273
265 /* Release the sock and any reference counts we took in the 274 /* Release the sock and the sock ref we took in the lookup calls.
266 * lookup calls. 275 * The asoc/ep ref will be released in sctp_backlog_rcv.
267 */ 276 */
268 sctp_bh_unlock_sock(sk); 277 sctp_bh_unlock_sock(sk);
269 if (asoc)
270 sctp_association_put(asoc);
271 else
272 sctp_endpoint_put(ep);
273 sock_put(sk); 278 sock_put(sk);
279
274 return ret; 280 return ret;
275 281
276discard_it: 282discard_it:
@@ -296,12 +302,50 @@ discard_release:
296int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb) 302int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
297{ 303{
298 struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk; 304 struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
299 struct sctp_inq *inqueue = &chunk->rcvr->inqueue; 305 struct sctp_inq *inqueue = NULL;
300 306 struct sctp_ep_common *rcvr = NULL;
301 sctp_inq_push(inqueue, chunk); 307
308 rcvr = chunk->rcvr;
309
310 BUG_TRAP(rcvr->sk == sk);
311
312 if (rcvr->dead) {
313 sctp_chunk_free(chunk);
314 } else {
315 inqueue = &chunk->rcvr->inqueue;
316 sctp_inq_push(inqueue, chunk);
317 }
318
319 /* Release the asoc/ep ref we took in the lookup calls in sctp_rcv. */
320 if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type)
321 sctp_association_put(sctp_assoc(rcvr));
322 else
323 sctp_endpoint_put(sctp_ep(rcvr));
324
302 return 0; 325 return 0;
303} 326}
304 327
328void sctp_backlog_migrate(struct sctp_association *assoc,
329 struct sock *oldsk, struct sock *newsk)
330{
331 struct sk_buff *skb;
332 struct sctp_chunk *chunk;
333
334 skb = oldsk->sk_backlog.head;
335 oldsk->sk_backlog.head = oldsk->sk_backlog.tail = NULL;
336 while (skb != NULL) {
337 struct sk_buff *next = skb->next;
338
339 chunk = SCTP_INPUT_CB(skb)->chunk;
340 skb->next = NULL;
341 if (&assoc->base == chunk->rcvr)
342 sk_add_backlog(newsk, skb);
343 else
344 sk_add_backlog(oldsk, skb);
345 skb = next;
346 }
347}
348
305/* Handle icmp frag needed error. */ 349/* Handle icmp frag needed error. */
306void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc, 350void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
307 struct sctp_transport *t, __u32 pmtu) 351 struct sctp_transport *t, __u32 pmtu)
@@ -544,10 +588,16 @@ int sctp_rcv_ootb(struct sk_buff *skb)
544 sctp_errhdr_t *err; 588 sctp_errhdr_t *err;
545 589
546 ch = (sctp_chunkhdr_t *) skb->data; 590 ch = (sctp_chunkhdr_t *) skb->data;
547 ch_end = ((__u8 *) ch) + WORD_ROUND(ntohs(ch->length));
548 591
549 /* Scan through all the chunks in the packet. */ 592 /* Scan through all the chunks in the packet. */
550 while (ch_end > (__u8 *)ch && ch_end < skb->tail) { 593 do {
594 /* Break out if chunk length is less then minimal. */
595 if (ntohs(ch->length) < sizeof(sctp_chunkhdr_t))
596 break;
597
598 ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
599 if (ch_end > skb->tail)
600 break;
551 601
552 /* RFC 8.4, 2) If the OOTB packet contains an ABORT chunk, the 602 /* RFC 8.4, 2) If the OOTB packet contains an ABORT chunk, the
553 * receiver MUST silently discard the OOTB packet and take no 603 * receiver MUST silently discard the OOTB packet and take no
@@ -578,8 +628,7 @@ int sctp_rcv_ootb(struct sk_buff *skb)
578 } 628 }
579 629
580 ch = (sctp_chunkhdr_t *) ch_end; 630 ch = (sctp_chunkhdr_t *) ch_end;
581 ch_end = ((__u8 *) ch) + WORD_ROUND(ntohs(ch->length)); 631 } while (ch_end < skb->tail);
582 }
583 632
584 return 0; 633 return 0;
585 634
diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c
index 2d33922c044b..297b8951463e 100644
--- a/net/sctp/inqueue.c
+++ b/net/sctp/inqueue.c
@@ -73,8 +73,10 @@ void sctp_inq_free(struct sctp_inq *queue)
73 /* If there is a packet which is currently being worked on, 73 /* If there is a packet which is currently being worked on,
74 * free it as well. 74 * free it as well.
75 */ 75 */
76 if (queue->in_progress) 76 if (queue->in_progress) {
77 sctp_chunk_free(queue->in_progress); 77 sctp_chunk_free(queue->in_progress);
78 queue->in_progress = NULL;
79 }
78 80
79 if (queue->malloced) { 81 if (queue->malloced) {
80 /* Dump the master memory segment. */ 82 /* Dump the master memory segment. */
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 6e4dc28874d7..d47a52c303a8 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -176,7 +176,7 @@ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_associa
176 176
177static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos) 177static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos)
178{ 178{
179 if (*pos > sctp_ep_hashsize) 179 if (*pos >= sctp_ep_hashsize)
180 return NULL; 180 return NULL;
181 181
182 if (*pos < 0) 182 if (*pos < 0)
@@ -185,8 +185,6 @@ static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos)
185 if (*pos == 0) 185 if (*pos == 0)
186 seq_printf(seq, " ENDPT SOCK STY SST HBKT LPORT UID INODE LADDRS\n"); 186 seq_printf(seq, " ENDPT SOCK STY SST HBKT LPORT UID INODE LADDRS\n");
187 187
188 ++*pos;
189
190 return (void *)pos; 188 return (void *)pos;
191} 189}
192 190
@@ -198,11 +196,9 @@ static void sctp_eps_seq_stop(struct seq_file *seq, void *v)
198 196
199static void * sctp_eps_seq_next(struct seq_file *seq, void *v, loff_t *pos) 197static void * sctp_eps_seq_next(struct seq_file *seq, void *v, loff_t *pos)
200{ 198{
201 if (*pos > sctp_ep_hashsize) 199 if (++*pos >= sctp_ep_hashsize)
202 return NULL; 200 return NULL;
203 201
204 ++*pos;
205
206 return pos; 202 return pos;
207} 203}
208 204
@@ -214,19 +210,19 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v)
214 struct sctp_ep_common *epb; 210 struct sctp_ep_common *epb;
215 struct sctp_endpoint *ep; 211 struct sctp_endpoint *ep;
216 struct sock *sk; 212 struct sock *sk;
217 int hash = *(int *)v; 213 int hash = *(loff_t *)v;
218 214
219 if (hash > sctp_ep_hashsize) 215 if (hash >= sctp_ep_hashsize)
220 return -ENOMEM; 216 return -ENOMEM;
221 217
222 head = &sctp_ep_hashtable[hash-1]; 218 head = &sctp_ep_hashtable[hash];
223 sctp_local_bh_disable(); 219 sctp_local_bh_disable();
224 read_lock(&head->lock); 220 read_lock(&head->lock);
225 for (epb = head->chain; epb; epb = epb->next) { 221 for (epb = head->chain; epb; epb = epb->next) {
226 ep = sctp_ep(epb); 222 ep = sctp_ep(epb);
227 sk = epb->sk; 223 sk = epb->sk;
228 seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk, 224 seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk,
229 sctp_sk(sk)->type, sk->sk_state, hash-1, 225 sctp_sk(sk)->type, sk->sk_state, hash,
230 epb->bind_addr.port, 226 epb->bind_addr.port,
231 sock_i_uid(sk), sock_i_ino(sk)); 227 sock_i_uid(sk), sock_i_ino(sk));
232 228
@@ -283,7 +279,7 @@ void sctp_eps_proc_exit(void)
283 279
284static void * sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos) 280static void * sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos)
285{ 281{
286 if (*pos > sctp_assoc_hashsize) 282 if (*pos >= sctp_assoc_hashsize)
287 return NULL; 283 return NULL;
288 284
289 if (*pos < 0) 285 if (*pos < 0)
@@ -293,8 +289,6 @@ static void * sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos)
293 seq_printf(seq, " ASSOC SOCK STY SST ST HBKT ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT " 289 seq_printf(seq, " ASSOC SOCK STY SST ST HBKT ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT "
294 "RPORT LADDRS <-> RADDRS\n"); 290 "RPORT LADDRS <-> RADDRS\n");
295 291
296 ++*pos;
297
298 return (void *)pos; 292 return (void *)pos;
299} 293}
300 294
@@ -306,11 +300,9 @@ static void sctp_assocs_seq_stop(struct seq_file *seq, void *v)
306 300
307static void * sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos) 301static void * sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos)
308{ 302{
309 if (*pos > sctp_assoc_hashsize) 303 if (++*pos >= sctp_assoc_hashsize)
310 return NULL; 304 return NULL;
311 305
312 ++*pos;
313
314 return pos; 306 return pos;
315} 307}
316 308
@@ -321,12 +313,12 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
321 struct sctp_ep_common *epb; 313 struct sctp_ep_common *epb;
322 struct sctp_association *assoc; 314 struct sctp_association *assoc;
323 struct sock *sk; 315 struct sock *sk;
324 int hash = *(int *)v; 316 int hash = *(loff_t *)v;
325 317
326 if (hash > sctp_assoc_hashsize) 318 if (hash >= sctp_assoc_hashsize)
327 return -ENOMEM; 319 return -ENOMEM;
328 320
329 head = &sctp_assoc_hashtable[hash-1]; 321 head = &sctp_assoc_hashtable[hash];
330 sctp_local_bh_disable(); 322 sctp_local_bh_disable();
331 read_lock(&head->lock); 323 read_lock(&head->lock);
332 for (epb = head->chain; epb; epb = epb->next) { 324 for (epb = head->chain; epb; epb = epb->next) {
@@ -335,7 +327,7 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
335 seq_printf(seq, 327 seq_printf(seq,
336 "%8p %8p %-3d %-3d %-2d %-4d %4d %8d %8d %7d %5lu %-5d %5d ", 328 "%8p %8p %-3d %-3d %-2d %-4d %4d %8d %8d %7d %5lu %-5d %5d ",
337 assoc, sk, sctp_sk(sk)->type, sk->sk_state, 329 assoc, sk, sctp_sk(sk)->type, sk->sk_state,
338 assoc->state, hash-1, assoc->assoc_id, 330 assoc->state, hash, assoc->assoc_id,
339 (sk->sk_rcvbuf - assoc->rwnd), 331 (sk->sk_rcvbuf - assoc->rwnd),
340 assoc->sndbuf_used, 332 assoc->sndbuf_used,
341 sock_i_uid(sk), sock_i_ino(sk), 333 sock_i_uid(sk), sock_i_ino(sk),
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 556c495c6922..5e0de3c0eead 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1275,7 +1275,12 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
1275 unsigned int keylen; 1275 unsigned int keylen;
1276 char *key; 1276 char *key;
1277 1277
1278 headersize = sizeof(sctp_paramhdr_t) + SCTP_SECRET_SIZE; 1278 /* Header size is static data prior to the actual cookie, including
1279 * any padding.
1280 */
1281 headersize = sizeof(sctp_paramhdr_t) +
1282 (sizeof(struct sctp_signed_cookie) -
1283 sizeof(struct sctp_cookie));
1279 bodysize = sizeof(struct sctp_cookie) 1284 bodysize = sizeof(struct sctp_cookie)
1280 + ntohs(init_chunk->chunk_hdr->length) + addrs_len; 1285 + ntohs(init_chunk->chunk_hdr->length) + addrs_len;
1281 1286
@@ -1354,7 +1359,7 @@ struct sctp_association *sctp_unpack_cookie(
1354 struct sctp_signed_cookie *cookie; 1359 struct sctp_signed_cookie *cookie;
1355 struct sctp_cookie *bear_cookie; 1360 struct sctp_cookie *bear_cookie;
1356 int headersize, bodysize, fixed_size; 1361 int headersize, bodysize, fixed_size;
1357 __u8 digest[SCTP_SIGNATURE_SIZE]; 1362 __u8 *digest = ep->digest;
1358 struct scatterlist sg; 1363 struct scatterlist sg;
1359 unsigned int keylen, len; 1364 unsigned int keylen, len;
1360 char *key; 1365 char *key;
@@ -1362,7 +1367,12 @@ struct sctp_association *sctp_unpack_cookie(
1362 struct sk_buff *skb = chunk->skb; 1367 struct sk_buff *skb = chunk->skb;
1363 struct timeval tv; 1368 struct timeval tv;
1364 1369
1365 headersize = sizeof(sctp_chunkhdr_t) + SCTP_SECRET_SIZE; 1370 /* Header size is static data prior to the actual cookie, including
1371 * any padding.
1372 */
1373 headersize = sizeof(sctp_chunkhdr_t) +
1374 (sizeof(struct sctp_signed_cookie) -
1375 sizeof(struct sctp_cookie));
1366 bodysize = ntohs(chunk->chunk_hdr->length) - headersize; 1376 bodysize = ntohs(chunk->chunk_hdr->length) - headersize;
1367 fixed_size = headersize + sizeof(struct sctp_cookie); 1377 fixed_size = headersize + sizeof(struct sctp_cookie);
1368 1378
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index b8b38aba92b3..8d1dc24bab4c 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -1300,7 +1300,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
1300 "T1 INIT Timeout adjustment" 1300 "T1 INIT Timeout adjustment"
1301 " init_err_counter: %d" 1301 " init_err_counter: %d"
1302 " cycle: %d" 1302 " cycle: %d"
1303 " timeout: %d\n", 1303 " timeout: %ld\n",
1304 asoc->init_err_counter, 1304 asoc->init_err_counter,
1305 asoc->init_cycle, 1305 asoc->init_cycle,
1306 asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]); 1306 asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]);
@@ -1328,7 +1328,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
1328 SCTP_DEBUG_PRINTK( 1328 SCTP_DEBUG_PRINTK(
1329 "T1 COOKIE Timeout adjustment" 1329 "T1 COOKIE Timeout adjustment"
1330 " init_err_counter: %d" 1330 " init_err_counter: %d"
1331 " timeout: %d\n", 1331 " timeout: %ld\n",
1332 asoc->init_err_counter, 1332 asoc->init_err_counter,
1333 asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]); 1333 asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]);
1334 1334
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 477d7f80dba6..71c9a961c321 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3090,6 +3090,8 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep,
3090 break; 3090 break;
3091 3091
3092 ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); 3092 ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
3093 if (ch_end > skb->tail)
3094 break;
3093 3095
3094 if (SCTP_CID_SHUTDOWN_ACK == ch->type) 3096 if (SCTP_CID_SHUTDOWN_ACK == ch->type)
3095 ootb_shut_ack = 1; 3097 ootb_shut_ack = 1;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index c98ee375ba5e..fb1821d9f338 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -2995,7 +2995,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
2995 sp->hbinterval = jiffies_to_msecs(sctp_hb_interval); 2995 sp->hbinterval = jiffies_to_msecs(sctp_hb_interval);
2996 sp->pathmaxrxt = sctp_max_retrans_path; 2996 sp->pathmaxrxt = sctp_max_retrans_path;
2997 sp->pathmtu = 0; // allow default discovery 2997 sp->pathmtu = 0; // allow default discovery
2998 sp->sackdelay = sctp_sack_timeout; 2998 sp->sackdelay = jiffies_to_msecs(sctp_sack_timeout);
2999 sp->param_flags = SPP_HB_ENABLE | 2999 sp->param_flags = SPP_HB_ENABLE |
3000 SPP_PMTUD_ENABLE | 3000 SPP_PMTUD_ENABLE |
3001 SPP_SACKDELAY_ENABLE; 3001 SPP_SACKDELAY_ENABLE;
@@ -5602,8 +5602,12 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
5602 */ 5602 */
5603 newsp->type = type; 5603 newsp->type = type;
5604 5604
5605 spin_lock_bh(&oldsk->sk_lock.slock);
5606 /* Migrate the backlog from oldsk to newsk. */
5607 sctp_backlog_migrate(assoc, oldsk, newsk);
5605 /* Migrate the association to the new socket. */ 5608 /* Migrate the association to the new socket. */
5606 sctp_assoc_migrate(assoc, newsk); 5609 sctp_assoc_migrate(assoc, newsk);
5610 spin_unlock_bh(&oldsk->sk_lock.slock);
5607 5611
5608 /* If the association on the newsk is already closed before accept() 5612 /* If the association on the newsk is already closed before accept()
5609 * is called, set RCV_SHUTDOWN flag. 5613 * is called, set RCV_SHUTDOWN flag.
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index fcd7096c953d..dc6f3ff32358 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -159,12 +159,9 @@ static ctl_table sctp_table[] = {
159 .ctl_name = NET_SCTP_PRESERVE_ENABLE, 159 .ctl_name = NET_SCTP_PRESERVE_ENABLE,
160 .procname = "cookie_preserve_enable", 160 .procname = "cookie_preserve_enable",
161 .data = &sctp_cookie_preserve_enable, 161 .data = &sctp_cookie_preserve_enable,
162 .maxlen = sizeof(long), 162 .maxlen = sizeof(int),
163 .mode = 0644, 163 .mode = 0644,
164 .proc_handler = &proc_doulongvec_ms_jiffies_minmax, 164 .proc_handler = &proc_dointvec
165 .strategy = &sctp_sysctl_jiffies_ms,
166 .extra1 = &rto_timer_min,
167 .extra2 = &rto_timer_max
168 }, 165 },
169 { 166 {
170 .ctl_name = NET_SCTP_RTO_ALPHA, 167 .ctl_name = NET_SCTP_RTO_ALPHA,
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 68d73e2dd155..160f62ad1cc5 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -350,7 +350,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
350 tp->rto_pending = 0; 350 tp->rto_pending = 0;
351 351
352 SCTP_DEBUG_PRINTK("%s: transport: %p, rtt: %d, srtt: %d " 352 SCTP_DEBUG_PRINTK("%s: transport: %p, rtt: %d, srtt: %d "
353 "rttvar: %d, rto: %d\n", __FUNCTION__, 353 "rttvar: %d, rto: %ld\n", __FUNCTION__,
354 tp, rtt, tp->srtt, tp->rttvar, tp->rto); 354 tp, rtt, tp->srtt, tp->rttvar, tp->rto);
355} 355}
356 356