/*
* net/dccp/ipv4.c
*
* An implementation of the DCCP protocol
* Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/config.h>
#include <linux/dccp.h>
#include <linux/icmp.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/random.h>
#include <net/icmp.h>
#include <net/inet_hashtables.h>
#include <net/sock.h>
#include <net/tcp_states.h>
#include <net/xfrm.h>
#include "ackvec.h"
#include "ccid.h"
#include "dccp.h"
struct inet_hashinfo __cacheline_aligned dccp_hashinfo = {
.lhash_lock = RW_LOCK_UNLOCKED,
.lhash_users = ATOMIC_INIT(0),
.lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(dccp_hashinfo.lhash_wait),
};
EXPORT_SYMBOL_GPL(dccp_hashinfo);
static int dccp_v4_get_port(struct sock *sk, const unsigned short snum)
{
return inet_csk_get_port(&dccp_hashinfo, sk, snum,
inet_csk_bind_conflict);
}
static void dccp_v4_hash(struct sock *sk)
{
inet_hash(&dccp_hashinfo, sk);
}
static void dccp_v4_unhash(struct sock *sk)
{
inet_unhash(&dccp_hashinfo, sk);
}
/* called with local bh disabled */
static int __dccp_v4_check_established(struct sock *sk, const __u16 lport,
struct inet_timewait_sock **twp)
{
struct inet_sock *inet = inet_sk(sk);
const u32 daddr = inet->rcv_saddr;
const u32 saddr = inet->daddr;
const int dif = sk->sk_bound_dev_if;
INET_ADDR_COOKIE(acookie, saddr, daddr)
const __u32 ports = INET_COMBINED_PORTS(inet->dport, lport);
unsigned int hash = inet_ehashfn(daddr, lport, saddr, inet->dport);
struct inet_ehash_bucket *head = inet_ehash_bucket(&dccp_hashinfo, hash);
const struct sock *sk2;
const struct hlist_node *node;
struct inet_timewait_sock *tw;
prefetch(head->chain.first);
write_lock(&head->lock);
/* Check TIME-WAIT sockets first. */
sk_for_each(sk2