
I. Linux kernel articles
7. Sockets
I'm gonna write a tutorial on kernel sockets. A source code of mine is available here and here:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/mutex.h>
#include <linux/semaphore.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/netdevice.h>
#include <linux/ip.h>
#include <linux/in.h>
#define _bswap_16(x) ((unsigned short)(_builtin_bswap32(x) >> 16))
MODULE_LICENSE("Dual BSD/GPL");
#define PORT 1111
#define SERVER_ADDR "192.168.37.138"
struct task_struct *kthread = NULL;
struct mutex mutex;
struct socket *sock = NULL;
static char *init_msg = "Init message";
static int  size_init_msg = 13;
static char *exit_msg = "Exit message";
static int  size_exit_msg = 13;
static void convert_from_addr(const char *addr, unsigned char nbs[4])
{
    int i;
    int value;
    int pos;
    for (i = 0, pos = 0; addr[i] && pos < 4; ++i)
    {
        for (value = 0; addr[i] && addr[i] != '.'; ++i) {
            value *= 10;
            value += addr[i] - '0';
        }
        nbs[pos++] = value;
        if (!addr[i])
            return;
    }
}
static int send_msg(unsigned char *buf, int len)
{
    struct msghdr msg = {0};
    struct iovec iov;
    mm_segment_t oldfs;
    int size = 0;
    iov.iov_base = buf;
    iov.iov_len = len;
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;
    oldfs = get_fs();
    set_fs(KERNEL_DS);
    size = sock_sendmsg(sock,&msg,len);
    set_fs(oldfs);
    if (size < 0)
        printk("thug_write_to_socket: sock_sendmsg error: %d\n", size);
    return size;
}
static int my_connect(struct socket **s, const char *s_addr)
{
    struct sockaddr_in address = {0};
    int len = sizeof(struct sockaddr_in), ret;
    unsigned char i_addr[4] = {0};
    if ((ret = sock_create(AF_INET, SOCK_STREAM, IPPROTO_TCP, s)) < 0)
    {
        printk("echo_server: sock_create error");
        return ret;
    }
    convert_from_addr(s_addr, i_addr);
    address.sin_addr.s_addr = *(unsigned int*)i_addr;
    address.sin_port = htons(PORT);
    address.sin_family = AF_INET;
    if ((ret = (*s)->ops->connect(sock, (struct sockaddr*)&address, len, 0)) < 0)
    {
        sock_release(*s);
        *s = NULL;
    }
    return ret;
}
static int echo_server_init(void)
{
    int ret;
    if ((ret = my_connect(&sock, "127.0.0.1")) < 0)
    {
        printk("echo_server: connect error");
        return ret;
    }
    printk(KERN_ALERT "echo-server is on !\n");  
    send_msg(init_msg, size_init_msg);
    return 0;
}
static void echo_server_exit(void)
{
    send_msg(exit_msg, size_exit_msg);
    if (sock != NULL)
    {
        sock_release(sock);
        sock = NULL;
    }   
    printk(KERN_ALERT "echo-server is now ending\n");
}
module_init(echo_server_init);
module_exit(echo_server_exit);