Skip to content

Instantly share code, notes, and snippets.

@upa
Created August 10, 2015 06:42
Show Gist options
  • Save upa/e95c5807500e801ac32d to your computer and use it in GitHub Desktop.
Save upa/e95c5807500e801ac32d to your computer and use it in GitHub Desktop.
/dev/hiroshi
/* /dev/hiroshi */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/netdevice.h>
#include <net/dst.h>
#include <uapi/linux/if_ether.h>
#ifndef DEBUG
#define DEBUG
#endif
#define func_enter() printk ("entering %s\n", __func__);
MODULE_AUTHOR ("[email protected]");
MODULE_LICENSE ("GPL");
static int devmajor = 77;
static char * devname = "hiroshi";
#define HIROSHI "/dev/hiroshi"
inline static int
k_atoi (char *str)
{
int res = 0, i;
for (i = 0; str[i] != '\0'; ++i)
res = res*10 + str[i] - '0';
return res;
}
static int
hiroshi_open (struct inode * inode, struct file * fp)
{
func_enter ();
return 0;
}
static int
hiroshi_release (struct inode * inode, struct file * fp)
{
func_enter ();
return 0;
}
static ssize_t
hiroshi_read (struct file * fp, char * buf, size_t count, loff_t * ppos)
{
func_enter ();
return count;
}
static ssize_t
hiroshi_write (struct file * fp, const char __user * buf, size_t count,
loff_t * ppos)
{
/* build MPLS packet with specified label.
* string format is [DEVICE] [LABEL].
* ex) eth0 20
*/
struct net_device * dev; // output device
struct sk_buff * skb;
struct ethhdr * eth;
int n, label;
u32 mpls, * mplsh;
char kbuf[16];
char * dp, * lp;
netdev_tx_t ret;
func_enter ();
memset (kbuf, 0, sizeof (kbuf));
copy_from_user (kbuf, buf, count < 16 ? count : 16);
for (n = 0, dp = kbuf, lp = NULL; n < (count < 16 ? count : 16); n++) {
if (kbuf[n] == ' ') {
kbuf[n] = '\0';
lp = &(kbuf[n + 1]);
kbuf[count - 1] = '\0';
break;
}
}
if (!lp) {
printk (KERN_ERR "%s: failed to parse \"%s\"", HIROSHI, kbuf);
}
label = k_atoi (lp);
dev = dev_get_by_name_rcu (get_net_ns_by_pid (1), dp);
if (!dev) {
printk (KERN_ERR "%s: device %s does is not found",
HIROSHI, dp);
return count;
}
skb = netdev_alloc_skb (dev, sizeof (struct ethhdr) + 4);
if (!skb) {
printk (KERN_ERR "%s: failed to alloc akb.\n", HIROSHI);
}
skb_put (skb, sizeof (struct ethhdr) + 4);
skb_reset_mac_header (skb);
/* setup ether header */
eth = (struct ethhdr *) skb->data;
eth->h_source[0] = 0x01;
eth->h_source[1] = 0x01;
eth->h_source[2] = 0x01;
eth->h_source[3] = 0x01;
eth->h_source[4] = 0x01;
eth->h_source[5] = 0x01;
eth->h_dest[0] = 0x01;
eth->h_dest[1] = 0x01;
eth->h_dest[2] = 0x01;
eth->h_dest[3] = 0x02;
eth->h_dest[4] = 0x02;
eth->h_dest[5] = 0x02;
eth->h_proto = htons (ETH_P_MPLS_UC);
/* setup mpls header */
skb_reset_network_header (skb);
mpls = 0;
mpls = label;
mpls <<= 12; /* set label */
mpls |= 0x00F; /* exp 0 stack 0, 16 hop */
mplsh = (u32 *) (eth + 1);
*mplsh = htonl (mpls);
skb->dev = dev;
skb_dst_drop (skb);
//ret = dev->netdev_ops->ndo_start_xmit (skb, dev);
ret = dev_queue_xmit (skb);
if (ret != NETDEV_TX_OK) {
printk (KERN_ERR "%s: failed to xmit mpls pakcet\n", HIROSHI);
} else {
printk (KERN_INFO
"%s: send packet label %u success via %s %s\n",
HIROSHI, label, dp, lp);
}
return count;
}
static struct file_operations hiroshi_fops = {
.owner = THIS_MODULE,
.read = hiroshi_read,
.write = hiroshi_write,
.open = hiroshi_open,
.release = hiroshi_release,
};
static int
__init hiroshi_init_module (void)
{
int ret;
ret = register_chrdev (devmajor, devname, &hiroshi_fops);
if (ret) {
printk (KERN_ERR "%s: failed to register /dev/hiroshi\n",
HIROSHI);
return -1;
}
printk (KERN_INFO "%s loaded.\n", HIROSHI);
return 0;
}
module_init (hiroshi_init_module);
static void
__exit hiroshi_exit_module (void)
{
unregister_chrdev (devmajor, devname);
printk (KERN_INFO "%s unloaded.\n", HIROSHI);
return;
}
module_exit (hiroshi_exit_module);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment