int rst_restore_synwait_queue(struct sock *sk, struct cpt_sock_image *si, loff_t pos, struct cpt_context *ctx) { int err; loff_t end = pos + si->cpt_next; pos += si->cpt_hdrlen; lock_sock(sk); while (pos < end) { struct cpt_openreq_image oi; err = rst_sock_attr(&pos, sk, ctx); if (!err) continue; if (err < 0) goto out; err = rst_get_object(CPT_OBJ_OPENREQ, pos, &oi, ctx); if (err) goto out; if (oi.cpt_object == CPT_OBJ_OPENREQ) { struct request_sock *req; if (oi.cpt_family == AF_INET6 && sk->sk_family != AF_INET6) /* related to non initialized cpt_family bug */ goto next; req = rst_reqsk_alloc(oi.cpt_family); if (IS_ERR(req)) { release_sock(sk); return PTR_ERR(req); } if (req == NULL) { release_sock(sk); return -ENOMEM; } tcp_rsk(req)->rcv_isn = oi.cpt_rcv_isn; tcp_rsk(req)->snt_isn = oi.cpt_snt_isn; inet_rsk(req)->rmt_port = oi.cpt_rmt_port; req->mss = oi.cpt_mss; req->retrans = oi.cpt_retrans; inet_rsk(req)->snd_wscale = oi.cpt_snd_wscale; inet_rsk(req)->rcv_wscale = oi.cpt_rcv_wscale; inet_rsk(req)->tstamp_ok = oi.cpt_tstamp_ok; inet_rsk(req)->sack_ok = oi.cpt_sack_ok; inet_rsk(req)->wscale_ok = oi.cpt_wscale_ok; inet_rsk(req)->ecn_ok = oi.cpt_ecn_ok; inet_rsk(req)->acked = oi.cpt_acked; inet_rsk(req)->opt = NULL; req->window_clamp = oi.cpt_window_clamp; req->rcv_wnd = oi.cpt_rcv_wnd; req->ts_recent = oi.cpt_ts_recent; req->expires = jiffies_import(oi.cpt_expires); req->sk = NULL; req->secid = 0; req->peer_secid = 0; if (oi.cpt_family == AF_INET6) { #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) inet6_rsk(req)->pktopts = NULL; memcpy(&inet6_rsk(req)->loc_addr, oi.cpt_loc_addr, 16); memcpy(&inet6_rsk(req)->rmt_addr, oi.cpt_rmt_addr, 16); inet6_rsk(req)->iif = oi.cpt_iif; inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); #endif } else { memcpy(&inet_rsk(req)->loc_addr, oi.cpt_loc_addr, 4); memcpy(&inet_rsk(req)->rmt_addr, oi.cpt_rmt_addr, 4); inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); } } next: pos += oi.cpt_next; } err = 0; out: release_sock(sk); return err; }
static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) { struct request_sock *req; struct dccp_request_sock *dreq; struct inet_request_sock *ireq; struct ipv6_pinfo *np = inet6_sk(sk); const __be32 service = dccp_hdr_request(skb)->dccph_req_service; struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); if (skb->protocol == htons(ETH_P_IP)) return dccp_v4_conn_request(sk, skb); if (!ipv6_unicast_destination(skb)) return 0; /* discard, don't send a reset here */ if (dccp_bad_service_code(sk, service)) { dcb->dccpd_reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE; goto drop; } /* * There are no SYN attacks on IPv6, yet... */ dcb->dccpd_reset_code = DCCP_RESET_CODE_TOO_BUSY; if (inet_csk_reqsk_queue_is_full(sk)) goto drop; if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) goto drop; req = inet6_reqsk_alloc(&dccp6_request_sock_ops); if (req == NULL) goto drop; if (dccp_reqsk_init(req, dccp_sk(sk), skb)) goto drop_and_free; dreq = dccp_rsk(req); if (dccp_parse_options(sk, dreq, skb)) goto drop_and_free; if (security_inet_conn_request(sk, skb, req)) goto drop_and_free; ireq = inet_rsk(req); ireq->ir_v6_rmt_addr = ipv6_hdr(skb)->saddr; ireq->ir_v6_loc_addr = ipv6_hdr(skb)->daddr; if (ipv6_opt_accepted(sk, skb) || np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) { atomic_inc(&skb->users); ireq->pktopts = skb; } ireq->ir_iif = sk->sk_bound_dev_if; /* So that link locals have meaning */ if (!sk->sk_bound_dev_if && ipv6_addr_type(&ireq->ir_v6_rmt_addr) & IPV6_ADDR_LINKLOCAL) ireq->ir_iif = inet6_iif(skb); /* * Step 3: Process LISTEN state * * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie * * Setting S.SWL/S.SWH to is deferred to dccp_create_openreq_child(). */ dreq->dreq_isr = dcb->dccpd_seq; dreq->dreq_gsr = dreq->dreq_isr; dreq->dreq_iss = dccp_v6_init_sequence(skb); dreq->dreq_gss = dreq->dreq_iss; dreq->dreq_service = service; if (dccp_v6_send_response(sk, req)) goto drop_and_free; inet6_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT); return 0; drop_and_free: reqsk_free(req); drop: DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS); return -1; }