Version 1.8.0.0
[socat.git] / DEVELOPMENT
blob31e4d4ad5a9293a043b66b346c1c1b0c7af3df4a
2 This file should help you to add new address types and address options to
3 socat. 
5 NOTE:
6 socat will in future releases be split into a library "libxio" containing all
7 the address stuff, useful also for many other purposes, and the socat main()
8 and data shuffler. If you intend to perform major changes to the xio part and
9 to publish them, please contact me before!
12 ADDING A NEW ADDRESS TYPE:
14 * Create new files xio-newaddr.c and xio-newaddr.h
16 * Create a new record of struct addrdesc in xio-newaddr.c, with declaration in xio-newaddr.h.
18 * Make a new entry to addressnames[] in xioopen.c with the addresses main name
19 and maybe with alias names. Keep this array ASCII sorted, without uppercase
20 chars.
22 * config.h.in: #undef WITH_NEWADDR
24 * configure.in: Copy the disable part of, e.g., WITH_SOCKS4 and adapt it to
25 NEWADDR
27 * In socat.c, add to socat_version
29 * Write a function xioopen_newaddr() in xio-newaddr.c, declaration in
30 xio-newaddr.h
31 Do not forget the following option processing calls:
32 All groups: _xio_openlate()
33 Group FD: applyopts_cloexec()
34 Group NAMED: applyopts_file() for phases PREOPEN, OPEN, and FD
36 * Describe a tested example in file EXAMPLES, and maybe in the socat manpage
37 source.
39 * Try to define a test for this address type in test.sh
41 * Update file CHANGES
44 ADDING A NEW ADDRESS OPTION:
46 xioopen.c:
48 * If this option depends on a #define that is probably not available on all
49 platforms, make all new code for this option dependent on the existence of this
50 C header define:
51 #ifdef PREFIX_NEWOPTION
52 ...
53 #endif
55 * Add an OPT_NEWOPTION to enum e_optcode in xioopts.h, preferably keeping
56 alphabetic order
58 * Add a struct optdesc opt_newoption record in xio-newaddr.c and its
59 declaration in xio-newaddr.h. The complete structure definition must be in one
60 line without breaks for automatic docu extraction.
61 Build the record from the following components:
62 . A canonical default name (e.g. "newoption")
63 . A short, preferable name (e.g. "newopt") or NULL
64 . OPT_NEWOPTION (from enum e_optcode, see above)
65 . A group membership that restricts appliance of the new option to matching
66 address types (e.g., one of GROUP_ANY, GROUP_IP_TCP, GROUP_EXEC)
67 . A phase specification that positions this option within address processing.
68 Note that the function code can override this value.
69 . A representation type for option arguments (e.g., TYPE_INT, TYPE_STRING etc.;
70 use TYPE_BOOL if this option just triggers an action)
71 . A function or action definition for applying this option. If it does not use
72 one of the standard functions (open(), ioctl(), setsockopt()...), then use
73 OFUNC_SPEC (specific). 
75 * For the canonical name and all its aliases and abbreviations, add entries to
76 the array optionnames in xioopts.c. KEEP STRICT ALPHABETIC (ASCII) ORDER!
77 The entries must be embedded in an IF_... macro of their group for conditional
78 compiling.
80 * For options using some predefined action (see OFUNC above), this might be
81 enough - test the option and document it in doc/socat.yo!
82 For OFUNC_SPEC, it might suffice to add another "case" to the OFUNC_SPEC branch
83 in applyopts() in xioopts.c. If you need more special handling, you should try
84 to understand the address specific functions and add your code there.
86 * If you use system or low level C library calls or library calls that might
87 hang or induce problems, please invoke them with capitalized name; if no such
88 name is defined, add an appropriate debug function to sycls.c, and a header
89 entry and a wrapper "define" to sycls.h
91 * Update file CHANGES
94 INFO ABOUT ADDRESS PHASES:
96 Each option entry has a field specifying a default phase for its application.
97 Of course, the code that analyses and applies an address may override this
98 default phase. 
100 Depending on the type of address there are several major phase sequences:
103 OPEN addresses:
105 PH_INIT         retrieving info from original state
106 PH_EARLY        before any other processing
107 PH_PREOPEN      before file creation/opening (not UNIX sockets)
108 PH_OPEN         during file creation/opening (not UNIX sockets)
109 PH_PASTOPEN     past file creation/opening (not UNIX sockets)
110 PH_FD           soon after FD creation or identification
111 PH_LATE         FD is ready, before start of data loop
112 PH_LATE2        FD is ready, dropping privileges
115 SOCKET addresses:
117 PH_INIT         retrieving info from original state
118 PH_EARLY        before any other processing
119 PH_PRESOCKET    before socket call
120 PH_SOCKET       for socket call
121 PH_PASTSOCKET   after socket call
122 PH_FD           soon after FD creation or identification
123 PH_PREBIND      before socket bind()
124 PH_BIND         during socket bind()
125 PH_PASTBIND     past socket bind()
126 PH_PRECONNECT   before connect()
127 PH_CONNECT      during connect()
128 PH_PASTCONNECT  after connect()
129 PH_CONNECTED    phase common with listen
130 PH_LATE         FD is ready, before start of data loop
131 PH_LATE2        FD is ready, dropping privileges
134 SOCKET with LISTEN and ACCEPT:
136 PH_INIT         retrieving info from original state
137 PH_EARLY        before any other processing
138 PH_PRESOCKET    before socket call
139 PH_SOCKET       for socket call
140 PH_PREBIND      before socket bind()
141 PH_BIND         during socket bind()
142 PH_PASTBIND     past socket bind()
143 PH_PRELISTEN    before listen()
144 PH_LISTEN       during listen()
145 PH_PASTLISTEN   after listen()
146 PH_PREACCEPT    before accept()
147 PH_ACCEPT       during accept()
148 PH_PASTACCEPT   after accept()
149 # and the following on the new FD:
150 PH_FD           soon after FD creation or identification
151 PH_PASTSOCKET   after socket call
152 PH_CONNECTED    phase common with connect
153 PH_PREFORK      before forking
154 PH_FORK         during fork()
155 PH_PASTFORK     after fork()
156 PH_LATE         FD is ready, before start of data loop
157 PH_LATE2        FD is ready, dropping privileges
160 Passive UNIX socket addresses; this is a mix of socket phases and file system phases:
161 PH_INIT         retrieving info from original state
162 PH_EARLY        before any other processing
163 PH_PRESOCKET    before socket call
164 PH_SOCKET       for socket call
165 PH_PASTSOCKET   after socket call
166 PH_FD           soon after FD creation or identification
167 PH_PREOPEN      before file creation/opening
168 PH_PREBIND      before socket bind()
169 PH_BIND         during socket bind()
170 PH_PASTOPEN     past file creation/opening
171 PH_PASTBIND     past socket bind(), not used up to 1.7.3.4
172 PH_PRECONNECT   before connect()
173 PH_CONNECT      during connect()
174 PH_PASTCONNECT  after connect()
175 PH_CONNECTED    phase common with listen
176 PH_LATE         FD is ready, before start of data loop
177 PH_LATE2        FD is ready, dropping privileges
180 FD addresses:
182 PH_INIT         retrieving info from original state
183 PH_EARLY        before any other processing
184 PH_FD           soon after FD identification
185 PH_LATE         FD is ready, before start of data loop
186 PH_LATE2        FD is ready, dropping privileges
189 EXEC addresses:
191 PH_INIT         retrieving info from original state
192 PH_EARLY        before any other processing
193 PH_PREBIGEN     before socketpair() pipe() openpty()
194 PH_BIGEN        during socketpair() pipe() openpty()
195 PH_PASTBIGEN    past socketpair() pipe() openpty()
196 PH_PASTSOCKET   for socketpair()
197 PH_FD           soon after FD creation or identification
198 PH_PREFORK      before forking
199 PH_FORK         during fork()
200 PH_PASTFORK     after fork()
201 PH_LATE         FD is ready, before start of data loop
202 PH_LATE2        FD is ready, dropping privileges
203 PH_PREEXEC      before exec() or system()
204 PH_EXEC         during exec() or system()
207 There are lots of semantic relations between group, phase, and func fields of
208 an option.
211 There exists something like an overall phase sequence:
212 PH_INIT                                         # su-d.1
213 PH_EARLY                                        # chroot-early
214 PH_PREOPEN,     PH_OPEN,        PH_PASTOPEN     # (chroot before/after?)
215 PH_PRESOCKET,   PH_SOCKET,      PH_PASTSOCKET   # (su after (root for raw)?)
216 PH_PREBIGEN,    PH_BIGEN,       PH_PASTBIGEN    # (chroot before/after (/dev..)?)
217 PH_FD
218 PH_PREBIND,     PH_BIND,        PH_PASTBIND     # (su after(before?))
219 PH_PRELISTEN,   PH_LISTEN,      PH_PASTLISTEN
220 PH_PRECONNECT,  PH_CONNECT,     PH_PASTCONNECT  # (chroot before/after (AF_UNIX)?)
221 PH_PREACCEPT,   PH_ACCEPT,      PH_PASTACCEPT
222 PH_CONNECTED
223 PH_PREFORK,     PH_FORK,        PH_PASTFORK     # (all before/after?)
224 PH_LATE                                         # chroot
225 PH_LATE2                                        # su, su-d.2
226 PH_PREEXEC,     PH_EXEC                         # (all before)
228 ===============================================================================
229 // Up to 1.7.2.4 socat used non async signal safe system and library calls in signal handlers, mostly for logging purposes. This problem was fixed in release 1.7.3.0 with the following concepts:
231 Signal handlers set on entry and unset on return the diag_in_handler global variable. The logging system, when this variable is set, queues the text message together with errno and exit info in a UNIX datagram socket. When invoked with unset diag_in_handler it first checks if there are messages in that queue and prints them first.
233 A async signal safe but minimal version of vsnprintf, named vsnprintf_r, was written so no value arguments need to be queued.
235 Because strerror is not async signal safe a new function snprinterr was written that replaces the (glibc compatible) %m format with strerror output. The original errno is passed in the message queue, snprinterr is called when dequeuing messages outside of signal handler.
237 // List of signal handlers in socat
238 socat.c:socat_signal (generic, just logs and maybe exits)
239 xioshutdown.c:signal_kill_pid (SIGALRM, kill child process)
240 xiosigchld.c:childdied (SIGCHLD: get info, log; possibly close channel)
241 xiosignal.c:socatsignalpass: cascades signal to channel child processes; w/ options sighup,sigint,sigquit
242 xio-socket.c:xiosigaction_hasread: SIGUSR1,SIGCHLD, tells parent that datagram has been consumed