Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion tools/labs/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/skels/

vmlinux
zImage
serial.pts
Expand Down
3 changes: 3 additions & 0 deletions tools/labs/skels/networking/1-2-netfilter/kernel/Kbuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
EXTRA_CFLAGS = -g

obj-m = filter.o
147 changes: 147 additions & 0 deletions tools/labs/skels/networking/1-2-netfilter/kernel/filter.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
* SO2 - Networking Lab (#10)
*
* Exercise #1, #2: simple netfilter module
*
* Code skeleton.
*/

#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/module.h>
#include <asm/uaccess.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/atomic.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/net.h>
#include <linux/in.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/tcp.h>

#include "filter.h"

MODULE_DESCRIPTION("Simple netfilter module");
MODULE_AUTHOR("SO2");
MODULE_LICENSE("GPL");

#define LOG_LEVEL KERN_ALERT
#define MY_DEVICE "filter"

static struct cdev my_cdev;
static atomic_t ioctl_set;
static unsigned int ioctl_set_addr;


/* Test ioctl_set_addr if it has been set.
*/
static int test_daddr(unsigned int dst_addr)
{
int ret = 0;

/* TODO 2: return non-zero if address has been set
* *and* matches dst_addr
*/

return ret;
}

/* TODO 1: netfilter hook function */
static unsigned int my_nf_hookfn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) {
struct iphdr *iph = ip_hdr(skb);

if (iph->protocol == IPPROTO_TCP) {
struct tcphdr *tcph = tcp_hdr(skb);
printk("IP address is %pI4\n", &iph->saddr);
printk("Port number is %i\n", ntohs(tcph->source));
}

return NF_ACCEPT;
}

static int my_open(struct inode *inode, struct file *file)
{
return 0;
}

static int my_close(struct inode *inode, struct file *file)
{
return 0;
}

static long my_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
switch (cmd) {
case MY_IOCTL_FILTER_ADDRESS:
/* TODO 2: set filter address from arg */
break;

default:
return -ENOTTY;
}

return 0;
}

static const struct file_operations my_fops = {
.owner = THIS_MODULE,
.open = my_open,
.release = my_close,
.unlocked_ioctl = my_ioctl
};

/* TODO 1: define netfilter hook operations structure */
static struct nf_hook_ops ops = {
.hook = my_nf_hookfn,
.hooknum = NF_INET_LOCAL_OUT,
.pf = PF_INET,
.priority = NF_IP_PRI_FIRST
};

int __init my_hook_init(void)
{
int err;

/* register filter device */
err = register_chrdev_region(MKDEV(MY_MAJOR, 0), 1, MY_DEVICE);
if (err != 0)
return err;

atomic_set(&ioctl_set, 0);
ioctl_set_addr = 0;

/* init & add device */
cdev_init(&my_cdev, &my_fops);
cdev_add(&my_cdev, MKDEV(MY_MAJOR, 0), 1);

/* TODO 1: register netfilter hook */
err = nf_register_net_hook(&init_net, &ops);
if (err != 0) {
pr_info("nf_register_net_hook failed: %d\n", err);
return err;
}

return 0;

out:
/* cleanup */
cdev_del(&my_cdev);
unregister_chrdev_region(MKDEV(MY_MAJOR, 0), 1);

return err;
}

void __exit my_hook_exit(void)
{
/* TODO 1: unregister hook */
nf_unregister_net_hook(&init_net, &ops);
/* cleanup device */
cdev_del(&my_cdev);
unregister_chrdev_region(MKDEV(MY_MAJOR, 0), 1);
}

module_init(my_hook_init);
module_exit(my_hook_exit);
11 changes: 11 additions & 0 deletions tools/labs/skels/networking/1-2-netfilter/kernel/filter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef _FILTER_H_
#define _FILTER_H_

#include <asm/ioctl.h>

/* ioctl command to pass address to filter driver */
#define MY_IOCTL_FILTER_ADDRESS _IOW('k', 1, unsigned int)

#define MY_MAJOR 42

#endif /* _FILTER_H_ */
1 change: 1 addition & 0 deletions tools/labs/skels/networking/1-2-netfilter/user/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/test
16 changes: 16 additions & 0 deletions tools/labs/skels/networking/1-2-netfilter/user/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#
# SO2 - Networking Lab (#10)
#
# Makefile for test filter module
#

CFLAGS = -Wall -static -m32

all: test

test: test.c

.PHONY: clean

clean:
-rm -f test *~ *.o
25 changes: 25 additions & 0 deletions tools/labs/skels/networking/1-2-netfilter/user/test-1.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/sh
#
# SO2 - Networking Lab (#10)
#
# Test script for exercise #1
#

# insert module
insmod ../kernel/filter.ko || exit 1

# listen for connections on localhost, port 60000 (run in background)
../../netcat -l -p 60000 &

# wait for netcat to start listening
sleep 1

# connect to localhost, port 60000, starting a connection using local
# port number 600001;
echo "Should show up in filter." | ../../netcat -q 2 127.0.0.1 60000

# look for filter message in dmesg output
echo "Check dmesg output."

# remove module
rmmod filter || exit 1
41 changes: 41 additions & 0 deletions tools/labs/skels/networking/1-2-netfilter/user/test-2.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/bin/sh
#
# SO2 - Networking Lab (#10)
#
# Test script for exercise #2
#

# insert module
insmod ../kernel/filter.ko || exit 1

# set filter IP address to 127.0.0.1
./test 127.0.0.1

# listen for connections on localhost, port 60000 (run in background)
../../netcat -l -p 60000 &

# wait for netcat to start listening
sleep 1

# connect to localhost, port 60000, starting a connection using local
# port number 600001;
echo "Should show up in filter." | ../../netcat -q 2 127.0.0.1 60000

# set filter IP address to 127.0.0.2
./test 127.0.0.2

# listen for connections on localhost, port 60000 (run in background)
../../netcat -l -p 60000 &

# wait for netcat to start listening
sleep 1

# connect to localhost, port 60000, starting a connection using local
# port number 600001;
echo "Should NOT show up in filter." | ../../netcat -q 2 127.0.0.1 60000

# look for filter message in dmesg output
echo "Check dmesg output."

# remove module
rmmod filter || exit 1
73 changes: 73 additions & 0 deletions tools/labs/skels/networking/1-2-netfilter/user/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* SO2 - Networking Lab (#11)
*
* Test filter module for exercise #2
*
* Sends MY_IOCTL_FILTER_ADDRESS to filter module.
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/sysmacros.h>
#include <fcntl.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>

#include "../kernel/filter.h"

#define MY_DEVICE "/dev/filter"


static void print_usage(char *argv0)
{
fprintf(stderr, "Usage: %s <address>\n"
"\taddress must be a string containing "
"an IP dotted address\n", argv0);
}

int main(int argc, char **argv)
{
int fd;
unsigned int addr;

if (argc != 2) {
print_usage(argv[0]);
exit(EXIT_FAILURE);
}

/* get address */
addr = inet_addr(argv[1]);

/* make device node */
if (mknod(MY_DEVICE, 0644 | S_IFCHR, makedev(MY_MAJOR, 0)) < 0) {
if (errno != EEXIST) {
perror("mknod " MY_DEVICE);
exit(EXIT_FAILURE);
}
}

/* open device */
fd = open(MY_DEVICE, O_RDONLY);
if (fd < 0) {
perror("open " MY_DEVICE);
} else {
/* send ioctl */
if (ioctl(fd, MY_IOCTL_FILTER_ADDRESS, &addr) < 0)
perror("ioctl MY_IOCTL_FILTER_ADDRESS");

/* close device */
if (close(fd) < 0)
perror("close");
}

/* cleanup device node */
if (unlink(MY_DEVICE) < 0)
perror("unlink " MY_DEVICE);

return 0;
}
3 changes: 3 additions & 0 deletions tools/labs/skels/networking/3-4-tcp-sock/Kbuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
EXTRA_CFLAGS = -Wall -g

obj-m = tcp_sock.o
Loading