--- ./drivers/net/ppp_generic.c.original 2006-09-20 07:42:06.000000000 +0400 +++ ./drivers/net/ppp_generic.c 2008-06-11 15:04:14.000000000 +0400 @@ -47,6 +47,9 @@ #include #include #include +#include +#include +#include #define PPP_VERSION "2.4.2" @@ -196,14 +199,32 @@ static unsigned int cardmap_find_first_free(struct cardmap *map); static void cardmap_destroy(struct cardmap **map); +#ifdef CONFIG_VE +struct ve_ppp { + /* INTERFACE related attributes: */ + struct cardmap *_all_ppp_units; + atomic_t _ppp_unit_count; + /* CHANNEL related attributes: */ + struct list_head _all_channels; + struct list_head _new_channels; + int _last_channel_index; + atomic_t _channel_count; +}; +#endif + /* * all_ppp_mutex protects the all_ppp_units mapping. * It also ensures that finding a ppp unit in the all_ppp_units map * and updating its file.refcnt field is atomic. */ static DEFINE_MUTEX(all_ppp_mutex); +#ifdef CONFIG_VE +#define all_ppp_units (get_exec_env()->_ve_ppp->_all_ppp_units) +#define ppp_unit_count (get_exec_env()->_ve_ppp->_ppp_unit_count) +#else static struct cardmap *all_ppp_units; static atomic_t ppp_unit_count = ATOMIC_INIT(0); +#endif /* * all_channels_lock protects all_channels and last_channel_index, @@ -211,10 +232,17 @@ * field. */ static DEFINE_SPINLOCK(all_channels_lock); +#ifdef CONFIG_VE +#define all_channels (get_exec_env()->_ve_ppp->_all_channels) +#define new_channels (get_exec_env()->_ve_ppp->_new_channels) +#define last_channel_index (get_exec_env()->_ve_ppp->_last_channel_index) +#define channel_count (get_exec_env()->_ve_ppp->_channel_count) +#else static LIST_HEAD(all_channels); static LIST_HEAD(new_channels); static int last_channel_index; static atomic_t channel_count = ATOMIC_INIT(0); +#endif /* Get the PPP protocol number from a skb */ #define PPP_PROTO(skb) (((skb)->data[0] << 8) + (skb)->data[1]) @@ -360,7 +388,7 @@ /* * This could (should?) be enforced by the permissions on /dev/ppp. */ - if (!capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN) && !capable(CAP_VE_NET_ADMIN)) return -EPERM; return 0; } @@ -846,6 +874,64 @@ #define PPP_MAJOR 108 +#ifdef CONFIG_VE +static int ppp_ve_start(void *data) +{ + struct ve_struct *env; + int ret = 0; + + env = (struct ve_struct *)data; + //if (!ve_is_super(env) && !(env->features & VE_FEATURE_PPP)) + // return ret; + + if (!ve_is_super(env)) + __module_get(THIS_MODULE); + + env->_ve_ppp = kmalloc(sizeof(struct ve_ppp), GFP_KERNEL); + if (!env->_ve_ppp) { + ret = -ENOMEM; + goto out_put; + } + memset(env->_ve_ppp, 0, sizeof(struct ve_ppp)); + + atomic_set(&ppp_unit_count, 0); + INIT_LIST_HEAD(&all_channels); + INIT_LIST_HEAD(&new_channels); + atomic_set(&channel_count, 0); + +out: + return ret; +out_put: + if (!ve_is_super(env)) + module_put(THIS_MODULE); + goto out; +} + +static void ppp_ve_stop(void *data) +{ + struct ve_struct *env; + + env = (struct ve_struct *)data; + if (env->_ve_ppp == NULL) + return; + + kfree(env->_ve_ppp); + env->_ve_ppp = NULL; + if (!ve_is_super(env)) + module_put(THIS_MODULE); +} + +static struct ve_hook ppp_ve_hook = { + .init = ppp_ve_start, + .fini = ppp_ve_stop, + .owner = THIS_MODULE, + .priority = HOOK_PRIO_NET_POST, +}; +#else +#define ppp_ve_start(t) do { } while (0) +#define ppp_ve_stop(t) do { } while (0) +#endif + /* Called at boot time if ppp is compiled into the kernel, or at module load time (from init_module) if compiled as a module. */ static int __init ppp_init(void) @@ -863,6 +949,11 @@ class_device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL, "ppp"); } + err = ppp_ve_start(get_exec_env()); + if (err) + goto out_chrdev; + + ve_hook_register(VE_SS_CHAIN, &ppp_ve_hook); out: if (err) printk(KERN_ERR "failed to register PPP device (%d)\n", err); @@ -988,6 +1079,7 @@ dev->tx_queue_len = 3; dev->type = ARPHRD_PPP; dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + dev->features |= NETIF_F_VIRTUAL; } /* @@ -1995,6 +2087,9 @@ { struct channel *pch; + if (!ve_is_super(get_exec_env()) && !(get_exec_env()->_ve_ppp)) + return -EFAULT; + pch = kzalloc(sizeof(struct channel), GFP_KERNEL); if (pch == 0) return -ENOMEM; @@ -2669,10 +2764,13 @@ static void __exit ppp_cleanup(void) { + ve_hook_unregister(&ppp_ve_hook); /* should never happen */ if (atomic_read(&ppp_unit_count) || atomic_read(&channel_count)) printk(KERN_ERR "PPP: removing module but units remain!\n"); cardmap_destroy(&all_ppp_units); + ppp_ve_stop(get_exec_env()); + if (unregister_chrdev(PPP_MAJOR, "ppp") != 0) printk(KERN_ERR "PPP: failed to unregister PPP device\n"); class_device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0)); --- ./include/linux/vzcalluser.h.original 2008-06-11 13:35:59.000000000 +0400 +++ ./include/linux/vzcalluser.h 2008-06-11 15:04:14.000000000 +0400 @@ -148,6 +148,7 @@ #define VE_FEATURE_SYSFS (1ULL << 0) #define VE_FEATURE_NFS (1ULL << 1) #define VE_FEATURE_DEF_PERMS (1ULL << 2) +#define VE_FEATURE_PPP (1ULL << 6) #define VE_FEATURES_OLD (VE_FEATURE_SYSFS) #define VE_FEATURES_DEF (VE_FEATURE_SYSFS | \ --- ./include/linux/ve.h.original 2008-06-11 13:36:03.000000000 +0400 +++ ./include/linux/ve.h 2008-06-11 15:08:17.000000000 +0400 @@ -117,6 +117,7 @@ } ____cacheline_aligned; struct ve_ipt_recent; +struct ve_ppp; struct ve_ipt_hashlimit; struct ve_struct { @@ -197,6 +198,9 @@ int ifindex; struct net_device *_loopback_dev; struct net_device_stats *_loopback_stats; +#if defined(CONFIG_PPP) || defined(CONFIG_PPP_MODULE) + struct ve_ppp *_ve_ppp; +#endif #ifdef CONFIG_INET struct ipv4_devconf *_ipv4_devconf; struct ipv4_devconf *_ipv4_devconf_dflt; --- ./include/linux/if_ppp.h.original 2006-09-20 07:42:06.000000000 +0400 +++ ./include/linux/if_ppp.h 2008-06-11 15:04:14.000000000 +0400 @@ -113,6 +113,10 @@ #define ifr__name b.ifr_ifrn.ifrn_name #define stats_ptr b.ifr_ifru.ifru_data +#ifdef CONFIG_VE +struct ve_ppp; +#endif + /* * Ioctl definitions. */