Added doc of OpenSSL options min-proto-version etc.
[socat.git] / xioinitialize.c
blob81925e99e00bf19407f5738d0576e82bb7a81cbb
1 /* source: xioinitialize.c */
2 /* Copyright Gerhard Rieger and contributors (see file CHANGES) */
3 /* Published under the GNU General Public License V.2, see file COPYING */
5 /* this file contains the source for the initialize function */
7 #include "xiosysincludes.h"
9 #include "xioopen.h"
10 #include "xiolockfile.h"
12 #include "xio-openssl.h" /* xio_reset_fips_mode() */
14 static int xioinitialized;
15 xiofile_t *sock[XIO_MAXSOCK];
16 int (*xiohook_newchild)(void); /* xio calls this function from a new child
17 process */
18 int num_child = 0;
20 /* returns 0 on success or != if an error occurred */
21 int xioinitialize(void) {
22 if (xioinitialized) return 0;
24 /* configure and .h's cannot guarantee this */
25 assert(sizeof(uint8_t)==1);
26 assert(sizeof(uint16_t)==2);
27 assert(sizeof(uint32_t)==4);
29 /* assertions regarding O_ flags - important for XIO_READABLE() etc. */
30 assert(O_RDONLY==0);
31 assert(O_WRONLY==1);
32 assert(O_RDWR==2);
34 assert(SHUT_RD==0);
35 assert(SHUT_WR==1);
36 assert(SHUT_RDWR==2);
38 /* some assertions about termios */
39 #if WITH_TERMIOS
40 #if defined(CRDLY) && CRDLY_SHIFT >= 0
41 assert(3 << opt_crdly.arg3 == CRDLY);
42 #endif
43 #if defined(TABDLY) && TABDLY_SHIFT >= 0
44 assert(3 << opt_tabdly.arg3 == TABDLY);
45 #endif
46 #if CSIZE_SHIFT >= 0
47 assert(3 << opt_csize.arg3 == CSIZE);
48 #endif
50 union {
51 struct termios termarg;
52 tcflag_t flags[4];
53 #if HAVE_TERMIOS_ISPEED
54 speed_t speeds[sizeof(struct termios)/sizeof(speed_t)];
55 #endif
56 } tdata;
57 tdata.termarg.c_iflag = 0x12345678;
58 tdata.termarg.c_oflag = 0x23456789;
59 tdata.termarg.c_cflag = 0x3456789a;
60 tdata.termarg.c_lflag = 0x456789ab;
61 assert(tdata.termarg.c_iflag == tdata.flags[0]);
62 assert(tdata.termarg.c_oflag == tdata.flags[1]);
63 assert(tdata.termarg.c_cflag == tdata.flags[2]);
64 assert(tdata.termarg.c_lflag == tdata.flags[3]);
66 #endif
68 /* these dependencies required in applyopts() for OFUNC_FCNTL */
69 assert(F_GETFD == F_SETFD-1);
70 assert(F_GETFL == F_SETFL-1);
73 const char *default_ip;
74 default_ip = getenv("SOCAT_DEFAULT_LISTEN_IP");
75 if (default_ip != NULL) {
76 switch (default_ip[0]) {
77 case '4':
78 case '6':
79 xioopts.default_ip = default_ip[0]; break;
84 const char *preferred_ip;
85 preferred_ip = getenv("SOCAT_PREFERRED_RESOLVE_IP");
86 if (preferred_ip != NULL) {
87 switch (preferred_ip[0]) {
88 case '4':
89 case '6':
90 xioopts.preferred_ip = preferred_ip[0]; break;
91 default:
92 xioopts.preferred_ip = '0'; break;
97 if (Atexit(xioexit) < 0) {
98 Error("atexit(xioexit) failed");
99 return -1;
102 xioinitialized = 1;
103 return 0;
106 /* call this function when option -lp (reset program name) has been applied */
107 int xioinitialize2(void) {
108 pid_t pid = Getpid();
109 xiosetenvulong("PID", pid, 1);
110 xiosetenvulong("PPID", pid, 1);
111 return 0;
115 /* well, this function is not for initialization, but I could not find a better
116 place for it
117 it is called in the child process after fork
118 it drops the locks of the xiofile's so only the parent owns them
120 void xiodroplocks(void) {
121 int i;
123 for (i = 0; i < XIO_MAXSOCK; ++i) {
124 if (sock[i] != NULL && sock[i]->tag != XIO_TAG_INVALID) {
125 xiofiledroplock(sock[i]);
131 /* consider an invokation like this:
132 socat -u exec:'some program that accepts data' tcp-l:...,fork
133 we do not want the program to be killed by the first tcp-l sub process, it's
134 better if it survives all sub processes. Thus, it must not be killed when
135 the sub process delivers EOF. Also, a socket that is reused in sub processes
136 should not be shut down (affects the connection), but closed (affects only
137 sub processes copy of file descriptor) */
138 static int xio_nokill(xiofile_t *sock) {
139 int result = 0;
140 switch (sock->tag) {
141 case XIO_TAG_INVALID:
142 default:
143 return -1;
144 case XIO_TAG_DUAL:
145 if ((result = xio_nokill((xiofile_t *)sock->dual.stream[0])) != 0)
146 return result;
147 result = xio_nokill((xiofile_t *)sock->dual.stream[1]);
148 break;
149 case XIO_TAG_RDONLY:
150 case XIO_TAG_WRONLY:
151 case XIO_TAG_RDWR:
152 /* here is the core of this function */
153 switch (sock->stream.howtoend) {
154 case END_SHUTDOWN_KILL: sock->stream.howtoend = END_CLOSE; break;
155 case END_CLOSE_KILL: sock->stream.howtoend = END_CLOSE; break;
156 case END_SHUTDOWN: sock->stream.howtoend = END_CLOSE; break;
157 default: break;
159 break;
161 return result;
164 /* call this function immediately after fork() in child process */
165 /* it performs some neccessary actions
166 returns 0 on success or != 0 if an error occurred */
167 int xio_forked_inchild(void) {
168 int result = 0;
169 int i;
171 diag_fork();
172 for (i=0; i<NUMUNKNOWN; ++i) {
173 diedunknown[i] = 0;
175 num_child = 0;
176 xiodroplocks();
177 #if WITH_FIPS
178 if (xio_reset_fips_mode() != 0) {
179 result = 1;
181 #endif /* WITH_FIPS */
182 /* some locks belong to parent process, so "drop" them now */
183 if (xiohook_newchild) {
184 if ((*xiohook_newchild)() != 0) {
185 Exit(1);
189 /* change XIO_SHUTDOWN_KILL to XIO_SHUTDOWN */
190 if (sock1 != NULL) {
191 int result2;
192 result2 = xio_nokill(sock1);
193 if (result2 < 0) Exit(1);
194 result |= result2;
197 return result;
200 /* subchild != 0 means that the current process is already a child process of
201 the master process and thus the new sub child process should not set the
202 SOCAT_PID variable */
203 pid_t xio_fork(bool subchild, int level) {
204 pid_t pid;
205 const char *forkwaitstring;
206 int forkwaitsecs = 0;
208 if ((pid = Fork()) < 0) {
209 Msg1(level, "fork(): %s", strerror(errno));
210 return pid;
213 if (pid == 0) { /* child process */
214 pid_t cpid = Getpid();
216 Info1("just born: child process "F_pid, cpid);
217 if (!subchild) {
218 /* set SOCAT_PID to new value */
219 xiosetenvulong("PID", pid, 1);
221 /* gdb recommends to have env controlled sleep after fork */
222 if (forkwaitstring = getenv("SOCAT_FORK_WAIT")) {
223 forkwaitsecs = atoi(forkwaitstring);
224 Sleep(forkwaitsecs);
226 if (xio_forked_inchild() != 0) {
227 Exit(1);
229 return 0;
232 num_child++;
233 /* parent process */
234 Notice1("forked off child process "F_pid, pid);
235 /* gdb recommends to have env controlled sleep after fork */
236 if (forkwaitstring = getenv("SOCAT_FORK_WAIT")) {
237 forkwaitsecs = atoi(forkwaitstring);
238 Sleep(forkwaitsecs);
240 return pid;