Kernel Korner - Network Programming in the Kernel

Take a tour of the kernel's networking functionality by writing a network client that runs in kernel space.

All Linux distributions provide a wide range of
network applications—from dæmons that provide a
variety of services such as WWW, mail and SSH to
client programs that access one or more of these
services. These programs are written in user mode
and use the system calls provided by the kernel
to perform various operations like network read
and write. Although this is the traditional method of
writing programs, there is another interesting way
to develop these applications by implementing them
in the kernel. The TUX Web server is a good example of
an application that runs inside the kernel and serves
static content. In this article, we explain the basics
of writing network applications within the kernel and
their advantages and disadvantages. As an example, we
explain the implementation of an in-kernel FTP client.

Advantages and Disadvantages of In-Kernel Implementations

Why would one want to implement applications within the kernel?
Here are a few advantages:

When a user-space program makes a system call, there is some
overhead associated in the user-space/kernel-space transition. By
programming all functionality in the kernel, we can make gains in performance.

The data corresponding to any application that sends or receives
packets is copied from user mode to kernel mode and
vice versa. By implementing network applications within the
kernel, it is possible to reduce such overhead and increase
efficiency by not copying data to user mode.

In specific research and high-performance computing
environments, there is a need for achieving data transfers at
great speeds. Kernel applications find use in such situations.

On the other hand, in-kernel
implementations have certain disadvantages:

Security is a primary concern within the kernel, and a large class
of user-mode applications are not suitable to be run directly in
the kernel. Consequently, special care needs to be taken while
designing in-kernel applications. For example, reading and writing
to files within the kernel is usually a bad idea, but most
applications require some kind of file I/O.

Large applications cannot be implemented in the kernel due to
memory constraints.

Network Programming Basics

Network programming is usually done with sockets. A socket serves as a
communication end point between two processes. In this article, we
describe network programming with TCP/IP sockets.

Server programs create sockets, bind to well-known ports, listen and
accept connections from clients. Servers are usually designed to accept
multiple connections from clients—they either fork a new process to
serve each client request (concurrent servers) or completely serve one
request before accepting more connections (iterative servers). Client
programs, on the other hand, create sockets to connect to servers and
exchange information.

FTP Client-Server Interaction

Let's take a quick look at how an FTP client and
server are implemented in user mode. We discuss
only active FTP in this article. The differences between
active and passive FTP are not relevant to our
discussion of network programming here.

Socket Programming Basics

Here is a brief explanation of the design of an FTP client and server.
The server program creates a socket using the
socket() system call.
It then binds on a well-known port using bind() and waits for
connections from clients using the listen() system call. The server
then accepts incoming requests from clients using
accept() and forks a
new process (or thread) to serve each incoming client request.

The client program creates a control socket using
socket() and next
calls connect() to establish a connection with the server. It then
creates a separate socket for data transfer using
socket() and binds
to an unprivileged port (>1024) using bind(). The
client now listen()s
on this port for data transfer from the server. The server now has
enough knowledge to honor a data transfer request from the client.
Finally, the client uses accept() to accept connections from the
server to send and receive data. For sending and receiving data, the client
and server use the write() and
read() or sendmsg() and
recvmsg()
system calls. The client issues close() on all open sockets to tear
down its connection to the server. Figure 1 sums it up.

Figure 1. The FTP protocol uses two sockets: one for control messages and
one for data.

Hello,
I am new to linux kernel development. so if any mistakes you find, pls
frgive it and correct me.

I wanted to send raw packets through ethernet, from kernel level.
So i use PF_PACKET family. & SOCK_RAW.And i used sock_create()
function to create socket.
But I found that when i create socket with
sock_create(PF_PACKET,SOCK_RAW,.....) the program always fails in
bind. (when i do sock->ops->bind(.....))
why is it so ? but when I use PF_INET & SOCK_PACKET to create socket.
bind happens successfully.
Can any one help me to come out of this issue?? OR direct me to create
raw packets and send from kernel??

In your example you don't actually use insmod after building the module, does that mean its not necessary? If not then how does the userland program see the system call. If so then do you know why it insmod'ing it would freeze my system? Cause it does. I did fiddle with the code a bit, mostly stripped it down to just connect, send a message, and close.

Trending Topics

Upcoming Webinar

Getting Started with DevOps - Including New Data on IT Performance from Puppet Labs 2015 State of DevOps Report

August 27, 2015
12:00 PM CDT

DevOps represents a profound change from the way most IT departments have traditionally worked: from siloed teams and high-anxiety releases to everyone collaborating on uneventful and more frequent releases of higher-quality code. It doesn't matter how large or small an organization is, or even whether it's historically slow moving or risk averse — there are ways to adopt DevOps sanely, and get measurable results in just weeks.