Example #1
0
File: vlan.c Project: PterX/rt-n56u
/*
 *	VLAN IOCTL handler.
 *	o execute requested action or pass command to the device driver
 *   arg is really a struct vlan_ioctl_args __user *.
 */
static int vlan_ioctl_handler(struct net *net, void __user *arg)
{
	int err;
	struct vlan_ioctl_args args;
	struct net_device *dev = NULL;

	if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args)))
		return -EFAULT;

	/* Null terminate this sucker, just in case. */
	args.device1[23] = 0;
	args.u.device2[23] = 0;

	rtnl_lock();

	switch (args.cmd) {
	case SET_VLAN_INGRESS_PRIORITY_CMD:
	case SET_VLAN_EGRESS_PRIORITY_CMD:
	case SET_VLAN_FLAG_CMD:
	case ADD_VLAN_CMD:
	case DEL_VLAN_CMD:
	case GET_VLAN_REALDEV_NAME_CMD:
	case GET_VLAN_VID_CMD:
		err = -ENODEV;
		dev = __dev_get_by_name(net, args.device1);
		if (!dev)
			goto out;

		err = -EINVAL;
		if (args.cmd != ADD_VLAN_CMD && !is_vlan_dev(dev))
			goto out;
	}

	switch (args.cmd) {
	case SET_VLAN_INGRESS_PRIORITY_CMD:
		err = -EPERM;
		if (!capable(CAP_NET_ADMIN))
			break;
		vlan_dev_set_ingress_priority(dev,
					      args.u.skb_priority,
					      args.vlan_qos);
		err = 0;
		break;

	case SET_VLAN_EGRESS_PRIORITY_CMD:
		err = -EPERM;
		if (!capable(CAP_NET_ADMIN))
			break;
		err = vlan_dev_set_egress_priority(dev,
						   args.u.skb_priority,
						   args.vlan_qos);
		break;

	case SET_VLAN_FLAG_CMD:
		err = -EPERM;
		if (!capable(CAP_NET_ADMIN))
			break;
		err = vlan_dev_change_flags(dev,
					    args.vlan_qos ? args.u.flag : 0,
					    args.u.flag);
		break;

	case SET_VLAN_NAME_TYPE_CMD:
		err = -EPERM;
		if (!capable(CAP_NET_ADMIN))
			break;
		if ((args.u.name_type >= 0) &&
		    (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
			struct vlan_net *vn;

			vn = net_generic(net, vlan_net_id);
			vn->name_type = args.u.name_type;
			err = 0;
		} else {
			err = -EINVAL;
		}
		break;

	case ADD_VLAN_CMD:
		err = -EPERM;
		if (!capable(CAP_NET_ADMIN))
			break;
		err = register_vlan_device(dev, args.u.VID);
		break;

	case DEL_VLAN_CMD:
		err = -EPERM;
		if (!capable(CAP_NET_ADMIN))
			break;
		unregister_vlan_dev(dev, NULL);
		err = 0;
		break;

	case GET_VLAN_REALDEV_NAME_CMD:
		err = 0;
		vlan_dev_get_realdev_name(dev, args.u.device2);
		if (copy_to_user(arg, &args,
				 sizeof(struct vlan_ioctl_args)))
			err = -EFAULT;
		break;

	case GET_VLAN_VID_CMD:
		err = 0;
		args.u.VID = vlan_dev_vlan_id(dev);
		if (copy_to_user(arg, &args,
				 sizeof(struct vlan_ioctl_args)))
		      err = -EFAULT;
		break;

	default:
		err = -EOPNOTSUPP;
		break;
	}
out:
	rtnl_unlock();
	return err;
}
/*
 *	VLAN IOCTL handler.
 *	o execute requested action or pass command to the device driver
 *   arg is really a void* to a vlan_ioctl_args structure.
 */
int vlan_ioctl_handler(unsigned long arg)
{
	int err = 0;
        unsigned short vid = 0;
	struct vlan_ioctl_args args;

	if (copy_from_user(&args, (void*)arg,
                           sizeof(struct vlan_ioctl_args)))
		return -EFAULT;

	/* Null terminate this sucker, just in case. */
	args.device1[23] = 0;
	args.u.device2[23] = 0;

#ifdef VLAN_DEBUG
	printk(VLAN_DBG "%s: args.cmd: %x\n", __FUNCTION__, args.cmd);
#endif

	switch (args.cmd) {
	case SET_VLAN_INGRESS_PRIORITY_CMD:
		if (!capable(CAP_NET_ADMIN))
			return -EPERM;

		err = vlan_dev_set_ingress_priority(args.device1,
						    args.u.skb_priority,
						    args.vlan_qos);
		break;

	case SET_VLAN_EGRESS_PRIORITY_CMD:
		if (!capable(CAP_NET_ADMIN))
			return -EPERM;
		err = vlan_dev_set_egress_priority(args.device1,
						   args.u.skb_priority,
						   args.vlan_qos);
		break;

	case SET_VLAN_FLAG_CMD:
		if (!capable(CAP_NET_ADMIN))
			return -EPERM;
		err = vlan_dev_set_vlan_flag(args.device1,
					     args.u.flag,
					     args.vlan_qos);
		break;

	case SET_VLAN_NAME_TYPE_CMD:
		if (!capable(CAP_NET_ADMIN))
			return -EPERM;
		if ((args.u.name_type >= 0) &&
		    (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
			vlan_name_type = args.u.name_type;
			err = 0;
		} else {
			err = -EINVAL;
		}
		break;

	case ADD_VLAN_CMD:
		if (!capable(CAP_NET_ADMIN))
			return -EPERM;
		/* we have been given the name of the Ethernet Device we want to
		 * talk to:  args.dev1	 We also have the
		 * VLAN ID:  args.u.VID
		 */
		if (register_vlan_device(args.device1, args.u.VID)) {
			err = 0;
		} else {
			err = -EINVAL;
		}
		break;

	case DEL_VLAN_CMD:
		if (!capable(CAP_NET_ADMIN))
			return -EPERM;
		/* Here, the args.dev1 is the actual VLAN we want
		 * to get rid of.
		 */
		err = unregister_vlan_device(args.device1);
		break;

	case GET_VLAN_INGRESS_PRIORITY_CMD:
		/* TODO:  Implement
		err = vlan_dev_get_ingress_priority(args);
		if (copy_to_user((void*)arg, &args,
				 sizeof(struct vlan_ioctl_args))) {
			err = -EFAULT;
		}
		*/
		err = -EINVAL;
		break;

	case GET_VLAN_EGRESS_PRIORITY_CMD:
		/* TODO:  Implement
		err = vlan_dev_get_egress_priority(args.device1, &(args.args);
		if (copy_to_user((void*)arg, &args,
				 sizeof(struct vlan_ioctl_args))) {
			err = -EFAULT;
		}
		*/
		err = -EINVAL;
		break;

	case GET_VLAN_REALDEV_NAME_CMD:
		err = vlan_dev_get_realdev_name(args.device1, args.u.device2);
		if (copy_to_user((void*)arg, &args,
				 sizeof(struct vlan_ioctl_args))) {
			err = -EFAULT;
		}
		break;

	case GET_VLAN_VID_CMD:
		err = vlan_dev_get_vid(args.device1, &vid);
		args.u.VID = vid;
		if (copy_to_user((void*)arg, &args,
				 sizeof(struct vlan_ioctl_args))) {
			err = -EFAULT;
		}
		break;
		
	default:
		/* pass on to underlying device instead?? */
		printk(VLAN_DBG "%s: Unknown VLAN CMD: %x \n",
			__FUNCTION__, args.cmd);
		return -EINVAL;
	};

	return err;
}