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; }
int cpt_dump_tail(struct cpt_context *ctx) { struct cpt_major_tail hdr; int i; if (ctx->file == NULL) return 0; cpt_open_section(ctx, CPT_SECT_TRAILER); memset(&hdr, 0, sizeof(hdr)); hdr.cpt_next = sizeof(hdr); hdr.cpt_object = CPT_OBJ_TRAILER; hdr.cpt_hdrlen = sizeof(hdr); hdr.cpt_content = CPT_CONTENT_VOID; hdr.cpt_lazypages = 0; #ifdef CONFIG_VZ_CHECKPOINT_LAZY hdr.cpt_lazypages = ctx->lazypages; #endif hdr.cpt_64bit = ctx->tasks64; hdr.cpt_signature[0] = CPT_SIGNATURE0; hdr.cpt_signature[1] = CPT_SIGNATURE1; hdr.cpt_signature[2] = CPT_SIGNATURE2; hdr.cpt_signature[3] = CPT_SIGNATURE3; hdr.cpt_nsect = CPT_SECT_MAX_INDEX; for (i = 0; i < CPT_SECT_MAX_INDEX; i++) hdr.cpt_sections[i] = ctx->sections[i]; ctx->write(&hdr, sizeof(hdr), ctx); cpt_close_section(ctx); return 0; }
int cpt_open_section(struct cpt_context *ctx, __u32 type) { struct cpt_section_hdr hdr; if (ctx->file == NULL) return 0; cpt_close_section(ctx); ctx->current_section = ctx->file->f_pos; ctx->sections[type] = ctx->current_section; hdr.cpt_next = 0; hdr.cpt_section = type; hdr.cpt_hdrlen = sizeof(hdr); hdr.cpt_align = 0; ctx->write(&hdr, sizeof(hdr), ctx); return 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; }
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; }