aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp')
-rw-r--r--net/dccp/Kconfig9
-rw-r--r--net/dccp/ccids/ccid3.c9
-rw-r--r--net/dccp/dccp.h4
-rw-r--r--net/dccp/ipv4.c65
-rw-r--r--net/dccp/ipv6.c44
-rw-r--r--net/dccp/proto.c6
6 files changed, 72 insertions, 65 deletions
diff --git a/net/dccp/Kconfig b/net/dccp/Kconfig
index 24a6981e209a..7e096ba8454f 100644
--- a/net/dccp/Kconfig
+++ b/net/dccp/Kconfig
@@ -40,15 +40,6 @@ config IP_DCCP_DEBUG
40 40
41 Just say N. 41 Just say N.
42 42
43config IP_DCCP_UNLOAD_HACK
44 depends on IP_DCCP=m && IP_DCCP_CCID3=m
45 bool "DCCP control sock unload hack"
46 ---help---
47 Enable this to be able to unload the dccp module when the it
48 has only one refcount held, the control sock one. Just execute
49 "rmmod dccp_ccid3 dccp"
50
51 Just say N.
52endmenu 43endmenu
53 44
54endmenu 45endmenu
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index ff6a0d7076ef..ff426a900999 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -1211,15 +1211,6 @@ module_init(ccid3_module_init);
1211 1211
1212static __exit void ccid3_module_exit(void) 1212static __exit void ccid3_module_exit(void)
1213{ 1213{
1214#ifdef CONFIG_IP_DCCP_UNLOAD_HACK
1215 /*
1216 * Hack to use while developing, so that we get rid of the control
1217 * sock, that is what keeps a refcount on dccp.ko -acme
1218 */
1219 extern void dccp_ctl_sock_exit(void);
1220
1221 dccp_ctl_sock_exit();
1222#endif
1223 ccid_unregister(&ccid3); 1214 ccid_unregister(&ccid3);
1224 1215
1225 if (ccid3_tx_hist != NULL) { 1216 if (ccid3_tx_hist != NULL) {
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 6fcc9d47ae8c..d57d21351149 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -177,7 +177,7 @@ extern int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
177extern int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, 177extern int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
178 const struct dccp_hdr *dh, const unsigned len); 178 const struct dccp_hdr *dh, const unsigned len);
179 179
180extern int dccp_init_sock(struct sock *sk); 180extern int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized);
181extern int dccp_destroy_sock(struct sock *sk); 181extern int dccp_destroy_sock(struct sock *sk);
182 182
183extern void dccp_close(struct sock *sk, long timeout); 183extern void dccp_close(struct sock *sk, long timeout);
@@ -337,8 +337,6 @@ extern void dccp_insert_option(struct sock *sk, struct sk_buff *skb,
337 unsigned char option, 337 unsigned char option,
338 const void *value, unsigned char len); 338 const void *value, unsigned char len);
339 339
340extern struct socket *dccp_ctl_socket;
341
342extern void dccp_timestamp(const struct sock *sk, struct timeval *tv); 340extern void dccp_timestamp(const struct sock *sk, struct timeval *tv);
343 341
344static inline suseconds_t timeval_usecs(const struct timeval *tv) 342static inline suseconds_t timeval_usecs(const struct timeval *tv)
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 3fe958eb4bf3..f53bce590ade 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -32,6 +32,13 @@
32#include "dccp.h" 32#include "dccp.h"
33#include "feat.h" 33#include "feat.h"
34 34
35/*
36 * This is the global socket data structure used for responding to
37 * the Out-of-the-blue (OOTB) packets. A control sock will be created
38 * for this socket at the initialization time.
39 */
40static struct socket *dccp_v4_ctl_socket;
41
35static 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)
36{ 43{
37 return inet_csk_get_port(&dccp_hashinfo, sk, snum, 44 return inet_csk_get_port(&dccp_hashinfo, sk, snum,
@@ -226,11 +233,11 @@ static void dccp_v4_ctl_send_ack(struct sk_buff *rxskb)
226 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), 233 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
227 DCCP_SKB_CB(rxskb)->dccpd_seq); 234 DCCP_SKB_CB(rxskb)->dccpd_seq);
228 235
229 bh_lock_sock(dccp_ctl_socket->sk); 236 bh_lock_sock(dccp_v4_ctl_socket->sk);
230 err = ip_build_and_send_pkt(skb, dccp_ctl_socket->sk, 237 err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
231 rxskb->nh.iph->daddr, 238 rxskb->nh.iph->daddr,
232 rxskb->nh.iph->saddr, NULL); 239 rxskb->nh.iph->saddr, NULL);
233 bh_unlock_sock(dccp_ctl_socket->sk); 240 bh_unlock_sock(dccp_v4_ctl_socket->sk);
234 241
235 if (err == NET_XMIT_CN || err == 0) { 242 if (err == NET_XMIT_CN || err == 0) {
236 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); 243 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
@@ -704,7 +711,7 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb)
704 if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL) 711 if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL)
705 return; 712 return;
706 713
707 dst = dccp_v4_route_skb(dccp_ctl_socket->sk, rxskb); 714 dst = dccp_v4_route_skb(dccp_v4_ctl_socket->sk, rxskb);
708 if (dst == NULL) 715 if (dst == NULL)
709 return; 716 return;
710 717
@@ -741,11 +748,11 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb)
741 dh->dccph_checksum = dccp_v4_checksum(skb, rxskb->nh.iph->saddr, 748 dh->dccph_checksum = dccp_v4_checksum(skb, rxskb->nh.iph->saddr,
742 rxskb->nh.iph->daddr); 749 rxskb->nh.iph->daddr);
743 750
744 bh_lock_sock(dccp_ctl_socket->sk); 751 bh_lock_sock(dccp_v4_ctl_socket->sk);
745 err = ip_build_and_send_pkt(skb, dccp_ctl_socket->sk, 752 err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
746 rxskb->nh.iph->daddr, 753 rxskb->nh.iph->daddr,
747 rxskb->nh.iph->saddr, NULL); 754 rxskb->nh.iph->saddr, NULL);
748 bh_unlock_sock(dccp_ctl_socket->sk); 755 bh_unlock_sock(dccp_v4_ctl_socket->sk);
749 756
750 if (err == NET_XMIT_CN || err == 0) { 757 if (err == NET_XMIT_CN || err == 0) {
751 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); 758 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
@@ -997,10 +1004,15 @@ static struct inet_connection_sock_af_ops dccp_ipv4_af_ops = {
997 1004
998static int dccp_v4_init_sock(struct sock *sk) 1005static int dccp_v4_init_sock(struct sock *sk)
999{ 1006{
1000 const int err = dccp_init_sock(sk); 1007 static __u8 dccp_v4_ctl_sock_initialized;
1008 int err = dccp_init_sock(sk, dccp_v4_ctl_sock_initialized);
1001 1009
1002 if (err == 0) 1010 if (err == 0) {
1011 if (unlikely(!dccp_v4_ctl_sock_initialized))
1012 dccp_v4_ctl_sock_initialized = 1;
1003 inet_csk(sk)->icsk_af_ops = &dccp_ipv4_af_ops; 1013 inet_csk(sk)->icsk_af_ops = &dccp_ipv4_af_ops;
1014 }
1015
1004 return err; 1016 return err;
1005} 1017}
1006 1018
@@ -1087,48 +1099,29 @@ static struct inet_protosw dccp_v4_protosw = {
1087 .flags = INET_PROTOSW_ICSK, 1099 .flags = INET_PROTOSW_ICSK,
1088}; 1100};
1089 1101
1090/* 1102static char dccp_v4_ctl_socket_err_msg[] __initdata =
1091 * This is the global socket data structure used for responding to
1092 * the Out-of-the-blue (OOTB) packets. A control sock will be created
1093 * for this socket at the initialization time.
1094 */
1095struct socket *dccp_ctl_socket;
1096
1097static char dccp_ctl_socket_err_msg[] __initdata =
1098 KERN_ERR "DCCP: Failed to create the control socket.\n"; 1103 KERN_ERR "DCCP: Failed to create the control socket.\n";
1099 1104
1100static int __init dccp_ctl_sock_init(void) 1105static int __init dccp_v4_ctl_sock_init(void)
1101{ 1106{
1102 int rc = sock_create_kern(PF_INET, SOCK_DCCP, IPPROTO_DCCP, 1107 int rc = sock_create_kern(PF_INET, SOCK_DCCP, IPPROTO_DCCP,
1103 &dccp_ctl_socket); 1108 &dccp_v4_ctl_socket);
1104 if (rc < 0) 1109 if (rc < 0)
1105 printk(dccp_ctl_socket_err_msg); 1110 printk(dccp_v4_ctl_socket_err_msg);
1106 else { 1111 else {
1107 dccp_ctl_socket->sk->sk_allocation = GFP_ATOMIC; 1112 dccp_v4_ctl_socket->sk->sk_allocation = GFP_ATOMIC;
1108 inet_sk(dccp_ctl_socket->sk)->uc_ttl = -1; 1113 inet_sk(dccp_v4_ctl_socket->sk)->uc_ttl = -1;
1109 1114
1110 /* Unhash it so that IP input processing does not even 1115 /* Unhash it so that IP input processing does not even
1111 * see it, we do not wish this socket to see incoming 1116 * see it, we do not wish this socket to see incoming
1112 * packets. 1117 * packets.
1113 */ 1118 */
1114 dccp_ctl_socket->sk->sk_prot->unhash(dccp_ctl_socket->sk); 1119 dccp_v4_ctl_socket->sk->sk_prot->unhash(dccp_v4_ctl_socket->sk);
1115 } 1120 }
1116 1121
1117 return rc; 1122 return rc;
1118} 1123}
1119 1124
1120#ifdef CONFIG_IP_DCCP_UNLOAD_HACK
1121void dccp_ctl_sock_exit(void)
1122{
1123 if (dccp_ctl_socket != NULL) {
1124 sock_release(dccp_ctl_socket);
1125 dccp_ctl_socket = NULL;
1126 }
1127}
1128
1129EXPORT_SYMBOL_GPL(dccp_ctl_sock_exit);
1130#endif
1131
1132static int __init dccp_v4_init(void) 1125static int __init dccp_v4_init(void)
1133{ 1126{
1134 int err = proto_register(&dccp_v4_prot, 1); 1127 int err = proto_register(&dccp_v4_prot, 1);
@@ -1142,7 +1135,7 @@ static int __init dccp_v4_init(void)
1142 1135
1143 inet_register_protosw(&dccp_v4_protosw); 1136 inet_register_protosw(&dccp_v4_protosw);
1144 1137
1145 err = dccp_ctl_sock_init(); 1138 err = dccp_v4_ctl_sock_init();
1146 if (err) 1139 if (err)
1147 goto out_unregister_protosw; 1140 goto out_unregister_protosw;
1148out: 1141out:
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 904967bf2fe9..3c9f0836404f 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -33,6 +33,9 @@
33#include "dccp.h" 33#include "dccp.h"
34#include "ipv6.h" 34#include "ipv6.h"
35 35
36/* Socket used for sending RSTs and ACKs */
37static struct socket *dccp_v6_ctl_socket;
38
36static void dccp_v6_ctl_send_reset(struct sk_buff *skb); 39static void dccp_v6_ctl_send_reset(struct sk_buff *skb);
37static void dccp_v6_reqsk_send_ack(struct sk_buff *skb, 40static void dccp_v6_reqsk_send_ack(struct sk_buff *skb,
38 struct request_sock *req); 41 struct request_sock *req);
@@ -568,7 +571,7 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
568 /* sk = NULL, but it is safe for now. RST socket required. */ 571 /* sk = NULL, but it is safe for now. RST socket required. */
569 if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) { 572 if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
570 if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) { 573 if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
571 ip6_xmit(NULL, skb, &fl, NULL, 0); 574 ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0);
572 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); 575 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
573 DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS); 576 DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
574 return; 577 return;
@@ -623,7 +626,7 @@ static void dccp_v6_ctl_send_ack(struct sk_buff *rxskb)
623 626
624 if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) { 627 if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
625 if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) { 628 if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
626 ip6_xmit(NULL, skb, &fl, NULL, 0); 629 ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0);
627 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); 630 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
628 return; 631 return;
629 } 632 }
@@ -1146,10 +1149,14 @@ static struct inet_connection_sock_af_ops dccp_ipv6_mapped = {
1146 */ 1149 */
1147static int dccp_v6_init_sock(struct sock *sk) 1150static int dccp_v6_init_sock(struct sock *sk)
1148{ 1151{
1149 int err = dccp_init_sock(sk); 1152 static __u8 dccp_v6_ctl_sock_initialized;
1153 int err = dccp_init_sock(sk, dccp_v6_ctl_sock_initialized);
1150 1154
1151 if (err == 0) 1155 if (err == 0) {
1156 if (unlikely(!dccp_v6_ctl_sock_initialized))
1157 dccp_v6_ctl_sock_initialized = 1;
1152 inet_csk(sk)->icsk_af_ops = &dccp_ipv6_af_ops; 1158 inet_csk(sk)->icsk_af_ops = &dccp_ipv6_af_ops;
1159 }
1153 1160
1154 return err; 1161 return err;
1155} 1162}
@@ -1222,6 +1229,29 @@ static struct inet_protosw dccp_v6_protosw = {
1222 .flags = INET_PROTOSW_ICSK, 1229 .flags = INET_PROTOSW_ICSK,
1223}; 1230};
1224 1231
1232static char dccp_v6_ctl_socket_err_msg[] __initdata =
1233 KERN_ERR "DCCP: Failed to create the control socket.\n";
1234
1235static int __init dccp_v6_ctl_sock_init(void)
1236{
1237 int rc = sock_create_kern(PF_INET6, SOCK_DCCP, IPPROTO_DCCP,
1238 &dccp_v6_ctl_socket);
1239 if (rc < 0)
1240 printk(dccp_v6_ctl_socket_err_msg);
1241 else {
1242 dccp_v6_ctl_socket->sk->sk_allocation = GFP_ATOMIC;
1243 inet_sk(dccp_v6_ctl_socket->sk)->uc_ttl = -1;
1244
1245 /* Unhash it so that IP input processing does not even
1246 * see it, we do not wish this socket to see incoming
1247 * packets.
1248 */
1249 dccp_v6_ctl_socket->sk->sk_prot->unhash(dccp_v6_ctl_socket->sk);
1250 }
1251
1252 return rc;
1253}
1254
1225static int __init dccp_v6_init(void) 1255static int __init dccp_v6_init(void)
1226{ 1256{
1227 int err = proto_register(&dccp_v6_prot, 1); 1257 int err = proto_register(&dccp_v6_prot, 1);
@@ -1234,8 +1264,14 @@ static int __init dccp_v6_init(void)
1234 goto out_unregister_proto; 1264 goto out_unregister_proto;
1235 1265
1236 inet6_register_protosw(&dccp_v6_protosw); 1266 inet6_register_protosw(&dccp_v6_protosw);
1267
1268 if (dccp_v6_ctl_sock_init() != 0)
1269 goto out_unregister_protosw;
1237out: 1270out:
1238 return err; 1271 return err;
1272out_unregister_protosw:
1273 inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
1274 inet6_unregister_protosw(&dccp_v6_protosw);
1239out_unregister_proto: 1275out_unregister_proto:
1240 proto_unregister(&dccp_v6_prot); 1276 proto_unregister(&dccp_v6_prot);
1241 goto out; 1277 goto out;
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index f644c1a23c4d..baccaf35ffbd 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -163,11 +163,10 @@ void dccp_unhash(struct sock *sk)
163 163
164EXPORT_SYMBOL_GPL(dccp_unhash); 164EXPORT_SYMBOL_GPL(dccp_unhash);
165 165
166int dccp_init_sock(struct sock *sk) 166int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
167{ 167{
168 struct dccp_sock *dp = dccp_sk(sk); 168 struct dccp_sock *dp = dccp_sk(sk);
169 struct inet_connection_sock *icsk = inet_csk(sk); 169 struct inet_connection_sock *icsk = inet_csk(sk);
170 static int dccp_ctl_socket_init = 1;
171 170
172 dccp_options_init(&dp->dccps_options); 171 dccp_options_init(&dp->dccps_options);
173 do_gettimeofday(&dp->dccps_epoch); 172 do_gettimeofday(&dp->dccps_epoch);
@@ -179,7 +178,7 @@ int dccp_init_sock(struct sock *sk)
179 * lets leave it here, later the real solution is to do this in a 178 * lets leave it here, later the real solution is to do this in a
180 * setsockopt(CCIDs-I-want/accept). -acme 179 * setsockopt(CCIDs-I-want/accept). -acme
181 */ 180 */
182 if (likely(!dccp_ctl_socket_init)) { 181 if (likely(ctl_sock_initialized)) {
183 int rc = dccp_feat_init(sk); 182 int rc = dccp_feat_init(sk);
184 183
185 if (rc) 184 if (rc)
@@ -211,7 +210,6 @@ int dccp_init_sock(struct sock *sk)
211 /* control socket doesn't need feat nego */ 210 /* control socket doesn't need feat nego */
212 INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending); 211 INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending);
213 INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf); 212 INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf);
214 dccp_ctl_socket_init = 0;
215 } 213 }
216 214
217 dccp_init_xmit_timers(sk); 215 dccp_init_xmit_timers(sk);