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; }
static void cpt_dump_netstats(struct net_device *dev, struct cpt_context * ctx) { struct cpt_netstats_image *n; struct net_device_stats *stats; if (!dev->netdev_ops->ndo_get_stats) return; n = cpt_get_buf(ctx); stats = dev->netdev_ops->ndo_get_stats(dev); cpt_open_object(NULL, ctx); n->cpt_next = CPT_NULL; n->cpt_object = CPT_OBJ_NET_STATS; n->cpt_hdrlen = sizeof(*n); n->cpt_content = CPT_CONTENT_VOID; n->cpt_rx_packets = stats->rx_packets; n->cpt_tx_packets = stats->tx_packets; n->cpt_rx_bytes = stats->rx_bytes; n->cpt_tx_bytes = stats->tx_bytes; n->cpt_rx_errors = stats->rx_errors; n->cpt_tx_errors = stats->tx_errors; n->cpt_rx_dropped = stats->rx_dropped; n->cpt_tx_dropped = stats->tx_dropped; n->cpt_multicast = stats->multicast; n->cpt_collisions = stats->collisions; n->cpt_rx_length_errors = stats->rx_length_errors; n->cpt_rx_over_errors = stats->rx_over_errors; n->cpt_rx_crc_errors = stats->rx_crc_errors; n->cpt_rx_frame_errors = stats->rx_frame_errors; n->cpt_rx_fifo_errors = stats->rx_fifo_errors; n->cpt_rx_missed_errors = stats->rx_missed_errors; n->cpt_tx_aborted_errors = stats->tx_aborted_errors; n->cpt_tx_carrier_errors = stats->tx_carrier_errors; n->cpt_tx_fifo_errors = stats->tx_fifo_errors; n->cpt_tx_heartbeat_errors = stats->tx_heartbeat_errors; n->cpt_tx_window_errors = stats->tx_window_errors; n->cpt_rx_compressed = stats->rx_compressed; n->cpt_tx_compressed = stats->tx_compressed; ctx->write(n, sizeof(*n), ctx); cpt_close_object(ctx); cpt_release_buf(ctx); return; }
static void cpt_push(loff_t *p, struct cpt_context *ctx) { cpt_push_object(p, ctx); cpt_open_object(NULL, ctx); }
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 {
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; }
int cpt_dump_ifaddr(struct cpt_context * ctx) { struct net *net = get_exec_env()->ve_netns; struct net_device *dev; cpt_open_section(ctx, CPT_SECT_NET_IFADDR); for_each_netdev(net, dev) { struct in_device *idev = in_dev_get(dev); struct in_ifaddr *ifa; if (!idev) continue; for (ifa = idev->ifa_list; ifa; ifa = ifa->ifa_next) { struct cpt_ifaddr_image v; cpt_open_object(NULL, ctx); v.cpt_next = CPT_NULL; v.cpt_object = CPT_OBJ_NET_IFADDR; v.cpt_hdrlen = sizeof(v); v.cpt_content = CPT_CONTENT_VOID; v.cpt_index = dev->ifindex; v.cpt_family = AF_INET; v.cpt_masklen = ifa->ifa_prefixlen; v.cpt_flags = ifa->ifa_flags; v.cpt_scope = ifa->ifa_scope; memset(&v.cpt_address, 0, sizeof(v.cpt_address)); memset(&v.cpt_peer, 0, sizeof(v.cpt_peer)); memset(&v.cpt_broadcast, 0, sizeof(v.cpt_broadcast)); v.cpt_address[0] = ifa->ifa_local; v.cpt_peer[0] = ifa->ifa_address; v.cpt_broadcast[0] = ifa->ifa_broadcast; memcpy(v.cpt_label, ifa->ifa_label, IFNAMSIZ); ctx->write(&v, sizeof(v), ctx); cpt_close_object(ctx); } in_dev_put(idev); } #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) for_each_netdev(net, dev) { struct inet6_dev *idev = in6_dev_get(dev); struct inet6_ifaddr *ifa; if (!idev) continue; for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) { struct cpt_ifaddr_image v; if (dev == net->loopback_dev && ifa->prefix_len == 128 && ifa->addr.s6_addr32[0] == 0 && ifa->addr.s6_addr32[1] == 0 && ifa->addr.s6_addr32[2] == 0 && ifa->addr.s6_addr32[3] == htonl(1)) continue; cpt_open_object(NULL, ctx); v.cpt_next = CPT_NULL; v.cpt_object = CPT_OBJ_NET_IFADDR; v.cpt_hdrlen = sizeof(v); v.cpt_content = CPT_CONTENT_VOID; v.cpt_index = dev->ifindex; v.cpt_family = AF_INET6; v.cpt_masklen = ifa->prefix_len; v.cpt_flags = ifa->flags; v.cpt_scope = ifa->scope; v.cpt_valid_lft = ifa->valid_lft; v.cpt_prefered_lft = ifa->prefered_lft; memcpy(&v.cpt_address, &ifa->addr, 16); memcpy(&v.cpt_peer, &ifa->addr, 16); memset(&v.cpt_broadcast, 0, sizeof(v.cpt_broadcast)); memcpy(v.cpt_label, dev->name, IFNAMSIZ); ctx->write(&v, sizeof(v), ctx); cpt_close_object(ctx); } in6_dev_put(idev); } #endif cpt_close_section(ctx); return 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; }