aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/ipv4.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-01-04 19:27:41 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-04 19:27:41 -0500
commitd347da0deffa1d8f88f0d270eab040e4707c9916 (patch)
treee0911f2ef4d36a7b44f7a5379feabebbd37dcfc4 /net/dccp/ipv4.c
parentc6c88bbde4d8b2ffe9886b7130b2e23781d424e5 (diff)
parent74cb8798222bb7d1aecb0acb91e6eeedf5feb948 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
Diffstat (limited to 'net/dccp/ipv4.c')
-rw-r--r--net/dccp/ipv4.c305
1 files changed, 77 insertions, 228 deletions
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 656e13e38cfb..3f244670764a 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -19,7 +19,9 @@
19 19
20#include <net/icmp.h> 20#include <net/icmp.h>
21#include <net/inet_hashtables.h> 21#include <net/inet_hashtables.h>
22#include <net/inet_sock.h>
22#include <net/sock.h> 23#include <net/sock.h>
24#include <net/timewait_sock.h>
23#include <net/tcp_states.h> 25#include <net/tcp_states.h>
24#include <net/xfrm.h> 26#include <net/xfrm.h>
25 27
@@ -37,7 +39,8 @@ EXPORT_SYMBOL_GPL(dccp_hashinfo);
37 39
38static int dccp_v4_get_port(struct sock *sk, const unsigned short snum) 40static int dccp_v4_get_port(struct sock *sk, const unsigned short snum)
39{ 41{
40 return inet_csk_get_port(&dccp_hashinfo, sk, snum); 42 return inet_csk_get_port(&dccp_hashinfo, sk, snum,
43 inet_csk_bind_conflict);
41} 44}
42 45
43static void dccp_v4_hash(struct sock *sk) 46static void dccp_v4_hash(struct sock *sk)
@@ -45,171 +48,14 @@ static void dccp_v4_hash(struct sock *sk)
45 inet_hash(&dccp_hashinfo, sk); 48 inet_hash(&dccp_hashinfo, sk);
46} 49}
47 50
48static void dccp_v4_unhash(struct sock *sk) 51void dccp_unhash(struct sock *sk)
49{ 52{
50 inet_unhash(&dccp_hashinfo, sk); 53 inet_unhash(&dccp_hashinfo, sk);
51} 54}
52 55
53/* called with local bh disabled */ 56EXPORT_SYMBOL_GPL(dccp_unhash);
54static int __dccp_v4_check_established(struct sock *sk, const __u16 lport,
55 struct inet_timewait_sock **twp)
56{
57 struct inet_sock *inet = inet_sk(sk);
58 const u32 daddr = inet->rcv_saddr;
59 const u32 saddr = inet->daddr;
60 const int dif = sk->sk_bound_dev_if;
61 INET_ADDR_COOKIE(acookie, saddr, daddr)
62 const __u32 ports = INET_COMBINED_PORTS(inet->dport, lport);
63 unsigned int hash = inet_ehashfn(daddr, lport, saddr, inet->dport);
64 struct inet_ehash_bucket *head = inet_ehash_bucket(&dccp_hashinfo, hash);
65 const struct sock *sk2;
66 const struct hlist_node *node;
67 struct inet_timewait_sock *tw;
68
69 prefetch(head->chain.first);
70 write_lock(&head->lock);
71
72 /* Check TIME-WAIT sockets first. */
73 sk_for_each(sk2, node, &(head + dccp_hashinfo.ehash_size)->chain) {
74 tw = inet_twsk(sk2);
75
76 if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif))
77 goto not_unique;
78 }
79 tw = NULL;
80
81 /* And established part... */
82 sk_for_each(sk2, node, &head->chain) {
83 if (INET_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif))
84 goto not_unique;
85 }
86 57
87 /* Must record num and sport now. Otherwise we will see 58int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
88 * in hash table socket with a funny identity. */
89 inet->num = lport;
90 inet->sport = htons(lport);
91 sk->sk_hash = hash;
92 BUG_TRAP(sk_unhashed(sk));
93 __sk_add_node(sk, &head->chain);
94 sock_prot_inc_use(sk->sk_prot);
95 write_unlock(&head->lock);
96
97 if (twp != NULL) {
98 *twp = tw;
99 NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
100 } else if (tw != NULL) {
101 /* Silly. Should hash-dance instead... */
102 inet_twsk_deschedule(tw, &dccp_death_row);
103 NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
104
105 inet_twsk_put(tw);
106 }
107
108 return 0;
109
110not_unique:
111 write_unlock(&head->lock);
112 return -EADDRNOTAVAIL;
113}
114
115/*
116 * Bind a port for a connect operation and hash it.
117 */
118static int dccp_v4_hash_connect(struct sock *sk)
119{
120 const unsigned short snum = inet_sk(sk)->num;
121 struct inet_bind_hashbucket *head;
122 struct inet_bind_bucket *tb;
123 int ret;
124
125 if (snum == 0) {
126 int low = sysctl_local_port_range[0];
127 int high = sysctl_local_port_range[1];
128 int remaining = (high - low) + 1;
129 int rover = net_random() % (high - low) + low;
130 struct hlist_node *node;
131 struct inet_timewait_sock *tw = NULL;
132
133 local_bh_disable();
134 do {
135 head = &dccp_hashinfo.bhash[inet_bhashfn(rover,
136 dccp_hashinfo.bhash_size)];
137 spin_lock(&head->lock);
138
139 /* Does not bother with rcv_saddr checks,
140 * because the established check is already
141 * unique enough.
142 */
143 inet_bind_bucket_for_each(tb, node, &head->chain) {
144 if (tb->port == rover) {
145 BUG_TRAP(!hlist_empty(&tb->owners));
146 if (tb->fastreuse >= 0)
147 goto next_port;
148 if (!__dccp_v4_check_established(sk,
149 rover,
150 &tw))
151 goto ok;
152 goto next_port;
153 }
154 }
155
156 tb = inet_bind_bucket_create(dccp_hashinfo.bind_bucket_cachep,
157 head, rover);
158 if (tb == NULL) {
159 spin_unlock(&head->lock);
160 break;
161 }
162 tb->fastreuse = -1;
163 goto ok;
164
165 next_port:
166 spin_unlock(&head->lock);
167 if (++rover > high)
168 rover = low;
169 } while (--remaining > 0);
170
171 local_bh_enable();
172
173 return -EADDRNOTAVAIL;
174
175ok:
176 /* All locks still held and bhs disabled */
177 inet_bind_hash(sk, tb, rover);
178 if (sk_unhashed(sk)) {
179 inet_sk(sk)->sport = htons(rover);
180 __inet_hash(&dccp_hashinfo, sk, 0);
181 }
182 spin_unlock(&head->lock);
183
184 if (tw != NULL) {
185 inet_twsk_deschedule(tw, &dccp_death_row);
186 inet_twsk_put(tw);
187 }
188
189 ret = 0;
190 goto out;
191 }
192
193 head = &dccp_hashinfo.bhash[inet_bhashfn(snum,
194 dccp_hashinfo.bhash_size)];
195 tb = inet_csk(sk)->icsk_bind_hash;
196 spin_lock_bh(&head->lock);
197 if (sk_head(&tb->owners) == sk && sk->sk_bind_node.next == NULL) {
198 __inet_hash(&dccp_hashinfo, sk, 0);
199 spin_unlock_bh(&head->lock);
200 return 0;
201 } else {
202 spin_unlock(&head->lock);
203 /* No definite answer... Walk to established hash table */
204 ret = __dccp_v4_check_established(sk, snum, NULL);
205out:
206 local_bh_enable();
207 return ret;
208 }
209}
210
211static int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr,
212 int addr_len)
213{ 59{
214 struct inet_sock *inet = inet_sk(sk); 60 struct inet_sock *inet = inet_sk(sk);
215 struct dccp_sock *dp = dccp_sk(sk); 61 struct dccp_sock *dp = dccp_sk(sk);
@@ -259,9 +105,9 @@ static int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr,
259 inet->dport = usin->sin_port; 105 inet->dport = usin->sin_port;
260 inet->daddr = daddr; 106 inet->daddr = daddr;
261 107
262 dp->dccps_ext_header_len = 0; 108 inet_csk(sk)->icsk_ext_hdr_len = 0;
263 if (inet->opt != NULL) 109 if (inet->opt != NULL)
264 dp->dccps_ext_header_len = inet->opt->optlen; 110 inet_csk(sk)->icsk_ext_hdr_len = inet->opt->optlen;
265 /* 111 /*
266 * Socket identity is still unknown (sport may be zero). 112 * Socket identity is still unknown (sport may be zero).
267 * However we set state to DCCP_REQUESTING and not releasing socket 113 * However we set state to DCCP_REQUESTING and not releasing socket
@@ -269,7 +115,7 @@ static int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr,
269 * complete initialization after this. 115 * complete initialization after this.
270 */ 116 */
271 dccp_set_state(sk, DCCP_REQUESTING); 117 dccp_set_state(sk, DCCP_REQUESTING);
272 err = dccp_v4_hash_connect(sk); 118 err = inet_hash_connect(&dccp_death_row, sk);
273 if (err != 0) 119 if (err != 0)
274 goto failure; 120 goto failure;
275 121
@@ -287,16 +133,6 @@ static int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr,
287 usin->sin_port); 133 usin->sin_port);
288 dccp_update_gss(sk, dp->dccps_iss); 134 dccp_update_gss(sk, dp->dccps_iss);
289 135
290 /*
291 * SWL and AWL are initially adjusted so that they are not less than
292 * the initial Sequence Numbers received and sent, respectively:
293 * SWL := max(GSR + 1 - floor(W/4), ISR),
294 * AWL := max(GSS - W' + 1, ISS).
295 * These adjustments MUST be applied only at the beginning of the
296 * connection.
297 */
298 dccp_set_seqno(&dp->dccps_awl, max48(dp->dccps_awl, dp->dccps_iss));
299
300 inet->id = dp->dccps_iss ^ jiffies; 136 inet->id = dp->dccps_iss ^ jiffies;
301 137
302 err = dccp_connect(sk); 138 err = dccp_connect(sk);
@@ -316,6 +152,8 @@ failure:
316 goto out; 152 goto out;
317} 153}
318 154
155EXPORT_SYMBOL_GPL(dccp_v4_connect);
156
319/* 157/*
320 * This routine does path mtu discovery as defined in RFC1191. 158 * This routine does path mtu discovery as defined in RFC1191.
321 */ 159 */
@@ -354,7 +192,7 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk,
354 mtu = dst_mtu(dst); 192 mtu = dst_mtu(dst);
355 193
356 if (inet->pmtudisc != IP_PMTUDISC_DONT && 194 if (inet->pmtudisc != IP_PMTUDISC_DONT &&
357 dp->dccps_pmtu_cookie > mtu) { 195 inet_csk(sk)->icsk_pmtu_cookie > mtu) {
358 dccp_sync_mss(sk, mtu); 196 dccp_sync_mss(sk, mtu);
359 197
360 /* 198 /*
@@ -606,6 +444,17 @@ out:
606 sock_put(sk); 444 sock_put(sk);
607} 445}
608 446
447/* This routine computes an IPv4 DCCP checksum. */
448void dccp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb)
449{
450 const struct inet_sock *inet = inet_sk(sk);
451 struct dccp_hdr *dh = dccp_hdr(skb);
452
453 dh->dccph_checksum = dccp_v4_checksum(skb, inet->saddr, inet->daddr);
454}
455
456EXPORT_SYMBOL_GPL(dccp_v4_send_check);
457
609int dccp_v4_send_reset(struct sock *sk, enum dccp_reset_codes code) 458int dccp_v4_send_reset(struct sock *sk, enum dccp_reset_codes code)
610{ 459{
611 struct sk_buff *skb; 460 struct sk_buff *skb;
@@ -641,16 +490,6 @@ static inline u64 dccp_v4_init_sequence(const struct sock *sk,
641 dccp_hdr(skb)->dccph_sport); 490 dccp_hdr(skb)->dccph_sport);
642} 491}
643 492
644static inline int dccp_bad_service_code(const struct sock *sk,
645 const __u32 service)
646{
647 const struct dccp_sock *dp = dccp_sk(sk);
648
649 if (dp->dccps_service == service)
650 return 0;
651 return !dccp_list_has_service(dp->dccps_service_list, service);
652}
653
654int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) 493int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
655{ 494{
656 struct inet_request_sock *ireq; 495 struct inet_request_sock *ireq;
@@ -662,7 +501,6 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
662 const __u32 service = dccp_hdr_request(skb)->dccph_req_service; 501 const __u32 service = dccp_hdr_request(skb)->dccph_req_service;
663 struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); 502 struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
664 __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY; 503 __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
665 struct dst_entry *dst = NULL;
666 504
667 /* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */ 505 /* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */
668 if (((struct rtable *)skb->dst)->rt_flags & 506 if (((struct rtable *)skb->dst)->rt_flags &
@@ -703,7 +541,6 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
703 ireq = inet_rsk(req); 541 ireq = inet_rsk(req);
704 ireq->loc_addr = daddr; 542 ireq->loc_addr = daddr;
705 ireq->rmt_addr = saddr; 543 ireq->rmt_addr = saddr;
706 /* FIXME: Merge Aristeu's option parsing code when ready */
707 req->rcv_wnd = 100; /* Fake, option parsing will get the 544 req->rcv_wnd = 100; /* Fake, option parsing will get the
708 right value */ 545 right value */
709 ireq->opt = NULL; 546 ireq->opt = NULL;
@@ -721,23 +558,22 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
721 dreq->dreq_iss = dccp_v4_init_sequence(sk, skb); 558 dreq->dreq_iss = dccp_v4_init_sequence(sk, skb);
722 dreq->dreq_service = service; 559 dreq->dreq_service = service;
723 560
724 if (dccp_v4_send_response(sk, req, dst)) 561 if (dccp_v4_send_response(sk, req, NULL))
725 goto drop_and_free; 562 goto drop_and_free;
726 563
727 inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT); 564 inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT);
728 return 0; 565 return 0;
729 566
730drop_and_free: 567drop_and_free:
731 /* 568 reqsk_free(req);
732 * FIXME: should be reqsk_free after implementing req->rsk_ops
733 */
734 __reqsk_free(req);
735drop: 569drop:
736 DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS); 570 DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
737 dcb->dccpd_reset_code = reset_code; 571 dcb->dccpd_reset_code = reset_code;
738 return -1; 572 return -1;
739} 573}
740 574
575EXPORT_SYMBOL_GPL(dccp_v4_conn_request);
576
741/* 577/*
742 * The three way handshake has completed - we got a valid ACK or DATAACK - 578 * The three way handshake has completed - we got a valid ACK or DATAACK -
743 * now create the new socket. 579 * now create the new socket.
@@ -792,6 +628,8 @@ exit:
792 return NULL; 628 return NULL;
793} 629}
794 630
631EXPORT_SYMBOL_GPL(dccp_v4_request_recv_sock);
632
795static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) 633static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
796{ 634{
797 const struct dccp_hdr *dh = dccp_hdr(skb); 635 const struct dccp_hdr *dh = dccp_hdr(skb);
@@ -1011,7 +849,9 @@ discard:
1011 return 0; 849 return 0;
1012} 850}
1013 851
1014static inline int dccp_invalid_packet(struct sk_buff *skb) 852EXPORT_SYMBOL_GPL(dccp_v4_do_rcv);
853
854int dccp_invalid_packet(struct sk_buff *skb)
1015{ 855{
1016 const struct dccp_hdr *dh; 856 const struct dccp_hdr *dh;
1017 857
@@ -1065,29 +905,30 @@ static inline int dccp_invalid_packet(struct sk_buff *skb)
1065 return 1; 905 return 1;
1066 } 906 }
1067 907
1068 /* If the header checksum is incorrect, drop packet and return */
1069 if (dccp_v4_verify_checksum(skb, skb->nh.iph->saddr,
1070 skb->nh.iph->daddr) < 0) {
1071 LIMIT_NETDEBUG(KERN_WARNING "DCCP: header checksum is "
1072 "incorrect\n");
1073 return 1;
1074 }
1075
1076 return 0; 908 return 0;
1077} 909}
1078 910
911EXPORT_SYMBOL_GPL(dccp_invalid_packet);
912
1079/* this is called when real data arrives */ 913/* this is called when real data arrives */
1080int dccp_v4_rcv(struct sk_buff *skb) 914int dccp_v4_rcv(struct sk_buff *skb)
1081{ 915{
1082 const struct dccp_hdr *dh; 916 const struct dccp_hdr *dh;
1083 struct sock *sk; 917 struct sock *sk;
1084 int rc;
1085 918
1086 /* Step 1: Check header basics: */ 919 /* Step 1: Check header basics: */
1087 920
1088 if (dccp_invalid_packet(skb)) 921 if (dccp_invalid_packet(skb))
1089 goto discard_it; 922 goto discard_it;
1090 923
924 /* If the header checksum is incorrect, drop packet and return */
925 if (dccp_v4_verify_checksum(skb, skb->nh.iph->saddr,
926 skb->nh.iph->daddr) < 0) {
927 LIMIT_NETDEBUG(KERN_WARNING "%s: incorrect header checksum\n",
928 __FUNCTION__);
929 goto discard_it;
930 }
931
1091 dh = dccp_hdr(skb); 932 dh = dccp_hdr(skb);
1092 933
1093 DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb); 934 DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb);
@@ -1143,28 +984,10 @@ int dccp_v4_rcv(struct sk_buff *skb)
1143 goto do_time_wait; 984 goto do_time_wait;
1144 } 985 }
1145 986
1146 if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) { 987 if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
1147 dccp_pr_debug("xfrm4_policy_check failed\n");
1148 goto discard_and_relse; 988 goto discard_and_relse;
1149 }
1150
1151 if (sk_filter(sk, skb, 0)) {
1152 dccp_pr_debug("sk_filter failed\n");
1153 goto discard_and_relse;
1154 }
1155
1156 skb->dev = NULL;
1157
1158 bh_lock_sock(sk);
1159 rc = 0;
1160 if (!sock_owned_by_user(sk))
1161 rc = dccp_v4_do_rcv(sk, skb);
1162 else
1163 sk_add_backlog(sk, skb);
1164 bh_unlock_sock(sk);
1165 989
1166 sock_put(sk); 990 return sk_receive_skb(sk, skb);
1167 return rc;
1168 991
1169no_dccp_socket: 992no_dccp_socket:
1170 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) 993 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
@@ -1194,9 +1017,23 @@ do_time_wait:
1194 goto no_dccp_socket; 1017 goto no_dccp_socket;
1195} 1018}
1196 1019
1197static int dccp_v4_init_sock(struct sock *sk) 1020struct inet_connection_sock_af_ops dccp_ipv4_af_ops = {
1021 .queue_xmit = ip_queue_xmit,
1022 .send_check = dccp_v4_send_check,
1023 .rebuild_header = inet_sk_rebuild_header,
1024 .conn_request = dccp_v4_conn_request,
1025 .syn_recv_sock = dccp_v4_request_recv_sock,
1026 .net_header_len = sizeof(struct iphdr),
1027 .setsockopt = ip_setsockopt,
1028 .getsockopt = ip_getsockopt,
1029 .addr2sockaddr = inet_csk_addr2sockaddr,
1030 .sockaddr_len = sizeof(struct sockaddr_in),
1031};
1032
1033int dccp_v4_init_sock(struct sock *sk)
1198{ 1034{
1199 struct dccp_sock *dp = dccp_sk(sk); 1035 struct dccp_sock *dp = dccp_sk(sk);
1036 struct inet_connection_sock *icsk = inet_csk(sk);
1200 static int dccp_ctl_socket_init = 1; 1037 static int dccp_ctl_socket_init = 1;
1201 1038
1202 dccp_options_init(&dp->dccps_options); 1039 dccp_options_init(&dp->dccps_options);
@@ -1236,9 +1073,11 @@ static int dccp_v4_init_sock(struct sock *sk)
1236 dccp_ctl_socket_init = 0; 1073 dccp_ctl_socket_init = 0;
1237 1074
1238 dccp_init_xmit_timers(sk); 1075 dccp_init_xmit_timers(sk);
1239 inet_csk(sk)->icsk_rto = DCCP_TIMEOUT_INIT; 1076 icsk->icsk_rto = DCCP_TIMEOUT_INIT;
1240 sk->sk_state = DCCP_CLOSED; 1077 sk->sk_state = DCCP_CLOSED;
1241 sk->sk_write_space = dccp_write_space; 1078 sk->sk_write_space = dccp_write_space;
1079 icsk->icsk_af_ops = &dccp_ipv4_af_ops;
1080 icsk->icsk_sync_mss = dccp_sync_mss;
1242 dp->dccps_mss_cache = 536; 1081 dp->dccps_mss_cache = 536;
1243 dp->dccps_role = DCCP_ROLE_UNDEFINED; 1082 dp->dccps_role = DCCP_ROLE_UNDEFINED;
1244 dp->dccps_service = DCCP_SERVICE_INVALID_VALUE; 1083 dp->dccps_service = DCCP_SERVICE_INVALID_VALUE;
@@ -1246,7 +1085,9 @@ static int dccp_v4_init_sock(struct sock *sk)
1246 return 0; 1085 return 0;
1247} 1086}
1248 1087
1249static int dccp_v4_destroy_sock(struct sock *sk) 1088EXPORT_SYMBOL_GPL(dccp_v4_init_sock);
1089
1090int dccp_v4_destroy_sock(struct sock *sk)
1250{ 1091{
1251 struct dccp_sock *dp = dccp_sk(sk); 1092 struct dccp_sock *dp = dccp_sk(sk);
1252 1093
@@ -1279,6 +1120,8 @@ static int dccp_v4_destroy_sock(struct sock *sk)
1279 return 0; 1120 return 0;
1280} 1121}
1281 1122
1123EXPORT_SYMBOL_GPL(dccp_v4_destroy_sock);
1124
1282static void dccp_v4_reqsk_destructor(struct request_sock *req) 1125static void dccp_v4_reqsk_destructor(struct request_sock *req)
1283{ 1126{
1284 kfree(inet_rsk(req)->opt); 1127 kfree(inet_rsk(req)->opt);
@@ -1293,7 +1136,11 @@ static struct request_sock_ops dccp_request_sock_ops = {
1293 .send_reset = dccp_v4_ctl_send_reset, 1136 .send_reset = dccp_v4_ctl_send_reset,
1294}; 1137};
1295 1138
1296struct proto dccp_v4_prot = { 1139static struct timewait_sock_ops dccp_timewait_sock_ops = {
1140 .twsk_obj_size = sizeof(struct inet_timewait_sock),
1141};
1142
1143struct proto dccp_prot = {
1297 .name = "DCCP", 1144 .name = "DCCP",
1298 .owner = THIS_MODULE, 1145 .owner = THIS_MODULE,
1299 .close = dccp_close, 1146 .close = dccp_close,
@@ -1307,7 +1154,7 @@ struct proto dccp_v4_prot = {
1307 .recvmsg = dccp_recvmsg, 1154 .recvmsg = dccp_recvmsg,
1308 .backlog_rcv = dccp_v4_do_rcv, 1155 .backlog_rcv = dccp_v4_do_rcv,
1309 .hash = dccp_v4_hash, 1156 .hash = dccp_v4_hash,
1310 .unhash = dccp_v4_unhash, 1157 .unhash = dccp_unhash,
1311 .accept = inet_csk_accept, 1158 .accept = inet_csk_accept,
1312 .get_port = dccp_v4_get_port, 1159 .get_port = dccp_v4_get_port,
1313 .shutdown = dccp_shutdown, 1160 .shutdown = dccp_shutdown,
@@ -1316,5 +1163,7 @@ struct proto dccp_v4_prot = {
1316 .max_header = MAX_DCCP_HEADER, 1163 .max_header = MAX_DCCP_HEADER,
1317 .obj_size = sizeof(struct dccp_sock), 1164 .obj_size = sizeof(struct dccp_sock),
1318 .rsk_prot = &dccp_request_sock_ops, 1165 .rsk_prot = &dccp_request_sock_ops,
1319 .twsk_obj_size = sizeof(struct inet_timewait_sock), 1166 .twsk_prot = &dccp_timewait_sock_ops,
1320}; 1167};
1168
1169EXPORT_SYMBOL_GPL(dccp_prot);