static int generic_restore_queues(struct sock *sk, struct cpt_sock_image *si, loff_t pos, struct cpt_context *ctx) { loff_t endpos; pos = pos + si->cpt_hdrlen; endpos = pos + si->cpt_next; while (pos < endpos) { struct sk_buff *skb; __u32 type; skb = rst_skb(sk, &pos, NULL, &type, ctx); if (IS_ERR(skb)) { if (PTR_ERR(skb) == -EINVAL) { int err; err = rst_sock_attr(&pos, sk, ctx); if (err) return err; } return PTR_ERR(skb); } if (type == CPT_SKB_RQ) { skb_set_owner_r(skb, sk); skb_queue_tail(&sk->sk_receive_queue, skb); } else { wprintk_ctx("strange socket queue type %u\n", type); kfree_skb(skb); } } return 0; }
static int restore_unix_rqueue(struct sock *sk, struct cpt_sock_image *si, loff_t pos, struct cpt_context *ctx) { loff_t endpos; pos = pos + si->cpt_hdrlen; endpos = pos + si->cpt_next; while (pos < endpos) { struct sk_buff *skb; struct sock *owner_sk; __u32 owner; skb = rst_skb(sk, &pos, &owner, NULL, ctx); if (IS_ERR(skb)) { if (PTR_ERR(skb) == -EINVAL) { int err; err = rst_sock_attr(&pos, sk, ctx); if (err) return err; } return PTR_ERR(skb); } owner_sk = unix_peer(sk); if (owner != -1) { cpt_object_t *pobj; pobj = lookup_cpt_obj_byindex(CPT_OBJ_SOCKET, owner, ctx); if (pobj == NULL) { eprintk_ctx("orphan af_unix skb?\n"); kfree_skb(skb); continue; } owner_sk = pobj->o_obj; } if (owner_sk == NULL) { dprintk_ctx("orphan af_unix skb 2?\n"); kfree_skb(skb); continue; } skb_set_owner_w(skb, owner_sk); if (UNIXCB(skb).fp) skb->destructor = unix_destruct_fds; skb_queue_tail(&sk->sk_receive_queue, skb); if (sk->sk_state == TCP_LISTEN) { struct socket *sock = skb->sk->sk_socket; if (sock == NULL) BUG(); if (sock->file) BUG(); skb->sk->sk_socket = NULL; skb->sk->sk_sleep = NULL; sock->sk = NULL; sock_release(sock); } } return 0; }
static int restore_queues(struct sock *sk, struct cpt_sock_image *si, loff_t pos, struct cpt_context *ctx) { loff_t endpos; endpos = pos + si->cpt_next; pos = pos + si->cpt_hdrlen; while (pos < endpos) { struct sk_buff *skb; __u32 type; int err; err = rst_sock_attr(&pos, sk, ctx); if (!err) continue; if (err < 0) return err; skb = rst_skb(sk, &pos, NULL, &type, ctx); if (IS_ERR(skb)) return PTR_ERR(skb); if (sk->sk_type == SOCK_STREAM) { if (type == CPT_SKB_RQ) { skb_set_owner_r(skb, sk); ub_tcprcvbuf_charge_forced(sk, skb); skb_queue_tail(&sk->sk_receive_queue, skb); } else if (type == CPT_SKB_OFOQ) { struct tcp_sock *tp = tcp_sk(sk); skb_set_owner_r(skb, sk); ub_tcprcvbuf_charge_forced(sk, skb); skb_queue_tail(&tp->out_of_order_queue, skb); } else if (type == CPT_SKB_WQ) { sk->sk_wmem_queued += skb->truesize; sk->sk_forward_alloc -= skb->truesize; ub_tcpsndbuf_charge_forced(sk, skb); skb_queue_tail(&sk->sk_write_queue, skb); } else { wprintk_ctx("strange stream queue type %u\n", type); kfree_skb(skb); } } else { if (type == CPT_SKB_RQ) { skb_set_owner_r(skb, sk); skb_queue_tail(&sk->sk_receive_queue, skb); } else if (type == CPT_SKB_WQ) { struct inet_sock *inet = inet_sk(sk); if (inet->cork.fragsize) { skb_set_owner_w(skb, sk); skb_queue_tail(&sk->sk_write_queue, skb); } else { eprintk_ctx("cork skb is dropped\n"); kfree_skb(skb); } } else { wprintk_ctx("strange dgram queue type %u\n", type); kfree_skb(skb); } } } return 0; }
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; }