1
2
3
4
5
6
7
8
9
10
11
12#include <linux/dccp.h>
13#include <linux/module.h>
14#include <linux/types.h>
15#include <linux/sched.h>
16#include <linux/kernel.h>
17#include <linux/skbuff.h>
18#include <linux/netdevice.h>
19#include <linux/in.h>
20#include <linux/if_arp.h>
21#include <linux/init.h>
22#include <linux/random.h>
23#include <net/checksum.h>
24
25#include <net/inet_sock.h>
26#include <net/sock.h>
27#include <net/xfrm.h>
28
29#include <asm/ioctls.h>
30#include <linux/spinlock.h>
31#include <linux/timer.h>
32#include <linux/delay.h>
33#include <linux/poll.h>
34
35#include "ccid.h"
36#include "dccp.h"
37#include "feat.h"
38
39DEFINE_SNMP_STAT(struct dccp_mib, dccp_statistics) __read_mostly;
40
41EXPORT_SYMBOL_GPL(dccp_statistics);
42
43struct percpu_counter dccp_orphan_count;
44EXPORT_SYMBOL_GPL(dccp_orphan_count);
45
46struct inet_hashinfo dccp_hashinfo;
47EXPORT_SYMBOL_GPL(dccp_hashinfo);
48
49
50int sysctl_dccp_tx_qlen __read_mostly = 5;
51
52void dccp_set_state(struct sock *sk, const int state)
53{
54 const int oldstate = sk->sk_state;
55
56 dccp_pr_debug("%s(%p) %s --> %s\n", dccp_role(sk), sk,
57 dccp_state_name(oldstate), dccp_state_name(state));
58 WARN_ON(state == oldstate);
59
60 switch (state) {
61 case DCCP_OPEN:
62 if (oldstate != DCCP_OPEN)
63 DCCP_INC_STATS(DCCP_MIB_CURRESTAB);
64
65 if (oldstate == DCCP_PARTOPEN)
66 dccp_feat_list_purge(&dccp_sk(sk)->dccps_featneg);
67 break;
68
69 case DCCP_CLOSED:
70 if (oldstate == DCCP_OPEN || oldstate == DCCP_ACTIVE_CLOSEREQ ||
71 oldstate == DCCP_CLOSING)
72 DCCP_INC_STATS(DCCP_MIB_ESTABRESETS);
73
74 sk->sk_prot->unhash(sk);
75 if (inet_csk(sk)->icsk_bind_hash != NULL &&
76 !(sk->sk_userlocks & SOCK_BINDPORT_LOCK))
77 inet_put_port(sk);
78
79 default:
80 if (oldstate == DCCP_OPEN)
81 DCCP_DEC_STATS(DCCP_MIB_CURRESTAB);
82 }
83
84
85
86
87 sk->sk_state = state;
88}
89
90EXPORT_SYMBOL_GPL(dccp_set_state);
91
92static void dccp_finish_passive_close(struct sock *sk)
93{
94 switch (sk->sk_state) {
95 case DCCP_PASSIVE_CLOSE:
96
97 dccp_send_reset(sk, DCCP_RESET_CODE_CLOSED);
98 dccp_set_state(sk, DCCP_CLOSED);
99 break;
100 case DCCP_PASSIVE_CLOSEREQ:
101
102
103
104
105 dccp_send_close(sk, 1);
106 dccp_set_state(sk, DCCP_CLOSING);
107 }
108}
109
110void dccp_done(struct sock *sk)
111{
112 dccp_set_state(sk, DCCP_CLOSED);
113 dccp_clear_xmit_timers(sk);
114
115 sk->sk_shutdown = SHUTDOWN_MASK;
116
117 if (!sock_flag(sk, SOCK_DEAD))
118 sk->sk_state_change(sk);
119 else
120 inet_csk_destroy_sock(sk);
121}
122
123EXPORT_SYMBOL_GPL(dccp_done);
124
125const char *dccp_packet_name(const int type)
126{
127 static const char *const dccp_packet_names[] = {
128 [DCCP_PKT_REQUEST] = "REQUEST",
129 [DCCP_PKT_RESPONSE] = "RESPONSE",
130 [DCCP_PKT_DATA] = "DATA",
131 [DCCP_PKT_ACK] = "ACK",
132 [DCCP_PKT_DATAACK] = "DATAACK",
133 [DCCP_PKT_CLOSEREQ] = "CLOSEREQ",
134 [DCCP_PKT_CLOSE] = "CLOSE",
135 [DCCP_PKT_RESET] = "RESET",
136 [DCCP_PKT_SYNC] = "SYNC",
137 [DCCP_PKT_SYNCACK] = "SYNCACK",
138 };
139
140 if (type >= DCCP_NR_PKT_TYPES)
141 return "INVALID";
142 else
143 return dccp_packet_names[type];
144}
145
146EXPORT_SYMBOL_GPL(dccp_packet_name);
147
148const char *dccp_state_name(const int state)
149{
150 static const char *const dccp_state_names[] = {
151 [DCCP_OPEN] = "OPEN",
152 [DCCP_REQUESTING] = "REQUESTING",
153 [DCCP_PARTOPEN] = "PARTOPEN",
154 [DCCP_LISTEN] = "LISTEN",
155 [DCCP_RESPOND] = "RESPOND",
156 [DCCP_CLOSING] = "CLOSING",
157 [DCCP_ACTIVE_CLOSEREQ] = "CLOSEREQ",
158 [DCCP_PASSIVE_CLOSE] = "PASSIVE_CLOSE",
159 [DCCP_PASSIVE_CLOSEREQ] = "PASSIVE_CLOSEREQ",
160 [DCCP_TIME_WAIT] = "TIME_WAIT",
161 [DCCP_CLOSED] = "CLOSED",
162 };
163
164 if (state >= DCCP_MAX_STATES)
165 return "INVALID STATE!";
166 else
167 return dccp_state_names[state];
168}
169
170EXPORT_SYMBOL_GPL(dccp_state_name);
171
172int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
173{
174 struct dccp_sock *dp = dccp_sk(sk);
175 struct inet_connection_sock *icsk = inet_csk(sk);
176
177 icsk->icsk_rto = DCCP_TIMEOUT_INIT;
178 icsk->icsk_syn_retries = sysctl_dccp_request_retries;
179 sk->sk_state = DCCP_CLOSED;
180 sk->sk_write_space = dccp_write_space;
181 icsk->icsk_sync_mss = dccp_sync_mss;
182 dp->dccps_mss_cache = 536;
183 dp->dccps_rate_last = jiffies;
184 dp->dccps_role = DCCP_ROLE_UNDEFINED;
185 dp->dccps_service = DCCP_SERVICE_CODE_IS_ABSENT;
186 dp->dccps_l_ack_ratio = dp->dccps_r_ack_ratio = 1;
187
188 dccp_init_xmit_timers(sk);
189
190 INIT_LIST_HEAD(&dp->dccps_featneg);
191
192 if (likely(ctl_sock_initialized))
193 return dccp_feat_init(sk);
194 return 0;
195}
196
197EXPORT_SYMBOL_GPL(dccp_init_sock);
198
199void dccp_destroy_sock(struct sock *sk)
200{
201 struct dccp_sock *dp = dccp_sk(sk);
202
203
204
205
206
207 if (sk->sk_send_head != NULL) {
208 kfree_skb(sk->sk_send_head);
209 sk->sk_send_head = NULL;
210 }
211
212
213 if (inet_csk(sk)->icsk_bind_hash != NULL)
214 inet_put_port(sk);
215
216 kfree(dp->dccps_service_list);
217 dp->dccps_service_list = NULL;
218
219 if (dp->dccps_hc_rx_ackvec != NULL) {
220 dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
221 dp->dccps_hc_rx_ackvec = NULL;
222 }
223 ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
224 ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
225 dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
226
227
228 dccp_feat_list_purge(&dp->dccps_featneg);
229}
230
231EXPORT_SYMBOL_GPL(dccp_destroy_sock);
232
233static inline int dccp_listen_start(struct sock *sk, int backlog)
234{
235 struct dccp_sock *dp = dccp_sk(sk);
236
237 dp->dccps_role = DCCP_ROLE_LISTEN;
238
239 if (dccp_feat_finalise_settings(dp))
240 return -EPROTO;
241 return inet_csk_listen_start(sk, backlog);
242}
243
244static inline int dccp_need_reset(int state)
245{
246 return state != DCCP_CLOSED && state != DCCP_LISTEN &&
247 state != DCCP_REQUESTING;
248}
249
250int dccp_disconnect(struct sock *sk, int flags)
251{
252 struct inet_connection_sock *icsk = inet_csk(sk);
253 struct inet_sock *inet = inet_sk(sk);
254 int err = 0;
255 const int old_state = sk->sk_state;
256
257 if (old_state != DCCP_CLOSED)
258 dccp_set_state(sk, DCCP_CLOSED);
259
260
261
262
263
264 if (old_state == DCCP_LISTEN) {
265 inet_csk_listen_stop(sk);
266 } else if (dccp_need_reset(old_state)) {
267 dccp_send_reset(sk, DCCP_RESET_CODE_ABORTED);
268 sk->sk_err = ECONNRESET;
269 } else if (old_state == DCCP_REQUESTING)
270 sk->sk_err = ECONNRESET;
271
272 dccp_clear_xmit_timers(sk);
273
274 __skb_queue_purge(&sk->sk_receive_queue);
275 __skb_queue_purge(&sk->sk_write_queue);
276 if (sk->sk_send_head != NULL) {
277 __kfree_skb(sk->sk_send_head);
278 sk->sk_send_head = NULL;
279 }
280
281 inet->dport = 0;
282
283 if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK))
284 inet_reset_saddr(sk);
285
286 sk->sk_shutdown = 0;
287 sock_reset_flag(sk, SOCK_DONE);
288
289 icsk->icsk_backoff = 0;
290 inet_csk_delack_init(sk);
291 __sk_dst_reset(sk);
292
293 WARN_ON(inet->num && !icsk->icsk_bind_hash);
294
295 sk->sk_error_report(sk);
296 return err;
297}
298
299EXPORT_SYMBOL_GPL(dccp_disconnect);
300
301
302
303
304
305
306
307
308unsigned int dccp_poll(struct file *file, struct socket *sock,
309 poll_table *wait)
310{
311 unsigned int mask;
312 struct sock *sk = sock->sk;
313
314 sock_poll_wait(file, sk->sk_sleep, wait);
315 if (sk->sk_state == DCCP_LISTEN)
316 return inet_csk_listen_poll(sk);
317
318
319
320
321
322
323 mask = 0;
324 if (sk->sk_err)
325 mask = POLLERR;
326
327 if (sk->sk_shutdown == SHUTDOWN_MASK || sk->sk_state == DCCP_CLOSED)
328 mask |= POLLHUP;
329 if (sk->sk_shutdown & RCV_SHUTDOWN)
330 mask |= POLLIN | POLLRDNORM | POLLRDHUP;
331
332
333 if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_RESPOND)) {
334 if (atomic_read(&sk->sk_rmem_alloc) > 0)
335 mask |= POLLIN | POLLRDNORM;
336
337 if (!(sk->sk_shutdown & SEND_SHUTDOWN)) {
338 if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) {
339 mask |= POLLOUT | POLLWRNORM;
340 } else {
341 set_bit(SOCK_ASYNC_NOSPACE,
342 &sk->sk_socket->flags);
343 set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
344
345
346
347
348
349 if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk))
350 mask |= POLLOUT | POLLWRNORM;
351 }
352 }
353 }
354 return mask;
355}
356
357EXPORT_SYMBOL_GPL(dccp_poll);
358
359int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg)
360{
361 int rc = -ENOTCONN;
362
363 lock_sock(sk);
364
365 if (sk->sk_state == DCCP_LISTEN)
366 goto out;
367
368 switch (cmd) {
369 case SIOCINQ: {
370 struct sk_buff *skb;
371 unsigned long amount = 0;
372
373 skb = skb_peek(&sk->sk_receive_queue);
374 if (skb != NULL) {
375
376
377
378
379 amount = skb->len;
380 }
381 rc = put_user(amount, (int __user *)arg);
382 }
383 break;
384 default:
385 rc = -ENOIOCTLCMD;
386 break;
387 }
388out:
389 release_sock(sk);
390 return rc;
391}
392
393EXPORT_SYMBOL_GPL(dccp_ioctl);
394
395static int dccp_setsockopt_service(struct sock *sk, const __be32 service,
396 char __user *optval, unsigned int optlen)
397{
398 struct dccp_sock *dp = dccp_sk(sk);
399 struct dccp_service_list *sl = NULL;
400
401 if (service == DCCP_SERVICE_INVALID_VALUE ||
402 optlen > DCCP_SERVICE_LIST_MAX_LEN * sizeof(u32))
403 return -EINVAL;
404
405 if (optlen > sizeof(service)) {
406 sl = kmalloc(optlen, GFP_KERNEL);
407 if (sl == NULL)
408 return -ENOMEM;
409
410 sl->dccpsl_nr = optlen / sizeof(u32) - 1;
411 if (copy_from_user(sl->dccpsl_list,
412 optval + sizeof(service),
413 optlen - sizeof(service)) ||
414 dccp_list_has_service(sl, DCCP_SERVICE_INVALID_VALUE)) {
415 kfree(sl);
416 return -EFAULT;
417 }
418 }
419
420 lock_sock(sk);
421 dp->dccps_service = service;
422
423 kfree(dp->dccps_service_list);
424
425 dp->dccps_service_list = sl;
426 release_sock(sk);
427 return 0;
428}
429
430static int dccp_setsockopt_cscov(struct sock *sk, int cscov, bool rx)
431{
432 u8 *list, len;
433 int i, rc;
434
435 if (cscov < 0 || cscov > 15)
436 return -EINVAL;
437
438
439
440
441
442
443 if (cscov == 0)
444 return 0;
445 len = 16 - cscov;
446
447 list = kmalloc(len, GFP_KERNEL);
448 if (list == NULL)
449 return -ENOBUFS;
450
451 for (i = 0; i < len; i++)
452 list[i] = cscov++;
453
454 rc = dccp_feat_register_sp(sk, DCCPF_MIN_CSUM_COVER, rx, list, len);
455
456 if (rc == 0) {
457 if (rx)
458 dccp_sk(sk)->dccps_pcrlen = cscov;
459 else
460 dccp_sk(sk)->dccps_pcslen = cscov;
461 }
462 kfree(list);
463 return rc;
464}
465
466static int dccp_setsockopt_ccid(struct sock *sk, int type,
467 char __user *optval, unsigned int optlen)
468{
469 u8 *val;
470 int rc = 0;
471
472 if (optlen < 1 || optlen > DCCP_FEAT_MAX_SP_VALS)
473 return -EINVAL;
474
475 val = kmalloc(optlen, GFP_KERNEL);
476 if (val == NULL)
477 return -ENOMEM;
478
479 if (copy_from_user(val, optval, optlen)) {
480 kfree(val);
481 return -EFAULT;
482 }
483
484 lock_sock(sk);
485 if (type == DCCP_SOCKOPT_TX_CCID || type == DCCP_SOCKOPT_CCID)
486 rc = dccp_feat_register_sp(sk, DCCPF_CCID, 1, val, optlen);
487
488 if (!rc && (type == DCCP_SOCKOPT_RX_CCID || type == DCCP_SOCKOPT_CCID))
489 rc = dccp_feat_register_sp(sk, DCCPF_CCID, 0, val, optlen);
490 release_sock(sk);
491
492 kfree(val);
493 return rc;
494}
495
496static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
497 char __user *optval, unsigned int optlen)
498{
499 struct dccp_sock *dp = dccp_sk(sk);
500 int val, err = 0;
501
502 switch (optname) {
503 case DCCP_SOCKOPT_PACKET_SIZE:
504 DCCP_WARN("sockopt(PACKET_SIZE) is deprecated: fix your app\n");
505 return 0;
506 case DCCP_SOCKOPT_CHANGE_L:
507 case DCCP_SOCKOPT_CHANGE_R:
508 DCCP_WARN("sockopt(CHANGE_L/R) is deprecated: fix your app\n");
509 return 0;
510 case DCCP_SOCKOPT_CCID:
511 case DCCP_SOCKOPT_RX_CCID:
512 case DCCP_SOCKOPT_TX_CCID:
513 return dccp_setsockopt_ccid(sk, optname, optval, optlen);
514 }
515
516 if (optlen < (int)sizeof(int))
517 return -EINVAL;
518
519 if (get_user(val, (int __user *)optval))
520 return -EFAULT;
521
522 if (optname == DCCP_SOCKOPT_SERVICE)
523 return dccp_setsockopt_service(sk, val, optval, optlen);
524
525 lock_sock(sk);
526 switch (optname) {
527 case DCCP_SOCKOPT_SERVER_TIMEWAIT:
528 if (dp->dccps_role != DCCP_ROLE_SERVER)
529 err = -EOPNOTSUPP;
530 else
531 dp->dccps_server_timewait = (val != 0);
532 break;
533 case DCCP_SOCKOPT_SEND_CSCOV:
534 err = dccp_setsockopt_cscov(sk, val, false);
535 break;
536 case DCCP_SOCKOPT_RECV_CSCOV:
537 err = dccp_setsockopt_cscov(sk, val, true);
538 break;
539 default:
540 err = -ENOPROTOOPT;
541 break;
542 }
543 release_sock(sk);
544
545 return err;
546}
547
548int dccp_setsockopt(struct sock *sk, int level, int optname,
549 char __user *optval, unsigned int optlen)
550{
551 if (level != SOL_DCCP)
552 return inet_csk(sk)->icsk_af_ops->setsockopt(sk, level,
553 optname, optval,
554 optlen);
555 return do_dccp_setsockopt(sk, level, optname, optval, optlen);
556}
557
558EXPORT_SYMBOL_GPL(dccp_setsockopt);
559
560#ifdef CONFIG_COMPAT
561int compat_dccp_setsockopt(struct sock *sk, int level, int optname,
562 char __user *optval, unsigned int optlen)
563{
564 if (level != SOL_DCCP)
565 return inet_csk_compat_setsockopt(sk, level, optname,
566 optval, optlen);
567 return do_dccp_setsockopt(sk, level, optname, optval, optlen);
568}
569
570EXPORT_SYMBOL_GPL(compat_dccp_setsockopt);
571#endif
572
573static int dccp_getsockopt_service(struct sock *sk, int len,
574 __be32 __user *optval,
575 int __user *optlen)
576{
577 const struct dccp_sock *dp = dccp_sk(sk);
578 const struct dccp_service_list *sl;
579 int err = -ENOENT, slen = 0, total_len = sizeof(u32);
580
581 lock_sock(sk);
582 if ((sl = dp->dccps_service_list) != NULL) {
583 slen = sl->dccpsl_nr * sizeof(u32);
584 total_len += slen;
585 }
586
587 err = -EINVAL;
588 if (total_len > len)
589 goto out;
590
591 err = 0;
592 if (put_user(total_len, optlen) ||
593 put_user(dp->dccps_service, optval) ||
594 (sl != NULL && copy_to_user(optval + 1, sl->dccpsl_list, slen)))
595 err = -EFAULT;
596out:
597 release_sock(sk);
598 return err;
599}
600
601static int do_dccp_getsockopt(struct sock *sk, int level, int optname,
602 char __user *optval, int __user *optlen)
603{
604 struct dccp_sock *dp;
605 int val, len;
606
607 if (get_user(len, optlen))
608 return -EFAULT;
609
610 if (len < (int)sizeof(int))
611 return -EINVAL;
612
613 dp = dccp_sk(sk);
614
615 switch (optname) {
616 case DCCP_SOCKOPT_PACKET_SIZE:
617 DCCP_WARN("sockopt(PACKET_SIZE) is deprecated: fix your app\n");
618 return 0;
619 case DCCP_SOCKOPT_SERVICE:
620 return dccp_getsockopt_service(sk, len,
621 (__be32 __user *)optval, optlen);
622 case DCCP_SOCKOPT_GET_CUR_MPS:
623 val = dp->dccps_mss_cache;
624 break;
625 case DCCP_SOCKOPT_AVAILABLE_CCIDS:
626 return ccid_getsockopt_builtin_ccids(sk, len, optval, optlen);
627 case DCCP_SOCKOPT_TX_CCID:
628 val = ccid_get_current_tx_ccid(dp);
629 if (val < 0)
630 return -ENOPROTOOPT;
631 break;
632 case DCCP_SOCKOPT_RX_CCID:
633 val = ccid_get_current_rx_ccid(dp);
634 if (val < 0)
635 return -ENOPROTOOPT;
636 break;
637 case DCCP_SOCKOPT_SERVER_TIMEWAIT:
638 val = dp->dccps_server_timewait;
639 break;
640 case DCCP_SOCKOPT_SEND_CSCOV:
641 val = dp->dccps_pcslen;
642 break;
643 case DCCP_SOCKOPT_RECV_CSCOV:
644 val = dp->dccps_pcrlen;
645 break;
646 case 128 ... 191:
647 return ccid_hc_rx_getsockopt(dp->dccps_hc_rx_ccid, sk, optname,
648 len, (u32 __user *)optval, optlen);
649 case 192 ... 255:
650 return ccid_hc_tx_getsockopt(dp->dccps_hc_tx_ccid, sk, optname,
651 len, (u32 __user *)optval, optlen);
652 default:
653 return -ENOPROTOOPT;
654 }
655
656 len = sizeof(val);
657 if (put_user(len, optlen) || copy_to_user(optval, &val, len))
658 return -EFAULT;
659
660 return 0;
661}
662
663int dccp_getsockopt(struct sock *sk, int level, int optname,
664 char __user *optval, int __user *optlen)
665{
666 if (level != SOL_DCCP)
667 return inet_csk(sk)->icsk_af_ops->getsockopt(sk, level,
668 optname, optval,
669 optlen);
670 return do_dccp_getsockopt(sk, level, optname, optval, optlen);
671}
672
673EXPORT_SYMBOL_GPL(dccp_getsockopt);
674
675#ifdef CONFIG_COMPAT
676int compat_dccp_getsockopt(struct sock *sk, int level, int optname,
677 char __user *optval, int __user *optlen)
678{
679 if (level != SOL_DCCP)
680 return inet_csk_compat_getsockopt(sk, level, optname,
681 optval, optlen);
682 return do_dccp_getsockopt(sk, level, optname, optval, optlen);
683}
684
685EXPORT_SYMBOL_GPL(compat_dccp_getsockopt);
686#endif
687
688int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
689 size_t len)
690{
691 const struct dccp_sock *dp = dccp_sk(sk);
692 const int flags = msg->msg_flags;
693 const int noblock = flags & MSG_DONTWAIT;
694 struct sk_buff *skb;
695 int rc, size;
696 long timeo;
697
698 if (len > dp->dccps_mss_cache)
699 return -EMSGSIZE;
700
701 lock_sock(sk);
702
703 if (sysctl_dccp_tx_qlen &&
704 (sk->sk_write_queue.qlen >= sysctl_dccp_tx_qlen)) {
705 rc = -EAGAIN;
706 goto out_release;
707 }
708
709 timeo = sock_sndtimeo(sk, noblock);
710
711
712
713
714
715
716 if ((1 << sk->sk_state) & ~(DCCPF_OPEN | DCCPF_PARTOPEN))
717 if ((rc = sk_stream_wait_connect(sk, &timeo)) != 0)
718 goto out_release;
719
720 size = sk->sk_prot->max_header + len;
721 release_sock(sk);
722 skb = sock_alloc_send_skb(sk, size, noblock, &rc);
723 lock_sock(sk);
724 if (skb == NULL)
725 goto out_release;
726
727 skb_reserve(skb, sk->sk_prot->max_header);
728 rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
729 if (rc != 0)
730 goto out_discard;
731
732 skb_queue_tail(&sk->sk_write_queue, skb);
733 dccp_write_xmit(sk,0);
734out_release:
735 release_sock(sk);
736 return rc ? : len;
737out_discard:
738 kfree_skb(skb);
739 goto out_release;
740}
741
742EXPORT_SYMBOL_GPL(dccp_sendmsg);
743
744int dccp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
745 size_t len, int nonblock, int flags, int *addr_len)
746{
747 const struct dccp_hdr *dh;
748 long timeo;
749
750 lock_sock(sk);
751
752 if (sk->sk_state == DCCP_LISTEN) {
753 len = -ENOTCONN;
754 goto out;
755 }
756
757 timeo = sock_rcvtimeo(sk, nonblock);
758
759 do {
760 struct sk_buff *skb = skb_peek(&sk->sk_receive_queue);
761
762 if (skb == NULL)
763 goto verify_sock_status;
764
765 dh = dccp_hdr(skb);
766
767 switch (dh->dccph_type) {
768 case DCCP_PKT_DATA:
769 case DCCP_PKT_DATAACK:
770 goto found_ok_skb;
771
772 case DCCP_PKT_CLOSE:
773 case DCCP_PKT_CLOSEREQ:
774 if (!(flags & MSG_PEEK))
775 dccp_finish_passive_close(sk);
776
777 case DCCP_PKT_RESET:
778 dccp_pr_debug("found fin (%s) ok!\n",
779 dccp_packet_name(dh->dccph_type));
780 len = 0;
781 goto found_fin_ok;
782 default:
783 dccp_pr_debug("packet_type=%s\n",
784 dccp_packet_name(dh->dccph_type));
785 sk_eat_skb(sk, skb, 0);
786 }
787verify_sock_status:
788 if (sock_flag(sk, SOCK_DONE)) {
789 len = 0;
790 break;
791 }
792
793 if (sk->sk_err) {
794 len = sock_error(sk);
795 break;
796 }
797
798 if (sk->sk_shutdown & RCV_SHUTDOWN) {
799 len = 0;
800 break;
801 }
802
803 if (sk->sk_state == DCCP_CLOSED) {
804 if (!sock_flag(sk, SOCK_DONE)) {
805
806
807
808 len = -ENOTCONN;
809 break;
810 }
811 len = 0;
812 break;
813 }
814
815 if (!timeo) {
816 len = -EAGAIN;
817 break;
818 }
819
820 if (signal_pending(current)) {
821 len = sock_intr_errno(timeo);
822 break;
823 }
824
825 sk_wait_data(sk, &timeo);
826 continue;
827 found_ok_skb:
828 if (len > skb->len)
829 len = skb->len;
830 else if (len < skb->len)
831 msg->msg_flags |= MSG_TRUNC;
832
833 if (skb_copy_datagram_iovec(skb, 0, msg->msg_iov, len)) {
834
835 len = -EFAULT;
836 break;
837 }
838 found_fin_ok:
839 if (!(flags & MSG_PEEK))
840 sk_eat_skb(sk, skb, 0);
841 break;
842 } while (1);
843out:
844 release_sock(sk);
845 return len;
846}
847
848EXPORT_SYMBOL_GPL(dccp_recvmsg);
849
850int inet_dccp_listen(struct socket *sock, int backlog)
851{
852 struct sock *sk = sock->sk;
853 unsigned char old_state;
854 int err;
855
856 lock_sock(sk);
857
858 err = -EINVAL;
859 if (sock->state != SS_UNCONNECTED || sock->type != SOCK_DCCP)
860 goto out;
861
862 old_state = sk->sk_state;
863 if (!((1 << old_state) & (DCCPF_CLOSED | DCCPF_LISTEN)))
864 goto out;
865
866
867
868
869 if (old_state != DCCP_LISTEN) {
870
871
872
873
874 err = dccp_listen_start(sk, backlog);
875 if (err)
876 goto out;
877 }
878 sk->sk_max_ack_backlog = backlog;
879 err = 0;
880
881out:
882 release_sock(sk);
883 return err;
884}
885
886EXPORT_SYMBOL_GPL(inet_dccp_listen);
887
888static void dccp_terminate_connection(struct sock *sk)
889{
890 u8 next_state = DCCP_CLOSED;
891
892 switch (sk->sk_state) {
893 case DCCP_PASSIVE_CLOSE:
894 case DCCP_PASSIVE_CLOSEREQ:
895 dccp_finish_passive_close(sk);
896 break;
897 case DCCP_PARTOPEN:
898 dccp_pr_debug("Stop PARTOPEN timer (%p)\n", sk);
899 inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);
900
901 case DCCP_OPEN:
902 dccp_send_close(sk, 1);
903
904 if (dccp_sk(sk)->dccps_role == DCCP_ROLE_SERVER &&
905 !dccp_sk(sk)->dccps_server_timewait)
906 next_state = DCCP_ACTIVE_CLOSEREQ;
907 else
908 next_state = DCCP_CLOSING;
909
910 default:
911 dccp_set_state(sk, next_state);
912 }
913}
914
915void dccp_close(struct sock *sk, long timeout)
916{
917 struct dccp_sock *dp = dccp_sk(sk);
918 struct sk_buff *skb;
919 u32 data_was_unread = 0;
920 int state;
921
922 lock_sock(sk);
923
924 sk->sk_shutdown = SHUTDOWN_MASK;
925
926 if (sk->sk_state == DCCP_LISTEN) {
927 dccp_set_state(sk, DCCP_CLOSED);
928
929
930 inet_csk_listen_stop(sk);
931
932 goto adjudge_to_death;
933 }
934
935 sk_stop_timer(sk, &dp->dccps_xmit_timer);
936
937
938
939
940
941
942 while ((skb = __skb_dequeue(&sk->sk_receive_queue)) != NULL) {
943 data_was_unread += skb->len;
944 __kfree_skb(skb);
945 }
946
947 if (data_was_unread) {
948
949 DCCP_WARN("DCCP: ABORT -- %u bytes unread\n", data_was_unread);
950 dccp_send_reset(sk, DCCP_RESET_CODE_ABORTED);
951 dccp_set_state(sk, DCCP_CLOSED);
952 } else if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) {
953
954 sk->sk_prot->disconnect(sk, 0);
955 } else if (sk->sk_state != DCCP_CLOSED) {
956 dccp_terminate_connection(sk);
957 }
958
959 sk_stream_wait_close(sk, timeout);
960
961adjudge_to_death:
962 state = sk->sk_state;
963 sock_hold(sk);
964 sock_orphan(sk);
965
966
967
968
969 release_sock(sk);
970
971
972
973
974 local_bh_disable();
975 bh_lock_sock(sk);
976 WARN_ON(sock_owned_by_user(sk));
977
978 percpu_counter_inc(sk->sk_prot->orphan_count);
979
980
981 if (state != DCCP_CLOSED && sk->sk_state == DCCP_CLOSED)
982 goto out;
983
984 if (sk->sk_state == DCCP_CLOSED)
985 inet_csk_destroy_sock(sk);
986
987
988
989out:
990 bh_unlock_sock(sk);
991 local_bh_enable();
992 sock_put(sk);
993}
994
995EXPORT_SYMBOL_GPL(dccp_close);
996
997void dccp_shutdown(struct sock *sk, int how)
998{
999 dccp_pr_debug("called shutdown(%x)\n", how);
1000}
1001
1002EXPORT_SYMBOL_GPL(dccp_shutdown);
1003
1004static inline int dccp_mib_init(void)
1005{
1006 return snmp_mib_init((void**)dccp_statistics, sizeof(struct dccp_mib));
1007}
1008
1009static inline void dccp_mib_exit(void)
1010{
1011 snmp_mib_free((void**)dccp_statistics);
1012}
1013
1014static int thash_entries;
1015module_param(thash_entries, int, 0444);
1016MODULE_PARM_DESC(thash_entries, "Number of ehash buckets");
1017
1018#ifdef CONFIG_IP_DCCP_DEBUG
1019int dccp_debug;
1020module_param(dccp_debug, bool, 0644);
1021MODULE_PARM_DESC(dccp_debug, "Enable debug messages");
1022
1023EXPORT_SYMBOL_GPL(dccp_debug);
1024#endif
1025
1026static int __init dccp_init(void)
1027{
1028 unsigned long goal;
1029 int ehash_order, bhash_order, i;
1030 int rc;
1031
1032 BUILD_BUG_ON(sizeof(struct dccp_skb_cb) >
1033 FIELD_SIZEOF(struct sk_buff, cb));
1034 rc = percpu_counter_init(&dccp_orphan_count, 0);
1035 if (rc)
1036 goto out;
1037 rc = -ENOBUFS;
1038 inet_hashinfo_init(&dccp_hashinfo);
1039 dccp_hashinfo.bind_bucket_cachep =
1040 kmem_cache_create("dccp_bind_bucket",
1041 sizeof(struct inet_bind_bucket), 0,
1042 SLAB_HWCACHE_ALIGN, NULL);
1043 if (!dccp_hashinfo.bind_bucket_cachep)
1044 goto out_free_percpu;
1045
1046
1047
1048
1049
1050
1051
1052 if (totalram_pages >= (128 * 1024))
1053 goal = totalram_pages >> (21 - PAGE_SHIFT);
1054 else
1055 goal = totalram_pages >> (23 - PAGE_SHIFT);
1056
1057 if (thash_entries)
1058 goal = (thash_entries *
1059 sizeof(struct inet_ehash_bucket)) >> PAGE_SHIFT;
1060 for (ehash_order = 0; (1UL << ehash_order) < goal; ehash_order++)
1061 ;
1062 do {
1063 dccp_hashinfo.ehash_size = (1UL << ehash_order) * PAGE_SIZE /
1064 sizeof(struct inet_ehash_bucket);
1065 while (dccp_hashinfo.ehash_size &
1066 (dccp_hashinfo.ehash_size - 1))
1067 dccp_hashinfo.ehash_size--;
1068 dccp_hashinfo.ehash = (struct inet_ehash_bucket *)
1069 __get_free_pages(GFP_ATOMIC|__GFP_NOWARN, ehash_order);
1070 } while (!dccp_hashinfo.ehash && --ehash_order > 0);
1071
1072 if (!dccp_hashinfo.ehash) {
1073 DCCP_CRIT("Failed to allocate DCCP established hash table");
1074 goto out_free_bind_bucket_cachep;
1075 }
1076
1077 for (i = 0; i < dccp_hashinfo.ehash_size; i++) {
1078 INIT_HLIST_NULLS_HEAD(&dccp_hashinfo.ehash[i].chain, i);
1079 INIT_HLIST_NULLS_HEAD(&dccp_hashinfo.ehash[i].twchain, i);
1080 }
1081
1082 if (inet_ehash_locks_alloc(&dccp_hashinfo))
1083 goto out_free_dccp_ehash;
1084
1085 bhash_order = ehash_order;
1086
1087 do {
1088 dccp_hashinfo.bhash_size = (1UL << bhash_order) * PAGE_SIZE /
1089 sizeof(struct inet_bind_hashbucket);
1090 if ((dccp_hashinfo.bhash_size > (64 * 1024)) &&
1091 bhash_order > 0)
1092 continue;
1093 dccp_hashinfo.bhash = (struct inet_bind_hashbucket *)
1094 __get_free_pages(GFP_ATOMIC|__GFP_NOWARN, bhash_order);
1095 } while (!dccp_hashinfo.bhash && --bhash_order >= 0);
1096
1097 if (!dccp_hashinfo.bhash) {
1098 DCCP_CRIT("Failed to allocate DCCP bind hash table");
1099 goto out_free_dccp_locks;
1100 }
1101
1102 for (i = 0; i < dccp_hashinfo.bhash_size; i++) {
1103 spin_lock_init(&dccp_hashinfo.bhash[i].lock);
1104 INIT_HLIST_HEAD(&dccp_hashinfo.bhash[i].chain);
1105 }
1106
1107 rc = dccp_mib_init();
1108 if (rc)
1109 goto out_free_dccp_bhash;
1110
1111 rc = dccp_ackvec_init();
1112 if (rc)
1113 goto out_free_dccp_mib;
1114
1115 rc = dccp_sysctl_init();
1116 if (rc)
1117 goto out_ackvec_exit;
1118
1119 rc = ccid_initialize_builtins();
1120 if (rc)
1121 goto out_sysctl_exit;
1122
1123 dccp_timestamping_init();
1124out:
1125 return rc;
1126out_sysctl_exit:
1127 dccp_sysctl_exit();
1128out_ackvec_exit:
1129 dccp_ackvec_exit();
1130out_free_dccp_mib:
1131 dccp_mib_exit();
1132out_free_dccp_bhash:
1133 free_pages((unsigned long)dccp_hashinfo.bhash, bhash_order);
1134 dccp_hashinfo.bhash = NULL;
1135out_free_dccp_locks:
1136 inet_ehash_locks_free(&dccp_hashinfo);
1137out_free_dccp_ehash:
1138 free_pages((unsigned long)dccp_hashinfo.ehash, ehash_order);
1139 dccp_hashinfo.ehash = NULL;
1140out_free_bind_bucket_cachep:
1141 kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep);
1142 dccp_hashinfo.bind_bucket_cachep = NULL;
1143out_free_percpu:
1144 percpu_counter_destroy(&dccp_orphan_count);
1145 goto out;
1146}
1147
1148static void __exit dccp_fini(void)
1149{
1150 ccid_cleanup_builtins();
1151 dccp_mib_exit();
1152 free_pages((unsigned long)dccp_hashinfo.bhash,
1153 get_order(dccp_hashinfo.bhash_size *
1154 sizeof(struct inet_bind_hashbucket)));
1155 free_pages((unsigned long)dccp_hashinfo.ehash,
1156 get_order(dccp_hashinfo.ehash_size *
1157 sizeof(struct inet_ehash_bucket)));
1158 inet_ehash_locks_free(&dccp_hashinfo);
1159 kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep);
1160 dccp_ackvec_exit();
1161 dccp_sysctl_exit();
1162 percpu_counter_destroy(&dccp_orphan_count);
1163}
1164
1165module_init(dccp_init);
1166module_exit(dccp_fini);
1167
1168MODULE_LICENSE("GPL");
1169MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@conectiva.com.br>");
1170MODULE_DESCRIPTION("DCCP - Datagram Congestion Controlled Protocol");
1171