%% LyX 1.1 created this file.  For more info, see http://www.lyx.org/.
%% Do not edit unless you really know what you are doing.
\documentclass[german,dvips]{slides}
\usepackage[T1]{fontenc}
\usepackage[latin1]{inputenc}
\usepackage{babel}
\usepackage{graphics}
\usepackage{longtable}
\IfFileExists{url.sty}{\usepackage{url}}
                      {\newcommand{\url}{\texttt}}

\makeatletter

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% LyX specific LaTeX commands.
\providecommand{\LyX}{L\kern-.1667em\lower.25em\hbox{Y}\kern-.125emX\@}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Textclass specific LaTeX commands.
 \newcounter{slidetype}
 \setcounter{slidetype}{0}
 \newif\ifLyXsNoCenter
 \LyXsNoCenterfalse
 \newcommand{\noslidecentering}{
    \LyXsNoCentertrue%
 }
 \newcommand{\slidecentering}{
    \LyXsNoCenterfalse%
 }
 \newcommand{\lyxendslide}[1]{
    \ifLyXsNoCenter%
         \vfill%
    \fi%
    \ifcase \value{slidetype}%
         \or % no action for 0
         \end{slide} \or%
         \end{overlay} \or%
         \end{note}%
    \fi%
    \setcounter{slidetype}{0}
\visible
 }
 \AtEndDocument{\lyxendslide{.}}
 \newcommand{\lyxnewslide}[1]{
    \lyxendslide{.}
    \setcounter{slidetype}{1}
    \begin{slide}
 }
 \newenvironment{lyxcode}
   {\begin{list}{}{
     \setlength{\rightmargin}{\leftmargin}
     \raggedright
     \setlength{\itemsep}{0pt}
     \setlength{\parsep}{0pt}
     \normalfont\ttfamily}%
    \item[]}
   {\end{list}}

\makeatother
\begin{document}
\vspace{20pt}

{\centering Linux-Internals\par}

\vspace{20pt}

{\centering Interprozess- und Netzwerkkommunikation (Kernel 2.4)\par}

\vspace{20pt}

{\centering Stephan Uhlmann <su@su2.info>\\
15.02.2002\par}

\vfill

{\tiny Copyright 2002 Stephan Uhlmann}{\tiny \par}

{\tiny Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU Free Documentation License, Version
1.1 or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts and no Back-Cover
Texts. A copy of the license is included in the section entitled \char`\"{}GNU
Free Documentation License\char`\"{}.}{\tiny \par}


\lyxnewslide{Übersicht Interprozesskommunikation}

Interprozesskommunikation

\begin{enumerate}
\item Primitive Kommunikation

\begin{enumerate}
\item Lock files
\item File locks
\end{enumerate}
\item Pipes
\item Named Pipes
\item System V IPC

\begin{enumerate}
\item Semaphoren
\item Message queues
\item Shared memory
\end{enumerate}
\item IPC mit Sockets
\end{enumerate}

\lyxnewslide{Primitive Kommunikation - Lock files}

Lock files

\begin{itemize}
\item benutzt bestehende Mechanismen des VFS
\item Prozess legt lock file an, um Belegung einer Ressource zu signalisieren
\item Beispiel: Locking des Mailspools durch SMTP-/POP3-Server
\item 1:n Beziehung
\item für Datenaustausch ungeeignet
\end{itemize}

\lyxnewslide{Primitive Kommunikation - File locks}

File locks

\begin{itemize}
\item benutzt bestehende Mechanismen des VFS
\item Prozess lockt existierende Datei, um Belegung einer Ressource zu signalisieren
\item gelockte Datei kann die gemeinsam genutzte Ressource sein (Datenaustausch)
\item \texttt{flock()} (4.4BSD), \texttt{lockf()} (POSIX) und \texttt{fnctl()}
(beides).
\item 1:n Beziehung
\item für Datenaustausch geeignet
\end{itemize}

\lyxnewslide{Pipes (1)}

Pipes

\begin{itemize}
\item \texttt{ls -la | more}
\item \texttt{int pipe(int filedes{[}2{]});} -> Inode mit 2 Dateideskriptoren
(lesen\&schreiben)
\item Shell: erzeugt Pipe und 2x \texttt{fork()}
\item Kindprozesse kopieren per \texttt{dup2(int oldfd, int newfd)} die
jeweiligen Pipe-Dateidesktiptoren auf die Standardeingabe (fd 0) bzw.
Standardausgabe (fd 1) 
\item Kindprozesse starten die Programme (ls, more)
\end{itemize}

\lyxnewslide{Pipes (2)}

Pipes

\begin{itemize}
\item im Kernel: im VFS ein \texttt{inode} und zwei \texttt{file} Objekte
\item \texttt{inode->u} verweist auf ein \texttt{struct pipe\_inode\_info}
{[}include/linux/pipe\_fs\_i.h{]}
\end{itemize}

\lyxnewslide{Pipes (3)}

\begin{lyxcode}
struct~pipe\_inode\_info~\{~\\
~~wait\_queue\_head\_t~wait;~\\
~~char~{*}base;~\\
~~unsigned~int~len;~\\
~~unsigned~int~start;~\\
~~unsigned~int~readers;~\\
~~unsigned~int~writers;~\\
~~unsigned~int~waiting\_readers;~\\
~~unsigned~int~waiting\_writers;~\\
~~unsigned~int~r\_counter;~\\
~~unsigned~int~w\_counter;~\\
\};
\end{lyxcode}

\lyxnewslide{Pipes (4)}

Pipes

\begin{itemize}
\item Zugriff über normale \texttt{read()} und \texttt{write()} Systemaufrufe
\item Im Kernel: \texttt{pipe\_read()} und \texttt{pipe\_write()} {[}fs/pipe.c{]}
\item POSIX: bis 4 kB (\texttt{PIPE\_BUF} {[}include/linux/limits.h{]})
atomar
\item Pipe-Dateideskriptoren können von mehreren Prozessen genutzt werden,
effektiv aber nur Datenaustausch zwischen 2 Prozessen -> 1:1
\end{itemize}

\lyxnewslide{Named Pipes}

Named Pipes

\begin{itemize}
\item Nachteile Pipes: Prozesse müssen vom selben Elternprozess abstammen,
Lebensdauer beschränkt auf die Lebensdauer der Prozesse
\item \texttt{mkfifo} \texttt{\textit{Name}}, Systemaufruf: \texttt{mknod()},
Kernel: Device anlegen
\item \texttt{ls -la > fifo}
\item \texttt{more fifo}
\item Zugiff: wie normale Pipes
\item auch hier effektiv nur 1:1 Kommunikation
\end{itemize}

\lyxnewslide{System V IPC}

System V IPC

\begin{itemize}
\item aus System V Unix Variante (<->BSD), kein POSIX Standard
\item erlauben Rechtevergabe
\end{itemize}
\begin{lyxcode}
struct~kern\_ipc\_perm~\{~\\
~~key\_t~key;~~~~/{*}~Schlüssel~{*}/~\\
~~uid\_t~uid;~~~~/{*}~UID~Eigentümer~{*}/~\\
~~gid\_t~gid;~~~~/{*}~GID~Eigentümer~{*}/~\\
~~uid\_t~cuid;~~~/{*}~UID~Erzeuger~{*}/~\\
~~gid\_t~cgid;~~~/{*}~GID~Erzeuger~{*}/~\\
~~mode\_t~mode;~~/{*}~Zugriffsmodus~{*}/~\\
~~unsigned~long~seq;~~/{*}~Sequenznummer~{*}/~\\
\};
\end{lyxcode}

\lyxnewslide{System V IPC - Semaphoren (1)}

Semaphoren

\begin{itemize}
\item Speicherbereich der von Prozessen atomar abgefragt und verändert werden
kann
\item \texttt{int semget ( key\_t key, int nsems, int semflg )} -> erzeugt
Semaphoren-Array (\texttt{struct sem\_array} {[}include/linux/sem.h{]})
\end{itemize}

\lyxnewslide{System V IPC - Semaphoren (2)}

\begin{lyxcode}
struct~sem\_array~\{~\\
~~struct~kern\_ipc\_perm~sem\_perm;~~~~~~~~/{*}~permissions~..~see~ipc.h~{*}/~\\
~~time\_t~sem\_otime;~~~~~~~~~~~~~~~~~~~~~/{*}~last~semop~time~{*}/~\\
~~time\_t~sem\_ctime;~~~~~~~~~~~~~~~~~~~~~/{*}~last~change~time~{*}/~\\
~~struct~sem~{*}sem\_base;~~~~~~~~~~~~~~~~~/{*}~ptr~to~first~semaphore~in~array~{*}/~\\
~~struct~sem\_queue~{*}sem\_pending;~~~~~~~~/{*}~pending~operations~to~be~processed~{*}/~\\
~~struct~sem\_queue~{*}{*}sem\_pending\_last;~~/{*}~last~pending~operation~{*}/~\\
~~struct~sem\_undo~{*}undo;~~~~~~~~~~~~~~~~/{*}~undo~requests~on~this~array~{*}/~\\
~~unsigned~long~sem\_nsems;~~~~~~~~~~~~~~/{*}~no.~of~semaphores~in~array~{*}/~\\
\};
\end{lyxcode}

\lyxnewslide{System V IPC - Semaphoren (3)}

Semaphoren

\begin{itemize}
\item eine einzelne Semaphore wird durch die \texttt{struct sem} implementiert:\\
\texttt{struct sem \{}~\\
 \texttt{ int semval; /{*} current value {*}/}~\\
 \texttt{ int sempid; /{*} pid of last operation {*}/}~\\
\texttt{\};}
\item Zugriff über den Systemaufruf\texttt{}~\\
\texttt{int semop ( int semid, struct sembuf {*}sops, unsigned nsops
)}
\item eine Operation auf einer Semaphore:\texttt{}~\\
\texttt{struct sembuf \{}~\\
 \texttt{ unsigned short sem\_num; /{*} semaphore index in array {*}/}~\\
 \texttt{ short sem\_op;       /{*} semaphore operation {*}/}~\\
 \texttt{ short sem\_flg;         /{*} operation flags {*}/}~\\
\texttt{\};}
\item {}``undo''-Funktion: negierte Operationen in der \texttt{struct
sem\_undo}
\item n:m Kommunikationsbeziehung, aber kein Datenaustausch
\end{itemize}

\lyxnewslide{System V IPC - Message queues (1)}

Message queues

\begin{itemize}
\item Verschicken von {}``Nachrichten''
\item mit Typkennzeichnung
\item Erzeugen einer message queue mit dem Systemaufruf\\
\texttt{int msgget ( key\_t key, int msgflg )}
\item Im Kernel: \texttt{struct msg\_queue} {[}ipc/msg.c{]}
\end{itemize}

\lyxnewslide{System V IPC - Message queues (2)}

\begin{lyxcode}
struct~msg\_queue~\{~\\
~~struct~kern\_ipc\_perm~q\_perm;~\\
~~time\_t~q\_stime;~~~~~~~~~~/{*}~last~msgsnd~time~{*}/~\\
~~time\_t~q\_rtime;~~~~~~~~~~/{*}~last~msgrcv~time~{*}/~~\\
~~time\_t~q\_ctime;~~~~~~~~~~/{*}~last~change~time~{*}/~\\
~~unsigned~long~q\_cbytes;~~/{*}~current~number~of~bytes~on~queue~{*}/~\\
~~unsigned~long~q\_qnum;~~~~/{*}~number~of~messages~in~queue~{*}/~\\
~~unsigned~long~q\_qbytes;~~/{*}~max~number~of~bytes~on~queue~{*}/~\\
~~pid\_t~q\_lspid;~~~~~~~~~~~/{*}~pid~of~last~msgsnd~{*}/~\\
~~pid\_t~q\_lrpid;~~~~~~~~~~~/{*}~last~receive~pid~{*}/~\\
~\\
~~struct~list\_head~q\_messages;~\\
~~struct~list\_head~q\_receivers;~\\
~~struct~list\_head~q\_senders;~\\
\};
\end{lyxcode}

\lyxnewslide{System V IPC - Message queues (3)}

Message queues

\begin{itemize}
\item Elemente von \texttt{q\_messages}:\texttt{}~\\
\texttt{struct msg\_msg \{}~\\
 \texttt{struct list\_head m\_list;}~\\
 \texttt{long m\_type;}~\\
 \texttt{int m\_ts; /{*} message text size {*}/}~\\
 \texttt{struct msg\_msgseg{*} next;}~\\
 \texttt{/{*} the actual message follows immediately {*}/}~\\
\texttt{\};}
\item \texttt{ssize\_t msgrcv ( int msqid, struct msgbuf {*}msgp, size\_t
msgsz, long msgtyp, int msgflg )}
\item \texttt{int msgsnd ( int msqid, struct msgbuf {*}msgp, size\_t msgsz,
int msgflg )}
\end{itemize}

\lyxnewslide{System V IPC - Message queues (4)}

Message queues

\begin{itemize}
\item eine Nachricht:\\
\texttt{struct msgbuf \{}~\\
 \texttt{ long mtype; /{*} type of message {*}/}~\\
 \texttt{ char mtext{[}1{]}; /{*} message text {*}/}~\\
\texttt{\};}
\item Zugriff auf eine message queue zwar von mehreren Prozessen möglich,
Datenaustausch jedoch 1:1, gelesene Nachrichten werden sofort aus
der message queue entfernt
\end{itemize}

\lyxnewslide{System V IPC - Shared memory (1)}

Shared memory

\begin{itemize}
\item gemeinsame Speicherbereiche verschiedener Prozesse
\item schnellste Form von IPC
\item keine Synchronisation
\item Erzeugen eines shares memory Bereichs:\\
\texttt{int shmget(key\_t key, int size, int shmflg)}
\item im Kernel: \texttt{struct shmid\_kernel} {[}ipc/shm.c{]}
\end{itemize}

\lyxnewslide{System V IPC - Shared memory (2)}

\begin{lyxcode}
struct~shmid\_kernel~/{*}~private~to~the~kernel~{*}/~\\
\{~\\
~~struct~kern\_ipc\_perm~shm\_perm;~\\
~~struct~file~{*}~shm\_file;~\\
~~int~id;~\\
~~unsigned~long~shm\_nattch;~\\
~~unsigned~long~shm\_segsz;~\\
~~time\_t~shm\_atim;~\\
~~time\_t~shm\_dtim;~\\
~~time\_t~shm\_ctim;~\\
~~pid\_t~shm\_cprid;~\\
~~pid\_t~shm\_lprid;~\\
\};
\end{lyxcode}

\lyxnewslide{System V IPC - Shared memory (3)}

Shared memory

\begin{itemize}
\item \texttt{shm\_file}: eine {}``unlinked'' (nicht sichtbare) Datei
im FS (shmfs gemountet unter /dev/shm/)
\item Zugriff über:\\
\texttt{void {*}shmat ( int shmid, const void {*}shmaddr, int shmflg
)}~\\
\texttt{int shmdt ( const void {*}shmaddr)}~\\
Zuordnen des shared memory Segments zum eigenen Datensegment ({}``attach'')
\item shared memory kann von beliebig vielen Prozessen benutzt werden ->
n:m Kommunikationsbeziehung
\end{itemize}

\lyxnewslide{System V IPC - ipcs und ipcrm}

ipcs / ipcrm

\begin{lyxcode}
han:\textasciitilde{}~\#~ipcs~\\
-{}-{}-{}-{}-{}-~Shared~Memory~Segments~-{}-{}-{}-{}-{}-{}-{}-~\\
key~~~~~~~shmid~~owner~~~perms~~bytes~~~~nattch~status~\\
0x00000000~512~~~root~~~~600~~~~1056768~~~3~~~~~~dest~\\
0x00000000~513~~~wwwrun~~600~~~~46084~~~~~3~~~~~~dest~\\
0x74b8f640~514~~~oracle~~640~~~~374599680~14~\\
0xd06f7024~515~~~oracle~~640~~~~255062016~10~\\
0x91b0e5f8~516~~~oracle~~640~~~~143319040~11~\\
-{}-{}-{}-{}-{}-~Semaphore~Arrays~-{}-{}-{}-{}-{}-{}-{}-~\\
key~~~~~~~semid~~owner~~~perms~~nsems~~status~\\
0x06999a36~1536~~oracle~~640~~~~~154~\\
0x052b3e16~3073~~oracle~~640~~~~~154~\\
0x0699aa36~4610~~oracle~~640~~~~~154~\\
-{}-{}-{}-{}-{}-~Message~Queues~-{}-{}-{}-{}-{}-{}-{}-~\\
key~~~~~~~msqid~~owner~~~perms~~used-bytes~~~messages~\\
han:\textasciitilde{}~\#
\end{lyxcode}

\lyxnewslide{IPC mit Sockets (1)}

IPC mit Sockets

\begin{itemize}
\item spezielle Variante der Sockets: Unix-Domain-Sockets
\item gleiche Arbeitsweise wie normale Sockets
\item \texttt{AF\_UNIX} o. \texttt{AF\_LOCAL} beim \texttt{socket()} Aufruf
angeben
\item Bei \texttt{connect()} Angabe eines \texttt{struct sockaddr\_un} statt
normalerweise \texttt{struct sockaddr}
\end{itemize}

\lyxnewslide{IPC mit Sockets (2)}

IPC mit Sockets

\begin{itemize}
\item {[}include/linux/un.h{]}\texttt{}~\\
\texttt{\#define UNIX\_PATH\_MAX 108}~\\
\texttt{}~\\
\texttt{struct sockaddr\_un \{}~\\
 \texttt{sa\_family\_t sun\_family; /{*} AF\_UNIX {*}/}~\\
 \texttt{char sun\_path{[}UNIX\_PATH\_MAX{]}; /{*} pathname {*}/}~\\
\texttt{\};}
\item Dateiname repräsentiert den Socket im Dateisystem
\item Socket kann von vielen Prozessen genutzt werden, Datenaustausch jedoch
nur 1:1
\end{itemize}

\lyxnewslide{Zusammenfassung Kommunikationsbeziehungen}

{\centering Zusammenfassung der\\
Kommunikationsbeziehungen\par}

\vspace{20pt}

\begin{longtable}{|c|c|c|}
\hline 
IPC-Art&
Beziehung&
Datenaustausch\\
\hline
\hline 
Lock files&
1:n&
nein\\
\hline
\hline 
File locks&
1:n&
ja\\
\hline
\hline 
Pipes&
1:1&
ja\\
\hline
\hline 
Named Pipes&
1:1&
ja\\
\hline
\hline 
Semaphoren&
n:m&
nein\\
\hline
\hline 
Message queues&
1:1&
ja\\
\hline
\hline 
Shared memory&
n:m&
ja\\
\hline
\hline 
Sockets&
1:n&
ja\\
\hline
\end{longtable}


\lyxnewslide{Übersicht Netzwerkkommunikation (1)}

Netzwerkkommunikation

\begin{itemize}
\item BSD-Socket
\item INET-Socket
\item TCP/UDP
\item IP
\item Netzwerkgeräte
\end{itemize}

\lyxnewslide{Übersicht Netzwerkkommunikation (2)}

\vspace{0.3cm}
{\centering \resizebox*{1\textwidth}{0.6\textheight}{\includegraphics{net_layers.eps}} \par}
\vspace{0.3cm}


\lyxnewslide{BSD-Socket (1)}

BSD-Socket

\begin{itemize}
\item Schnittstelle für Programmierer: C-Bibliothek\\
int socket(int domain, int type, int protocol);
\end{itemize}
\begin{lyxcode}
int~bind(int~sockfd,~struct~sockaddr~{*}my\_addr,~socklen\_t~addrlen);

int~listen(int~s,~int~backlog);

int~connect(int~sockfd,~const~struct~sockaddr~{*}serv\_addr,~socklen\_t~addrlen);

int~accept(int~s,~struct~sockaddr~{*}addr,~socklen\_t~{*}addrlen);

int~send(int~s,~const~void~{*}msg,~size\_t~len,~int~flags);

int~sendto(int~s,~const~void~{*}msg,~size\_t~len,~int~flags,~const~struct~sockaddr~{*}to,~socklen\_t~tolen);

int~recv(int~s,~void~{*}buf,~size\_t~len,~int~flags);

int~recvfrom(int~s,~void~{*}buf,~size\_t~len,~int~flags,~struct~sockaddr~{*}from,~socklen\_t~{*}fromlen);

int~getsockopt(int~s,~int~level,~int~optname,~void~{*}optval,~socklen\_t~{*}optlen);

int~setsockopt(int~s,~int~level,~int~optname,~const~void~{*}optval,~socklen\_t~optlen);
\end{lyxcode}

\lyxnewslide{BSD-Socket (2)}

BSD-Socket

\begin{itemize}
\item ein Socket im Kernel: \texttt{struct socket} {[}include/linux/net.h{]}
\end{itemize}
\begin{lyxcode}
struct~socket~\{~\\
~~socket\_state~state;

~~unsigned~long~flags;

~~struct~proto\_ops~{*}ops;

~~struct~inode~{*}inode;~\\
~~struct~fasync\_struct~{*}fasync\_list;~\\
~~struct~file~{*}file;

~~struct~sock~{*}sk;

~~wait\_queue\_head\_t~wait;~\\
~~short~type;

~~unsigned~char~passcred;

\};
\end{lyxcode}

\lyxnewslide{BSD-Socket (3)}

\begin{lyxcode}
struct~sk\_buff~\{~\\
~~struct~sk\_buff~{*}~next;~~~~~~~/{*}~Next~buffer~in~list~{*}/~\\
~~struct~sk\_buff~{*}~prev;~~~~~~~/{*}~Previous~buffer~in~list~{*}/~\\
~~struct~sk\_buff\_head~{*}~list;~~/{*}~List~we~are~on~{*}/~\\
~~struct~sock~{*}sk;~~~~~~~~~~~~~/{*}~Socket~we~are~owned~by~{*}/~\\
~~struct~timeval~stamp;~~~~~~~~/{*}~Time~we~arrived~{*}/~\\
~~struct~net\_device~{*}dev;~~~~~~/{*}~Device~we~arrived~on/are~leaving~by~{*}/~\\
~\\
~~/{*}~Transport~layer~header~{*}/~\\
~~union~\{~\\
~~~~struct~tcphdr~{*}th;~\\
~~~~struct~udphdr~{*}uh;~\\
~~~~struct~icmphdr~{*}icmph;~\\
~~~~struct~igmphdr~{*}igmph;~\\
~~~~struct~iphdr~{*}ipiph;~\\
~~~~unsigned~char~{*}raw;~\\
~~\}~h;~\\
~\\
~~/{*}~Network~layer~header~{*}/~\\
~~union~\{~\\
~~~~struct~iphdr~{*}iph;~\\
~~~~struct~ipv6hdr~{*}ipv6h;~\\
~~~~struct~arphdr~{*}arph;~\\
~~~~struct~ipxhdr~{*}ipxh;~\\
~~~~unsigned~char~{*}raw;~\\
~~\}~nh;~\\
~\\
~~/{*}~Link~layer~header~{*}/~\\
~~union~\{~\\
~~~~struct~ethhdr~{*}ethernet;~\\
~~~~unsigned~char~{*}raw;~\\
~~\}~mac;~\\
~...~\\
~~struct~dst\_entry~{*}dst;~\\
~\\
~~unsigned~int~truesize;~~/{*}~Buffer~size~{*}/~\\
~~unsigned~char~{*}head;~~~~/{*}~Head~of~buffer~{*}/~\\
~~unsigned~char~{*}data;~~~~/{*}~Data~head~pointer~{*}/~\\
~~unsigned~char~{*}tail;~~~~/{*}~Tail~pointer~{*}/~\\
~~unsigned~char~{*}end;~~~~~/{*}~End~pointer~{*}/~\\
~...~\\
\};
\end{lyxcode}

\lyxnewslide{BSD-Socket (4)}

BSD-Socket

\begin{itemize}
\item die in {[}net/socket.c{]} implementierten Funktionen greifen über
den \texttt{ops} Eintrag des \texttt{struct socket} auf die Funktionen
der INET-Socket Schicht zu
\end{itemize}

\lyxnewslide{INET-Socket (1)}

INET-Socket

\begin{itemize}
\item AF\_INET Adressfamilie (TCP/IP)
\item wichtigste Struktur: \texttt{struct sock} {[}include/net/sock.h{]}
(gekürzt)
\end{itemize}

\lyxnewslide{INET-Socket (2)}

\begin{lyxcode}
struct~sock~\{~\\
~~\_\_u32~daddr;~\\
~~\_\_u16~dport;~\\
~~\_\_u32~saddr;~\\
~~\_\_u16~sport;

~~struct~sk\_buff\_head~receive\_queue;

~~struct~sk\_buff\_head~write\_queue;

struct~proto~{*}prot;

~union~\{~\\
~~~~struct~tcp\_opt~af\_tcp;~~\\
~~~~struct~raw\_opt~tp\_raw4;~\\
~~~~struct~raw6\_opt~tp\_raw;~\\
~~~~struct~spx\_opt~af\_spx;~\\
~~\}~tp\_pinfo;

~~union~\{~\\
~~~~struct~unix\_opt~af\_unix;~\\
~~~~struct~inet\_opt~af\_inet;~\\
~~~~struct~atalk\_sock~af\_at;~\\
~~~~struct~ipx\_opt~af\_ipx;~\\
~~~~...~\\
~~\}~protinfo;

~~...~\\
\};
\end{lyxcode}

\lyxnewslide{INET-Socket (3)}

INET-Socket

\begin{itemize}
\item Funktionen der AF\_INET Adressfamilie implementiert in {[}net/ipv4/af\_inet.c{]}
\end{itemize}
\begin{lyxcode}
inet\_stream\_connect(struct~socket~{*}sock,~struct~sockaddr~{*}~uaddr,~int~addr\_len,~int~flags);

inet\_dgram\_connect(struct~socket~{*}sock,~struct~sockaddr~{*}~uaddr,~int~addr\_len,~int~flags);~extern~inet\_accept(struct~socket~{*}sock,

inet\_listen(struct~socket~{*}sock,~int~backlog);

inet\_accept(struct~socket~{*}sock,~struct~socket~{*}newsock,~int~flags);

inet\_recvmsg(struct~socket~{*}sock,~struct~msghdr~{*}ubuf,~int~size,~int~flags,~struct~scm\_cookie~{*}scm);

inet\_sendmsg(struct~socket~{*}sock,~struct~msghdr~{*}msg,~int~size,~struct~scm\_cookie~{*}scm);

inet\_shutdown(struct~socket~{*}sock,~int~how);

inet\_setsockopt(struct~socket~{*}sock,~int~level,~int~optname,~char~{*}optval,~int~optlen);

inet\_getsockopt(struct~socket~{*}sock,~int~level,~int~optname,~char~{*}optval,~int~{*}optlen);
\end{lyxcode}

\lyxnewslide{INET-Socket (4)}

INET-Socket

\begin{itemize}
\item diese Funktionen werden aus der BSD-Socket Schicht aus aufgerufen
\item rufen ihrerseits über den \texttt{prot} Eintrag der \texttt{struct
sock} Funktionen der jeweiligen Transportschicht auf
\end{itemize}
\begin{lyxcode}
struct~proto~\{~\\
~~int~({*}connect)(struct~sock~{*}sk,~struct~sockaddr~{*}uaddr,~int~addr\_len);~\\
~~int~({*}setsockopt)(struct~sock~{*}sk,~int~level,~int~optname,~char~{*}optval,~int~optlen);~\\
~~int~({*}getsockopt)(struct~sock~{*}sk,~int~level,~int~optname,~char~{*}optval,~int~{*}option);~\\
~~int~({*}sendmsg)(struct~sock~{*}sk,~struct~msghdr~{*}msg,~int~len);~\\
~~int~({*}recvmsg)(struct~sock~{*}sk,~struct~msghdr~{*}msg,~int~len,~int~noblock,~int~flags,~int~{*}addr\_len);~\\
~~int~({*}bind)(struct~sock~{*}sk,~struct~sockaddr~{*}uaddr,~int~addr\_len);~\\
...~\\
\};
\end{lyxcode}

\lyxnewslide{TCP/UDP (1)}

TCP/UDP

\begin{itemize}
\item Transportschicht
\item transportiert {}``Nachrichten'' nach Art des 4.4BSD message passing
system:\\
\texttt{struct msghdr} {[}include/linux/socket.h{]}
\end{itemize}
\begin{lyxcode}
struct~msghdr~\{~\\
~void~{*}~msg\_name;~~~~~~~~/{*}~Socket~name~{*}/~\\
~int~msg\_namelen;~~~~~~~~/{*}~Length~of~name~{*}/~\\
~struct~iovec~{*}~msg\_iov;~/{*}~Data~blocks~{*}/~\\
~\_\_kernel\_size\_t~msg\_iovlen;~~/{*}~Number~of~blocks~{*}/~\\
~void~{*}~msg\_control;~~~~~/{*}~Per~protocol~magic~(eg~BSD~file~descriptor~passing)~{*}/~\\
~\_\_kernel\_size\_t~msg\_controllen;~~/{*}~Length~of~cmsg~list~{*}/~\\
~unsigned~msg\_flags;~\\
\};
\end{lyxcode}

\lyxnewslide{TCP/UDP (2)}

TCP/UDP

\begin{itemize}
\item Funktionen verarbeiten diese {}``Nachrichten'' zu Pakete der \texttt{struct
sk\_buff}
\item implementiert in {[}net/ipv4/udp.c{]}, {[}net/ipv4/tcp.c{]}, {[}net/ipv4/tcp\_v4.c{]}
\end{itemize}
\begin{lyxcode}
int~udp\_connect(struct~sock~{*}sk,~struct~sockaddr~{*}uaddr,~int~addr\_len)~\\
int~tcp\_v4\_connect(struct~sock~{*}sk,~struct~sockaddr~{*}uaddr,~int~addr\_len)~\\
int~tcp\_sendmsg(struct~sock~{*}sk,~struct~msghdr~{*}msg,~int~size)~\\
int~udp\_sendmsg(struct~sock~{*}sk,~struct~msghdr~{*}msg,~int~len)~\\
int~tcp\_recvmsg(struct~sock~{*}sk,~struct~msghdr~{*}msg,~int~len,~int~nonblock,~int~flags,~int~{*}addr\_len)~\\
int~udp\_recvmsg(struct~sock~{*}sk,~struct~msghdr~{*}msg,~int~len,~int~nonblock,~int~flags,~int~{*}addr\_len)
\end{lyxcode}
\begin{itemize}
\item benutzen Funktionen der IP-Schicht
\end{itemize}

\lyxnewslide{IP (1)}

IP

\begin{itemize}
\item allg. {}``Paketübermittlungsdienst''
\item Paket (\texttt{struct sk\_buff}) \& Adresse -> Übermittlung
\item keine Garantie, dass das Paket ankommt (->TCP)
\item wichtige Struktur: \texttt{struct iphdr} {[}include/linux/ip.h{]}
\item Unterteilung: Empfangen, Weiterleiten, Senden von IP-Paketen
\end{itemize}

\lyxnewslide{IP (2)}

\begin{lyxcode}
struct~iphdr~\{~\\
\#if~defined(\_\_LITTLE\_ENDIAN\_BITFIELD)~\\
~~\_\_u8~ihl:4,~\\
~~version:4;~\\
\#elif~defined~(\_\_BIG\_ENDIAN\_BITFIELD)~\\
~~\_\_u8~version:4,~\\
~~ihl:4;~\\
\#else~\\
\#error~\char`\"{}Please~fix~<asm/byteorder.h>\char`\"{}~\\
\#endif~\\
~~\_\_u8~tos;~\\
~~\_\_u16~tot\_len;~\\
~~\_\_u16~id;~\\
~~\_\_u16~frag\_off;~\\
~~\_\_u8~ttl;~\\
~~\_\_u8~protocol;~\\
~~\_\_u16~check;~\\
~~\_\_u32~saddr;~\\
~~\_\_u32~daddr;~\\
~~/{*}The~options~start~here.~{*}/~\\
\};
\end{lyxcode}

\lyxnewslide{IP (3)}

IP - Empfangen:

\begin{enumerate}
\item Erhalt des Pakets\\
\texttt{int ip\_rcv(struct sk\_buff {*}skb, struct net\_device {*}dev,
struct packet\_type {*}pt)}\\
{[}net/ipv4/ip\_input.c{]}, Empfang eines \texttt{sk\_buff} vom Netzwerkgerät
\texttt{dev}\\

\item Überprüfen des IP-Headers\\
RFC 1122:\\
1. angegebene Länge des Paktes gültig?\\
2. IP-Versionsnummer korrekt?\\
3. IP Checksumme ok?\\

\item Vergleich der Zieladresse mit der eigenen Adresse\\
\texttt{ip\_rcv\_finish(struct sk\_buff {*}skb)}:\texttt{}~\\
\texttt{ip\_route\_input()} ?\\
lokaler Rechner: \texttt{int ip\_local\_deliver(struct sk\_buff {*}skb)}~\\
sonst\texttt{: int ip\_forward(struct sk\_buff {*}skb)} \\

\item Defragmentierung des IP-Pakets\\
Fragment? -> zusammen mit anderen Fragmenten defragmentieren\\
fehlen Fragmente? -> Fragmentliste\\
\texttt{struct sk\_buff {*}ip\_defrag(struct sk\_buff {*}skb)} {[}net/ipv4/ip\_fragment.c{]}\\

\item Übergabe des Pakets an das nächste Protokoll\\
\texttt{ip\_rcv\_finish(): skb->dst->input(skb)} (Funktions-Zeiger
der \texttt{input} Funktion der höheren Transportschicht.
\end{enumerate}

\lyxnewslide{IP (4)}

IP - Weiterleiten

\texttt{int ip\_forward(struct sk\_buff {*}skb)}~\\
{[}net/ipv4/ip\_forward.c{]}

\begin{enumerate}
\item Überprüfen des \texttt{ttl} Feldes im IP-Header\\
<=1 ? -> Paket verwerfen, ICMP-Nachricht an Absender\\

\item Überprüfen des Pakets auf fehlerhaftes/ungewolltes Routing\\
 (z.B: ''strict routing'' aber Ziel kein Gateway)\\

\item Kopieren des Paket-Headers\\
copy on write des \texttt{sk\_buff} Headers (\texttt{skb\_cow()} {[}include/linux/skbuff.h{]})\\

\item Setzen/Ändern von IP Optionen\\
Aufruf \texttt{void ip\_forward\_options(struct sk\_buff {*}skb)}
{[}net/ipv4/ip\_options.c{]}\\

\item Senden\\
Aufruf \texttt{int ip\_send(struct sk\_buff {*}skb)} (als \texttt{static
inline} in {[}include/net/ip.h{]} implementiert).\\
MTU Grösse überschritten? -> fragmentieren (\texttt{ip\_fragment()})\texttt{}~\\
dann per \texttt{int ip\_finish\_output(struct sk\_buff {*}skb)} verschicken
{[}net/ipv4/ip\_output.c{]}
\end{enumerate}

\lyxnewslide{IP (5)}

IP - Senden

\begin{enumerate}
\item Erhalt des Pakets\\
\\
(z.B. durch Aufruf der Funktion \texttt{int ip\_queue\_xmit(struct
sk\_buff {*}skb)} {[}net/ipv4/ip\_output.c{]})\\

\item Ermitteln der Ziel-Route\\
\\
Aufruf \texttt{ip\_route\_output()} {[}include/net/route.h{]} -> Netzwerkgerät
über das das Paket verschickt werden soll\\

\item Füllen des IP-Headers\\
\\
\texttt{skb\_push()} {[}include/linux/skbuff.h{]} macht am Anfang
des \texttt{sk\_buff} Platz für IP-Header -> füllen mit entsprechenden
Werten (Quell- und Ziel-Adresse)\\

\item Fragmentierung des IP-Pakets\\
\\
\texttt{int ip\_queue\_xmit2(struct sk\_buff {*}skb)}:\\
MTU Grösse überschritten? -> \texttt{int ip\_fragment()} {[}net/ipv4/ip\_output.c{]}\\

\item Setzen der IP-Checksumme\\
\\
\texttt{void ip\_send\_check(struct iphdr {*}iph)} {[}net/ipv4/output.c{]}\\

\item Übergabe an das entsprechende Netzwerkgerät\\
\\
Aufruf \texttt{skb->dst->output(skb)} -> \texttt{dev\_queue\_xmit()}
des Netzwerkgerätes
\end{enumerate}

\lyxnewslide{Netzwerkgeräte (1)}

Netzwerkgeräte

\begin{itemize}
\item hardwareunabhängige Schnittstelle
\item \texttt{struct net\_device} {[}include/linux/netdevice.h{]} verwaltet
ein abstaktes Netzwerkgerät
\item Name (eth0), IRQ / IO-Adresse, Hardwareadresse (MAC bei Ethernet),
Multicast-, Broadcastadresse, statistische Angaben (\# empfangener
\& gesandter Pakete)
\end{itemize}

\lyxnewslide{Netzwerkgeräte (2)}

Netzwerkgeräte

\begin{itemize}
\item Funktionszeiger zur hardwarespezifischen Implementation:\\
\texttt{int ({*}init)(struct net\_device {*}dev);}~\\
\texttt{int ({*}open)(struct net\_device {*}dev);}~\\
\texttt{int ({*}stop)(struct net\_device {*}dev);}~\\
\texttt{int ({*}hard\_start\_xmit) (struct sk\_buff {*}skb, struct
net\_device {*}dev);}
\item werden von den hardwareunabhängigen Funktionen {[}net/core/dev.c{]}
benutzt
\item Bsp.: \texttt{void dev\_queue\_xmit(struct sk\_buff {*}skb, struct
net\_device {*}dev)}: überprüft ob Netzwerkgerät gerade beschäftigt
ist, überträgt Paket entweder sofort per \texttt{hard\_start\_xmit()}
oder trägt es in Liste der noch zu sendenden Pakete des \texttt{struct
net\_device} ein
\end{itemize}

\lyxnewslide{Referenzen}

\begin{itemize}
\item ''Linux-Kernel-Programmierung'', Beck, Böhme, Dziadzka, Kunitz,
Magnus, Verworner, Addison Wesley, ISBN 3-8273-1144-6
\item ''The Linux Kernel'', David A Rusling, \url{http://www.linuxdoc.org/LDP/tlk/}
\item ''Linux Kernel 2.4 Internals'', Tigran Aivazian, \url{http://www.moses.uklinux.net/patches/lki.html}
\item ''Interprocess Communication in Unix'', John Shapley Gray, Prentice
Hall, ISBN 0-13-186891-8
\item Linux IP Networking, Glenn Herrin, \url{http://kernelnewbies.org/documents/ipnetworking/linuxipnetworking.html}
\item ''Understanding the Linux Kernel'', Daniel P. Bovet, Marco Cesati,
O'Reilly\end{itemize}

\end{document}
