From de4f373bd531eaaa540bd6533c0fa4bfa41eaeb4 Mon Sep 17 00:00:00 2001 From: Gerhard Rieger Date: Mon, 20 Oct 2008 09:50:03 +0200 Subject: [PATCH] forgot to git add doc/socat-genericsocket.html --- doc/socat-genericsocket.html | 327 +++++++++++++++++++++++++++++++++++ 1 file changed, 327 insertions(+) create mode 100644 doc/socat-genericsocket.html diff --git a/doc/socat-genericsocket.html b/doc/socat-genericsocket.html new file mode 100644 index 0000000..c30a8db --- /dev/null +++ b/doc/socat-genericsocket.html @@ -0,0 +1,327 @@ + +Generic sockets with Socat + + + + + +

Generic sockets with Socat

+ +

Introduction

+

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. +

+ + + +

Generic socket options

+ +

Example 1: DCCP communication

+ +

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: +

+ + +socat TCP4-LISTEN:4096,reuseaddr,type=6,prototype=33 exec:'tr A-Z a-z',pty,raw,echo=0 + + +

A simple client that sends some upper case characters to the server via DCCP + and prints what the server returns: +

+ + +echo ABCD |socat - TCP4-CONNECT:localhost:4096,type=6,prototype=33 + + +

We choose the TCP4 addresses as base because it best matches the DCCP + requirements: +

    +
  1. DCCP is (here) based on IPv4
  2. +
  3. DCCP is stream oriented and uses connect() and listen(); + accept() calls
  4. +
  5. DCCP protocol uses ports
  6. +
+

+ +

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]! +

+ + +

Generic socket addresses

+ +

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. +

+ + +

Enabling AppleTalk protocol

+ +

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. +

+ +

Example 2: AppleTalk datagram communication

+ +

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: +

+ + + + + + + + + + +
componentoffsetlengthvaluemeaning
sat_family02x0005address family
sat_port21x40port
-31x00padding
sat_addr.s_net42xff00network address
sat_addr.s_node61xf3node address
-71x00padding
sat_zero88x0000000000000000padding
+ +

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 + +

Parameters for well known socket types

+ +

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.

+ +

Socket parameters

+ +

Table: parameter names for "well known" sockets:

+ + + + + + + + + + + +
namedomainsocktypeprotocol levelremark
UDP4PF_INETSOCK_DGRAMIPPROTO_UDP SOL_UDP
UDP6PF_INET6SOCK_DGRAMIPPROTO_UDP SOL_UDP
raw IPv4PF_INETSOCK_RAWIPPROTO_RAW SOL_IP
raw IPv6PF_INET6SOCK_RAWIPPROTO_RAW SOL_IPV6
UNIXPF_LOCALSOCK_DGRAM0 SOL_SOCKET
PACKETPF_PACKETSOCK_RAW768SOL_PACKETtcpdump (include layer 2 header)
PACKETPF_PACKETSOCK_DGRAM768SOL_PACKETno level 2 header
SCTP4PF_INETSOCK_SEQPACKETIPPROTO_SCTP SOL_SCTP
+ +

Table: parameter values:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
nameLinuxFreeBSDNetBSDOpenBSDSolarisAIXCygwinMac OS XHP-UX
PF_LOCAL111111111
PF_INET222222222
PF_APPLETALK51616161616161616
PF_INET6102824242624-3022
PF_PACKET17--------
SOCK_STREAM111121111
SOCK_DGRAM222212222
SOCK_RAW333343333
SOCK_SEQPACKET555565555
SOCK_DCCP(6)--------
SOCK_PACKET10--------
IPPROTO_IP000000000
IPPROTO_TCP666666666
IPPROTO_UDP171717171717171717
IPPROTO_DCCP33--------
IPPROTO_SCTP132132--132132---
IPPROTO_RAW255255255255255----
SOL_SOCKET16553565535655356553565535655356553565535
SOL_IP000000000
SOL_TCP666666666
SOL_UDP17-----17--
SOL_IPV6414141414141-4141
SOL_PACKET263--------
SOL_DCCP269--------
+ + +

Socket address specifications

+ +

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.

+ +

Linux on 32bit Intel:

+ + + + + + + +
namesocket address type (without leading address family)binary specification
IPv42 bytes port, 4 bytes IPv4 addr, 8 bytes 0x0016 +x7f000001 x0000000000000000
IPv62 bytes port, 4 bytes flowinfo, 16 bytes IPv6 addr, 4 bytes scope-idx0016 x00000000 x0102030405060708090a0b0c0d0e0f x00000000
UNIXvariable length path name, 0 terminatedx2f746d702f736f636b00
PACKET2 bytes protocol (0x0003), interface index as int in host byte order, 8 bytes 0x0003 x02000000 x0000000000000000
+ +

For AppleTalk see above example.

+ +

Solaris on 32bit Intel:

+ + + + +
namesocket address type (without leading address family)binary specification
IPv62 bytes port, 4 bytes flowinfo, 16 bytes IPv6 addr, 4 + bytes scope-id, 4 bytes src-idx0016 x00000000 x0102030405060708090a0b0c0d0e0f x00000000 x00000000
+ +

Forever - play on...

+ +

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) +

+ + +