Commit eb637cb2 authored by Ben Greear's avatar Ben Greear Committed by David S. Miller

[VLAN]: Sync code and feature set with 2.4.x

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 234d5bda
...@@ -366,7 +366,9 @@ enum vlan_ioctl_cmds { ...@@ -366,7 +366,9 @@ enum vlan_ioctl_cmds {
GET_VLAN_INGRESS_PRIORITY_CMD, GET_VLAN_INGRESS_PRIORITY_CMD,
GET_VLAN_EGRESS_PRIORITY_CMD, GET_VLAN_EGRESS_PRIORITY_CMD,
SET_VLAN_NAME_TYPE_CMD, SET_VLAN_NAME_TYPE_CMD,
SET_VLAN_FLAG_CMD SET_VLAN_FLAG_CMD,
GET_VLAN_REALDEV_NAME_CMD, /* If this works, you know it's a VLAN device, btw */
GET_VLAN_VID_CMD /* Get the VID of this VLAN (specified by name) */
}; };
enum vlan_name_types { enum vlan_name_types {
......
...@@ -647,15 +647,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, ...@@ -647,15 +647,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
static int vlan_ioctl_handler(void __user *arg) static int vlan_ioctl_handler(void __user *arg)
{ {
int err = 0; int err = 0;
unsigned short vid = 0;
struct vlan_ioctl_args args; struct vlan_ioctl_args args;
/* everything here needs root permissions, except aguably the
* hack ioctls for sending packets. However, I know _I_ don't
* want users running that on my network! --BLG
*/
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args))) if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args)))
return -EFAULT; return -EFAULT;
...@@ -669,24 +663,32 @@ static int vlan_ioctl_handler(void __user *arg) ...@@ -669,24 +663,32 @@ static int vlan_ioctl_handler(void __user *arg)
switch (args.cmd) { switch (args.cmd) {
case SET_VLAN_INGRESS_PRIORITY_CMD: case SET_VLAN_INGRESS_PRIORITY_CMD:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
err = vlan_dev_set_ingress_priority(args.device1, err = vlan_dev_set_ingress_priority(args.device1,
args.u.skb_priority, args.u.skb_priority,
args.vlan_qos); args.vlan_qos);
break; break;
case SET_VLAN_EGRESS_PRIORITY_CMD: case SET_VLAN_EGRESS_PRIORITY_CMD:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
err = vlan_dev_set_egress_priority(args.device1, err = vlan_dev_set_egress_priority(args.device1,
args.u.skb_priority, args.u.skb_priority,
args.vlan_qos); args.vlan_qos);
break; break;
case SET_VLAN_FLAG_CMD: case SET_VLAN_FLAG_CMD:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
err = vlan_dev_set_vlan_flag(args.device1, err = vlan_dev_set_vlan_flag(args.device1,
args.u.flag, args.u.flag,
args.vlan_qos); args.vlan_qos);
break; break;
case SET_VLAN_NAME_TYPE_CMD: case SET_VLAN_NAME_TYPE_CMD:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if ((args.u.name_type >= 0) && if ((args.u.name_type >= 0) &&
(args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) { (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
vlan_name_type = args.u.name_type; vlan_name_type = args.u.name_type;
...@@ -696,17 +698,9 @@ static int vlan_ioctl_handler(void __user *arg) ...@@ -696,17 +698,9 @@ static int vlan_ioctl_handler(void __user *arg)
} }
break; break;
/* TODO: Figure out how to pass info back...
case GET_VLAN_INGRESS_PRIORITY_IOCTL:
err = vlan_dev_get_ingress_priority(args);
break;
case GET_VLAN_EGRESS_PRIORITY_IOCTL:
err = vlan_dev_get_egress_priority(args);
break;
*/
case ADD_VLAN_CMD: case ADD_VLAN_CMD:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
/* we have been given the name of the Ethernet Device we want to /* we have been given the name of the Ethernet Device we want to
* talk to: args.dev1 We also have the * talk to: args.dev1 We also have the
* VLAN ID: args.u.VID * VLAN ID: args.u.VID
...@@ -719,12 +713,51 @@ static int vlan_ioctl_handler(void __user *arg) ...@@ -719,12 +713,51 @@ static int vlan_ioctl_handler(void __user *arg)
break; break;
case DEL_VLAN_CMD: case DEL_VLAN_CMD:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
/* Here, the args.dev1 is the actual VLAN we want /* Here, the args.dev1 is the actual VLAN we want
* to get rid of. * to get rid of.
*/ */
err = unregister_vlan_device(args.device1); err = unregister_vlan_device(args.device1);
break; 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: default:
/* pass on to underlying device instead?? */ /* pass on to underlying device instead?? */
printk(VLAN_DBG "%s: Unknown VLAN CMD: %x \n", printk(VLAN_DBG "%s: Unknown VLAN CMD: %x \n",
......
...@@ -66,6 +66,8 @@ int vlan_dev_ioctl(struct net_device* dev, struct ifreq *ifr, int cmd); ...@@ -66,6 +66,8 @@ int vlan_dev_ioctl(struct net_device* dev, struct ifreq *ifr, int cmd);
int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio); int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
int vlan_dev_set_egress_priority(char* dev_name, __u32 skb_prio, short vlan_prio); int vlan_dev_set_egress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
int vlan_dev_set_vlan_flag(char* dev_name, __u32 flag, short flag_val); int vlan_dev_set_vlan_flag(char* dev_name, __u32 flag, short flag_val);
int vlan_dev_get_realdev_name(const char* dev_name, char* result);
int vlan_dev_get_vid(const char* dev_name, unsigned short* result);
void vlan_dev_set_multicast_list(struct net_device *vlan_dev); void vlan_dev_set_multicast_list(struct net_device *vlan_dev);
#endif /* !(__BEN_VLAN_802_1Q_INC__) */ #endif /* !(__BEN_VLAN_802_1Q_INC__) */
/* /* -*- linux-c -*-
* INET 802.1Q VLAN * INET 802.1Q VLAN
* Ethernet-type device handling. * Ethernet-type device handling.
* *
...@@ -484,13 +484,26 @@ int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -484,13 +484,26 @@ int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
veth->h_vlan_proto, veth->h_vlan_TCI, veth->h_vlan_encapsulated_proto); veth->h_vlan_proto, veth->h_vlan_TCI, veth->h_vlan_encapsulated_proto);
#endif #endif
stats->tx_packets++; /* for statics only */
stats->tx_bytes += skb->len;
skb->dev = VLAN_DEV_INFO(dev)->real_dev; skb->dev = VLAN_DEV_INFO(dev)->real_dev;
dev_queue_xmit(skb);
return 0; {
/* Please note, dev_queue_xmit consumes the pkt regardless of the
* error value. So, will copy the skb first and free if successful.
*/
struct sk_buff* skb2 = skb_get(skb);
int rv = dev_queue_xmit(skb2);
if (rv == 0) {
/* Was success, need to free the skb reference since we bumped up the
* user count above.
*/
stats->tx_packets++; /* for statics only */
stats->tx_bytes += skb->len;
kfree_skb(skb);
}
return rv;
}
} }
int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
...@@ -622,6 +635,44 @@ int vlan_dev_set_vlan_flag(char *dev_name, __u32 flag, short flag_val) ...@@ -622,6 +635,44 @@ int vlan_dev_set_vlan_flag(char *dev_name, __u32 flag, short flag_val)
return -EINVAL; return -EINVAL;
} }
int vlan_dev_get_realdev_name(const char *dev_name, char* result)
{
struct net_device *dev = dev_get_by_name(dev_name);
int rv = 0;
if (dev) {
if (dev->priv_flags & IFF_802_1Q_VLAN) {
strncpy(result, VLAN_DEV_INFO(dev)->real_dev->name, 23);
rv = 0;
} else {
rv = -EINVAL;
}
dev_put(dev);
} else {
rv = -ENODEV;
}
return rv;
}
int vlan_dev_get_vid(const char *dev_name, unsigned short* result)
{
struct net_device *dev = dev_get_by_name(dev_name);
int rv = 0;
if (dev) {
if (dev->priv_flags & IFF_802_1Q_VLAN) {
*result = VLAN_DEV_INFO(dev)->vlan_id;
rv = 0;
} else {
rv = -EINVAL;
}
dev_put(dev);
} else {
rv = -ENODEV;
}
return rv;
}
int vlan_dev_set_mac_address(struct net_device *dev, void *addr_struct_p) int vlan_dev_set_mac_address(struct net_device *dev, void *addr_struct_p)
{ {
struct sockaddr *addr = (struct sockaddr *)(addr_struct_p); struct sockaddr *addr = (struct sockaddr *)(addr_struct_p);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment