1 /* source: xioopts.c */
2 /* Copyright Gerhard Rieger and contributors (see file CHANGES) */
3 /* Published under the GNU General Public License V.2, see file COPYING */
4 
5 /* this file contains the source for address options handling */
6 
7 #include "xiosysincludes.h"
8 #include "xioopen.h"
9 #include "xio-unix.h"
10 #include "xio-ip.h"
11 
12 #include "xiomodes.h"
13 #include "xiolockfile.h"
14 #include "nestlex.h"
15 
16 bool xioopts_ignoregroups;
17 
18 #define IF_ANY(a,b) {a,b},
19 
20 #if WITH_NAMED
21 #  define IF_NAMED(a,b) {a,b},
22 #else
23 #  define IF_NAMED(a,b)
24 #endif
25 
26 #if WITH_PIPE || WITH_GOPEN
27 #  define IF_OPEN(a,b) {a,b},
28 #else
29 #  define IF_OPEN(a,b)
30 #endif
31 
32 #if WITH_TERMIOS
33 #  define IF_TERMIOS(a,b) {a,b},
34 #else
35 #  define IF_TERMIOS(a,b)
36 #endif
37 
38 #if WITH_EXEC
39 #  define IF_EXEC(a,b) {a,b},
40 #else
41 #  define IF_EXEC(a,b)
42 #endif
43 
44 #if _WITH_SOCKET
45 #  define IF_SOCKET(a,b) {a,b},
46 #else
47 #  define IF_SOCKET(a,b)
48 #endif
49 
50 #if WITH_LISTEN
51 #  define IF_LISTEN(a,b) {a,b},
52 #else
53 #  define IF_LISTEN(a,b)
54 #endif
55 
56 #if (WITH_UDP || WITH_TCP) && WITH_LISTEN
57 #  define IF_RANGE(a,b) {a,b},
58 #else
59 #  define IF_RANGE(a,b)
60 #endif
61 
62 #if WITH_IP4 || WITH_IP6
63 #  define IF_IP(a,b) {a,b},
64 #else
65 #  define IF_IP(a,b)
66 #endif
67 
68 #if WITH_IP6
69 #  define IF_IP6(a,b) {a,b},
70 #else
71 #  define IF_IP6(a,b)
72 #endif
73 
74 #if WITH_TCP|WITH_UDP
75 #  define IF_IPAPP(a,b) {a,b},
76 #else
77 #  define IF_IPAPP(a,b)
78 #endif
79 
80 #if WITH_TCP
81 #  define IF_TCP(a,b) {a,b},
82 #else
83 #  define IF_TCP(a,b)
84 #endif
85 
86 #if WITH_UDP
87 #  define IF_UDP(a,b) {a,b},
88 #else
89 #  define IF_UDP(a,b)
90 #endif
91 
92 #if WITH_SCTP
93 #  define IF_SCTP(a,b) {a,b},
94 #else
95 #  define IF_SCTP(a,b)
96 #endif
97 
98 #if WITH_SOCKS4
99 #  define IF_SOCKS4(a,b) {a,b},
100 #else
101 #  define IF_SOCKS4(a,b)
102 #endif
103 
104 #if WITH_PROXY
105 #  define IF_PROXY(a,b) {a,b},
106 #else
107 #  define IF_PROXY(a,b)
108 #endif
109 
110 #if WITH_READLINE
111 #  define IF_READLINE(a,b) {a,b},
112 #else
113 #  define IF_READLINE(a,b)
114 #endif
115 
116 #if WITH_PTY
117 #  define IF_PTY(a,b) {a,b},
118 #else
119 #  define IF_PTY(a,b)
120 #endif
121 
122 #if WITH_OPENSSL
123 #  define IF_OPENSSL(a,b) {a,b},
124 #else
125 #  define IF_OPENSSL(a,b)
126 #endif
127 
128 #if WITH_TUN
129 #  define IF_TUN(a,b) {a,b},
130 #else
131 #  define IF_TUN(a,b)
132 #endif
133 
134 #if WITH_UNIX
135 #  define IF_UNIX(a,b) {a,b},
136 #else
137 #  define IF_UNIX(a,b)
138 #endif
139 
140 #if WITH_RETRY
141 #  define IF_RETRY(a,b) {a,b},
142 #else
143 #  define IF_RETRY(a,b)
144 #endif
145 
146 
147 static int applyopt_offset(struct single *xfd, struct opt *opt);
148 
149 
150 /* address options - keep this array strictly alphabetically sorted for
151    binary search! */
152 /* NULL terminated */
153 const struct optname optionnames[] = {
154 #if HAVE_RESOLV_H && WITH_RES_AAONLY
155 	IF_IP     ("aaonly",	&opt_res_aaonly)
156 #endif
157 #ifdef TCP_ABORT_THRESHOLD  /* HP_UX */
158 	IF_TCP    ("abort-threshold",	&opt_tcp_abort_threshold)
159 #endif
160 	IF_LISTEN ("accept-timeout",	&opt_accept_timeout)
161 #ifdef SO_ACCEPTCONN /* AIX433 */
162 	IF_SOCKET ("acceptconn",	&opt_so_acceptconn)
163 #endif /* SO_ACCEPTCONN */
164 #ifdef IP_ADD_MEMBERSHIP
165 	IF_IP     ("add-membership",	&opt_ip_add_membership)
166 #endif
167 #ifdef IP_ADD_SOURCE_MEMBERSHIP
168 	IF_IP     ("add-source-membership",	&opt_ip_add_source_membership)
169 #endif
170 	IF_TUN    ("allmulti",	&opt_iff_allmulti)
171 #if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE)
172 	IF_IPAPP  ("allow-table",	&opt_tcpwrap_hosts_allow_table)
173 #endif
174 	IF_ANY    ("append",	&opt_append)
175 #ifdef O_ASYNC
176 	IF_ANY    ("async",	&opt_async)
177 #endif
178 #ifdef SO_ATTACH_FILTER
179 	IF_SOCKET ("attach-filter",	&opt_so_attach_filter)
180 	IF_SOCKET ("attachfilter",	&opt_so_attach_filter)
181 #endif
182 #ifdef SO_AUDIT	/* AIX 4.3.3 */
183 	IF_SOCKET ("audit",	&opt_so_audit)
184 #endif /* SO_AUDIT */
185 #ifdef IPV6_AUTHHDR
186 	IF_IP6    ("authhdr",	&opt_ipv6_authhdr)
187 #endif
188 	IF_TUN    ("automedia",	&opt_iff_automedia)
189 #ifdef CBAUD
190 	IF_TERMIOS("b0",	&opt_b0)
191 #ifdef B1000000
192 	IF_TERMIOS("b1000000",	&opt_b1000000)
193 #endif
194 	IF_TERMIOS("b110",	&opt_b110)
195 #ifdef B115200
196 	IF_TERMIOS("b115200",	&opt_b115200)
197 #endif
198 #ifdef B1152000
199 	IF_TERMIOS("b1152000",	&opt_b1152000)
200 #endif
201 	IF_TERMIOS("b1200",	&opt_b1200)
202 	IF_TERMIOS("b134",	&opt_b134)
203 	IF_TERMIOS("b150",	&opt_b150)
204 #ifdef B1500000
205 	IF_TERMIOS("b1500000",	&opt_b1500000)
206 #endif
207 	IF_TERMIOS("b1800",	&opt_b1800)
208 	IF_TERMIOS("b19200",	&opt_b19200)
209 	IF_TERMIOS("b200",	&opt_b200)
210 #ifdef B2000000
211 	IF_TERMIOS("b2000000",	&opt_b2000000)
212 #endif
213 #ifdef B230400
214 	IF_TERMIOS("b230400",	&opt_b230400)
215 #endif
216 	IF_TERMIOS("b2400",	&opt_b2400)
217 #ifdef B2500000
218 	IF_TERMIOS("b2500000",	&opt_b2500000)
219 #endif
220 	IF_TERMIOS("b300",	&opt_b300)
221 #ifdef B3000000
222 	IF_TERMIOS("b3000000",	&opt_b3000000)
223 #endif
224 #ifdef B3500000
225 	IF_TERMIOS("b3500000",	&opt_b3500000)
226 #endif
227 #ifdef B3600	/* HP-UX */
228 	IF_TERMIOS("b3600",	&opt_b3600)
229 #endif
230 	IF_TERMIOS("b38400",	&opt_b38400)
231 #ifdef B4000000
232 	IF_TERMIOS("b4000000",	&opt_b4000000)
233 #endif
234 #ifdef B460800
235 	IF_TERMIOS("b460800",	&opt_b460800)
236 #endif
237 	IF_TERMIOS("b4800",	&opt_b4800)
238 	IF_TERMIOS("b50",	&opt_b50)
239 #ifdef B500000
240 	IF_TERMIOS("b500000",	&opt_b500000)
241 #endif
242 #ifdef B57600
243 	IF_TERMIOS("b57600",	&opt_b57600)
244 #endif
245 #ifdef B576000
246 	IF_TERMIOS("b576000",	&opt_b576000)
247 #endif
248 	IF_TERMIOS("b600",	&opt_b600)
249 #ifdef B7200	/* HP-UX */
250 	IF_TERMIOS("b7200",	&opt_b7200)
251 #endif
252 	IF_TERMIOS("b75",	&opt_b75)
253 #ifdef B900	/* HP-UX */
254 	IF_TERMIOS("b900",	&opt_b900)
255 #endif
256 #ifdef B921600
257 	IF_TERMIOS("b921600",	&opt_b921600)
258 #endif
259 	IF_TERMIOS("b9600",	&opt_b9600)
260 #endif /* defined(CBAUD) */
261 	IF_LISTEN ("backlog",	&opt_backlog)
262 #ifdef O_BINARY
263 	IF_OPEN   ("bin",		&opt_o_binary)
264 	IF_OPEN   ("binary",		&opt_o_binary)
265 #endif
266 	IF_SOCKET ("bind",	&opt_bind)
267 #ifdef SO_BINDTODEVICE
268 	IF_SOCKET ("bindtodevice",	&opt_so_bindtodevice)
269 #endif
270 	IF_TERMIOS("brkint",	&opt_brkint)
271 	IF_SOCKET ("broadcast",	&opt_so_broadcast)
272 #ifdef BSDLY
273 #  ifdef BS0
274 	IF_TERMIOS("bs0",	&opt_bs0)
275 #  endif
276 #  ifdef BS1
277 	IF_TERMIOS("bs1",	&opt_bs1)
278 #  endif
279 #endif
280 #ifdef SO_BSDCOMPAT
281 	IF_SOCKET ("bsdcompat",	&opt_so_bsdcompat)
282 #endif
283 #ifdef BSDLY
284 	IF_TERMIOS("bsdly",	&opt_bsdly)
285 #endif
286 	IF_ANY    ("bytes",     &opt_readbytes)
287 	IF_OPENSSL("cafile",	&opt_openssl_cafile)
288 	IF_OPENSSL("capath",	&opt_openssl_capath)
289 	IF_OPENSSL("cert",	&opt_openssl_certificate)
290 	IF_OPENSSL("certificate",	&opt_openssl_certificate)
291 	IF_TERMIOS("cfmakeraw",		&opt_termios_cfmakeraw)
292 	IF_ANY    ("chroot",	&opt_chroot)
293 	IF_ANY    ("chroot-early",	&opt_chroot_early)
294 	/*IF_TERMIOS("cibaud",	&opt_cibaud)*/
295 	IF_OPENSSL("cipher",	&opt_openssl_cipherlist)
296 	IF_OPENSSL("cipherlist",	&opt_openssl_cipherlist)
297 	IF_OPENSSL("ciphers",	&opt_openssl_cipherlist)
298 #ifdef SO_CKSUMRECV
299 	IF_SOCKET ("cksumrecv",	&opt_so_cksumrecv)
300 #endif /* SO_CKSUMRECV */
301 	/*IF_NAMED  ("cleanup",	&opt_cleanup)*/
302 	IF_TERMIOS("clocal",	&opt_clocal)
303 	IF_ANY    ("cloexec",	&opt_cloexec)
304 	IF_ANY    ("close",	&opt_end_close)
305 	IF_OPENSSL("cn",		&opt_openssl_commonname)
306 	IF_OPENSSL("commonname",	&opt_openssl_commonname)
307 #if WITH_FS && defined(FS_COMPR_FL)
308 	IF_ANY    ("compr",	&opt_fs_compr)
309 #endif
310 #if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_COMP)
311 	IF_OPENSSL("compress",	&opt_openssl_compress)
312 #endif
313 #ifdef TCP_CONN_ABORT_THRESHOLD  /* HP_UX */
314 	IF_TCP    ("conn-abort-threshold",	&opt_tcp_conn_abort_threshold)
315 #endif
316 	IF_SOCKET ("connect-timeout",	&opt_connect_timeout)
317 	IF_LISTEN ("cool-write",	&opt_cool_write)
318 	IF_LISTEN ("coolwrite",	&opt_cool_write)
319 #ifdef TCP_CORK
320 	IF_TCP    ("cork",	&opt_tcp_cork)
321 #endif
322 	IF_ANY    ("cr",        &opt_cr)
323 #ifdef CRDLY
324 #  ifdef CR0
325 	IF_TERMIOS("cr0",	&opt_cr0)
326 #  endif
327 #  ifdef CR1
328 	IF_TERMIOS("cr1",	&opt_cr1)
329 #  endif
330 #  ifdef CR2
331 	IF_TERMIOS("cr2",	&opt_cr2)
332 #  endif
333 #  ifdef CR3
334 	IF_TERMIOS("cr3",	&opt_cr3)
335 #  endif
336 #  if CRDLY_SHIFT >= 0
337 	IF_TERMIOS("crdly",	&opt_crdly)
338 #  endif
339 #endif /* defined(CRDLY) */
340 	IF_TERMIOS("cread",	&opt_cread)
341 	IF_OPEN   ("creat",	&opt_o_create)
342 	IF_OPEN   ("create",	&opt_o_create)
343 	IF_ANY    ("crlf",      &opt_crnl)
344 	IF_ANY    ("crnl",      &opt_crnl)
345 	IF_TERMIOS("crterase",	&opt_echoe)
346 	IF_TERMIOS("crtkill",	&opt_echoke)
347 #ifdef CRTSCTS
348 	IF_TERMIOS("crtscts",	&opt_crtscts)
349 #endif
350 	IF_TERMIOS("cs5",	&opt_cs5)
351 	IF_TERMIOS("cs6",	&opt_cs6)
352 	IF_TERMIOS("cs7",	&opt_cs7)
353 	IF_TERMIOS("cs8",	&opt_cs8)
354 #if CSIZE_SHIFT >= 0
355 	IF_TERMIOS("csize",	&opt_csize)
356 #endif
357 	IF_TERMIOS("cstopb",	&opt_cstopb)
358 	IF_TERMIOS("ctlecho",	&opt_echoctl)
359 	IF_TERMIOS("ctty",	&opt_tiocsctty)
360 	IF_EXEC   ("dash",	&opt_dash)
361 	IF_SOCKET ("debug",	&opt_so_debug)
362 	/*IF_IP     ("debug",	&opt_res_debug)*/
363 #ifdef O_DEFER
364 	IF_OPEN   ("defer",	&opt_o_defer)
365 #endif
366 #ifdef TCP_DEFER_ACCEPT	/* Linux 2.4.0 */
367 	IF_TCP    ("defer-accept",	&opt_tcp_defer_accept)
368 #endif
369 #if HAVE_RESOLV_H
370 	IF_IP     ("defnames",	&opt_res_defnames)
371 #endif /* HAVE_RESOLV_H */
372 #ifdef O_DELAY
373 	IF_OPEN   ("delay",	&opt_o_delay)
374 #endif
375 	IF_NAMED  ("delete",	&opt_unlink)
376 #if WITH_LIBWRAP && defined(HAVE_HOSTS_DENY_TABLE)
377 	IF_IPAPP  ("deny-table",	&opt_tcpwrap_hosts_deny_table)
378 #endif
379 #ifdef SO_DETACH_FILTER
380 	IF_SOCKET ("detach-filter", &opt_so_detach_filter)
381 	IF_SOCKET ("detachfilter",  &opt_so_detach_filter)
382 #endif
383 #ifdef SO_DGRAM_ERRIND
384 	IF_SOCKET ("dgram-errind",	&opt_so_dgram_errind)
385 	IF_SOCKET ("dgramerrind",	&opt_so_dgram_errind)
386 #endif
387 	IF_OPENSSL("dh",	&opt_openssl_dhparam)
388 	IF_OPENSSL("dhparam",	&opt_openssl_dhparam)
389 	IF_OPENSSL("dhparams",	&opt_openssl_dhparam)
390 #ifdef O_DIRECT
391 	IF_OPEN   ("direct",	&opt_o_direct)
392 #endif
393 #ifdef O_DIRECTORY
394 	IF_OPEN   ("directory",	&opt_o_directory)
395 #endif
396 #if WITH_FS && defined(FS_DIRSYNC_FL)
397 	IF_ANY    ("dirsync",	&opt_fs_dirsync)
398 #endif
399 #ifdef VDISCARD
400 	IF_TERMIOS("discard",	&opt_vdiscard)
401 #endif
402 #if HAVE_RESOLV_H
403 	IF_IP     ("dnsrch",	&opt_res_dnsrch)
404 #endif /* HAVE_RESOLV_H */
405 #ifdef SO_DONTLINGER
406 	IF_SOCKET ("dontlinger",	&opt_so_dontlinger)
407 #endif
408 	IF_SOCKET ("dontroute",	&opt_so_dontroute)
409 #ifdef IPV6_DSTOPTS
410 	IF_IP6    ("dstopts",	&opt_ipv6_dstopts)
411 #endif
412 #ifdef VDSUSP	/* HP-UX */
413 	IF_TERMIOS("dsusp",	&opt_vdsusp)
414 #endif
415 #ifdef O_DSYNC
416 	IF_OPEN   ("dsync",	&opt_o_dsync)
417 #endif
418 	IF_TERMIOS("echo",	&opt_echo)
419 	IF_TERMIOS("echoctl",	&opt_echoctl)
420 	IF_TERMIOS("echoe",	&opt_echoe)
421 	IF_TERMIOS("echok",	&opt_echok)
422 	IF_TERMIOS("echoke",	&opt_echoke)
423 	IF_TERMIOS("echonl",	&opt_echonl)
424 #ifdef ECHOPRT
425 	IF_TERMIOS("echoprt",	&opt_echoprt)
426 #endif
427 	IF_OPENSSL("egd",	&opt_openssl_egd)
428 	IF_ANY    ("end-close",	&opt_end_close)
429 	IF_TERMIOS("eof",	&opt_veof)
430 	IF_TERMIOS("eol",	&opt_veol)
431 	IF_TERMIOS("eol2",	&opt_veol2)
432 	IF_TERMIOS("erase",	&opt_verase)
433 	IF_SOCKET ("error",	&opt_so_error)
434 	IF_ANY    ("escape",	&opt_escape)
435 	IF_OPEN   ("excl",	&opt_o_excl)
436 #if WITH_FS && defined(FS_APPEND_FL)
437 	IF_ANY    ("ext2-append",	&opt_fs_append)
438 #endif
439 #if WITH_FS && defined(FS_COMPR_FL)
440 	IF_ANY    ("ext2-compr",	&opt_fs_compr)
441 #endif
442 #if WITH_FS && defined(FS_DIRSYNC_FL)
443 	IF_ANY    ("ext2-dirsync",	&opt_fs_dirsync)
444 #endif
445 #if WITH_FS && defined(FS_IMMUTABLE_FL)
446 	IF_ANY    ("ext2-immutable",	&opt_fs_immutable)
447 #endif
448 #if WITH_FS && defined(FS_JOURNAL_DATA_FL)
449 	IF_ANY    ("ext2-journal-data",	&opt_fs_journal_data)
450 #endif
451 #if WITH_FS && defined(FS_NOATIME_FL)
452 	IF_ANY    ("ext2-noatime",	&opt_fs_noatime)
453 #endif
454 #if WITH_FS && defined(FS_NODUMP_FL)
455 	IF_ANY    ("ext2-nodump",	&opt_fs_nodump)
456 #endif
457 #if WITH_FS && defined(FS_NOTAIL_FL)
458 	IF_ANY    ("ext2-notail",	&opt_fs_notail)
459 #endif
460 #if WITH_FS && defined(FS_SECRM_FL)
461 	IF_ANY    ("ext2-secrm",	&opt_fs_secrm)
462 #endif
463 #if WITH_FS && defined(FS_SYNC_FL)
464 	IF_ANY    ("ext2-sync",		&opt_fs_sync)
465 #endif
466 #if WITH_FS && defined(FS_TOPDIR_FL)
467 	IF_ANY    ("ext2-topdir",	&opt_fs_topdir)
468 #endif
469 #if WITH_FS && defined(FS_UNRM_FL)
470 	IF_ANY    ("ext2-unrm",		&opt_fs_unrm)
471 #endif
472 #if WITH_FS && defined(FS_APPEND_FL)
473 	IF_ANY    ("ext3-append",	&opt_fs_append)
474 #endif
475 #if WITH_FS && defined(FS_COMPR_FL)
476 	IF_ANY    ("ext3-compr",	&opt_fs_compr)
477 #endif
478 #if WITH_FS && defined(FS_DIRSYNC_FL)
479 	IF_ANY    ("ext3-dirsync",	&opt_fs_dirsync)
480 #endif
481 #if WITH_FS && defined(FS_IMMUTABLE_FL)
482 	IF_ANY    ("ext3-immutable",	&opt_fs_immutable)
483 #endif
484 #if WITH_FS && defined(FS_JOURNAL_DATA_FL)
485 	IF_ANY    ("ext3-journal-data",	&opt_fs_journal_data)
486 #endif
487 #if WITH_FS && defined(FS_NOATIME_FL)
488 	IF_ANY    ("ext3-noatime",	&opt_fs_noatime)
489 #endif
490 #if WITH_FS && defined(FS_NODUMP_FL)
491 	IF_ANY    ("ext3-nodump",	&opt_fs_nodump)
492 #endif
493 #if WITH_FS && defined(FS_NOTAIL_FL)
494 	IF_ANY    ("ext3-notail",	&opt_fs_notail)
495 #endif
496 #if WITH_FS && defined(FS_SECRM_FL)
497 	IF_ANY    ("ext3-secrm",	&opt_fs_secrm)
498 #endif
499 #if WITH_FS && defined(FS_SYNC_FL)
500 	IF_ANY    ("ext3-sync",		&opt_fs_sync)
501 #endif
502 #if WITH_FS && defined(FS_TOPDIR_FL)
503 	IF_ANY    ("ext3-topdir",	&opt_fs_topdir)
504 #endif
505 #if WITH_FS && defined(FS_UNRM_FL)
506 	IF_ANY    ("ext3-unrm",		&opt_fs_unrm)
507 #endif
508 	IF_ANY 	  ("f-setlk",	&opt_f_setlk_wr)
509 	IF_ANY 	  ("f-setlk-rd",	&opt_f_setlk_rd)
510 	IF_ANY 	  ("f-setlk-wr",	&opt_f_setlk_wr)
511 	IF_ANY 	  ("f-setlkw",	&opt_f_setlkw_wr)
512 	IF_ANY 	  ("f-setlkw-rd",	&opt_f_setlkw_rd)
513 	IF_ANY 	  ("f-setlkw-wr",	&opt_f_setlkw_wr)
514 	IF_EXEC   ("fdin",	&opt_fdin)
515 	IF_EXEC   ("fdout",	&opt_fdout)
516 #ifdef FFDLY
517 #  ifdef FF0
518 	IF_TERMIOS("ff0",	&opt_ff0)
519 #  endif
520 #  ifdef FF1
521 	IF_TERMIOS("ff1",	&opt_ff1)
522 #  endif
523 	IF_TERMIOS("ffdly",	&opt_ffdly)
524 #endif
525 #ifdef FIOSETOWN
526 	IF_SOCKET ("fiosetown",	&opt_fiosetown)
527 #endif
528 #if WITH_FIPS
529 	IF_OPENSSL("fips",	&opt_openssl_fips)
530 #endif
531 #if HAVE_FLOCK
532 	IF_ANY    ("flock",	&opt_flock_ex)
533 	IF_ANY    ("flock-ex",	&opt_flock_ex)
534 	IF_ANY    ("flock-ex-nb",	&opt_flock_ex_nb)
535 	IF_ANY    ("flock-nb",	&opt_flock_ex_nb)
536 	IF_ANY    ("flock-sh",	&opt_flock_sh)
537 	IF_ANY    ("flock-sh-nb",	&opt_flock_sh_nb)
538 #endif
539 #ifdef IPV4_FLOWINFO
540 	IF_IP6    ("flowinfo",	&opt_ipv6_flowinfo)
541 #endif
542 	IF_TERMIOS("flusho",	&opt_flusho)
543 	IF_RETRY  ("forever",	&opt_forever)
544 	IF_LISTEN ("fork",	&opt_fork)
545 #ifdef IP_FREEBIND
546 	IF_IP     ("freebind",	&opt_ip_freebind)
547 #endif
548 #if WITH_FS && defined(FS_APPEND_FL)
549 	IF_ANY    ("fs-append",	&opt_fs_append)
550 #endif
551 #if WITH_FS && defined(FS_COMPR_FL)
552 	IF_ANY    ("fs-compr",	&opt_fs_compr)
553 #endif
554 #if WITH_FS && defined(FS_DIRSYNC_FL)
555 	IF_ANY    ("fs-dirsync",	&opt_fs_dirsync)
556 #endif
557 #if WITH_FS && defined(FS_IMMUTABLE_FL)
558 	IF_ANY    ("fs-immutable",	&opt_fs_immutable)
559 #endif
560 #if WITH_FS && defined(FS_JOURNAL_DATA_FL)
561 	IF_ANY    ("fs-journal-data",	&opt_fs_journal_data)
562 #endif
563 #if WITH_FS && defined(FS_NOATIME_FL)
564 	IF_ANY    ("fs-noatime",	&opt_fs_noatime)
565 #endif
566 #if WITH_FS && defined(FS_NODUMP_FL)
567 	IF_ANY    ("fs-nodump",	&opt_fs_nodump)
568 #endif
569 #if WITH_FS && defined(FS_NOTAIL_FL)
570 	IF_ANY    ("fs-notail",	&opt_fs_notail)
571 #endif
572 #if WITH_FS && defined(FS_SECRM_FL)
573 	IF_ANY    ("fs-secrm",	&opt_fs_secrm)
574 #endif
575 #if WITH_FS && defined(FS_SYNC_FL)
576 	IF_ANY    ("fs-sync",		&opt_fs_sync)
577 #endif
578 #if WITH_FS && defined(FS_TOPDIR_FL)
579 	IF_ANY    ("fs-topdir",	&opt_fs_topdir)
580 #endif
581 #if WITH_FS && defined(FS_UNRM_FL)
582 	IF_ANY    ("fs-unrm",		&opt_fs_unrm)
583 #endif
584 #if HAVE_FTRUNCATE64
585 	IF_ANY    ("ftruncate",	&opt_ftruncate64)
586 #else
587 	IF_ANY    ("ftruncate",	&opt_ftruncate32)
588 #endif
589 	IF_ANY    ("ftruncate32",	&opt_ftruncate32)
590 #if HAVE_FTRUNCATE64
591 	IF_ANY    ("ftruncate64",	&opt_ftruncate64)
592 #endif
593 	IF_ANY    ("gid",	&opt_group)
594 	IF_NAMED  ("gid-e",	&opt_group_early)
595 	IF_ANY    ("gid-l",	&opt_group_late)
596 	IF_ANY    ("group",	&opt_group)
597 	IF_NAMED  ("group-early",	&opt_group_early)
598 	IF_ANY    ("group-late",	&opt_group_late)
599 #ifdef IP_HDRINCL
600 	IF_IP     ("hdrincl",	&opt_ip_hdrincl)
601 #endif
602 	IF_READLINE("history",	&opt_history_file)
603 	IF_READLINE("history-file",	&opt_history_file)
604 #ifdef IPV6_HOPLIMIT
605 	IF_IP6    ("hoplimit",	&opt_ipv6_hoplimit)
606 #endif
607 #ifdef	IPV6_HOPOPTS
608 	IF_IP6    ("hopopts",	&opt_ipv6_hopopts)
609 #endif
610 #if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE)
611 	IF_IPAPP  ("hosts-allow",	&opt_tcpwrap_hosts_allow_table)
612 #endif
613 #if WITH_LIBWRAP && defined(HAVE_HOSTS_DENY_TABLE)
614 	IF_IPAPP  ("hosts-deny",	&opt_tcpwrap_hosts_deny_table)
615 #endif
616 	IF_TERMIOS("hup",	&opt_hupcl)
617 	IF_TERMIOS("hupcl",	&opt_hupcl)
618 #ifdef I_POP
619 	IF_ANY    ("i-pop-all",	&opt_streams_i_pop_all)
620 #endif
621 #ifdef I_PUSH
622 	IF_ANY    ("i-push",	&opt_streams_i_push)
623 #endif
624 	IF_TERMIOS("icanon",	&opt_icanon)
625 	IF_TERMIOS("icrnl",	&opt_icrnl)
626 	IF_TERMIOS("iexten",	&opt_iexten)
627 #ifdef SO_BINDTODEVICE
628 	IF_SOCKET ("if",	&opt_so_bindtodevice)
629 #endif
630 	IF_TUN    ("iff-allmulti",	&opt_iff_allmulti)
631 	IF_TUN    ("iff-automedia",	&opt_iff_automedia)
632 	IF_TUN    ("iff-broadcast",	&opt_iff_broadcast)
633 	IF_TUN    ("iff-debug",	&opt_iff_debug)
634 	/*IF_TUN    ("iff-dynamic",	&opt_iff_dynamic)*/
635 	IF_TUN    ("iff-loopback",	&opt_iff_loopback)
636 	IF_TUN    ("iff-master",	&opt_iff_master)
637 	IF_TUN    ("iff-multicast",	&opt_iff_multicast)
638 	IF_TUN    ("iff-no-pi",	&opt_iff_no_pi)
639 	IF_TUN    ("iff-noarp",	&opt_iff_noarp)
640 	IF_TUN    ("iff-notrailers",	&opt_iff_notrailers)
641 	IF_TUN    ("iff-pointopoint",	&opt_iff_pointopoint)
642 	IF_TUN    ("iff-portsel",	&opt_iff_portsel)
643 	IF_TUN    ("iff-promisc",	&opt_iff_promisc)
644 	IF_TUN    ("iff-running",	&opt_iff_running)
645 	IF_TUN    ("iff-slave",	&opt_iff_slave)
646 	IF_TUN    ("iff-up",	&opt_iff_up)
647 	IF_TERMIOS("ignbrk",	&opt_ignbrk)
648 	IF_TERMIOS("igncr",	&opt_igncr)
649   /* you might need to terminate socat manually if you use this option: */
650 	IF_PROXY  ("ignorecr",	&opt_ignorecr)
651 	IF_ANY    ("ignoreeof",	&opt_ignoreeof)
652 	IF_ANY    ("ignoreof",	&opt_ignoreeof)
653 	IF_TERMIOS("ignpar",	&opt_ignpar)
654 #if HAVE_RESOLV_H
655 	IF_IP     ("igntc",	&opt_res_igntc)
656 #endif /* HAVE_RESOLV_H */
657 	IF_TERMIOS("imaxbel",	&opt_imaxbel)
658 #if WITH_FS && defined(FS_IMMUTABLE_FL)
659 	IF_ANY    ("immutable",	&opt_fs_immutable)
660 #endif
661 #ifdef TCP_INFO	/* Linux 2.4.0 */
662 	IF_TCP    ("info",	&opt_tcp_info)
663 #endif
664 	IF_TERMIOS("inlcr",	&opt_inlcr)
665 	IF_TERMIOS("inpck",	&opt_inpck)
666 #ifdef SO_BINDTODEVICE
667 	IF_SOCKET ("interface",	&opt_so_bindtodevice)
668 #endif
669 	IF_RETRY  ("interval",	&opt_intervall)
670 	IF_RETRY  ("intervall",	&opt_intervall)
671 	IF_TERMIOS("intr",	&opt_vintr)
672 	IF_ANY    ("ioctl",	&opt_ioctl_void)
673 	IF_ANY    ("ioctl-bin",	&opt_ioctl_bin)
674 	IF_ANY    ("ioctl-int",	&opt_ioctl_int)
675 	IF_ANY    ("ioctl-intp",	&opt_ioctl_intp)
676 	IF_ANY    ("ioctl-string",	&opt_ioctl_string)
677 	IF_ANY    ("ioctl-void",	&opt_ioctl_void)
678 #ifdef IP_ADD_MEMBERSHIP
679 	IF_IP     ("ip-add-membership",	&opt_ip_add_membership)
680 #endif
681 #ifdef IP_ADD_SOURCE_MEMBERSHIP
682 	IF_IP     ("ip-add-source-membership",	&opt_ip_add_source_membership)
683 #endif
684 #ifdef IP_FREEBIND
685 	IF_IP     ("ip-freebind",	&opt_ip_freebind)
686 #endif
687 #ifdef IP_HDRINCL
688 	IF_IP     ("ip-hdrincl",	&opt_ip_hdrincl)
689 #endif
690 #ifdef IP_ADD_MEMBERSHIP
691 	IF_IP     ("ip-membership",	&opt_ip_add_membership)
692 #endif
693 #ifdef IP_MTU
694 	IF_IP     ("ip-mtu",	&opt_ip_mtu)
695 #endif
696 #ifdef IP_MTU_DISCOVER
697 	IF_IP     ("ip-mtu-discover",	&opt_ip_mtu_discover)
698 #endif
699 	IF_IP     ("ip-multicast-if",	&opt_ip_multicast_if)
700 	IF_IP     ("ip-multicast-loop",	&opt_ip_multicast_loop)
701 	IF_IP     ("ip-multicast-ttl",	&opt_ip_multicast_ttl)
702 #ifdef IP_OPTIONS
703 	IF_IP     ("ip-options",	&opt_ip_options)
704 #endif
705 #ifdef IP_PKTINFO
706 	IF_IP     ("ip-pktinfo",	&opt_ip_pktinfo)
707 #endif
708 #ifdef IP_PKTOPTIONS
709 	IF_IP     ("ip-pktoptions",	&opt_ip_pktoptions)
710 #endif
711 #ifdef IP_RECVDSTADDR
712 	IF_IP     ("ip-recvdstaddr",	&opt_ip_recvdstaddr)
713 #endif
714 #ifdef IP_RECVERR
715 	IF_IP     ("ip-recverr",	&opt_ip_recverr)
716 #endif
717 #ifdef IP_RECVIF
718 	IF_IP     ("ip-recvif",		&opt_ip_recvif)
719 #endif
720 #ifdef IP_RECVOPTS
721 	IF_IP     ("ip-recvopts",	&opt_ip_recvopts)
722 #endif
723 #ifdef IP_RECVTOS
724 	IF_IP     ("ip-recvtos",	&opt_ip_recvtos)
725 #endif
726 #ifdef IP_RECVTTL
727 	IF_IP     ("ip-recvttl",	&opt_ip_recvttl)
728 #endif
729 #ifdef IP_RETOPTS
730 	IF_IP     ("ip-retopts",	&opt_ip_retopts)
731 #endif
732 #ifdef IP_ROUTER_ALERT
733 	IF_IP     ("ip-router-alert",	&opt_ip_router_alert)
734 #endif
735 	IF_IP     ("ip-tos",	&opt_ip_tos)
736 #ifdef IP_TRANSPARENT
737 	IF_IP     ("ip-transparent",    &opt_ip_transparent)
738 #endif
739 	IF_IP     ("ip-ttl",	&opt_ip_ttl)
740 #ifdef IP_FREEBIND
741 	IF_IP     ("ipfreebind",	&opt_ip_freebind)
742 #endif
743 #ifdef IP_HDRINCL
744 	IF_IP     ("iphdrincl",	&opt_ip_hdrincl)
745 #endif
746 #ifdef IP_MTU
747 	IF_IP     ("ipmtu",	&opt_ip_mtu)
748 #endif
749 #ifdef IP_MTU_DISCOVER
750 	IF_IP     ("ipmtudiscover",	&opt_ip_mtu_discover)
751 #endif
752 	IF_IP     ("ipmulticastloop",	&opt_ip_multicast_loop)
753 	IF_IP     ("ipmulticastttl",	&opt_ip_multicast_ttl)
754 #ifdef IP_OPTIONS
755 	IF_IP     ("ipoptions",	&opt_ip_options)
756 #endif
757 #ifdef IP_PKTINFO
758 	IF_IP     ("ippktinfo",	&opt_ip_pktinfo)
759 #endif
760 #ifdef IP_PKTOPTIONS
761 	IF_IP     ("ippktoptions",	&opt_ip_pktoptions)
762 #endif
763 #ifdef IP_RECVDSTADDR
764 	IF_IP     ("iprecvdstaddr",	&opt_ip_recvdstaddr)
765 #endif
766 #ifdef IP_RECVERR
767 	IF_IP     ("iprecverr",	&opt_ip_recverr)
768 #endif
769 #ifdef IP_RECVOPTS
770 	IF_IP     ("iprecvopts",	&opt_ip_recvopts)
771 #endif
772 #ifdef IP_RECVTOS
773 	IF_IP     ("iprecvtos",	&opt_ip_recvtos)
774 #endif
775 #ifdef IP_RECVTTL
776 	IF_IP     ("iprecvttl",	&opt_ip_recvttl)
777 #endif
778 #ifdef IP_RETOPTS
779 	IF_IP     ("ipretopts",	&opt_ip_retopts)
780 #endif
781 #ifdef IP_ROUTER_ALERT
782 	IF_IP     ("iprouteralert",	&opt_ip_router_alert)
783 #endif
784 	IF_IP     ("iptos",	&opt_ip_tos)
785 	IF_IP     ("ipttl",	&opt_ip_ttl)
786 #ifdef IPV6_JOIN_GROUP
787 	IF_IP6    ("ipv6-add-membership",	&opt_ipv6_join_group)
788 #endif
789 #ifdef IPV6_AUTHHDR
790 	IF_IP6    ("ipv6-authhdr",	&opt_ipv6_authhdr)
791 #endif
792 #ifdef IPV6_DSTOPTS
793 	IF_IP6    ("ipv6-dstopts",	&opt_ipv6_dstopts)
794 #endif
795 #ifdef IPV4_FLOWINFO
796 	IF_IP6    ("ipv6-flowinfo",	&opt_ipv6_flowinfo)
797 #endif
798 #ifdef IPV6_HOPLIMIT
799 	IF_IP6    ("ipv6-hoplimit",	&opt_ipv6_hoplimit)
800 #endif
801 #ifdef IPV6_HOPOPTS
802 	IF_IP6    ("ipv6-hopopts",	&opt_ipv6_hopopts)
803 #endif
804 #ifdef IPV6_JOIN_GROUP
805 	IF_IP6    ("ipv6-join-group",	&opt_ipv6_join_group)
806 #endif
807 #ifdef IPV6_PKTINFO
808 	IF_IP6    ("ipv6-pktinfo",	&opt_ipv6_pktinfo)
809 #endif
810 #ifdef IPV6_RECVDSTOPTS
811 	IF_IP6    ("ipv6-recvdstopts",	&opt_ipv6_recvdstopts)
812 #endif
813 #ifdef IPV6_RECVERR
814 	IF_IP6    ("ipv6-recverr",	&opt_ipv6_recverr)
815 #endif
816 #ifdef IPV6_RECVHOPLIMIT
817 	IF_IP6    ("ipv6-recvhoplimit",	&opt_ipv6_recvhoplimit)
818 #endif
819 #ifdef IPV6_RECVHOPOPTS
820 	IF_IP6    ("ipv6-recvhopopts",	&opt_ipv6_recvhopopts)
821 #endif
822 #ifdef IPV6_PATHMTU
823 	IF_IP6    ("ipv6-recvpathmtu",	&opt_ipv6_recvpathmtu)
824 #endif
825 #ifdef IPV6_RECVPKTINFO
826 	IF_IP6    ("ipv6-recvpktinfo",	&opt_ipv6_recvpktinfo)
827 #endif
828 #ifdef IPV6_RECVRTHDR
829 	IF_IP6    ("ipv6-recvrthdr",	&opt_ipv6_recvrthdr)
830 #endif
831 #ifdef IPV6_RECVTCLASS
832 	IF_IP6    ("ipv6-recvtclass",	&opt_ipv6_recvtclass)
833 #endif
834 #ifdef IPV6_RTHDR
835 	IF_IP6    ("ipv6-rthdr",	&opt_ipv6_rthdr)
836 #endif
837 #ifdef IPV6_TCLASS
838 	IF_IP6    ("ipv6-tclass",	&opt_ipv6_tclass)
839 #endif
840 	IF_IP6    ("ipv6-unicast-hops",	&opt_ipv6_unicast_hops)
841 #ifdef IPV6_V6ONLY
842 	IF_IP6    ("ipv6-v6only",	&opt_ipv6_v6only)
843 	IF_IP6    ("ipv6only",	&opt_ipv6_v6only)
844 #endif
845 	IF_TERMIOS("isig",	&opt_isig)
846 #if HAVE_TERMIOS_ISPEED
847 	IF_TERMIOS("ispeed",	&opt_ispeed)
848 #endif
849 	IF_TERMIOS("istrip",	&opt_istrip)
850 #ifdef IUCLC
851 	IF_TERMIOS("iuclc",	&opt_iuclc)
852 #endif
853 	IF_TERMIOS("ixany",	&opt_ixany)
854 	IF_TERMIOS("ixoff",	&opt_ixoff)
855 	IF_TERMIOS("ixon",	&opt_ixon)
856 #ifdef IPV6_JOIN_GROUP
857 	IF_IP6    ("join-group",	&opt_ipv6_join_group)
858 #endif
859 #if WITH_FS && defined(FS_JOURNAL_DATA_FL)
860 	IF_ANY    ("journal",		&opt_fs_journal_data)
861 	IF_ANY    ("journal-data",	&opt_fs_journal_data)
862 #endif
863 	IF_SOCKET ("keepalive",	&opt_so_keepalive)
864 #ifdef TCP_KEEPCNT	/* Linux 2.4.0 */
865 	IF_TCP    ("keepcnt",	&opt_tcp_keepcnt)
866 #endif
867 #ifdef TCP_KEEPIDLE	/* Linux 2.4.0 */
868 	IF_TCP    ("keepidle",	&opt_tcp_keepidle)
869 #endif
870 #ifdef TCP_KEEPINIT	/* OSF1 */
871 	IF_TCP    ("keepinit",	&opt_tcp_keepinit)
872 #endif
873 #ifdef TCP_KEEPINTVL	/* Linux 2.4.0 */
874 	IF_TCP    ("keepintvl",	&opt_tcp_keepintvl)
875 #endif
876 #ifdef SO_KERNACCEPT	/* AIX 4.3.3 */
877 	IF_SOCKET ("kernaccept",	&opt_so_kernaccept)
878 #endif /* SO_KERNACCEPT */
879 	IF_OPENSSL("key",	&opt_openssl_key)
880 	IF_TERMIOS("kill",	&opt_vkill)
881 #ifdef O_LARGEFILE
882 	IF_OPEN   ("largefile",	&opt_o_largefile)
883 #endif
884 #if WITH_LIBWRAP
885 	IF_IPAPP  ("libwrap",		&opt_tcpwrappers)
886 #endif
887 	IF_SOCKET ("linger",	&opt_so_linger)
888 #ifdef TCP_LINGER2	/* Linux 2.4.0 */
889 	IF_TCP    ("linger2",	&opt_tcp_linger2)
890 #endif
891 	IF_PTY    ("link",	&opt_symbolic_link)
892 	IF_LISTEN ("listen-timeout",	&opt_accept_timeout)
893 	IF_TERMIOS("lnext",	&opt_vlnext)
894 #if defined(F_SETLKW)
895 	IF_ANY    ("lock",	&opt_f_setlkw_wr)	/* POSIX, first choice */
896 #elif defined(HAVE_FLOCK)
897 	IF_ANY    ("lock",	&opt_flock_ex)	/* BSD, fallback */
898 #endif
899 	IF_ANY    ("lockfile",	&opt_lockfile)
900 #if defined(F_SETLKW)
901 	IF_ANY    ("lockw",	&opt_f_setlkw_wr)	/* POSIX, first choice */
902 #elif defined(HAVE_FLOCK)
903 	IF_ANY    ("lockw",	&opt_flock_ex_nb)	/* BSD, fallback */
904 #endif
905 	IF_EXEC   ("login",	&opt_dash)
906 	IF_TUN    ("loopback",	&opt_iff_loopback)
907 	IF_IPAPP  ("lowport",	&opt_lowport)
908 #if HAVE_LSEEK64
909 	IF_ANY    ("lseek",	&opt_lseek64_set)
910 #else
911 	IF_ANY    ("lseek",	&opt_lseek32_set)
912 #endif
913 	IF_ANY    ("lseek32",		&opt_lseek32_set)
914 	IF_ANY    ("lseek32-cur",	&opt_lseek32_cur)
915 	IF_ANY    ("lseek32-end",	&opt_lseek32_end)
916 	IF_ANY    ("lseek32-set",	&opt_lseek32_set)
917 #if HAVE_LSEEK64
918 	IF_ANY    ("lseek64",		&opt_lseek64_set)
919 	IF_ANY    ("lseek64-cur",	&opt_lseek64_cur)
920 	IF_ANY    ("lseek64-end",	&opt_lseek64_end)
921 	IF_ANY    ("lseek64-set",	&opt_lseek64_set)
922 #endif
923 	IF_TUN    ("master",	&opt_iff_master)
924 	IF_LISTEN ("max-children",	&opt_max_children)
925 #if HAVE_SSL_set_max_proto_version || defined(SSL_set_max_proto_version)
926 	IF_OPENSSL("max-version",	&opt_openssl_max_proto_version)
927 #endif
928 	IF_LISTEN ("maxchildren",	&opt_max_children)
929 #ifdef TCP_MAXSEG
930 	IF_TCP    ("maxseg",	&opt_tcp_maxseg)
931 	IF_TCP    ("maxseg-late",	&opt_tcp_maxseg_late)
932 #endif
933 #ifdef TCP_MD5SUM
934 	IF_TCP    ("md5sig",	&opt_tcp_md5sig)
935 #endif
936 #ifdef IP_ADD_MEMBERSHIP
937 	IF_IP     ("membership",	&opt_ip_add_membership)
938 #endif
939 #if WITH_OPENSSL_METHOD
940 	IF_OPENSSL("method",	&opt_openssl_method)
941 #endif
942 	IF_TERMIOS("min",	&opt_vmin)
943 #if HAVE_SSL_set_min_proto_version || defined(SSL_set_min_proto_version)
944 	IF_OPENSSL("min-version",	&opt_openssl_min_proto_version)
945 #endif
946 	IF_ANY    ("mode",	&opt_perm)
947 #ifdef TCP_MAXSEG
948 	IF_TCP    ("mss",	&opt_tcp_maxseg)
949 	IF_TCP    ("mss-late",	&opt_tcp_maxseg_late)
950 #endif
951 #ifdef IP_MTU
952 	IF_IP     ("mtu",	&opt_ip_mtu)
953 #endif
954 #ifdef IP_MTU_DISCOVER
955 	IF_IP     ("mtudiscover",	&opt_ip_mtu_discover)
956 #endif
957 	IF_TUN    ("multicast",	&opt_iff_multicast)
958 	IF_IP     ("multicast-if",	&opt_ip_multicast_if)
959 	IF_IP     ("multicast-loop",	&opt_ip_multicast_loop)
960 	IF_IP     ("multicast-ttl",	&opt_ip_multicast_ttl)
961 	IF_IP     ("multicastloop",	&opt_ip_multicast_loop)
962 	IF_IP     ("multicastttl",	&opt_ip_multicast_ttl)
963 #if defined(O_NDELAY) && (!defined(O_NONBLOCK) || O_NDELAY != O_NONBLOCK)
964 	IF_ANY    ("ndelay",	&opt_o_ndelay)
965 #else
966 	IF_ANY    ("ndelay",	&opt_nonblock)
967 #endif
968 	IF_NAMED  ("new",	&opt_unlink_early)
969 #ifdef NLDLY
970 #  ifdef NL0
971 	IF_TERMIOS("nl0",	&opt_nl0)
972 #  endif
973 #  ifdef NL1
974 	IF_TERMIOS("nl1",	&opt_nl1)
975 #  endif
976 	IF_TERMIOS("nldly",	&opt_nldly)
977 #endif /* defined(NLDLY) */
978 #ifdef SO_NO_CHECK
979 	IF_SOCKET ("no-check",	&opt_so_no_check)
980 #endif
981 	IF_TUN    ("no-pi",	&opt_iff_no_pi)
982 #if defined(HAVE_SSL_set_tlsext_host_name) || defined(SSL_set_tlsext_host_name)
983 	IF_OPENSSL("no-sni",	&opt_openssl_no_sni)
984 #endif
985 	IF_TUN    ("noarp",	&opt_iff_noarp)
986 #ifdef O_NOATIME
987 	IF_OPEN   ("noatime",	&opt_o_noatime)
988 #endif
989 #ifdef SO_NO_CHECK
990 	IF_SOCKET ("nocheck",	&opt_so_no_check)
991 #endif
992 	IF_OPEN   ("noctty",	&opt_o_noctty)
993 #ifdef TCP_NODELAY
994 	IF_TCP    ("nodelay",	&opt_tcp_nodelay)
995 #endif
996 #if WITH_FS && defined(FS_NODUMP_FL)
997 	IF_ANY    ("nodump",	&opt_fs_nodump)
998 #endif
999 #if HAVE_REGEX_H
1000 	IF_READLINE("noecho",	&opt_noecho)
1001 #endif /* HAVE_REGEX_H */
1002 	IF_TERMIOS("noflsh",	&opt_noflsh)
1003 #ifdef O_NOFOLLOW
1004 	IF_OPEN   ("nofollow",	&opt_o_nofollow)
1005 #endif
1006 	IF_EXEC   ("nofork",	&opt_nofork)
1007 #ifdef O_NOINHERIT
1008 	IF_ANY    ("noinherit",		&opt_o_noinherit)
1009 #endif
1010 	IF_ANY    ("nonblock",	&opt_nonblock)
1011 #ifdef TCP_NOOPT
1012 	IF_TCP    ("noopt",		&opt_tcp_noopt)
1013 #endif
1014 	IF_READLINE("noprompt",	&opt_noprompt)
1015 #ifdef TCP_NOPUSH
1016 	IF_TCP    ("nopush",	&opt_tcp_nopush)
1017 #endif
1018 #ifdef SO_NOREUSEADDR	/* AIX 4.3.3 */
1019 	IF_SOCKET ("noreuseaddr",	&opt_so_noreuseaddr)
1020 #endif /* SO_NOREUSEADDR */
1021 #if defined(HAVE_SSL_set_tlsext_host_name) || defined(SSL_set_tlsext_host_name)
1022 	IF_OPENSSL("nosni",		&opt_openssl_no_sni)
1023 #endif
1024 	IF_TUN    ("notrailers",	&opt_iff_notrailers)
1025 #ifdef O_NSHARE
1026 	IF_OPEN   ("nshare",	&opt_o_nshare)
1027 #endif
1028 	IF_SOCKET ("null-eof",		&opt_null_eof)
1029 	IF_ANY    ("o-append",		&opt_append)
1030 #ifdef O_ASYNC
1031 	IF_ANY    ("o-async",		&opt_async)
1032 #endif
1033 #ifdef O_BINARY
1034 	IF_OPEN   ("o-binary",		&opt_o_binary)
1035 #endif
1036 	IF_OPEN   ("o-creat",	&opt_o_create)
1037 	IF_OPEN   ("o-create",	&opt_o_create)
1038 #ifdef O_DEFER
1039 	IF_OPEN   ("o-defer",	&opt_o_defer)
1040 #endif
1041 #ifdef O_DELAY
1042 	IF_OPEN   ("o-delay",	&opt_o_delay)
1043 #endif
1044 #ifdef O_DIRECT
1045 	IF_OPEN   ("o-direct",	&opt_o_direct)
1046 #endif
1047 #ifdef O_DIRECTORY
1048 	IF_OPEN   ("o-directory",	&opt_o_directory)
1049 #endif
1050 #ifdef O_DSYNC
1051 	IF_OPEN   ("o-dsync",	&opt_o_dsync)
1052 #endif
1053 	IF_OPEN   ("o-excl",	&opt_o_excl)
1054 #ifdef O_LARGEFILE
1055 	IF_OPEN   ("o-largefile",	&opt_o_largefile)
1056 #endif
1057 #if defined(O_NDELAY) && (!defined(O_NONBLOCK) || O_NDELAY != O_NONBLOCK)
1058 	IF_ANY    ("o-ndelay",	&opt_o_ndelay)
1059 #else
1060 	IF_ANY    ("o-ndelay",	&opt_nonblock)
1061 #endif
1062 #ifdef O_NOATIME
1063 	IF_OPEN   ("o-noatime",	&opt_o_noatime)
1064 #endif
1065 	IF_OPEN   ("o-noctty",	&opt_o_noctty)
1066 #ifdef O_NOFOLLOW
1067 	IF_OPEN   ("o-nofollow",	&opt_o_nofollow)
1068 #endif
1069 #ifdef O_NOINHERIT
1070 	IF_ANY    ("o-noinherit",	&opt_o_noinherit)
1071 #endif
1072 	IF_ANY    ("o-nonblock",	&opt_nonblock)
1073 #ifdef O_NSHARE
1074 	IF_OPEN   ("o-nshare",	&opt_o_nshare)
1075 #endif
1076 #ifdef O_PRIV
1077 	IF_OPEN   ("o-priv",	&opt_o_priv)
1078 #endif
1079 	IF_OPEN   ("o-rdonly",	&opt_o_rdonly)
1080 	IF_OPEN   ("o-rdwr",	&opt_o_rdwr)
1081 #ifdef O_RSHARE
1082 	IF_OPEN   ("o-rshare",	&opt_o_rshare)
1083 #endif
1084 #ifdef O_RSYNC
1085 	IF_OPEN   ("o-rsync",	&opt_o_rsync)
1086 #endif
1087 #ifdef O_SYNC
1088 	IF_OPEN   ("o-sync",	&opt_o_sync)
1089 #endif
1090 #ifdef O_TEXT
1091 	IF_ANY    ("o-text",		&opt_o_text)
1092 #endif
1093 	IF_OPEN   ("o-trunc",	&opt_o_trunc)
1094 	IF_OPEN   ("o-wronly",	&opt_o_wronly)
1095 	IF_OPEN   ("o_create",	&opt_o_create)
1096 #ifdef O_DEFER
1097 	IF_OPEN   ("o_defer",	&opt_o_defer)
1098 #endif
1099 #ifdef O_DELAY
1100 	IF_OPEN   ("o_delay",	&opt_o_delay)
1101 #endif
1102 #ifdef O_DIRECT
1103 	IF_OPEN   ("o_direct",	&opt_o_direct)
1104 #endif
1105 #ifdef O_DIRECTORY
1106 	IF_OPEN   ("o_directory",	&opt_o_directory)
1107 #endif
1108 #ifdef O_DSYNC
1109 	IF_OPEN   ("o_dsync",	&opt_o_dsync)
1110 #endif
1111 	IF_OPEN   ("o_excl",	&opt_o_excl)
1112 #ifdef O_LARGEFILE
1113 	IF_OPEN   ("o_largefile",	&opt_o_largefile)
1114 #endif
1115 #if defined(O_NDELAY) && (!defined(O_NONBLOCK) || O_NDELAY != O_NONBLOCK)
1116 	IF_ANY    ("o_ndelay",	&opt_o_ndelay)
1117 #else
1118 	IF_ANY    ("o_ndelay",	&opt_nonblock)
1119 #endif
1120 	IF_OPEN   ("o_noctty",	&opt_o_noctty)
1121 #ifdef O_NOFOLLOW
1122 	IF_OPEN   ("o_nofollow",	&opt_o_nofollow)
1123 #endif
1124 #ifdef O_NSHARE
1125 	IF_OPEN   ("o_nshare",	&opt_o_nshare)
1126 #endif
1127 #ifdef O_PRIV
1128 	IF_OPEN   ("o_priv",	&opt_o_priv)
1129 #endif
1130 	IF_OPEN   ("o_rdonly",	&opt_o_rdonly)
1131 	IF_OPEN   ("o_rdwr",	&opt_o_rdwr)
1132 #ifdef O_RSHARE
1133 	IF_OPEN   ("o_rshare",	&opt_o_rshare)
1134 #endif
1135 #ifdef O_RSYNC
1136 	IF_OPEN   ("o_rsync",	&opt_o_rsync)
1137 #endif
1138 #ifdef O_SYNC
1139 	IF_OPEN   ("o_sync",	&opt_o_sync)
1140 #endif
1141 	IF_OPEN   ("o_wronly",	&opt_o_wronly)
1142 #ifdef OCRNL
1143 	IF_TERMIOS("ocrnl",	&opt_ocrnl)
1144 #endif
1145 #ifdef OFDEL
1146 	IF_TERMIOS("ofdel",	&opt_ofdel)
1147 #endif
1148 #ifdef OFILL
1149 	IF_TERMIOS("ofill",	&opt_ofill)
1150 #endif
1151 #ifdef OLCUC
1152 	IF_TERMIOS("olcuc",	&opt_olcuc)
1153 #endif
1154 	IF_TERMIOS("onlcr",	&opt_onlcr)
1155 #ifdef ONLRET
1156 	IF_TERMIOS("onlret",	&opt_onlret)
1157 #endif
1158 #ifdef ONOCR
1159 	IF_TERMIOS("onocr",	&opt_onocr)
1160 #endif
1161 	IF_SOCKET ("oobinline",	&opt_so_oobinline)
1162 #if HAVE_OPENPTY
1163 	IF_EXEC   ("openpty",	&opt_openpty)
1164 #endif /* HAVE_OPENPTY */
1165 	IF_OPENSSL("openssl-cafile",	&opt_openssl_cafile)
1166 	IF_OPENSSL("openssl-capath",	&opt_openssl_capath)
1167 	IF_OPENSSL("openssl-certificate",	&opt_openssl_certificate)
1168 	IF_OPENSSL("openssl-cipherlist",	&opt_openssl_cipherlist)
1169 	IF_OPENSSL("openssl-commonname",	&opt_openssl_commonname)
1170 #if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_COMP)
1171 	IF_OPENSSL("openssl-compress",	&opt_openssl_compress)
1172 #endif
1173 	IF_OPENSSL("openssl-dhparam",	&opt_openssl_dhparam)
1174 	IF_OPENSSL("openssl-dhparams",	&opt_openssl_dhparam)
1175 	IF_OPENSSL("openssl-egd",	&opt_openssl_egd)
1176 #if WITH_FIPS
1177 	IF_OPENSSL("openssl-fips",	&opt_openssl_fips)
1178 #endif
1179 	IF_OPENSSL("openssl-key",	&opt_openssl_key)
1180 #if HAVE_SSL_set_max_proto_version || defined(SSL_set_max_proto_version)
1181 	IF_OPENSSL("openssl-max-proto-version",	&opt_openssl_max_proto_version)
1182 #endif
1183 #if WITH_OPENSSL_METHOD
1184 	IF_OPENSSL("openssl-method",	&opt_openssl_method)
1185 #endif
1186 #if HAVE_SSL_set_min_proto_version || defined(SSL_set_min_proto_version)
1187 	IF_OPENSSL("openssl-min-proto-version",	&opt_openssl_min_proto_version)
1188 #endif
1189 #if defined(HAVE_SSL_set_tlsext_host_name) || defined(SSL_set_tlsext_host_name)
1190 	IF_OPENSSL("openssl-no-sni",	&opt_openssl_no_sni)
1191 #endif
1192 	IF_OPENSSL("openssl-pseudo",	&opt_openssl_pseudo)
1193 #if defined(HAVE_SSL_set_tlsext_host_name) || defined(SSL_set_tlsext_host_name)
1194 	IF_OPENSSL("openssl-snihost",   &opt_openssl_snihost)
1195 #endif
1196 	IF_OPENSSL("openssl-verify",	&opt_openssl_verify)
1197 	IF_TERMIOS("opost",	&opt_opost)
1198 #if HAVE_TERMIOS_OSPEED
1199 	IF_TERMIOS("ospeed",	&opt_ospeed)
1200 #endif
1201 	IF_ANY    ("owner",	&opt_user)
1202 	IF_TERMIOS("parenb",	&opt_parenb)
1203 	IF_TERMIOS("parmrk",	&opt_parmrk)
1204 	IF_TERMIOS("parodd",	&opt_parodd)
1205 #ifdef SO_PASSCRED
1206 	IF_SOCKET ("passcred",	&opt_so_passcred)
1207 #endif
1208 	IF_EXEC   ("path",	&opt_path)
1209 #ifdef TCP_PAWS	/* OSF1 */
1210 	IF_TCP    ("paws",	&opt_tcp_paws)
1211 #endif
1212 #ifdef SO_PEERCRED
1213 	IF_SOCKET ("peercred",	&opt_so_peercred)
1214 #endif
1215 #ifdef PENDIN
1216 	IF_TERMIOS("pendin",	&opt_pendin)
1217 #endif
1218 	IF_ANY    ("perm",	&opt_perm)
1219 	IF_NAMED  ("perm-early",	&opt_perm_early)
1220 	IF_ANY    ("perm-late",	&opt_perm_late)
1221 	IF_SOCKET ("pf",	&opt_protocol_family)
1222 	IF_EXEC   ("pgid",	&opt_setpgid)
1223 	IF_EXEC   ("pipes",	&opt_pipes)
1224 #ifdef IP_PKTINFO
1225 	IF_IP     ("pktinfo",	&opt_ip_pktinfo)
1226 #endif
1227 #ifdef IP_PKTOPTIONS
1228 	IF_IP     ("pktoptions",	&opt_ip_pktoptions)
1229 	IF_IP     ("pktopts",	&opt_ip_pktoptions)
1230 #endif
1231 	IF_TUN    ("pointopoint",	&opt_iff_pointopoint)
1232 #ifdef I_POP
1233 	IF_ANY    ("pop-all",	&opt_streams_i_pop_all)
1234 #endif
1235 	/*IF_IPAPP("port",	&opt_port)*/
1236 	IF_TUN    ("portsel",	&opt_iff_portsel)
1237 #if HAVE_RESOLV_H && WITH_RES_PRIMARY
1238 	IF_IP     ("primary",	&opt_res_primary)
1239 #endif
1240 #ifdef SO_PRIORITY
1241 	IF_SOCKET ("priority",	&opt_so_priority)
1242 #endif
1243 #ifdef O_PRIV
1244 	IF_OPEN   ("priv",	&opt_o_priv)
1245 #endif
1246 	IF_TUN    ("promisc",	&opt_iff_promisc)
1247 	IF_READLINE("prompt",	&opt_prompt)
1248 #ifdef SO_PROTOTYPE
1249 	IF_SOCKET ("protocol",	&opt_so_prototype)
1250 #endif
1251 	IF_SOCKET ("protocol-family",	&opt_protocol_family)
1252 #ifdef SO_PROTOTYPE
1253 	IF_SOCKET ("prototype",	&opt_so_prototype)
1254 #endif
1255 	IF_PROXY  ("proxy-auth",	&opt_proxy_authorization)
1256 	IF_PROXY  ("proxy-authorization",	&opt_proxy_authorization)
1257 	IF_PROXY  ("proxy-authorization-file",	&opt_proxy_authorization_file)
1258 	IF_PROXY  ("proxy-resolve",	&opt_proxy_resolve)
1259 	IF_PROXY  ("proxyauth",	&opt_proxy_authorization)
1260 	IF_PROXY  ("proxyauthfile",	&opt_proxy_authorization_file)
1261 	IF_PROXY  ("proxyport",	&opt_proxyport)
1262 #ifdef ECHOPRT
1263 	IF_TERMIOS("prterase",	&opt_echoprt)
1264 #endif
1265 	IF_OPENSSL("pseudo",	&opt_openssl_pseudo)
1266 #if HAVE_DEV_PTMX || HAVE_DEV_PTC
1267 	IF_EXEC   ("ptmx",	&opt_ptmx)
1268 #endif
1269 #if HAVE_PTY
1270 	IF_EXEC   ("pty",	&opt_pty)
1271 #endif
1272 #if HAVE_PTY && HAVE_POLL
1273 	IF_PTY    ("pty-interval",	&opt_pty_intervall)
1274 	IF_PTY    ("pty-intervall",	&opt_pty_intervall)
1275 	IF_PTY    ("pty-wait-slave",	&opt_pty_wait_slave)
1276 #endif /* HAVE_PTY && HAVE_POLL */
1277 #ifdef I_PUSH
1278 	IF_ANY    ("push",	&opt_streams_i_push)
1279 #endif
1280 #ifdef TCP_QUICKACK
1281 	IF_TCP    ("quickack",	&opt_tcp_quickack)
1282 #endif
1283 	IF_TERMIOS("quit",	&opt_vquit)
1284 	IF_RANGE  ("range",	&opt_range)
1285 	IF_TERMIOS("raw",	&opt_raw)
1286 	IF_TERMIOS("rawer",	&opt_termios_rawer)
1287 	IF_SOCKET ("rcvbuf",	&opt_so_rcvbuf)
1288 	IF_SOCKET ("rcvbuf-late",	&opt_so_rcvbuf_late)
1289 #ifdef SO_RCVLOWAT
1290 	IF_SOCKET ("rcvlowat",	&opt_so_rcvlowat)
1291 #endif
1292 	IF_OPEN   ("rdonly",	&opt_o_rdonly)
1293 	IF_OPEN   ("rdwr",	&opt_o_rdwr)
1294 	IF_ANY    ("readbytes", &opt_readbytes)
1295 #if HAVE_RESOLV_H
1296 	IF_IP     ("recurse",	&opt_res_recurse)
1297 #endif /* HAVE_RESOLV_H */
1298 #ifdef IP_RECVDSTADDR
1299 	IF_IP     ("recvdstaddr",	&opt_ip_recvdstaddr)
1300 #endif
1301 #ifdef IPV6_RECVDSTOPTS
1302 	IF_IP6    ("recvdstopts",	&opt_ipv6_recvdstopts)
1303 #endif
1304 #ifdef IP_RECVERR
1305 	IF_IP     ("recverr",	&opt_ip_recverr)
1306 #endif
1307 #ifdef IPV6_RECVHOPLIMIT
1308 	IF_IP6    ("recvhoplimit",	&opt_ipv6_recvhoplimit)
1309 #endif
1310 #ifdef IPV6_RECVHOPOPTS
1311 	IF_IP6    ("recvhopopts",	&opt_ipv6_recvhopopts)
1312 #endif
1313 #ifdef IP_RECVIF
1314 	IF_IP     ("recvif",		&opt_ip_recvif)
1315 #endif
1316 #ifdef IP_RECVOPTS
1317 	IF_IP     ("recvopts",	&opt_ip_recvopts)
1318 #endif
1319 #ifdef IPV6_RECVPKTINFO
1320 	IF_IP6    ("recvpktinfo",	&opt_ipv6_recvpktinfo)
1321 #endif
1322 #ifdef IPV6_RECVRTHDR
1323 	IF_IP6    ("recvrthdr",	&opt_ipv6_recvrthdr)
1324 #endif
1325 #ifdef IP_RECVTOS
1326 	IF_IP     ("recvtos",	&opt_ip_recvtos)
1327 #endif
1328 #ifdef IP_RECVTTL
1329 	IF_IP     ("recvttl",	&opt_ip_recvttl)
1330 #endif
1331 	IF_NAMED  ("remove",	&opt_unlink)
1332 #ifdef VREPRINT
1333 	IF_TERMIOS("reprint",	&opt_vreprint)
1334 #endif
1335 #if HAVE_RESOLV_H
1336 #  if WITH_AA_ONLY
1337 	IF_IP     ("res-aaonly",	&opt_res_aaonly)
1338 #  endif
1339 	IF_IP     ("res-debug",	&opt_res_debug)
1340 	IF_IP     ("res-defnames",	&opt_res_defnames)
1341 	IF_IP     ("res-dnsrch",	&opt_res_dnsrch)
1342 	IF_IP     ("res-igntc",	&opt_res_igntc)
1343 #  if WITH_RES_PRIMARY
1344 	IF_IP     ("res-primary",	&opt_res_primary)
1345 #  endif
1346 	IF_IP     ("res-recurse",	&opt_res_recurse)
1347 	IF_IP     ("res-stayopen",	&opt_res_stayopen)
1348 	IF_IP     ("res-usevc",	&opt_res_usevc)
1349 #endif /* HAVE_RESOLV_H */
1350 	IF_PROXY  ("resolv",	&opt_proxy_resolve)
1351 	IF_PROXY  ("resolve",	&opt_proxy_resolve)
1352 #ifdef IP_RETOPTS
1353 	IF_IP     ("retopts",	&opt_ip_retopts)
1354 #endif
1355 	IF_RETRY  ("retry",	&opt_retry)
1356 	IF_SOCKET ("reuseaddr",	&opt_so_reuseaddr)
1357 #ifdef SO_REUSEPORT	/* AIX 4.3.3 */
1358 	IF_SOCKET ("reuseport",	&opt_so_reuseport)
1359 #endif /* defined(SO_REUSEPORT) */
1360 #ifdef TCP_RFC1323
1361 	IF_TCP    ("rfc1323",	&opt_tcp_rfc1323)
1362 #endif
1363 #ifdef IP_ROUTER_ALERT
1364 	IF_IP     ("routeralert",	&opt_ip_router_alert)
1365 #endif
1366 #ifdef VREPRINT
1367 	IF_TERMIOS("rprnt",	&opt_vreprint)
1368 #endif
1369 #ifdef O_RSHARE
1370 	IF_OPEN   ("rshare",	&opt_o_rshare)
1371 #endif
1372 #ifdef O_RSYNC
1373 	IF_OPEN   ("rsync",	&opt_o_rsync)
1374 #endif
1375 #ifdef IPV6_RTHDR
1376 	IF_IP6    ("rthdr",	&opt_ipv6_rthdr)
1377 #endif
1378 	IF_TUN    ("running",	&opt_iff_running)
1379 #ifdef TCP_SACK_DISABLE
1380 	IF_TCP    ("sack-disable",	&opt_tcp_sack_disable)
1381 #endif
1382 #ifdef TCP_SACKENA	/* OSF1 */
1383 	IF_TCP    ("sackena",	&opt_tcp_sackena)
1384 #endif
1385 	IF_TERMIOS("sane",	&opt_sane)
1386 #ifdef SCTP_MAXSEG
1387 	IF_SCTP   ("sctp-maxseg",	&opt_sctp_maxseg)
1388 	IF_SCTP   ("sctp-maxseg-late",	&opt_sctp_maxseg_late)
1389 #endif
1390 #ifdef SCTP_NODELAY
1391 	IF_SCTP   ("sctp-nodelay",	&opt_sctp_nodelay)
1392 #endif
1393 #if WITH_FS && defined(FS_SECRM_FL)
1394 	IF_ANY    ("secrm",	&opt_fs_secrm)
1395 #endif
1396 #ifdef SO_SECURITY_AUTHENTICATION
1397 	IF_SOCKET ("security-authentication",	&opt_so_security_authentication)
1398 #endif
1399 #ifdef SO_SECURITY_ENCRYPTION_NETWORK
1400 	IF_SOCKET ("security-encryption-network",	&opt_so_security_encryption_network)
1401 #endif
1402 #ifdef SO_SECURITY_ENCRYPTION_TRANSPORT
1403 	IF_SOCKET ("security-encryption-transport",	&opt_so_security_encryption_transport)
1404 #endif
1405 #ifdef SO_SECURITY_AUTHENTICATION
1406 	IF_SOCKET ("securityauthentication",	&opt_so_security_authentication)
1407 #endif
1408 #ifdef SO_SECURITY_ENCRYPTION_NETWORK
1409 	IF_SOCKET ("securityencryptionnetwork",	&opt_so_security_encryption_network)
1410 #endif
1411 #ifdef SO_SECURITY_ENCRYPTION_TRANSPORT
1412 	IF_SOCKET ("securityencryptiontransport",	&opt_so_security_encryption_transport)
1413 #endif
1414 #if HAVE_LSEEK64
1415 	IF_ANY    ("seek",		&opt_lseek64_set)
1416 	IF_ANY    ("seek-cur",		&opt_lseek64_cur)
1417 	IF_ANY    ("seek-end",		&opt_lseek64_end)
1418 	IF_ANY    ("seek-set",		&opt_lseek64_set)
1419 #else
1420 	IF_ANY    ("seek",		&opt_lseek32_set)
1421 	IF_ANY    ("seek-cur",		&opt_lseek32_cur)
1422 	IF_ANY    ("seek-end",		&opt_lseek32_end)
1423 	IF_ANY    ("seek-set",		&opt_lseek32_set)
1424 #endif
1425 	IF_ANY    ("setgid",	&opt_setgid)
1426 	IF_ANY    ("setgid-early",	&opt_setgid_early)
1427 	IF_ANY 	  ("setlk",	&opt_f_setlk_wr)
1428 	IF_ANY 	  ("setlk-rd",	&opt_f_setlk_rd)
1429 	IF_ANY 	  ("setlk-wr",	&opt_f_setlk_wr)
1430 	IF_ANY 	  ("setlkw",	&opt_f_setlkw_wr)
1431 	IF_ANY 	  ("setlkw-rd",	&opt_f_setlkw_rd)
1432 	IF_ANY 	  ("setlkw-wr",	&opt_f_setlkw_wr)
1433 	IF_EXEC   ("setpgid",	&opt_setpgid)
1434 #if WITH_EXEC || WITH_SYSTEM
1435 	IF_EXEC   ("setsid",	&opt_setsid)
1436 #endif
1437 	IF_SOCKET ("setsockopt",	&opt_setsockopt)
1438 	IF_SOCKET ("setsockopt-bin",	&opt_setsockopt_bin)
1439 	IF_SOCKET ("setsockopt-int",	&opt_setsockopt_int)
1440 	IF_SOCKET ("setsockopt-listen",	&opt_setsockopt_listen)
1441 	IF_SOCKET ("setsockopt-string",	&opt_setsockopt_string)
1442 	IF_ANY    ("setuid",	&opt_setuid)
1443 	IF_ANY    ("setuid-early",	&opt_setuid_early)
1444 	IF_ANY    ("shut-close",	&opt_shut_close)
1445 	IF_ANY    ("shut-down",	&opt_shut_down)
1446 	IF_ANY    ("shut-none",	&opt_shut_none)
1447 	IF_ANY    ("shut-null",		&opt_shut_null)
1448 #if WITH_EXEC || WITH_SYSTEM
1449 	IF_ANY    ("sid",	&opt_setsid)
1450 #endif
1451 	IF_EXEC   ("sighup",	&opt_sighup)
1452 	IF_EXEC   ("sigint",	&opt_sigint)
1453 #ifdef TCP_SIGNATURE_ENABLE
1454 	IF_TCP    ("signature-enable",	&opt_tcp_signature_enable)
1455 #endif
1456 	IF_EXEC   ("sigquit",	&opt_sigquit)
1457 #ifdef SIOCSPGRP
1458 	IF_SOCKET ("siocspgrp",	&opt_siocspgrp)
1459 #endif
1460 	IF_TUN    ("slave",	&opt_iff_slave)
1461 	IF_SOCKET ("sndbuf",	&opt_so_sndbuf)
1462 	IF_SOCKET ("sndbuf-late",	&opt_so_sndbuf_late)
1463 #ifdef SO_SNDLOWAT
1464 	IF_SOCKET ("sndlowat",	&opt_so_sndlowat)
1465 #endif
1466 #if defined(HAVE_SSL_set_tlsext_host_name) || defined(SSL_set_tlsext_host_name)
1467 	IF_OPENSSL("snihost",    &opt_openssl_snihost)
1468 #endif
1469 #ifdef SO_ACCEPTCONN /* AIX433 */
1470 	IF_SOCKET ("so-acceptconn",	&opt_so_acceptconn)
1471 #endif /* SO_ACCEPTCONN */
1472 #ifdef SO_ATTACH_FILTER
1473 	IF_SOCKET ("so-attach-filter",	&opt_so_attach_filter)
1474 #endif
1475 #ifdef SO_AUDIT	/* AIX 4.3.3 */
1476 	IF_SOCKET ("so-audit",	&opt_so_audit)
1477 #endif /* SO_AUDIT */
1478 #ifdef SO_BINDTODEVICE
1479 	IF_SOCKET ("so-bindtodevice",	&opt_so_bindtodevice)
1480 #endif
1481 	IF_SOCKET ("so-broadcast",	&opt_so_broadcast)
1482 #ifdef SO_BSDCOMPAT
1483 	IF_SOCKET ("so-bsdcompat",	&opt_so_bsdcompat)
1484 #endif
1485 #ifdef SO_CKSUMRECV
1486 	IF_SOCKET ("so-cksumrecv",	&opt_so_cksumrecv)
1487 #endif /* SO_CKSUMRECV */
1488 	IF_SOCKET ("so-debug",	&opt_so_debug)
1489 #ifdef SO_DETACH_FILTER
1490 	IF_SOCKET ("so-detach-filter", &opt_so_detach_filter)
1491 #endif
1492 #ifdef SO_DGRAM_ERRIND
1493 	IF_SOCKET ("so-dgram-errind",	&opt_so_dgram_errind)
1494 #endif
1495 #ifdef SO_DONTLINGER
1496 	IF_SOCKET ("so-dontlinger",	&opt_so_dontlinger)
1497 #endif
1498 	IF_SOCKET ("so-dontroute",	&opt_so_dontroute)
1499 	IF_SOCKET ("so-error",	&opt_so_error)
1500 	IF_SOCKET ("so-keepalive",	&opt_so_keepalive)
1501 #ifdef SO_KERNACCEPT	/* AIX 4.3.3 */
1502 	IF_SOCKET ("so-kernaccept",	&opt_so_kernaccept)
1503 #endif /* SO_KERNACCEPT */
1504 	IF_SOCKET ("so-linger",	&opt_so_linger)
1505 #ifdef SO_NO_CHECK
1506 	IF_SOCKET ("so-no-check",	&opt_so_no_check)
1507 #endif
1508 #ifdef SO_NOREUSEADDR	/* AIX 4.3.3 */
1509 	IF_SOCKET ("so-noreuseaddr",	&opt_so_noreuseaddr)
1510 #endif /* SO_NOREUSEADDR */
1511 	IF_SOCKET ("so-oobinline",	&opt_so_oobinline)
1512 #ifdef SO_PASSCRED
1513 	IF_SOCKET ("so-passcred",	&opt_so_passcred)
1514 #endif
1515 #ifdef SO_PEERCRED
1516 	IF_SOCKET ("so-peercred",	&opt_so_peercred)
1517 #endif
1518 #ifdef SO_PRIORITY
1519 	IF_SOCKET ("so-priority",	&opt_so_priority)
1520 #endif
1521 #ifdef SO_PROTOTYPE
1522 	IF_SOCKET ("so-protocol",	&opt_so_prototype)
1523 	IF_SOCKET ("so-prototype",	&opt_so_prototype)
1524 #endif
1525 	IF_SOCKET ("so-rcvbuf",	&opt_so_rcvbuf)
1526 	IF_SOCKET ("so-rcvbuf-late",	&opt_so_rcvbuf_late)
1527 #ifdef SO_RCVLOWAT
1528 	IF_SOCKET ("so-rcvlowat",	&opt_so_rcvlowat)
1529 #endif
1530 	IF_SOCKET ("so-reuseaddr",	&opt_so_reuseaddr)
1531 #ifdef SO_REUSEPORT	/* AIX 4.3.3 */
1532 	IF_SOCKET ("so-reuseport",	&opt_so_reuseport)
1533 #endif /* defined(SO_REUSEPORT) */
1534 #ifdef SO_SECURITY_AUTHENTICATION
1535 	IF_SOCKET ("so-security-authentication",	&opt_so_security_authentication)
1536 #endif
1537 #ifdef SO_SECURITY_ENCRYPTION_NETWORK
1538 	IF_SOCKET ("so-security-encryption-network",	&opt_so_security_encryption_network)
1539 #endif
1540 #ifdef SO_SECURITY_ENCRYPTION_TRANSPORT
1541 	IF_SOCKET ("so-security-encryption-transport",	&opt_so_security_encryption_transport)
1542 #endif
1543 	IF_SOCKET ("so-sndbuf",	&opt_so_sndbuf)
1544 	IF_SOCKET ("so-sndbuf-late",	&opt_so_sndbuf_late)
1545 #ifdef SO_SNDLOWAT
1546 	IF_SOCKET ("so-sndlowat",	&opt_so_sndlowat)
1547 #endif
1548 #ifdef SO_TIMESTAMP
1549 	IF_SOCKET ("so-timestamp",	&opt_so_timestamp)
1550 #endif
1551 	IF_SOCKET ("so-type",	&opt_so_type)
1552 #ifdef SO_USE_IFBUFS
1553 	IF_SOCKET ("so-use-ifbufs",	&opt_so_use_ifbufs)
1554 #endif /* SO_USE_IFBUFS */
1555 #ifdef SO_USELOOPBACK /* AIX433, Solaris */
1556 	IF_SOCKET ("so-useloopback",	&opt_so_useloopback)
1557 #endif /* SO_USELOOPBACK */
1558 	IF_SOCKET ("sockopt",		&opt_setsockopt)
1559 	IF_SOCKET ("sockopt-bin",	&opt_setsockopt_bin)
1560 	IF_SOCKET ("sockopt-int",	&opt_setsockopt_int)
1561 	IF_SOCKET ("sockopt-listen",	&opt_setsockopt_listen)
1562 	IF_SOCKET ("sockopt-string",	&opt_setsockopt_string)
1563 	IF_SOCKS4 ("socksport",	&opt_socksport)
1564 	IF_SOCKS4 ("socksuser",	&opt_socksuser)
1565 	IF_SOCKET ("socktype",	&opt_so_type)
1566 #ifdef IP_ADD_SOURCE_MEMBERSHIP
1567 	IF_IP     ("source-membership",	&opt_ip_add_source_membership)
1568 #endif
1569 	IF_IPAPP  ("sourceport",	&opt_sourceport)
1570 	IF_IPAPP  ("sp",	&opt_sourceport)
1571 	IF_TERMIOS("start",	&opt_vstart)
1572 #if HAVE_RESOLV_H
1573 	IF_IP     ("stayopen",	&opt_res_stayopen)
1574 #endif /* HAVE_RESOLV_H */
1575 	IF_EXEC   ("stderr",    &opt_stderr)
1576 #ifdef TCP_STDURG
1577 	IF_TCP    ("stdurg",	&opt_tcp_stdurg)
1578 #endif
1579 	IF_TERMIOS("stop",	&opt_vstop)
1580 #ifdef I_POP
1581 	IF_ANY    ("streams-i-pop-all",	&opt_streams_i_pop_all)
1582 #endif
1583 #ifdef I_PUSH
1584 	IF_ANY    ("streams-i-push",	&opt_streams_i_push)
1585 #endif
1586 	IF_ANY    ("su",	&opt_substuser)
1587 #if defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT)
1588 	IF_ANY    ("su-d",	&opt_substuser_delayed)
1589 #endif
1590 	IF_ANY    ("su-e",	&opt_substuser_early)
1591 	IF_ANY    ("substuser",	&opt_substuser)
1592 #if defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT)
1593 	IF_ANY    ("substuser-delayed",	&opt_substuser_delayed)
1594 #endif
1595 	IF_ANY    ("substuser-early",	&opt_substuser_early)
1596 	IF_TERMIOS("susp",	&opt_vsusp)
1597 #ifdef VSWTC
1598 	IF_TERMIOS("swtc",	&opt_vswtc)
1599 	IF_TERMIOS("swtch",	&opt_vswtc)
1600 #endif
1601 	IF_PTY    ("symbolic-link",	&opt_symbolic_link)
1602 #ifdef O_SYNC
1603 	IF_OPEN   ("sync",	&opt_o_sync)
1604 #elif FS_SYNC_FL
1605 	IF_ANY    ("sync",	&opt_fs_sync)
1606 #endif
1607 #ifdef TCP_SYNCNT
1608 	IF_TCP    ("syncnt",	&opt_tcp_syncnt)
1609 #endif
1610 #ifdef TABDLY
1611 #  ifdef TAB0
1612 	IF_TERMIOS("tab0",	&opt_tab0)
1613 #  endif
1614 #  ifdef TAB1
1615 	IF_TERMIOS("tab1",	&opt_tab1)
1616 #  endif
1617 #  ifdef TAB2
1618 	IF_TERMIOS("tab2",	&opt_tab2)
1619 #  endif
1620 #  ifdef TAB3
1621 	IF_TERMIOS("tab3",	&opt_tab3)
1622 #  endif
1623 #  if TABDLY_SHIFT >= 0
1624 	IF_TERMIOS("tabdly",	&opt_tabdly)
1625 #  endif
1626 #endif
1627 	IF_TERMIOS("tandem",	&opt_ixoff)
1628 #ifdef TCP_ABORT_THRESHOLD  /* HP_UX */
1629 	IF_TCP    ("tcp-abort-threshold",	&opt_tcp_abort_threshold)
1630 #endif
1631 #ifdef TCP_CONN_ABORT_THRESHOLD  /* HP_UX */
1632 	IF_TCP    ("tcp-conn-abort-threshold",	&opt_tcp_conn_abort_threshold)
1633 #endif
1634 #ifdef TCP_CORK
1635 	IF_TCP    ("tcp-cork",	&opt_tcp_cork)
1636 #endif
1637 #ifdef TCP_DEFER_ACCEPT	/* Linux 2.4.0 */
1638 	IF_TCP    ("tcp-defer-accept",	&opt_tcp_defer_accept)
1639 #endif
1640 #ifdef TCP_INFO	/* Linux 2.4.0 */
1641 	IF_TCP    ("tcp-info",	&opt_tcp_info)
1642 #endif
1643 #ifdef TCP_KEEPCNT	/* Linux 2.4.0 */
1644 	IF_TCP    ("tcp-keepcnt",	&opt_tcp_keepcnt)
1645 #endif
1646 #ifdef TCP_KEEPIDLE	/* Linux 2.4.0 */
1647 	IF_TCP    ("tcp-keepidle",	&opt_tcp_keepidle)
1648 #endif
1649 #ifdef TCP_KEEPINIT	/* OSF1 */
1650 	IF_TCP    ("tcp-keepinit",	&opt_tcp_keepinit)
1651 #endif
1652 #ifdef TCP_KEEPINTVL	/* Linux 2.4.0 */
1653 	IF_TCP    ("tcp-keepintvl",	&opt_tcp_keepintvl)
1654 #endif
1655 #ifdef TCP_LINGER2	/* Linux 2.4.0 */
1656 	IF_TCP    ("tcp-linger2",	&opt_tcp_linger2)
1657 #endif
1658 #ifdef TCP_MAXSEG
1659 	IF_TCP    ("tcp-maxseg",	&opt_tcp_maxseg)
1660 	IF_TCP    ("tcp-maxseg-late",	&opt_tcp_maxseg_late)
1661 #endif
1662 #ifdef TCP_MD5SIG
1663 	IF_TCP    ("tcp-md5sig",	&opt_tcp_md5sig)
1664 #endif
1665 #ifdef TCP_NODELAY
1666 	IF_TCP    ("tcp-nodelay",	&opt_tcp_nodelay)
1667 #endif
1668 #ifdef TCP_NOOPT
1669 	IF_TCP    ("tcp-noopt",		&opt_tcp_noopt)
1670 #endif
1671 #ifdef TCP_NOPUSH
1672 	IF_TCP    ("tcp-nopush",	&opt_tcp_nopush)
1673 #endif
1674 #ifdef TCP_PAWS	/* OSF1 */
1675 	IF_TCP    ("tcp-paws",		&opt_tcp_paws)
1676 #endif
1677 #ifdef TCP_QUICKACK
1678 	IF_TCP    ("tcp-quickack",	&opt_tcp_quickack)
1679 #endif
1680 #ifdef TCP_RFC1323
1681 	IF_TCP    ("tcp-rfc1323",	&opt_tcp_rfc1323)
1682 #endif
1683 #ifdef TCP_SACK_DISABLE
1684 	IF_TCP    ("tcp-sack-disable",	&opt_tcp_sack_disable)
1685 #endif
1686 #ifdef TCP_SACKENA	/* OSF1 */
1687 	IF_TCP    ("tcp-sackena",	&opt_tcp_sackena)
1688 #endif
1689 #ifdef TCP_SIGNATURE_ENABLE
1690 	IF_TCP    ("tcp-signature-enable",	&opt_tcp_signature_enable)
1691 #endif
1692 #ifdef TCP_STDURG
1693 	IF_TCP    ("tcp-stdurg",	&opt_tcp_stdurg)
1694 #endif
1695 #ifdef TCP_SYNCNT	/* Linux 2.4.0 */
1696 	IF_TCP    ("tcp-syncnt",	&opt_tcp_syncnt)
1697 #endif
1698 #ifdef TCP_TSOPTENA	/* OSF1 */
1699 	IF_TCP    ("tcp-tsoptena",	&opt_tcp_tsoptena)
1700 #endif
1701 #ifdef TCP_WINDOW_CLAMP	/* Linux 2.4.0 */
1702 	IF_TCP    ("tcp-window-clamp",	&opt_tcp_window_clamp)
1703 #endif
1704 #if WITH_LIBWRAP
1705 	IF_IPAPP  ("tcpwrap",		&opt_tcpwrappers)
1706 	IF_IPAPP  ("tcpwrap-dir",	&opt_tcpwrap_etc)
1707 	IF_IPAPP  ("tcpwrap-etc",	&opt_tcpwrap_etc)
1708 #if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE)
1709 	IF_IPAPP  ("tcpwrap-hosts-allow-table",	&opt_tcpwrap_hosts_allow_table)
1710 #endif
1711 #if WITH_LIBWRAP && defined(HAVE_HOSTS_DENY_TABLE)
1712 	IF_IPAPP  ("tcpwrap-hosts-deny-table",	&opt_tcpwrap_hosts_deny_table)
1713 #endif
1714 	IF_IPAPP  ("tcpwrapper",	&opt_tcpwrappers)
1715 	IF_IPAPP  ("tcpwrappers",	&opt_tcpwrappers)
1716 #endif
1717 	IF_TERMIOS("termios-cfmakeraw",	&opt_termios_cfmakeraw)
1718 	IF_TERMIOS("termios-rawer",	&opt_termios_rawer)
1719 #ifdef O_TEXT
1720 	IF_ANY    ("text",	&opt_o_text)
1721 #endif
1722 	IF_UNIX   ("tightsocklen",	&xioopt_unix_tightsocklen)
1723 	IF_TERMIOS("time",	&opt_vtime)
1724 #ifdef SO_TIMESTAMP
1725 	IF_SOCKET ("timestamp",	&opt_so_timestamp)
1726 #endif
1727 	IF_TERMIOS("tiocsctty",	&opt_tiocsctty)
1728 #if WITH_FS && defined(FS_TOPDIR_FL)
1729 	IF_ANY    ("topdir",	&opt_fs_topdir)
1730 #endif
1731 	IF_IP     ("tos",	&opt_ip_tos)
1732 	IF_TERMIOS("tostop",	&opt_tostop)
1733 #ifdef IP_TRANSPARENT
1734 	IF_IP     ("transparent",    &opt_ip_transparent)
1735 #endif
1736 	IF_OPEN   ("trunc",	&opt_o_trunc)
1737 #if HAVE_FTRUNCATE64
1738 	IF_ANY    ("truncate",	&opt_ftruncate64)
1739 #else
1740 	IF_ANY    ("truncate",	&opt_ftruncate32)
1741 #endif
1742 #ifdef TCP_TSOPTENA	/* OSF1 */
1743 	IF_TCP    ("tsoptena",	&opt_tcp_tsoptena)
1744 #endif
1745 	IF_IP     ("ttl",	&opt_ip_ttl)
1746 	IF_TUN    ("tun-device",	&opt_tun_device)
1747 	IF_TUN    ("tun-name",	&opt_tun_name)
1748 	IF_TUN    ("tun-no-pi",	&opt_iff_no_pi)
1749 	IF_TUN    ("tun-type",	&opt_tun_type)
1750 	IF_SOCKET ("type",	&opt_so_type)
1751 	IF_ANY    ("uid",	&opt_user)
1752 	IF_NAMED  ("uid-e",	&opt_user_early)
1753 	IF_ANY    ("uid-l",	&opt_user_late)
1754 	IF_NAMED  ("umask",	&opt_umask)
1755 	IF_IP6    ("unicast-hops",	&opt_ipv6_unicast_hops)
1756 	IF_UNIX   ("unix-tightsocklen",	&xioopt_unix_tightsocklen)
1757 	IF_NAMED  ("unlink",	&opt_unlink)
1758 	IF_NAMED  ("unlink-close",	&opt_unlink_close)
1759 	IF_NAMED  ("unlink-early",	&opt_unlink_early)
1760 	IF_NAMED  ("unlink-late",	&opt_unlink_late)
1761 #if WITH_FS && defined(FS_UNRM_FL)
1762 	IF_ANY    ("unrm",		&opt_fs_unrm)
1763 #endif
1764 	IF_TUN    ("up",	&opt_iff_up)
1765 #ifdef SO_USE_IFBUFS
1766 	IF_SOCKET ("use-ifbufs",	&opt_so_use_ifbufs)
1767 	IF_SOCKET ("useifbufs",		&opt_so_use_ifbufs)
1768 #endif /* SO_USE_IFBUFS */
1769 #ifdef SO_USELOOPBACK /* AIX433, Solaris */
1770 	IF_SOCKET ("useloopback",	&opt_so_useloopback)
1771 #endif /* SO_USELOOPBACK */
1772 	IF_ANY    ("user",	&opt_user)
1773 	IF_NAMED  ("user-early",	&opt_user_early)
1774 	IF_ANY    ("user-late",	&opt_user_late)
1775 #if HAVE_RESOLV_H
1776 	IF_IP     ("usevc",	&opt_res_usevc)
1777 #endif /* HAVE_RESOLV_H */
1778 #ifdef IPV6_V6ONLY
1779 	IF_IP6    ("v6only",	&opt_ipv6_v6only)
1780 #endif
1781 #ifdef VDISCARD
1782 	IF_TERMIOS("vdiscard",	&opt_vdiscard)
1783 #endif
1784 #ifdef VDSUSP	/* HP-UX */
1785 	IF_TERMIOS("vdsusp",	&opt_vdsusp)
1786 #endif
1787 	IF_TERMIOS("veof",	&opt_veof)
1788 	IF_TERMIOS("veol",	&opt_veol)
1789 	IF_TERMIOS("veol2",	&opt_veol2)
1790 	IF_TERMIOS("verase",	&opt_verase)
1791 	IF_OPENSSL("verify",	&opt_openssl_verify)
1792 	IF_TERMIOS("vintr",	&opt_vintr)
1793 	IF_TERMIOS("vkill",	&opt_vkill)
1794 	IF_TERMIOS("vlnext",	&opt_vlnext)
1795 	IF_TERMIOS("vmin",	&opt_vmin)
1796 	IF_TERMIOS("vquit",	&opt_vquit)
1797 #ifdef VREPRINT
1798 	IF_TERMIOS("vreprint",	&opt_vreprint)
1799 #endif
1800 	IF_TERMIOS("vstart",	&opt_vstart)
1801 	IF_TERMIOS("vstop",	&opt_vstop)
1802 	IF_TERMIOS("vsusp",	&opt_vsusp)
1803 #ifdef VSWTC
1804 	IF_TERMIOS("vswtc",	&opt_vswtc)
1805 #endif
1806 #ifdef VTDLY
1807 #  ifdef VT0
1808 	IF_TERMIOS("vt0",	&opt_vt0)
1809 #  endif
1810 #  ifdef VT1
1811 	IF_TERMIOS("vt1",	&opt_vt1)
1812 #  endif
1813 	IF_TERMIOS("vtdly",	&opt_vtdly)
1814 #endif
1815 	IF_TERMIOS("vtime",	&opt_vtime)
1816 #ifdef VWERASE
1817 	IF_TERMIOS("vwerase",	&opt_vwerase)
1818 #endif
1819 #if HAVE_PTY && HAVE_POLL
1820 	IF_PTY    ("wait-slave",	&opt_pty_wait_slave)
1821 #endif /* HAVE_PTY && HAVE_POLL */
1822 	IF_ANY    ("waitlock",	&opt_waitlock)
1823 #if HAVE_PTY && HAVE_POLL
1824 	IF_PTY    ("waitslave",	&opt_pty_wait_slave)
1825 #endif /* HAVE_PTY && HAVE_POLL */
1826 #ifdef VWERASE
1827 	IF_TERMIOS("werase",	&opt_vwerase)
1828 #endif
1829 #ifdef TCP_WINDOW_CLAMP	/* Linux 2.4.0 */
1830 	IF_TCP    ("window-clamp",	&opt_tcp_window_clamp)
1831 #endif
1832 #if WITH_LIBWRAP
1833 	IF_IPAPP  ("wrap",		&opt_tcpwrappers)
1834 #endif
1835 	IF_OPEN   ("wronly",	&opt_o_wronly)
1836 #ifdef XCASE
1837 	IF_TERMIOS("xcase",	&opt_xcase)
1838 #endif
1839 #if defined(TABDLY) && defined(XTABS)
1840 	IF_TERMIOS("xtabs",	&opt_xtabs)
1841 #endif
1842 	{ NULL }
1843 } ;
1844 
1845 
1846 /* walks the text argument a and writes its options that conform to groups
1847    to the array opts. Uses the option table 'optionnames'.
1848    returns 0 on success, -1 on error, 1 on unknown/wrong option
1849 */
parseopts(const char ** a,unsigned int groups,struct opt ** opts)1850 int parseopts(const char **a, unsigned int groups, struct opt **opts) {
1851 
1852    return parseopts_table(a, groups, opts, optionnames,
1853 			  sizeof(optionnames)/sizeof(struct optname)-1);
1854 }
1855 
1856 
1857 /* walks the text argument a and writes its options that conform to groups
1858    to the array opts. Uses the specified option table.
1859    returns 0 on success, -1 on error, 1 on unknown/wrong option
1860 */
parseopts_table(const char ** a,unsigned int groups,struct opt ** opts,const struct optname optionnames[],size_t optionnum)1861 int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
1862 	      const struct optname optionnames[], size_t optionnum) {
1863    int i=0;
1864    struct opt *opt;
1865    bool assign;
1866    const char *a0 = *a;
1867    unsigned long ulongval;
1868    long slongval;
1869    long long slonglongval;
1870    char token[2048], *tokp;  size_t len;
1871    int parsres;
1872    int result;
1873    uint8_t optbuf[256];  size_t optlen;
1874    const char *endkey[6+1];
1875    const char *endval[5+1];
1876    const char *assign_str = "=";
1877    const char *hquotes[] = {
1878       "'",
1879       NULL
1880    } ;
1881    const char *squotes[] = {
1882       "\"",
1883       NULL
1884    } ;
1885    const char *nests[] = {
1886       "(", ")",
1887       "[", "]",
1888       "{", "}",
1889       NULL
1890    } ;
1891 
1892    i = 0;
1893    /*endkey[i++] = xioopts.chainsep;*/	/* default: "|" */
1894    endkey[i++] = xioopts.pipesep;		/* default: "!!" */
1895    endkey[i++] = ","/*xioopts.comma*/;		/* default: "," */
1896    endkey[i++] = "=";
1897    endkey[i++] = NULL;
1898 
1899    i = 0;
1900    /*endval[i++] = xioopts.chainsep;*/	/* default: "|" */
1901    endval[i++] = xioopts.pipesep;		/* default: "!!" */
1902    endval[i++] = ","/*xioopts.comma*/;		/* default: "," */
1903    endval[i++] = NULL;
1904 
1905    i = 0;
1906    *opts = Malloc((i+8)*sizeof(struct opt));
1907    if (*opts == NULL) {
1908       return -1;
1909    }
1910    if (*a == NULL) {
1911       (*opts)[i].desc = ODESC_END;
1912       return 0;
1913    }
1914 
1915    while (true) {
1916       const struct optname *ent;
1917 
1918       if (a == NULL || *a == NULL || **a == '\0')
1919 	 break;
1920 
1921       while (!strncmp(*a, ",", strlen(",")))  { (*a) += strlen(","); }
1922       a0 = *a;
1923 
1924       len = sizeof(token);  tokp = token;
1925       parsres =
1926 	 nestlex(a, &tokp, &len, endkey, hquotes, squotes, nests,
1927 		 true, true, false);
1928       if (parsres < 0) {
1929 	 Error1("option too long:  \"%s\"", *a);
1930 	 return -1;
1931       } else if (parsres > 0) {
1932 	 Error1("syntax error in \"%s\"", *a);
1933 	 return -1;
1934       }
1935       if (tokp == token) {
1936 	 /* no option found */
1937 	 break;
1938       }
1939       *tokp = '\0';
1940 
1941       ent = (struct optname *)
1942 	 keyw((struct wordent *)optionnames, token, optionnum);
1943       if (ent == NULL) {
1944 	 Error1("parseopts_table(): unknown option \"%s\"", token);
1945 	 continue;
1946       }
1947 
1948       if (!(ent->desc->group & groups) && !(ent->desc->group & GROUP_ANY) &&
1949 	  !xioopts_ignoregroups) {
1950 	 Error1("parseopts_table(): option \"%s\" not supported with this address type",
1951 		token /*a0*/);
1952 	 Info2("parseopts_table()  groups=%08x, ent->group=%08x",
1953 	       groups, ent->desc->group);
1954 #if 0
1955 	 continue;
1956 #endif
1957       }
1958       (*opts)[i].desc = ent->desc;
1959 
1960       if (!strncmp(*a, assign_str, strlen(assign_str))) {
1961 	 /* there is an assignment (mostly "=") */
1962 	 (*a) += strlen(assign_str);
1963 	 len = sizeof(token);  tokp = token;
1964 	 parsres =
1965 	    nestlex(a, &tokp, &len, endval, hquotes, squotes, nests,
1966 		    true, true, false);
1967 	 if (parsres < 0) {
1968 	    Error1("option too long:  \"%s\"", *a);
1969 	    return -1;
1970 	 } else if (parsres > 0) {
1971 	    Error1("syntax error in \"%s\"", *a);
1972 	    return -1;
1973 	 }
1974 	 *tokp = '\0';
1975 	 assign = true;
1976 
1977       } else {
1978 	 assign = false;
1979       }
1980       opt = &(*opts)[i];
1981 
1982       switch (ent->desc->type) {
1983       case TYPE_CONST:
1984 	 if (assign) {
1985 	    Error1("no value permitted for option \"%s\"",
1986 		   ent->desc->defname);
1987 	    continue;
1988 	 }
1989 	 Info1("setting option \"%s\"", ent->desc->defname);
1990 	 break;
1991       case TYPE_BIN:
1992 	 if (!assign) { Error1("option \"%s\": value required", a0);
1993 	    continue; }
1994 	 optlen = 0;
1995 	 if ((result = dalan(token, optbuf, &optlen, sizeof(optbuf), 'i')) != 0) {
1996 	    Error1("parseopts_table(): problem with \"%s\" data", token);
1997 	    continue;
1998 	 }
1999 	 if (((*opts)[i].value.u_bin.b_data = memdup(optbuf, optlen)) == NULL) {
2000 	    Error1("memdup(, "F_Zu"): out of memory", optlen);
2001 	    return -1;
2002 	 }
2003 	 (*opts)[i].value.u_bin.b_len = optlen;
2004 	 break;
2005       case TYPE_BYTE:
2006 	 if (assign) {
2007 	  unsigned long ul;
2008 	  char *rest;
2009 	  ul = strtoul(token, &rest/*!*/, 0);
2010 	  if (ul > UCHAR_MAX) {
2011 	    Error3("parseopts_table(%s): byte value exceeds limit (%lu vs. %u), using max",
2012 		   a0, ul, UCHAR_MAX);
2013 	    (*opts)[i].value.u_byte = UCHAR_MAX;
2014 	  } else {
2015 	    (*opts)[i].value.u_byte = ul;
2016 	  }
2017 	 } else {
2018 	    (*opts)[i].value.u_byte = 1;
2019 	 }
2020 	 Info2("setting option \"%s\" to %d", ent->desc->defname,
2021 	       (*opts)[i].value.u_byte);
2022 	 break;
2023 #if HAVE_BASIC_OFF_T==3
2024       case TYPE_OFF32:
2025 #endif
2026       case TYPE_INT:
2027 	 if (assign) {
2028 	    char *rest;
2029 	    (*opts)[i].value.u_int = strtoul(token, &rest/*!*/, 0);
2030 	 } else {
2031 	    (*opts)[i].value.u_int = 1;
2032 	 }
2033 	 Info2("setting option \"%s\" to %d", ent->desc->defname,
2034 	       (*opts)[i].value.u_int);
2035 	 break;
2036       case TYPE_BOOL:
2037 	 if (!assign) {
2038 	    (*opts)[i].value.u_bool = 1;
2039 	 } else {
2040 	    char *rest;
2041 	    (*opts)[i].value.u_bool = strtoul(token, &rest, 0);
2042 	    if (rest && *rest) {
2043 	       Error1("error in option \"%s\": \"0\" or \"1\" required", a0);
2044 	    }
2045 	 }
2046 	 Info2("setting option \"%s\" to %d", ent->desc->defname,
2047 	       (*opts)[i].value.u_bool);
2048 	 break;
2049 
2050 #if HAVE_BASIC_SIZE_T==4
2051       case TYPE_SIZE_T:
2052 #endif
2053       case TYPE_UINT:
2054 	 if (!assign) {
2055 	    (*opts)[i].value.u_uint = 1;
2056 	 } else {
2057 	    char *rest;
2058 	    ulongval = strtoul(token, &rest/*!*/, 0);
2059 	    if (ulongval > UINT_MAX) {
2060 	       Error3("parseopts_table(%s): unsigned int value exceeds limit (%lu vs. %u), using max",
2061 		      a0, ulongval, UINT_MAX);
2062 	    }
2063 	    (*opts)[i].value.u_uint = ulongval;
2064 	 }
2065 	 Info2("setting option \"%s\" to %u", ent->desc->defname,
2066 	       (*opts)[i].value.u_uint);
2067 	 break;
2068 
2069 #if HAVE_BASIC_SIZE_T==2
2070       case TYPE_SIZE_T:
2071 #endif
2072       case TYPE_USHORT:
2073 	 if (!assign) {
2074 	    (*opts)[i].value.u_ushort = 1;
2075 	 } else {
2076 	    char *rest;
2077 	    ulongval = strtoul(token, &rest/*!*/, 0);
2078 	    if (ulongval > USHRT_MAX) {
2079 	       Error3("parseopts_table(%s): unsigned short value exceeds limit (%lu vs. %u), using max",
2080 		      a0, ulongval, USHRT_MAX);
2081 	    }
2082 	    (*opts)[i].value.u_ushort = ulongval;
2083 	 }
2084 	 Info2("setting option \"%s\" to %u", ent->desc->defname,
2085 	       (*opts)[i].value.u_ushort);
2086 	 break;
2087 
2088 #if HAVE_BASIC_OFF_T==5
2089       case TYPE_OFF32:
2090 #endif
2091 #if HAVE_STAT64 && defined(HAVE_BASIC_OFF64_T) && HAVE_BASIC_OFF64_T==5
2092       case TYPE_OFF64:
2093 #endif
2094       case TYPE_LONG:
2095 	 if (!assign) {
2096 	    (*opts)[i].value.u_long = 1;
2097 	 } else {
2098 	    char *rest;
2099 	    slongval = strtol(token, &rest, 0);
2100 	    (*opts)[i].value.u_long = slongval;
2101 	 }
2102 	 Info2("setting option \"%s\" to %lu", ent->desc->defname,
2103 	       (*opts)[i].value.u_long);
2104 	 break;
2105 
2106 #if HAVE_BASIC_SIZE_T==6
2107       case TYPE_SIZE_T:
2108 #endif
2109       case TYPE_ULONG:
2110 	 if (!assign) {
2111 	    (*opts)[i].value.u_ulong = 1;
2112 	 } else {
2113 	    char *rest;
2114 	    ulongval = strtoul(token, &rest, 0);
2115 	    (*opts)[i].value.u_ulong = ulongval;
2116 	 }
2117 	 Info2("setting option \"%s\" to %lu", ent->desc->defname,
2118 	       (*opts)[i].value.u_ulong);
2119 	 break;
2120 
2121 #if HAVE_BASIC_OFF_T==7
2122       case TYPE_OFF32:
2123 #endif
2124 #if HAVE_TYPE_LONGLONG
2125       case TYPE_LONGLONG:
2126 #  if HAVE_STAT64 && defined(HAVE_BASIC_OFF64_T) && HAVE_BASIC_OFF64_T==7
2127       case TYPE_OFF64:
2128 #  endif
2129 	 if (!assign) {
2130 	    (*opts)[i].value.u_longlong = 1;
2131 	 } else {
2132 	    char *rest;
2133 #  if HAVE_STRTOLL
2134 	    slonglongval = strtoll(token, &rest, 0);
2135 #  else
2136 	    /* in this case, input value range is limited */
2137 	    slonglongval = strtol(token, &rest, 0);
2138 #  endif /* HAVE_STRTOLL */
2139 	    (*opts)[i].value.u_longlong = slonglongval;
2140 	 }
2141 	 Info2("setting option \"%s\" to %Lu", ent->desc->defname,
2142 	       (*opts)[i].value.u_longlong);
2143 	 break;
2144 #endif /* HAVE_TYPE_LONGLONG */
2145 
2146       case TYPE_UIDT:
2147 	 if (!assign) {
2148 	    Error1("option \"%s\": value required", a0);
2149 	    continue;
2150 	 }
2151 	 if (isdigit((*token)&0xff)) {
2152 	    char *rest;
2153 	    (*opts)[i].value.u_uidt = strtoul(token, &rest/*!*/, 0);
2154 	 } else {
2155 	    struct passwd *pwd;
2156 	    if ((pwd = getpwnam(token)) == NULL) {
2157 	       Error1("getpwnam(\"%s\"): no such user", token);
2158 	       continue;
2159 	    }
2160 	    (*opts)[i].value.u_uidt = getpwnam(token)->pw_uid;
2161 	 }
2162 	 Info2("setting option \"%s\" to %u", ent->desc->defname,
2163 	       (*opts)[i].value.u_uidt);
2164 	 break;
2165 
2166       case TYPE_GIDT:
2167 	 if (!assign) { Error1("option \"%s\": value required", a0);
2168 	    continue; }
2169 	 if (isdigit((token[0])&0xff)) {
2170 	    char *rest;
2171 	    (*opts)[i].value.u_gidt = strtoul(token, &rest/*!*/, 0);
2172 	 } else {
2173 	    struct group *grp;
2174 	    grp = getgrnam(token);
2175 	    if (grp == NULL) {
2176 	       Error1("getgrnam(\"%s\"): no such group", token);
2177 	       continue;
2178 	    }
2179 	    (*opts)[i].value.u_gidt = grp->gr_gid;
2180 	 }
2181 	 Info2("setting option \"%s\" to %u", ent->desc->defname,
2182 	       (*opts)[i].value.u_gidt);
2183 	 break;
2184 
2185       case TYPE_MODET:
2186 	 if (!assign) { Error1("option \"%s\": value required", a0);
2187 	    continue;
2188 	 }
2189 	 {
2190 	    char *rest;
2191 	    (*opts)[i].value.u_modet = strtoul(token, &rest/*!*/, 8);
2192 	 }
2193 	 Info2("setting option \"%s\" to %u", ent->desc->defname,
2194 	       (*opts)[i].value.u_modet);
2195 	 break;
2196 
2197       case TYPE_STRING:
2198 	 if (!assign) {
2199 	    Error1("option \"%s\": value required", a0);
2200 	    continue;
2201 	 }
2202 	 if (((*opts)[i].value.u_string = strdup(token)) == NULL) {
2203 	    Error("out of memory"); return -1;
2204 	 }
2205 	 Info2("setting option \"%s\" to \"%s\"", ent->desc->defname,
2206 	       (*opts)[i].value.u_string);
2207 	 break;
2208 
2209       case TYPE_STRING_NULL:
2210 	 if (!assign) {
2211 	    (*opts)[i].value.u_string = NULL;
2212 	    Info1("setting option \"%s\" to NULL", ent->desc->defname);
2213 	 } else {
2214 	    (*opts)[i].value.u_string = strdup(token);
2215 	    Info2("setting option \"%s\" to \"%s\"", ent->desc->defname,
2216 		  (*opts)[i].value.u_string);
2217 	 }
2218 	 break;
2219 
2220 #if LATER
2221       case TYPE_INT3:
2222 
2223 	 break;
2224 #endif
2225 
2226       case TYPE_TIMEVAL:
2227 	 if (!assign) {
2228 	    Error1("option \"%s\": value required", a0);
2229 	    continue;
2230 	 } else {
2231 	    double val;
2232 	    val = strtod(token, NULL);
2233 	    if (val == HUGE_VAL || val == -HUGE_VAL ||
2234 		val == 0.0 && errno == ERANGE) {
2235 	       Error2("strtod(\"%s\", NULL): %s", token, strerror(errno));
2236 	       val = 0.0;
2237 	    }
2238 	    (*opts)[i].value.u_timeval.tv_sec  = val;
2239 	    (*opts)[i].value.u_timeval.tv_usec =
2240 	       (val-(*opts)[i].value.u_timeval.tv_sec+0.0000005) * 1000000;
2241 	 }
2242 	 break;
2243 
2244 #if HAVE_STRUCT_TIMESPEC
2245       case TYPE_TIMESPEC:
2246 	 if (!assign) {
2247 	    Error1("option \"%s\": value required", a0);
2248 	    continue;
2249 	 } else {
2250 	    double val;
2251 	    val = strtod(token, NULL);
2252 	    if (val == HUGE_VAL || val == -HUGE_VAL ||
2253 		val == 0.0 && errno == ERANGE) {
2254 	       Error2("strtod(\"%s\", NULL): %s", token, strerror(errno));
2255 	       val = 0.0;
2256 	    }
2257 	    (*opts)[i].value.u_timespec.tv_sec  = val;
2258 	    (*opts)[i].value.u_timespec.tv_nsec =
2259 	       (val-(*opts)[i].value.u_timespec.tv_sec) * 1000000000.;
2260 	 }
2261 	 break;
2262 #endif /* HAVE_STRUCT_TIMESPEC */
2263 
2264 #if HAVE_STRUCT_LINGER
2265       case TYPE_LINGER:
2266 	 if (!assign) {
2267 	    Error1("option \"%s\": value required", a0);
2268 	    continue;
2269 	 }
2270 	 (*opts)[i].value.u_linger.l_onoff = 1;
2271 	 {
2272 	    char *rest;
2273 	    (*opts)[i].value.u_linger.l_linger = strtoul(token, &rest/*!*/, 0);
2274 	 }
2275 	 Info3("setting option \"%s\" to {%d,%d}", ent->desc->defname,
2276 	       (*opts)[i].value.u_linger.l_onoff,
2277 	       (*opts)[i].value.u_linger.l_linger);
2278 	 break;
2279 #endif /* HAVE_STRUCT_LINGER */
2280 
2281       case TYPE_INT_INT:
2282       case TYPE_INT_INTP:
2283 	 if (!assign) {
2284 	    Error1("option \"%s\": values required", a0);
2285 	    continue;
2286 	 }
2287 	 {
2288 	    char *rest;
2289 	    (*opts)[i].value.u_int = strtoul(token, &rest, 0);
2290 	    if (*rest != ':') {
2291 	       Error1("option \"%s\": 2 arguments required",
2292 		      ent->desc->defname);
2293 	    }
2294 	    ++rest;
2295 	    (*opts)[i].value2.u_int = strtoul(rest, &rest, 0);
2296 	 }
2297 	 Info3("setting option \"%s\" to %d:%d", ent->desc->defname,
2298 	       (*opts)[i].value.u_int, (*opts)[i].value2.u_int);
2299 	 break;
2300 
2301       case TYPE_INT_BIN:
2302 	 if (!assign) {
2303 	    Error1("option \"%s\": values required", a0);
2304 	    continue;
2305 	 }
2306 	 {
2307 	    char *rest;
2308 	    (*opts)[i].value.u_int = strtoul(token, &rest, 0);
2309 	    if (*rest != ':') {
2310 	       Error1("option \"%s\": 2 arguments required",
2311 		      ent->desc->defname);
2312 	    }
2313 	    ++rest;
2314 	    optlen = 0;
2315 	    if ((result = dalan(rest, optbuf, &optlen, sizeof(optbuf), 'i')) != 0) {
2316 	       Error1("parseopts_table(): problem with \"%s\" data", rest);
2317 	       continue;
2318 	    }
2319 	    if (((*opts)[i].value2.u_bin.b_data = memdup(optbuf, optlen)) == NULL) {
2320 	       Error1("memdup(, "F_Zu"): out of memory", optlen);
2321 	       return -1;
2322 	    }
2323 	    (*opts)[i].value2.u_bin.b_len = optlen;
2324 	 }
2325 	 Info2("setting option \"%s\" to %d:..."/*!!!*/, ent->desc->defname,
2326 	       (*opts)[i].value.u_int);
2327 	 break;
2328 
2329       case TYPE_INT_STRING:
2330 	 if (!assign) {
2331 	    Error1("option \"%s\": values required", a0);
2332 	    continue;
2333 	 }
2334 	 {
2335 	    char *rest;
2336 	    (*opts)[i].value.u_int = strtoul(token, &rest, 0);
2337 	    if (*rest != ':') {
2338 	       Error1("option \"%s\": 2 arguments required",
2339 		      ent->desc->defname);
2340 	    }
2341 	    ++rest;
2342 	    if (((*opts)[i].value2.u_string = strdup(rest)) == NULL) {
2343 	       Error("out of memory"); return -1;
2344 	    }
2345 	 }
2346 	 Info3("setting option \"%s\" to %d:\"%s\"", ent->desc->defname,
2347 	       (*opts)[i].value.u_int, (*opts)[i].value2.u_string);
2348 	 break;
2349 
2350       case TYPE_INT_INT_INT:
2351 	 if (!assign) {
2352 	    Error1("option \"%s\": values required", a0);
2353 	    continue;
2354 	 }
2355 	 {
2356 	    char *rest;
2357 	    (*opts)[i].value.u_int = strtoul(token, &rest, 0);
2358 	    if (*rest != ':') {
2359 	       Error1("option \"%s\": 3 arguments required",
2360 		      ent->desc->defname);
2361 	    }
2362 	    ++rest;
2363 	    (*opts)[i].value2.u_int = strtoul(rest, &rest, 0);
2364 	    if (*rest != ':') {
2365 	       Error1("option \"%s\": 3 arguments required",
2366 		      ent->desc->defname);
2367 	    }
2368 	    ++rest;
2369 	    (*opts)[i].value3.u_int = strtoul(rest, &rest, 0);
2370 	 }
2371 	 Info4("setting option \"%s\" to %d:%d:%d", ent->desc->defname,
2372 	       (*opts)[i].value.u_int, (*opts)[i].value2.u_int, (*opts)[i].value3.u_int);
2373 	 break;
2374 
2375       case TYPE_INT_INT_BIN:
2376       case TYPE_INT_INT_GENERIC:
2377 	 if (!assign) {
2378 	    Error1("option \"%s\": values required", a0);
2379 	    continue;
2380 	 }
2381 	 {
2382 	    char *rest;
2383 	    (*opts)[i].value.u_int = strtoul(token, &rest, 0);
2384 	    if (*rest != ':') {
2385 	       Error1("option \"%s\": 3 arguments required",
2386 		      ent->desc->defname);
2387 	    }
2388 	    ++rest;
2389 	    (*opts)[i].value2.u_int = strtoul(rest, &rest, 0);
2390 	    if (*rest != ':') {
2391 	       Error1("option \"%s\": 3 arguments required",
2392 		      ent->desc->defname);
2393 	    }
2394 	    ++rest;
2395 	    optlen = 0;
2396 	    if ((result = dalan(rest, optbuf, &optlen, sizeof(optbuf), 'i')) != 0) {
2397 	       Error1("parseopts_table(): problem with \"%s\" data", rest);
2398 	       continue;
2399 	    }
2400 	    if (((*opts)[i].value3.u_bin.b_data = memdup(optbuf, optlen)) == NULL) {
2401 	       Error1("memdup(, "F_Zu"): out of memory", optlen);
2402 	       return -1;
2403 	    }
2404 	    (*opts)[i].value3.u_bin.b_len = optlen;
2405 	 }
2406 	 Info3("setting option \"%s\" to %d:%d:..."/*!!!*/, ent->desc->defname,
2407 	       (*opts)[i].value.u_int, (*opts)[i].value2.u_int);
2408 	 break;
2409 
2410       case TYPE_INT_INT_STRING:
2411 	 if (!assign) {
2412 	    Error1("option \"%s\": values required", a0);
2413 	    continue;
2414 	 }
2415 	 {
2416 	    char *rest;
2417 	    (*opts)[i].value.u_int = strtoul(token, &rest, 0);
2418 	    if (*rest != ':') {
2419 	       Error1("option \"%s\": 3 arguments required",
2420 		      ent->desc->defname);
2421 	    }
2422 	    ++rest;
2423 	    (*opts)[i].value2.u_int = strtoul(rest, &rest, 0);
2424 	    if (*rest != ':') {
2425 	       Error1("option \"%s\": 3 arguments required",
2426 		      ent->desc->defname);
2427 	    }
2428 	    ++rest;
2429 	    if (((*opts)[i].value3.u_string = strdup(rest)) == NULL) {
2430 	       Error("out of memory"); return -1;
2431 	    }
2432 	 }
2433 	 Info4("setting option \"%s\" to %d:%d:\"%s\"", ent->desc->defname,
2434 	       (*opts)[i].value.u_int, (*opts)[i].value2.u_int,
2435 	       (*opts)[i].value3.u_string);
2436 	 break;
2437 #if defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)
2438 
2439       case TYPE_IP_MREQN:
2440 	 {
2441 	    /* we do not resolve the addresses here because we do not yet know
2442 	       if we are coping with a IPv4 or IPv6 socat address */
2443 	    const char *ends[] = { ":", NULL };
2444 	    const char *nests[] = { "[","]", NULL };
2445 	    char buff[512], *buffp=buff; size_t bufspc = sizeof(buff)-1;
2446 
2447 	    /* parse first IP address, expect ':' */
2448 	    tokp = token;
2449 	    /*! result= */
2450 	    parsres =
2451 	       nestlex((const char **)&tokp, &buffp, &bufspc,
2452 		       ends, NULL, NULL, nests,
2453 		       true, false, false);
2454 	    if (parsres < 0) {
2455 	       Error1("option too long:  \"%s\"", *a);
2456 	       return -1;
2457 	    } else if (parsres > 0) {
2458 	       Error1("syntax error in \"%s\"", *a);
2459 	       return -1;
2460 	    }
2461 	    if (*tokp != ':') {
2462 	       Error1("syntax in option %s: missing ':'", token);
2463 	    }
2464 	    *buffp++ = '\0';
2465 	    (*opts)[i].value.u_ip_mreq.multiaddr = strdup(buff); /*!!! NULL */
2466 
2467 	    ++tokp;
2468 	    /* parse second IP address, expect ':' or '\0'' */
2469 	    buffp = buff;
2470 	    /*! result= */
2471 	    parsres =
2472 	       nestlex((const char **)&tokp, &buffp, &bufspc,
2473 		       ends, NULL, NULL, nests,
2474 		       true, false, false);
2475 	    if (parsres < 0) {
2476 	       Error1("option too long:  \"%s\"", *a);
2477 	       return -1;
2478 	    } else if (parsres > 0) {
2479 	       Error1("syntax error in \"%s\"", *a);
2480 	       return -1;
2481 	    }
2482 	    *buffp++ = '\0';
2483 	    (*opts)[i].value.u_ip_mreq.param2 = strdup(buff); /*!!! NULL */
2484 
2485 #if HAVE_STRUCT_IP_MREQN
2486 	    if (*tokp++ == ':') {
2487 	       strncpy((*opts)[i].value.u_ip_mreq.ifindex, tokp, IF_NAMESIZE);	/* ok */
2488 	       Info4("setting option \"%s\" to {\"%s\",\"%s\",\"%s\"}",
2489 		     ent->desc->defname,
2490 		     (*opts)[i].value.u_ip_mreq.multiaddr,
2491 		     (*opts)[i].value.u_ip_mreq.param2,
2492 		     (*opts)[i].value.u_ip_mreq.ifindex);
2493 	    } else {
2494 	       (*opts)[i].value.u_ip_mreq.ifindex[0] = '\0';
2495 	       Info3("setting option \"%s\" to {\"%s\",\"%s\"}",
2496 		     ent->desc->defname,
2497 		     (*opts)[i].value.u_ip_mreq.multiaddr,
2498 		     (*opts)[i].value.u_ip_mreq.param2);
2499 	    }
2500 #else /* !HAVE_STRUCT_IP_MREQN */
2501 	    Info3("setting option \"%s\" to {0x%08x,0x%08x}",
2502 		  ent->desc->defname,
2503 		  (*opts)[i].value.u_ip_mreq.multiaddr,
2504 		  (*opts)[i].value.u_ip_mreq.param2);
2505 #endif /* !HAVE_STRUCT_IP_MREQN */
2506 	 }
2507 	 break;
2508 #endif /* defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) */
2509 
2510 #if HAVE_STRUCT_IP_MREQ_SOURCE
2511       case TYPE_IP_MREQ_SOURCE:
2512 	 xiotype_ip_add_source_membership(token, ent, opt);
2513 	 break;
2514 #endif
2515 
2516 #if WITH_IP4
2517       case TYPE_IP4NAME:
2518 	 {
2519 	    struct sockaddr_in sa;  socklen_t salen = sizeof(sa);
2520 	    const char *ends[] = { NULL };
2521 	    const char *nests[] = { "[","]", NULL };
2522 	    char buff[512], *buffp=buff; size_t bufspc = sizeof(buff)-1;
2523 
2524 	    tokp = token;
2525 	    parsres =
2526 	    nestlex((const char **)&tokp, &buffp, &bufspc,
2527 		    ends, NULL, NULL, nests,
2528 		    true, false, false);
2529 	    if (parsres < 0) {
2530 	       Error1("option too long:  \"%s\"", *a);
2531 	       return -1;
2532 	    } else if (parsres > 0) {
2533 	       Error1("syntax error in \"%s\"", *a);
2534 	       return -1;
2535 	    }
2536 	    if (*tokp != '\0') {
2537 	       Error1("trailing data in option \"%s\"", token);
2538 	    }
2539 	    *buffp = '\0';
2540 	    if (xiogetaddrinfo(buff, NULL, AF_INET, SOCK_DGRAM, IPPROTO_IP,
2541 			       (union sockaddr_union *)&sa, &salen,
2542 			       0, 0/*!!!*/) != STAT_OK) {
2543 	       opt->desc = ODESC_ERROR; continue;
2544 	    }
2545 	    opt->value.u_ip4addr = sa.sin_addr;
2546 	 }
2547 	 break;
2548 #endif /* defined(WITH_IP4) */
2549 
2550       case TYPE_GENERIC:
2551 	 if (!assign) {
2552 	    (*opts)[i].value.u_int = 1;
2553 	 } else {
2554 	    int rc;
2555 	    size_t binlen = 64; 	/*!!!*/
2556 	    if (((*opts[i]).value.u_bin.b_data = Malloc(binlen)) == NULL) Error("!!!");
2557 	    (*opts)[i].value.u_bin.b_len = 0;
2558 	    rc = dalan(token, (*opts)[i].value.u_bin.b_data,
2559 		       &(*opts)[i].value.u_bin.b_len, binlen, 'i');
2560 	    if (rc != 0) {
2561 	       Error("!!!");
2562 	    }
2563 	    //(*opts)[i].value.u_bin.b_len
2564 	 }
2565 	 break;
2566 
2567       default:
2568 	 Error2("parseopts_table(): internal error on option \"%s\": unimplemented type %d",
2569 		ent->desc->defname, ent->desc->type);
2570 	 continue;
2571       }
2572 
2573       ++i;
2574       if ((i % 8) == 0) {
2575 	 *opts = Realloc(*opts, (i+8) * sizeof(struct opt));
2576 	 if (*opts == NULL) {
2577 	    return -1;
2578 	 }
2579       }
2580    }
2581 
2582    /*(*opts)[i+1].desc = ODESC_END;*/
2583    (*opts)[i].desc = ODESC_END;
2584    return 0;
2585 }
2586 
2587 
2588 /* look for an option with the given properties
2589    return a pointer to the first matching valid option in the list
2590    Returns NULL when no matching option found */
searchopt(const struct opt * opts,unsigned int groups,enum e_phase from,enum e_phase to,enum e_func func)2591 const struct opt *searchopt(const struct opt *opts, unsigned int groups, enum e_phase from, enum e_phase to,
2592 		      enum e_func func) {
2593    int i;
2594 
2595    if (!opts)  return NULL;
2596 
2597    /* remember: struct opt are in an array */
2598    i = 0;
2599    while (opts[i].desc != ODESC_END) {
2600       if (opts[i].desc != ODESC_DONE &&
2601 	  (groups == 0 || (groups && (opts[i].desc->group&groups))) &&
2602 	  (from == 0 || (from <= opts[i].desc->phase)) &&
2603 	  (to   == 0 || (opts[i].desc->phase <= to)) &&
2604 	  (func == 0 || (opts[i].desc->func == func))) {
2605 	 return &opts[i];
2606       }
2607       ++i;
2608    }
2609    return NULL;
2610 }
2611 
2612 /* copy the already parsed options for repeated application, but only those
2613    matching groups ANY and <groups> */
copyopts(const struct opt * opts,unsigned int groups)2614 struct opt *copyopts(const struct opt *opts, unsigned int groups) {
2615    struct opt *new;
2616    int i, j, n;
2617 
2618    if (!opts)  return NULL;
2619 
2620    /* just count the options in the array */
2621    i = 0; while (opts[i].desc != ODESC_END) {
2622       ++i;
2623    }
2624    n = i+1;
2625 
2626    new = Malloc(n * sizeof(struct opt));
2627    if (new == NULL) {
2628       return NULL;
2629    }
2630 
2631    i = 0, j = 0;
2632    while (i < n-1) {
2633       if (opts[i].desc == ODESC_DONE) {
2634 	 new[j].desc = ODESC_DONE;
2635       } else if ((opts[i].desc->group & (GROUP_ANY&~GROUP_PROCESS)) ||
2636 		 (opts[i].desc->group & groups)) {
2637 	 new[j++] = opts[i];
2638       }
2639       ++i;
2640    }
2641    new[j].desc = ODESC_END;
2642    return new;
2643 }
2644 
2645 /* move options to a new options list
2646    move only those matching <groups> */
moveopts(struct opt * opts,unsigned int groups)2647 struct opt *moveopts(struct opt *opts, unsigned int groups) {
2648    struct opt *new;
2649    int i, j, n;
2650 
2651    if (!opts)  return NULL;
2652 
2653    /* just count the options in the array */
2654    i = 0; j = 0; while (opts[i].desc != ODESC_END) {
2655       if (opts[i].desc != ODESC_DONE &&
2656 	  opts[i].desc != ODESC_ERROR)
2657 	 ++j;
2658       ++i;
2659    }
2660    n = i;
2661 
2662    new = Malloc((j+1) * sizeof(struct opt));
2663    if (new == NULL) {
2664       return NULL;
2665    }
2666 
2667    i = 0, j = 0;
2668    while (i < n) {
2669       if (opts[i].desc == ODESC_DONE ||
2670 	  opts[i].desc == ODESC_ERROR) {
2671 	 ++i; continue;
2672       } else if (opts[i].desc->group & groups) {
2673 	 new[j++] = opts[i];
2674 	 opts[i].desc = ODESC_DONE;
2675       }
2676       ++i;
2677    }
2678    new[j].desc = ODESC_END;
2679    return new;
2680 }
2681 
2682 /* return the number of yet unconsumed options; -1 on error */
leftopts(const struct opt * opts)2683 int leftopts(const struct opt *opts) {
2684    const struct opt *opt = opts;
2685    int num = 0;
2686 
2687    if (!opts)  return 0;
2688 
2689    while (opt->desc != ODESC_END) {
2690       if (opt->desc != ODESC_DONE) {
2691 	 ++num;
2692       }
2693       ++opt;
2694    }
2695    return num;
2696 }
2697 
2698 /* show as warning which options are still unused */
showleft(const struct opt * opts)2699 int showleft(const struct opt *opts) {
2700    const struct opt *opt = opts;
2701 
2702    while (opt->desc != ODESC_END) {
2703       if (opt->desc != ODESC_DONE) {
2704 	 Warn1("showleft(): option \"%s\" not inquired", opt->desc->defname);
2705       }
2706       ++opt;
2707    }
2708    return 0;
2709 }
2710 
2711 
2712 /* determines the address group from mode_t */
2713 /* does not set GROUP_FD; cannot determine GROUP_TERMIOS ! */
_groupbits(mode_t mode)2714 int _groupbits(mode_t mode) {
2715    unsigned int result = 0;
2716 
2717    switch ((mode&S_IFMT)>>12) {
2718    case (S_IFIFO>>12):	/* 1, FIFO */
2719       result = GROUP_FIFO;   break;
2720    case (S_IFCHR>>12):	/* 2, character device */
2721       result = GROUP_CHR|GROUP_TERMIOS;    break;
2722    case (S_IFDIR>>12):	/* 4, directory !!! not supported */
2723       result = GROUP_NONE;   break;
2724    case (S_IFBLK>>12):	/* 6, block device */
2725       result = GROUP_BLK;    break;
2726    case (S_IFREG>>12):	/* 8, regular file */
2727       result = GROUP_REG;    break;
2728    case (S_IFLNK>>12):	/* 10, symbolic link !!! not supported */
2729       result = GROUP_NONE;   break;
2730 #ifdef S_IFSOCK
2731    case (S_IFSOCK>>12): /* 12, socket */
2732       result = GROUP_SOCKET|GROUP_SOCK_UNIX; break;
2733 #else
2734    default: /* some systems (pure POSIX.1) do not know S_IFSOCK */
2735       result = GROUP_SOCKET|GROUP_SOCK_UNIX; break;
2736 #endif
2737    }
2738    Debug2("_groupbits(%d) -> %d", mode, result);
2739    return result;
2740 }
2741 
2742 /* does not set GROUP_FD */
groupbits(int fd)2743 int groupbits(int fd) {
2744 #if HAVE_STAT64
2745    struct stat64 buf;
2746 #else
2747    struct stat buf;
2748 #endif /* !HAVE_STAT64 */
2749    int result;
2750 
2751    if (
2752 #if HAVE_STAT64
2753        Fstat64(fd, &buf) < 0
2754 #else
2755        Fstat(fd, &buf) < 0
2756 #endif /* !HAVE_STAT64 */
2757       ) {
2758       Error4("groupbits(%d): fstat(%d, %p): %s",
2759 	     fd, fd, &buf, strerror(errno));
2760       return -1;
2761    }
2762    result = _groupbits(buf.st_mode&S_IFMT);
2763    if (result == GROUP_CHR) {
2764       if (Isatty(fd) > 0) {
2765 	 result |= GROUP_TERMIOS;
2766       }
2767    }
2768    return result;
2769 }
2770 
2771 #if 0	/* currently not used */
2772 int retropt(struct opt *opts, int optcode, union integral *result) {
2773    struct opt *opt = opts;
2774 
2775    while (opt->desc != ODESC_END) {
2776       if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2777 	 *result = opt->value;
2778 	 opt->desc = ODESC_DONE;
2779 	 return 0;
2780       }
2781       ++opt;
2782    }
2783    return -1;
2784 }
2785 #endif
2786 
xio_findopt(struct opt * opts,int optcode)2787 static struct opt *xio_findopt(struct opt *opts, int optcode) {
2788    struct opt *opt = opts;
2789 
2790    while (opt->desc != ODESC_END) {
2791       if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2792 	 return opt;
2793       }
2794       ++opt;
2795    }
2796    return NULL;
2797 }
2798 
retropt_timespec(struct opt * opts,int optcode,struct timespec * result)2799 int retropt_timespec(struct opt *opts, int optcode, struct timespec *result) {
2800    struct opt *opt;
2801 
2802    if (!(opt = xio_findopt(opts, optcode))) {
2803       return -1;
2804    }
2805    *result = opt->value.u_timespec;
2806    opt->desc = ODESC_DONE;
2807    return 0;
2808 }
2809 
2810 
2811 /* Looks for the first option of type <optcode>. If the option is found,
2812    this function stores its bool value in *result, "consumes" the
2813    option, and returns 0.
2814    If the option is not found, *result is not modified, and -1 is returned. */
retropt_bool(struct opt * opts,int optcode,bool * result)2815 int retropt_bool(struct opt *opts, int optcode, bool *result) {
2816    struct opt *opt = opts;
2817 
2818    while (opt->desc != ODESC_END) {
2819       if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2820 	 *result = opt->value.u_bool;
2821 	 opt->desc = ODESC_DONE;
2822 	 return 0;
2823       }
2824       ++opt;
2825    }
2826    return -1;
2827 }
2828 
2829 #if 0	/* currently not used */
2830 /* Looks for the first option of type <optcode>. If the option is found,
2831    this function stores its short value in *result, "consumes" the
2832    option, and returns 0.
2833    If the option is not found, *result is not modified, and -1 is returned. */
2834 int retropt_short(struct opt *opts, int optcode, short *result) {
2835    struct opt *opt = opts;
2836 
2837    while (opt->desc != ODESC_END) {
2838       if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2839 	 *result = opt->value.u_short;
2840 	 opt->desc = ODESC_DONE;
2841 	 return 0;
2842       }
2843       ++opt;
2844    }
2845    return -1;
2846 }
2847 #endif
2848 
2849 /* Looks for the first option of type <optcode>. If the option is found,
2850    this function stores its unsigned short value in *result, "consumes" the
2851    option, and returns 0.
2852    If the option is not found, *result is not modified, and -1 is returned. */
retropt_ushort(struct opt * opts,int optcode,unsigned short * result)2853 int retropt_ushort(struct opt *opts, int optcode, unsigned short *result) {
2854    struct opt *opt = opts;
2855 
2856    while (opt->desc != ODESC_END) {
2857       if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2858 	 *result = opt->value.u_ushort;
2859 	 opt->desc = ODESC_DONE;
2860 	 return 0;
2861       }
2862       ++opt;
2863    }
2864    return -1;
2865 }
2866 
2867 /* Looks for the first option of type <optcode>. If the option is found,
2868    this function stores its int value in *result, "consumes" the
2869    option, and returns 0.
2870    If the option is not found, *result is not modified, and -1 is returned. */
retropt_int(struct opt * opts,int optcode,int * result)2871 int retropt_int(struct opt *opts, int optcode, int *result) {
2872    struct opt *opt = opts;
2873 
2874    while (opt->desc != ODESC_END) {
2875       if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2876 	 switch (opt->desc->type) {
2877 	 case TYPE_INT: *result = opt->value.u_int; break;
2878 	 case TYPE_STRING: *result = strtol(opt->value.u_string, NULL, 0);
2879 	    break;
2880 	 default: Error2("cannot convert type %d of option %s to int",
2881 			 opt->desc->type, opt->desc->defname);
2882 	    opt->desc = ODESC_ERROR;
2883 	    return -1;
2884 	 }
2885 	 opt->desc = ODESC_DONE;
2886 	 return 0;
2887       }
2888       ++opt;
2889    }
2890    return -1;
2891 }
2892 
2893 /* Looks for the first option of type <optcode>. If the option is found,
2894    this function stores its unsigned int value in *result, "consumes" the
2895    option, and returns 0.
2896    If the option is not found, *result is not modified, and -1 is returned. */
retropt_uint(struct opt * opts,int optcode,unsigned int * result)2897 int retropt_uint(struct opt *opts, int optcode, unsigned int *result) {
2898    struct opt *opt = opts;
2899 
2900    while (opt->desc != ODESC_END) {
2901       if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2902 	 *result = opt->value.u_uint;
2903 	 opt->desc = ODESC_DONE;
2904 	 return 0;
2905       }
2906       ++opt;
2907    }
2908    return -1;
2909 }
2910 
2911 /* Looks for the first option of type <optcode>. If the option is found,
2912    this function stores its long value in *result, "consumes" the option,
2913    and returns 0.
2914    If the option is not found, *result is not modified, and -1 is returned. */
retropt_long(struct opt * opts,int optcode,long * result)2915 int retropt_long(struct opt *opts, int optcode, long *result) {
2916    struct opt *opt = opts;
2917 
2918    while (opt->desc != ODESC_END) {
2919       if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2920 	 *result = opt->value.u_long;
2921 	 opt->desc = ODESC_DONE;
2922 	 return 0;
2923       }
2924       ++opt;
2925    }
2926    return -1;
2927 }
2928 
2929 /* Looks for the first option of type <optcode>. If the option is found,
2930    this function stores its unsigned long value in *result, "consumes" the
2931    option, and returns 0.
2932    If the option is not found, *result is not modified, and -1 is returned. */
retropt_ulong(struct opt * opts,int optcode,unsigned long * result)2933 int retropt_ulong(struct opt *opts, int optcode, unsigned long *result) {
2934    struct opt *opt = opts;
2935 
2936    while (opt->desc != ODESC_END) {
2937       if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2938 	 *result = opt->value.u_ulong;
2939 	 opt->desc = ODESC_DONE;
2940 	 return 0;
2941       }
2942       ++opt;
2943    }
2944    return -1;
2945 }
2946 
2947 #if 0	/* currently not used */
2948 /* get the value of a FLAG typed option, and apply it to the appropriate
2949    bit position. Mark the option as consumed (done). return 0 if options was found and successfully applied,
2950    or -1 if option was not in opts */
2951 int retropt_flag(struct opt *opts, int optcode, flags_t *result) {
2952    struct opt *opt = opts;
2953 
2954    while (opt->desc != ODESC_END) {
2955       if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2956 	 if (opt->value.u_bool) {
2957 	    *result |= opt->desc->major;
2958 	 } else {
2959 	    *result &= ~opt->desc->major;
2960 	 }
2961 	 opt->desc = ODESC_DONE;
2962 	 return 0;
2963       }
2964       ++opt;
2965    }
2966    return -1;
2967 }
2968 #endif
2969 
2970 /* Looks for the first option of type <optcode>. If the option is found,
2971    this function stores its character pointer value in *result, "consumes" the
2972    option, and returns 0. Note that, for options of type STRING_NULL, the
2973    character pointer might degenerate to NULL.
2974    The resulting string is malloc'ed and should be freed after use.
2975    If the option is not found, *result is not modified, and -1 is returned.
2976  */
retropt_string(struct opt * opts,int optcode,char ** result)2977 int retropt_string(struct opt *opts, int optcode, char **result) {
2978    struct opt *opt = opts;
2979 
2980    while (opt->desc != ODESC_END) {
2981       if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2982 	 if (opt->value.u_string == NULL) {
2983 	    *result = NULL;
2984 	 } else if ((*result = strdup(opt->value.u_string)) == NULL) {
2985 	    Error1("strdup("F_Zu"): out of memory",
2986 		   strlen(opt->value.u_string));
2987 	    return -1;
2988 	 }
2989 	 opt->desc = ODESC_DONE;
2990 	 return 0;
2991       }
2992       ++opt;
2993    }
2994    return -1;
2995 }
2996 
2997 
2998 #if _WITH_SOCKET
2999 /* looks for a bind option and, if found, overwrites the complete contents of
3000    sa with the appropriate value(s).
3001    returns STAT_OK if option exists and could be resolved,
3002    STAT_NORETRY if option exists but had error,
3003    or STAT_NOACTION if it does not exist */
3004 /* currently only for IP (v4, v6) and raw (PF_UNSPEC) */
retropt_bind(struct opt * opts,int af,int socktype,int ipproto,struct sockaddr * sa,socklen_t * salen,int feats,unsigned long res_opts0,unsigned long res_opts1)3005 int retropt_bind(struct opt *opts,
3006 		 int af,
3007 		 int socktype,
3008 		 int ipproto,
3009 		 struct sockaddr *sa,
3010 		 socklen_t *salen,
3011 		 int feats,	/* TCP etc: 1..address allowed,
3012 					    3..address and port allowed
3013 				   UNIX (or'd): 1..tight
3014 						2..abstract
3015 				*/
3016 		 unsigned long res_opts0, unsigned long res_opts1) {
3017    const char portsep[] = ":";
3018    const char *ends[] = { portsep, NULL };
3019    const char *nests[] = { "[", "]", NULL };
3020    bool portallowed;
3021    char *bindname, *bindp;
3022    char hostname[512], *hostp = hostname, *portp = NULL;
3023    size_t hostlen = sizeof(hostname)-1;
3024    int parsres;
3025    int result;
3026 
3027    if (retropt_string(opts, OPT_BIND, &bindname) < 0) {
3028       return STAT_NOACTION;
3029    }
3030    bindp = bindname;
3031 
3032    switch (af) {
3033 
3034    case AF_UNSPEC:
3035       {
3036 	 size_t p = 0;
3037 	 dalan(bindname, (uint8_t *)sa->sa_data, &p, *salen-sizeof(sa->sa_family), 'i');
3038 	 *salen = p + sizeof(sa->sa_family);
3039 	 *salen = p +
3040 #if HAVE_STRUCT_SOCKADDR_SALEN
3041 	    sizeof(sa->sa_len) +
3042 #endif
3043 	    sizeof(sa->sa_family);
3044 #if HAVE_STRUCT_SOCKADDR_SALEN
3045 	 sa->sa_len = *salen;
3046 #endif
3047       }
3048       break;
3049 
3050 #if WITH_IP4 || WITH_IP6 || WITH_VSOCK
3051 #if WITH_VSOCK
3052    case AF_VSOCK:
3053 #endif
3054 #if WITH_IP4
3055    case AF_INET:
3056 #endif
3057 #if WITH_IP6
3058    case AF_INET6:
3059 #endif /*WITH_IP6 */
3060       portallowed = (feats>=2);
3061       parsres =
3062 	 nestlex((const char **)&bindp, &hostp, &hostlen, ends, NULL, NULL, nests,
3063 		 true, false, false);
3064       if (parsres < 0) {
3065 	 Error1("option too long:  \"%s\"", bindp);
3066 	 return STAT_NORETRY;
3067       } else if (parsres > 0) {
3068 	 Error1("syntax error in \"%s\"", bindp);
3069 	 return STAT_NORETRY;
3070       }
3071       *hostp++ = '\0';
3072       if (!strncmp(bindp, portsep, strlen(portsep))) {
3073 	 if (!portallowed) {
3074 	    Error("port specification not allowed in this bind option");
3075 	    return STAT_NORETRY;
3076 	 } else {
3077 	    portp = bindp + strlen(portsep);
3078 	 }
3079       }
3080       if ((result =
3081 	   xiogetaddrinfo(hostname[0]!='\0'?hostname:NULL, portp,
3082 			  af, socktype, ipproto,
3083 			  (union sockaddr_union *)sa, salen,
3084 			  res_opts0, res_opts1))
3085 	  != STAT_OK) {
3086 	 Error("error resolving bind option");
3087 	 return STAT_NORETRY;
3088       }
3089       break;
3090 #endif /* WITH_IP4 || WITH_IP6 */
3091 
3092 #if WITH_UNIX
3093    case AF_UNIX:
3094       {
3095 	 bool abstract = (feats&2);
3096 	 bool tight = (feats&1);
3097 	 struct sockaddr_un *s_un = (struct sockaddr_un *)sa;
3098 	 *salen = xiosetunix(af, s_un, bindname, abstract, tight);
3099       }
3100       break;
3101 #endif /* WITH_UNIX */
3102 
3103    default:
3104       Error1("bind: unknown address family %d", af);
3105       return STAT_NORETRY;
3106    }
3107    return STAT_OK;
3108 }
3109 #endif /* _WITH_SOCKET */
3110 
3111 
3112 /* applies to fd all options belonging to phase */
3113 /* note: not all options can be applied this way (e.g. OFUNC_SPEC with PH_OPEN)
3114    implemented are: OFUNC_FCNTL, OFUNC_SOCKOPT (probably not all types),
3115    OFUNC_TERMIOS_FLAG, OFUNC_TERMIOS_PATTERN, and some OFUNC_SPEC */
applyopts(int fd,struct opt * opts,enum e_phase phase)3116 int applyopts(int fd, struct opt *opts, enum e_phase phase) {
3117    struct opt *opt;
3118 
3119    opt = opts; while (opt && opt->desc != ODESC_END) {
3120       if (opt->desc == ODESC_DONE ||
3121 	  (phase != PH_ALL && opt->desc->phase != phase)) {
3122 	 ++opt; continue; }
3123 
3124       if (opt->desc->func == OFUNC_SEEK32) {
3125 	 if (Lseek(fd, opt->value.u_off, opt->desc->major) < 0) {
3126 	    Error4("lseek(%d, "F_off", %d): %s",
3127 		   fd, opt->value.u_off, opt->desc->major, strerror(errno));
3128 	 }
3129 #if HAVE_LSEEK64
3130       } else if (opt->desc->func == OFUNC_SEEK64) {
3131 
3132 	 /*! this depends on off64_t atomic type */
3133 	 if (Lseek64(fd, opt->value.u_off64, opt->desc->major) < 0) {
3134 	    Error4("lseek64(%d, "F_off64", %d): %s",
3135 		   fd, opt->value.u_off64, opt->desc->major, strerror(errno));
3136 	 }
3137 #endif /* HAVE_LSEEK64 */
3138 
3139       } else if (opt->desc->func == OFUNC_FCNTL) {
3140 	 int flag;
3141 
3142 	 /* retrieve existing flag setttings */
3143 	 if ((flag = Fcntl(fd, opt->desc->major-1)) < 0) {
3144 	    Error3("fcntl(%d, %d): %s",
3145 		   fd, opt->desc->major, strerror(errno));
3146 	    opt->desc = ODESC_ERROR; ++opt; continue;
3147 	 } else {
3148 	    if (opt->value.u_bool) {
3149 	       flag |= opt->desc->minor;
3150 	    } else {
3151 	       flag &= ~opt->desc->minor;
3152 	    }
3153 	    if (Fcntl_l(fd, opt->desc->major, flag) < 0) {
3154 	       Error4("fcntl(%d, %d, %d): %s",
3155 		      fd, opt->desc->major, flag, strerror(errno));
3156 	       opt->desc = ODESC_ERROR; ++opt; continue;
3157 	    }
3158 	 }
3159 
3160       } else if (opt->desc->func == OFUNC_IOCTL) {
3161 	 if (Ioctl(fd, opt->desc->major, (void *)&opt->value) < 0) {
3162 	    Error4("ioctl(%d, 0x%x, %p): %s",
3163 		   fd, opt->desc->major, (void *)&opt->value, strerror(errno));
3164 	    opt->desc = ODESC_ERROR; ++opt; continue;
3165 	 }
3166 
3167       } else if (opt->desc->func == OFUNC_IOCTL_MASK_LONG) {
3168 	 long val;
3169 	 int getreq = opt->desc->major;
3170 	 int setreq = opt->desc->minor;
3171 	 long mask  = opt->desc->arg3;
3172 
3173 	 if (Ioctl(fd, getreq, (void *)&val) < 0) {
3174 	    Error4("ioctl(%d, 0x%x, %p): %s",
3175 		   fd, opt->desc->major, (void *)&val, strerror(errno));
3176 	    opt->desc = ODESC_ERROR; ++opt; continue;
3177 	 }
3178 	 val &= ~mask;
3179 	 if (opt->value.u_bool)  val |= mask;
3180 	 if (Ioctl(fd, setreq, (void *)&val) < 0) {
3181 	    Error4("ioctl(%d, 0x%x, %p): %s",
3182 		   fd, opt->desc->major, (void *)&val, strerror(errno));
3183 	    opt->desc = ODESC_ERROR; ++opt; continue;
3184 	 }
3185 
3186       } else if (opt->desc->func == OFUNC_IOCTL_GENERIC) {
3187 	 switch (opt->desc->type) {
3188 	 case TYPE_INT:
3189 	    if (Ioctl(fd, opt->value.u_int, NULL) < 0) {
3190 	       Error3("ioctl(%d, 0x%x, NULL): %s",
3191 		      fd, opt->value.u_int, strerror(errno));
3192 	       opt->desc = ODESC_ERROR; ++opt; continue;
3193 	    }
3194 	    break;
3195 	 case TYPE_INT_INT:
3196 	    if (Ioctl_int(fd, opt->value.u_int, opt->value2.u_int) < 0) {
3197 	       Error4("ioctl(%d, 0x%x, 0x%x): %s",
3198 		      fd, opt->value.u_int, opt->value2.u_int, strerror(errno));
3199 	       opt->desc = ODESC_ERROR; ++opt; continue;
3200 	    }
3201 	    break;
3202 	 case TYPE_INT_INTP:
3203 	    if (Ioctl(fd, opt->value.u_int, (void *)&opt->value2.u_int) < 0) {
3204 	       Error4("ioctl(%d, 0x%x, %p): %s",
3205 		      fd, opt->value.u_int, (void *)&opt->value2.u_int, strerror(errno));
3206 	       opt->desc = ODESC_ERROR; ++opt; continue;
3207 	    }
3208 	    break;
3209 	 case TYPE_INT_BIN:
3210 	    if (Ioctl(fd, opt->value.u_int, (void *)opt->value2.u_bin.b_data) < 0) {
3211 	       Error4("ioctl(%d, 0x%x, %p): %s",
3212 		      fd, opt->value.u_int, (void *)opt->value2.u_bin.b_data, strerror(errno));
3213 	       opt->desc = ODESC_ERROR; ++opt; continue;
3214 	    }
3215 	    break;
3216 	 case TYPE_INT_STRING:
3217 	    if (Ioctl(fd, opt->value.u_int, (void *)opt->value2.u_string) < 0) {
3218 	       Error4("ioctl(%d, 0x%x, %p): %s",
3219 		      fd, opt->value.u_int, (void *)opt->value2.u_string, strerror(errno));
3220 	       opt->desc = ODESC_ERROR; ++opt; continue;
3221 	    }
3222 	    break;
3223 	 default:
3224 	    Error1("ioctl() data type %d not implemented",
3225 		   opt->desc->type);
3226 	 }
3227 
3228 #if _WITH_SOCKET
3229       } else if (opt->desc->func == OFUNC_SOCKOPT) {
3230 	 if (0) {
3231 	    ;
3232 #if 0 && HAVE_STRUCT_LINGER
3233 	 } else if (opt->desc->optcode == OPT_SO_LINGER) {
3234 	    struct linger lingstru;
3235 	    lingstru.l_onoff = (opt->value.u_int>=0 ? 1 : 0);
3236 	    lingstru.l_linger = opt->value.u_int;
3237 	    if (Setsockopt(fd, opt->desc->major, opt->desc->minor, &lingstru,
3238 			   sizeof(lingstru)) < 0) {
3239 	       Error6("setsockopt(%d, %d, %d, {%d,%d}, "F_Zu,
3240 		      fd, opt->desc->major, opt->desc->minor, lingstru.l_onoff,
3241 		      lingstru.l_linger, sizeof(lingstru));
3242 	       opt->desc = ODESC_ERROR; ++opt; continue;
3243 	    }
3244 #endif /* HAVE_STRUCT_LINGER */
3245 	 } else {
3246 	    switch (opt->desc->type) {
3247 	    case TYPE_BIN:
3248 	       if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3249 			      opt->value.u_bin.b_data, opt->value.u_bin.b_len)
3250 		   < 0) {
3251 		  Error6("setsockopt(%d, %d, %d, %p, "F_Zu"): %s",
3252 			 fd, opt->desc->major, opt->desc->minor,
3253 			 opt->value.u_bin.b_data, opt->value.u_bin.b_len,
3254 			 strerror(errno));
3255 		  opt->desc = ODESC_ERROR; ++opt; continue;
3256 	       }
3257 	       break;
3258 	    case TYPE_BOOL:
3259 	       if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3260 			      &opt->value.u_bool, sizeof(opt->value.u_bool))
3261 		   < 0) {
3262 		  Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s", fd,
3263 			 opt->desc->major, opt->desc->minor,
3264 			 opt->value.u_bool, sizeof(opt->value.u_bool),
3265 			 strerror(errno));
3266 		  opt->desc = ODESC_ERROR; ++opt; continue;
3267 	       }
3268 	       break;
3269 	    case TYPE_BYTE:
3270 	       if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3271 			      &opt->value.u_byte, sizeof(uint8_t)) < 0) {
3272 		  Error6("setsockopt(%d, %d, %d, {%u}, "F_Zu"): %s",
3273 			 fd, opt->desc->major, opt->desc->minor,
3274 			 opt->value.u_byte, sizeof(uint8_t), strerror(errno));
3275 		  opt->desc = ODESC_ERROR; ++opt; continue;
3276 	       }
3277 	       break;
3278 	    case TYPE_INT:
3279 	       if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3280 			      &opt->value.u_int, sizeof(int)) < 0) {
3281 		  Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s",
3282 			 fd, opt->desc->major, opt->desc->minor,
3283 			 opt->value.u_int, sizeof(int), strerror(errno));
3284 		  opt->desc = ODESC_ERROR; ++opt; continue;
3285 	       }
3286 	       break;
3287 	    case TYPE_LONG:
3288 	       if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3289 			      &opt->value.u_long, sizeof(long)) < 0) {
3290 		  Error6("setsockopt(%d, %d, %d, {%ld}, "F_Zu"): %s",
3291 			 fd, opt->desc->major, opt->desc->minor,
3292 			 opt->value.u_long, sizeof(long), strerror(errno));
3293 		  opt->desc = ODESC_ERROR; ++opt; continue;
3294 	       }
3295 	       break;
3296 	    case TYPE_STRING:
3297 	       if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3298 			      opt->value.u_string,
3299 			      strlen(opt->value.u_string)+1) < 0) {
3300 		  Error6("setsockopt(%d, %d, %d, \"%s\", "F_Zu"): %s",
3301 			 fd, opt->desc->major, opt->desc->minor,
3302 			 opt->value.u_string, strlen(opt->value.u_string)+1,
3303 			 strerror(errno));
3304 		  opt->desc = ODESC_ERROR; ++opt; continue;
3305 	       }
3306 	       break;
3307 	    case TYPE_UINT:
3308 	       if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3309 			      &opt->value.u_uint, sizeof(unsigned int)) < 0) {
3310 		  Error6("setsockopt(%d, %d, %d, {%u}, "F_Zu"): %s",
3311 			 fd, opt->desc->major, opt->desc->minor,
3312 			 opt->value.u_uint, sizeof(unsigned int),
3313 			 strerror(errno));
3314 		  opt->desc = ODESC_ERROR; ++opt; continue;
3315 	       }
3316 	       break;
3317 	    case TYPE_TIMEVAL:
3318 	       if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3319 			      &opt->value.u_timeval, sizeof(struct timeval)) < 0) {
3320 		  Error7("setsockopt(%d, %d, %d, {%ld,%ld}, "F_Zu"): %s",
3321 			 fd, opt->desc->major, opt->desc->minor,
3322 			 opt->value.u_timeval.tv_sec, opt->value.u_timeval.tv_usec,
3323 			 sizeof(struct timeval), strerror(errno));
3324 		  opt->desc = ODESC_ERROR; ++opt; continue;
3325 	       }
3326 	       break;
3327 #if HAVE_STRUCT_LINGER
3328 	    case TYPE_LINGER:
3329 	       {
3330 		  struct linger lingstru;
3331 		  lingstru.l_onoff = (opt->value.u_linger.l_onoff>=0 ? 1 : 0);
3332 		  lingstru.l_linger = opt->value.u_linger.l_linger;
3333 		  if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3334 				 &lingstru, sizeof(lingstru)) < 0) {
3335 		     Error6("setsockopt(%d, %d, %d, {%d,%d}): %s",
3336 			    fd, opt->desc->major, opt->desc->minor,
3337 			    lingstru.l_onoff, lingstru.l_linger,
3338 			    strerror(errno));
3339 		     opt->desc = ODESC_ERROR; ++opt; continue;
3340 		  }
3341 	       }
3342 	       break;
3343 #endif /* HAVE_STRUCT_LINGER */
3344 #if defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)
3345 	    case TYPE_IP_MREQN:
3346 	       /* handled in applyopts_single */
3347 	       ++opt; continue;
3348 #endif /* defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) */
3349 
3350 	       /*! still many types missing; implement on demand */
3351 #if WITH_IP4
3352 	    case TYPE_IP4NAME:
3353 	       if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3354 			      &opt->value.u_ip4addr, sizeof(opt->value.u_ip4addr)) < 0) {
3355 		  Error6("setsockopt(%d, %d, %d, {0x%x}, "F_Zu"): %s",
3356 			 fd, opt->desc->major, opt->desc->minor,
3357 			 *(uint32_t *)&opt->value.u_ip4addr, sizeof(opt->value.u_ip4addr),
3358 			 strerror(errno));
3359 	       }
3360 	       break;
3361 #endif /* defined(WITH_IP4) */
3362 	    default:
3363 #if !NDEBUG
3364 	       Error1("applyopts(): type %d not implemented",
3365 			    opt->desc->type);
3366 #else
3367 	       Warn1("applyopts(): type %d not implemented",
3368 			    opt->desc->type);
3369 #endif
3370 	       opt->desc = ODESC_ERROR; ++opt; continue;
3371 	    }
3372 	 }
3373 
3374       } else if (opt->desc->func == OFUNC_SOCKOPT_APPEND) {
3375 	 switch (opt->desc->type) {
3376 	    uint8_t data[256];
3377 	    socklen_t oldlen, newlen;
3378 	 case TYPE_BIN:
3379 	    oldlen = sizeof(data);
3380 	    if (Getsockopt(fd, opt->desc->major, opt->desc->minor,
3381 			   data, &oldlen)
3382 		< 0) {
3383 	       Error6("getsockopt(%d, %d, %d, %p, {"F_socklen"}): %s",
3384 		      fd, opt->desc->major, opt->desc->minor, data, oldlen,
3385 		      strerror(errno));
3386 	       opt->desc = ODESC_ERROR; ++opt; continue;
3387 	    }
3388 	    memcpy(&data[oldlen], opt->value.u_bin.b_data,
3389 		   MIN(opt->value.u_bin.b_len, sizeof(data)-oldlen));
3390 	    newlen = oldlen + MIN(opt->value.u_bin.b_len, sizeof(data)-oldlen);
3391 	    if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3392 			   data, newlen)
3393 		< 0) {
3394 	       Error6("setsockopt(%d, %d, %d, %p, %d): %s",
3395 		      fd, opt->desc->major, opt->desc->minor, data, newlen,
3396 		      strerror(errno));
3397 	       opt->desc = ODESC_ERROR; ++opt; continue;
3398 	    }
3399 	    break;
3400 	 default:
3401 	    Error2("internal: option \"%s\": unimplemented type %d",
3402 		   opt->desc->defname, opt->desc->type);
3403 	    break;
3404 	 }
3405       } else if (opt->desc->func == OFUNC_SOCKOPT_GENERIC) {
3406 	 switch (opt->desc->type) {
3407 	 case TYPE_INT_INT_INT:
3408 	    if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int,
3409 			   &opt->value3.u_int, sizeof(int)) < 0) {
3410 	       Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s",
3411 		      fd, opt->value.u_int, opt->value2.u_int,
3412 		      opt->value3.u_int, sizeof(int), strerror(errno));
3413 	    }
3414 	    break;
3415 	 case TYPE_INT_INT_BIN:
3416 	    if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int,
3417 			   opt->value3.u_bin.b_data, opt->value3.u_bin.b_len) < 0) {
3418 	       Error5("setsockopt(%d, %d, %d, {...}, "F_Zu"): %s",
3419 		      fd, opt->value.u_int, opt->value2.u_int,
3420 		      opt->value3.u_bin.b_len, strerror(errno));
3421 	    }
3422 	    break;
3423 	 case TYPE_INT_INT_STRING:
3424 	    if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int,
3425 			   opt->value3.u_string,
3426 			   strlen(opt->value3.u_string)+1) < 0) {
3427 	       Error6("setsockopt(%d, %d, %d, \"%s\", "F_Zu"): %s",
3428 		      fd, opt->value.u_int, opt->value2.u_int,
3429 		      opt->value3.u_string, strlen(opt->value3.u_string)+1,
3430 		      strerror(errno));
3431 	    }
3432 	    break;
3433 	 default:
3434 	    Error1("setsockopt() data type %d not implemented",
3435 		   opt->desc->type);
3436 	 }
3437 #endif /* _WITH_SOCKET */
3438 
3439 #if HAVE_FLOCK
3440       } else if (opt->desc->func == OFUNC_FLOCK) {
3441 	 if (Flock(fd, opt->desc->major) < 0) {
3442 	    Error3("flock(%d, %d): %s",
3443 		   fd, opt->desc->major, strerror(errno));
3444 	    opt->desc = ODESC_ERROR; ++opt; continue;
3445 	 }
3446 #endif /* defined(HAVE_FLOCK) */
3447 
3448       } else if (opt->desc->func == OFUNC_SPEC ||
3449 		 opt->desc->func == OFUNC_FLAG) {
3450 	 switch (opt->desc->optcode) {
3451 	 case OPT_USER:
3452 	 case OPT_USER_LATE:
3453 	    if (Fchown(fd, opt->value.u_uidt, -1) < 0) {
3454 	       Error3("fchown(%d, "F_uid", -1): %s",
3455 		      fd, opt->value.u_uidt, strerror(errno));
3456 	       opt->desc = ODESC_ERROR; ++opt; continue;
3457 	    }
3458 	    break;
3459 	 case OPT_GROUP:
3460 	 case OPT_GROUP_LATE:
3461 	    if (Fchown(fd, -1, opt->value.u_gidt) < 0) {
3462 	       Error3("fchown(%d, -1, "F_gid"): %s",
3463 		      fd, opt->value.u_gidt, strerror(errno));
3464 	       opt->desc = ODESC_ERROR; ++opt; continue;
3465 	    }
3466 	    break;
3467 	 case OPT_PERM:
3468 	 case OPT_PERM_LATE:
3469 	    if (Fchmod(fd, opt->value.u_modet) < 0) {
3470 	       Error3("fchmod(%d, %u): %s",
3471 		      fd, opt->value.u_modet, strerror(errno));
3472 	       opt->desc = ODESC_ERROR; ++opt; continue;
3473 	    }
3474 	    break;
3475 	 case OPT_FTRUNCATE32:
3476 	    if (Ftruncate(fd, opt->value.u_off) < 0) {
3477 	       Error3("ftruncate(%d, "F_off"): %s",
3478 		      fd, opt->value.u_off, strerror(errno));
3479 	       opt->desc = ODESC_ERROR; ++opt; continue;
3480 	    }
3481 	    break;
3482 #if HAVE_FTRUNCATE64
3483 	 case OPT_FTRUNCATE64:
3484 	    if (Ftruncate64(fd, opt->value.u_off64) < 0) {
3485 	       Error3("ftruncate64(%d, "F_off64"): %s",
3486 		      fd, opt->value.u_off64, strerror(errno));
3487 	       opt->desc = ODESC_ERROR; ++opt; continue;
3488 	    }
3489 #endif /* HAVE_FTRUNCATE64 */
3490 	    break;
3491 	 case OPT_F_SETLK_RD:
3492 	 case OPT_F_SETLK_WR:
3493 	 case OPT_F_SETLKW_RD:
3494 	 case OPT_F_SETLKW_WR:
3495 	    {
3496 	       struct flock l;	/* Linux: <asm/fcntl.h> */
3497 	       l.l_type   = opt->desc->minor;
3498 	       l.l_whence = SEEK_SET;
3499 	       l.l_start  = 0;
3500 	       l.l_len    = LONG_MAX;
3501 	       l.l_pid    = 0;	/* hope this uses our current process */
3502 	       if (Fcntl_lock(fd, opt->desc->major, &l) < 0) {
3503 		  Error3("fcntl(%d, %d, {type=F_WRLCK,whence=SEEK_SET,start=0,len=LONG_MAX,pid=0}): %s", fd, opt->desc->major, strerror(errno));
3504 		  opt->desc = ODESC_ERROR; ++opt; continue;
3505 	       }
3506 	    }
3507 	    break;
3508 	 case OPT_SETUID_EARLY:
3509 	 case OPT_SETUID:
3510 	    if (Setuid(opt->value.u_uidt) < 0) {
3511 	       Error2("setuid("F_uid"): %s", opt->value.u_uidt,
3512 		      strerror(errno));
3513 	       opt->desc = ODESC_ERROR; ++opt; continue;
3514 	    }
3515 	    break;
3516 	 case OPT_SETGID_EARLY:
3517 	 case OPT_SETGID:
3518 	    if (Setgid(opt->value.u_gidt) < 0) {
3519 	       Error2("setgid("F_gid"): %s", opt->value.u_gidt,
3520 		      strerror(errno));
3521 	       opt->desc = ODESC_ERROR; ++opt; continue;
3522 	    }
3523 	    break;
3524 	 case OPT_SUBSTUSER_EARLY:
3525 	 case OPT_SUBSTUSER:
3526 	    {
3527 	       struct passwd *pwd;
3528 	       if ((pwd = getpwuid(opt->value.u_uidt)) == NULL) {
3529 		  Error1("getpwuid("F_uid"): no such user",
3530 			 opt->value.u_uidt);
3531 		  opt->desc = ODESC_ERROR; ++opt; continue;
3532 	       }
3533 	       if (Initgroups(pwd->pw_name, pwd->pw_gid) < 0) {
3534 		  Error3("initgroups(%s, "F_gid"): %s",
3535 			 pwd->pw_name, pwd->pw_gid, strerror(errno));
3536 		  opt->desc = ODESC_ERROR; ++opt; continue;
3537 	       }
3538 	       if (Setgid(pwd->pw_gid) < 0) {
3539 		  Error2("setgid("F_gid"): %s", pwd->pw_gid,
3540 			 strerror(errno));
3541 		  opt->desc = ODESC_ERROR; ++opt; continue;
3542 	       }
3543 	       if (Setuid(opt->value.u_uidt) < 0) {
3544 		  Error2("setuid("F_uid"): %s", opt->value.u_uidt,
3545 			 strerror(errno));
3546 		  opt->desc = ODESC_ERROR; ++opt; continue;
3547 	       }
3548 #if 1
3549 	       if (setenv("USER", pwd->pw_name, 1) < 0)
3550 		  Error1("setenv(\"USER\", \"%s\", 1): insufficient space",
3551 			 pwd->pw_name);
3552 	       if (setenv("LOGNAME", pwd->pw_name, 1) < 0)
3553 		  Error1("setenv(\"LOGNAME\", \"%s\", 1): insufficient space",
3554 			 pwd->pw_name);
3555 	       if (setenv("HOME", pwd->pw_dir, 1) < 0)
3556 		  Error1("setenv(\"HOME\", \"%s\", 1): insufficient space",
3557 			 pwd->pw_dir);
3558 	       if (setenv("SHELL", pwd->pw_shell, 1) < 0)
3559 		  Error1("setenv(\"SHELL\", \"%s\", 1): insufficient space",
3560 			 pwd->pw_shell);
3561 #endif
3562 	    }
3563 	    break;
3564 #if defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT)
3565 	 case OPT_SUBSTUSER_DELAYED:
3566 	    {
3567 	       struct passwd *pwd;
3568 
3569 	       if ((pwd = getpwuid(opt->value.u_uidt)) == NULL) {
3570 		  Error1("getpwuid("F_uid"): no such user",
3571 			 opt->value.u_uidt);
3572 		  opt->desc = ODESC_ERROR; ++opt; continue;
3573 	       }
3574 	       delayeduser_uid = opt->value.u_uidt;
3575 	       delayeduser_gid = pwd->pw_gid;
3576 	       if ((delayeduser_name = strdup(pwd->pw_name)) == NULL) {
3577 		  Error1("strdup("F_Zu"): out of memory",
3578 			 strlen(pwd->pw_name)+1);
3579 		  opt->desc = ODESC_ERROR; ++opt; continue;
3580 	       }
3581 	       if ((delayeduser_dir = strdup(pwd->pw_dir)) == NULL) {
3582 		  Error1("strdup("F_Zu"): out of memory",
3583 			 strlen(pwd->pw_dir)+1);
3584 		  opt->desc = ODESC_ERROR; ++opt; continue;
3585 	       }
3586 	       if ((delayeduser_shell = strdup(pwd->pw_shell)) == NULL) {
3587 		  Error1("strdup("F_Zu"): out of memory",
3588 			 strlen(pwd->pw_shell)+1);
3589 		  opt->desc = ODESC_ERROR; ++opt; continue;
3590 	       }
3591 	       /* function to get all supplementary groups of user */
3592 	       delayeduser_ngids = sizeof(delayeduser_gids)/sizeof(gid_t);
3593 	       getusergroups(delayeduser_name, delayeduser_gids,
3594 			     &delayeduser_ngids);
3595 	       delayeduser = true;
3596 	    }
3597 	    break;
3598 #endif
3599 	 case OPT_CHROOT_EARLY:
3600 	 case OPT_CHROOT:
3601 	    if (Chroot(opt->value.u_string) < 0) {
3602 	       Error2("chroot(\"%s\"): %s", opt->value.u_string,
3603 		      strerror(errno));
3604 	       opt->desc = ODESC_ERROR; ++opt; continue;
3605 	    }
3606 	    if (Chdir("/") < 0) {
3607 	       Error1("chdir(\"/\"): %s", strerror(errno));
3608 	    }
3609 	    break;
3610 	 case OPT_SETSID:
3611 	    if (Setsid() < 0) {
3612 	       Warn1("setsid(): %s", strerror(errno));
3613 	       if (Setpgid(getpid(), getppid()) < 0) {
3614 		  Warn3("setpgid(%d, %d): %s",
3615 			getpid(), getppid(), strerror(errno));
3616 	       } else {
3617 		  if (Setsid() < 0) {
3618 		     Error1("setsid(): %s", strerror(errno));
3619 		  }
3620 	       }
3621 	    }
3622 	    break;
3623 	 case OPT_SETPGID:
3624 	    if (Setpgid(0, opt->value.u_int) < 0) {
3625 	       Warn2("setpgid(0, "F_pid"): %s",
3626 		     opt->value.u_int, strerror(errno));
3627 	    }
3628 	    break;
3629 	 case OPT_TIOCSCTTY:
3630 	    {
3631 	       int mytty;
3632 	       /* this code idea taken from ssh/pty.c: make pty controlling term. */
3633 	       if ((mytty = Open("/dev/tty", O_NOCTTY, 0640)) < 0) {
3634 		  Warn1("open(\"/dev/tty\", O_NOCTTY, 0640): %s", strerror(errno));
3635 	       } else {
3636 		  /*0 Info1("open(\"/dev/tty\", O_NOCTTY, 0640) -> %d", mytty);*/
3637 #ifdef TIOCNOTTY
3638 		  if (Ioctl(mytty, TIOCNOTTY, NULL) < 0) {
3639 		     Warn2("ioctl(%d, TIOCNOTTY, NULL): %s",
3640 			   mytty, strerror(errno));
3641 		  }
3642 #endif
3643 		  if (Close(mytty) < 0) {
3644 		     Info2("close(%d): %s",
3645 			   mytty, strerror(errno));
3646 		  }
3647 	       }
3648 #ifdef TIOCSCTTY
3649 	       if (Ioctl(fd, TIOCSCTTY, NULL) < 0) {
3650 		  Warn2("ioctl(%d, TIOCSCTTY, NULL): %s", fd, strerror(errno));
3651 	       }
3652 #endif
3653 	       if (Tcsetpgrp(0, getpid()) < 0) {
3654 		  Warn2("tcsetpgrp("F_pid"): %s", getpid(), strerror(errno));
3655 	       }
3656 	    }
3657 	    break;
3658 
3659 	 default: Error1("applyopts(): option \"%s\" not implemented",
3660 			 opt->desc->defname);
3661 	    opt->desc = ODESC_ERROR; ++opt; continue;
3662 	 }
3663 
3664 #if WITH_TERMIOS
3665       } else if (opt->desc->func == OFUNC_TERMIOS_FLAG) {
3666 	 if (xiotermiosflag_applyopt(fd, opt) < 0) {
3667 	    opt->desc = ODESC_ERROR; ++opt; continue;
3668 	 }
3669 
3670       } else if (opt->desc->func == OFUNC_TERMIOS_VALUE) {
3671 	 if (((opt->value.u_uint << opt->desc->arg3) & opt->desc->minor) !=
3672 	     (opt->value.u_uint << opt->desc->arg3)) {
3673 	    Error2("option %s: invalid value %u",
3674 		   opt->desc->defname, opt->value.u_uint);
3675 	    opt->desc = ODESC_ERROR; ++opt; continue;
3676 	 }
3677 	 if (xiotermios_value(fd, opt->desc->major, opt->desc->minor,
3678 			      (opt->value.u_uint << opt->desc->arg3) & opt->desc->minor) < 0) {
3679 	    opt->desc = ODESC_ERROR; ++opt; continue;
3680 	 }
3681 
3682       } else if (opt->desc->func == OFUNC_TERMIOS_PATTERN) {
3683 	 if (xiotermios_value(fd, opt->desc->major,  opt->desc->arg3, opt->desc->minor) < 0) {
3684 	    opt->desc = ODESC_ERROR; ++opt; continue;
3685 	 }
3686 
3687       } else if (opt->desc->func == OFUNC_TERMIOS_CHAR) {
3688 	 if (xiotermios_char(fd, opt->desc->major, opt->value.u_byte) < 0) {
3689 	    opt->desc = ODESC_ERROR; ++opt; continue;
3690 	 }
3691 
3692 #ifdef HAVE_TERMIOS_ISPEED
3693       } else if (opt->desc->func == OFUNC_TERMIOS_SPEED) {
3694 	 if (xiotermios_speed(fd, opt->desc->major, opt->value.u_uint) < 0) {
3695 	    opt->desc = ODESC_ERROR; ++opt; continue;
3696 	 }
3697 #endif /* HAVE_TERMIOS_ISPEED */
3698 
3699       } else if (opt->desc->func == OFUNC_TERMIOS_SPEC) {
3700 	 if (xiotermios_spec(fd, opt->desc->optcode) < 0) {
3701 	    opt->desc = ODESC_ERROR; ++opt; continue;
3702 	 }
3703 
3704 #endif /* WITH_TERMIOS */
3705 
3706 #if WITH_STREAMS
3707 #define ENABLE_APPLYOPT
3708 #include "xio-streams.c"
3709 #undef ENABLE_APPLYOPT
3710 #endif /* WITH_STREAMS */
3711 
3712       } else {
3713 	/*Error1("applyopts(): function %d not implemented",
3714 	  opt->desc->func);*/
3715 	 if (opt->desc->func != OFUNC_EXT && opt->desc->func != OFUNC_SIGNAL) {
3716 	    Error1("applyopts(): option \"%s\" does not apply",
3717 		   opt->desc->defname);
3718 	    opt->desc = ODESC_ERROR;
3719 	    ++opt;
3720 	    continue;
3721 	 }
3722 	 ++opt;
3723 	 continue;
3724       }
3725       opt->desc = ODESC_DONE;
3726       ++opt;
3727    }
3728 
3729 #if WITH_TERMIOS
3730    if (phase == PH_FD || phase == PH_ALL) {
3731       xiotermios_flush(fd);
3732    }
3733 #endif /* WITH_TERMIOS */
3734   return 0;
3735 }
3736 
3737 /* applies to fd all options belonging to phases */
3738 /* note: not all options can be applied this way (e.g. OFUNC_SPEC with PH_OPEN)
3739    implemented are: OFUNC_FCNTL, OFUNC_SOCKOPT (probably not all types),
3740    OFUNC_TERMIOS_FLAG, OFUNC_TERMIOS_PATTERN, and some OFUNC_SPEC */
applyopts2(int fd,struct opt * opts,unsigned int from,unsigned int to)3741 int applyopts2(int fd, struct opt *opts, unsigned int from, unsigned int to) {
3742    unsigned int i;
3743    int stat;
3744 
3745    for (i = from; i <= to; ++i) {
3746       if ((stat = applyopts(fd, opts, i)) < 0)
3747 	 return stat;
3748    }
3749    return 0;
3750 }
3751 
3752 /* apply and consume all options of type FLAG and group.
3753    Return 0 if everything went right, or -1 if an error occurred. */
applyopts_flags(struct opt * opts,int group,flags_t * result)3754 int applyopts_flags(struct opt *opts, int group, flags_t *result) {
3755    struct opt *opt = opts;
3756 
3757    if (!opts)  return 0;
3758 
3759    while (opt->desc != ODESC_END) {
3760       if (opt->desc != ODESC_DONE &&
3761 	  (opt->desc->group & group)) {
3762 	 if (opt->desc->func == OFUNC_FLAG) {
3763 	    if (opt->value.u_bool) {
3764 	       *result |= opt->desc->major;
3765 	    } else {
3766 	       *result &= ~opt->desc->major;
3767 	    }
3768 	    opt->desc = ODESC_DONE;
3769 	 } else if (opt->desc->func == OFUNC_FLAG_PATTERN) {
3770 	    *result &= ~opt->desc->minor;
3771 	    *result |= opt->desc->major;
3772 	    opt->desc = ODESC_DONE;
3773 	 }
3774       }
3775       ++opt;
3776    }
3777    return 0;
3778 }
3779 
3780 
3781 
3782 /* set the FD_CLOEXEC fcntl if the options do not set it to 0 */
applyopts_cloexec(int fd,struct opt * opts)3783 int applyopts_cloexec(int fd, struct opt *opts) {
3784    bool docloexec = 1;
3785 
3786    if (!opts)  return 0;
3787 
3788    retropt_bool(opts, OPT_CLOEXEC, &docloexec);
3789    if (docloexec) {
3790       if (Fcntl_l(fd, F_SETFD, FD_CLOEXEC) < 0) {
3791 	 Warn2("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", fd, strerror(errno));
3792       }
3793    }
3794    return 0;
3795 }
3796 
applyopts_fchown(int fd,struct opt * opts)3797 int applyopts_fchown(int fd, struct opt *opts) {
3798    uid_t user = -1;
3799    gid_t group = -1;
3800 
3801    retropt_uidt(opts, OPT_USER, &user);
3802    retropt_gidt(opts, OPT_GROUP, &group);
3803 
3804    if (user != (uid_t)-1 || group != (gid_t)-1) {
3805       if (Fchown(fd, user, group) < 0) {
3806 	 Error4("fchown(%d, "F_uid", "F_gid"): %s", fd, user, group,
3807 		strerror(errno));
3808 	 return STAT_RETRYLATER;
3809       }
3810    }
3811    return 0;
3812 }
3813 
3814 /* caller must make sure that option is not yet consumed */
applyopt_offset(struct single * xfd,struct opt * opt)3815 static int applyopt_offset(struct single *xfd, struct opt *opt) {
3816    unsigned char *ptr;
3817 
3818    ptr = (unsigned char *)xfd + opt->desc->major;
3819    switch (opt->desc->type) {
3820    case TYPE_BOOL:
3821       *(bool *)ptr = opt->value.u_bool;  break;
3822    case TYPE_INT:
3823       *(int *)ptr = opt->value.u_int;  break;
3824    case TYPE_DOUBLE:
3825       *(double *)ptr = opt->value.u_double;  break;
3826    case TYPE_TIMEVAL:
3827       *(struct timeval *)ptr = opt->value.u_timeval;  break;
3828    case TYPE_STRING_NULL:
3829       if (opt->value.u_string == NULL) {
3830 	 *(char **)ptr = NULL;
3831 	 break;
3832       }
3833       /* PASSTHROUGH */
3834    case TYPE_STRING:
3835       if ((*(char **)ptr = strdup(opt->value.u_string)) == NULL) {
3836 	 Error1("strdup("F_Zu"): out of memory",
3837 		strlen(opt->value.u_string)+1);
3838       }
3839       break;
3840    case TYPE_CONST:
3841       *(int *)ptr = opt->desc->minor;
3842       break;
3843    default:
3844       Error1("applyopt_offset(): type %d not implemented",
3845 	     opt->desc->type);
3846       return -1;
3847    }
3848    opt->desc = ODESC_DONE;
3849    return 0;
3850 }
3851 
applyopts_offset(struct single * xfd,struct opt * opts)3852 int applyopts_offset(struct single *xfd, struct opt *opts) {
3853    struct opt *opt;
3854 
3855    opt = opts; while (opt->desc != ODESC_END) {
3856       if ((opt->desc == ODESC_DONE) ||
3857 	  opt->desc->func != OFUNC_OFFSET)  {
3858 	 ++opt; continue; }
3859 
3860       applyopt_offset(xfd, opt);
3861       opt->desc = ODESC_DONE;
3862       ++opt;
3863    }
3864    return 0;
3865 }
3866 
3867 /* applies to xfd all OFUNC_EXT options belonging to phase
3868    returns -1 if an error occurred */
applyopts_single(struct single * xfd,struct opt * opts,enum e_phase phase)3869 int applyopts_single(struct single *xfd, struct opt *opts, enum e_phase phase) {
3870    struct opt *opt;
3871    int lockrc;
3872 
3873    if (!opts)  return 0;
3874 
3875    opt = opts; while (opt->desc != ODESC_END) {
3876       if ((opt->desc == ODESC_DONE) ||
3877 	  (opt->desc->phase != phase && phase != PH_ALL)) {
3878 	 /* option not handled in this function */
3879 	 ++opt; continue;
3880       } else {
3881      switch (opt->desc->func) {
3882 
3883      case OFUNC_OFFSET:
3884 	applyopt_offset(xfd, opt);
3885 	break;
3886 
3887      case OFUNC_EXT:
3888       switch (opt->desc->optcode) {
3889 #if 0
3890       case OPT_IGNOREEOF:
3891 	 xfd->ignoreeof = true;
3892 	 break;
3893       case OPT_CR:
3894 	 xfd->lineterm = LINETERM_CR;
3895 	 break;
3896       case OPT_CRNL:
3897 	 xfd->lineterm = LINETERM_CRNL;
3898 	 break;
3899 #endif /* 0 */
3900       case OPT_READBYTES:
3901 	 xfd->readbytes = opt->value.u_sizet;
3902 	 xfd->actbytes  = xfd->readbytes;
3903 	 break;
3904       case OPT_LOCKFILE:
3905 	 if (xfd->lock.lockfile) {
3906 	    Error("only one use of options lockfile and waitlock allowed");
3907 	 }
3908 	 xfd->lock.lockfile = strdup(opt->value.u_string);
3909 	 xfd->lock.intervall.tv_sec  = 1;
3910 	 xfd->lock.intervall.tv_nsec = 0;
3911 
3912 	 if ((lockrc = xiolock(&xfd->lock)) < 0) {
3913 	    /* error message already printed */
3914 	    return -1;
3915 	 }
3916 	 if (lockrc) {
3917 	    Error1("could not obtain lock \"%s\"", xfd->lock.lockfile);
3918 	 } else {
3919 	    xfd->havelock = true;
3920 	 }
3921 	 break;
3922       case OPT_WAITLOCK:
3923 	 if (xfd->lock.lockfile) {
3924 	    Error("only one use of options lockfile and waitlock allowed");
3925 	 }
3926 	 xfd->lock.lockfile = strdup(opt->value.u_string);
3927 	 xfd->lock.waitlock = true;
3928 	 xfd->lock.intervall.tv_sec  = 1;
3929 	 xfd->lock.intervall.tv_nsec = 0;
3930 
3931 	 /*! this should be integrated into central select()/poll() loop */
3932 	 if (xiolock(&xfd->lock) < 0) {
3933 	    return -1;
3934 	 }
3935 	 xfd->havelock = true;
3936 	 break;
3937 
3938       default:
3939 	 /* just store the value in the correct component of struct single */
3940 	 if (opt->desc->type == TYPE_CONST) {
3941 	    /* only for integral types compatible to int */
3942 	    *(int *)(&((char *)xfd)[opt->desc->major]) = opt->desc->arg3;
3943 	 } else {
3944 	    memcpy(&((char *)xfd)[opt->desc->major], &opt->value, opt->desc->minor);
3945 	 }
3946       }
3947       break;
3948 
3949      case OFUNC_OFFSET_MASKS:
3950 	{
3951 	   void *masks = (char *)xfd + opt->desc->major;
3952 	   size_t masksize = opt->desc->minor;
3953 	   unsigned long bit = opt->desc->arg3;
3954 	   switch (masksize>>1) {
3955 	   case sizeof(uint16_t):
3956 	      if (opt->value.u_bool) {
3957 		 ((uint16_t *)masks)[0] |= bit;
3958 	      } else {
3959 		 ((uint16_t *)masks)[1] |= bit;
3960 	      }
3961 	      break;
3962 	   case sizeof(uint32_t):
3963 	      if (opt->value.u_bool) {
3964 		 ((uint32_t *)masks)[0] |= bit;
3965 	      } else {
3966 		 ((uint32_t *)masks)[1] |= bit;
3967 	      }
3968 	      break;
3969 	   default:
3970 	      Info1("sizeof(uint32_t)="F_Zu, sizeof(uint32_t));
3971 	      Error1("applyopts_single: masksize "F_Zu" not implemented",
3972 		     masksize);
3973 	   }
3974 	}
3975 	break;
3976 
3977 #if _WITH_SOCKET
3978      case OFUNC_SOCKOPT:
3979 	 switch (opt->desc->optcode) {
3980 #if WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN))
3981 	 case OPT_IP_ADD_MEMBERSHIP:
3982 	    {
3983 	       union {
3984 #if HAVE_STRUCT_IP_MREQN
3985 		  struct ip_mreqn mreqn;
3986 #endif
3987 		  struct ip_mreq  mreq;
3988 	       } ip4_mreqn = {{{0}}};
3989 	       /* IPv6 not supported - seems to have different handling */
3990 /*
3991 mc:addr:ifname|ifind
3992 mc:ifname|ifind
3993 mc:addr
3994 */
3995 	       union sockaddr_union sockaddr1;
3996 	       socklen_t socklen1 = sizeof(sockaddr1.ip4);
3997 	       union sockaddr_union sockaddr2;
3998 	       socklen_t socklen2 = sizeof(sockaddr2.ip4);
3999 
4000 	       /* first parameter is alway multicast address */
4001 	       /*! result */
4002 	       xiogetaddrinfo(opt->value.u_ip_mreq.multiaddr, NULL,
4003 			      xfd->para.socket.la.soa.sa_family,
4004 			      SOCK_DGRAM, IPPROTO_IP,
4005 			      &sockaddr1, &socklen1, 0, 0);
4006 	       ip4_mreqn.mreq.imr_multiaddr = sockaddr1.ip4.sin_addr;
4007 	       if (0) {
4008 		  ;	/* for canonical reasons */
4009 #if HAVE_STRUCT_IP_MREQN
4010 	       } else if (opt->value.u_ip_mreq.ifindex[0] != '\0') {
4011 		  /* three parameters */
4012 		  /* second parameter is interface address */
4013 		  xiogetaddrinfo(opt->value.u_ip_mreq.param2, NULL,
4014 				 xfd->para.socket.la.soa.sa_family,
4015 				 SOCK_DGRAM, IPPROTO_IP,
4016 				 &sockaddr2, &socklen2, 0, 0);
4017 		  ip4_mreqn.mreq.imr_interface = sockaddr2.ip4.sin_addr;
4018 		  /* third parameter is interface */
4019 		  if (ifindex(opt->value.u_ip_mreq.ifindex,
4020 			      (unsigned int *)&ip4_mreqn.mreqn.imr_ifindex, -1)
4021 		      < 0) {
4022 		     Error1("cannot resolve interface \"%s\"",
4023 			    opt->value.u_ip_mreq.ifindex);
4024 		  }
4025 #endif /* HAVE_STRUCT_IP_MREQN */
4026 	       } else {
4027 		  /* two parameters */
4028 		  if (0) {
4029 		     ;	/* for canonical reasons */
4030 #if HAVE_STRUCT_IP_MREQN
4031 		  /* there is a form with two parameters that uses mreqn */
4032 		  } else if (ifindex(opt->value.u_ip_mreq.param2,
4033 				     (unsigned int *)&ip4_mreqn.mreqn.imr_ifindex,
4034 				     -1)
4035 			     >= 0) {
4036 		     /* yes, second param converts to interface */
4037 		     ip4_mreqn.mreq.imr_interface.s_addr = htonl(0);
4038 #endif /* HAVE_STRUCT_IP_MREQN */
4039 		  } else {
4040 		     /*! result */
4041 		     xiogetaddrinfo(opt->value.u_ip_mreq.param2, NULL,
4042 				    xfd->para.socket.la.soa.sa_family,
4043 				    SOCK_DGRAM, IPPROTO_IP,
4044 				    &sockaddr2, &socklen2, 0, 0);
4045 		     ip4_mreqn.mreq.imr_interface = sockaddr2.ip4.sin_addr;
4046 		  }
4047 	       }
4048 
4049 #if LATER
4050 	       if (0) {
4051 		  ; /* for canonical reasons */
4052 	       } else if (xfd->para.socket.la.soa.sa_family == PF_INET) {
4053 	       } else if (xfd->para.socket.la.soa.sa_family == PF_INET6) {
4054 		  ip6_mreqn.mreq.imr_multiaddr = sockaddr1.ip6.sin6_addr;
4055 		  ip6_mreqn.mreq.imr_interface = sockaddr2.ip6.sin6_addr;
4056 	       }
4057 #endif
4058 
4059 #if HAVE_STRUCT_IP_MREQN
4060 	       if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor,
4061 			      &ip4_mreqn.mreqn, sizeof(ip4_mreqn.mreqn)) < 0) {
4062 		  Error8("setsockopt(%d, %d, %d, {0x%08x,0x%08x,%d}, "F_Zu"): %s",
4063 			 xfd->fd, opt->desc->major, opt->desc->minor,
4064 			 ip4_mreqn.mreqn.imr_multiaddr.s_addr,
4065 			 ip4_mreqn.mreqn.imr_address.s_addr,
4066 			 ip4_mreqn.mreqn.imr_ifindex,
4067 			 sizeof(ip4_mreqn.mreqn),
4068 			 strerror(errno));
4069 		  opt->desc = ODESC_ERROR; continue;
4070 	       }
4071 #else
4072 	       if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor,
4073 			      &ip4_mreqn.mreq, sizeof(ip4_mreqn.mreq)) < 0) {
4074 		  Error7("setsockopt(%d, %d, %d, {0x%08x,0x%08x}, "F_Zu"): %s",
4075 			 xfd->fd, opt->desc->major, opt->desc->minor,
4076 			 ip4_mreqn.mreq.imr_multiaddr,
4077 			 ip4_mreqn.mreq.imr_interface,
4078 			 sizeof(ip4_mreqn.mreq),
4079 			 strerror(errno));
4080 		  opt->desc = ODESC_ERROR; continue;
4081 	       }
4082 #endif
4083 	       break;
4084 	    }
4085 	   break;
4086 #endif /* WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)) */
4087 
4088 #if WITH_IP4 && defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP)
4089 	 case OPT_IP_ADD_SOURCE_MEMBERSHIP:
4090 	    if (xioapply_ip_add_source_membership(xfd, opt) < 0) {
4091 	       continue;
4092 	    }
4093 	   break;
4094 #endif /* WITH_IP4 && defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP) */
4095 
4096 #if WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ)
4097 	 case OPT_IPV6_JOIN_GROUP:
4098 	    {
4099 	       struct ipv6_mreq ip6_mreq = {{{{0}}}};
4100 	       union sockaddr_union sockaddr1;
4101 	       socklen_t socklen1 = sizeof(sockaddr1.ip6);
4102 
4103 	       /* always two parameters */
4104 	       /* first parameter is multicast address */
4105 	       /*! result */
4106 	       xiogetaddrinfo(opt->value.u_ip_mreq.multiaddr, NULL,
4107 			      xfd->para.socket.la.soa.sa_family,
4108 			      SOCK_DGRAM, IPPROTO_IP,
4109 			      &sockaddr1, &socklen1, 0, 0);
4110 	       ip6_mreq.ipv6mr_multiaddr = sockaddr1.ip6.sin6_addr;
4111 	       if (ifindex(opt->value.u_ip_mreq.param2,
4112 			   &ip6_mreq.ipv6mr_interface, -1)
4113 		   < 0) {
4114 		  Error1("interface \"%s\" not found",
4115 			 opt->value.u_ip_mreq.param2);
4116 		  ip6_mreq.ipv6mr_interface = htonl(0);
4117 	       }
4118 
4119 	       if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor,
4120 			      &ip6_mreq, sizeof(ip6_mreq)) < 0) {
4121 		  Error6("setsockopt(%d, %d, %d, {...,0x%08x}, "F_Zu"): %s",
4122 			 xfd->fd, opt->desc->major, opt->desc->minor,
4123 			 ip6_mreq.ipv6mr_interface,
4124 			 sizeof(ip6_mreq),
4125 			 strerror(errno));
4126 		  opt->desc = ODESC_ERROR; continue;
4127 	       }
4128 	    }
4129 	   break;
4130 #endif /* WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ) */
4131 	default:
4132 	   /* ignore here */
4133 	   ++opt; continue;
4134 	}
4135 	break;
4136 #endif /* _WITH_SOCKET */
4137 
4138      default:
4139 	++opt;
4140 	continue;
4141      }
4142      opt->desc = ODESC_DONE;
4143      ++opt;
4144       }
4145    }
4146    return 0;
4147 }
4148 
4149 
4150 /* xfd->para.exec.pid must be set */
applyopts_signal(struct single * xfd,struct opt * opts)4151 int applyopts_signal(struct single *xfd, struct opt *opts) {
4152    struct opt *opt;
4153 
4154    if (!opts)  return 0;
4155 
4156    opt = opts; while (opt->desc != ODESC_END) {
4157       if (opt->desc == ODESC_DONE || opt->desc->func != OFUNC_SIGNAL) {
4158 	 ++opt; continue;
4159       }
4160 
4161       if (xio_opt_signal(xfd->para.exec.pid, opt->desc->major) < 0) {
4162 	 opt->desc = ODESC_ERROR; continue;
4163       }
4164       opt->desc = ODESC_DONE;
4165       ++opt;
4166    }
4167    return 0;
4168 }
4169 
4170 /* apply remaining options to file descriptor, and tell us if something is
4171    still unused */
_xio_openlate(struct single * fd,struct opt * opts)4172 int _xio_openlate(struct single *fd, struct opt *opts) {
4173    int numleft;
4174    int result;
4175 
4176    _xioopen_setdelayeduser();
4177 
4178    if ((result = applyopts(fd->fd, opts, PH_LATE)) < 0) {
4179       return result;
4180    }
4181    if ((result = applyopts_single(fd, opts, PH_LATE)) < 0) {
4182       return result;
4183    }
4184    if ((result = applyopts(fd->fd, opts, PH_LATE2)) < 0) {
4185       return result;
4186    }
4187 
4188    if ((numleft = leftopts(opts)) > 0) {
4189       showleft(opts);
4190       Error1("%d option(s) could not be used", numleft);
4191       return -1;
4192    }
4193    return 0;
4194 }
4195 
dropopts(struct opt * opts,unsigned int phase)4196 int dropopts(struct opt *opts, unsigned int phase) {
4197    struct opt *opt;
4198 
4199    if (phase == PH_ALL) {
4200       opts[0].desc = ODESC_END;
4201       return 0;
4202    }
4203    opt = opts; while (opt && opt->desc != ODESC_END) {
4204       if (opt->desc != ODESC_DONE && opt->desc->phase == phase) {
4205 	 Debug1("ignoring option \"%s\"", opt->desc->defname);
4206 	 opt->desc = ODESC_DONE;
4207       }
4208       ++opt;
4209    }
4210    return 0;
4211 }
4212 
dropopts2(struct opt * opts,unsigned int from,unsigned int to)4213 int dropopts2(struct opt *opts, unsigned int from, unsigned int to) {
4214    unsigned int i;
4215 
4216    for (i = from; i <= to; ++i) {
4217       dropopts(opts, i);
4218    }
4219    return 0;
4220 }
4221 
4222