From de4f373bd531eaaa540bd6533c0fa4bfa41eaeb4 Mon Sep 17 00:00:00 2001
From: Gerhard Rieger Beginning with version 1.7.0 socat provides means to freely control
+ important aspects of socket handling. This allows to experiment with socket
+ types and protocols that are not explicitely implemented in socat.
+ The related socat features fall into three major categories:
+
+ In practice this gives you two possibilities: If you want to cope with sockets staying within the usual domains ( =
+ protocol families = address families) which are IPv4, IPv6, UNIX/local, and
+ raw interface for socat 1.7.0, it is sufficient to learn about a couple of
+ address options that allow to change default
+ parameters, and to apply generic socket options. For other address families socat provides generic socket addresses.
+ A relatively new communication protocol has been introduced in the Internet
+ community for which no socat address type has been implemented up to version
+ 1.7.0
+ (see IETF's
+ Datagram Congestion Control Protocol
+ and Linux
+ foundation Net:DCCP for more info). Taken that the
+ operating system implements DCCP, it is possible to use this protocol
+ with socat while just employing standard socket addresses and some options.
+ A simple server that accepts a DCCP connection, passes the arriving data to a
+ subprocess for converting upper case to lower case characters, and then
+ returns it to the client:
+ A simple client that sends some upper case characters to the server via DCCP
+ and prints what the server returns:
+ We choose the TCP4 addresses as base because it best matches the DCCP
+ requirements:
+ Generic sockets with Socat
+
+Introduction
+
+
+
+Generic socket options
+
+Example 1: DCCP communication
+
+
+
+
Option type=6 changes TCP's + SOCK_STREAM parameter to SOCK_DCCP, and + prototype=33 replaces the + default IPPROTO_TCP with IPPROTO_DCCP. +
+ +DCCP has an important parameter, the service code. It provides another + multiplexing layer beyond the protocol ports. The Linux implementation of DCCP + allows to set this parameter with code like setsocktopt(fd, SOL_DCCP, + DCCP_SOCKOPT_SERVICE, {1}, sizeof(int)). The equivalent generic socat + option is: setsockopt-int=269:2:1 for service code 1. + If the service codes on server and client do not match the connect() + operation fails with error:
+ +
... E connect(3, AF=2 127.0.0.1:4096, 16): Invalid request code |
Please note that this examples works with IPv6 as well, you just need to + replace the TCP4 words with TCP6, and the IPv4 socket address with an + appropriate IPv6 socket address, e.g. [::1]! +
+ + +socat's generic socket addresses are a more comprehensive mechanism that + allows to deal with protocol families whose socket addresses are not supported + by socat - no semantical parsing, no structured assignment to the struct + components are available. Instead, the socket address records for binding and + connecting/sending are specified in unstructured hexadecimal form. The + following example demonstrates this by performing simple data transfer over + raw AppleTalk protocol. +
+ +Note: I do not have any knowledge about AppleTalk. I just managed to + configure my Linux host to tolerate the creation of a receiving and a sending + socket. Don't blame me nor ask me for support if it does not work for you. +
+ + +Install the netatalk package. Check that /etc/netatalk/atalkd.conf + has an entry like eth0 -phase 2 -net 0-65534 -addr 65280.243. The + last part is an arbitrary (?) host address, some of the following values must + fit it. Make sure the atalkd daemon is running. Run the AppleTalk + ping command: +
+ + +aecho 65280.243 + + +If you get an error like: +
+ +Device or resource busy |
then try to restart atalkd:
+ + +/etc/init.d/atalkd restart + + +When aecho works like ping you are ready for the next step. +
+ +We start a socat process with a receiver and echo service: +
+ + +socat SOCKET-RECVFROM:5:2:0:x40x00x0000x00x00x0000000000000000 PIPE + + +Then, in another shell on the same host, we start a client socket process + that sends data to the server and gets the answer: +
+ + +echo ABCD |socat - SOCKET-DATAGRAM:5:2:0:x40x00xff00xf3x00x0000000000000000 + + +The client process should print the data. +
+ +How did this work? The generic socat address has just used the system call + parameters that were provided on command line, without knowing anything about + AppleTalk sockets and protocol. The values 5, 2, and 0 are directly used for + the socket() call: they specify the domain (PF_APPLETALK=5), + socket type (SOCK_DGRAM=2), and no protocol (0) - values for Linux. + The long hex strings define the socket addresses. They can only be constructed + with knowledge of the underlying structure. In + /usr/include/linux/atalk.h we find the following declarations: +
+ ++struct atalk_addr { + __be16 s_net; + __u8 s_node; +}; + +struct sockaddr_at { + sa_family_t sat_family; + __u8 sat_port; + struct atalk_addr sat_addr; + char sat_zero[8]; ++ +
After rolling out atalk_addr and considering implicit padding by the + C programming language we get the following byte map: +
+ +component | offset | length | value | meaning |
---|---|---|---|---|
sat_family | 0 | 2 | x0005 | address family |
sat_port | 2 | 1 | x40 | port |
- | 3 | 1 | x00 | padding |
sat_addr.s_net | 4 | 2 | xff00 | network address |
sat_addr.s_node | 6 | 1 | xf3 | node address |
- | 7 | 1 | x00 | padding |
sat_zero | 8 | 8 | x0000000000000000 | padding |
Note that hexadecimal ff00 is the same as decimal 65280, and hexadecimal xf3 + is the same as decimal 243 - these are the numbers specified in + atalkd.conf. +
+ +The address family component must be omitted from the socket address because + it is added by socat implicitely. The resulting hexadecimal representation of + the target socket address is therefore: +
+x40x00xff00xf3x00x0000000000000000 + +The receiver just has to specify the port, so its bind address data is: +
+x40x00x0000x00x00x0000000000000000 + +Finding the correct parameters and socket addresses is not always trivial. + Therefore this section provides tables with the parameters of common socket + types. Some of these types are directly implemented by socat (and other + programs). Establishing interoperability between a directly implemented + socket and a generic socket might be your first step before entering unknown + ground.
+ +name | domain | socktype | protocol | level | remark | |
---|---|---|---|---|---|---|
UDP4 | PF_INET | SOCK_DGRAM | IPPROTO_UDP | SOL_UDP | ||
UDP6 | PF_INET6 | SOCK_DGRAM | IPPROTO_UDP | SOL_UDP | ||
raw IPv4 | PF_INET | SOCK_RAW | IPPROTO_RAW | SOL_IP | ||
raw IPv6 | PF_INET6 | SOCK_RAW | IPPROTO_RAW | SOL_IPV6 | ||
UNIX | PF_LOCAL | SOCK_DGRAM | 0 | SOL_SOCKET | ||
PACKET | PF_PACKET | SOCK_RAW | 768 | SOL_PACKET | tcpdump (include layer 2 header) | |
PACKET | PF_PACKET | SOCK_DGRAM | 768 | SOL_PACKET | no level 2 header | |
SCTP4 | PF_INET | SOCK_SEQPACKET | IPPROTO_SCTP | SOL_SCTP |
name | Linux | FreeBSD | NetBSD | OpenBSD | Solaris | AIX | Cygwin | Mac OS X | HP-UX |
---|---|---|---|---|---|---|---|---|---|
PF_LOCAL | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
PF_INET | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 |
PF_APPLETALK | 5 | 16 | 16 | 16 | 16 | 16 | 16 | 16 | 16 |
PF_INET6 | 10 | 28 | 24 | 24 | 26 | 24 | - | 30 | 22 |
PF_PACKET | 17 | - | - | - | - | - | - | - | - |
SOCK_STREAM | 1 | 1 | 1 | 1 | 2 | 1 | 1 | 1 | 1 |
SOCK_DGRAM | 2 | 2 | 2 | 2 | 1 | 2 | 2 | 2 | 2 |
SOCK_RAW | 3 | 3 | 3 | 3 | 4 | 3 | 3 | 3 | 3 |
SOCK_SEQPACKET | 5 | 5 | 5 | 5 | 6 | 5 | 5 | 5 | 5 |
SOCK_DCCP | (6) | - | - | - | - | - | - | - | - |
SOCK_PACKET | 10 | - | - | - | - | - | - | - | - |
IPPROTO_IP | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
IPPROTO_TCP | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 |
IPPROTO_UDP | 17 | 17 | 17 | 17 | 17 | 17 | 17 | 17 | 17 |
IPPROTO_DCCP | 33 | - | - | - | - | - | - | - | - |
IPPROTO_SCTP | 132 | 132 | - | - | 132 | 132 | - | - | - |
IPPROTO_RAW | 255 | 255 | 255 | 255 | 255 | - | - | - | - |
SOL_SOCKET | 1 | 65535 | 65535 | 65535 | 65535 | 65535 | 65535 | 65535 | 65535 |
SOL_IP | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
SOL_TCP | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 |
SOL_UDP | 17 | - | - | - | - | - | 17 | - | - |
SOL_IPV6 | 41 | 41 | 41 | 41 | 41 | 41 | - | 41 | 41 |
SOL_PACKET | 263 | - | - | - | - | - | - | - | - |
SOL_DCCP | 269 | - | - | - | - | - | - | - | - |
These hexadecimal data define socket addresses for local and remote sockets, +and for bind and range options. The basis is the struct sockaddr_* for +the respective address family that should be declared in the C include files. +Please keep in mind that their first two bytes (sa_family and - on BSD +- sa_len) are implicitely prepended by socat.
+ +name | socket address type (without leading address family) | binary specification |
---|---|---|
IPv4 | 2 bytes port, 4 bytes IPv4 addr, 8 bytes 0 | x0016 +x7f000001 x0000000000000000 |
IPv6 | 2 bytes port, 4 bytes flowinfo, 16 bytes IPv6 addr, 4 bytes scope-id | x0016 x00000000 x0102030405060708090a0b0c0d0e0f x00000000 |
UNIX | variable length path name, 0 terminated | x2f746d702f736f636b00 |
PACKET | 2 bytes protocol (0x0003), interface index as int in host byte order, 8 bytes 0 | x0003 x02000000 x0000000000000000 |
For AppleTalk see above example.
+ +name | socket address type (without leading address family) | binary specification |
---|---|---|
IPv6 | 2 bytes port, 4 bytes flowinfo, 16 bytes IPv6 addr, 4 + bytes scope-id, 4 bytes src-id | x0016 x00000000 x0102030405060708090a0b0c0d0e0f x00000000 x00000000 |
Eager to experiment with exotic socket types? Run nmap's protocol scan and +see what is available on your system: +
+ + +nmap -sO localhost + + +
+Copyright: Gerhard Rieger 2008
+License: GNU Free Documentation License (FDL)
+