Exemple #1
0
int cpt_dump_link(struct cpt_context * ctx)
{
	struct net *net = get_exec_env()->ve_netns;
	struct net_device *dev;

	cpt_open_section(ctx, CPT_SECT_NET_DEVICE);
	for_each_netdev(net, dev) {
		struct cpt_netdev_image v;
		struct cpt_hwaddr_image hw;
		loff_t saved_obj;

		if (dev->netdev_ops->ndo_cpt == NULL) {
			eprintk_ctx("unsupported netdev %s\n", dev->name);
			cpt_close_section(ctx);
			return -EBUSY;
		}

		cpt_open_object(NULL, ctx);

		v.cpt_next = CPT_NULL;
		v.cpt_object = CPT_OBJ_NET_DEVICE;
		v.cpt_hdrlen = sizeof(v);
		v.cpt_content = CPT_CONTENT_ARRAY;

		v.cpt_index = dev->ifindex;
		v.cpt_flags = dev->flags;
		memcpy(v.cpt_name, dev->name, IFNAMSIZ);
		ctx->write(&v, sizeof(v), ctx);

		cpt_push_object(&saved_obj, ctx);

		cpt_open_object(NULL, ctx);
		dev->netdev_ops->ndo_cpt(dev, &cpt_ops, ctx);

		/* Dump hardware address */
		cpt_open_object(NULL, ctx);
		hw.cpt_next = CPT_NULL;
		hw.cpt_object = CPT_OBJ_NET_HWADDR;
		hw.cpt_hdrlen = sizeof(hw);
		hw.cpt_content = CPT_CONTENT_VOID;

		if (dev->dev_addrs.count != 1) {
			eprintk_ctx("multiple hwaddrs on %s\n", dev->name);
			return -EINVAL;
		}

		BUILD_BUG_ON(sizeof(hw.cpt_dev_addr) != MAX_ADDR_LEN);
		memcpy(hw.cpt_dev_addr, dev->dev_addr, sizeof(hw.cpt_dev_addr));
		ctx->write(&hw, sizeof(hw), ctx);
		cpt_close_object(ctx);
		
		cpt_dump_netstats(dev, ctx);

		cpt_pop_object(&saved_obj, ctx);

		cpt_close_object(ctx);
	}
	cpt_close_section(ctx);
	return 0;
}
Exemple #2
0
/* Find slave/master tty in image, when we already know master/slave.
 * It might be optimized, of course. */
static loff_t find_pty_pair(struct tty_struct *stty, loff_t pos, struct cpt_tty_image *pi, struct cpt_context *ctx)
{
	int err;
	loff_t sec = ctx->sections[CPT_SECT_TTY];
	loff_t endsec;
	struct cpt_section_hdr h;
	struct cpt_tty_image *pibuf;

	err = ctx->pread(&h, sizeof(h), ctx, sec);
	if (err)
		return CPT_NULL;
	if (h.cpt_section != CPT_SECT_TTY || h.cpt_hdrlen < sizeof(h))
		return CPT_NULL;
	pibuf = kmalloc(sizeof(*pibuf), GFP_KERNEL);
	if (pibuf == NULL) {
		eprintk_ctx("cannot allocate buffer\n");
		return CPT_NULL;
	}
	endsec = sec + h.cpt_next;
	sec += h.cpt_hdrlen;
	while (sec < endsec) {
		if (rst_get_object(CPT_OBJ_TTY, sec, pibuf, ctx))
			return CPT_NULL;
		if (pibuf->cpt_index == pi->cpt_index &&
		    !((pi->cpt_drv_flags^pibuf->cpt_drv_flags)&TTY_DRIVER_DEVPTS_MEM) &&
		    pos != sec && strncmp("vtty", pibuf->cpt_name, 4)) {
			pty_setup(stty, sec, pibuf, ctx);
			return sec;
		}
		sec += pibuf->cpt_next;
	}
	kfree(pibuf);
	return CPT_NULL;
}
Exemple #3
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;
}
Exemple #4
0
static int rst_restore_netstats(loff_t pos, struct net_device *dev,
			struct cpt_context * ctx)
{
	struct cpt_netstats_image *n;
	struct net_device_stats *stats = NULL;
	int err;

	if (!dev->netdev_ops->ndo_get_stats)
		return 0;

	n = cpt_get_buf(ctx);
	err = rst_get_object(CPT_OBJ_NET_STATS, pos, n, ctx);
	if (err)
		goto out;
	BUG_ON(sizeof(struct cpt_netstats_image) != n->cpt_hdrlen);
	preempt_disable();

	if (dev->netdev_ops->ndo_cpt == NULL) {
		err = -ENODEV;
		eprintk_ctx("Network device %s is not supported\n", dev->name);
		goto out;
	}

	stats = dev->netdev_ops->ndo_get_stats(dev);

	stats->rx_packets = n->cpt_rx_packets;
	stats->tx_packets = n->cpt_tx_packets;
	stats->rx_bytes = n->cpt_rx_bytes;
	stats->tx_bytes = n->cpt_tx_bytes;
	stats->rx_errors = n->cpt_rx_errors;
	stats->tx_errors = n->cpt_tx_errors;
	stats->rx_dropped = n->cpt_rx_dropped;
	stats->tx_dropped = n->cpt_tx_dropped;
	stats->multicast = n->cpt_multicast;
	stats->collisions = n->cpt_collisions;
	stats->rx_length_errors = n->cpt_rx_length_errors;
	stats->rx_over_errors = n->cpt_rx_over_errors;
	stats->rx_crc_errors = n->cpt_rx_crc_errors;
	stats->rx_frame_errors = n->cpt_rx_frame_errors;
	stats->rx_fifo_errors = n->cpt_rx_fifo_errors;
	stats->rx_missed_errors = n->cpt_rx_missed_errors;
	stats->tx_aborted_errors = n->cpt_tx_aborted_errors;
	stats->tx_carrier_errors = n->cpt_tx_carrier_errors;
	stats->tx_fifo_errors = n->cpt_tx_fifo_errors;
	stats->tx_heartbeat_errors = n->cpt_tx_heartbeat_errors;
	stats->tx_window_errors = n->cpt_tx_window_errors;
	stats->rx_compressed = n->cpt_rx_compressed;
	stats->tx_compressed = n->cpt_tx_compressed;

out:
	preempt_enable();
	cpt_release_buf(ctx);
	return err;
}
int rst_sk_mcfilter_in6(struct sock *sk, struct cpt_sockmc_image *v,
			loff_t pos, cpt_context_t *ctx)
{

	if (v->cpt_mode || v->cpt_next != v->cpt_hdrlen) {
		eprintk_ctx("IGMPv3 is still not supported\n");
		return -EINVAL;
	}

	return ipv6_sock_mc_join(sk, v->cpt_ifindex,
				 (struct in6_addr*)v->cpt_mcaddr);
}
Exemple #6
0
int rst_tty_jobcontrol(struct cpt_context *ctx)
{
	int err;
	loff_t sec = ctx->sections[CPT_SECT_TTY];
	loff_t endsec;
	struct cpt_section_hdr h;

	err = ctx->pread(&h, sizeof(h), ctx, sec);
	if (err)
		return err;
	if (h.cpt_section != CPT_SECT_TTY || h.cpt_hdrlen < sizeof(h))
		return -EINVAL;
	endsec = sec + h.cpt_next;
	sec += h.cpt_hdrlen;
	while (sec < endsec) {
		cpt_object_t *obj;
		struct cpt_tty_image *pibuf = cpt_get_buf(ctx);

		if (rst_get_object(CPT_OBJ_TTY, sec, pibuf, ctx)) {
			cpt_release_buf(ctx);
			return -EINVAL;
		}

		obj = lookup_cpt_obj_bypos(CPT_OBJ_TTY, sec, ctx);
		if (obj) {
			struct tty_struct *stty = obj->o_obj;
			if ((int)pibuf->cpt_pgrp > 0) {
				stty->pgrp = alloc_vpid_safe(pibuf->cpt_pgrp);
				if (!stty->pgrp)
					dprintk_ctx("unknown tty pgrp %d\n", pibuf->cpt_pgrp);
			} else if (pibuf->cpt_pgrp) {
				stty->pgrp = alloc_pid(current->nsproxy->pid_ns,
							0);
				if (!stty->pgrp) {
					eprintk_ctx("cannot allocate stray tty->pgr\n");
					cpt_release_buf(ctx);
					return -EINVAL;
				}
			}
			if ((int)pibuf->cpt_session > 0) {
				stty->session = alloc_vpid_safe(pibuf->cpt_session);
				if (!stty->session)
					dprintk_ctx("unknown tty session %d\n", pibuf->cpt_session);
			}
		}
		sec += pibuf->cpt_next;
		cpt_release_buf(ctx);
	}
	return 0;
}
Exemple #7
0
int cpt_close_dumpfile(struct cpt_context *ctx)
{
	if (ctx->file) {
		fput(ctx->file);
		ctx->file = NULL;
	}
	if (ctx->tmpbuf) {
		free_page((unsigned long)ctx->tmpbuf);
		ctx->tmpbuf = NULL;
	}
	if (ctx->write_error)
		eprintk_ctx("error while writing dump file: %d\n", ctx->write_error);
	return ctx->write_error;
}
int rst_sk_mcfilter_in(struct sock *sk, struct cpt_sockmc_image *v,
		       loff_t pos, cpt_context_t *ctx)
{
	struct ip_mreqn imr;

	if (v->cpt_mode || v->cpt_next != v->cpt_hdrlen) {
		eprintk_ctx("IGMPv3 is still not supported\n");
		return -EINVAL;
	}

	memset(&imr, 0, sizeof(imr));
	imr.imr_ifindex = v->cpt_ifindex;
	imr.imr_multiaddr.s_addr = v->cpt_mcaddr[0];
	return ip_mc_join_group(sk, &imr);
}
Exemple #9
0
int rst_eventpoll(cpt_context_t *ctx)
{
	int err;
	loff_t sec = ctx->sections[CPT_SECT_EPOLL];
	loff_t endsec;
	struct cpt_section_hdr h;

	if (sec == CPT_NULL)
		return 0;

	err = ctx->pread(&h, sizeof(h), ctx, sec);
	if (err)
		return err;
	if (h.cpt_section != CPT_SECT_EPOLL || h.cpt_hdrlen < sizeof(h))
		return -EINVAL;

	endsec = sec + h.cpt_next;
	sec += h.cpt_hdrlen;
	while (sec < endsec) {
		cpt_object_t *obj;
		struct cpt_epoll_image *ebuf = cpt_get_buf(ctx);
		err = rst_get_object(CPT_OBJ_EPOLL, sec, ebuf, ctx);
		if (err) {
			cpt_release_buf(ctx);
			return err;
		}
		obj = lookup_cpt_obj_bypos(CPT_OBJ_FILE, ebuf->cpt_file, ctx);
		if (obj == NULL) {
			eprintk_ctx("cannot find epoll file object\n");
			cpt_release_buf(ctx);
			return -EINVAL;
		}
		err = restore_one_epoll(obj, sec, ebuf, ctx);
		cpt_release_buf(ctx);
		if (err)
			return err;
		sec += ebuf->cpt_next;
	}

	return 0;
	
}
Exemple #10
0
static int
select_deleted_name(char * name, cpt_context_t *ctx)
{
    int i;

    for (i=0; i<100; i++) {
        struct nameidata nd;
        unsigned int rnd = net_random();

        sprintf(name, "/tmp/SOCK.%08x", rnd);

        if (path_lookup(name, 0, &nd) != 0)
            return 0;

        path_put(&nd.path);
    }

    eprintk_ctx("failed to allocate deleted socket inode\n");
    return -ELOOP;
}
Exemple #11
0
static int do_rst_aio(struct cpt_aio_ctx_image *aimg, loff_t pos, cpt_context_t *ctx)
{
	int err;
	struct kioctx *aio_ctx;
	extern spinlock_t aio_nr_lock;

	aio_ctx = kmem_cache_alloc(kioctx_cachep, GFP_KERNEL);
	if (!aio_ctx)
		return -ENOMEM;

	memset(aio_ctx, 0, sizeof(*aio_ctx));
	aio_ctx->max_reqs = aimg->cpt_max_reqs;

	if ((err = restore_aio_ring(aio_ctx, aimg)) < 0) {
		kmem_cache_free(kioctx_cachep, aio_ctx);
		eprintk_ctx("AIO %Ld restore_aio_ring: %d\n", pos, err);
		return err;
	}

	aio_ctx->mm = current->mm;
	atomic_inc(&aio_ctx->mm->mm_count);
	atomic_set(&aio_ctx->users, 1);
	spin_lock_init(&aio_ctx->ctx_lock);
	spin_lock_init(&aio_ctx->ring_info.ring_lock);
	init_waitqueue_head(&aio_ctx->wait);
	INIT_LIST_HEAD(&aio_ctx->active_reqs);
	INIT_LIST_HEAD(&aio_ctx->run_list);
	INIT_DELAYED_WORK(&aio_ctx->wq, aio_kick_handler);

	spin_lock(&aio_nr_lock);
	aio_nr += aio_ctx->max_reqs;
	spin_unlock(&aio_nr_lock);

	spin_lock(&aio_ctx->mm->ioctx_lock);
	hlist_add_head(&aio_ctx->list, &aio_ctx->mm->ioctx_list);
	spin_unlock(&aio_ctx->mm->ioctx_lock);

	return 0;
}
Exemple #12
0
int rst_restore_netdev(struct cpt_context *ctx)
{
	struct net *net = get_exec_env()->ve_netns;
	int err;
	loff_t sec = ctx->sections[CPT_SECT_NET_DEVICE];
	loff_t endsec;
	struct cpt_section_hdr h;
	struct cpt_netdev_image di;
	struct net_device *dev;

	get_exec_env()->disable_net = 1;

	if (sec == CPT_NULL)
		return 0;

	err = ctx->pread(&h, sizeof(h), ctx, sec);
	if (err)
		return err;
	if (h.cpt_section != CPT_SECT_NET_DEVICE || h.cpt_hdrlen < sizeof(h))
		return -EINVAL;

	endsec = sec + h.cpt_next;
	sec += h.cpt_hdrlen;
	while (sec < endsec) {
		loff_t pos;
		struct net_device *dev_new;
		struct netdev_rst *ops;

		err = rst_get_object(CPT_OBJ_NET_DEVICE, sec, &di, ctx);
		if (err)
			return err;

		rtnl_lock();
		pos = sec + di.cpt_hdrlen;
		if (di.cpt_next > sizeof(di)) {
			struct cpt_object_hdr hdr;
			err = ctx->pread(&hdr, sizeof(struct cpt_object_hdr),
					ctx, sec + di.cpt_hdrlen);
			if (err)
				goto out;

			ops = NULL;
			while (1) {
				ops = netdev_find_rst(hdr.cpt_object, ops);
				if (ops == NULL)
					break;

				err = ops->ndo_rst(sec, &di, &rst_ops, ctx);
				if (!err) {
					pos += hdr.cpt_next;
					break;
				} else if (err < 0) {
					eprintk_ctx("netdev %d rst failed %d\n",
							hdr.cpt_object, err);
					goto out;
				}
			}
		}

		dev = __dev_get_by_name(net, di.cpt_name);
		if (dev) {
			if (dev->ifindex != di.cpt_index) {
				dev_new = __dev_get_by_index(net, di.cpt_index);
				if (!dev_new) {
					write_lock_bh(&dev_base_lock);
					hlist_del(&dev->index_hlist);
					if (dev->iflink == dev->ifindex)
						dev->iflink = di.cpt_index;
					dev->ifindex = di.cpt_index;
					hlist_add_head(&dev->index_hlist,
							dev_index_hash(net, dev->ifindex));
					write_unlock_bh(&dev_base_lock);
				} else {
					write_lock_bh(&dev_base_lock);
					hlist_del(&dev->index_hlist);
					hlist_del(&dev_new->index_hlist);
					if (dev_new->iflink == dev_new->ifindex)
						dev_new->iflink = dev->ifindex;
					dev_new->ifindex = dev->ifindex;
					if (dev->iflink == dev->ifindex)
						dev->iflink = di.cpt_index;
					dev->ifindex = di.cpt_index;
					hlist_add_head(&dev->index_hlist,
							dev_index_hash(net, dev->ifindex));
					hlist_add_head(&dev_new->index_hlist,
							dev_index_hash(net, dev_new->ifindex));
					write_unlock_bh(&dev_base_lock);
				}
			}
			if (di.cpt_flags^dev->flags) {
				err = dev_change_flags(dev, di.cpt_flags);
				if (err)
					eprintk_ctx("dev_change_flags err: %d\n", err);
			}
			while (pos < sec + di.cpt_next) {
				struct cpt_object_hdr hdr;
				err = ctx->pread(&hdr, sizeof(struct cpt_object_hdr),
						ctx, pos);
				if (err)
					goto out;
				if (hdr.cpt_object == CPT_OBJ_NET_HWADDR) {
					/* Restore hardware address */
					struct cpt_hwaddr_image hw;
					err = rst_get_object(CPT_OBJ_NET_HWADDR,
							pos, &hw, ctx);
					if (err)
						goto out;
					BUILD_BUG_ON(sizeof(hw.cpt_dev_addr) !=
							MAX_ADDR_LEN);
					memcpy(dev->dev_addr, hw.cpt_dev_addr,
							sizeof(hw.cpt_dev_addr));
				} else if (hdr.cpt_object == CPT_OBJ_NET_STATS) {
					err = rst_restore_netstats(pos, dev, ctx);
					if (err) {
						eprintk_ctx("rst stats %s: %d\n",
								di.cpt_name, err);
						goto out;
					}
				}
				pos += hdr.cpt_next;
			}
		} else {
			eprintk_ctx("unknown interface 2 %s\n", di.cpt_name);
		}
		rtnl_unlock();
		sec += di.cpt_next;
	}
	return 0;
out:
	rtnl_unlock();
	return err;
}
Exemple #13
0
int rst_restore_ifaddr(struct cpt_context *ctx)
{
	struct net *net = get_exec_env()->ve_netns;
	int err;
	loff_t sec = ctx->sections[CPT_SECT_NET_IFADDR];
	loff_t endsec;
	struct cpt_section_hdr h;
	struct cpt_ifaddr_image di;
	struct net_device *dev;

	if (sec == CPT_NULL)
		return 0;

	err = ctx->pread(&h, sizeof(h), ctx, sec);
	if (err)
		return err;
	if (h.cpt_section != CPT_SECT_NET_IFADDR || h.cpt_hdrlen < sizeof(h))
		return -EINVAL;

	endsec = sec + h.cpt_next;
	sec += h.cpt_hdrlen;
	while (sec < endsec) {
		int cindex = -1;
		int err;
		err = rst_get_object(CPT_OBJ_NET_IFADDR, sec, &di, ctx);
		if (err)
			return err;
		cindex = di.cpt_index;
		rtnl_lock();
		dev = __dev_get_by_index(net, cindex);
		if (dev && di.cpt_family == AF_INET) {
			struct in_device *in_dev;
			struct in_ifaddr *ifa;
			if ((in_dev = __in_dev_get_rtnl(dev)) == NULL)
				in_dev = inetdev_init(dev);
			ifa = inet_alloc_ifa();
			if (ifa) {
				ifa->ifa_local = di.cpt_address[0];
				ifa->ifa_address = di.cpt_peer[0];
				ifa->ifa_broadcast = di.cpt_broadcast[0];
				ifa->ifa_prefixlen = di.cpt_masklen;
				ifa->ifa_mask = inet_make_mask(ifa->ifa_prefixlen);
				ifa->ifa_flags = di.cpt_flags;
				ifa->ifa_scope = di.cpt_scope;
				memcpy(ifa->ifa_label, di.cpt_label, IFNAMSIZ);
				in_dev_hold(in_dev);
				ifa->ifa_dev   = in_dev;
				err = inet_insert_ifa(ifa);
				if (err && err != -EEXIST) {
					rtnl_unlock();
					eprintk_ctx("add ifaddr err %d for %d %s\n", err, di.cpt_index, di.cpt_label);
					return err;
				}
			}
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
		} else if (dev && di.cpt_family == AF_INET6) {
			__u32 prefered_lft;
			__u32 valid_lft;
			struct net *net = get_exec_env()->ve_ns->net_ns;
			prefered_lft = (di.cpt_flags & IFA_F_DEPRECATED) ?
				0 : di.cpt_prefered_lft;
			valid_lft = (di.cpt_flags & IFA_F_PERMANENT) ?
				0xFFFFFFFF : di.cpt_valid_lft;
			err = inet6_addr_add(net, dev->ifindex,
					     (struct in6_addr *)di.cpt_address,
					     di.cpt_masklen, 0,
					     prefered_lft,
					     valid_lft);
			if (err && err != -EEXIST) {
				rtnl_unlock();
				eprintk_ctx("add ifaddr err %d for %d %s\n", err, di.cpt_index, di.cpt_label);
				return err;
			}
#endif
		} else {
			rtnl_unlock();
			eprintk_ctx("unknown ifaddr 2 for %d\n", di.cpt_index);
			return -EINVAL;
		}
		rtnl_unlock();
		sec += di.cpt_next;
	}
	return 0;
}
Exemple #14
0
int rst_restore_route(struct cpt_context *ctx)
{
	int err;
	struct socket *sock;
	struct msghdr msg;
	struct iovec iov;
	struct sockaddr_nl nladdr;
	mm_segment_t oldfs;
	loff_t sec = ctx->sections[CPT_SECT_NET_ROUTE];
	loff_t endsec;
	struct cpt_section_hdr h;
	struct cpt_object_hdr v;
	char *pg;

	if (sec == CPT_NULL)
		return 0;

	err = ctx->pread(&h, sizeof(h), ctx, sec);
	if (err)
		return err;
	if (h.cpt_section != CPT_SECT_NET_ROUTE || h.cpt_hdrlen < sizeof(h))
		return -EINVAL;

	if (h.cpt_hdrlen >= h.cpt_next)
		return 0;

	sec += h.cpt_hdrlen;
	err = rst_get_object(CPT_OBJ_NET_ROUTE, sec, &v, ctx);
	if (err < 0)
		return err;

	err = sock_create(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE, &sock);
	if (err)
		return err;

	pg = (char*)__get_free_page(GFP_KERNEL);
	if (pg == NULL) {
		err = -ENOMEM;
		goto out_sock;
	}

	memset(&nladdr, 0, sizeof(nladdr));
	nladdr.nl_family = AF_NETLINK;

	endsec = sec + v.cpt_next;
	sec += v.cpt_hdrlen;

	while (sec < endsec) {
		struct nlmsghdr *n;
		struct nlmsghdr nh;
		int kernel_flag;

		if (endsec - sec < sizeof(nh))
			break;

		err = ctx->pread(&nh, sizeof(nh), ctx, sec);
		if (err)
			goto out_sock_pg;
		if (nh.nlmsg_len < sizeof(nh) || nh.nlmsg_len > PAGE_SIZE ||
		    endsec - sec < nh.nlmsg_len) {
			err = -EINVAL;
			goto out_sock_pg;
		}
		err = ctx->pread(pg, nh.nlmsg_len, ctx, sec);
		if (err)
			goto out_sock_pg;

		n = (struct nlmsghdr*)pg;
		n->nlmsg_flags = NLM_F_REQUEST|NLM_F_APPEND|NLM_F_CREATE;

		err = rewrite_rtmsg(n, ctx);
		if (err < 0)
			goto out_sock_pg;
		kernel_flag = err;

		if (kernel_flag == 2)
			goto do_next;

		iov.iov_base=n;
		iov.iov_len=nh.nlmsg_len;
		msg.msg_name=&nladdr;
		msg.msg_namelen=sizeof(nladdr);
		msg.msg_iov=&iov;
		msg.msg_iovlen=1;
		msg.msg_control=NULL;
		msg.msg_controllen=0;
		msg.msg_flags=MSG_DONTWAIT;

		oldfs = get_fs(); set_fs(KERNEL_DS);
		err = sock_sendmsg(sock, &msg, nh.nlmsg_len);
		set_fs(oldfs);

		if (err < 0)
			goto out_sock_pg;
		err = 0;

		iov.iov_base=pg;
		iov.iov_len=PAGE_SIZE;

		oldfs = get_fs(); set_fs(KERNEL_DS);
		err = sock_recvmsg(sock, &msg, PAGE_SIZE, MSG_DONTWAIT);
		set_fs(oldfs);
		if (err != -EAGAIN) {
			if (n->nlmsg_type == NLMSG_ERROR) {
				struct nlmsgerr *e = NLMSG_DATA(n);
				if (e->error != -EEXIST || !kernel_flag)
					eprintk_ctx("NLMERR: %d\n", e->error);
			} else {
				eprintk_ctx("Res: %d %d\n", err, n->nlmsg_type);
			}
		}
do_next:
		err = 0;
		sec += NLMSG_ALIGN(nh.nlmsg_len);
	}

out_sock_pg:
	free_page((unsigned long)pg);
out_sock:
	sock_release(sock);
	return err;
}
Exemple #15
0
static int cpt_dump_iptables(struct cpt_context * ctx)
{
	int err = 0;
#ifdef CONFIG_VE_IPTABLES
	int pid;
	int pfd[2];
	struct file *f;
	struct cpt_object_hdr v;
	char buf[16];
	loff_t pos;
	int n;
	int status;
	mm_segment_t oldfs;
	sigset_t ignore, blocked;
	struct args_t args;
	struct ve_struct *oldenv;

	if (!(get_exec_env()->_iptables_modules & VE_IP_IPTABLES_MOD))
		return 0;

	err = sc_pipe(pfd);
	if (err < 0) {
		eprintk_ctx("sc_pipe: %d\n", err);
		return err;
	}
	args.pfd = pfd;
	args.veid = VEID(get_exec_env());
	ignore.sig[0] = CPT_SIG_IGNORE_MASK;
	sigprocmask(SIG_BLOCK, &ignore, &blocked);
	oldenv = set_exec_env(get_ve0());
	err = pid = local_kernel_thread(dumpfn, (void*)&args,
			SIGCHLD | CLONE_VFORK, 0);
	set_exec_env(oldenv);
	if (err < 0) {
		eprintk_ctx("local_kernel_thread: %d\n", err);
		goto out;
	}

	f = fget(pfd[0]);
	sc_close(pfd[1]);
	sc_close(pfd[0]);

	cpt_open_section(ctx, CPT_SECT_NET_IPTABLES);

	cpt_open_object(NULL, ctx);
	v.cpt_next = CPT_NULL;
	v.cpt_object = CPT_OBJ_NAME;
	v.cpt_hdrlen = sizeof(v);
	v.cpt_content = CPT_CONTENT_NAME;

	ctx->write(&v, sizeof(v), ctx);

	pos = ctx->file->f_pos;
	do {
		oldfs = get_fs(); set_fs(KERNEL_DS);
		n = f->f_op->read(f, buf, sizeof(buf), &f->f_pos);
		set_fs(oldfs);
		if (n > 0)
			ctx->write(buf, n, ctx);
	} while (n > 0);

	if (n < 0)
		eprintk_ctx("read: %d\n", n);

	fput(f);

	oldfs = get_fs(); set_fs(KERNEL_DS);
	if ((err = sc_waitx(pid, 0, &status)) < 0)
		eprintk_ctx("wait4: %d\n", err);
	else if ((status & 0x7f) == 0) {
		err = (status & 0xff00) >> 8;
		if (err != 0) {
			eprintk_ctx("iptables-save exited with %d\n", err);
			err = -EINVAL;
		}
	} else {
Exemple #16
0
static int
bind_unix_socket(struct socket *sock, struct cpt_sock_image *si,
                 cpt_context_t *ctx)
{
    int err;
    char *name;
    struct sockaddr* addr;
    int addrlen;
    struct sockaddr_un sun;
    struct nameidata nd;

    if ((addrlen = si->cpt_laddrlen) <= 2)
        return 0;

    nd.path.dentry = NULL;
    name = ((char*)si->cpt_laddr) + 2;
    addr = (struct sockaddr *)si->cpt_laddr;

    if (name[0]) {
        if (path_lookup(name, 0, &nd))
            nd.path.dentry = NULL;

        if (si->cpt_deleted) {
            if (nd.path.dentry == NULL &&
                    sock->ops->bind(sock, addr, addrlen) == 0) {
                sc_unlink(name);
                return 0;
            }

            addr = (struct sockaddr*)&sun;
            addr->sa_family = AF_UNIX;
            name = ((char*)addr) + 2;
            err = select_deleted_name(name, ctx);
            if (err)
                goto out;
            addrlen = 2 + strlen(name);
        } else if (nd.path.dentry) {
            if (!S_ISSOCK(nd.path.dentry->d_inode->i_mode)) {
                eprintk_ctx("bind_unix_socket: not a socket dentry\n");
                err = -EINVAL;
                goto out;
            }
            sc_unlink(name);
        }
    }

    err = sock->ops->bind(sock, addr, addrlen);

    if (!err && name[0]) {
        if (nd.path.dentry) {
            sc_chown(name, nd.path.dentry->d_inode->i_uid,
                     nd.path.dentry->d_inode->i_gid);
            sc_chmod(name, nd.path.dentry->d_inode->i_mode);
        }
        if (si->cpt_deleted)
            sc_unlink(name);
    }

out:
    if (nd.path.dentry)
        path_put(&nd.path);
    return err;
}
Exemple #17
0
static int restore_one_epoll(cpt_object_t *obj,
			     loff_t pos,
			     struct cpt_epoll_image *ebuf,
			     cpt_context_t *ctx)
{
	int err = 0;
	loff_t endpos;
	struct file *file = obj->o_obj;
	struct eventpoll *ep;

	if (file->f_op != &eventpoll_fops) {
		eprintk_ctx("bad epoll file\n");
		return -EINVAL;
	}

	ep = file->private_data;

	if (unlikely(ep == NULL)) {
		eprintk_ctx("bad epoll device\n");
		return -EINVAL;
	}

	endpos = pos + ebuf->cpt_next;
	pos += ebuf->cpt_hdrlen;
	while (pos < endpos) {
		struct cpt_epoll_file_image efi;
		struct epoll_event epds;
		
		cpt_object_t *tobj;

		err = rst_get_object(CPT_OBJ_EPOLL_FILE, pos, &efi, ctx);
		if (err)
			return err;
		tobj = lookup_cpt_obj_bypos(CPT_OBJ_FILE, efi.cpt_file, ctx);
		if (!tobj) {
			eprintk_ctx("epoll file not found\n");
			return -EINVAL;
		}
		epds.events = efi.cpt_events;
		epds.data = efi.cpt_data;
		mutex_lock(&ep->mtx);
		err = ep_insert(ep, &epds, tobj->o_obj, efi.cpt_fd);
		if (!err) {
			struct epitem *epi;
			epi = ep_find(ep, tobj->o_obj, efi.cpt_fd);
			if (epi) {
				if (efi.cpt_ready) {
					unsigned long flags;
					spin_lock_irqsave(&ep->lock, flags);
					if (list_empty(&epi->rdllink))
						list_add_tail(&epi->rdllink, &ep->rdllist);
					spin_unlock_irqrestore(&ep->lock, flags);
				}
			}
		}
		mutex_unlock(&ep->mtx);
		if (err)
			break;
		pos += efi.cpt_next;
	}
	return err;
}
Exemple #18
0
static int open_socket(cpt_object_t *obj, struct cpt_sock_image *si,
                       struct cpt_context *ctx)
{
    int err;
    struct socket *sock;
    struct socket *sock2 = NULL;
    struct file *file;
    cpt_object_t *fobj;
    cpt_object_t *pobj = NULL;

    err = sock_create(si->cpt_family, si->cpt_type, si->cpt_protocol,
                      &sock);
    if (err)
        return err;

    if (si->cpt_socketpair) {
        err = sock_create(si->cpt_family, si->cpt_type,
                          si->cpt_protocol, &sock2);
        if (err)
            goto err_out;

        err = sock->ops->socketpair(sock, sock2);
        if (err < 0)
            goto err_out;

        /* Socketpair with a peer outside our environment.
         * So, we create real half-open pipe and do not worry
         * about dead end anymore. */
        if (si->cpt_peer == -1) {
            sock_release(sock2);
            sock2 = NULL;
        }
    }

    cpt_obj_setobj(obj, sock->sk, ctx);

    if (si->cpt_file != CPT_NULL) {
        file = sock_mapfile(sock);
        err = PTR_ERR(file);
        if (IS_ERR(file))
            goto err_out;

        err = -ENOMEM;

        obj->o_parent = file;

        if ((fobj = cpt_object_add(CPT_OBJ_FILE, file, ctx)) == NULL)
            goto err_out;
        cpt_obj_setpos(fobj, si->cpt_file, ctx);
        cpt_obj_setindex(fobj, si->cpt_index, ctx);
    }

    if (sock2) {
        struct file *file2;

        pobj = lookup_cpt_obj_byindex(CPT_OBJ_SOCKET, si->cpt_peer, ctx);
        if (!pobj) BUG();
        if (pobj->o_obj) BUG();
        cpt_obj_setobj(pobj, sock2->sk, ctx);

        if (pobj->o_ppos != CPT_NULL) {
            file2 = sock_mapfile(sock2);
            err = PTR_ERR(file2);
            if (IS_ERR(file2))
                goto err_out;

            err = -ENOMEM;
            if ((fobj = cpt_object_add(CPT_OBJ_FILE, file2, ctx)) == NULL)
                goto err_out;
            cpt_obj_setpos(fobj, pobj->o_ppos, ctx);
            cpt_obj_setindex(fobj, si->cpt_peer, ctx);

            pobj->o_parent = file2;
        }
    }

    setup_sock_common(sock->sk, si, obj->o_pos, ctx);
    if (sock->sk->sk_family == AF_INET || sock->sk->sk_family == AF_INET6) {
        int saved_reuse = sock->sk->sk_reuse;

        inet_sk(sock->sk)->freebind = 1;
        sock->sk->sk_reuse = 2;
        if (si->cpt_laddrlen) {
            err = sock->ops->bind(sock, (struct sockaddr *)&si->cpt_laddr, si->cpt_laddrlen);
            if (err) {
                dprintk_ctx("binding failed: %d, do not worry\n", err);
            }
        }
        sock->sk->sk_reuse = saved_reuse;
        rst_socket_in(si, obj->o_pos, sock->sk, ctx);
    } else if (sock->sk->sk_family == AF_NETLINK) {
        struct sockaddr_nl *nl = (struct sockaddr_nl *)&si->cpt_laddr;
        if (nl->nl_pid) {
            err = sock->ops->bind(sock, (struct sockaddr *)&si->cpt_laddr, si->cpt_laddrlen);
            if (err) {
                eprintk_ctx("AF_NETLINK binding failed: %d\n", err);
            }
        }
        if (si->cpt_raddrlen && nl->nl_pid) {
            err = sock->ops->connect(sock, (struct sockaddr *)&si->cpt_raddr, si->cpt_raddrlen, O_NONBLOCK);
            if (err) {
                eprintk_ctx("oops, AF_NETLINK connect failed: %d\n", err);
            }
        }
        generic_restore_queues(sock->sk, si, obj->o_pos, ctx);
    } else if (sock->sk->sk_family == PF_PACKET) {
        struct sockaddr_ll *ll = (struct sockaddr_ll *)&si->cpt_laddr;
        if (ll->sll_protocol || ll->sll_ifindex) {
            int alen = si->cpt_laddrlen;
            if (alen < sizeof(struct sockaddr_ll))
                alen = sizeof(struct sockaddr_ll);
            err = sock->ops->bind(sock, (struct sockaddr *)&si->cpt_laddr, alen);
            if (err) {
                eprintk_ctx("AF_PACKET binding failed: %d\n", err);
            }
        }
        generic_restore_queues(sock->sk, si, obj->o_pos, ctx);
    }
    fixup_unix_address(sock, si, ctx);

    if (sock2) {
        err = rst_get_object(CPT_OBJ_SOCKET, pobj->o_pos, si, ctx);
        if (err)
            return err;
        setup_sock_common(sock2->sk, si, pobj->o_pos, ctx);
        fixup_unix_address(sock2, si, ctx);
    }

    if ((sock->sk->sk_family == AF_INET || sock->sk->sk_family == AF_INET6)
            && (int)si->cpt_parent != -1) {
        cpt_object_t *lobj = lookup_cpt_obj_byindex(CPT_OBJ_SOCKET, si->cpt_parent, ctx);
        if (lobj && cpt_attach_accept(lobj->o_obj, sock->sk, ctx) == 0)
            sock->sk = NULL;
    }


    if (si->cpt_file == CPT_NULL && sock->sk &&
            sock->sk->sk_family == AF_INET) {
        struct sock *sk = sock->sk;

        if (sk) {
            sock->sk = NULL;

            local_bh_disable();
            bh_lock_sock(sk);
            if (sock_owned_by_user(sk))
                eprintk_ctx("oops, sock is locked by user\n");

            sock_hold(sk);
            sock_orphan(sk);
            ub_inc_orphan_count(sk);
            bh_unlock_sock(sk);
            local_bh_enable();
            sock_put(sk);
            dprintk_ctx("orphaning socket %p\n", sk);
        }
    }

    if (si->cpt_file == CPT_NULL && sock->sk == NULL)
        sock_release(sock);

    return 0;

err_out:
    if (sock2)
        sock_release(sock2);
    sock_release(sock);
    return err;
}
int rst_socket_in(struct cpt_sock_image *si, loff_t pos, struct sock *sk,
		  struct cpt_context *ctx)
{
	struct inet_sock *inet = inet_sk(sk);
	struct net *net = get_exec_env()->ve_ns->net_ns;
	int err, ret_err = 0;

	lock_sock(sk);

	sk->sk_state = si->cpt_state;

	inet->daddr = si->cpt_daddr;
	inet->dport = si->cpt_dport;
	inet->saddr = si->cpt_saddr;
	inet->rcv_saddr = si->cpt_rcv_saddr;
	inet->sport = si->cpt_sport;
	inet->uc_ttl = si->cpt_uc_ttl;
	inet->tos = si->cpt_tos;
	inet->cmsg_flags = si->cpt_cmsg_flags;
	inet->mc_index = si->cpt_mc_index;
	inet->mc_addr = si->cpt_mc_addr;
	inet->hdrincl = si->cpt_hdrincl;
	inet->mc_ttl = si->cpt_mc_ttl;
	inet->mc_loop = si->cpt_mc_loop;
	inet->pmtudisc = si->cpt_pmtudisc;
	inet->recverr = si->cpt_recverr;
	inet->freebind = si->cpt_freebind;
	inet->id = si->cpt_idcounter;

	inet->cork.flags = si->cpt_cork_flags;
	inet->cork.fragsize = si->cpt_cork_fragsize;
	inet->cork.length = si->cpt_cork_length;
	inet->cork.addr = si->cpt_cork_addr;
	inet->cork.fl.fl4_src = si->cpt_cork_saddr;
	inet->cork.fl.fl4_dst = si->cpt_cork_daddr;
	inet->cork.fl.oif = si->cpt_cork_oif;
	if (inet->cork.fragsize) {
		if (ip_route_output_key(net, (struct rtable **)&inet->cork.dst, &inet->cork.fl)) {
			eprintk_ctx("failed to restore cork route\n");
			inet->cork.fragsize = 0;
		}
	}

	if (sk->sk_type == SOCK_DGRAM && sk->sk_protocol == IPPROTO_UDP) {
		struct udp_sock *up = udp_sk(sk);
		up->pending = si->cpt_udp_pending;
		up->corkflag = si->cpt_udp_corkflag;
		up->encap_type = si->cpt_udp_encap;
		up->len = si->cpt_udp_len;
	}

	if (sk->sk_family == AF_INET6) {
		struct ipv6_pinfo *np = inet6_sk(sk);

		memcpy(&np->saddr, si->cpt_saddr6, 16);
		memcpy(&np->rcv_saddr, si->cpt_rcv_saddr6, 16);
		memcpy(&np->daddr, si->cpt_daddr6, 16);
		np->flow_label = si->cpt_flow_label6;
		np->frag_size = si->cpt_frag_size6;
		np->hop_limit = si->cpt_hop_limit6;
		np->mcast_hops = si->cpt_mcast_hops6;
		np->mcast_oif = si->cpt_mcast_oif6;
		np->rxopt.all = si->cpt_rxopt6;
		np->mc_loop = si->cpt_mc_loop6;
		np->recverr = si->cpt_recverr6;
		np->sndflow = si->cpt_sndflow6;
		np->pmtudisc = si->cpt_pmtudisc6;
		np->ipv6only = si->cpt_ipv6only6;

#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
		if (si->cpt_mapped) {
			extern struct inet_connection_sock_af_ops ipv6_mapped;
			if (sk->sk_type == SOCK_STREAM &&
			    sk->sk_protocol == IPPROTO_TCP) {
				inet_csk(sk)->icsk_af_ops = &ipv6_mapped;
				sk->sk_backlog_rcv = tcp_v4_do_rcv;
			}
		}
#endif
	}

	err = restore_queues(sk, si, pos, ctx);

	if (sk->sk_type == SOCK_STREAM && sk->sk_protocol == IPPROTO_TCP) {
		ret_err = err;
		rst_socket_tcp(si, pos, sk, ctx);
	}

	release_sock(sk);
	return ret_err;
}
Exemple #20
0
static int rst_restore_iptables(struct cpt_context * ctx)
{
	int err;
	int pfd[2];
	struct file *f;
	struct cpt_object_hdr v;
	int n;
	struct cpt_section_hdr h;
	loff_t sec = ctx->sections[CPT_SECT_NET_IPTABLES];
	loff_t end;
	int pid;
	int status;
	mm_segment_t oldfs;
	sigset_t ignore, blocked;

	if (sec == CPT_NULL)
		return 0;

	err = ctx->pread(&h, sizeof(h), ctx, sec);
	if (err)
		return err;
	if (h.cpt_section != CPT_SECT_NET_IPTABLES || h.cpt_hdrlen < sizeof(h))
		return -EINVAL;

	if (h.cpt_hdrlen == h.cpt_next)
		return 0;
	if (h.cpt_hdrlen > h.cpt_next)
		return -EINVAL;
	sec += h.cpt_hdrlen;
	err = rst_get_object(CPT_OBJ_NAME, sec, &v, ctx);
	if (err < 0)
		return err;

	err = sc_pipe(pfd);
	if (err < 0)
		return err;
	ignore.sig[0] = CPT_SIG_IGNORE_MASK;
	sigprocmask(SIG_BLOCK, &ignore, &blocked);
	pid = err = local_kernel_thread(dumpfn, (void*)pfd, SIGCHLD, 0);
	if (err < 0) {
		eprintk_ctx("iptables local_kernel_thread: %d\n", err);
		goto out;
	}
	f = fget(pfd[1]);
	sc_close(pfd[1]);
	sc_close(pfd[0]);

	ctx->file->f_pos = sec + v.cpt_hdrlen;
	end = sec + v.cpt_next;
	do {
		char *p;
		char buf[16];

		n = end - ctx->file->f_pos;
		if (n > sizeof(buf))
			n = sizeof(buf);

		if (ctx->read(buf, n, ctx))
			break;
		if ((p = memchr(buf, 0, n)) != NULL)
			n = p - buf;
		oldfs = get_fs(); set_fs(KERNEL_DS);
		f->f_op->write(f, buf, n, &f->f_pos);
		set_fs(oldfs);
	} while (ctx->file->f_pos < end);

	fput(f);

	oldfs = get_fs(); set_fs(KERNEL_DS);
	if ((err = sc_waitx(pid, 0, &status)) < 0)
		eprintk_ctx("wait4: %d\n", err);
	else if ((status & 0x7f) == 0) {
		err = (status & 0xff00) >> 8;
		if (err != 0) {
			eprintk_ctx("iptables-restore exited with %d\n", err);
			eprintk_ctx("Most probably some iptables modules are not loaded\n");
			err = -EINVAL;
		}
	} else {
Exemple #21
0
struct sk_buff * rst_skb(struct sock *sk, loff_t *pos_p, __u32 *owner,
                         __u32 *queue, struct cpt_context *ctx)
{
    int err;
    struct sk_buff *skb;
    struct cpt_skb_image v;
    loff_t pos = *pos_p;
    struct scm_fp_list *fpl = NULL;
    struct timeval tmptv;

    err = rst_get_object(CPT_OBJ_SKB, pos, &v, ctx);
    if (err)
        return ERR_PTR(err);
    *pos_p = pos + v.cpt_next;

    if (owner)
        *owner = v.cpt_owner;
    if (queue)
        *queue = v.cpt_queue;

    skb = alloc_skb(v.cpt_len + v.cpt_hspace + v.cpt_tspace, GFP_KERNEL);
    if (skb == NULL)
        return ERR_PTR(-ENOMEM);
    skb_reserve(skb, v.cpt_hspace);
    skb_put(skb, v.cpt_len);
#ifdef NET_SKBUFF_DATA_USES_OFFSET
    skb->transport_header = v.cpt_h;
    skb->network_header = v.cpt_nh;
    skb->mac_header = v.cpt_mac;
#else
    skb->transport_header = skb->head + v.cpt_h;
    skb->network_header = skb->head + v.cpt_nh;
    skb->mac_header = skb->head + v.cpt_mac;
#endif
    BUILD_BUG_ON(sizeof(skb->cb) < sizeof(v.cpt_cb));
    if (sk->sk_protocol == IPPROTO_TCP) {
        /*
         * According to Alexey all packets in queue have non-zero
         * flags, as at least TCPCB_FLAG_ACK is set on them.
         * Luckily for us, offset of field flags in tcp_skb_cb struct
         * with IPv6 is higher then total size of tcp_skb_cb struct
         * without IPv6.
         */
        if (ctx->image_version >= CPT_VERSION_18_2 ||
                ((struct tcp_skb_cb_ipv6 *)&v.cpt_cb)->flags) {
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
            check_tcp_cb_conv(NOT_CONV, CONV);
            memcpy(skb->cb, v.cpt_cb, sizeof(v.cpt_cb));
#else
            check_tcp_cb_conv(CONV, NOT_CONV);
            rst_tcp_cb_ipv6_to_ipv4(&v, skb);
#endif
        } else {
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
            check_tcp_cb_conv(CONV, NOT_CONV);
            rst_tcp_cb_ipv4_to_ipv6(&v, skb);
#else
            check_tcp_cb_conv(NOT_CONV, CONV);
            memcpy(skb->cb, v.cpt_cb, sizeof(v.cpt_cb));
#endif
        }
    } else
        memcpy(skb->cb, v.cpt_cb, sizeof(v.cpt_cb));
    skb->mac_len = v.cpt_mac_len;

    skb->csum = v.cpt_csum;
    skb->local_df = v.cpt_local_df;
    skb->pkt_type = v.cpt_pkt_type;
    skb->ip_summed = v.cpt_ip_summed;
    skb->priority = v.cpt_priority;
    skb->protocol = v.cpt_protocol;
    cpt_timeval_import(&tmptv, v.cpt_stamp);
    skb->tstamp = timeval_to_ktime(tmptv);

    skb_shinfo(skb)->gso_segs = v.cpt_gso_segs;
    skb_shinfo(skb)->gso_size = v.cpt_gso_size;
    if (ctx->image_version == 0) {
        skb_shinfo(skb)->gso_segs = 1;
        skb_shinfo(skb)->gso_size = 0;
    }

    if (v.cpt_next > v.cpt_hdrlen) {
        pos = pos + v.cpt_hdrlen;
        while (pos < *pos_p) {
            union {
                struct cpt_obj_bits b;
                struct cpt_fd_image f;
            } u;

            err = rst_get_object(-1, pos, &u, ctx);
            if (err) {
                kfree_skb(skb);
                return ERR_PTR(err);
            }
            if (u.b.cpt_object == CPT_OBJ_BITS) {
                if (u.b.cpt_size != v.cpt_hspace + skb->len) {
                    eprintk_ctx("invalid skb image %u != %u + %u\n", u.b.cpt_size, v.cpt_hspace, skb->len);
                    kfree_skb(skb);
                    return ERR_PTR(-EINVAL);
                }

                err = ctx->pread(skb->head, u.b.cpt_size, ctx, pos+u.b.cpt_hdrlen);
                if (err) {
                    kfree_skb(skb);
                    return ERR_PTR(err);
                }
            } else if (u.f.cpt_object == CPT_OBJ_FILEDESC) {
                if (!fpl) {
                    fpl = kmalloc(sizeof(struct scm_fp_list),
                                  GFP_KERNEL_UBC);
                    if (!fpl) {
                        kfree_skb(skb);
                        return ERR_PTR(-ENOMEM);
                    }
                    fpl->count = 0;
                    UNIXCB(skb).fp = fpl;
                }
                fpl->fp[fpl->count] = rst_file(u.f.cpt_file, -1, ctx);
                if (!IS_ERR(fpl->fp[fpl->count]))
                    fpl->count++;
            }
            pos += u.b.cpt_next;
        }
    }

    return skb;
}
Exemple #22
0
static int open_listening_socket(loff_t pos, struct cpt_sock_image *si,
                                 struct cpt_context *ctx)
{
    int err;
    struct socket *sock;
    struct file *file;
    cpt_object_t *obj, *fobj;

    err = sock_create(si->cpt_family, si->cpt_type, si->cpt_protocol,
                      &sock);
    if (err) {
        eprintk_ctx("open_listening_socket: sock_create: %d\n", err);
        return err;
    }

    sock->sk->sk_reuse = 2;
    sock->sk->sk_bound_dev_if = si->cpt_bound_dev_if;

    if (sock->sk->sk_family == AF_UNIX) {
        err = bind_unix_socket(sock, si, ctx);
    } else if (si->cpt_laddrlen) {
        if (sock->sk->sk_family == AF_INET || sock->sk->sk_family == AF_INET6)
            inet_sk(sock->sk)->freebind = 1;

        err = sock->ops->bind(sock, (struct sockaddr *)&si->cpt_laddr, si->cpt_laddrlen);

        if (err) {
            eprintk_ctx("open_listening_socket: bind: %d\n", err);
            goto err_out;
        }
    }

    err = sock->ops->listen(sock, si->cpt_max_ack_backlog);
    if (err) {
        eprintk_ctx("open_listening_socket: listen: %d, %Ld, %d\n", err, pos, si->cpt_deleted);
        goto err_out;
    }

    /* Now we may access socket body directly and fixup all the things. */

    file = sock_mapfile(sock);
    err = PTR_ERR(file);
    if (IS_ERR(file)) {
        eprintk_ctx("open_listening_socket: map: %d\n", err);
        goto err_out;
    }

    err = -ENOMEM;
    if ((fobj = cpt_object_add(CPT_OBJ_FILE, file, ctx)) == NULL)
        goto err_out;
    if ((obj = cpt_object_add(CPT_OBJ_SOCKET, sock->sk, ctx)) == NULL)
        goto err_out;
    cpt_obj_setpos(obj, pos, ctx);
    cpt_obj_setindex(obj, si->cpt_index, ctx);
    obj->o_parent = file;
    cpt_obj_setpos(fobj, si->cpt_file, ctx);
    cpt_obj_setindex(fobj, si->cpt_index, ctx);

    setup_sock_common(sock->sk, si, pos, ctx);

    if (si->cpt_family == AF_INET || si->cpt_family == AF_INET6) {
        rst_listen_socket_in(sock->sk, si, pos, ctx);
        rst_restore_synwait_queue(sock->sk, si, pos, ctx);
    }

    return 0;

err_out:
    sock_release(sock);
    return err;
}
static int rst_socket_tcp(struct cpt_sock_image *si, loff_t pos, struct sock *sk,
			  struct cpt_context *ctx)
{
	struct tcp_sock *tp = tcp_sk(sk);
	struct sk_buff *skb;
	tp->pred_flags = si->cpt_pred_flags;
	tp->rcv_nxt = si->cpt_rcv_nxt;
	tp->snd_nxt = si->cpt_snd_nxt;
	tp->snd_una = si->cpt_snd_una;
	tp->snd_sml = si->cpt_snd_sml;
	tp->rcv_tstamp = tcp_jiffies_import(si->cpt_rcv_tstamp);
	tp->lsndtime = tcp_jiffies_import(si->cpt_lsndtime);
	tp->tcp_header_len = si->cpt_tcp_header_len;
	inet_csk(sk)->icsk_ack.pending = si->cpt_ack_pending;
	inet_csk(sk)->icsk_ack.quick = si->cpt_quick;
	inet_csk(sk)->icsk_ack.pingpong = si->cpt_pingpong;
	inet_csk(sk)->icsk_ack.blocked = si->cpt_blocked;
	inet_csk(sk)->icsk_ack.ato = si->cpt_ato;
	inet_csk(sk)->icsk_ack.timeout = jiffies_import(si->cpt_ack_timeout);
	inet_csk(sk)->icsk_ack.lrcvtime = tcp_jiffies_import(si->cpt_lrcvtime);
	inet_csk(sk)->icsk_ack.last_seg_size = si->cpt_last_seg_size;
	inet_csk(sk)->icsk_ack.rcv_mss = si->cpt_rcv_mss;
	tp->snd_wl1 = si->cpt_snd_wl1;
	tp->snd_wnd = si->cpt_snd_wnd;
	tp->max_window = si->cpt_max_window;
	inet_csk(sk)->icsk_pmtu_cookie = si->cpt_pmtu_cookie;
	tp->mss_cache = si->cpt_mss_cache;
	tp->rx_opt.mss_clamp = si->cpt_mss_clamp;
	inet_csk(sk)->icsk_ext_hdr_len = si->cpt_ext_header_len;
	inet_csk(sk)->icsk_ca_state = si->cpt_ca_state;
	inet_csk(sk)->icsk_retransmits = si->cpt_retransmits;
	tp->reordering = si->cpt_reordering;
	tp->frto_counter = si->cpt_frto_counter;
	tp->frto_highmark = si->cpt_frto_highmark;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
	// // tp->adv_cong = si->cpt_adv_cong;
#endif
	inet_csk(sk)->icsk_accept_queue.rskq_defer_accept = si->cpt_defer_accept;
	inet_csk(sk)->icsk_backoff = si->cpt_backoff;
	tp->srtt = si->cpt_srtt;
	tp->mdev = si->cpt_mdev;
	tp->mdev_max = si->cpt_mdev_max;
	tp->rttvar = si->cpt_rttvar;
	tp->rtt_seq = si->cpt_rtt_seq;
	inet_csk(sk)->icsk_rto = si->cpt_rto;
	tp->packets_out = si->cpt_packets_out;
	tp->retrans_out = si->cpt_retrans_out;
	tp->lost_out = si->cpt_lost_out;
	tp->sacked_out = si->cpt_sacked_out;
	tp->fackets_out = si->cpt_fackets_out;
	tp->snd_ssthresh = si->cpt_snd_ssthresh;
	tp->snd_cwnd = si->cpt_snd_cwnd;
	tp->snd_cwnd_cnt = si->cpt_snd_cwnd_cnt;
	tp->snd_cwnd_clamp = si->cpt_snd_cwnd_clamp;
	tp->snd_cwnd_used = si->cpt_snd_cwnd_used;
	tp->snd_cwnd_stamp = tcp_jiffies_import(si->cpt_snd_cwnd_stamp);
	inet_csk(sk)->icsk_timeout = tcp_jiffies_import(si->cpt_timeout);
	tp->rcv_wnd = si->cpt_rcv_wnd;
	tp->rcv_wup = si->cpt_rcv_wup;
	tp->write_seq = si->cpt_write_seq;
	tp->pushed_seq = si->cpt_pushed_seq;
	tp->copied_seq = si->cpt_copied_seq;
	tp->rx_opt.tstamp_ok = si->cpt_tstamp_ok;
	tp->rx_opt.wscale_ok = si->cpt_wscale_ok;
	tp->rx_opt.sack_ok = si->cpt_sack_ok;
	tp->rx_opt.saw_tstamp = si->cpt_saw_tstamp;
	tp->rx_opt.snd_wscale = si->cpt_snd_wscale;
	tp->rx_opt.rcv_wscale = si->cpt_rcv_wscale;
	tp->nonagle = si->cpt_nonagle;
	tp->keepalive_probes = si->cpt_keepalive_probes;
	tp->rx_opt.rcv_tsval = si->cpt_rcv_tsval;
	tp->rx_opt.rcv_tsecr = si->cpt_rcv_tsecr;
	tp->rx_opt.ts_recent = si->cpt_ts_recent;
	tp->rx_opt.ts_recent_stamp = si->cpt_ts_recent_stamp;
	tp->rx_opt.user_mss = si->cpt_user_mss;
	tp->rx_opt.dsack = si->cpt_dsack;
	tp->duplicate_sack[0].start_seq = si->cpt_sack_array[0];
	tp->duplicate_sack[0].end_seq = si->cpt_sack_array[1];
	tp->selective_acks[0].start_seq = si->cpt_sack_array[2];
	tp->selective_acks[0].end_seq = si->cpt_sack_array[3];
	tp->selective_acks[1].start_seq = si->cpt_sack_array[4];
	tp->selective_acks[1].end_seq = si->cpt_sack_array[5];
	tp->selective_acks[2].start_seq = si->cpt_sack_array[6];
	tp->selective_acks[2].end_seq = si->cpt_sack_array[7];
	tp->selective_acks[3].start_seq = si->cpt_sack_array[8];
	tp->selective_acks[3].end_seq = si->cpt_sack_array[9];

	tp->window_clamp = si->cpt_window_clamp;
	tp->rcv_ssthresh = si->cpt_rcv_ssthresh;
	inet_csk(sk)->icsk_probes_out = si->cpt_probes_out;
	tp->rx_opt.num_sacks = si->cpt_num_sacks;
	tp->advmss = si->cpt_advmss;
	inet_csk(sk)->icsk_syn_retries = si->cpt_syn_retries;
	tp->ecn_flags = si->cpt_ecn_flags;
	tp->prior_ssthresh = si->cpt_prior_ssthresh;
	tp->high_seq = si->cpt_high_seq;
	tp->retrans_stamp = si->cpt_retrans_stamp;
	tp->undo_marker = si->cpt_undo_marker;
	tp->undo_retrans = si->cpt_undo_retrans;
	tp->urg_seq = si->cpt_urg_seq;
	tp->urg_data = si->cpt_urg_data;
	inet_csk(sk)->icsk_pending = si->cpt_pending;
	tp->snd_up = si->cpt_snd_up;
	tp->keepalive_time = si->cpt_keepalive_time;
	tp->keepalive_intvl = si->cpt_keepalive_intvl;
	tp->linger2 = si->cpt_linger2;

	sk->sk_send_head = NULL;
	for (skb = skb_peek(&sk->sk_write_queue);
	     skb && skb != (struct sk_buff*)&sk->sk_write_queue;
	     skb = skb->next) {
		if (!after(tp->snd_nxt, TCP_SKB_CB(skb)->seq)) {
			sk->sk_send_head = skb;
			break;
		}
	}

	if (sk->sk_state != TCP_CLOSE && sk->sk_state != TCP_LISTEN) {
		struct inet_sock *inet = inet_sk(sk);
		if (inet->num == 0) {
			cpt_object_t *lobj = NULL;

			if ((int)si->cpt_parent != -1)
				lobj = lookup_cpt_obj_byindex(CPT_OBJ_SOCKET, si->cpt_parent, ctx);

			if (lobj && lobj->o_obj) {
				inet->num = ntohs(inet->sport);
				local_bh_disable();
				__inet_inherit_port(lobj->o_obj, sk);
				local_bh_enable();
				dprintk_ctx("port inherited from parent\n");
			} else {
				struct sock *lsk = find_parent(inet->sport, ctx);
				if (lsk) {
					inet->num = ntohs(inet->sport);
					local_bh_disable();
					__inet_inherit_port(lsk, sk);
					local_bh_enable();
					dprintk_ctx("port inherited\n");
				} else {
					eprintk_ctx("we are kinda lost...\n");
				}
			}
		}

		sk->sk_prot->hash(sk);

		if (inet_csk(sk)->icsk_ack.pending&ICSK_ACK_TIMER)
			sk_reset_timer(sk, &inet_csk(sk)->icsk_delack_timer, inet_csk(sk)->icsk_ack.timeout);
		if (inet_csk(sk)->icsk_pending)
			sk_reset_timer(sk, &inet_csk(sk)->icsk_retransmit_timer,
				       inet_csk(sk)->icsk_timeout);
		if (sock_flag(sk, SOCK_KEEPOPEN)) {
			unsigned long expires = jiffies_import(si->cpt_ka_timeout);
			if (time_after(jiffies, expires))
				expires = jiffies + HZ;
			sk_reset_timer(sk, &sk->sk_timer, expires);
		}
	}

	if (sk->sk_family == AF_INET6)
		sk->sk_gso_type = SKB_GSO_TCPV6;
	else
		sk->sk_gso_type = SKB_GSO_TCPV4;

	return 0;
}
Exemple #24
0
static int cpt_dump_route(struct cpt_context * ctx)
{
	int err;
	struct socket *sock;
	struct msghdr msg;
	struct iovec iov;
	struct {
		struct nlmsghdr nlh;
		struct rtgenmsg g;
	} req;
	struct sockaddr_nl nladdr;
	struct cpt_object_hdr v;
	mm_segment_t oldfs;
	char *pg;

	err = sock_create(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE, &sock);
	if (err)
		return err;

	memset(&nladdr, 0, sizeof(nladdr));
	nladdr.nl_family = AF_NETLINK;

	req.nlh.nlmsg_len = sizeof(req);
	req.nlh.nlmsg_type = RTM_GETROUTE;
	req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
	req.nlh.nlmsg_pid = 0;
	req.g.rtgen_family = AF_INET;

	iov.iov_base=&req;
	iov.iov_len=sizeof(req);
	msg.msg_name=&nladdr;
	msg.msg_namelen=sizeof(nladdr);
	msg.msg_iov=&iov;
	msg.msg_iovlen=1;
	msg.msg_control=NULL;
	msg.msg_controllen=0;
	msg.msg_flags=MSG_DONTWAIT;

	oldfs = get_fs(); set_fs(KERNEL_DS);
	err = sock_sendmsg(sock, &msg, sizeof(req));
	set_fs(oldfs);

	if (err < 0)
		goto out_sock;

	pg = (char*)__get_free_page(GFP_KERNEL);
	if (pg == NULL) {
		err = -ENOMEM;
		goto out_sock;
	}

	cpt_open_section(ctx, CPT_SECT_NET_ROUTE);
	cpt_open_object(NULL, ctx);
	v.cpt_next = CPT_NULL;
	v.cpt_object = CPT_OBJ_NET_ROUTE;
	v.cpt_hdrlen = sizeof(v);
	v.cpt_content = CPT_CONTENT_NLMARRAY;

	ctx->write(&v, sizeof(v), ctx);

#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
restart:
#endif
	for (;;) {
		struct nlmsghdr *h;

		iov.iov_base = pg;
		iov.iov_len = PAGE_SIZE;

		oldfs = get_fs(); set_fs(KERNEL_DS);
		err = sock_recvmsg(sock, &msg, PAGE_SIZE, MSG_DONTWAIT);
		set_fs(oldfs);

		if (err < 0)
			goto out_sock_pg;
		if (msg.msg_flags & MSG_TRUNC) {
			err = -ENOBUFS;
			goto out_sock_pg;
		}

		h = (struct nlmsghdr*)pg;
		while (NLMSG_OK(h, err)) {
			if (h->nlmsg_type == NLMSG_DONE) {
				err = 0;
				goto done;
			}
			if (h->nlmsg_type == NLMSG_ERROR) {
				struct nlmsgerr *errm = (struct nlmsgerr*)NLMSG_DATA(h);
				err = errm->error;
				eprintk_ctx("NLMSG error: %d\n", errm->error);
				goto done;
			}
			if (h->nlmsg_type != RTM_NEWROUTE) {
				eprintk_ctx("NLMSG: %d\n", h->nlmsg_type);
				err = -EINVAL;
				goto done;
			}
			ctx->write(h, NLMSG_ALIGN(h->nlmsg_len), ctx);
			h = NLMSG_NEXT(h, err);
		}
		if (err) {
			eprintk_ctx("!!!Remnant of size %d %d %d\n", err, h->nlmsg_len, h->nlmsg_type);
			err = -EINVAL;
			break;
		}
	}
done:
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
	if (!err && req.g.rtgen_family == AF_INET) {
		req.g.rtgen_family = AF_INET6;
		iov.iov_base=&req;
		iov.iov_len=sizeof(req);
		msg.msg_name=&nladdr;
		msg.msg_namelen=sizeof(nladdr);
		msg.msg_iov=&iov;
		msg.msg_iovlen=1;
		msg.msg_control=NULL;
		msg.msg_controllen=0;
		msg.msg_flags=MSG_DONTWAIT;

		oldfs = get_fs(); set_fs(KERNEL_DS);
		err = sock_sendmsg(sock, &msg, sizeof(req));
		set_fs(oldfs);

		if (err > 0)
			goto restart;
	}
#endif
	ctx->align(ctx);
	cpt_close_object(ctx);
	cpt_close_section(ctx);

out_sock_pg:
	free_page((unsigned long)pg);
out_sock:
	sock_release(sock);
	return err;
}
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;
}
Exemple #26
0
struct file * rst_open_tty(cpt_object_t *mntobj, char *name,
			   struct cpt_file_image *fi, struct cpt_inode_image *ii,
			   unsigned flags, struct cpt_context *ctx)
{
	int err;
	cpt_object_t *obj;
	struct file *master, *slave;
	struct tty_struct *stty;
	struct cpt_tty_image *pi;
	static char *a = "pqrstuvwxyzabcde";
	static char *b = "0123456789abcdef";
	char pairname[16];
	unsigned master_flags, slave_flags;

	if (fi->cpt_priv == CPT_NULL)
		return ERR_PTR(-EINVAL);

	obj = lookup_cpt_obj_bypos(CPT_OBJ_TTY, fi->cpt_priv, ctx);
	if (obj && obj->o_parent) {
		dprintk_ctx("obtained pty as pair to existing\n");
		master = obj->o_parent;
		stty = file_tty(master);

		if (stty->driver->subtype == PTY_TYPE_MASTER &&
		    (stty->driver->flags&TTY_DRIVER_DEVPTS_MEM)) {
			wprintk_ctx("cloning ptmx\n");
			get_file(master);
			return master;
		}

		master = dentry_open(dget(master->f_dentry),
				     mntget(master->f_vfsmnt), flags,
				     current_cred());
		if (!IS_ERR(master)) {
			stty = file_tty(master);
			if (stty->driver->subtype != PTY_TYPE_MASTER)
				fixup_tty_attrs(ii, master, ctx);
		}
		return master;
	}

	pi = cpt_get_buf(ctx);
	err = rst_get_object(CPT_OBJ_TTY, fi->cpt_priv, pi, ctx);
	if (err) {
		cpt_release_buf(ctx);
		return ERR_PTR(err);
	}

	if (MAJOR(ii->cpt_rdev) == TTY_MAJOR ||
	    ii->cpt_rdev == MKDEV(TTYAUX_MAJOR, 1)) {
		if (mntobj && (mntobj->o_flags & CPT_VFSMOUNT_DELAYFS))
		       return ERR_PTR(-ENOTSUPP);
		master = rst_open_file(mntobj, name, fi,
				flags|O_NONBLOCK|O_NOCTTY, ctx);
		if (IS_ERR(master)) {
			eprintk_ctx("rst_open_tty: %s %Ld %ld\n",
					name, (long long)fi->cpt_priv,
					PTR_ERR(master));
			return master;
		}

		stty = file_tty(master);
		obj = cpt_object_add(CPT_OBJ_TTY, stty, ctx);
		obj->o_parent = master;
		cpt_obj_setpos(obj, fi->cpt_priv, ctx);

		obj = cpt_object_add(CPT_OBJ_FILE, master, ctx);
		cpt_obj_setpos(obj, CPT_NULL, ctx);
		get_file(master);

		/* Do not restore /dev/ttyX state */
		cpt_release_buf(ctx);
		return master;
	}

	master_flags = slave_flags = 0;
	if (pi->cpt_drv_subtype == PTY_TYPE_MASTER)
		master_flags = flags;
	else
		slave_flags = flags;

	/*
	 * Open pair master/slave.
	 */
	if (pi->cpt_drv_flags&TTY_DRIVER_DEVPTS_MEM) {
		master = ptmx_open(pi->cpt_index, master_flags);
	} else {
		sprintf(pairname, "/dev/pty%c%c", a[pi->cpt_index/16], b[pi->cpt_index%16]);
		master = filp_open(pairname, master_flags|O_NONBLOCK|O_NOCTTY|O_RDWR, 0);
	}
	if (IS_ERR(master)) {
		eprintk_ctx("filp_open master: %Ld %ld\n", (long long)fi->cpt_priv, PTR_ERR(master));
		cpt_release_buf(ctx);
		return master;
	}
	stty = file_tty(master);
	clear_bit(TTY_PTY_LOCK, &stty->flags);
	if (pi->cpt_drv_flags&TTY_DRIVER_DEVPTS_MEM)
		sprintf(pairname, "/dev/pts/%d", stty->index);
	else
		sprintf(pairname, "/dev/tty%c%c", a[stty->index/16], b[stty->index%16]);
	slave = filp_open(pairname, slave_flags|O_NONBLOCK|O_NOCTTY|O_RDWR, 0);
	if (IS_ERR(slave)) {
		eprintk_ctx("filp_open slave %s: %ld\n", pairname, PTR_ERR(slave));
		fput(master);
		cpt_release_buf(ctx);
		return slave;
	}

	if (pi->cpt_drv_subtype != PTY_TYPE_MASTER)
		fixup_tty_attrs(ii, slave, ctx);

	cpt_object_add(CPT_OBJ_TTY, file_tty(master), ctx);
	cpt_object_add(CPT_OBJ_TTY, file_tty(slave), ctx);
	cpt_object_add(CPT_OBJ_FILE, master, ctx);
	cpt_object_add(CPT_OBJ_FILE, slave, ctx);

	if (pi->cpt_drv_subtype == PTY_TYPE_MASTER) {
		loff_t pos;
		obj = lookup_cpt_object(CPT_OBJ_TTY, file_tty(master), ctx);
		obj->o_parent = master;
		cpt_obj_setpos(obj, fi->cpt_priv, ctx);
		pty_setup(stty, fi->cpt_priv, pi, ctx);

		obj = lookup_cpt_object(CPT_OBJ_TTY, file_tty(slave), ctx);
		obj->o_parent = slave;
		pos = find_pty_pair(stty->link, fi->cpt_priv, pi, ctx);
		cpt_obj_setpos(obj, pos, ctx);

		obj = lookup_cpt_object(CPT_OBJ_FILE, slave, ctx);
		cpt_obj_setpos(obj, CPT_NULL, ctx);
		get_file(master);
		cpt_release_buf(ctx);
		return master;
	} else {
		loff_t pos;
		obj = lookup_cpt_object(CPT_OBJ_TTY, file_tty(slave), ctx);
		obj->o_parent = slave;
		cpt_obj_setpos(obj, fi->cpt_priv, ctx);
		pty_setup(stty->link, fi->cpt_priv, pi, ctx);

		obj = lookup_cpt_object(CPT_OBJ_TTY, file_tty(master), ctx);
		obj->o_parent = master;
		pos = find_pty_pair(stty, fi->cpt_priv, pi, ctx);
		cpt_obj_setpos(obj, pos, ctx);

		obj = lookup_cpt_object(CPT_OBJ_FILE, master, ctx);
		cpt_obj_setpos(obj, CPT_NULL, ctx);
		get_file(slave);
		cpt_release_buf(ctx);
		return slave;
	}
}
Exemple #27
0
int rst_sockets(struct cpt_context *ctx)
{
    int err;
    loff_t sec = ctx->sections[CPT_SECT_SOCKET];
    loff_t endsec;
    cpt_object_t *obj;
    struct cpt_section_hdr h;

    if (sec == CPT_NULL)
        return 0;

    err = ctx->pread(&h, sizeof(h), ctx, sec);
    if (err) {
        eprintk_ctx("rst_sockets: ctx->pread: %d\n", err);
        return err;
    }
    if (h.cpt_section != CPT_SECT_SOCKET || h.cpt_hdrlen < sizeof(h)) {
        eprintk_ctx("rst_sockets: hdr err\n");
        return -EINVAL;
    }

    /* The first pass: we create socket index and open listening sockets. */
    endsec = sec + h.cpt_next;
    sec += h.cpt_hdrlen;
    while (sec < endsec) {
        struct cpt_sock_image *sbuf = cpt_get_buf(ctx);
        err = rst_get_object(CPT_OBJ_SOCKET, sec, sbuf, ctx);
        if (err) {
            eprintk_ctx("rst_sockets: rst_get_object: %d\n", err);
            cpt_release_buf(ctx);
            return err;
        }
        if (sbuf->cpt_state == TCP_LISTEN) {
            err = open_listening_socket(sec, sbuf, ctx);
            cpt_release_buf(ctx);
            if (err) {
                eprintk_ctx("rst_sockets: open_listening_socket: %d\n", err);
                return err;
            }
        } else {
            cpt_release_buf(ctx);
            obj = alloc_cpt_object(GFP_KERNEL, ctx);
            if (obj == NULL)
                return -ENOMEM;
            cpt_obj_setindex(obj, sbuf->cpt_index, ctx);
            cpt_obj_setpos(obj, sec, ctx);
            obj->o_ppos  = sbuf->cpt_file;
            intern_cpt_object(CPT_OBJ_SOCKET, obj, ctx);
        }
        sec += sbuf->cpt_next;
    }

    /* Pass 2: really restore sockets */
    for_each_object(obj, CPT_OBJ_SOCKET) {
        struct cpt_sock_image *sbuf;
        if (obj->o_obj != NULL)
            continue;
        sbuf = cpt_get_buf(ctx);
        err = rst_get_object(CPT_OBJ_SOCKET, obj->o_pos, sbuf, ctx);
        if (err) {
            eprintk_ctx("rst_sockets: rst_get_object: %d\n", err);
            cpt_release_buf(ctx);
            return err;
        }
        if (sbuf->cpt_state == TCP_LISTEN) BUG();
        err = open_socket(obj, sbuf, ctx);
        cpt_release_buf(ctx);
        if (err) {
            eprintk_ctx("rst_sockets: open_socket: %d\n", err);
            return err;
        }
    }

    return 0;
}
Exemple #28
0
int cpt_dump_tty(cpt_object_t *obj, struct cpt_context *ctx)
{
	struct tty_struct *tty = obj->o_obj;
	struct cpt_tty_image *v;

	if (tty->link) {
		if (lookup_cpt_object(CPT_OBJ_TTY, tty->link, ctx) == NULL) {
			eprintk_ctx("orphan pty %s %d\n", tty->name, tty->driver->subtype == PTY_TYPE_SLAVE);
			return -EINVAL;
		}
		if (tty->link->link != tty) {
			eprintk_ctx("bad pty pair\n");
			return -EINVAL;
		}
		if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
		    tty->driver->subtype == PTY_TYPE_SLAVE &&
		    tty->link->count)
			obj->o_count++;
	}
	if (obj->o_count != tty->count) {
		eprintk_ctx("tty %s is referenced outside %d %d\n", tty->name, obj->o_count, tty->count);
		return -EBUSY;
	}

	cpt_open_object(obj, ctx);

	v = cpt_get_buf(ctx);
	v->cpt_next = -1;
	v->cpt_object = CPT_OBJ_TTY;
	v->cpt_hdrlen = sizeof(*v);
	v->cpt_content = CPT_CONTENT_ARRAY;

	v->cpt_index = tty->index;
	v->cpt_link = -1;
	if (tty->link)
		v->cpt_link = tty->link->index;
	v->cpt_drv_type = tty->driver->type;
	v->cpt_drv_subtype = tty->driver->subtype;
	v->cpt_drv_flags = tty->driver->flags;
	v->cpt_packet = tty->packet;
	v->cpt_stopped = tty->stopped;
	v->cpt_hw_stopped = tty->hw_stopped;
	v->cpt_flow_stopped = tty->flow_stopped;
	v->cpt_flags = tty->flags;
	v->cpt_ctrl_status = tty->ctrl_status;
	v->cpt_canon_data = tty->canon_data;
	v->cpt_canon_head = tty->canon_head - tty->read_tail;
	v->cpt_canon_column = tty->canon_column;
	v->cpt_column = tty->column;
	v->cpt_erasing = tty->erasing;
	v->cpt_lnext = tty->lnext;
	v->cpt_icanon = tty->icanon;
	v->cpt_raw = tty->raw;
	v->cpt_real_raw = tty->real_raw;
	v->cpt_closing = tty->closing;
	v->cpt_minimum_to_wake = tty->minimum_to_wake;
	v->cpt_pgrp = 0;
	if (tty->pgrp) {
		v->cpt_pgrp = pid_vnr(tty->pgrp);
		if ((int)v->cpt_pgrp < 0) {
			dprintk_ctx("cannot map tty->pgrp %d -> %d\n", pid_vnr(tty->pgrp), (int)v->cpt_pgrp);
			v->cpt_pgrp = -1;
		}
	}
	v->cpt_session = 0;
	if (tty->session) {
		v->cpt_session = pid_vnr(tty->session);
		if ((int)v->cpt_session < 0) {
			eprintk_ctx("cannot map tty->session %d -> %d\n", pid_nr(tty->session), (int)v->cpt_session);
			cpt_release_buf(ctx);
			return -EINVAL;
		}
	}
	memcpy(v->cpt_name, tty->name, 64);
	v->cpt_ws_row = tty->winsize.ws_row;
	v->cpt_ws_col = tty->winsize.ws_col;
	v->cpt_ws_prow = tty->winsize.ws_ypixel;
	v->cpt_ws_pcol = tty->winsize.ws_xpixel;
	if (tty->termios == NULL) {
		eprintk_ctx("NULL termios");
		cpt_release_buf(ctx);
		return -EINVAL;
	}
	v->cpt_c_line = tty->termios->c_line;
	v->cpt_c_iflag = tty->termios->c_iflag;
	v->cpt_c_oflag = tty->termios->c_oflag;
	v->cpt_c_cflag = tty->termios->c_cflag;
	v->cpt_c_lflag = tty->termios->c_lflag;
	memcpy(v->cpt_c_cc, tty->termios->c_cc, NCCS);
	if (NCCS < 32)
		memset(v->cpt_c_cc + NCCS, 255, 32 - NCCS);
	memcpy(v->cpt_read_flags, tty->read_flags, sizeof(v->cpt_read_flags));

	ctx->write(v, sizeof(*v), ctx);
	cpt_release_buf(ctx);

	if (tty->read_buf && tty->read_cnt) {
		struct cpt_obj_bits *v = cpt_get_buf(ctx);
		loff_t saved_pos;

		cpt_push_object(&saved_pos, ctx);
		cpt_open_object(NULL, ctx);
		v->cpt_next = CPT_NULL;
		v->cpt_object = CPT_OBJ_BITS;
		v->cpt_hdrlen = sizeof(*v);
		v->cpt_content = CPT_CONTENT_DATA;
		v->cpt_size = tty->read_cnt;
		ctx->write(v, sizeof(*v), ctx);
		cpt_release_buf(ctx);

		if (tty->read_cnt) {
			int n = min(tty->read_cnt, N_TTY_BUF_SIZE - tty->read_tail);
			ctx->write(tty->read_buf + tty->read_tail, n, ctx);
			if (tty->read_cnt > n)
				ctx->write(tty->read_buf, tty->read_cnt-n, ctx);
			ctx->align(ctx);
		}

		cpt_close_object(ctx);
		cpt_pop_object(&saved_pos, ctx);
	}

	cpt_close_object(ctx);

	return 0;
}