kernel mode sockets part 2 (the clean way)

by nks · august 30 2008 · 3 comments

Version 0.3 -  23.01.2009

Willkommen zu teil 2 der linux kernel mode socket Serie. Nun befassen wir uns mit einem sauberem weg der socketcalls vom kernel aus. Auch hierfür gibt es noch andere Wege. In einem der nächsten Teile bauen wir uns eine socket()-Funktion selber, aber nun zum sauberem socket :D

Auch hier müssen wir wieder set_fs/get_fs (man kann sie auch weglassen, aber in diesem Fall garantiere ich für NICHTS, bzw das Modul lässt sich kompilieren aber die Funktion funktioniert im besten Fall nicht…) nutzen da file-Operationen im kernelmode nicht gestattet sind, der Zugriff auf sockets ist ein Dateizugriff. Die Funktion inet_addr müssen wir uns nicht extra schreiben, hab ich zwischenzeitlich herausgefunden in der “linux/inet.h” gibt es in_aton() :D

Die Hauptschwierigkeit besteht in den neuen Strukturen iovec und msghdr. Die ich allerdings anhand von Kommentaren erklären werde, soweit wichtig, bzw unter den beiden links steht alles was man wissen muss (obwohl es nicht spezifisch um die linux Strukturen geht).

Ab an den Code:

/*
 * lkm_clean_socket.c - nks
 */
 
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <linux/in.h>
#include <linux/inet.h>
#include <net/sock.h>
#include <asm/uaccess.h>
 
int init_module(void)
{
	struct socket *socket;
	struct sockaddr_in saddr;
	int errno;
	char buffer[1024];
	struct msghdr msg;
	struct iovec iov;
	mm_segment_t old_fs;
 
	printk(KERN_INFO "#sixserv/sixserv.org presents:\n");
	printk(KERN_INFO "simple & clean kernel mode socket - nks\n");
 
	if ((errno = sock_create(PF_INET,SOCK_STREAM,IPPROTO_TCP,&socket))<0)
	{
		printk(KERN_INFO "-- Kernel Mode Socket ERROR...\n");
		printk(KERN_INFO "-- ERRNO: %d..\n",errno);
		return 0;
	}
	else
        {
		printk(KERN_INFO "++ Kernel Mode Socket is up ...\n");
		printk(KERN_INFO "++ ERRNO: %d..\n",errno);
        }
 
	saddr.sin_addr.s_addr = in_aton("79.140.33.153");
	saddr.sin_port = htons(80);
	saddr.sin_family = AF_INET;
 
 
	if ((errno = socket->ops->connect(socket,(struct sockaddr*)&saddr,sizeof(saddr),0))<0)
	{
		printk(KERN_INFO "-- Kernel Mode Socket ERROR...\n");
		printk(KERN_INFO "-- ERRNO: %d..\n",errno);
		return 0;
        }
        else
        {
		printk(KERN_INFO "++ Kernel Mode Socket is up an connected...\n");
		printk(KERN_INFO "++ ERRNO: %d..\n",errno);
        }
 
	iov.iov_base = "GET / HTTP/1.0\r\n\r\n";
	iov.iov_len = sizeof("GET / HTTP/1.0\r\n\r\n");
 
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = NULL;
	msg.msg_controllen = 0;
	msg.msg_name = NULL;
	msg.msg_namelen = 0;
	msg.msg_flags	= 0;
 
	old_fs = get_fs();
	set_fs(KERNEL_DS);	
 
	if ((errno = sock_sendmsg(socket,&msg,sizeof("GET / HTTP/1.0\r\n\r\n")))<0)
	{
		printk(KERN_INFO "-- Kernel Mode Socket ERROR...\n");
		printk(KERN_INFO "-- ERRNO: %d..\n",errno);
		set_fs(old_fs);
		return 0;
        }
        else
        {
                printk(KERN_INFO "++ Kernel Mode Socket is sending stuff...\n");
                printk(KERN_INFO "++ ERRNO: %d..\n",errno);
		set_fs(old_fs);
        }	
 
	iov.iov_base = buffer;
	iov.iov_len = 1024;
 
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = NULL;
	msg.msg_name = NULL;
	msg.msg_namelen = 0;
 
	old_fs = get_fs();
	set_fs(KERNEL_DS);
 
	if ((errno = sock_recvmsg(socket,&msg,1024,0))<0)
        {
                printk(KERN_INFO "-- Kernel Mode Socket ERROR...\n");
                printk(KERN_INFO "++ ERRNO: %d..\n",errno);
                set_fs(old_fs);
                return 0;
        }
        else
        {
                printk(KERN_INFO "++ Kernel Mode Socket is recieving stuff...\n");
                printk(KERN_INFO "++ ERRNO: %d..\n",errno);
                printk(KERN_INFO "++ Recieved: %s..\n",buffer);
		set_fs(old_fs);
 
        }
	return 0;
}
 
void cleanup_module(void)
{
	printk(KERN_INFO "Goodbye world.\n");
}
 
MODULE_LICENSE("GPL");

Ein weiteres mal passen wir unsere Makfeile an:

obj-m += lkm_clean_socket.o
 
all:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
 
clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Nach einem make ist das modul fertig und liegt unter dem namen “lkm_clean_socket.ko” im aktuellem verzeichnis.
Wenn alles geklappt hat machen wir folgendes:

# modinfo lkm_clean_socket.ko
filename:       lkm_clean_socket.ko
license:        GPL
depends:
vermagic:       2.6.25-gentoo-r7 SMP mod_unload PENTIUM4
# insmod lkm_clean_socket.ko
# dmesg
....
 
++ Kernel Mode Socket is up ...
++ ERRNO: 0..
++ Kernel Mode Socket is up an connected...
++ ERRNO: 0..
++ Kernel Mode Socket is sending stuff...
++ ERRNO: 19..
++ Kernel Mode Socket is recieving stuff...
++ ERRNO: 1024..
++ Recieved: HTTP/1.1 200 OK
Date: Sat, 30 Aug 2008 00:18:58 GMT
Server: Apache
X-Powered-By: PHP/5.2.0-8+etch11
X-Pingback: http://sixserv.org/xmlrpc.php
Connection: close
Content-Type: text/html; charset=UTF-8
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="de-DE">
<head profile="http://gmpg.org/xfn/11"&gt;
<title>sixserv blog</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="description" content="welcome to teh #sixserv!" /&gt;
<meta name="generator" content="WordPress 2.6.1" /> <!-- leave this for stats please -->
<link href="http://sixserv.org/wp-content/themes/journalist/style.css" rel="stylesheet" type="text/css" media="screen" />
<link rel="alternate" type="application/rss+xml" title="sixserv blog RSS Feed" href="http://sixserv.org/feed/" />
<link rel="shortcut icon" type="image/x-png" href="http://sixserv.org/wp-content/the
....
# rmmod lkm_clean_socket.ko

Wie man sehen kann ist unser buffer ein wenig zu klein, und die errnos kann man sich eigtl. auch sparen wenn kein Fehler auftritt.

Seid gespannt auf den nächsten teil der kernel mode Serie :D

nks

quellen:

ps:
cuil.com und metager2.de lassen sich beide in die Suchleiste integrieren (klickt einfach auf den namen dann fragt euch FF). Nach einigem testen gefällt mir metager2 wesentlich besser weil es VIEL mehr findet. Allerdings gefällt mir die Aufmachung von cuil.com, ich sehe noch einiges an potenzial.

pps:
Mal wieder ein musikalischer Tipp:
http://www.myspace.com/blue_nine

edit: Unterschiede zu Version 0.1 haben nur mit der Rechtschreibung zu tun!

Tagged: , , , ,

3 Comments

Subscribe to comments with RSS or TrackBack to 'kernel mode sockets part 2 (the clean way)'.

  1. Super Crashkurs in Socket-Programmierung für Masochisten xD

    Allerdings muss ich mich noch an deine nur-Kleinbuchstaben Syntax gewöhnen. Kleiner Hinweis: Eventuell mal “more” nach einem Excerpt benutzen, oder hast du das bewusst nicht benutzt?

  2. Dann halt nicht :)

    Könntest aber wenigstens darauf achten das der Code nicht zu breit für unsere Themes sind.

  3. hehe un du kannst mir das auch im irc sagen :D
    trotz allem… done xD

Leave a Reply