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 {
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 {