Version 1.8.0.0
[socat.git] / sysutils.c
blobc62d555349aab2ff285257aad937b59ca98f6a10
1 /* source: sysutils.c */
2 /* Copyright Gerhard Rieger and contributors (see file CHANGES) */
3 /* Published under the GNU General Public License V.2, see file COPYING */
5 /* translate socket addresses into human readable form */
7 #include "config.h"
8 #include "xioconfig.h"
10 #include "sysincludes.h"
12 #include "compat.h" /* socklen_t */
13 #include "mytypes.h"
14 #include "error.h"
15 #include "sycls.h"
16 #include "utils.h"
17 #include "sysutils.h"
19 #if _WITH_INTERFACE
20 const int one = 1;
21 #endif
23 /* Substitute for Write():
24 Try to write all bytes before returning; this handles EINTR,
25 EAGAIN/EWOULDBLOCK, and partial write situations. The drawback is that this
26 function might block even with O_NONBLOCK option.
27 Returns <0 on unhandled error, errno valid
28 Will only return <0 or bytes
30 ssize_t writefull(int fd, const void *buff, size_t bytes) {
31 size_t writt = 0;
32 ssize_t chk;
33 while (1) {
34 chk = Write(fd, (const char *)buff + writt, bytes - writt);
35 if (chk < 0) {
36 switch (errno) {
37 case EINTR:
38 case EAGAIN:
39 #if EAGAIN != EWOULDBLOCK
40 case EWOULDBLOCK:
41 #endif
42 Warn4("write(%d, %p, "F_Zu"): %s", fd, (const char *)buff+writt, bytes-writt, strerror(errno));
43 Sleep(1); continue;
44 default: return -1;
46 } else if (writt+chk < bytes) {
47 Warn4("write(%d, %p, "F_Zu"): only wrote "F_Zu" bytes, trying to continue (rev.direction is blocked)",
48 fd, (const char *)buff+writt, bytes-writt, chk);
49 writt += chk;
50 } else {
51 writt = bytes;
52 break;
55 Notice3("write(%d, %p, "F_Zu") completed", fd, (const char *)buff, bytes);
56 return writt;
59 #if WITH_UNIX
60 void socket_un_init(struct sockaddr_un *sa) {
61 #if HAVE_STRUCT_SOCKADDR_SALEN
62 sa->sun_len = sizeof(struct sockaddr_un);
63 #endif
64 sa->sun_family = AF_UNIX;
65 memset(sa->sun_path, '\0', sizeof(sa->sun_path));
67 #endif /* WITH_UNIX */
69 #if WITH_IP4
70 void socket_in_init(struct sockaddr_in *sa) {
71 #if HAVE_STRUCT_SOCKADDR_SALEN
72 sa->sin_len = sizeof(struct sockaddr_in);
73 #endif
74 sa->sin_family = AF_INET;
75 sa->sin_port = 0;
76 sa->sin_addr.s_addr = 0;
77 sa->sin_zero[0] = 0;
78 sa->sin_zero[1] = 0;
79 sa->sin_zero[2] = 0;
80 sa->sin_zero[3] = 0;
81 sa->sin_zero[4] = 0;
82 sa->sin_zero[5] = 0;
83 sa->sin_zero[6] = 0;
84 sa->sin_zero[7] = 0;
86 #endif /* WITH_IP4 */
88 #if WITH_IP6
89 void socket_in6_init(struct sockaddr_in6 *sa) {
90 #if HAVE_STRUCT_SOCKADDR_SALEN
91 sa->sin6_len = sizeof(struct sockaddr_in6);
92 #endif
93 sa->sin6_family = AF_INET6;
94 sa->sin6_port = 0;
95 sa->sin6_flowinfo = 0;
96 #if HAVE_IP6_SOCKADDR==0
97 sa->sin6_addr.s6_addr[0] = 0;
98 sa->sin6_addr.s6_addr[1] = 0;
99 sa->sin6_addr.s6_addr[2] = 0;
100 sa->sin6_addr.s6_addr[3] = 0;
101 sa->sin6_addr.s6_addr[4] = 0;
102 sa->sin6_addr.s6_addr[5] = 0;
103 sa->sin6_addr.s6_addr[6] = 0;
104 sa->sin6_addr.s6_addr[7] = 0;
105 sa->sin6_addr.s6_addr[8] = 0;
106 sa->sin6_addr.s6_addr[9] = 0;
107 sa->sin6_addr.s6_addr[10] = 0;
108 sa->sin6_addr.s6_addr[11] = 0;
109 sa->sin6_addr.s6_addr[12] = 0;
110 sa->sin6_addr.s6_addr[13] = 0;
111 sa->sin6_addr.s6_addr[14] = 0;
112 sa->sin6_addr.s6_addr[15] = 0;
113 #elif HAVE_IP6_SOCKADDR==1
114 sa->sin6_addr.u6_addr.u6_addr32[0] = 0;
115 sa->sin6_addr.u6_addr.u6_addr32[1] = 0;
116 sa->sin6_addr.u6_addr.u6_addr32[2] = 0;
117 sa->sin6_addr.u6_addr.u6_addr32[3] = 0;
118 #elif HAVE_IP6_SOCKADDR==2
119 sa->sin6_addr.u6_addr32[0] = 0;
120 sa->sin6_addr.u6_addr32[1] = 0;
121 sa->sin6_addr.u6_addr32[2] = 0;
122 sa->sin6_addr.u6_addr32[3] = 0;
123 #elif HAVE_IP6_SOCKADDR==3
124 sa->sin6_addr.in6_u.u6_addr32[0] = 0;
125 sa->sin6_addr.in6_u.u6_addr32[1] = 0;
126 sa->sin6_addr.in6_u.u6_addr32[2] = 0;
127 sa->sin6_addr.in6_u.u6_addr32[3] = 0;
128 #elif HAVE_IP6_SOCKADDR==4
129 sa->sin6_addr._S6_un._S6_u32[0] = 0;
130 sa->sin6_addr._S6_un._S6_u32[1] = 0;
131 sa->sin6_addr._S6_un._S6_u32[2] = 0;
132 sa->sin6_addr._S6_un._S6_u32[3] = 0;
133 #elif HAVE_IP6_SOCKADDR==5
134 sa->sin6_addr.__u6_addr.__u6_addr32[0] = 0;
135 sa->sin6_addr.__u6_addr.__u6_addr32[1] = 0;
136 sa->sin6_addr.__u6_addr.__u6_addr32[2] = 0;
137 sa->sin6_addr.__u6_addr.__u6_addr32[3] = 0;
138 #endif
140 #endif /* WITH_IP6 */
143 #if _WITH_SOCKET
144 /* initializes the socket address of the specified address family. Returns the
145 length of the specific socket address, or 0 on error. */
146 socklen_t socket_init(int af, union sockaddr_union *sa) {
147 switch (af) {
148 case AF_UNSPEC: memset(sa, 0, sizeof(*sa)); return sizeof(*sa);
149 #if WITH_UNIX
150 case AF_UNIX: socket_un_init(&sa->un); return sizeof(sa->un);
151 #endif
152 #if WITH_IP4
153 case AF_INET: socket_in_init(&sa->ip4); return sizeof(sa->ip4);
154 #endif
155 #if WITH_IP6
156 case AF_INET6: socket_in6_init(&sa->ip6); return sizeof(sa->ip6);
157 #endif
158 default: Info1("socket_init(): unknown address family %d", af);
159 memset(sa, 0, sizeof(union sockaddr_union));
160 sa->soa.sa_family = af;
161 return 0;
164 #endif /* _WITH_SOCKET */
166 #if WITH_UNIX
167 #define XIOUNIXSOCKOVERHEAD (sizeof(struct sockaddr_un)-sizeof(((struct sockaddr_un*)0)->sun_path))
168 #endif
170 #if _WITH_SOCKET
171 /* writes a textual human readable representation of the sockaddr contents to buff and returns a pointer to buff
172 writes at most blen bytes to buff including the terminating \0 byte
174 char *sockaddr_info(const struct sockaddr *sa, socklen_t salen, char *buff, size_t blen) {
175 union sockaddr_union *sau = (union sockaddr_union *)sa;
176 char *lbuff = buff;
177 char *cp = lbuff;
178 int n;
180 #if HAVE_STRUCT_SOCKADDR_SALEN
181 n = xio_snprintf(cp, blen, "LEN=%d ", sau->soa.sa_len);
182 if (n < 0 || n >= blen) {
183 Warn1("sockaddr_info(): buffer too short ("F_Zu")", blen);
184 *buff = '\0';
185 return buff;
187 cp += n, blen -= n;
188 #endif
189 n = xio_snprintf(cp, blen, "AF=%d ", sau->soa.sa_family);
190 if (n < 0 || n >= blen) {
191 Warn1("sockaddr_info(): buffer too short ("F_Zu")", blen);
192 *buff = '\0';
193 return buff;
195 cp += n, blen -= n;
197 switch (sau->soa.sa_family) {
198 #if WITH_UNIX
199 case 0:
200 case AF_UNIX:
201 *cp++ = '"'; --blen;
202 sockaddr_unix_info(&sau->un, salen, cp, blen-1);
203 blen -= strlen(cp);
204 cp = strchr(cp, '\0');
205 *cp++ = '"'; --blen;
206 if (blen > 0)
207 *cp = '\0';
208 break;
209 #endif
210 #if WITH_IP4
211 case AF_INET: sockaddr_inet4_info(&sau->ip4, cp, blen);
212 break;
213 #endif
214 #if WITH_IP6
215 case AF_INET6: sockaddr_inet6_info(&sau->ip6, cp, blen);
216 break;
217 #endif
218 #if WITH_VSOCK
219 case AF_VSOCK: sockaddr_vm_info(&sau->vm, cp, blen);
220 break;
221 #endif
222 default:
223 n = xio_snprintf(cp, blen, "AF=%d ", sa->sa_family);
224 if (n < 0 || n >= blen) {
225 Warn1("sockaddr_info(): buffer too short ("F_Zu")", blen);
226 *buff = '\0';
227 return buff;
229 cp += n, blen -= n;
230 n = xio_snprintf(cp, blen,
231 "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
232 ((unsigned char *)sau->soa.sa_data)[0],
233 ((unsigned char *)sau->soa.sa_data)[1],
234 ((unsigned char *)sau->soa.sa_data)[2],
235 ((unsigned char *)sau->soa.sa_data)[3],
236 ((unsigned char *)sau->soa.sa_data)[4],
237 ((unsigned char *)sau->soa.sa_data)[5],
238 ((unsigned char *)sau->soa.sa_data)[6],
239 ((unsigned char *)sau->soa.sa_data)[7],
240 ((unsigned char *)sau->soa.sa_data)[8],
241 ((unsigned char *)sau->soa.sa_data)[9],
242 ((unsigned char *)sau->soa.sa_data)[10],
243 ((unsigned char *)sau->soa.sa_data)[11],
244 ((unsigned char *)sau->soa.sa_data)[12],
245 ((unsigned char *)sau->soa.sa_data)[13]);
246 if (n < 0 || n >= blen) {
247 Warn("sockaddr_info(): buffer too short");
248 *buff = '\0';
249 return buff;
252 return lbuff;
254 #endif /* _WITH_SOCKET */
257 #if WITH_UNIX
258 char *sockaddr_unix_info(const struct sockaddr_un *sa, socklen_t salen, char *buff, size_t blen) {
259 char ubuff[5*UNIX_PATH_MAX+3];
260 char *nextc;
262 #if WITH_ABSTRACT_UNIXSOCKET
263 if (salen > XIOUNIXSOCKOVERHEAD &&
264 sa->sun_path[0] == '\0') {
265 nextc =
266 sanitize_string(sa->sun_path, salen-XIOUNIXSOCKOVERHEAD,
267 ubuff, XIOSAN_DEFAULT_BACKSLASH_OCT_3);
268 } else
269 #endif /* WITH_ABSTRACT_UNIXSOCKET */
271 if (salen <= XIOUNIXSOCKOVERHEAD) {
272 nextc = sanitize_string ("<anon>", MIN(UNIX_PATH_MAX, strlen("<anon>")),
273 ubuff, XIOSAN_DEFAULT_BACKSLASH_OCT_3);
274 } else {
275 nextc = sanitize_string(sa->sun_path,
276 MIN(UNIX_PATH_MAX, strlen(sa->sun_path)),
277 ubuff, XIOSAN_DEFAULT_BACKSLASH_OCT_3);
280 *nextc = '\0';
281 buff[0] = '\0'; strncat(buff, ubuff, blen-1);
282 return buff;
284 #endif /* WITH_UNIX */
286 #if WITH_IP4
287 /* addr in host byte order! */
288 char *inet4addr_info(uint32_t addr, char *buff, size_t blen) {
289 if (xio_snprintf(buff, blen, "%u.%u.%u.%u",
290 (unsigned int)(addr >> 24), (unsigned int)((addr >> 16) & 0xff),
291 (unsigned int)((addr >> 8) & 0xff), (unsigned int)(addr & 0xff)) >= blen) {
292 Warn("inet4addr_info(): buffer too short");
293 buff[blen-1] = '\0';
295 return buff;
297 #endif /* WITH_IP4 */
299 #if WITH_IP4
300 char *sockaddr_inet4_info(const struct sockaddr_in *sa, char *buff, size_t blen) {
301 if (xio_snprintf(buff, blen, "%u.%u.%u.%u:%hu",
302 ((unsigned char *)&sa->sin_addr.s_addr)[0],
303 ((unsigned char *)&sa->sin_addr.s_addr)[1],
304 ((unsigned char *)&sa->sin_addr.s_addr)[2],
305 ((unsigned char *)&sa->sin_addr.s_addr)[3],
306 htons(sa->sin_port)) >= blen) {
307 Warn("sockaddr_inet4_info(): buffer too short");
308 buff[blen-1] = '\0';
310 return buff;
312 #endif /* WITH_IP4 */
314 #if WITH_VSOCK
315 char *sockaddr_vm_info(const struct sockaddr_vm *sa, char *buff, size_t blen) {
316 if (xio_snprintf(buff, blen, "cid:%u port:%u", sa->svm_cid, sa->svm_port) >= blen) {
317 Warn("sockaddr_vm_info(): buffer too short");
318 buff[blen-1] = '\0';
320 return buff;
323 int sockaddr_vm_parse(struct sockaddr_vm *sa, const char *cid_str,
324 const char *port_str)
326 char *garbage = NULL;
327 if (!cid_str) {
328 sa->svm_cid = VMADDR_CID_ANY;
329 } else {
330 sa->svm_cid = strtoul(cid_str, &garbage, 0);
331 if (*garbage != '\0') {
332 Error1("sockaddr_vm - garbage in cid: \"%s\"", garbage);
333 return -EINVAL;
337 if (!port_str) {
338 sa->svm_port = VMADDR_PORT_ANY;
339 } else {
340 sa->svm_port = strtoul(port_str, &garbage, 0);
341 if (*garbage != '\0') {
342 Error1("sockaddr_vm - garbage in port: \"%s\"", garbage);
343 return -EINVAL;
347 return 0;
349 #endif /* WITH_IP4 */
351 #if !HAVE_INET_NTOP
352 /* http://www.opengroup.org/onlinepubs/000095399/functions/inet_ntop.html */
353 const char *inet_ntop(int pf, const void *binaddr,
354 char *addrtext, socklen_t textlen) {
355 size_t retlen;
356 switch (pf) {
357 case PF_INET:
358 if ((retlen =
359 xio_snprintf(addrtext, textlen, "%u.%u.%u.%u",
360 ((unsigned char *)binaddr)[0],
361 ((unsigned char *)binaddr)[1],
362 ((unsigned char *)binaddr)[2],
363 ((unsigned char *)binaddr)[3]))
364 >= textlen) {
365 errno = ENOSPC; return NULL;
367 break;
368 #if WITH_IP6
369 case PF_INET6:
370 if ((retlen =
371 xio_snprintf(addrtext, textlen, "%x:%x:%x:%x:%x:%x:%x:%x",
372 ntohs(((uint16_t *)binaddr)[0]),
373 ntohs(((uint16_t *)binaddr)[1]),
374 ntohs(((uint16_t *)binaddr)[2]),
375 ntohs(((uint16_t *)binaddr)[3]),
376 ntohs(((uint16_t *)binaddr)[4]),
377 ntohs(((uint16_t *)binaddr)[5]),
378 ntohs(((uint16_t *)binaddr)[6]),
379 ntohs(((uint16_t *)binaddr)[7])
381 >= textlen) {
382 errno = ENOSPC; return NULL;
384 break;
385 #endif /* WITH_IP6 */
386 default:
387 errno = EAFNOSUPPORT;
388 return NULL;
390 addrtext[retlen] = '\0';
391 return addrtext;
393 #endif /* !HAVE_INET_NTOP */
395 #if WITH_IP6
396 /* convert the IP6 socket address to human readable form. buff should be at
397 least 50 chars long. output includes the port number */
398 char *sockaddr_inet6_info(const struct sockaddr_in6 *sa, char *buff, size_t blen) {
399 if (xio_snprintf(buff, blen, "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]:%hu",
400 #if HAVE_IP6_SOCKADDR==0
401 (sa->sin6_addr.s6_addr[0]<<8)+
402 sa->sin6_addr.s6_addr[1],
403 (sa->sin6_addr.s6_addr[2]<<8)+
404 sa->sin6_addr.s6_addr[3],
405 (sa->sin6_addr.s6_addr[4]<<8)+
406 sa->sin6_addr.s6_addr[5],
407 (sa->sin6_addr.s6_addr[6]<<8)+
408 sa->sin6_addr.s6_addr[7],
409 (sa->sin6_addr.s6_addr[8]<<8)+
410 sa->sin6_addr.s6_addr[9],
411 (sa->sin6_addr.s6_addr[10]<<8)+
412 sa->sin6_addr.s6_addr[11],
413 (sa->sin6_addr.s6_addr[12]<<8)+
414 sa->sin6_addr.s6_addr[13],
415 (sa->sin6_addr.s6_addr[14]<<8)+
416 sa->sin6_addr.s6_addr[15],
417 #elif HAVE_IP6_SOCKADDR==1
418 ntohs(((unsigned short *)&sa->sin6_addr.u6_addr.u6_addr16)[0]),
419 ntohs(((unsigned short *)&sa->sin6_addr.u6_addr.u6_addr16)[1]),
420 ntohs(((unsigned short *)&sa->sin6_addr.u6_addr.u6_addr16)[2]),
421 ntohs(((unsigned short *)&sa->sin6_addr.u6_addr.u6_addr16)[3]),
422 ntohs(((unsigned short *)&sa->sin6_addr.u6_addr.u6_addr16)[4]),
423 ntohs(((unsigned short *)&sa->sin6_addr.u6_addr.u6_addr16)[5]),
424 ntohs(((unsigned short *)&sa->sin6_addr.u6_addr.u6_addr16)[6]),
425 ntohs(((unsigned short *)&sa->sin6_addr.u6_addr.u6_addr16)[7]),
426 #elif HAVE_IP6_SOCKADDR==2
427 ntohs(((unsigned short *)&sa->sin6_addr.u6_addr16)[0]),
428 ntohs(((unsigned short *)&sa->sin6_addr.u6_addr16)[1]),
429 ntohs(((unsigned short *)&sa->sin6_addr.u6_addr16)[2]),
430 ntohs(((unsigned short *)&sa->sin6_addr.u6_addr16)[3]),
431 ntohs(((unsigned short *)&sa->sin6_addr.u6_addr16)[4]),
432 ntohs(((unsigned short *)&sa->sin6_addr.u6_addr16)[5]),
433 ntohs(((unsigned short *)&sa->sin6_addr.u6_addr16)[6]),
434 ntohs(((unsigned short *)&sa->sin6_addr.u6_addr16)[7]),
435 #elif HAVE_IP6_SOCKADDR==3
436 ntohs(((unsigned short *)&sa->sin6_addr.in6_u.u6_addr16)[0]),
437 ntohs(((unsigned short *)&sa->sin6_addr.in6_u.u6_addr16)[1]),
438 ntohs(((unsigned short *)&sa->sin6_addr.in6_u.u6_addr16)[2]),
439 ntohs(((unsigned short *)&sa->sin6_addr.in6_u.u6_addr16)[3]),
440 ntohs(((unsigned short *)&sa->sin6_addr.in6_u.u6_addr16)[4]),
441 ntohs(((unsigned short *)&sa->sin6_addr.in6_u.u6_addr16)[5]),
442 ntohs(((unsigned short *)&sa->sin6_addr.in6_u.u6_addr16)[6]),
443 ntohs(((unsigned short *)&sa->sin6_addr.in6_u.u6_addr16)[7]),
444 #elif HAVE_IP6_SOCKADDR==4
445 (sa->sin6_addr._S6_un._S6_u8[0]<<8)|(sa->sin6_addr._S6_un._S6_u8[1]&0xff),
446 (sa->sin6_addr._S6_un._S6_u8[2]<<8)|(sa->sin6_addr._S6_un._S6_u8[3]&0xff),
447 (sa->sin6_addr._S6_un._S6_u8[4]<<8)|(sa->sin6_addr._S6_un._S6_u8[5]&0xff),
448 (sa->sin6_addr._S6_un._S6_u8[6]<<8)|(sa->sin6_addr._S6_un._S6_u8[7]&0xff),
449 (sa->sin6_addr._S6_un._S6_u8[8]<<8)|(sa->sin6_addr._S6_un._S6_u8[9]&0xff),
450 (sa->sin6_addr._S6_un._S6_u8[10]<<8)|(sa->sin6_addr._S6_un._S6_u8[11]&0xff),
451 (sa->sin6_addr._S6_un._S6_u8[12]<<8)|(sa->sin6_addr._S6_un._S6_u8[13]&0xff),
452 (sa->sin6_addr._S6_un._S6_u8[14]<<8)|(sa->sin6_addr._S6_un._S6_u8[15]&0xff),
453 #elif HAVE_IP6_SOCKADDR==5
454 ntohs(((unsigned short *)&sa->sin6_addr.__u6_addr.__u6_addr16)[0]),
455 ntohs(((unsigned short *)&sa->sin6_addr.__u6_addr.__u6_addr16)[1]),
456 ntohs(((unsigned short *)&sa->sin6_addr.__u6_addr.__u6_addr16)[2]),
457 ntohs(((unsigned short *)&sa->sin6_addr.__u6_addr.__u6_addr16)[3]),
458 ntohs(((unsigned short *)&sa->sin6_addr.__u6_addr.__u6_addr16)[4]),
459 ntohs(((unsigned short *)&sa->sin6_addr.__u6_addr.__u6_addr16)[5]),
460 ntohs(((unsigned short *)&sa->sin6_addr.__u6_addr.__u6_addr16)[6]),
461 ntohs(((unsigned short *)&sa->sin6_addr.__u6_addr.__u6_addr16)[7]),
462 #endif
463 ntohs(sa->sin6_port)) >= blen) {
464 Warn("sockaddr_inet6_info(): buffer too short");
466 return buff;
468 #endif /* WITH_IP6 */
471 #if WITH_IP4
472 /* Checks if the given string is an IPv4 address.
473 Returns 0 when it is an address.
474 Returns 1 when it is not an address.
475 Returns -1 when an error occurred (bad regex - internal) */
476 int check_ip4addr(
477 const char *address)
479 #if HAVE_REGEX_H
480 regex_t preg;
481 if (regcomp(&preg, "^(25[0-5]|(2[0-4]|1[0-9]|[1-9]?)[0-9])\\.(25[0-5]|(2[0-4]|1[0-9]|[1-9]?)[0-9])\\.(25[0-5]|(2[0-4]|1[0-9]|[1-9]?)[0-9])\\.(25[0-5]|(2[0-4]|1[0-9]|[1-9]?)[0-9])$", REG_EXTENDED|REG_NOSUB)
482 != 0) {
483 return -1; /* do not handle, just state that no match */
485 if (regexec(&preg, address, 0, NULL, 0) == 0) {
486 return 0;
488 #endif /* HAVE_REGEX_H */
489 /* Fallback when no regexec() compiled in */
490 return 1;
492 #endif /* WITH_IP4 */
494 #if WITH_IP6
495 /* Checks if the given string is an IPv6 address.
496 Currently a hack, just checks a few criteria.
497 Returns 0 when it is an address.
498 Returns 1 when it is not an address.
499 Returns -1 when an error occurred (bad regex - internal) */
500 int check_ip6addr(
501 const char *address)
503 #if HAVE_REGEX_H
504 regex_t preg;
505 if (regcomp(&preg, "^\\[[0-9a-fA-F:]*\\]$", REG_EXTENDED|REG_NOSUB)
506 != 0) {
507 return -1; /* do not handle, just state that no match */
509 if (regexec(&preg, address, 0, NULL, 0) == 0) {
510 return 0;
512 #endif /* HAVE_REGEX_H */
513 /* Fallback when no regexec() compiled in */
514 return 1;
516 #endif /* WITH_IP6 */
518 /* Checks if the given string is an IPv6 address.
519 Currently a hack, just checks a few criteria.
520 Returns 0 when it is an address.
521 Returns 1 when it is not an address or on error. */
522 int check_ipaddr(
523 const char *address)
525 int res4, res6;
526 #if WITH_IP4
527 if ((res4 = check_ip4addr(address)) == 0) {
528 return 0;
530 #endif
531 #if WITH_IP6
532 if ((res6 = check_ip6addr(address)) == 0) {
533 return 0;
535 #endif
536 return 1;
540 #if HAVE_GETGROUPLIST || (defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT))
541 /* fills the list with the supplementary group ids of user.
542 caller passes size of list in ngroups, function returns number of groups in
543 ngroups.
544 function returns 0 if 0 or more groups were found, or 1 if the list is too
545 short. */
546 int getusergroups(const char *user, gid_t *list, int *ngroups) {
547 #if HAVE_GETGROUPLIST
548 /* we prefer getgrouplist because it may be much faster with many groups, but it is not standard */
549 gid_t grp, twogrps[2];
550 int two = 2;
551 /* getgrouplist requires to pass an extra group id, typically the users primary group, that is then added to the supplementary group list. We don't want such an additional group in the result, but there is not "unspecified" gid value available. Thus we try to find an abitrary supplementary group id that we then pass in a second call to getgrouplist. */
552 grp = 0;
553 Getgrouplist(user, grp, twogrps, &two);
554 if (two == 1) {
555 /* either user has just this supp group, or none; we try another id */
556 grp = 1; two = 2;
557 Getgrouplist(user, grp, twogrps, &two);
558 if (two == 1) {
559 /* user has no supp group */
560 *ngroups = 0;
561 return 0;
563 /* user has just the first tried group */
564 *ngroups = 1; list[0] = grp;
565 return 0;
567 /* find the first supp group that is not our grp, and use its id */
568 if (twogrps[0] == grp) {
569 grp = twogrps[1];
570 } else {
571 grp = twogrps[0];
573 if (Getgrouplist(user, grp, list, ngroups) < 0) {
574 return 1;
576 return 0;
578 #elif defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT)
579 /* this is standard (POSIX) but may be slow */
581 struct group *grp;
582 int i = 0;
584 setgrent();
585 while (grp = getgrent()) {
586 char **gusr = grp->gr_mem;
587 while (*gusr) {
588 if (!strcmp(*gusr, user)) {
589 if (i == *ngroups)
590 return 1;
591 list[i++] = grp->gr_gid;
592 break;
594 ++gusr;
597 endgrent();
598 *ngroups = i;
599 return 0;
600 #endif /* HAVE_SETGRENT... */
602 #endif
604 #if !HAVE_HSTRERROR
605 const char *hstrerror(int err) {
606 static const char *h_messages[] = {
607 "success",
608 "authoritative answer not found",
609 "non-authoritative, host not found, or serverfail",
610 "Host name lookup failure", /* "non recoverable error" */
611 "valid name, no data record of requested type" };
613 assert(HOST_NOT_FOUND==1);
614 assert(TRY_AGAIN==2);
615 assert(NO_RECOVERY==3);
616 assert(NO_DATA==4);
617 if ((err < 0) || err > sizeof(h_messages)/sizeof(const char *)) {
618 return "";
620 return h_messages[err];
622 #endif /* !HAVE_HSTRERROR */
625 /* this function behaves like poll(). It tries to do so even when the poll()
626 system call is not available. */
627 /* note: glibc 5.4 does not know nfds_t */
628 int xiopoll(struct pollfd fds[], unsigned long nfds, struct timeval *timeout) {
629 int i, n = 0;
630 int result = 0;
632 while (true) { /* should be if (), but we want to break */
633 fd_set readfds;
634 fd_set writefds;
635 fd_set exceptfds;
637 FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds);
638 for (i = 0; i < nfds; ++i) {
639 fds[i].revents = 0;
640 if (fds[i].fd < 0) { continue; }
641 if (fds[i].fd > FD_SETSIZE) { break; /* use poll */ }
642 if (fds[i].events & POLLIN) {
643 FD_SET(fds[i].fd, &readfds); n = MAX(n, fds[i].fd); }
644 if (fds[i].events & POLLOUT) {
645 FD_SET(fds[i].fd, &writefds); n = MAX(n, fds[i].fd); }
647 if (i < nfds) { break; /* use poll */ }
649 result = Select(n+1, &readfds, &writefds, &exceptfds, timeout);
650 if (result < 0) { return result; }
651 for (i = 0; i < nfds; ++i) {
652 if (fds[i].fd < 0) { continue; }
653 if ((fds[i].events & POLLIN) && FD_ISSET(fds[i].fd, &readfds)) {
654 fds[i].revents |= POLLIN; ++result;
656 if ((fds[i].events & POLLOUT) && FD_ISSET(fds[i].fd, &writefds)) {
657 fds[i].revents |= POLLOUT; ++result;
660 return result;
663 #if HAVE_POLL
664 int ms = 0;
665 if (timeout == NULL) {
666 ms = -1;
667 } else {
668 ms = 1000*timeout->tv_sec + timeout->tv_usec/1000;
670 /*! timeout */
671 return Poll(fds, nfds, ms);
672 #else /* HAVE_POLL */
673 Error("poll() not available");
674 return -1;
675 #endif /* !HAVE_POLL */
680 #if WITH_TCP || WITH_UDP
681 /* returns port in network byte order;
682 ipproto==IPPROTO_UDP resolves as UDP service, every other value resolves as
683 TCP */
684 int parseport(const char *portname, int ipproto) {
685 struct servent *se;
686 char *extra;
687 int result;
689 if (isdigit(portname[0]&0xff)) {
690 result = htons(strtoul(portname, &extra, 0));
691 if (*extra != '\0') {
692 Error3("parseport(\"%s\", %d): extra trailing data \"%s\"",
693 portname, ipproto, extra);
695 return result;
698 if ((se = getservbyname(portname, ipproto==IPPROTO_UDP?"udp":"tcp")) == NULL) {
699 Error2("cannot resolve service \"%s/%d\"", portname, ipproto);
700 return 0;
703 return se->s_port;
705 #endif /* WITH_TCP || WITH_UDP */
708 #if WITH_IP4 || WITH_IP6 || WITH_INTERFACE
709 /* check the systems interfaces for ifname and return its index
710 or -1 if no interface with this name was found
711 The system calls require an arbitrary socket; the calling program may
712 provide one in anysock to avoid creation of a dummy socket. anysock must be
713 <0 if it does not specify a socket fd.
715 int ifindexbyname(const char *ifname, int anysock) {
716 /* Linux: man 7 netdevice */
717 /* FreeBSD: man 4 networking */
718 /* Solaris: man 7 if_tcp */
720 #if defined(HAVE_STRUCT_IFREQ) && defined(SIOCGIFCONF) && defined(SIOCGIFINDEX)
721 /* currently we support Linux, FreeBSD; not Solaris */
723 #define IFBUFSIZ 32*sizeof(struct ifreq) /*1024*/
724 int s;
725 struct ifreq ifr;
727 if (ifname[0] == '\0') {
728 return -1;
730 if (anysock >= 0) {
731 s = anysock;
732 } else if ((s = Socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) {
733 Error1("socket(PF_INET, SOCK_DGRAM, IPPROTO_IP): %s", strerror(errno));
734 return -1;
737 strncpy(ifr.ifr_name, ifname, IFNAMSIZ); /* ok */
738 if (Ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
739 Info3("ioctl(%d, SIOCGIFINDEX, {\"%s\"}): %s",
740 s, ifr.ifr_name, strerror(errno));
741 Close(s);
742 return -1;
744 Close(s);
745 #if HAVE_STRUCT_IFREQ_IFR_INDEX
746 Info3("ioctl(%d, SIOCGIFINDEX, {\"%s\"}) -> { %d }",
747 s, ifname, ifr.ifr_index);
748 return ifr.ifr_index;
749 #elif HAVE_STRUCT_IFREQ_IFR_IFINDEX
750 Info3("ioctl(%d, SIOCGIFINDEX, {\"%s\"}) -> { %d }",
751 s, ifname, ifr.ifr_ifindex);
752 return ifr.ifr_ifindex;
753 #endif /* HAVE_STRUCT_IFREQ_IFR_IFINDEX */
755 #else /* !defined(HAVE_ STRUCT_IFREQ) && defined(SIOCGIFCONF) && defined(SIOCGIFINDEX) */
756 return -1;
757 #endif /* !defined(HAVE_ STRUCT_IFREQ) && defined(SIOCGIFCONF) && defined(SIOCGIFINDEX) */
759 #endif /* WITH_IP4 || WITH_IP6 || WITH_INTERFACE */
762 #if WITH_IP4 || WITH_IP6 || WITH_INTERFACE
763 /* like ifindexbyname(), but also allows the index number as input - in this
764 case it does not lookup the index.
765 writes the resulting index to *ifindex and returns 0,
766 or returns -1 on error */
767 int ifindex(const char *ifname, unsigned int *ifindex, int anysock) {
768 char *endptr;
769 long int val;
771 if (ifname[0] == '\0') {
772 return -1;
774 val = strtol(ifname, &endptr, 0);
775 if (endptr[0] == '\0') {
776 *ifindex = val;
777 return 0;
780 if ((val = ifindexbyname(ifname, anysock)) < 0) {
781 return -1;
783 *ifindex = val;
784 return 0;
786 #endif /* WITH_IP4 || WITH_IP6 || WITH_INTERFACE */
789 int _xiosetenv(const char *envname, const char *value, int overwrite, const char *sep) {
790 char *oldval;
791 char *newval;
792 if (overwrite >= 2 && (oldval = getenv(envname)) != NULL) {
793 size_t newlen = strlen(oldval)+strlen(sep)+strlen(value)+1;
794 if ((newval = Malloc(newlen+1)) == NULL) {
795 return -1;
797 snprintf(newval, newlen+1, "%s%s%s", oldval, sep, value);
798 } else {
799 newval = (char *)value;
801 if (Setenv(envname, newval, overwrite) < 0) {
802 Warn3("setenv(\"%s\", \"%s\", 1): %s",
803 envname, value, strerror(errno));
804 #if HAVE_UNSETENV
805 Unsetenv(envname); /* dont want to have a wrong value */
806 #endif
807 return -1;
809 return 0;
812 /* constructs an environment variable whose name is built from socats uppercase
813 program name, and underscore and varname;
814 if the variable of this name already exists arg overwrite determines:
815 0: keep old value
816 1: overwrite with new value
817 2: append to old value, separated by *sep
818 returns 0 on success or <0 if an error occurred. */
819 int xiosetenv(const char *varname, const char *value, int overwrite, const char *sep) {
820 # define XIO_ENVNAMELEN 256
821 const char *progname;
822 char envname[XIO_ENVNAMELEN];
823 size_t i, l;
825 progname = diag_get_string('p');
826 envname[0] = '\0'; strncat(envname, progname, XIO_ENVNAMELEN-1);
827 l = strlen(envname);
828 for (i = 0; i < l; ++i) envname[i] = toupper((unsigned char)envname[i]);
829 strncat(envname+l, "_", XIO_ENVNAMELEN-l-1);
830 l += 1;
831 strncat(envname+l, varname, XIO_ENVNAMELEN-l-1);
832 return _xiosetenv(envname, value, overwrite, sep);
833 # undef XIO_ENVNAMELEN
836 int xiosetenv2(const char *varname, const char *varname2, const char *value,
837 int overwrite, const char *sep) {
838 # define XIO_ENVNAMELEN 256
839 const char *progname;
840 char envname[XIO_ENVNAMELEN];
841 size_t i, l;
843 progname = diag_get_string('p');
844 envname[0] = '\0'; strncat(envname, progname, XIO_ENVNAMELEN-1);
845 l = strlen(progname);
846 strncat(envname+l, "_", XIO_ENVNAMELEN-l-1);
847 l += 1;
848 strncat(envname+l, varname, XIO_ENVNAMELEN-l-1);
849 l += strlen(envname+l);
850 strncat(envname+l, "_", XIO_ENVNAMELEN-l-1);
851 l += 1;
852 strncat(envname+l, varname2, XIO_ENVNAMELEN-l-1);
853 l += strlen(envname+l);
854 for (i = 0; i < l; ++i) envname[i] = toupper((unsigned char)envname[i]);
855 return _xiosetenv(envname, value, overwrite, sep);
856 # undef XIO_ENVNAMELEN
859 int xiosetenv3(const char *varname, const char *varname2, const char *varname3,
860 const char *value,
861 int overwrite, const char *sep) {
862 # define XIO_ENVNAMELEN 256
863 const char *progname;
864 char envname[XIO_ENVNAMELEN];
865 size_t i, l;
867 progname = diag_get_string('p');
868 envname[0] = '\0'; strncat(envname, progname, XIO_ENVNAMELEN-1);
869 l = strlen(progname);
870 strncat(envname+l, "_", XIO_ENVNAMELEN-l-1);
871 l += 1;
872 strncat(envname+l, varname, XIO_ENVNAMELEN-l-1);
873 l += strlen(envname+l);
874 strncat(envname+l, "_", XIO_ENVNAMELEN-l-1);
875 l += 1;
876 strncat(envname+l, varname2, XIO_ENVNAMELEN-l-1);
877 l += strlen(envname+l);
878 strncat(envname+l, "_", XIO_ENVNAMELEN-l-1);
879 l += 1;
880 strncat(envname+l, varname3, XIO_ENVNAMELEN-l-1);
881 l += strlen(envname+l);
882 for (i = 0; i < l; ++i) envname[i] = toupper((unsigned char)envname[i]);
883 return _xiosetenv(envname, value, overwrite, sep);
884 # undef XIO_ENVNAMELEN
888 /* like xiosetenv(), but uses an unsigned long value */
889 int xiosetenvulong(const char *varname, unsigned long value, int overwrite) {
890 # define XIO_LONGLEN 21 /* should suffice for 64bit longs with \0 */
891 char envbuff[XIO_LONGLEN];
893 snprintf(envbuff, XIO_LONGLEN, "%lu", value);
894 return xiosetenv(varname, envbuff, overwrite, NULL);
895 # undef XIO_LONGLEN
898 /* like xiosetenv(), but uses an unsigned short value */
899 int xiosetenvushort(const char *varname, unsigned short value, int overwrite) {
900 # define XIO_SHORTLEN 11 /* should suffice for 32bit shorts with \0 */
901 char envbuff[XIO_SHORTLEN];
903 snprintf(envbuff, XIO_SHORTLEN, "%hu", value);
904 return xiosetenv(varname, envbuff, overwrite, NULL);
905 # undef XIO_SHORTLEN
909 unsigned long int Strtoul(const char *nptr, char **endptr, int base, const char *txt) {
910 unsigned long res;
912 res = strtoul(nptr, endptr, base);
913 if (nptr == *endptr) {
914 Error1("parseopts(): missing numerical value of option \"%s\"", txt);
916 if (**endptr != '\0') {
917 Error1("parseopts(): trailing garbage in numerical arg of option \"%s\"", txt);
919 return res;
922 #if HAVE_STRTOLL
923 long long int Strtoll(const char *nptr, char **endptr, int base, const char *txt) {
924 long long int res;
926 res = strtoul(nptr, endptr, base);
927 if (nptr == *endptr) {
928 Error1("parseopts(): missing numerical value of option \"%s\"", txt);
930 if (**endptr != '\0') {
931 Error1("parseopts(): trailing garbage in numerical arg of option \"%s\"", txt);
933 return res;
935 #endif /* HAVE_STRTOLL */
937 double Strtod(const char *nptr, char **endptr, const char *txt) {
938 double res;
940 res = strtod(nptr, endptr);
941 if (nptr == *endptr) {
942 Error1("parseopts(): missing numerical value of option \"%s\"", txt);
944 if (**endptr != '\0') {
945 Error1("parseopts(): trailing garbage in numerical arg of option \"%s\"", txt);
947 return res;
951 /* This function gets a string with possible references to environment
952 variables and expands them. Variables must be prefixed with '$' and their
953 names consist only of A-Z, a-z, 0-9, and '_'.
954 The name may be enclosed with { }.
955 To pass a literal "$" us "\$".
956 There are special variables supported whose values do not comr from
957 environment:
958 $$ expands to the process's pid
959 $PROGNAME expands to the executables basename or the value of option -lp
960 $TIMESTAMP expands to the actual time in format %Y%m%dT%H%M%S
961 $MICROS expands to the actual microseconds (decimal)
962 The dst output is a copy of src but with the variables expanded.
963 Returns 0 on success;
964 returns -1 when the output buffer was too short (overflow);
965 returns 1 on syntax error.
967 int expandenv(
968 char *dst, /* prealloc'd output buff, will be \0 termd */
969 const char *src, /* input string to generate expansion from */
970 size_t n, /* length of dst */
971 struct timeval *tv) /* in/out timestamp for sync */
973 char c; /* char currently being lex'd/parsed */
974 bool esc = false; /* just got '\' */
975 bool bra = false; /* within ${ } */
976 char *nam = NULL; /* points to temp.allocated rw copy of src */
977 const char *e; /* pointer to isolated var name in tmp[] */
978 size_t s=0, d=0; /* counters in src, dst */
979 size_t v; /* variable name begin */
980 bool ofl = false; /* dst overflow, output truncated */
981 char tmp[18]; /* buffer for timestamp, micros */
983 while (c = src[s++]) {
984 if (esc) {
985 if (c == '\0') {
986 if (d+2 > n) { ofl = true; break; }
987 dst[d++] = '\\';
988 dst[d++] = c;
989 break;
991 if (c != '$') {
992 if (d+3 > n) { ofl = true; break; }
993 dst[d++] = '\\';
994 } else {
995 if (d+2 > n) { ofl = true; break; }
997 dst[d++] = c;
998 esc = false;
999 continue;
1001 if (c == '\0') {
1002 dst[d++] = c;
1003 break;
1005 if (c == '\\') {
1006 esc = true;
1007 continue;
1009 if (c != '$') {
1010 if (d+2 > n) { ofl = true; break; }
1011 dst[d++] = c;
1012 continue;
1015 /* c == '$': Expecting env var to expand */
1016 c = src[s];
1017 if (c == '\0') {
1018 if (d+2 > n) { ofl = true; break; }
1019 ++s;
1020 dst[d++] = '$';
1021 break;
1023 if (c == '$') {
1024 int wr;
1025 /* Special case: pid */
1026 ++s;
1027 wr = snprintf(&dst[d], n-d, F_pid, getpid());
1028 if (wr >= n-d || wr < 0) { ofl = true; break; }
1029 d += wr;
1030 continue;
1032 if (c == '{') {
1033 ++s;
1034 bra = true;
1036 if (!isalpha(c) && c != '_') {
1037 /* Special case no var name, just keep '$' */
1038 if (d+3 > n) { ofl = true; break; }
1039 ++s;
1040 dst[d++] = '$';
1041 dst[d++] = c;
1042 continue;
1044 v = 0; /* seems we found valid variable name */
1045 if (nam == NULL) {
1046 nam = strdup(src+s);
1047 if (nam == NULL) {
1048 errno = ENOMEM;
1049 return -1;
1052 while (c = src[s]) {
1053 if (!isalnum(c) && c != '_') {
1054 break;
1056 nam[v++] = c;
1057 ++s;
1059 if (bra && c != '}') {
1060 return 1;
1063 nam[v] = '\0';
1064 /* Var name is complete */
1065 /* Check hardcoded var names */
1066 if (strcmp(nam, "PROGNAME") == 0) {
1067 e = diag_get_string('p');
1068 } else if (strcmp(nam, "TIMESTAMP") == 0) {
1069 if (tv->tv_sec == 0) {
1070 gettimeofday(tv, NULL);
1072 struct tm tm;
1073 localtime_r(&tv->tv_sec, &tm);
1074 strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S", &tm);
1075 e = tmp;
1076 } else if (strcmp(nam, "MICROS") == 0) {
1077 if (tv->tv_sec == 0) {
1078 gettimeofday(tv, NULL);
1080 sprintf(tmp, F_tv_usec, tv->tv_usec);
1081 e = tmp;
1082 } else {
1083 e = getenv(nam);
1085 if (e == NULL) {
1086 /* Var not found, skip it */
1087 continue;
1089 /* Var found, copy it to output buffer */
1090 if (d+strlen(e)+1 > n) { ofl = true; break; }
1091 strcpy(&dst[d], e);
1092 d += strlen(&dst[d]);
1093 continue;
1096 if (nam != NULL) {
1097 free(nam);
1100 if (ofl) {
1101 dst[d] = '\0';
1102 return -1;
1104 dst[d] = '\0';
1105 if (src[s-1] != '\0') {
1106 errno = EINVAL;
1107 return -1;
1109 return 0;
1112 int xio_opensnifffile(
1113 const char *a,
1114 struct timeval *tv)
1116 char path[PATH_MAX];
1117 int flags;
1118 int rc;
1119 int fd;
1121 rc = expandenv(path, a, sizeof(path), tv);
1122 if (rc < 0) {
1123 Error2("expandenv(source=\"%s\", n="F_Zu"): Out of memory", a, sizeof(path));
1124 errno = ENOMEM;
1125 return -1;
1126 } else if (rc > 0) {
1127 Error1("expandenv(source=\"%s\"): Syntax error", a);
1128 errno = EINVAL;
1129 return -1;
1131 flags = O_CREAT|O_WRONLY|O_APPEND|
1132 #ifdef O_LARGEFILE
1133 O_LARGEFILE|
1134 #endif
1135 #ifdef O_CLOEXEC
1136 O_CLOEXEC|
1137 #endif
1138 O_NONBLOCK;
1139 if ((fd = Open(path, flags, 0664)) < 0) {
1140 if (errno == ENXIO) {
1141 /* try to open pipe rdwr */
1142 if ((fd = Open(path, flags, 0664)) < 0) {
1143 return -1;
1147 #ifdef O_CLOEXEC
1148 if (Fcntl_l(fd, F_SETFD, FD_CLOEXEC) < 0) {
1149 Warn2("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", fd, strerror(errno));
1151 #endif
1152 return fd;