[DCCP] ipv6: Add missing ipv6 control socket
I guess I forgot to add it, nah, now it just works: 18:04:33.274066 IP6 ::1.1476 > ::1.5001: request (service=0) 18:04:33.334482 IP6 ::1.5001 > ::1.1476: reset (code=bad_service_code) Ditched IP_DCCP_UNLOAD_HACK, as now we would have to do it for both IPv6 and IPv4, so I'll come up with another way for freeing the control sockets in upcoming changesets. Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
c25a18ba34
commit
7247887357
@@ -40,15 +40,6 @@ config IP_DCCP_DEBUG
|
|||||||
|
|
||||||
Just say N.
|
Just say N.
|
||||||
|
|
||||||
config IP_DCCP_UNLOAD_HACK
|
|
||||||
depends on IP_DCCP=m && IP_DCCP_CCID3=m
|
|
||||||
bool "DCCP control sock unload hack"
|
|
||||||
---help---
|
|
||||||
Enable this to be able to unload the dccp module when the it
|
|
||||||
has only one refcount held, the control sock one. Just execute
|
|
||||||
"rmmod dccp_ccid3 dccp"
|
|
||||||
|
|
||||||
Just say N.
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
@@ -1211,15 +1211,6 @@ module_init(ccid3_module_init);
|
|||||||
|
|
||||||
static __exit void ccid3_module_exit(void)
|
static __exit void ccid3_module_exit(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_IP_DCCP_UNLOAD_HACK
|
|
||||||
/*
|
|
||||||
* Hack to use while developing, so that we get rid of the control
|
|
||||||
* sock, that is what keeps a refcount on dccp.ko -acme
|
|
||||||
*/
|
|
||||||
extern void dccp_ctl_sock_exit(void);
|
|
||||||
|
|
||||||
dccp_ctl_sock_exit();
|
|
||||||
#endif
|
|
||||||
ccid_unregister(&ccid3);
|
ccid_unregister(&ccid3);
|
||||||
|
|
||||||
if (ccid3_tx_hist != NULL) {
|
if (ccid3_tx_hist != NULL) {
|
||||||
|
@@ -177,7 +177,7 @@ extern int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
|
|||||||
extern int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
|
extern int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
|
||||||
const struct dccp_hdr *dh, const unsigned len);
|
const struct dccp_hdr *dh, const unsigned len);
|
||||||
|
|
||||||
extern int dccp_init_sock(struct sock *sk);
|
extern int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized);
|
||||||
extern int dccp_destroy_sock(struct sock *sk);
|
extern int dccp_destroy_sock(struct sock *sk);
|
||||||
|
|
||||||
extern void dccp_close(struct sock *sk, long timeout);
|
extern void dccp_close(struct sock *sk, long timeout);
|
||||||
@@ -337,8 +337,6 @@ extern void dccp_insert_option(struct sock *sk, struct sk_buff *skb,
|
|||||||
unsigned char option,
|
unsigned char option,
|
||||||
const void *value, unsigned char len);
|
const void *value, unsigned char len);
|
||||||
|
|
||||||
extern struct socket *dccp_ctl_socket;
|
|
||||||
|
|
||||||
extern void dccp_timestamp(const struct sock *sk, struct timeval *tv);
|
extern void dccp_timestamp(const struct sock *sk, struct timeval *tv);
|
||||||
|
|
||||||
static inline suseconds_t timeval_usecs(const struct timeval *tv)
|
static inline suseconds_t timeval_usecs(const struct timeval *tv)
|
||||||
|
@@ -32,6 +32,13 @@
|
|||||||
#include "dccp.h"
|
#include "dccp.h"
|
||||||
#include "feat.h"
|
#include "feat.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the global socket data structure used for responding to
|
||||||
|
* the Out-of-the-blue (OOTB) packets. A control sock will be created
|
||||||
|
* for this socket at the initialization time.
|
||||||
|
*/
|
||||||
|
static struct socket *dccp_v4_ctl_socket;
|
||||||
|
|
||||||
static int dccp_v4_get_port(struct sock *sk, const unsigned short snum)
|
static int dccp_v4_get_port(struct sock *sk, const unsigned short snum)
|
||||||
{
|
{
|
||||||
return inet_csk_get_port(&dccp_hashinfo, sk, snum,
|
return inet_csk_get_port(&dccp_hashinfo, sk, snum,
|
||||||
@@ -226,11 +233,11 @@ static void dccp_v4_ctl_send_ack(struct sk_buff *rxskb)
|
|||||||
dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
|
dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
|
||||||
DCCP_SKB_CB(rxskb)->dccpd_seq);
|
DCCP_SKB_CB(rxskb)->dccpd_seq);
|
||||||
|
|
||||||
bh_lock_sock(dccp_ctl_socket->sk);
|
bh_lock_sock(dccp_v4_ctl_socket->sk);
|
||||||
err = ip_build_and_send_pkt(skb, dccp_ctl_socket->sk,
|
err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
|
||||||
rxskb->nh.iph->daddr,
|
rxskb->nh.iph->daddr,
|
||||||
rxskb->nh.iph->saddr, NULL);
|
rxskb->nh.iph->saddr, NULL);
|
||||||
bh_unlock_sock(dccp_ctl_socket->sk);
|
bh_unlock_sock(dccp_v4_ctl_socket->sk);
|
||||||
|
|
||||||
if (err == NET_XMIT_CN || err == 0) {
|
if (err == NET_XMIT_CN || err == 0) {
|
||||||
DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
|
DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
|
||||||
@@ -704,7 +711,7 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb)
|
|||||||
if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL)
|
if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dst = dccp_v4_route_skb(dccp_ctl_socket->sk, rxskb);
|
dst = dccp_v4_route_skb(dccp_v4_ctl_socket->sk, rxskb);
|
||||||
if (dst == NULL)
|
if (dst == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -741,11 +748,11 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb)
|
|||||||
dh->dccph_checksum = dccp_v4_checksum(skb, rxskb->nh.iph->saddr,
|
dh->dccph_checksum = dccp_v4_checksum(skb, rxskb->nh.iph->saddr,
|
||||||
rxskb->nh.iph->daddr);
|
rxskb->nh.iph->daddr);
|
||||||
|
|
||||||
bh_lock_sock(dccp_ctl_socket->sk);
|
bh_lock_sock(dccp_v4_ctl_socket->sk);
|
||||||
err = ip_build_and_send_pkt(skb, dccp_ctl_socket->sk,
|
err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
|
||||||
rxskb->nh.iph->daddr,
|
rxskb->nh.iph->daddr,
|
||||||
rxskb->nh.iph->saddr, NULL);
|
rxskb->nh.iph->saddr, NULL);
|
||||||
bh_unlock_sock(dccp_ctl_socket->sk);
|
bh_unlock_sock(dccp_v4_ctl_socket->sk);
|
||||||
|
|
||||||
if (err == NET_XMIT_CN || err == 0) {
|
if (err == NET_XMIT_CN || err == 0) {
|
||||||
DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
|
DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
|
||||||
@@ -997,10 +1004,15 @@ static struct inet_connection_sock_af_ops dccp_ipv4_af_ops = {
|
|||||||
|
|
||||||
static int dccp_v4_init_sock(struct sock *sk)
|
static int dccp_v4_init_sock(struct sock *sk)
|
||||||
{
|
{
|
||||||
const int err = dccp_init_sock(sk);
|
static __u8 dccp_v4_ctl_sock_initialized;
|
||||||
|
int err = dccp_init_sock(sk, dccp_v4_ctl_sock_initialized);
|
||||||
|
|
||||||
if (err == 0)
|
if (err == 0) {
|
||||||
|
if (unlikely(!dccp_v4_ctl_sock_initialized))
|
||||||
|
dccp_v4_ctl_sock_initialized = 1;
|
||||||
inet_csk(sk)->icsk_af_ops = &dccp_ipv4_af_ops;
|
inet_csk(sk)->icsk_af_ops = &dccp_ipv4_af_ops;
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1087,48 +1099,29 @@ static struct inet_protosw dccp_v4_protosw = {
|
|||||||
.flags = INET_PROTOSW_ICSK,
|
.flags = INET_PROTOSW_ICSK,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
static char dccp_v4_ctl_socket_err_msg[] __initdata =
|
||||||
* This is the global socket data structure used for responding to
|
|
||||||
* the Out-of-the-blue (OOTB) packets. A control sock will be created
|
|
||||||
* for this socket at the initialization time.
|
|
||||||
*/
|
|
||||||
struct socket *dccp_ctl_socket;
|
|
||||||
|
|
||||||
static char dccp_ctl_socket_err_msg[] __initdata =
|
|
||||||
KERN_ERR "DCCP: Failed to create the control socket.\n";
|
KERN_ERR "DCCP: Failed to create the control socket.\n";
|
||||||
|
|
||||||
static int __init dccp_ctl_sock_init(void)
|
static int __init dccp_v4_ctl_sock_init(void)
|
||||||
{
|
{
|
||||||
int rc = sock_create_kern(PF_INET, SOCK_DCCP, IPPROTO_DCCP,
|
int rc = sock_create_kern(PF_INET, SOCK_DCCP, IPPROTO_DCCP,
|
||||||
&dccp_ctl_socket);
|
&dccp_v4_ctl_socket);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
printk(dccp_ctl_socket_err_msg);
|
printk(dccp_v4_ctl_socket_err_msg);
|
||||||
else {
|
else {
|
||||||
dccp_ctl_socket->sk->sk_allocation = GFP_ATOMIC;
|
dccp_v4_ctl_socket->sk->sk_allocation = GFP_ATOMIC;
|
||||||
inet_sk(dccp_ctl_socket->sk)->uc_ttl = -1;
|
inet_sk(dccp_v4_ctl_socket->sk)->uc_ttl = -1;
|
||||||
|
|
||||||
/* Unhash it so that IP input processing does not even
|
/* Unhash it so that IP input processing does not even
|
||||||
* see it, we do not wish this socket to see incoming
|
* see it, we do not wish this socket to see incoming
|
||||||
* packets.
|
* packets.
|
||||||
*/
|
*/
|
||||||
dccp_ctl_socket->sk->sk_prot->unhash(dccp_ctl_socket->sk);
|
dccp_v4_ctl_socket->sk->sk_prot->unhash(dccp_v4_ctl_socket->sk);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_IP_DCCP_UNLOAD_HACK
|
|
||||||
void dccp_ctl_sock_exit(void)
|
|
||||||
{
|
|
||||||
if (dccp_ctl_socket != NULL) {
|
|
||||||
sock_release(dccp_ctl_socket);
|
|
||||||
dccp_ctl_socket = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(dccp_ctl_sock_exit);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int __init dccp_v4_init(void)
|
static int __init dccp_v4_init(void)
|
||||||
{
|
{
|
||||||
int err = proto_register(&dccp_v4_prot, 1);
|
int err = proto_register(&dccp_v4_prot, 1);
|
||||||
@@ -1142,7 +1135,7 @@ static int __init dccp_v4_init(void)
|
|||||||
|
|
||||||
inet_register_protosw(&dccp_v4_protosw);
|
inet_register_protosw(&dccp_v4_protosw);
|
||||||
|
|
||||||
err = dccp_ctl_sock_init();
|
err = dccp_v4_ctl_sock_init();
|
||||||
if (err)
|
if (err)
|
||||||
goto out_unregister_protosw;
|
goto out_unregister_protosw;
|
||||||
out:
|
out:
|
||||||
|
@@ -33,6 +33,9 @@
|
|||||||
#include "dccp.h"
|
#include "dccp.h"
|
||||||
#include "ipv6.h"
|
#include "ipv6.h"
|
||||||
|
|
||||||
|
/* Socket used for sending RSTs and ACKs */
|
||||||
|
static struct socket *dccp_v6_ctl_socket;
|
||||||
|
|
||||||
static void dccp_v6_ctl_send_reset(struct sk_buff *skb);
|
static void dccp_v6_ctl_send_reset(struct sk_buff *skb);
|
||||||
static void dccp_v6_reqsk_send_ack(struct sk_buff *skb,
|
static void dccp_v6_reqsk_send_ack(struct sk_buff *skb,
|
||||||
struct request_sock *req);
|
struct request_sock *req);
|
||||||
@@ -568,7 +571,7 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
|
|||||||
/* sk = NULL, but it is safe for now. RST socket required. */
|
/* sk = NULL, but it is safe for now. RST socket required. */
|
||||||
if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
|
if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
|
||||||
if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
|
if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
|
||||||
ip6_xmit(NULL, skb, &fl, NULL, 0);
|
ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0);
|
||||||
DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
|
DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
|
||||||
DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
|
DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
|
||||||
return;
|
return;
|
||||||
@@ -623,7 +626,7 @@ static void dccp_v6_ctl_send_ack(struct sk_buff *rxskb)
|
|||||||
|
|
||||||
if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
|
if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
|
||||||
if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
|
if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
|
||||||
ip6_xmit(NULL, skb, &fl, NULL, 0);
|
ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0);
|
||||||
DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
|
DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1146,10 +1149,14 @@ static struct inet_connection_sock_af_ops dccp_ipv6_mapped = {
|
|||||||
*/
|
*/
|
||||||
static int dccp_v6_init_sock(struct sock *sk)
|
static int dccp_v6_init_sock(struct sock *sk)
|
||||||
{
|
{
|
||||||
int err = dccp_init_sock(sk);
|
static __u8 dccp_v6_ctl_sock_initialized;
|
||||||
|
int err = dccp_init_sock(sk, dccp_v6_ctl_sock_initialized);
|
||||||
|
|
||||||
if (err == 0)
|
if (err == 0) {
|
||||||
|
if (unlikely(!dccp_v6_ctl_sock_initialized))
|
||||||
|
dccp_v6_ctl_sock_initialized = 1;
|
||||||
inet_csk(sk)->icsk_af_ops = &dccp_ipv6_af_ops;
|
inet_csk(sk)->icsk_af_ops = &dccp_ipv6_af_ops;
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -1222,6 +1229,29 @@ static struct inet_protosw dccp_v6_protosw = {
|
|||||||
.flags = INET_PROTOSW_ICSK,
|
.flags = INET_PROTOSW_ICSK,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static char dccp_v6_ctl_socket_err_msg[] __initdata =
|
||||||
|
KERN_ERR "DCCP: Failed to create the control socket.\n";
|
||||||
|
|
||||||
|
static int __init dccp_v6_ctl_sock_init(void)
|
||||||
|
{
|
||||||
|
int rc = sock_create_kern(PF_INET6, SOCK_DCCP, IPPROTO_DCCP,
|
||||||
|
&dccp_v6_ctl_socket);
|
||||||
|
if (rc < 0)
|
||||||
|
printk(dccp_v6_ctl_socket_err_msg);
|
||||||
|
else {
|
||||||
|
dccp_v6_ctl_socket->sk->sk_allocation = GFP_ATOMIC;
|
||||||
|
inet_sk(dccp_v6_ctl_socket->sk)->uc_ttl = -1;
|
||||||
|
|
||||||
|
/* Unhash it so that IP input processing does not even
|
||||||
|
* see it, we do not wish this socket to see incoming
|
||||||
|
* packets.
|
||||||
|
*/
|
||||||
|
dccp_v6_ctl_socket->sk->sk_prot->unhash(dccp_v6_ctl_socket->sk);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static int __init dccp_v6_init(void)
|
static int __init dccp_v6_init(void)
|
||||||
{
|
{
|
||||||
int err = proto_register(&dccp_v6_prot, 1);
|
int err = proto_register(&dccp_v6_prot, 1);
|
||||||
@@ -1234,8 +1264,14 @@ static int __init dccp_v6_init(void)
|
|||||||
goto out_unregister_proto;
|
goto out_unregister_proto;
|
||||||
|
|
||||||
inet6_register_protosw(&dccp_v6_protosw);
|
inet6_register_protosw(&dccp_v6_protosw);
|
||||||
|
|
||||||
|
if (dccp_v6_ctl_sock_init() != 0)
|
||||||
|
goto out_unregister_protosw;
|
||||||
out:
|
out:
|
||||||
return err;
|
return err;
|
||||||
|
out_unregister_protosw:
|
||||||
|
inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
|
||||||
|
inet6_unregister_protosw(&dccp_v6_protosw);
|
||||||
out_unregister_proto:
|
out_unregister_proto:
|
||||||
proto_unregister(&dccp_v6_prot);
|
proto_unregister(&dccp_v6_prot);
|
||||||
goto out;
|
goto out;
|
||||||
|
@@ -163,11 +163,10 @@ void dccp_unhash(struct sock *sk)
|
|||||||
|
|
||||||
EXPORT_SYMBOL_GPL(dccp_unhash);
|
EXPORT_SYMBOL_GPL(dccp_unhash);
|
||||||
|
|
||||||
int dccp_init_sock(struct sock *sk)
|
int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
|
||||||
{
|
{
|
||||||
struct dccp_sock *dp = dccp_sk(sk);
|
struct dccp_sock *dp = dccp_sk(sk);
|
||||||
struct inet_connection_sock *icsk = inet_csk(sk);
|
struct inet_connection_sock *icsk = inet_csk(sk);
|
||||||
static int dccp_ctl_socket_init = 1;
|
|
||||||
|
|
||||||
dccp_options_init(&dp->dccps_options);
|
dccp_options_init(&dp->dccps_options);
|
||||||
do_gettimeofday(&dp->dccps_epoch);
|
do_gettimeofday(&dp->dccps_epoch);
|
||||||
@@ -179,7 +178,7 @@ int dccp_init_sock(struct sock *sk)
|
|||||||
* lets leave it here, later the real solution is to do this in a
|
* lets leave it here, later the real solution is to do this in a
|
||||||
* setsockopt(CCIDs-I-want/accept). -acme
|
* setsockopt(CCIDs-I-want/accept). -acme
|
||||||
*/
|
*/
|
||||||
if (likely(!dccp_ctl_socket_init)) {
|
if (likely(ctl_sock_initialized)) {
|
||||||
int rc = dccp_feat_init(sk);
|
int rc = dccp_feat_init(sk);
|
||||||
|
|
||||||
if (rc)
|
if (rc)
|
||||||
@@ -211,7 +210,6 @@ int dccp_init_sock(struct sock *sk)
|
|||||||
/* control socket doesn't need feat nego */
|
/* control socket doesn't need feat nego */
|
||||||
INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending);
|
INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending);
|
||||||
INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf);
|
INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf);
|
||||||
dccp_ctl_socket_init = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dccp_init_xmit_timers(sk);
|
dccp_init_xmit_timers(sk);
|
||||||
|
Reference in New Issue
Block a user