The Network Layer (2.4)

References:
Linux Networking Howto ...
PPP Howto ...
G. Herrin, Linux IP Networking, 2000, available on www.kernelnewbies.org

Networking

This section summarizes the network configuration of a Linux system. In order to configure the networking one need to set up a few scripts and files, besides having the proper support compiled in the kernel or as module (but this is ususally the case).
An isolated host usually has only the loopback interface (IP 127.0.0.1), and can have a temporary ppp interface when it dials up. The bootproto should be set to "dhcp" if the IP address of the interface is retrieved, using dhcp, from a dhcp server. In this case BROADCAST, IPADDR, NETMASK, NETWORK and GATEWAY are not used and unnnecessary.



ppp connection
To set up a ppp connection start the pppd daemon with the "connect" option and a suitable chat script; for example,
   /usr/sbin/pppd connect '/usr/sbin/chat -v -f /etc/ppp/chat-isp ' \
   user marco_corvi@geocities.com -d -detach &

The pppd deamon is passed the the command "connect" which takes the script to execute for the connection. The option "-detach" tells the deamon to go in background. The command "user" sets the username used for authenticating with the peer. The options of "chat" specify the verbose mode, and the chat file to use. This file must contain the information to dial up your ISP with your modem. For example, I have
   ABORT "NO CARRIER"
   ABORT "NO DIALTONE"
   ABORT "ERROR"
   ABORT "NO ANSWER"
   ABORT "BUSY"
   ECHO OFF
   SAY "Dialing your ISP ... \n"
   "" "at"
   OK "atz1"
   OK "atdt<ISP_NUMBER>"
   TIMEOUT 60
   SAY "Waiting up to one minute ... \n"
   ECHO ON
   CONNECT ""

The interface will have the name of the pidfile /var/run/ppp*.pid which contains the pid of the deamon. The interface configuration can be seen with the command
   /sbin/ifconfig ppp_interface

The pppd deamon executes a few additional scripts:

Finally pppd uses an configuration file, /etc/ppp/options, which specifies all the other options. Here is an example,

# /etc/ppp/options
#
/dev/cua1       # device (should try /dev/ttyS1)
# /dev/modem
57600           # speed (try 115200 !!!)
debug           # debugging messages
lock            # lock the device
modem           # use modem control lines (CD): this is the default
# local           # do not use modem contro lines (ignore CD)
hide-password   # do not show password in syslog
logfile /etc/ppp/ppp.log  # logfile for stat purposes
# record /etc/ppp/ppp.rec # record file for pppdump (must try)
crtscts         # hw flow control
defaultroute    # `route add default`
noipdefault     # () disable local ip from hostname: peer must supply it
                # see local_ip_address:remote_ip_address option
# usepeerdns      # use if the provider does not supply DNS
                # see /etc/resolv.conf
# allow-ip *      # allow any ip_addr for the peer (w/o authentication)
asyncmap 0      # () no obsolete byte escaping
# mtu 552         # (can leave it disabled)
# mru 552         # (can leave it disabled: default 1500)
idle 180        # disconnect if we do not do anything for three minutes
deflate 15,15   # request peer deflate compresion (value range 8-15)
                # must have kernel module for BSD compression
bsdcomp 15,15   # request peer bsd compression (value range 9-15, 15 max)
                # pppd second choice (see man pppd)
                # must have kernel module for BSD compression
predictor1      # request peer predictor-1 compression
                # no effect unless kernel module supported
vj-max-slots 16 # number of VJ TCP/IP header compression slots (max 16) 

Last the /etc/ppp/pap-secrets file should contain your login data (so it should be readable only by root),

 
# Secrets for authentication using PAP
# client        server  secret                  IP addresses
marco_corvi@geocities.com * my_password

To terminate the connection send a SIGHUP to the pppd deamon,

   kill -HUP ppd_pid




Network packets

References:
J. Postel, RFC 791 INTERNET PROTOCOL
J. Postel, RFC 793 TRANSMISSION CONTROL PROTOCOL




Networking is structured in a layered architectures (the OSI model) in which the upper level relies on the lower level to send/receive data.
  1. The bottom level is the physical layer, with network boards, switches, cables, or radiowave, or whetever else;
  2. Immediately above it is the data-link layer. This puts the datagrams in packets and transmits them via the network interface. It adds start and end flags and bit error checking (CRC or parity).
  3. Above it is the network layer. This layer is responsible for routing the packets so that they can reach their destination. It may split the segment in fragments. It sends/receives datagrams.
  4. Next there is the transport layer. This layer breaks the data in small-size chunks (segments) that can be send to the network. It also reassembles incoming packets into a stream. It provides also error checking.
  5. Above is the session layer. This layer manages the logical control: source and destination, startup and shutdown of a session.
  6. Above is the presentation layer. This layer translates data from the network in a format usable by the application, and viceversa from application format into network format. Below this point bytes are a stream of octets.
  7. At the top there is the application layer, which interacts with the user and with other programs.



The network implementation does not strictly follow this model. TCP provides initialization of a connection (three way handshake), finilazation (FIN-ACK), and control. TCP is session aware (logical ports). IP provides fragmentation of long segments, and machine to machine routing with the IP address system. Finally ethernet encapsulates packets with their physical (MAC) address.



BSD Packet Filter

References:
McCanne, S. and Jacobson V., "The BSD Packet Filter: A New Architecture for User-level Packet Capture". Proceedings of the 1993 Winter USENIX Technical Conference, San Diego, CA.



To be able to attach a BPF filter to the socket you need to have compiled the kernel with the CONFIG_FILTER option. Infact the sock_setsockopt commands SO_ATTACH_FILTER and SO_DETACH_FILTER are conditioned to it (see net/core/sock.c). These act on the socket's sock. The first copies the filter code from userspace in a temporary sock_fprog, and calls sk_attach_filter. The second sets to NULL the sock's filter, and calls sk_filter_realease to free the filter: this does some sock bookkeeping, and free the filter if its ref-count drops to 0 (see include/net/sock.h).
The filter structures are defined in include/linux/filter.h. An instruction is stored in a sock_filter structure, which is exactly as described in the paper: 16 bits of opcode, 8 bits of jump true, 8 of jump false, and 32 bits of multiuse field. A filter program sock_fprog is an array of instructions: it contains the len of the filter and a pointer to the instructions. Finally a kernel sk_filter is a sock_fprog with prepended a refcnt.
A number of macros are available to write BPF code. Two can be used to write the filter statements, The instruction codes are
Instrcution code BPF_LD load in A register A = k, A = M[k], A = P[k], A = P[X=k]
BPF_LDX load in X (index) register X = k, X = M[k], X = len, X = 4*(P[k]&0xf)
BPF_ST store A register in scratch memory M[k] = A
BPF_STX store X (index) register in scratch memory M[k] = X
BPF_ALU perform arithmetical operations A = A+k, A = A-k, A = A*k, A = A/k, A = A&k, A = A|k, A = A<<k, A = A>>k, A = A+X, A = A-X, A = A*X, ..., A = -A
BPF_JMP jump instructions ...
BPF_RET return the number of accepted bytes ret A, ret k
BPF_MISC miscellaneous instruction X = A, A = X
size BPF_W word (32 bits)  
BPF_H half-word (16 bits)  
BPF_B byte (8 bits)  
addressing mode BPF_IMM constant  
BPF_ABS absolute packet offset  
BPF_IND relative packet offset  
BPF_MEM from scratch memory  
BPF_LEN packet length  
BPF_MSH ...  
arithmetical operations BPF_ADD addition A = A + k, A = A + X
BPF_SUB subtraction A = A - k, A = A - X
BPF_MUL multiplication A = A * k, A = A * X
BPF_DIV division A = A / k, A = A / X
BPF_OR bitwise or A = A | k, A = A | X
BPF_AND bitwise and A = A & k, A = A & X
BPF_LSH left shift A = A << k, A = A << X
BPF_RSH right shift A = A >> k, A = A >> X
BPF_NEG negative A = - A
jump instructions BPF_JA jump pc += k
BPF_JEQ jump if equal pc += (A==k)? jt : jf
pc += (A==X)? jt : jf
BPF_JGT jump if greater pc += (A>k)? jt : jf
pc += (A>X)? jt : jf
BPF_JGE jump if greater or equal pc += (A>=k)? jt : jf
pc += (A>=X)? jt : jf
BPF_JSET jump if in set pc += (A & k) ? jt : jf
pc += (A & X) ? jt : jf
registers BPF_K constant  
BPF_X index register  
BPF_A accumulator register  
exchange instructions BPF_TAX copy A into X X = A
BPF_TXA copy X into A A = X
Instructions are composed by adding the pieces together, instruction code, optionally the size, and the addressing mode.
struct bpf_insn insns[] = {
  BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),
  BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_REVARP, 0, 3),
  BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 20),
  BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, REVARP_REQUEST, 0, 1),
  BPF_STMT(BPF_RET+BPF_K, sizeof(struct ether_arp) + sizeof(struct ether_header)),
  BPF_STMT(BPF_RET+BPF_K, 0),
};



Example

sniff.c, a simple sniffer

Network kernel structures

References:




The net_device
The struct net_device is defined in the header file include/linux/netdevice.h. It contains, among the others, the following fields,
Its methods are, among the others,
The list of all net_device's is pointed to by dev_base, and dev_base_lock protects from concurrent access to it. The loopback_dev is a net_device.


The socket structure
The structure socket is defined in the header file include/linux/net.h and is rather short,
The proto_ops and proto structures
The protocol operations, struct proto_ops, are the user interface API. At the user level there is only one system call sys_socket(); the specific function is selected with an index. Indeed the user systemcalls do not map 1-1 on the propotol functions. The proto structure is a function table with pointers to routines for the IP protocol, that operate on the sock structure. The functions are, mainly, The inet protocols are kept on the list inetsw. At start three static protocols are added, SOCK_STREAM, SOCK_DGRAM, and SOCK_RAW. These are permanent and cannot be modified. Other protocols can be registered and unregistered with the functions inet_register_protosw and inet_unregister_protosw respectively. These take as parameter a pointer to a struct inet_protosw which contains, among other things,


The sock structure
The structure sock is defined in the header include/net/sock.h, and is rather large. There is a note in the source saying that it really should be better organized. Among other things it contains
The sk_buff structure
The socket buffer structure sk_buff is defined in include/linux/skbuff.h, and contains (besides other things)



Exercise
[to do]


Marco Corvi - 2003