Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 72478873 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo Committed by David S. Miller
Browse files

[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: default avatarArnaldo Carvalho de Melo <acme@mandriva.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c25a18ba
Loading
Loading
Loading
Loading
+0 −9
Original line number Diff line number Diff line
@@ -40,15 +40,6 @@ config IP_DCCP_DEBUG

	  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
+0 −9
Original line number Diff line number Diff line
@@ -1211,15 +1211,6 @@ module_init(ccid3_module_init);

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);

	if (ccid3_tx_hist != NULL) {
+1 −3
Original line number Diff line number Diff line
@@ -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,
				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 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,
			       const void *value, unsigned char len);

extern struct socket *dccp_ctl_socket;

extern void dccp_timestamp(const struct sock *sk, struct timeval *tv);

static inline suseconds_t timeval_usecs(const struct timeval *tv)
+29 −36
Original line number Diff line number Diff line
@@ -32,6 +32,13 @@
#include "dccp.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)
{
	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_SKB_CB(rxskb)->dccpd_seq);

	bh_lock_sock(dccp_ctl_socket->sk);
	err = ip_build_and_send_pkt(skb, dccp_ctl_socket->sk,
	bh_lock_sock(dccp_v4_ctl_socket->sk);
	err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
				    rxskb->nh.iph->daddr,
				    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) {
		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)
		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)
		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,
					      rxskb->nh.iph->daddr);

	bh_lock_sock(dccp_ctl_socket->sk);
	err = ip_build_and_send_pkt(skb, dccp_ctl_socket->sk,
	bh_lock_sock(dccp_v4_ctl_socket->sk);
	err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
				    rxskb->nh.iph->daddr,
				    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) {
		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)
{
	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;
	}

	return err;
}

@@ -1087,48 +1099,29 @@ static struct inet_protosw dccp_v4_protosw = {
	.flags		= INET_PROTOSW_ICSK,
};

/*
 * 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 =
static char dccp_v4_ctl_socket_err_msg[] __initdata =
	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,
				  &dccp_ctl_socket);
				  &dccp_v4_ctl_socket);
	if (rc < 0)
		printk(dccp_ctl_socket_err_msg);
		printk(dccp_v4_ctl_socket_err_msg);
	else {
		dccp_ctl_socket->sk->sk_allocation = GFP_ATOMIC;
		inet_sk(dccp_ctl_socket->sk)->uc_ttl = -1;
		dccp_v4_ctl_socket->sk->sk_allocation = GFP_ATOMIC;
		inet_sk(dccp_v4_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_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;
}

#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)
{
	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);

	err = dccp_ctl_sock_init();
	err = dccp_v4_ctl_sock_init();
	if (err)
		goto out_unregister_protosw;
out:
+40 −4
Original line number Diff line number Diff line
@@ -33,6 +33,9 @@
#include "dccp.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_reqsk_send_ack(struct sk_buff *skb,
				   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. */
	if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
		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_OUTRSTS);
			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 (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);
			return;
		}
@@ -1146,10 +1149,14 @@ static struct inet_connection_sock_af_ops dccp_ipv6_mapped = {
 */
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;
	}

	return err;
}
@@ -1222,6 +1229,29 @@ static struct inet_protosw dccp_v6_protosw = {
	.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)
{
	int err = proto_register(&dccp_v6_prot, 1);
@@ -1234,8 +1264,14 @@ static int __init dccp_v6_init(void)
		goto out_unregister_proto;

	inet6_register_protosw(&dccp_v6_protosw);

	if (dccp_v6_ctl_sock_init() != 0)
		goto out_unregister_protosw;
out:
	return err;
out_unregister_protosw:
	inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
	inet6_unregister_protosw(&dccp_v6_protosw);
out_unregister_proto:
	proto_unregister(&dccp_v6_prot);
	goto out;
Loading