#include "linux/vswitch.h" #include "linux/namespace.h" #include "linux/legacy.h" #include "linux/limit_cmd.h" #include "linux/context_cmd.h" #include #include #include #define _UNISTD_H #ifndef PROTO_SKIP extern "C" long int syscall (long int __sysno, ...) __THROW; #endif #include #include "old_syscall.p" #include #ifndef __NR_vserver # define __NR_vserver 273 #endif static enum KERNEL_TYPE{ K_UNKNOWN, // Do not support vserver at all K_NEW, // New vserver kernel K_OLD // Old vserver kernel } state = K_UNKNOWN; _syscall3(int, vserver, uint32_t, cmd, uint32_t, id, void *, data); static void init() { if (state == K_UNKNOWN){ int ret = vserver (VCMD_get_version,0,NULL); if (ret == -1){ state = K_OLD; }else{ state = K_NEW; } } } extern "C" int call_new_s_context( int nbctx, int ctxs[], unsigned int remove_cap, unsigned long long flags, unsigned long long flagmask) { int ret = -1; init(); #if 0 fprintf (stderr,"new_s_context ctx=%d %x %Lx\n" ,ctxs != NULL ? ctxs[0] : -10 ,remove_cap,flags); #endif if (state == K_NEW){ if (ctxs != NULL){ if (ctxs[0] == 1){ ret = vserver (VCMD_ctx_migrate,1,NULL); }else{ ret = vserver (VCMD_ctx_create,ctxs[0],NULL); //fprintf (stderr,"After create ctxs[0]=%d ret=%d errno=%d %d\n",ctxs[0],ret,errno,EINVAL); //if (ret == -1 && ((int)errno == EEXIST || (int)errno == EINVAL)){ if (ret == -1){ // In older kernel, it returns EINVAL instead of EEXIST // Since we know we are calling properly, we try // a migrate whenever we get an error ret = vserver (VCMD_ctx_migrate,ctxs[0],NULL); // fprintf (stderr,"After migrate ctxs[0]=%d ret=%d errno=%d\n",ctxs[0],ret,errno); flagmask = 0; // We can't set the flags // if we migrate remove_cap = 0; } } }else{ ret = 0; } if (ret != -1 && remove_cap != 0){ vcmd_ctx_caps_v0 data; data.bcaps = (unsigned long long)-1 & (~remove_cap); data.ccaps = 0; data.cmask = (unsigned long long)-1; int fret = vserver (VCMD_set_ccaps,(unsigned)-1,&data); if (fret == -1){ //fprintf (stderr,"set_ccaps %d %d\n",fret,errno); ret = -1; } } if (ret != -1 && flagmask != 0){ vcmd_ctx_flags_v0 data; data.flagword = flags; data.mask = flagmask; int fret = vserver (VCMD_set_cflags,(unsigned)-1,&data); if (fret == -1){ //fprintf (stderr,"set_flags %d %d\n",fret,errno); ret = -1; } } // fprintf (stderr,"End new_s_context\n"); #if 0 vcmd_new_s_context_v1 data; data.remove_cap = remove_cap; data.flags = flags; ret = vserver (VCMD_new_s_context,nbctx==0 ? -2 : ctxs[0],&data); #endif }else{ ret = call_old_new_s_context (nbctx,ctxs,remove_cap,flags); } return ret; } extern "C" int call_set_ipv4root( unsigned long ip[], int nb, unsigned long bcast, unsigned long mask[]) { int ret = -1; init(); if (state == K_NEW){ vcmd_set_ipv4root_v3 data; data.broadcast = bcast; for (int i=0; i