#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);
+#include "feat.h"
static int dccp_v4_get_port(struct sock *sk, const unsigned short snum)
{
inet_csk_bind_conflict);
}
-static void dccp_v4_hash(struct sock *sk)
-{
- inet_hash(&dccp_hashinfo, sk);
-}
-
-void dccp_unhash(struct sock *sk)
-{
- inet_unhash(&dccp_hashinfo, sk);
-}
-
-EXPORT_SYMBOL_GPL(dccp_unhash);
-
int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
struct inet_sock *inet = inet_sk(sk);
if (err != 0)
goto failure;
- err = ip_route_newports(&rt, inet->sport, inet->dport, sk);
+ err = ip_route_newports(&rt, IPPROTO_DCCP, inet->sport, inet->dport,
+ sk);
if (err != 0)
goto failure;
skb = dccp_make_response(sk, dst, req);
if (skb != NULL) {
const struct inet_request_sock *ireq = inet_rsk(req);
+ struct dccp_hdr *dh = dccp_hdr(skb);
+ dh->dccph_checksum = dccp_v4_checksum(skb, ireq->loc_addr,
+ ireq->rmt_addr);
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr,
ireq->rmt_addr,
EXPORT_SYMBOL_GPL(dccp_v4_send_check);
-int dccp_v4_send_reset(struct sock *sk, enum dccp_reset_codes code)
-{
- struct sk_buff *skb;
- /*
- * FIXME: what if rebuild_header fails?
- * Should we be doing a rebuild_header here?
- */
- int err = inet_sk_rebuild_header(sk);
-
- if (err != 0)
- return err;
-
- skb = dccp_make_reset(sk, sk->sk_dst_cache, code);
- if (skb != NULL) {
- const struct inet_sock *inet = inet_sk(sk);
-
- memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
- err = ip_build_and_send_pkt(skb, sk,
- inet->saddr, inet->daddr, NULL);
- if (err == NET_XMIT_CN)
- err = 0;
- }
-
- return err;
-}
-
static inline u64 dccp_v4_init_sequence(const struct sock *sk,
const struct sk_buff *skb)
{
struct dccp_sock dp;
struct request_sock *req;
struct dccp_request_sock *dreq;
- const __u32 saddr = skb->nh.iph->saddr;
- const __u32 daddr = skb->nh.iph->daddr;
- const __u32 service = dccp_hdr_request(skb)->dccph_req_service;
+ const __be32 saddr = skb->nh.iph->saddr;
+ const __be32 daddr = skb->nh.iph->daddr;
+ const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
__u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
if (req == NULL)
goto drop;
- /* FIXME: process options */
+ if (dccp_parse_options(sk, skb))
+ goto drop;
dccp_openreq_init(req, &dp, skb);
return sk;
}
-int dccp_v4_checksum(const struct sk_buff *skb, const u32 saddr,
- const u32 daddr)
+int dccp_v4_checksum(const struct sk_buff *skb, const __be32 saddr,
+ const __be32 daddr)
{
const struct dccp_hdr* dh = dccp_hdr(skb);
int checksum_len;
}
static int dccp_v4_verify_checksum(struct sk_buff *skb,
- const u32 saddr, const u32 daddr)
+ const __be32 saddr, const __be32 daddr)
{
struct dccp_hdr *dh = dccp_hdr(skb);
int checksum_len;
if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
goto discard_and_relse;
+ nf_reset(skb);
return sk_receive_skb(sk, skb);
.sockaddr_len = sizeof(struct sockaddr_in),
};
-int dccp_v4_init_sock(struct sock *sk)
+static int dccp_v4_init_sock(struct sock *sk)
{
- struct dccp_sock *dp = dccp_sk(sk);
- struct inet_connection_sock *icsk = inet_csk(sk);
- static int dccp_ctl_socket_init = 1;
-
- dccp_options_init(&dp->dccps_options);
- do_gettimeofday(&dp->dccps_epoch);
-
- if (dp->dccps_options.dccpo_send_ack_vector) {
- dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(DCCP_MAX_ACKVEC_LEN,
- GFP_KERNEL);
- if (dp->dccps_hc_rx_ackvec == NULL)
- return -ENOMEM;
- }
-
- /*
- * FIXME: We're hardcoding the CCID, and doing this at this point makes
- * the listening (master) sock get CCID control blocks, which is not
- * necessary, but for now, to not mess with the test userspace apps,
- * lets leave it here, later the real solution is to do this in a
- * setsockopt(CCIDs-I-want/accept). -acme
- */
- if (likely(!dccp_ctl_socket_init)) {
- dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_rx_ccid,
- sk);
- dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_tx_ccid,
- sk);
- if (dp->dccps_hc_rx_ccid == NULL ||
- dp->dccps_hc_tx_ccid == NULL) {
- ccid_exit(dp->dccps_hc_rx_ccid, sk);
- ccid_exit(dp->dccps_hc_tx_ccid, sk);
- if (dp->dccps_options.dccpo_send_ack_vector) {
- dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
- dp->dccps_hc_rx_ackvec = NULL;
- }
- dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
- return -ENOMEM;
- }
- } else
- dccp_ctl_socket_init = 0;
-
- dccp_init_xmit_timers(sk);
- icsk->icsk_rto = DCCP_TIMEOUT_INIT;
- sk->sk_state = DCCP_CLOSED;
- sk->sk_write_space = dccp_write_space;
- icsk->icsk_af_ops = &dccp_ipv4_af_ops;
- icsk->icsk_sync_mss = dccp_sync_mss;
- dp->dccps_mss_cache = 536;
- dp->dccps_role = DCCP_ROLE_UNDEFINED;
- dp->dccps_service = DCCP_SERVICE_INVALID_VALUE;
+ const int err = dccp_init_sock(sk);
- return 0;
-}
-
-EXPORT_SYMBOL_GPL(dccp_v4_init_sock);
-
-int dccp_v4_destroy_sock(struct sock *sk)
-{
- struct dccp_sock *dp = dccp_sk(sk);
-
- /*
- * DCCP doesn't use sk_write_queue, just sk_send_head
- * for retransmissions
- */
- if (sk->sk_send_head != NULL) {
- kfree_skb(sk->sk_send_head);
- sk->sk_send_head = NULL;
- }
-
- /* Clean up a referenced DCCP bind bucket. */
- if (inet_csk(sk)->icsk_bind_hash != NULL)
- inet_put_port(&dccp_hashinfo, sk);
-
- kfree(dp->dccps_service_list);
- dp->dccps_service_list = NULL;
-
- ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk);
- ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk);
- if (dp->dccps_options.dccpo_send_ack_vector) {
- dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
- dp->dccps_hc_rx_ackvec = NULL;
- }
- ccid_exit(dp->dccps_hc_rx_ccid, sk);
- ccid_exit(dp->dccps_hc_tx_ccid, sk);
- dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
-
- return 0;
+ if (err == 0)
+ inet_csk(sk)->icsk_af_ops = &dccp_ipv4_af_ops;
+ return err;
}
-EXPORT_SYMBOL_GPL(dccp_v4_destroy_sock);
-
static void dccp_v4_reqsk_destructor(struct request_sock *req)
{
kfree(inet_rsk(req)->opt);
.sendmsg = dccp_sendmsg,
.recvmsg = dccp_recvmsg,
.backlog_rcv = dccp_v4_do_rcv,
- .hash = dccp_v4_hash,
+ .hash = dccp_hash,
.unhash = dccp_unhash,
.accept = inet_csk_accept,
.get_port = dccp_v4_get_port,
.shutdown = dccp_shutdown,
- .destroy = dccp_v4_destroy_sock,
+ .destroy = dccp_destroy_sock,
.orphan_count = &dccp_orphan_count,
.max_header = MAX_DCCP_HEADER,
.obj_size = sizeof(struct dccp_sock),