Virtual Interface
hi everyone,
I am writing a virtual network interface for linux and I am using the sample code "insane" from Alessandro Rubini:
The main purpose is to make a virtual interface: insane. This interface directs all the packets sent to it to another physical-existing interface. The "insane" code works with linux kernel 2.3 but it does not work with 2.6. I have not found out the problem but I guess it should be wrong in the hard_start_xmit function.
I post the modified code here, if you can find out the errors in the code, please tell me!
Thank you very much!
Son
-------------------------------------------
int insane_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct insane_private *priv = dev->priv;
if (!priv->slave_device) { /* cannot send to anyone, just return */
priv->stats.tx_errors++;
priv->stats.tx_dropped++;
return 0;
}
priv->stats.tx_packets++;
priv->stats.tx_bytes += skb->len;
#if 0
printk(KERN_INFO "call: insane_xmit: use %s->hard_start_xmit\n",
priv->slave_device->name);
return priv->slave_device->hard_start_xmit(skb, priv->slave_device);
#else
/*
printk(KERN_INFO "call: insane_xmit: use slave_device->hard_start_xmit\n");
skb->dev = priv->slave_device;
skb->priority = 1;
dev_queue_xmit (skb);
return 0;
*/
#endif
}
-----------------
int insane_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
int err;
unsigned char *temp;
struct net_device *slave;
struct insane_private *priv = netdev_priv(dev);
/* hold a local (kernel-space) copy of the configuration data */
struct insane_userinfo info;
/* and a pointer into user space as well */
struct insane_userinfo *uptr = (struct insane_userinfo *) ifr->ifr_data;
/* only authorized users can control the interface */
if (cmd == SIOCINSANESETINFO && !capable(CAP_NET_ADMIN))
return -EPERM;
/* process the command */
switch (cmd) {
case SIOCINSANEGETINFO: /* return configuration to user space */
{
/* interface name */
memset(info.name, 0, INSANE_NAMELEN);
if (priv->slave_device)
strncpy(info.name, priv->slave_device->name, INSANE_NAMELEN-1);
err = copy_to_user(uptr, &info, sizeof(info));
if (err) return err;
break;
}
case SIOCINSANESETINFO: // set configuration from user space
{
/* retrieve the data structure from user space */
err = copy_from_user(&info, uptr, sizeof(info));
if (err) return err;
printk("name: %s \n", info.name);
/* interface name */
slave = dev_get_by_name(info.name);
if (!slave)
return -ENODEV;
if (slave->type != ARPHRD_ETHER && slave->type != ARPHRD_LOOPBACK)
return -EINVAL;
/* The interface is good, get hold of it */
priv->slave_device = slave;
if (slave->hard_header)
dev->hard_header = insane_hard_header;
else
dev->hard_header = NULL;
if (slave->rebuild_header)
dev->rebuild_header = insane_rebuild_header;
else
dev->rebuild_header = NULL;
/* also, and clone its IP, MAC and other information */
memcpy(dev->broadcast, slave->broadcast, sizeof(slave->broadcast));
break;
}
default:
{
return -EOPNOTSUPP;
}
}
return 0;
}
-------------------
|