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.c333
1 files changed, 159 insertions, 174 deletions
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index dc0487b5bace..29047995c695 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -18,8 +18,10 @@
18#include <linux/random.h> 18#include <linux/random.h>
19 19
20#include <net/icmp.h> 20#include <net/icmp.h>
21#include <net/inet_common.h>
21#include <net/inet_hashtables.h> 22#include <net/inet_hashtables.h>
22#include <net/inet_sock.h> 23#include <net/inet_sock.h>
24#include <net/protocol.h>
23#include <net/sock.h> 25#include <net/sock.h>
24#include <net/timewait_sock.h> 26#include <net/timewait_sock.h>
25#include <net/tcp_states.h> 27#include <net/tcp_states.h>
@@ -28,14 +30,14 @@
28#include "ackvec.h" 30#include "ackvec.h"
29#include "ccid.h" 31#include "ccid.h"
30#include "dccp.h" 32#include "dccp.h"
33#include "feat.h"
31 34
32struct inet_hashinfo __cacheline_aligned dccp_hashinfo = { 35/*
33 .lhash_lock = RW_LOCK_UNLOCKED, 36 * This is the global socket data structure used for responding to
34 .lhash_users = ATOMIC_INIT(0), 37 * the Out-of-the-blue (OOTB) packets. A control sock will be created
35 .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(dccp_hashinfo.lhash_wait), 38 * for this socket at the initialization time.
36}; 39 */
37 40static struct socket *dccp_v4_ctl_socket;
38EXPORT_SYMBOL_GPL(dccp_hashinfo);
39 41
40static int dccp_v4_get_port(struct sock *sk, const unsigned short snum) 42static int dccp_v4_get_port(struct sock *sk, const unsigned short snum)
41{ 43{
@@ -43,18 +45,6 @@ static int dccp_v4_get_port(struct sock *sk, const unsigned short snum)
43 inet_csk_bind_conflict); 45 inet_csk_bind_conflict);
44} 46}
45 47
46static void dccp_v4_hash(struct sock *sk)
47{
48 inet_hash(&dccp_hashinfo, sk);
49}
50
51void dccp_unhash(struct sock *sk)
52{
53 inet_unhash(&dccp_hashinfo, sk);
54}
55
56EXPORT_SYMBOL_GPL(dccp_unhash);
57
58int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) 48int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
59{ 49{
60 struct inet_sock *inet = inet_sk(sk); 50 struct inet_sock *inet = inet_sk(sk);
@@ -207,11 +197,12 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk,
207 } /* else let the usual retransmit timer handle it */ 197 } /* else let the usual retransmit timer handle it */
208} 198}
209 199
210static void dccp_v4_ctl_send_ack(struct sk_buff *rxskb) 200static void dccp_v4_reqsk_send_ack(struct sk_buff *rxskb,
201 struct request_sock *req)
211{ 202{
212 int err; 203 int err;
213 struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh; 204 struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh;
214 const int dccp_hdr_ack_len = sizeof(struct dccp_hdr) + 205 const u32 dccp_hdr_ack_len = sizeof(struct dccp_hdr) +
215 sizeof(struct dccp_hdr_ext) + 206 sizeof(struct dccp_hdr_ext) +
216 sizeof(struct dccp_hdr_ack_bits); 207 sizeof(struct dccp_hdr_ack_bits);
217 struct sk_buff *skb; 208 struct sk_buff *skb;
@@ -219,12 +210,12 @@ static void dccp_v4_ctl_send_ack(struct sk_buff *rxskb)
219 if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL) 210 if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL)
220 return; 211 return;
221 212
222 skb = alloc_skb(MAX_DCCP_HEADER + 15, GFP_ATOMIC); 213 skb = alloc_skb(dccp_v4_ctl_socket->sk->sk_prot->max_header, GFP_ATOMIC);
223 if (skb == NULL) 214 if (skb == NULL)
224 return; 215 return;
225 216
226 /* Reserve space for headers. */ 217 /* Reserve space for headers. */
227 skb_reserve(skb, MAX_DCCP_HEADER); 218 skb_reserve(skb, dccp_v4_ctl_socket->sk->sk_prot->max_header);
228 219
229 skb->dst = dst_clone(rxskb->dst); 220 skb->dst = dst_clone(rxskb->dst);
230 221
@@ -243,11 +234,11 @@ static void dccp_v4_ctl_send_ack(struct sk_buff *rxskb)
243 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), 234 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
244 DCCP_SKB_CB(rxskb)->dccpd_seq); 235 DCCP_SKB_CB(rxskb)->dccpd_seq);
245 236
246 bh_lock_sock(dccp_ctl_socket->sk); 237 bh_lock_sock(dccp_v4_ctl_socket->sk);
247 err = ip_build_and_send_pkt(skb, dccp_ctl_socket->sk, 238 err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
248 rxskb->nh.iph->daddr, 239 rxskb->nh.iph->daddr,
249 rxskb->nh.iph->saddr, NULL); 240 rxskb->nh.iph->saddr, NULL);
250 bh_unlock_sock(dccp_ctl_socket->sk); 241 bh_unlock_sock(dccp_v4_ctl_socket->sk);
251 242
252 if (err == NET_XMIT_CN || err == 0) { 243 if (err == NET_XMIT_CN || err == 0) {
253 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); 244 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
@@ -255,12 +246,6 @@ static void dccp_v4_ctl_send_ack(struct sk_buff *rxskb)
255 } 246 }
256} 247}
257 248
258static void dccp_v4_reqsk_send_ack(struct sk_buff *skb,
259 struct request_sock *req)
260{
261 dccp_v4_ctl_send_ack(skb);
262}
263
264static int dccp_v4_send_response(struct sock *sk, struct request_sock *req, 249static int dccp_v4_send_response(struct sock *sk, struct request_sock *req,
265 struct dst_entry *dst) 250 struct dst_entry *dst)
266{ 251{
@@ -275,7 +260,10 @@ static int dccp_v4_send_response(struct sock *sk, struct request_sock *req,
275 skb = dccp_make_response(sk, dst, req); 260 skb = dccp_make_response(sk, dst, req);
276 if (skb != NULL) { 261 if (skb != NULL) {
277 const struct inet_request_sock *ireq = inet_rsk(req); 262 const struct inet_request_sock *ireq = inet_rsk(req);
263 struct dccp_hdr *dh = dccp_hdr(skb);
278 264
265 dh->dccph_checksum = dccp_v4_checksum(skb, ireq->loc_addr,
266 ireq->rmt_addr);
279 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); 267 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
280 err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, 268 err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr,
281 ireq->rmt_addr, 269 ireq->rmt_addr,
@@ -301,7 +289,7 @@ out:
301 * check at all. A more general error queue to queue errors for later handling 289 * check at all. A more general error queue to queue errors for later handling
302 * is probably better. 290 * is probably better.
303 */ 291 */
304void dccp_v4_err(struct sk_buff *skb, u32 info) 292static void dccp_v4_err(struct sk_buff *skb, u32 info)
305{ 293{
306 const struct iphdr *iph = (struct iphdr *)skb->data; 294 const struct iphdr *iph = (struct iphdr *)skb->data;
307 const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + 295 const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data +
@@ -456,32 +444,6 @@ void dccp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb)
456 444
457EXPORT_SYMBOL_GPL(dccp_v4_send_check); 445EXPORT_SYMBOL_GPL(dccp_v4_send_check);
458 446
459int dccp_v4_send_reset(struct sock *sk, enum dccp_reset_codes code)
460{
461 struct sk_buff *skb;
462 /*
463 * FIXME: what if rebuild_header fails?
464 * Should we be doing a rebuild_header here?
465 */
466 int err = inet_sk_rebuild_header(sk);
467
468 if (err != 0)
469 return err;
470
471 skb = dccp_make_reset(sk, sk->sk_dst_cache, code);
472 if (skb != NULL) {
473 const struct inet_sock *inet = inet_sk(sk);
474
475 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
476 err = ip_build_and_send_pkt(skb, sk,
477 inet->saddr, inet->daddr, NULL);
478 if (err == NET_XMIT_CN)
479 err = 0;
480 }
481
482 return err;
483}
484
485static inline u64 dccp_v4_init_sequence(const struct sock *sk, 447static inline u64 dccp_v4_init_sequence(const struct sock *sk,
486 const struct sk_buff *skb) 448 const struct sk_buff *skb)
487{ 449{
@@ -497,9 +459,9 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
497 struct dccp_sock dp; 459 struct dccp_sock dp;
498 struct request_sock *req; 460 struct request_sock *req;
499 struct dccp_request_sock *dreq; 461 struct dccp_request_sock *dreq;
500 const __u32 saddr = skb->nh.iph->saddr; 462 const __be32 saddr = skb->nh.iph->saddr;
501 const __u32 daddr = skb->nh.iph->daddr; 463 const __be32 daddr = skb->nh.iph->daddr;
502 const __u32 service = dccp_hdr_request(skb)->dccph_req_service; 464 const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
503 struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); 465 struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
504 __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY; 466 __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
505 467
@@ -535,7 +497,8 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
535 if (req == NULL) 497 if (req == NULL)
536 goto drop; 498 goto drop;
537 499
538 /* FIXME: process options */ 500 if (dccp_parse_options(sk, skb))
501 goto drop;
539 502
540 dccp_openreq_init(req, &dp, skb); 503 dccp_openreq_init(req, &dp, skb);
541 504
@@ -660,8 +623,8 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
660 return sk; 623 return sk;
661} 624}
662 625
663int dccp_v4_checksum(const struct sk_buff *skb, const u32 saddr, 626int dccp_v4_checksum(const struct sk_buff *skb, const __be32 saddr,
664 const u32 daddr) 627 const __be32 daddr)
665{ 628{
666 const struct dccp_hdr* dh = dccp_hdr(skb); 629 const struct dccp_hdr* dh = dccp_hdr(skb);
667 int checksum_len; 630 int checksum_len;
@@ -680,8 +643,10 @@ int dccp_v4_checksum(const struct sk_buff *skb, const u32 saddr,
680 IPPROTO_DCCP, tmp); 643 IPPROTO_DCCP, tmp);
681} 644}
682 645
646EXPORT_SYMBOL_GPL(dccp_v4_checksum);
647
683static int dccp_v4_verify_checksum(struct sk_buff *skb, 648static int dccp_v4_verify_checksum(struct sk_buff *skb,
684 const u32 saddr, const u32 daddr) 649 const __be32 saddr, const __be32 daddr)
685{ 650{
686 struct dccp_hdr *dh = dccp_hdr(skb); 651 struct dccp_hdr *dh = dccp_hdr(skb);
687 int checksum_len; 652 int checksum_len;
@@ -741,16 +706,17 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb)
741 if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL) 706 if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL)
742 return; 707 return;
743 708
744 dst = dccp_v4_route_skb(dccp_ctl_socket->sk, rxskb); 709 dst = dccp_v4_route_skb(dccp_v4_ctl_socket->sk, rxskb);
745 if (dst == NULL) 710 if (dst == NULL)
746 return; 711 return;
747 712
748 skb = alloc_skb(MAX_DCCP_HEADER + 15, GFP_ATOMIC); 713 skb = alloc_skb(dccp_v4_ctl_socket->sk->sk_prot->max_header,
714 GFP_ATOMIC);
749 if (skb == NULL) 715 if (skb == NULL)
750 goto out; 716 goto out;
751 717
752 /* Reserve space for headers. */ 718 /* Reserve space for headers. */
753 skb_reserve(skb, MAX_DCCP_HEADER); 719 skb_reserve(skb, dccp_v4_ctl_socket->sk->sk_prot->max_header);
754 skb->dst = dst_clone(dst); 720 skb->dst = dst_clone(dst);
755 721
756 skb->h.raw = skb_push(skb, dccp_hdr_reset_len); 722 skb->h.raw = skb_push(skb, dccp_hdr_reset_len);
@@ -778,11 +744,11 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb)
778 dh->dccph_checksum = dccp_v4_checksum(skb, rxskb->nh.iph->saddr, 744 dh->dccph_checksum = dccp_v4_checksum(skb, rxskb->nh.iph->saddr,
779 rxskb->nh.iph->daddr); 745 rxskb->nh.iph->daddr);
780 746
781 bh_lock_sock(dccp_ctl_socket->sk); 747 bh_lock_sock(dccp_v4_ctl_socket->sk);
782 err = ip_build_and_send_pkt(skb, dccp_ctl_socket->sk, 748 err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
783 rxskb->nh.iph->daddr, 749 rxskb->nh.iph->daddr,
784 rxskb->nh.iph->saddr, NULL); 750 rxskb->nh.iph->saddr, NULL);
785 bh_unlock_sock(dccp_ctl_socket->sk); 751 bh_unlock_sock(dccp_v4_ctl_socket->sk);
786 752
787 if (err == NET_XMIT_CN || err == 0) { 753 if (err == NET_XMIT_CN || err == 0) {
788 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); 754 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
@@ -912,7 +878,7 @@ int dccp_invalid_packet(struct sk_buff *skb)
912EXPORT_SYMBOL_GPL(dccp_invalid_packet); 878EXPORT_SYMBOL_GPL(dccp_invalid_packet);
913 879
914/* this is called when real data arrives */ 880/* this is called when real data arrives */
915int dccp_v4_rcv(struct sk_buff *skb) 881static int dccp_v4_rcv(struct sk_buff *skb)
916{ 882{
917 const struct dccp_hdr *dh; 883 const struct dccp_hdr *dh;
918 struct sock *sk; 884 struct sock *sk;
@@ -1019,111 +985,37 @@ do_time_wait:
1019 goto no_dccp_socket; 985 goto no_dccp_socket;
1020} 986}
1021 987
1022struct inet_connection_sock_af_ops dccp_ipv4_af_ops = { 988static struct inet_connection_sock_af_ops dccp_ipv4_af_ops = {
1023 .queue_xmit = ip_queue_xmit, 989 .queue_xmit = ip_queue_xmit,
1024 .send_check = dccp_v4_send_check, 990 .send_check = dccp_v4_send_check,
1025 .rebuild_header = inet_sk_rebuild_header, 991 .rebuild_header = inet_sk_rebuild_header,
1026 .conn_request = dccp_v4_conn_request, 992 .conn_request = dccp_v4_conn_request,
1027 .syn_recv_sock = dccp_v4_request_recv_sock, 993 .syn_recv_sock = dccp_v4_request_recv_sock,
1028 .net_header_len = sizeof(struct iphdr), 994 .net_header_len = sizeof(struct iphdr),
1029 .setsockopt = ip_setsockopt, 995 .setsockopt = ip_setsockopt,
1030 .getsockopt = ip_getsockopt, 996 .getsockopt = ip_getsockopt,
1031 .addr2sockaddr = inet_csk_addr2sockaddr, 997 .addr2sockaddr = inet_csk_addr2sockaddr,
1032 .sockaddr_len = sizeof(struct sockaddr_in), 998 .sockaddr_len = sizeof(struct sockaddr_in),
999#ifdef CONFIG_COMPAT
1000 .compat_setsockopt = compat_ip_setsockopt,
1001 .compat_getsockopt = compat_ip_getsockopt,
1002#endif
1033}; 1003};
1034 1004
1035int dccp_v4_init_sock(struct sock *sk) 1005static int dccp_v4_init_sock(struct sock *sk)
1036{
1037 struct dccp_sock *dp = dccp_sk(sk);
1038 struct inet_connection_sock *icsk = inet_csk(sk);
1039 static int dccp_ctl_socket_init = 1;
1040
1041 dccp_options_init(&dp->dccps_options);
1042 do_gettimeofday(&dp->dccps_epoch);
1043
1044 if (dp->dccps_options.dccpo_send_ack_vector) {
1045 dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(DCCP_MAX_ACKVEC_LEN,
1046 GFP_KERNEL);
1047 if (dp->dccps_hc_rx_ackvec == NULL)
1048 return -ENOMEM;
1049 }
1050
1051 /*
1052 * FIXME: We're hardcoding the CCID, and doing this at this point makes
1053 * the listening (master) sock get CCID control blocks, which is not
1054 * necessary, but for now, to not mess with the test userspace apps,
1055 * lets leave it here, later the real solution is to do this in a
1056 * setsockopt(CCIDs-I-want/accept). -acme
1057 */
1058 if (likely(!dccp_ctl_socket_init)) {
1059 dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_rx_ccid,
1060 sk);
1061 dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_tx_ccid,
1062 sk);
1063 if (dp->dccps_hc_rx_ccid == NULL ||
1064 dp->dccps_hc_tx_ccid == NULL) {
1065 ccid_exit(dp->dccps_hc_rx_ccid, sk);
1066 ccid_exit(dp->dccps_hc_tx_ccid, sk);
1067 if (dp->dccps_options.dccpo_send_ack_vector) {
1068 dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
1069 dp->dccps_hc_rx_ackvec = NULL;
1070 }
1071 dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
1072 return -ENOMEM;
1073 }
1074 } else
1075 dccp_ctl_socket_init = 0;
1076
1077 dccp_init_xmit_timers(sk);
1078 icsk->icsk_rto = DCCP_TIMEOUT_INIT;
1079 sk->sk_state = DCCP_CLOSED;
1080 sk->sk_write_space = dccp_write_space;
1081 icsk->icsk_af_ops = &dccp_ipv4_af_ops;
1082 icsk->icsk_sync_mss = dccp_sync_mss;
1083 dp->dccps_mss_cache = 536;
1084 dp->dccps_role = DCCP_ROLE_UNDEFINED;
1085 dp->dccps_service = DCCP_SERVICE_INVALID_VALUE;
1086
1087 return 0;
1088}
1089
1090EXPORT_SYMBOL_GPL(dccp_v4_init_sock);
1091
1092int dccp_v4_destroy_sock(struct sock *sk)
1093{ 1006{
1094 struct dccp_sock *dp = dccp_sk(sk); 1007 static __u8 dccp_v4_ctl_sock_initialized;
1008 int err = dccp_init_sock(sk, dccp_v4_ctl_sock_initialized);
1095 1009
1096 /* 1010 if (err == 0) {
1097 * DCCP doesn't use sk_write_queue, just sk_send_head 1011 if (unlikely(!dccp_v4_ctl_sock_initialized))
1098 * for retransmissions 1012 dccp_v4_ctl_sock_initialized = 1;
1099 */ 1013 inet_csk(sk)->icsk_af_ops = &dccp_ipv4_af_ops;
1100 if (sk->sk_send_head != NULL) {
1101 kfree_skb(sk->sk_send_head);
1102 sk->sk_send_head = NULL;
1103 } 1014 }
1104 1015
1105 /* Clean up a referenced DCCP bind bucket. */ 1016 return err;
1106 if (inet_csk(sk)->icsk_bind_hash != NULL)
1107 inet_put_port(&dccp_hashinfo, sk);
1108
1109 kfree(dp->dccps_service_list);
1110 dp->dccps_service_list = NULL;
1111
1112 ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk);
1113 ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk);
1114 if (dp->dccps_options.dccpo_send_ack_vector) {
1115 dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
1116 dp->dccps_hc_rx_ackvec = NULL;
1117 }
1118 ccid_exit(dp->dccps_hc_rx_ccid, sk);
1119 ccid_exit(dp->dccps_hc_tx_ccid, sk);
1120 dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
1121
1122 return 0;
1123} 1017}
1124 1018
1125EXPORT_SYMBOL_GPL(dccp_v4_destroy_sock);
1126
1127static void dccp_v4_reqsk_destructor(struct request_sock *req) 1019static void dccp_v4_reqsk_destructor(struct request_sock *req)
1128{ 1020{
1129 kfree(inet_rsk(req)->opt); 1021 kfree(inet_rsk(req)->opt);
@@ -1142,7 +1034,7 @@ static struct timewait_sock_ops dccp_timewait_sock_ops = {
1142 .twsk_obj_size = sizeof(struct inet_timewait_sock), 1034 .twsk_obj_size = sizeof(struct inet_timewait_sock),
1143}; 1035};
1144 1036
1145struct proto dccp_prot = { 1037static struct proto dccp_v4_prot = {
1146 .name = "DCCP", 1038 .name = "DCCP",
1147 .owner = THIS_MODULE, 1039 .owner = THIS_MODULE,
1148 .close = dccp_close, 1040 .close = dccp_close,
@@ -1155,17 +1047,110 @@ struct proto dccp_prot = {
1155 .sendmsg = dccp_sendmsg, 1047 .sendmsg = dccp_sendmsg,
1156 .recvmsg = dccp_recvmsg, 1048 .recvmsg = dccp_recvmsg,
1157 .backlog_rcv = dccp_v4_do_rcv, 1049 .backlog_rcv = dccp_v4_do_rcv,
1158 .hash = dccp_v4_hash, 1050 .hash = dccp_hash,
1159 .unhash = dccp_unhash, 1051 .unhash = dccp_unhash,
1160 .accept = inet_csk_accept, 1052 .accept = inet_csk_accept,
1161 .get_port = dccp_v4_get_port, 1053 .get_port = dccp_v4_get_port,
1162 .shutdown = dccp_shutdown, 1054 .shutdown = dccp_shutdown,
1163 .destroy = dccp_v4_destroy_sock, 1055 .destroy = dccp_destroy_sock,
1164 .orphan_count = &dccp_orphan_count, 1056 .orphan_count = &dccp_orphan_count,
1165 .max_header = MAX_DCCP_HEADER, 1057 .max_header = MAX_DCCP_HEADER,
1166 .obj_size = sizeof(struct dccp_sock), 1058 .obj_size = sizeof(struct dccp_sock),
1167 .rsk_prot = &dccp_request_sock_ops, 1059 .rsk_prot = &dccp_request_sock_ops,
1168 .twsk_prot = &dccp_timewait_sock_ops, 1060 .twsk_prot = &dccp_timewait_sock_ops,
1061#ifdef CONFIG_COMPAT
1062 .compat_setsockopt = compat_dccp_setsockopt,
1063 .compat_getsockopt = compat_dccp_getsockopt,
1064#endif
1065};
1066
1067static struct net_protocol dccp_v4_protocol = {
1068 .handler = dccp_v4_rcv,
1069 .err_handler = dccp_v4_err,
1070 .no_policy = 1,
1071};
1072
1073static const struct proto_ops inet_dccp_ops = {
1074 .family = PF_INET,
1075 .owner = THIS_MODULE,
1076 .release = inet_release,
1077 .bind = inet_bind,
1078 .connect = inet_stream_connect,
1079 .socketpair = sock_no_socketpair,
1080 .accept = inet_accept,
1081 .getname = inet_getname,
1082 /* FIXME: work on tcp_poll to rename it to inet_csk_poll */
1083 .poll = dccp_poll,
1084 .ioctl = inet_ioctl,
1085 /* FIXME: work on inet_listen to rename it to sock_common_listen */
1086 .listen = inet_dccp_listen,
1087 .shutdown = inet_shutdown,
1088 .setsockopt = sock_common_setsockopt,
1089 .getsockopt = sock_common_getsockopt,
1090 .sendmsg = inet_sendmsg,
1091 .recvmsg = sock_common_recvmsg,
1092 .mmap = sock_no_mmap,
1093 .sendpage = sock_no_sendpage,
1094#ifdef CONFIG_COMPAT
1095 .compat_setsockopt = compat_sock_common_setsockopt,
1096 .compat_getsockopt = compat_sock_common_getsockopt,
1097#endif
1169}; 1098};
1170 1099
1171EXPORT_SYMBOL_GPL(dccp_prot); 1100static struct inet_protosw dccp_v4_protosw = {
1101 .type = SOCK_DCCP,
1102 .protocol = IPPROTO_DCCP,
1103 .prot = &dccp_v4_prot,
1104 .ops = &inet_dccp_ops,
1105 .capability = -1,
1106 .no_check = 0,
1107 .flags = INET_PROTOSW_ICSK,
1108};
1109
1110static int __init dccp_v4_init(void)
1111{
1112 int err = proto_register(&dccp_v4_prot, 1);
1113
1114 if (err != 0)
1115 goto out;
1116
1117 err = inet_add_protocol(&dccp_v4_protocol, IPPROTO_DCCP);
1118 if (err != 0)
1119 goto out_proto_unregister;
1120
1121 inet_register_protosw(&dccp_v4_protosw);
1122
1123 err = inet_csk_ctl_sock_create(&dccp_v4_ctl_socket, PF_INET,
1124 SOCK_DCCP, IPPROTO_DCCP);
1125 if (err)
1126 goto out_unregister_protosw;
1127out:
1128 return err;
1129out_unregister_protosw:
1130 inet_unregister_protosw(&dccp_v4_protosw);
1131 inet_del_protocol(&dccp_v4_protocol, IPPROTO_DCCP);
1132out_proto_unregister:
1133 proto_unregister(&dccp_v4_prot);
1134 goto out;
1135}
1136
1137static void __exit dccp_v4_exit(void)
1138{
1139 inet_unregister_protosw(&dccp_v4_protosw);
1140 inet_del_protocol(&dccp_v4_protocol, IPPROTO_DCCP);
1141 proto_unregister(&dccp_v4_prot);
1142}
1143
1144module_init(dccp_v4_init);
1145module_exit(dccp_v4_exit);
1146
1147/*
1148 * __stringify doesn't likes enums, so use SOCK_DCCP (6) and IPPROTO_DCCP (33)
1149 * values directly, Also cover the case where the protocol is not specified,
1150 * i.e. net-pf-PF_INET-proto-0-type-SOCK_DCCP
1151 */
1152MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-33-type-6");
1153MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-0-type-6");
1154MODULE_LICENSE("GPL");
1155MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>");
1156MODULE_DESCRIPTION("DCCP - Datagram Congestion Controlled Protocol");