1 /*
2 ** OSSP sa - Socket Abstraction
3 ** Copyright (c) 2001-2005 Ralf S. Engelschall <rse@engelschall.com>
4 ** Copyright (c) 2001-2005 The OSSP Project <http://www.ossp.org/>
5 ** Copyright (c) 2001-2005 Cable & Wireless <http://www.cw.com/>
6 **
7 ** This file is part of OSSP sa, a socket abstraction library which
8 ** can be found at http://www.ossp.org/pkg/lib/sa/.
9 **
10 ** Permission to use, copy, modify, and distribute this software for
11 ** any purpose with or without fee is hereby granted, provided that
12 ** the above copyright notice and this permission notice appear in all
13 ** copies.
14 **
15 ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
16 ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
19 ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
22 ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 ** SUCH DAMAGE.
27 **
28 ** sa.c: socket abstraction library
29 */
30
31 /* include optional Autoconf header */
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 /* include system API headers */
37 #include <stdio.h> /* for "s[n]printf()" */
38 #include <stdlib.h> /* for "malloc()" & friends */
39 #include <stdarg.h> /* for "va_XXX()" and "va_list" */
40 #include <string.h> /* for "strXXX()" and "size_t" */
41 #include <sys/types.h> /* for general prerequisites */
42 #include <ctype.h> /* for "isXXX()" */
43 #include <errno.h> /* for "EXXX" */
44 #include <fcntl.h> /* for "F_XXX" and "O_XXX" */
45 #include <unistd.h> /* for standard Unix stuff */
46 #include <netdb.h> /* for "struct prototent" */
47 #include <sys/time.h> /* for "struct timeval" */
48 #include <sys/un.h> /* for "struct sockaddr_un" */
49 #include <netinet/in.h> /* for "struct sockaddr_in[6]" */
50 #include <sys/socket.h> /* for "PF_XXX", "AF_XXX", "SOCK_XXX" and "SHUT_XX" */
51 #include <arpa/inet.h> /* for "inet_XtoX" */
52
53 /* include own API header */
54 #include "sa.h"
55
56 /* unique library identifier */
57 const char sa_id[] = "OSSP sa";
58
59 /* support for OSSP ex based exception throwing */
60 #ifdef WITH_EX
61 #include "ex.h"
62 #define SA_RC(rv) \
63 ( (rv) != SA_OK && (ex_catching && !ex_shielding) \
64 ? (ex_throw(sa_id, NULL, (rv)), (rv)) : (rv) )
65 #else
66 #define SA_RC(rv) (rv)
67 #endif /* WITH_EX */
68
69 /* boolean values */
70 #ifndef FALSE
71 #define FALSE (0)
72 #endif
73 #ifndef TRUE
74 #define TRUE (!FALSE)
75 #endif
76
77 /* backward compatibility for AF_LOCAL */
78 #if !defined(AF_LOCAL) && defined(AF_UNIX)
79 #define AF_LOCAL AF_UNIX
80 #endif
81
82 /* backward compatibility for PF_XXX (still unused) */
83 #if !defined(PF_LOCAL) && defined(AF_LOCAL)
84 #define PF_LOCAL AF_LOCAL
85 #endif
86 #if !defined(PF_INET) && defined(AF_INET)
87 #define PF_INET AF_INET
88 #endif
89 #if !defined(PF_INET6) && defined(AF_INET6)
90 #define PF_INET6 AF_INET6
91 #endif
92
93 /* backward compatibility for SHUT_XX. Some platforms (like brain-dead
94 OpenUNIX) define those only if _XOPEN_SOURCE is defined, but unfortunately
95 then fail in their other vendor includes due to internal inconsistencies. */
96 #if !defined(SHUT_RD)
97 #define SHUT_RD 0
98 #endif
99 #if !defined(SHUT_WR)
100 #define SHUT_WR 1
101 #endif
102 #if !defined(SHUT_RDWR)
103 #define SHUT_RDWR 2
104 #endif
105
106 /* backward compatibility for ssize_t */
107 #if defined(HAVE_CONFIG_H) && !defined(HAVE_SSIZE_T)
108 #define ssize_t long
109 #endif
110
111 /* backward compatibility for O_NONBLOCK */
112 #if !defined(O_NONBLOCK) && defined(O_NDELAY)
113 #define O_NONBLOCK O_NDELAY
114 #endif
115
116 /* system call structure declaration macros */
117 #define SA_SC_DECLARE_0(rc_t, fn) \
118 struct { \
119 union { void (*any)(void); \
120 rc_t (*std)(void); \
121 rc_t (*ctx)(void *); } fptr; \
122 void *fctx; \
123 } sc_##fn;
124 #define SA_SC_DECLARE_1(rc_t, fn, a1_t) \
125 struct { \
126 union { void (*any)(void); \
127 rc_t (*std)(a1_t); \
128 rc_t (*ctx)(void *, a1_t); } fptr; \
129 void *fctx; \
130 } sc_##fn;
131 #define SA_SC_DECLARE_2(rc_t, fn, a1_t, a2_t) \
132 struct { \
133 union { void (*any)(void); \
134 rc_t (*std)(a1_t, a2_t); \
135 rc_t (*ctx)(void *, a1_t, a2_t); } fptr; \
136 void *fctx; \
137 } sc_##fn;
138 #define SA_SC_DECLARE_3(rc_t, fn, a1_t, a2_t, a3_t) \
139 struct { \
140 union { void (*any)(void); \
141 rc_t (*std)(a1_t, a2_t, a3_t); \
142 rc_t (*ctx)(void *, a1_t, a2_t, a3_t); } fptr; \
143 void *fctx; \
144 } sc_##fn;
145 #define SA_SC_DECLARE_4(rc_t, fn, a1_t, a2_t, a3_t, a4_t) \
146 struct { \
147 union { void (*any)(void); \
148 rc_t (*std)(a1_t, a2_t, a3_t, a4_t); \
149 rc_t (*ctx)(void *, a1_t, a2_t, a3_t, a4_t); } fptr; \
150 void *fctx; \
151 } sc_##fn;
152 #define SA_SC_DECLARE_5(rc_t, fn, a1_t, a2_t, a3_t, a4_t, a5_t) \
153 struct { \
154 union { void (*any)(void); \
155 rc_t (*std)(a1_t, a2_t, a3_t, a4_t, a5_t); \
156 rc_t (*ctx)(void *, a1_t, a2_t, a3_t, a4_t, a5_t); } fptr; \
157 void *fctx; \
158 } sc_##fn;
159 #define SA_SC_DECLARE_6(rc_t, fn, a1_t, a2_t, a3_t, a4_t, a5_t, a6_t) \
160 struct { \
161 union { void (*any)(void); \
162 rc_t (*std)(a1_t, a2_t, a3_t, a4_t, a5_t, a6_t); \
163 rc_t (*ctx)(void *, a1_t, a2_t, a3_t, a4_t, a5_t, a6_t); } fptr; \
164 void *fctx; \
165 } sc_##fn;
166
167 /* system call structure assignment macro */
168 #define SA_SC_ASSIGN(sa, fn, ptr, ctx) \
169 do { \
170 (sa)->scSysCall.sc_##fn.fptr.any = (void (*)(void))(ptr); \
171 (sa)->scSysCall.sc_##fn.fctx = (ctx); \
172 } while (0)
173
174 /* system call structure assignment macro */
175 #define SA_SC_COPY(sa1, sa2, fn) \
176 do { \
177 (sa1)->scSysCall.sc_##fn.fptr.any = (sa2)->scSysCall.sc_##fn.fptr.any; \
178 (sa1)->scSysCall.sc_##fn.fctx = (sa2)->scSysCall.sc_##fn.fctx; \
179 } while (0)
180
181 /* system call function call macros */
182 #define SA_SC_CALL_0(sa, fn) \
183 ( (sa)->scSysCall.sc_##fn.fctx != NULL \
184 ? ((sa)->scSysCall.sc_##fn.fptr.ctx)((sa)->scSysCall.sc_##fn.fctx) \
185 : ((sa)->scSysCall.sc_##fn.fptr.std)(void) )
186 #define SA_SC_CALL_1(sa, fn, a1) \
187 ( (sa)->scSysCall.sc_##fn.fctx != NULL \
188 ? ((sa)->scSysCall.sc_##fn.fptr.ctx)((sa)->scSysCall.sc_##fn.fctx, a1) \
189 : ((sa)->scSysCall.sc_##fn.fptr.std)(a1) )
190 #define SA_SC_CALL_2(sa, fn, a1, a2) \
191 ( (sa)->scSysCall.sc_##fn.fctx != NULL \
192 ? ((sa)->scSysCall.sc_##fn.fptr.ctx)((sa)->scSysCall.sc_##fn.fctx, a1, a2) \
193 : ((sa)->scSysCall.sc_##fn.fptr.std)(a1, a2) )
194 #define SA_SC_CALL_3(sa, fn, a1, a2, a3) \
195 ( (sa)->scSysCall.sc_##fn.fctx != NULL \
196 ? ((sa)->scSysCall.sc_##fn.fptr.ctx)((sa)->scSysCall.sc_##fn.fctx, a1, a2, a3) \
197 : ((sa)->scSysCall.sc_##fn.fptr.std)(a1, a2, a3) )
198 #define SA_SC_CALL_4(sa, fn, a1, a2, a3, a4) \
199 ( (sa)->scSysCall.sc_##fn.fctx != NULL \
200 ? ((sa)->scSysCall.sc_##fn.fptr.ctx)((sa)->scSysCall.sc_##fn.fctx, a1, a2, a3, a4) \
201 : ((sa)->scSysCall.sc_##fn.fptr.std)(a1, a2, a3, a4) )
202 #define SA_SC_CALL_5(sa, fn, a1, a2, a3, a4, a5) \
203 ( (sa)->scSysCall.sc_##fn.fctx != NULL \
204 ? ((sa)->scSysCall.sc_##fn.fptr.ctx)((sa)->scSysCall.sc_##fn.fctx, a1, a2, a3, a4, a5) \
205 : ((sa)->scSysCall.sc_##fn.fptr.std)(a1, a2, a3, a4, a5) )
206 #define SA_SC_CALL_6(sa, fn, a1, a2, a3, a4, a5, a6) \
207 ( (sa)->scSysCall.sc_##fn.fctx != NULL \
208 ? ((sa)->scSysCall.sc_##fn.fptr.ctx)((sa)->scSysCall.sc_##fn.fctx, a1, a2, a3, a4, a5, a6) \
209 : ((sa)->scSysCall.sc_##fn.fptr.std)(a1, a2, a3, a4, a5, a6) )
210
211 /* system call table */
212 typedef struct {
213 SA_SC_DECLARE_3(int, connect, int, const struct sockaddr *, socklen_t)
214 SA_SC_DECLARE_3(int, accept, int, struct sockaddr *, socklen_t *)
215 SA_SC_DECLARE_5(int, select, int, fd_set *, fd_set *, fd_set *, struct timeval *)
216 SA_SC_DECLARE_3(ssize_t, read, int, void *, size_t)
217 SA_SC_DECLARE_3(ssize_t, write, int, const void *, size_t)
218 SA_SC_DECLARE_6(ssize_t, recvfrom, int, void *, size_t, int, struct sockaddr *, socklen_t *)
219 SA_SC_DECLARE_6(ssize_t, sendto, int, const void *, size_t, int, const struct sockaddr *, socklen_t)
220 } sa_syscall_tab_t;
221
222 /* socket option information */
223 typedef struct {
224 int todo;
225 int value;
226 } sa_optinfo_t;
227
228 /* socket abstraction object */
229 struct sa_st {
230 sa_type_t eType; /* socket type (stream or datagram) */
231 int fdSocket; /* socket file descriptor */
232 struct timeval tvTimeout[4]; /* timeout values (sec, usec) */
233 int nReadLen; /* read buffer current length */
234 int nReadSize; /* read buffer current size */
235 char *cpReadBuf; /* read buffer memory chunk */
236 int nWriteLen; /* write buffer current length */
237 int nWriteSize; /* write buffer current size */
238 char *cpWriteBuf; /* write buffer memory chunk */
239 sa_syscall_tab_t scSysCall; /* table of system calls */
240 sa_optinfo_t optInfo[5]; /* option storage */
241 };
242
243 /* socket address abstraction object */
244 struct sa_addr_st {
245 int nFamily; /* the socket family (AF_XXX) */
246 struct sockaddr *saBuf; /* the "struct sockaddr_xx" actually */
247 socklen_t slBuf; /* the length of "struct sockaddr_xx" */
248 };
249
250 /* handy struct timeval check */
251 #define SA_TVISZERO(tv) \
252 ((tv).tv_sec == 0 && (tv).tv_usec == 0)
253
254 /* convert Internet address from presentation to network format */
255 #ifndef HAVE_GETADDRINFO
sa_inet_pton(int family,const char * strptr,void * addrptr)256 static int sa_inet_pton(int family, const char *strptr, void *addrptr)
257 {
258 #ifdef HAVE_INET_PTON
259 return inet_pton(family, strptr, addrptr);
260 #else
261 struct in_addr in_val;
262
263 if (family == AF_INET) {
264 #if defined(HAVE_INET_ATON)
265 /* at least for IPv4 we can rely on the old inet_aton(3)
266 and for IPv6 inet_pton(3) would exist anyway */
267 if (inet_aton(strptr, &in_val) == 0)
268 return 0;
269 memcpy(addrptr, &in_val, sizeof(struct in_addr));
270 return 1;
271 #elif defined(HAVE_INET_ADDR)
272 /* at least for IPv4 try to rely on the even older inet_addr(3) */
273 memset(&in_val, '\0', sizeof(in_val));
274 if ((in_val.s_addr = inet_addr(strptr)) == ((in_addr_t)-1))
275 return 0;
276 memcpy(addrptr, &in_val, sizeof(struct in_addr));
277 return 1;
278 #endif
279 }
280 errno = EAFNOSUPPORT;
281 return 0;
282 #endif
283 }
284 #endif /* !HAVE_GETADDRINFO */
285
286 /* convert Internet address from network to presentation format */
sa_inet_ntop(int family,const void * src,char * dst,size_t size)287 static const char *sa_inet_ntop(int family, const void *src, char *dst, size_t size)
288 {
289 #ifdef HAVE_INET_NTOP
290 return inet_ntop(family, src, dst, size);
291 #else
292 #ifdef HAVE_INET_NTOA
293 char *cp;
294 int n;
295 #endif
296
297 if (family == AF_INET) {
298 #ifdef HAVE_INET_NTOA
299 /* at least for IPv4 we can rely on the old inet_ntoa(3)
300 and for IPv6 inet_ntop(3) would exist anyway */
301 if ((cp = inet_ntoa(*((struct in_addr *)src))) == NULL)
302 return NULL;
303 n = strlen(cp);
304 if (n > size-1)
305 n = size-1;
306 memcpy(dst, cp, n);
307 dst[n] = '\0';
308 return dst;
309 #endif
310 }
311 errno = EAFNOSUPPORT;
312 return NULL;
313 #endif
314 }
315
316 /* minimal output-independent vprintf(3) variant which supports %{c,s,d,%} only */
sa_mvxprintf(int (* output)(void * ctx,const char * buffer,size_t bufsize),void * ctx,const char * format,va_list ap)317 static int sa_mvxprintf(int (*output)(void *ctx, const char *buffer, size_t bufsize), void *ctx, const char *format, va_list ap)
318 {
319 /* sufficient integer buffer: <available-bits> x log_10(2) + safety */
320 char ibuf[((sizeof(int)*8)/3)+10];
321 char *cp;
322 char c;
323 int d;
324 int n;
325 int bytes;
326
327 if (format == NULL)
328 return -1;
329 bytes = 0;
330 while (*format != '\0') {
331 if (*format == '%') {
332 c = *(format+1);
333 if (c == '%') {
334 /* expand "%%" */
335 cp = &c;
336 n = (int)sizeof(char);
337 }
338 else if (c == 'c') {
339 /* expand "%c" */
340 c = (char)va_arg(ap, int);
341 cp = &c;
342 n = (int)sizeof(char);
343 }
344 else if (c == 's') {
345 /* expand "%s" */
346 if ((cp = (char *)va_arg(ap, char *)) == NULL)
347 cp = "(null)";
348 n = (int)strlen(cp);
349 }
350 else if (c == 'd') {
351 /* expand "%d" */
352 d = (int)va_arg(ap, int);
353 #ifdef HAVE_SNPRINTF
354 snprintf(ibuf, sizeof(ibuf), "%d", d); /* explicitly secure */
355 #else
356 sprintf(ibuf, "%d", d); /* implicitly secure */
357 #endif
358 cp = ibuf;
359 n = (int)strlen(cp);
360 }
361 else {
362 /* any other "%X" */
363 cp = (char *)format;
364 n = 2;
365 }
366 format += 2;
367 }
368 else {
369 /* plain text */
370 cp = (char *)format;
371 if ((format = strchr(cp, '%')) == NULL)
372 format = strchr(cp, '\0');
373 n = (int)(format - cp);
374 }
375 /* perform output operation */
376 if (output != NULL)
377 if ((n = output(ctx, cp, (size_t)n)) == -1)
378 break;
379 bytes += n;
380 }
381 return bytes;
382 }
383
384 /* output callback function context for sa_mvsnprintf() */
385 typedef struct {
386 char *bufptr;
387 size_t buflen;
388 } sa_mvsnprintf_cb_t;
389
390 /* output callback function for sa_mvsnprintf() */
sa_mvsnprintf_cb(void * _ctx,const char * buffer,size_t bufsize)391 static int sa_mvsnprintf_cb(void *_ctx, const char *buffer, size_t bufsize)
392 {
393 sa_mvsnprintf_cb_t *ctx = (sa_mvsnprintf_cb_t *)_ctx;
394
395 if (bufsize > ctx->buflen)
396 return -1;
397 memcpy(ctx->bufptr, buffer, bufsize);
398 ctx->bufptr += bufsize;
399 ctx->buflen -= bufsize;
400 return (int)bufsize;
401 }
402
403 /* minimal vsnprintf(3) variant which supports %{c,s,d} only */
sa_mvsnprintf(char * buffer,size_t bufsize,const char * format,va_list ap)404 static int sa_mvsnprintf(char *buffer, size_t bufsize, const char *format, va_list ap)
405 {
406 int n;
407 sa_mvsnprintf_cb_t ctx;
408
409 if (format == NULL)
410 return -1;
411 if (buffer != NULL && bufsize == 0)
412 return -1;
413 if (buffer == NULL)
414 /* just determine output length */
415 n = sa_mvxprintf(NULL, NULL, format, ap);
416 else {
417 /* perform real output */
418 ctx.bufptr = buffer;
419 ctx.buflen = bufsize;
420 n = sa_mvxprintf(sa_mvsnprintf_cb, &ctx, format, ap);
421 if (n != -1 && ctx.buflen == 0)
422 n = -1;
423 if (n != -1)
424 *(ctx.bufptr) = '\0';
425 }
426 return n;
427 }
428
429 /* minimal snprintf(3) variant which supports %{c,s,d} only */
sa_msnprintf(char * buffer,size_t bufsize,const char * format,...)430 static int sa_msnprintf(char *buffer, size_t bufsize, const char *format, ...)
431 {
432 int chars;
433 va_list ap;
434
435 /* pass through to va_list based variant */
436 va_start(ap, format);
437 chars = sa_mvsnprintf(buffer, bufsize, format, ap);
438 va_end(ap);
439
440 return chars;
441 }
442
443 /* create address object */
sa_addr_create(sa_addr_t ** saap)444 sa_rc_t sa_addr_create(sa_addr_t **saap)
445 {
446 sa_addr_t *saa;
447
448 /* argument sanity check(s) */
449 if (saap == NULL)
450 return SA_RC(SA_ERR_ARG);
451
452 /* allocate and initialize new address object */
453 if ((saa = (sa_addr_t *)malloc(sizeof(sa_addr_t))) == NULL)
454 return SA_RC(SA_ERR_MEM);
455 saa->nFamily = 0;
456 saa->saBuf = NULL;
457 saa->slBuf = 0;
458
459 /* pass object to caller */
460 *saap = saa;
461
462 return SA_OK;
463 }
464
465 /* destroy address object */
sa_addr_destroy(sa_addr_t * saa)466 sa_rc_t sa_addr_destroy(sa_addr_t *saa)
467 {
468 /* argument sanity check(s) */
469 if (saa == NULL)
470 return SA_RC(SA_ERR_ARG);
471
472 /* free address objects and sub-object(s) */
473 if (saa->saBuf != NULL)
474 free(saa->saBuf);
475 free(saa);
476
477 return SA_OK;
478 }
479
480 /* import URI into address object */
sa_addr_u2a(sa_addr_t * saa,const char * uri,...)481 sa_rc_t sa_addr_u2a(sa_addr_t *saa, const char *uri, ...)
482 {
483 va_list ap;
484 int sf;
485 socklen_t sl;
486 struct sockaddr *sa;
487 struct sockaddr_un un;
488 #ifdef HAVE_GETADDRINFO
489 struct addrinfo ai_hints;
490 struct addrinfo *ai = NULL;
491 int err;
492 #else
493 struct sockaddr_in sa4;
494 #ifdef AF_INET6
495 struct sockaddr_in6 sa6;
496 #endif
497 struct hostent *he;
498 #endif
499 struct servent *se;
500 int bIPv6;
501 int bNumeric;
502 const char *cpHost;
503 const char *cpPort;
504 char *cpProto;
505 unsigned int nPort;
506 const char *cpPath;
507 char uribuf[1024];
508 char *cp;
509 int i;
510 size_t n;
511 int k;
512
513 /* argument sanity check(s) */
514 if (saa == NULL || uri == NULL)
515 return SA_RC(SA_ERR_ARG);
516
517 /* on-the-fly create or just take over URI */
518 va_start(ap, uri);
519 k = sa_mvsnprintf(uribuf, sizeof(uribuf), uri, ap);
520 va_end(ap);
521 if (k == -1)
522 return SA_RC(SA_ERR_MEM);
523
524 /* initialize result variables */
525 sa = NULL;
526 sl = 0;
527 sf = 0;
528
529 /* parse URI and resolve contents.
530 The following syntax is recognized:
531 - unix:<path>
532 - inet://<host>:<port>[#(tcp|udp)] */
533 uri = uribuf;
534 if (strncmp(uri, "unix:", 5) == 0) {
535 /* parse URI */
536 cpPath = uri+5;
537
538 /* mandatory(!) socket address structure initialization */
539 memset(&un, 0, sizeof(un));
540
541 /* fill-in socket address structure */
542 n = strlen(cpPath);
543 if (n == 0)
544 return SA_RC(SA_ERR_ARG);
545 if ((n+1) > sizeof(un.sun_path))
546 return SA_RC(SA_ERR_MEM);
547 if (cpPath[0] != '/') {
548 if (getcwd(un.sun_path, sizeof(un.sun_path)-(n+1)) == NULL)
549 return SA_RC(SA_ERR_MEM);
550 cp = un.sun_path + strlen(un.sun_path);
551 }
552 else
553 cp = un.sun_path;
554 memcpy(cp, cpPath, n+1);
555 un.sun_family = AF_LOCAL;
556
557 /* provide results */
558 sa = (struct sockaddr *)&un;
559 sl = (socklen_t)sizeof(un);
560 sf = AF_LOCAL;
561 }
562 else if (strncmp(uri, "inet://", 7) == 0) {
563 /* parse URI into host, port and protocol parts */
564 cpHost = uri+7;
565 bIPv6 = FALSE;
566 if (cpHost[0] == '[') {
567 /* IPv6 address (see RFC2732) */
568 #ifndef AF_INET6
569 return SA_RC(SA_ERR_IMP);
570 #else
571 bIPv6 = TRUE;
572 cpHost++;
573 if ((cp = strchr(cpHost, ']')) == NULL)
574 return SA_RC(SA_ERR_ARG);
575 *cp++ = '\0';
576 if (*cp != ':')
577 return SA_RC(SA_ERR_ARG);
578 cp++;
579 #endif
580 }
581 else {
582 /* IPv4 address or hostname */
583 if ((cp = strrchr(cpHost, ':')) == NULL)
584 return SA_RC(SA_ERR_ARG);
585 *cp++ = '\0';
586 }
587 cpPort = cp;
588 cpProto = "tcp";
589 if ((cp = strchr(cpPort, '#')) != NULL) {
590 *cp++ = '\0';
591 cpProto = cp;
592 }
593
594 /* resolve port */
595 nPort = 0;
596 bNumeric = 1;
597 for (i = 0; cpPort[i] != '\0'; i++) {
598 if (!isdigit((int)cpPort[i])) {
599 bNumeric = 0;
600 break;
601 }
602 }
603 if (bNumeric)
604 nPort = (unsigned int)atoi(cpPort);
605 else {
606 if ((se = getservbyname(cpPort, cpProto)) == NULL)
607 return SA_RC(SA_ERR_SYS);
608 nPort = ntohs(se->s_port);
609 }
610
611 #ifdef HAVE_GETADDRINFO
612 memset(&ai_hints, 0, sizeof(ai_hints));
613 ai_hints.ai_family = PF_UNSPEC;
614 if ((err = getaddrinfo(cpHost, NULL, &ai_hints, &ai)) != 0) {
615 if (err == EAI_MEMORY)
616 return SA_RC(SA_ERR_MEM);
617 else if (err == EAI_SYSTEM)
618 return SA_RC(SA_ERR_SYS);
619 else
620 return SA_RC(SA_ERR_ARG);
621 }
622 sa = ai->ai_addr;
623 sl = ai->ai_addrlen;
624 sf = ai->ai_family;
625 if (sf == AF_INET)
626 ((struct sockaddr_in *)sa)->sin_port = htons(nPort);
627 else if (sf == AF_INET6)
628 ((struct sockaddr_in6 *)sa)->sin6_port = htons(nPort);
629 else
630 return SA_RC(SA_ERR_ARG);
631 #else /* !HAVE_GETADDRINFO */
632
633 /* mandatory(!) socket address structure initialization */
634 memset(&sa4, 0, sizeof(sa4));
635 #ifdef AF_INET6
636 memset(&sa6, 0, sizeof(sa6));
637 #endif
638
639 /* resolve host by trying to parse it as either directly an IPv4 or
640 IPv6 address or by resolving it to either an IPv4 or IPv6 address */
641 if (!bIPv6 && sa_inet_pton(AF_INET, cpHost, &sa4.sin_addr.s_addr) == 1) {
642 sa4.sin_family = AF_INET;
643 sa4.sin_port = htons(nPort);
644 sa = (struct sockaddr *)&sa4;
645 sl = (socklen_t)sizeof(sa4);
646 sf = AF_INET;
647 }
648 #ifdef AF_INET6
649 else if (bIPv6 && sa_inet_pton(AF_INET6, cpHost, &sa6.sin6_addr.s6_addr) == 1) {
650 sa6.sin6_family = AF_INET6;
651 sa6.sin6_port = htons(nPort);
652 sa = (struct sockaddr *)&sa6;
653 sl = (socklen_t)sizeof(sa6);
654 sf = AF_INET6;
655 }
656 #endif
657 else if ((he = gethostbyname(cpHost)) != NULL) {
658 if (he->h_addrtype == AF_INET) {
659 sa4.sin_family = AF_INET;
660 sa4.sin_port = htons(nPort);
661 memcpy(&sa4.sin_addr.s_addr, he->h_addr_list[0],
662 sizeof(sa4.sin_addr.s_addr));
663 sa = (struct sockaddr *)&sa4;
664 sl = (socklen_t)sizeof(sa4);
665 sf = AF_INET;
666 }
667 #ifdef AF_INET6
668 else if (he->h_addrtype == AF_INET6) {
669 sa6.sin6_family = AF_INET6;
670 sa6.sin6_port = htons(nPort);
671 memcpy(&sa6.sin6_addr.s6_addr, he->h_addr_list[0],
672 sizeof(sa6.sin6_addr.s6_addr));
673 sa = (struct sockaddr *)&sa6;
674 sl = (socklen_t)sizeof(sa6);
675 sf = AF_INET6;
676 }
677 #endif
678 else
679 return SA_RC(SA_ERR_ARG);
680 }
681 else
682 return SA_RC(SA_ERR_ARG);
683 #endif /* !HAVE_GETADDRINFO */
684 }
685 else
686 return SA_RC(SA_ERR_ARG);
687
688 /* fill-in result address structure */
689 if (saa->saBuf != NULL)
690 free(saa->saBuf);
691 if ((saa->saBuf = (struct sockaddr *)malloc((size_t)sl)) == NULL)
692 return SA_RC(SA_ERR_MEM);
693 memcpy(saa->saBuf, sa, (size_t)sl);
694 saa->slBuf = sl;
695 saa->nFamily = (int)sf;
696
697 #ifdef HAVE_GETADDRINFO
698 if (ai != NULL)
699 freeaddrinfo(ai);
700 #endif
701
702 return SA_OK;
703 }
704
705 /* import "struct sockaddr" into address object */
sa_addr_s2a(sa_addr_t * saa,const struct sockaddr * sabuf,socklen_t salen)706 sa_rc_t sa_addr_s2a(sa_addr_t *saa, const struct sockaddr *sabuf, socklen_t salen)
707 {
708 /* argument sanity check(s) */
709 if (saa == NULL || sabuf == NULL || salen == 0)
710 return SA_RC(SA_ERR_ARG);
711
712 /* make sure we import only supported addresses */
713 if (!( sabuf->sa_family == AF_LOCAL
714 || sabuf->sa_family == AF_INET
715 #ifdef AF_INET6
716 || sabuf->sa_family == AF_INET6
717 #endif
718 ))
719 return SA_RC(SA_ERR_USE);
720
721 /* create result address structure */
722 if (saa->saBuf != NULL)
723 free(saa->saBuf);
724 if ((saa->saBuf = (struct sockaddr *)malloc((size_t)salen)) == NULL)
725 return SA_RC(SA_ERR_MEM);
726 memcpy(saa->saBuf, sabuf, (size_t)salen);
727 saa->slBuf = salen;
728
729 /* remember family */
730 saa->nFamily = (int)(sabuf->sa_family);
731
732 return SA_OK;
733 }
734
735 /* export address object into URI */
sa_addr_a2u(const sa_addr_t * saa,char ** uri)736 sa_rc_t sa_addr_a2u(const sa_addr_t *saa, char **uri)
737 {
738 char uribuf[1024];
739 struct sockaddr_un *un;
740 struct sockaddr_in *sa4;
741 #ifdef AF_INET6
742 struct sockaddr_in6 *sa6;
743 #endif
744 char caHost[512];
745 unsigned int nPort;
746
747 /* argument sanity check(s) */
748 if (saa == NULL || uri == NULL)
749 return SA_RC(SA_ERR_ARG);
750
751 /* export object contents */
752 if (saa->nFamily == AF_LOCAL) {
753 un = (struct sockaddr_un *)((void *)saa->saBuf);
754 if ( ( saa->slBuf >= (socklen_t)(&(((struct sockaddr_un *)0)->sun_path[0]))
755 && un->sun_path[0] == '\0')
756 || (size_t)(saa->slBuf) < sizeof(struct sockaddr_un)) {
757 /* in case the remote side of a Unix Domain socket was not
758 bound, a "struct sockaddr_un" can occur with a length less
759 than the expected one. Then there is actually no path at all.
760 This has been verified under FreeBSD, Linux and Solaris. */
761 if (sa_msnprintf(uribuf, sizeof(uribuf), "unix:/NOT-BOUND") == -1)
762 return SA_RC(SA_ERR_FMT);
763 }
764 else {
765 if (sa_msnprintf(uribuf, sizeof(uribuf), "unix:%s", un->sun_path) == -1)
766 return SA_RC(SA_ERR_FMT);
767 }
768 }
769 else if (saa->nFamily == AF_INET) {
770 sa4 = (struct sockaddr_in *)((void *)saa->saBuf);
771 if (sa_inet_ntop(AF_INET, &sa4->sin_addr.s_addr, caHost, sizeof(caHost)) == NULL)
772 return SA_RC(SA_ERR_NET);
773 nPort = ntohs(sa4->sin_port);
774 if (sa_msnprintf(uribuf, sizeof(uribuf), "inet://%s:%d", caHost, nPort) == -1)
775 return SA_RC(SA_ERR_FMT);
776 }
777 #ifdef AF_INET6
778 else if (saa->nFamily == AF_INET6) {
779 sa6 = (struct sockaddr_in6 *)((void *)saa->saBuf);
780 if (sa_inet_ntop(AF_INET6, &sa6->sin6_addr.s6_addr, caHost, sizeof(caHost)) == NULL)
781 return SA_RC(SA_ERR_NET);
782 nPort = ntohs(sa6->sin6_port);
783 if (sa_msnprintf(uribuf, sizeof(uribuf), "inet://[%s]:%d", caHost, nPort) == -1)
784 return SA_RC(SA_ERR_FMT);
785 }
786 #endif
787 else
788 return SA_RC(SA_ERR_INT);
789
790 /* pass result to caller */
791 *uri = strdup(uribuf);
792
793 return SA_OK;
794 }
795
796 /* export address object into "struct sockaddr" */
sa_addr_a2s(const sa_addr_t * saa,struct sockaddr ** sabuf,socklen_t * salen)797 sa_rc_t sa_addr_a2s(const sa_addr_t *saa, struct sockaddr **sabuf, socklen_t *salen)
798 {
799 /* argument sanity check(s) */
800 if (saa == NULL || sabuf == NULL || salen == 0)
801 return SA_RC(SA_ERR_ARG);
802
803 /* export underlying address structure */
804 if ((*sabuf = (struct sockaddr *)malloc((size_t)saa->slBuf)) == NULL)
805 return SA_RC(SA_ERR_MEM);
806 memmove(*sabuf, saa->saBuf, (size_t)saa->slBuf);
807 *salen = saa->slBuf;
808
809 return SA_OK;
810 }
811
sa_addr_match(const sa_addr_t * saa1,const sa_addr_t * saa2,int prefixlen)812 sa_rc_t sa_addr_match(const sa_addr_t *saa1, const sa_addr_t *saa2, int prefixlen)
813 {
814 const unsigned char *ucp1, *ucp2;
815 unsigned int uc1, uc2, mask;
816 size_t l1, l2;
817 int nBytes;
818 int nBits;
819 #ifdef AF_INET6
820 int i;
821 const unsigned char *ucp0;
822 #endif
823 unsigned int np1, np2;
824 int bMatchPort;
825
826 /* argument sanity check(s) */
827 if (saa1 == NULL || saa2 == NULL)
828 return SA_RC(SA_ERR_ARG);
829
830 /* short circuiting for wildcard matching */
831 if (prefixlen == 0)
832 return SA_OK;
833
834 /* determine address representation pointer and size */
835 if (saa1->nFamily == AF_LOCAL) {
836 np1 = 0;
837 np2 = 0;
838 ucp1 = (const unsigned char *)(((struct sockaddr_un *)saa1->saBuf)->sun_path);
839 ucp2 = (const unsigned char *)(((struct sockaddr_un *)saa2->saBuf)->sun_path);
840 l1 = strlen(((struct sockaddr_un *)saa1->saBuf)->sun_path) * 8;
841 l2 = strlen(((struct sockaddr_un *)saa2->saBuf)->sun_path) * 8;
842 if (prefixlen < 0) {
843 if (l1 != l2)
844 return SA_RC(SA_ERR_MTC);
845 nBits = (int)l1;
846 }
847 else {
848 if ((int)l1 < prefixlen || (int)l2 < prefixlen)
849 return SA_RC(SA_ERR_MTC);
850 nBits = prefixlen;
851 }
852 }
853 #ifdef AF_INET6
854 else if ( (saa1->nFamily == AF_INET && saa2->nFamily == AF_INET6)
855 || (saa1->nFamily == AF_INET6 && saa2->nFamily == AF_INET )) {
856 /* special case of comparing a regular IPv4 address (1.2.3.4) with an
857 "IPv4-mapped IPv6 address" (::ffff:1.2.3.4). For details see RFC 2373. */
858 if (saa1->nFamily == AF_INET6) {
859 np1 = (unsigned int)(((struct sockaddr_in6 *)saa1->saBuf)->sin6_port);
860 np2 = (unsigned int)(((struct sockaddr_in *)saa2->saBuf)->sin_port);
861 ucp1 = (const unsigned char *)&(((struct sockaddr_in6 *)saa1->saBuf)->sin6_addr);
862 ucp2 = (const unsigned char *)&(((struct sockaddr_in *)saa2->saBuf)->sin_addr);
863 ucp0 = ucp1;
864 ucp1 += 12;
865 }
866 else {
867 np1 = (unsigned int)(((struct sockaddr_in *)saa1->saBuf)->sin_port);
868 np2 = (unsigned int)(((struct sockaddr_in6 *)saa2->saBuf)->sin6_port);
869 ucp1 = (const unsigned char *)&(((struct sockaddr_in *)saa1->saBuf)->sin_addr);
870 ucp2 = (const unsigned char *)&(((struct sockaddr_in6 *)saa2->saBuf)->sin6_addr);
871 ucp0 = ucp2;
872 ucp2 += 12;
873 }
874 for (i = 0; i < 10; i++)
875 if ((int)ucp0[i] != 0x00)
876 return SA_RC(SA_ERR_MTC);
877 if (!((int)ucp0[10] == 0xFF && (int)ucp0[11] == 0xFF))
878 return SA_RC(SA_ERR_MTC);
879 nBits = 32;
880 }
881 #endif
882 else if (saa1->nFamily == AF_INET) {
883 np1 = (unsigned int)(((struct sockaddr_in *)saa1->saBuf)->sin_port);
884 np2 = (unsigned int)(((struct sockaddr_in *)saa2->saBuf)->sin_port);
885 ucp1 = (const unsigned char *)&(((struct sockaddr_in *)saa1->saBuf)->sin_addr);
886 ucp2 = (const unsigned char *)&(((struct sockaddr_in *)saa2->saBuf)->sin_addr);
887 nBits = 32;
888 }
889 #ifdef AF_INET6
890 else if (saa1->nFamily == AF_INET6) {
891 np1 = (unsigned int)(((struct sockaddr_in6 *)saa1->saBuf)->sin6_port);
892 np2 = (unsigned int)(((struct sockaddr_in6 *)saa2->saBuf)->sin6_port);
893 ucp1 = (const unsigned char *)&(((struct sockaddr_in6 *)saa1->saBuf)->sin6_addr);
894 ucp2 = (const unsigned char *)&(((struct sockaddr_in6 *)saa2->saBuf)->sin6_addr);
895 nBits = 128;
896 }
897 #endif
898 else
899 return SA_RC(SA_ERR_INT);
900
901 /* make sure we do not compare than possible */
902 if (prefixlen > (nBits+1))
903 return SA_RC(SA_ERR_ARG);
904
905 /* support equal matching (= all bits plus optionally port) */
906 bMatchPort = FALSE;
907 if (prefixlen < 0) {
908 if (prefixlen < -1)
909 bMatchPort = TRUE;
910 prefixlen = nBits;
911 }
912
913 /* perform address representation comparison
914 (assumption guaranteed by API: network byte order is used) */
915 nBytes = (prefixlen / 8);
916 nBits = (prefixlen % 8);
917 if (nBytes > 0) {
918 if (memcmp(ucp1, ucp2, (size_t)nBytes) != 0)
919 return SA_RC(SA_ERR_MTC);
920 }
921 if (nBits > 0) {
922 uc1 = (unsigned int)ucp1[nBytes];
923 uc2 = (unsigned int)ucp2[nBytes];
924 mask = ((unsigned int)0xFF << (8-nBits)) & (unsigned int)0xFF;
925 if ((uc1 & mask) != (uc2 & mask))
926 return SA_RC(SA_ERR_MTC);
927 }
928
929 /* optionally perform additional port matching */
930 if (bMatchPort)
931 if (np1 != np2)
932 return SA_RC(SA_ERR_MTC);
933
934 return SA_OK;
935 }
936
937 /* set timeouts if timeouts or done in kernel */
sa_socket_settimeouts(const sa_t * sa)938 static sa_rc_t sa_socket_settimeouts(const sa_t *sa)
939 {
940 /* stop processing if socket is still not allocated */
941 if (sa->fdSocket == -1)
942 return SA_OK;
943
944 #if defined(SO_RCVTIMEO) && defined(USE_SO_RCVTIMEO) && defined(SO_SNDTIMEO) && defined(USE_SO_SNDTIMEO)
945 if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_READ])) {
946 if (setsockopt(sa->fdSocket, SOL_SOCKET, SO_RCVTIMEO,
947 (const void *)(&sa->tvTimeout[SA_TIMEOUT_READ]),
948 (socklen_t)(sizeof(sa->tvTimeout[SA_TIMEOUT_READ]))) < 0)
949 return SA_RC(SA_ERR_SYS);
950 }
951 if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_WRITE])) {
952 if (setsockopt(sa->fdSocket, SOL_SOCKET, SO_SNDTIMEO,
953 (const void *)(&sa->tvTimeout[SA_TIMEOUT_WRITE]),
954 (socklen_t)(sizeof(sa->tvTimeout[SA_TIMEOUT_WRITE]))) < 0)
955 return SA_RC(SA_ERR_SYS);
956 }
957 #endif
958 return SA_OK;
959 }
960
961 /* set socket options */
sa_socket_setoptions(sa_t * sa)962 static sa_rc_t sa_socket_setoptions(sa_t *sa)
963 {
964 int i;
965 sa_rc_t rv;
966
967 /* stop processing if socket is still not allocated */
968 if (sa->fdSocket == -1)
969 return SA_OK;
970
971 /* check for pending options */
972 rv = SA_OK;
973 for (i = 0; i < (int)(sizeof(sa->optInfo)/sizeof(sa->optInfo[0])); i++) {
974 if (sa->optInfo[i].todo) {
975 switch (i) {
976 /* enable/disable Nagle's Algorithm (see RFC898) */
977 case SA_OPTION_NAGLE: {
978 #if defined(IPPROTO_TCP) && defined(TCP_NODELAY)
979 int mode = sa->optInfo[i].value;
980 if (setsockopt(sa->fdSocket, IPPROTO_TCP, TCP_NODELAY,
981 (const void *)&mode,
982 (socklen_t)sizeof(mode)) < 0)
983 rv = SA_ERR_SYS;
984 else
985 sa->optInfo[i].todo = FALSE;
986 #endif
987 break;
988 }
989 /* enable/disable linger close semantics */
990 case SA_OPTION_LINGER: {
991 #if defined(SO_LINGER)
992 struct linger linger;
993 linger.l_onoff = (sa->optInfo[i].value == 0 ? 0 : 1);
994 linger.l_linger = (sa->optInfo[i].value <= 0 ? 0 : sa->optInfo[i].value);
995 if (setsockopt(sa->fdSocket, SOL_SOCKET, SO_LINGER,
996 (const void *)&linger,
997 (socklen_t)sizeof(struct linger)) < 0)
998 rv = SA_ERR_SYS;
999 else
1000 sa->optInfo[i].todo = FALSE;
1001 #endif
1002 break;
1003 }
1004 /* enable/disable reusability of binding to address */
1005 case SA_OPTION_REUSEADDR: {
1006 #if defined(SO_REUSEADDR)
1007 int mode = sa->optInfo[i].value;
1008 if (setsockopt(sa->fdSocket, SOL_SOCKET, SO_REUSEADDR,
1009 (const void *)&mode, (socklen_t)sizeof(mode)) < 0)
1010 rv = SA_ERR_SYS;
1011 else
1012 sa->optInfo[i].todo = FALSE;
1013 #endif
1014 break;
1015 }
1016 /* enable/disable reusability of binding to port */
1017 case SA_OPTION_REUSEPORT: {
1018 #if defined(SO_REUSEPORT)
1019 int mode = sa->optInfo[i].value;
1020 if (setsockopt(sa->fdSocket, SOL_SOCKET, SO_REUSEPORT,
1021 (const void *)&mode, (socklen_t)sizeof(mode)) < 0)
1022 rv = SA_ERR_SYS;
1023 else
1024 sa->optInfo[i].todo = FALSE;
1025 #endif
1026 break;
1027 }
1028 /* enable/disable non-blocking I/O mode */
1029 case SA_OPTION_NONBLOCK: {
1030 int mode = sa->optInfo[i].value;
1031 int flags;
1032 if ((flags = fcntl(sa->fdSocket, F_GETFL, 0)) < 0) {
1033 rv = SA_ERR_SYS;
1034 break;
1035 }
1036 if (mode == 0)
1037 flags &= ~(O_NONBLOCK);
1038 else
1039 flags |= O_NONBLOCK;
1040 if (fcntl(sa->fdSocket, F_SETFL, flags) < 0)
1041 rv = SA_ERR_SYS;
1042 else
1043 sa->optInfo[i].todo = FALSE;
1044 break;
1045 }
1046 default: /* NOTREACHED */ break;
1047 }
1048 }
1049 }
1050
1051 return SA_RC(rv);
1052 }
1053
1054 /* internal lazy/delayed initialization of underlying socket */
sa_socket_init(sa_t * sa,int nFamily)1055 static sa_rc_t sa_socket_init(sa_t *sa, int nFamily)
1056 {
1057 int nType;
1058 int nProto;
1059 #if !(defined(IPPROTO_TCP) && defined(IPPROTO_UDP))
1060 struct protoent *pe;
1061 #endif
1062 sa_rc_t rv;
1063
1064 /* argument sanity check(s) */
1065 if (sa == NULL)
1066 return SA_RC(SA_ERR_ARG);
1067
1068 /* only perform operation if socket still does not exist */
1069 if (sa->fdSocket != -1)
1070 return SA_RC(SA_ERR_USE);
1071
1072 /* determine socket type */
1073 if (sa->eType == SA_TYPE_STREAM)
1074 nType = SOCK_STREAM;
1075 else if (sa->eType == SA_TYPE_DATAGRAM)
1076 nType = SOCK_DGRAM;
1077 else
1078 return SA_RC(SA_ERR_INT);
1079
1080 /* determine socket protocol */
1081 if (nFamily == AF_LOCAL)
1082 nProto = 0;
1083 #ifdef AF_INET6
1084 else if (nFamily == AF_INET || nFamily == AF_INET6) {
1085 #else
1086 else if (nFamily == AF_INET) {
1087 #endif
1088 #if defined(IPPROTO_TCP) && defined(IPPROTO_UDP)
1089 if (nType == SOCK_STREAM)
1090 nProto = IPPROTO_TCP;
1091 else if (nType == SOCK_DGRAM)
1092 nProto = IPPROTO_UDP;
1093 else
1094 return SA_RC(SA_ERR_INT);
1095 #else
1096 if (nType == SOCK_STREAM)
1097 pe = getprotobyname("tcp");
1098 else if (nType == SOCK_DGRAM)
1099 pe = getprotobyname("udp");
1100 else
1101 return SA_RC(SA_ERR_INT);
1102 if (pe == NULL)
1103 return SA_RC(SA_ERR_SYS);
1104 nProto = pe->p_proto;
1105 #endif
1106 }
1107 else
1108 return SA_RC(SA_ERR_INT);
1109
1110 /* create the underlying socket */
1111 if ((sa->fdSocket = socket(nFamily, nType, nProto)) == -1)
1112 return SA_RC(SA_ERR_SYS);
1113
1114 /* optionally set kernel timeouts */
1115 if ((rv = sa_socket_settimeouts(sa)) != SA_OK)
1116 return SA_RC(rv);
1117
1118 /* optionally configure changed options */
1119 if ((rv = sa_socket_setoptions(sa)) != SA_OK)
1120 return SA_RC(rv);
1121
1122 return SA_OK;
1123 }
1124
1125 /* internal destruction of underlying socket */
1126 static sa_rc_t sa_socket_kill(sa_t *sa)
1127 {
1128 /* argument sanity check(s) */
1129 if (sa == NULL)
1130 return SA_RC(SA_ERR_ARG);
1131
1132 /* check context */
1133 if (sa->fdSocket == -1)
1134 return SA_RC(SA_ERR_USE);
1135
1136 /* close socket */
1137 (void)close(sa->fdSocket);
1138 sa->fdSocket = -1;
1139
1140 return SA_OK;
1141 }
1142
1143 /* create abstract socket object */
1144 sa_rc_t sa_create(sa_t **sap)
1145 {
1146 sa_t *sa;
1147 int i;
1148
1149 /* argument sanity check(s) */
1150 if (sap == NULL)
1151 return SA_RC(SA_ERR_ARG);
1152
1153 /* allocate and initialize socket object */
1154 if ((sa = (sa_t *)malloc(sizeof(sa_t))) == NULL)
1155 return SA_RC(SA_ERR_MEM);
1156
1157 /* init object attributes */
1158 sa->eType = SA_TYPE_STREAM;
1159 sa->fdSocket = -1;
1160 sa->nReadLen = 0;
1161 sa->nReadSize = 0;
1162 sa->cpReadBuf = NULL;
1163 sa->nWriteLen = 0;
1164 sa->nWriteSize = 0;
1165 sa->cpWriteBuf = NULL;
1166
1167 /* init timeval object attributes */
1168 for (i = 0; i < (int)(sizeof(sa->tvTimeout)/sizeof(sa->tvTimeout[0])); i++) {
1169 sa->tvTimeout[i].tv_sec = 0;
1170 sa->tvTimeout[i].tv_usec = 0;
1171 }
1172
1173 /* init options object attributes */
1174 for (i = 0; i < (int)(sizeof(sa->optInfo)/sizeof(sa->optInfo[0])); i++) {
1175 sa->optInfo[i].todo = FALSE;
1176 sa->optInfo[i].value = 0;
1177 }
1178
1179 /* init syscall object attributes */
1180 SA_SC_ASSIGN(sa, connect, connect, NULL);
1181 SA_SC_ASSIGN(sa, accept, accept, NULL);
1182 SA_SC_ASSIGN(sa, select, select, NULL);
1183 SA_SC_ASSIGN(sa, read, read, NULL);
1184 SA_SC_ASSIGN(sa, write, write, NULL);
1185 SA_SC_ASSIGN(sa, recvfrom, recvfrom, NULL);
1186 SA_SC_ASSIGN(sa, sendto, sendto, NULL);
1187
1188 /* pass object to caller */
1189 *sap = sa;
1190
1191 return SA_OK;
1192 }
1193
1194 /* destroy abstract socket object */
1195 sa_rc_t sa_destroy(sa_t *sa)
1196 {
1197 /* argument sanity check(s) */
1198 if (sa == NULL)
1199 return SA_RC(SA_ERR_ARG);
1200
1201 /* kill underlying socket */
1202 (void)sa_socket_kill(sa);
1203
1204 /* free object and sub-objects */
1205 if (sa->cpReadBuf != NULL)
1206 free(sa->cpReadBuf);
1207 if (sa->cpWriteBuf != NULL)
1208 free(sa->cpWriteBuf);
1209 free(sa);
1210
1211 return SA_OK;
1212 }
1213
1214 /* switch communication type of socket */
1215 sa_rc_t sa_type(sa_t *sa, sa_type_t type)
1216 {
1217 /* argument sanity check(s) */
1218 if (sa == NULL)
1219 return SA_RC(SA_ERR_ARG);
1220 if (!(type == SA_TYPE_STREAM || type == SA_TYPE_DATAGRAM))
1221 return SA_RC(SA_ERR_ARG);
1222
1223 /* kill underlying socket if type changes */
1224 if (sa->eType != type)
1225 (void)sa_socket_kill(sa);
1226
1227 /* set new type */
1228 sa->eType = type;
1229
1230 return SA_OK;
1231 }
1232
1233 /* configure I/O timeout */
1234 sa_rc_t sa_timeout(sa_t *sa, sa_timeout_t id, long sec, long usec)
1235 {
1236 int i;
1237 sa_rc_t rv;
1238
1239 /* argument sanity check(s) */
1240 if (sa == NULL)
1241 return SA_RC(SA_ERR_ARG);
1242
1243 if (id == SA_TIMEOUT_ALL) {
1244 for (i = 0; i < (int)(sizeof(sa->tvTimeout)/sizeof(sa->tvTimeout[0])); i++) {
1245 sa->tvTimeout[i].tv_sec = sec;
1246 sa->tvTimeout[i].tv_usec = usec;
1247 }
1248 }
1249 else {
1250 sa->tvTimeout[id].tv_sec = sec;
1251 sa->tvTimeout[id].tv_usec = usec;
1252 }
1253
1254 /* try to already set timeouts */
1255 if ((rv = sa_socket_settimeouts(sa)) != SA_OK)
1256 return SA_RC(rv);
1257
1258 return SA_OK;
1259 }
1260
1261 /* configure I/O buffers */
1262 sa_rc_t sa_buffer(sa_t *sa, sa_buffer_t id, size_t size)
1263 {
1264 char *cp;
1265
1266 /* argument sanity check(s) */
1267 if (sa == NULL)
1268 return SA_RC(SA_ERR_ARG);
1269
1270 if (id == SA_BUFFER_READ) {
1271 /* configure read/incoming buffer */
1272 if (sa->nReadLen > (int)size)
1273 return SA_RC(SA_ERR_USE);
1274 if (size > 0) {
1275 if (sa->cpReadBuf == NULL)
1276 cp = (char *)malloc(size);
1277 else
1278 cp = (char *)realloc(sa->cpReadBuf, size);
1279 if (cp == NULL)
1280 return SA_RC(SA_ERR_MEM);
1281 sa->cpReadBuf = cp;
1282 sa->nReadSize = (int)size;
1283 }
1284 else {
1285 if (sa->cpReadBuf != NULL)
1286 free(sa->cpReadBuf);
1287 sa->cpReadBuf = NULL;
1288 sa->nReadSize = 0;
1289 }
1290 }
1291 else if (id == SA_BUFFER_WRITE) {
1292 /* configure write/outgoing buffer */
1293 if (sa->nWriteLen > (int)size)
1294 return SA_RC(SA_ERR_USE);
1295 if (size > 0) {
1296 if (sa->cpWriteBuf == NULL)
1297 cp = (char *)malloc(size);
1298 else
1299 cp = (char *)realloc(sa->cpWriteBuf, size);
1300 if (cp == NULL)
1301 return SA_RC(SA_ERR_MEM);
1302 sa->cpWriteBuf = cp;
1303 sa->nWriteSize = (int)size;
1304 }
1305 else {
1306 if (sa->cpWriteBuf != NULL)
1307 free(sa->cpWriteBuf);
1308 sa->cpWriteBuf = NULL;
1309 sa->nWriteSize = 0;
1310 }
1311 }
1312 else
1313 return SA_RC(SA_ERR_ARG);
1314
1315 return SA_OK;
1316 }
1317
1318 /* configure socket option */
1319 sa_rc_t sa_option(sa_t *sa, sa_option_t id, ...)
1320 {
1321 sa_rc_t rv;
1322 va_list ap;
1323
1324 /* argument sanity check(s) */
1325 if (sa == NULL)
1326 return SA_RC(SA_ERR_ARG);
1327
1328 /* process option */
1329 rv = SA_OK;
1330 va_start(ap, id);
1331 switch (id) {
1332 case SA_OPTION_NAGLE: {
1333 #if defined(IPPROTO_TCP) && defined(TCP_NODELAY)
1334 int mode = ((int)va_arg(ap, int) ? 1 : 0);
1335 sa->optInfo[SA_OPTION_NAGLE].value = mode;
1336 sa->optInfo[SA_OPTION_NAGLE].todo = TRUE;
1337 #else
1338 rv = SA_ERR_IMP;
1339 #endif
1340 break;
1341 }
1342 case SA_OPTION_LINGER: {
1343 #if defined(SO_LINGER)
1344 int amount = (int)va_arg(ap, int);
1345 sa->optInfo[SA_OPTION_LINGER].value = amount;
1346 sa->optInfo[SA_OPTION_LINGER].todo = TRUE;
1347 #else
1348 rv = SA_ERR_IMP;
1349 #endif
1350 break;
1351 }
1352 case SA_OPTION_REUSEADDR:
1353 {
1354 #if defined(SO_REUSEADDR)
1355 int mode = ((int)va_arg(ap, int) ? 1 : 0);
1356 sa->optInfo[SA_OPTION_REUSEADDR].value = mode;
1357 sa->optInfo[SA_OPTION_REUSEADDR].todo = TRUE;
1358 #else
1359 rv = SA_ERR_IMP;
1360 #endif
1361 break;
1362 }
1363 case SA_OPTION_REUSEPORT:
1364 {
1365 #if defined(SO_REUSEPORT)
1366 int mode = ((int)va_arg(ap, int) ? 1 : 0);
1367 sa->optInfo[SA_OPTION_REUSEPORT].value = mode;
1368 sa->optInfo[SA_OPTION_REUSEPORT].todo = TRUE;
1369 #else
1370 rv = SA_ERR_IMP;
1371 #endif
1372 break;
1373 }
1374 case SA_OPTION_NONBLOCK: {
1375 int mode = (int)va_arg(ap, int);
1376 sa->optInfo[SA_OPTION_NONBLOCK].value = mode;
1377 sa->optInfo[SA_OPTION_NONBLOCK].todo = TRUE;
1378 break;
1379 }
1380 default: {
1381 rv = SA_ERR_ARG;
1382 }
1383 }
1384 va_end(ap);
1385
1386 /* if an error already occured, stop here */
1387 if (rv != SA_OK)
1388 return SA_RC(rv);
1389
1390 /* else already (re)set) options (if possible) */
1391 if ((rv = sa_socket_setoptions(sa)) != SA_OK)
1392 return SA_RC(rv);
1393
1394 return SA_OK;
1395 }
1396
1397 /* override system call */
1398 sa_rc_t sa_syscall(sa_t *sa, sa_syscall_t id, void (*fptr)(void), void *fctx)
1399 {
1400 sa_rc_t rv;
1401
1402 /* argument sanity check(s) */
1403 if (sa == NULL || fptr == NULL)
1404 return SA_RC(SA_ERR_ARG);
1405
1406 /* assign system call */
1407 rv = SA_OK;
1408 switch (id) {
1409 case SA_SYSCALL_CONNECT: SA_SC_ASSIGN(sa, connect, fptr, fctx); break;
1410 case SA_SYSCALL_ACCEPT: SA_SC_ASSIGN(sa, accept, fptr, fctx); break;
1411 case SA_SYSCALL_SELECT: SA_SC_ASSIGN(sa, select, fptr, fctx); break;
1412 case SA_SYSCALL_READ: SA_SC_ASSIGN(sa, read, fptr, fctx); break;
1413 case SA_SYSCALL_WRITE: SA_SC_ASSIGN(sa, write, fptr, fctx); break;
1414 case SA_SYSCALL_RECVFROM: SA_SC_ASSIGN(sa, recvfrom, fptr, fctx); break;
1415 case SA_SYSCALL_SENDTO: SA_SC_ASSIGN(sa, sendto, fptr, fctx); break;
1416 default: rv = SA_ERR_ARG;
1417 }
1418
1419 return SA_RC(rv);
1420 }
1421
1422 /* bind socket to a local address */
1423 sa_rc_t sa_bind(sa_t *sa, const sa_addr_t *laddr)
1424 {
1425 sa_rc_t rv;
1426 struct sockaddr_un *un;
1427
1428 /* argument sanity check(s) */
1429 if (sa == NULL || laddr == NULL)
1430 return SA_RC(SA_ERR_ARG);
1431
1432 /* lazy creation of underlying socket */
1433 if (sa->fdSocket == -1)
1434 if ((rv = sa_socket_init(sa, laddr->nFamily)) != SA_OK)
1435 return SA_RC(rv);
1436
1437 /* remove a possibly existing old Unix Domain socket on filesystem */
1438 if (laddr->nFamily == AF_LOCAL) {
1439 un = (struct sockaddr_un *)((void *)laddr->saBuf);
1440 (void)unlink(un->sun_path);
1441 }
1442
1443 /* perform bind operation on underlying socket */
1444 if (bind(sa->fdSocket, laddr->saBuf, laddr->slBuf) == -1)
1445 return SA_RC(SA_ERR_SYS);
1446
1447 return SA_OK;
1448 }
1449
1450 /* connect socket to a remote address */
1451 sa_rc_t sa_connect(sa_t *sa, const sa_addr_t *raddr)
1452 {
1453 int flags, n, error;
1454 fd_set rset, wset;
1455 socklen_t len;
1456 sa_rc_t rv;
1457 struct timeval *tv;
1458 struct timeval tv_buf;
1459
1460 /* argument sanity check(s) */
1461 if (sa == NULL || raddr == NULL)
1462 return SA_RC(SA_ERR_ARG);
1463
1464 /* connecting is only possible for stream communication */
1465 if (sa->eType != SA_TYPE_STREAM)
1466 return SA_RC(SA_ERR_USE);
1467
1468 /* lazy creation of underlying socket */
1469 if (sa->fdSocket == -1)
1470 if ((rv = sa_socket_init(sa, raddr->nFamily)) != SA_OK)
1471 return SA_RC(rv);
1472
1473 /* prepare return code decision */
1474 rv = SA_OK;
1475 error = 0;
1476
1477 /* temporarily switch underlying socket to non-blocking mode
1478 (necessary under timeout-aware operation only) */
1479 flags = 0;
1480 if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_CONNECT])) {
1481 flags = fcntl(sa->fdSocket, F_GETFL, 0);
1482 (void)fcntl(sa->fdSocket, F_SETFL, flags|O_NONBLOCK);
1483 }
1484
1485 /* perform the connect operation */
1486 if ((n = SA_SC_CALL_3(sa, connect, sa->fdSocket, raddr->saBuf, raddr->slBuf)) < 0) {
1487 if (errno != EINTR && errno != EINPROGRESS) {
1488 /* we have to perform the following post-processing under
1489 EINPROGRESS anway, but actually also for EINTR according
1490 to Unix Network Programming, volume 1, section 5.9, W.
1491 Richard Stevens: "What we are doing [] is restarting
1492 the interrupted system call ourself. This is fine for
1493 accept, along with the functions such as read, write,
1494 select and open. But there is one function that we cannot
1495 restart ourself: connect. If this function returns EINTR,
1496 we cannot call it again, as doing so will return an
1497 immediate error. When connect is interrupted by a caught
1498 signal and is not automatically restarted, we must call
1499 select to wait for the connection to complete, as we
1500 describe in section 15.3." */
1501 error = errno;
1502 goto done;
1503 }
1504 }
1505
1506 /* ok if connect completed immediately */
1507 if (n == 0)
1508 goto done;
1509
1510 /* wait for read or write possibility */
1511 FD_ZERO(&rset);
1512 FD_ZERO(&wset);
1513 FD_SET(sa->fdSocket, &rset);
1514 FD_SET(sa->fdSocket, &wset);
1515 if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_CONNECT])) {
1516 memcpy(&tv_buf, &sa->tvTimeout[SA_TIMEOUT_CONNECT], sizeof(struct timeval));
1517 tv = &tv_buf;
1518 }
1519 else
1520 tv = NULL;
1521 do {
1522 n = SA_SC_CALL_5(sa, select, sa->fdSocket+1, &rset, &wset, (fd_set *)NULL, tv);
1523 } while (n == -1 && errno == EINTR);
1524
1525 /* decide on return semantic */
1526 if (n < 0) {
1527 error = errno;
1528 goto done;
1529 }
1530 else if (n == 0) {
1531 (void)close(sa->fdSocket); /* stop TCP three-way handshake */
1532 sa->fdSocket = -1;
1533 rv = SA_ERR_TMT;
1534 goto done;
1535 }
1536
1537 /* fetch pending error */
1538 len = (socklen_t)sizeof(error);
1539 if (getsockopt(sa->fdSocket, SOL_SOCKET, SO_ERROR, (void *)&error, &len) < 0)
1540 error = errno;
1541
1542 done:
1543
1544 /* reset socket flags
1545 (necessary under timeout-aware operation only) */
1546 if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_CONNECT]))
1547 (void)fcntl(sa->fdSocket, F_SETFL, flags);
1548
1549 /* optionally set errno */
1550 if (error != 0) {
1551 (void)close(sa->fdSocket); /* just in case */
1552 sa->fdSocket = -1;
1553 errno = error;
1554 rv = SA_ERR_SYS;
1555 }
1556
1557 return SA_RC(rv);
1558 }
1559
1560 /* listen on socket for connections */
1561 sa_rc_t sa_listen(sa_t *sa, int backlog)
1562 {
1563 /* argument sanity check(s) */
1564 if (sa == NULL)
1565 return SA_RC(SA_ERR_ARG);
1566
1567 /* listening is only possible for stream communication */
1568 if (sa->eType != SA_TYPE_STREAM)
1569 return SA_RC(SA_ERR_USE);
1570
1571 /* at least sa_bind() has to be already performed */
1572 if (sa->fdSocket == -1)
1573 return SA_RC(SA_ERR_USE);
1574
1575 /* perform listen operation on underlying socket */
1576 if (listen(sa->fdSocket, backlog) == -1)
1577 return SA_RC(SA_ERR_SYS);
1578
1579 return SA_OK;
1580 }
1581
1582 /* accept a connection on socket */
1583 sa_rc_t sa_accept(sa_t *sa, sa_addr_t **caddr, sa_t **csa)
1584 {
1585 sa_rc_t rv;
1586 int n;
1587 fd_set fds;
1588 union {
1589 struct sockaddr_un un;
1590 struct sockaddr_in sa4;
1591 #ifdef AF_INET6
1592 struct sockaddr_in6 sa6;
1593 #endif
1594 } sa_buf;
1595 socklen_t sa_size;
1596 struct timeval tv;
1597 int s;
1598 int i;
1599
1600 /* argument sanity check(s) */
1601 if (sa == NULL || caddr == NULL || csa == NULL)
1602 return SA_RC(SA_ERR_ARG);
1603
1604 /* accepting connections is only possible for stream communication */
1605 if (sa->eType != SA_TYPE_STREAM)
1606 return SA_RC(SA_ERR_USE);
1607
1608 /* at least sa_listen() has to be already performed */
1609 if (sa->fdSocket == -1)
1610 return SA_RC(SA_ERR_USE);
1611
1612 /* if timeout is enabled, perform a smart-blocking wait */
1613 if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_ACCEPT])) {
1614 FD_ZERO(&fds);
1615 FD_SET(sa->fdSocket, &fds);
1616 memcpy(&tv, &sa->tvTimeout[SA_TIMEOUT_ACCEPT], sizeof(struct timeval));
1617 do {
1618 n = SA_SC_CALL_5(sa, select, sa->fdSocket+1, &fds, (fd_set *)NULL, (fd_set *)NULL, &tv);
1619 } while (n == -1 && errno == EINTR);
1620 if (n == 0)
1621 return SA_RC(SA_ERR_TMT);
1622 if (n <= 0)
1623 return SA_RC(SA_ERR_SYS);
1624 }
1625
1626 /* perform accept operation on underlying socket */
1627 sa_size = (socklen_t)sizeof(sa_buf);
1628 do {
1629 s = SA_SC_CALL_3(sa, accept, sa->fdSocket, (struct sockaddr *)&sa_buf, &sa_size);
1630 } while (s == -1 && errno == EINTR);
1631 if (s == -1)
1632 return SA_RC(SA_ERR_SYS);
1633
1634 /* create result address object */
1635 if ((rv = sa_addr_create(caddr)) != SA_OK)
1636 return SA_RC(rv);
1637 if ((rv = sa_addr_s2a(*caddr, (struct sockaddr *)&sa_buf, sa_size)) != SA_OK) {
1638 (void)sa_addr_destroy(*caddr);
1639 return SA_RC(rv);
1640 }
1641
1642 /* create result socket object */
1643 if ((rv = sa_create(csa)) != SA_OK) {
1644 (void)sa_addr_destroy(*caddr);
1645 return SA_RC(rv);
1646 }
1647
1648 /* fill-in child socket */
1649 (*csa)->fdSocket = s;
1650
1651 /* copy-over original system calls */
1652 SA_SC_COPY((*csa), sa, connect);
1653 SA_SC_COPY((*csa), sa, accept);
1654 SA_SC_COPY((*csa), sa, select);
1655 SA_SC_COPY((*csa), sa, read);
1656 SA_SC_COPY((*csa), sa, write);
1657 SA_SC_COPY((*csa), sa, recvfrom);
1658 SA_SC_COPY((*csa), sa, sendto);
1659
1660 /* copy-over original timeout values */
1661 for (i = 0; i < (int)(sizeof(sa->tvTimeout)/sizeof(sa->tvTimeout[0])); i++) {
1662 (*csa)->tvTimeout[i].tv_sec = sa->tvTimeout[i].tv_sec;
1663 (*csa)->tvTimeout[i].tv_usec = sa->tvTimeout[i].tv_usec;
1664 }
1665
1666 return SA_OK;
1667 }
1668
1669 /* determine remote address */
1670 sa_rc_t sa_getremote(sa_t *sa, sa_addr_t **raddr)
1671 {
1672 sa_rc_t rv;
1673 union {
1674 struct sockaddr_in sa4;
1675 #ifdef AF_INET6
1676 struct sockaddr_in6 sa6;
1677 #endif
1678 } sa_buf;
1679 socklen_t sa_size;
1680
1681 /* argument sanity check(s) */
1682 if (sa == NULL || raddr == NULL)
1683 return SA_RC(SA_ERR_ARG);
1684
1685 /* peers exist only for stream communication */
1686 if (sa->eType != SA_TYPE_STREAM)
1687 return SA_RC(SA_ERR_USE);
1688
1689 /* at least sa_connect() or sa_accept() has to be already performed */
1690 if (sa->fdSocket == -1)
1691 return SA_RC(SA_ERR_USE);
1692
1693 /* determine remote address of underlying socket */
1694 sa_size = (socklen_t)sizeof(sa_buf);
1695 if (getpeername(sa->fdSocket, (struct sockaddr *)&sa_buf, &sa_size) < 0)
1696 return SA_RC(SA_ERR_SYS);
1697
1698 /* create result address object */
1699 if ((rv = sa_addr_create(raddr)) != SA_OK)
1700 return SA_RC(rv);
1701 if ((rv = sa_addr_s2a(*raddr, (struct sockaddr *)&sa_buf, sa_size)) != SA_OK) {
1702 (void)sa_addr_destroy(*raddr);
1703 return SA_RC(rv);
1704 }
1705
1706 return SA_OK;
1707 }
1708
1709 /* determine local address */
1710 sa_rc_t sa_getlocal(sa_t *sa, sa_addr_t **laddr)
1711 {
1712 sa_rc_t rv;
1713 union {
1714 struct sockaddr_in sa4;
1715 #ifdef AF_INET6
1716 struct sockaddr_in6 sa6;
1717 #endif
1718 } sa_buf;
1719 socklen_t sa_size;
1720
1721 /* argument sanity check(s) */
1722 if (sa == NULL || laddr == NULL)
1723 return SA_RC(SA_ERR_ARG);
1724
1725 /* at least sa_bind() has to be already performed */
1726 if (sa->fdSocket == -1)
1727 return SA_RC(SA_ERR_USE);
1728
1729 /* determine local address of underlying socket */
1730 sa_size = (socklen_t)sizeof(sa_buf);
1731 if (getsockname(sa->fdSocket, (struct sockaddr *)&sa_buf, &sa_size) < 0)
1732 return SA_RC(SA_ERR_SYS);
1733
1734 /* create result address object */
1735 if ((rv = sa_addr_create(laddr)) != SA_OK)
1736 return SA_RC(rv);
1737 if ((rv = sa_addr_s2a(*laddr, (struct sockaddr *)&sa_buf, sa_size)) != SA_OK) {
1738 (void)sa_addr_destroy(*laddr);
1739 return SA_RC(rv);
1740 }
1741
1742 return SA_OK;
1743 }
1744
1745 /* peek at underlying socket */
1746 sa_rc_t sa_getfd(sa_t *sa, int *fd)
1747 {
1748 /* argument sanity check(s) */
1749 if (sa == NULL || fd == NULL)
1750 return SA_RC(SA_ERR_ARG);
1751
1752 /* if still no socket exists, say this explicitly */
1753 if (sa->fdSocket == -1)
1754 return SA_RC(SA_ERR_USE);
1755
1756 /* pass socket to caller */
1757 *fd = sa->fdSocket;
1758
1759 return SA_OK;
1760 }
1761
1762 /* internal raw read operation */
1763 static int sa_read_raw(sa_t *sa, char *cpBuf, int nBufLen)
1764 {
1765 int rv;
1766 #if !(defined(SO_RCVTIMEO) && defined(USE_SO_RCVTIMEO) && defined(SO_SNDTIMEO) && defined(USE_SO_SNDTIMEO))
1767 fd_set fds;
1768 struct timeval tv;
1769 #endif
1770
1771 /* if timeout is enabled, perform explicit/smart blocking instead
1772 of implicitly/hard blocking in the read(2) system call */
1773 #if !(defined(SO_RCVTIMEO) && defined(USE_SO_RCVTIMEO) && defined(SO_SNDTIMEO) && defined(USE_SO_SNDTIMEO))
1774 if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_READ])) {
1775 FD_ZERO(&fds);
1776 FD_SET(sa->fdSocket, &fds);
1777 memcpy(&tv, &sa->tvTimeout[SA_TIMEOUT_READ], sizeof(struct timeval));
1778 do {
1779 rv = SA_SC_CALL_5(sa, select, sa->fdSocket+1, &fds, (fd_set *)NULL, (fd_set *)NULL, &tv);
1780 } while (rv == -1 && errno == EINTR);
1781 if (rv == 0) {
1782 errno = ETIMEDOUT;
1783 return -1;
1784 }
1785 }
1786 #endif
1787
1788 /* perform read operation on underlying socket */
1789 do {
1790 rv = (int)SA_SC_CALL_3(sa, read, sa->fdSocket, cpBuf, (size_t)nBufLen);
1791 } while (rv == -1 && errno == EINTR);
1792
1793 #if defined(SO_RCVTIMEO) && defined(USE_SO_RCVTIMEO) && defined(SO_SNDTIMEO) && defined(USE_SO_SNDTIMEO)
1794 if (rv == -1 && errno == EWOULDBLOCK)
1795 errno = ETIMEDOUT;
1796 #endif
1797
1798 return rv;
1799 }
1800
1801 /* read data from socket */
1802 sa_rc_t sa_read(sa_t *sa, char *cpBuf, size_t nBufReq, size_t *nBufRes)
1803 {
1804 int n;
1805 sa_rc_t rv;
1806 int res;
1807
1808 /* argument sanity check(s) */
1809 if (sa == NULL || cpBuf == NULL || nBufReq == 0)
1810 return SA_RC(SA_ERR_ARG);
1811
1812 /* reading is only possible for stream communication */
1813 if (sa->eType != SA_TYPE_STREAM)
1814 return SA_RC(SA_ERR_USE);
1815
1816 /* at least a connection has to exist */
1817 if (sa->fdSocket == -1)
1818 return SA_RC(SA_ERR_USE);
1819
1820 /* perform read operation */
1821 rv = SA_OK;
1822 if (sa->nReadSize == 0) {
1823 /* user-space unbuffered I/O */
1824 if (sa->nWriteLen > 0)
1825 (void)sa_flush(sa);
1826 res = sa_read_raw(sa, cpBuf, (int)nBufReq);
1827 if (res == 0)
1828 rv = SA_ERR_EOF;
1829 else if (res < 0 && errno == ETIMEDOUT)
1830 rv = SA_ERR_TMT;
1831 else if (res < 0)
1832 rv = SA_ERR_SYS;
1833 }
1834 else {
1835 /* user-space buffered I/O */
1836 res = 0;
1837 for (;;) {
1838 if ((int)nBufReq <= sa->nReadLen) {
1839 /* buffer holds enough data, so just use this */
1840 memmove(cpBuf, sa->cpReadBuf, nBufReq);
1841 memmove(sa->cpReadBuf, sa->cpReadBuf+nBufReq, sa->nReadLen-nBufReq);
1842 sa->nReadLen -= nBufReq;
1843 res += nBufReq;
1844 }
1845 else {
1846 if (sa->nReadLen > 0) {
1847 /* fetch already existing buffer contents as a start */
1848 memmove(cpBuf, sa->cpReadBuf, (size_t)sa->nReadLen);
1849 nBufReq -= sa->nReadLen;
1850 cpBuf += sa->nReadLen;
1851 res += sa->nReadLen;
1852 sa->nReadLen = 0;
1853 }
1854 if (sa->nWriteLen > 0)
1855 (void)sa_flush(sa);
1856 if ((int)nBufReq >= sa->nReadSize) {
1857 /* buffer is too small at all, so read directly */
1858 n = sa_read_raw(sa, cpBuf, (int)nBufReq);
1859 if (n > 0)
1860 res += n;
1861 else if (n == 0)
1862 rv = (res == 0 ? SA_ERR_EOF : SA_OK);
1863 else if (n < 0 && errno == ETIMEDOUT)
1864 rv = (res == 0 ? SA_ERR_TMT : SA_OK);
1865 else if (n < 0)
1866 rv = (res == 0 ? SA_ERR_SYS : SA_OK);
1867 }
1868 else {
1869 /* fill buffer with new data */
1870 n = sa_read_raw(sa, sa->cpReadBuf, sa->nReadSize);
1871 if (n < 0 && errno == ETIMEDOUT)
1872 /* timeout on this read, but perhaps ok as a whole */
1873 rv = (res == 0 ? SA_ERR_TMT : SA_OK);
1874 else if (n < 0)
1875 /* error on this read, but perhaps ok as a whole */
1876 rv = (res == 0 ? SA_ERR_SYS : SA_OK);
1877 else if (n == 0)
1878 /* EOF on this read, but perhaps ok as a whole */
1879 rv = (res == 0 ? SA_ERR_EOF : SA_OK);
1880 else {
1881 sa->nReadLen = n;
1882 continue; /* REPEAT OPERATION! */
1883 }
1884 }
1885 }
1886 break;
1887 }
1888 }
1889
1890 /* pass number of actually read bytes to caller */
1891 if (nBufRes != NULL)
1892 *nBufRes = (size_t)res;
1893
1894 return SA_RC(rv);
1895 }
1896
1897 /* read data from socket until [CR]LF (convenience function) */
1898 sa_rc_t sa_readln(sa_t *sa, char *cpBuf, size_t nBufReq, size_t *nBufRes)
1899 {
1900 char c;
1901 size_t n;
1902 size_t res;
1903 sa_rc_t rv;
1904
1905 /* argument sanity check(s) */
1906 if (sa == NULL || cpBuf == NULL || nBufReq == 0)
1907 return SA_RC(SA_ERR_ARG);
1908
1909 /* reading is only possible for stream communication */
1910 if (sa->eType != SA_TYPE_STREAM)
1911 return SA_RC(SA_ERR_USE);
1912
1913 /* at least a connection has to exist */
1914 if (sa->fdSocket == -1)
1915 return SA_RC(SA_ERR_USE);
1916
1917 /* we just perform a plain sa_read() per character, because if
1918 buffers are enabled, this is not as stupid as it looks at the first
1919 hand and if buffers are disabled, there is no better solution
1920 anyway. */
1921 rv = SA_OK;
1922 res = 0;
1923 while (res < (nBufReq-1)) {
1924 rv = sa_read(sa, &c, 1, &n);
1925 if (rv != SA_OK)
1926 break;
1927 if (n == 0)
1928 break;
1929 cpBuf[res++] = c;
1930 if (c == '\n')
1931 break;
1932 }
1933 cpBuf[res] = '\0';
1934
1935 /* pass number of actually read characters to caller */
1936 if (nBufRes != NULL)
1937 *nBufRes = res;
1938
1939 return SA_RC(rv);
1940 }
1941
1942 /* internal raw write operation */
1943 static int sa_write_raw(sa_t *sa, const char *cpBuf, int nBufLen)
1944 {
1945 int rv;
1946 #if !(defined(SO_RCVTIMEO) && defined(USE_SO_RCVTIMEO) && defined(SO_SNDTIMEO) && defined(USE_SO_SNDTIMEO))
1947 fd_set fds;
1948 struct timeval tv;
1949 #endif
1950
1951 /* if timeout is enabled, perform explicit/smart blocking instead
1952 of implicitly/hard blocking in the write(2) system call */
1953 #if !(defined(SO_RCVTIMEO) && defined(USE_SO_RCVTIMEO) && defined(SO_SNDTIMEO) && defined(USE_SO_SNDTIMEO))
1954 if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_WRITE])) {
1955 FD_ZERO(&fds);
1956 FD_SET(sa->fdSocket, &fds);
1957 memcpy(&tv, &sa->tvTimeout[SA_TIMEOUT_WRITE], sizeof(struct timeval));
1958 do {
1959 rv = SA_SC_CALL_5(sa, select, sa->fdSocket+1, (fd_set *)NULL, &fds, (fd_set *)NULL, &tv);
1960 } while (rv == -1 && errno == EINTR);
1961 if (rv == 0) {
1962 errno = ETIMEDOUT;
1963 return -1;
1964 }
1965 }
1966 #endif
1967
1968 /* perform write operation on underlying socket */
1969 do {
1970 rv = (int)SA_SC_CALL_3(sa, write, sa->fdSocket, cpBuf, (size_t)nBufLen);
1971 } while (rv == -1 && errno == EINTR);
1972
1973 #if defined(SO_RCVTIMEO) && defined(USE_SO_RCVTIMEO) && defined(SO_SNDTIMEO) && defined(USE_SO_SNDTIMEO)
1974 if (rv == -1 && errno == EWOULDBLOCK)
1975 errno = ETIMEDOUT;
1976 #endif
1977
1978 return rv;
1979 }
1980
1981 /* write data to socket */
1982 sa_rc_t sa_write(sa_t *sa, const char *cpBuf, size_t nBufReq, size_t *nBufRes)
1983 {
1984 int n;
1985 int res;
1986 sa_rc_t rv;
1987
1988 /* argument sanity check(s) */
1989 if (sa == NULL || cpBuf == NULL || nBufReq == 0)
1990 return SA_RC(SA_ERR_ARG);
1991
1992 /* writing is only possible for stream communication */
1993 if (sa->eType != SA_TYPE_STREAM)
1994 return SA_RC(SA_ERR_USE);
1995
1996 /* at least a connection has to exist */
1997 if (sa->fdSocket == -1)
1998 return SA_RC(SA_ERR_USE);
1999
2000 rv = SA_OK;
2001 if (sa->nWriteSize == 0) {
2002 /* user-space unbuffered I/O */
2003 res = sa_write_raw(sa, cpBuf, (int)nBufReq);
2004 if (res < 0 && errno == ETIMEDOUT)
2005 rv = SA_ERR_TMT;
2006 else if (res < 0)
2007 rv = SA_ERR_SYS;
2008 }
2009 else {
2010 /* user-space buffered I/O */
2011 if ((int)nBufReq > (sa->nWriteSize - sa->nWriteLen)) {
2012 /* not enough space in buffer, so flush buffer first */
2013 (void)sa_flush(sa);
2014 }
2015 res = 0;
2016 if ((int)nBufReq >= sa->nWriteSize) {
2017 /* buffer too small at all, so write immediately */
2018 while (nBufReq > 0) {
2019 n = sa_write_raw(sa, cpBuf, (int)nBufReq);
2020 if (n < 0 && errno == ETIMEDOUT)
2021 rv = (res == 0 ? SA_ERR_TMT : SA_OK);
2022 else if (n < 0)
2023 rv = (res == 0 ? SA_ERR_SYS : SA_OK);
2024 if (n <= 0)
2025 break;
2026 nBufReq -= n;
2027 cpBuf += n;
2028 res += n;
2029 }
2030 }
2031 else {
2032 /* (again) enough sprace in buffer, so store data */
2033 memmove(sa->cpWriteBuf+sa->nWriteLen, cpBuf, nBufReq);
2034 sa->nWriteLen += nBufReq;
2035 res = (int)nBufReq;
2036 }
2037 }
2038
2039 /* pass number of actually written bytes to caller */
2040 if (nBufRes != NULL)
2041 *nBufRes = (size_t)res;
2042
2043 return SA_RC(rv);
2044 }
2045
2046 /* output callback function context for sa_writef() */
2047 typedef struct {
2048 sa_t *sa;
2049 sa_rc_t rv;
2050 } sa_writef_cb_t;
2051
2052 /* output callback function for sa_writef() */
2053 static int sa_writef_cb(void *_ctx, const char *buffer, size_t bufsize)
2054 {
2055 size_t n;
2056 sa_writef_cb_t *ctx = (sa_writef_cb_t *)_ctx;
2057
2058 if ((ctx->rv = sa_write(ctx->sa, buffer, bufsize, &n)) != SA_OK)
2059 return -1;
2060 return (int)n;
2061 }
2062
2063 /* write formatted string to socket (convenience function) */
2064 sa_rc_t sa_writef(sa_t *sa, const char *cpFmt, ...)
2065 {
2066 va_list ap;
2067 int n;
2068 sa_writef_cb_t ctx;
2069
2070 /* argument sanity check(s) */
2071 if (sa == NULL || cpFmt == NULL)
2072 return SA_RC(SA_ERR_ARG);
2073
2074 /* writing is only possible for stream communication */
2075 if (sa->eType != SA_TYPE_STREAM)
2076 return SA_RC(SA_ERR_USE);
2077
2078 /* at least a connection has to exist */
2079 if (sa->fdSocket == -1)
2080 return SA_RC(SA_ERR_USE);
2081
2082 /* format string into temporary buffer */
2083 va_start(ap, cpFmt);
2084 ctx.sa = sa;
2085 ctx.rv = SA_OK;
2086 n = sa_mvxprintf(sa_writef_cb, &ctx, cpFmt, ap);
2087 if (n == -1 && ctx.rv == SA_OK)
2088 ctx.rv = SA_ERR_FMT;
2089 va_end(ap);
2090
2091 return ctx.rv;
2092 }
2093
2094 /* flush write/outgoing I/O buffer */
2095 sa_rc_t sa_flush(sa_t *sa)
2096 {
2097 int n;
2098 sa_rc_t rv;
2099
2100 /* argument sanity check(s) */
2101 if (sa == NULL)
2102 return SA_RC(SA_ERR_ARG);
2103
2104 /* flushing is only possible for stream communication */
2105 if (sa->eType != SA_TYPE_STREAM)
2106 return SA_RC(SA_ERR_USE);
2107
2108 /* at least a connection has to exist */
2109 if (sa->fdSocket == -1)
2110 return SA_RC(SA_ERR_USE);
2111
2112 /* try to flush buffer */
2113 rv = SA_OK;
2114 if (sa->nWriteSize > 0) {
2115 while (sa->nWriteLen > 0) {
2116 n = sa_write_raw(sa, sa->cpWriteBuf, sa->nWriteLen);
2117 if (n < 0 && errno == ETIMEDOUT)
2118 rv = SA_ERR_TMT;
2119 else if (n < 0)
2120 rv = SA_ERR_SYS;
2121 if (n <= 0)
2122 break;
2123 memmove(sa->cpWriteBuf, sa->cpWriteBuf+n, (size_t)(sa->nWriteLen-n));
2124 sa->nWriteLen -= n;
2125 }
2126 sa->nWriteLen = 0;
2127 }
2128 return SA_RC(rv);
2129 }
2130
2131 /* shutdown a socket connection */
2132 sa_rc_t sa_shutdown(sa_t *sa, const char *flags)
2133 {
2134 int how;
2135
2136 /* argument sanity check(s) */
2137 if (sa == NULL || flags == NULL)
2138 return SA_RC(SA_ERR_ARG);
2139
2140 /* shutdown is only possible for stream communication */
2141 if (sa->eType != SA_TYPE_STREAM)
2142 return SA_RC(SA_ERR_USE);
2143
2144 /* at least a connection has to exist */
2145 if (sa->fdSocket == -1)
2146 return SA_RC(SA_ERR_USE);
2147
2148 /* determine flags for shutdown(2) */
2149 how = 0;
2150 if (strcmp(flags, "r") == 0)
2151 how = SHUT_RD;
2152 else if (strcmp(flags, "w") == 0)
2153 how = SHUT_WR;
2154 else if (strcmp(flags, "rw") == 0 || strcmp(flags, "wr") == 0)
2155 how = SHUT_RDWR;
2156 else
2157 return SA_RC(SA_ERR_ARG);
2158
2159 /* flush write buffers */
2160 if ((how & SHUT_WR) || (how & SHUT_RDWR))
2161 (void)sa_flush(sa);
2162
2163 /* perform shutdown operation on underlying socket */
2164 if (shutdown(sa->fdSocket, how) == -1)
2165 return SA_RC(SA_ERR_SYS);
2166
2167 return SA_OK;
2168 }
2169
2170 /* receive data via socket */
2171 sa_rc_t sa_recv(sa_t *sa, sa_addr_t **raddr, char *buf, size_t buflen, size_t *bufdone)
2172 {
2173 sa_rc_t rv;
2174 union {
2175 struct sockaddr_in sa4;
2176 #ifdef AF_INET6
2177 struct sockaddr_in6 sa6;
2178 #endif
2179 } sa_buf;
2180 socklen_t sa_size;
2181 ssize_t n;
2182 int k;
2183 fd_set fds;
2184 struct timeval tv;
2185
2186 /* argument sanity check(s) */
2187 if (sa == NULL || buf == NULL || buflen == 0 || raddr == NULL)
2188 return SA_RC(SA_ERR_ARG);
2189
2190 /* receiving is only possible for datagram communication */
2191 if (sa->eType != SA_TYPE_DATAGRAM)
2192 return SA_RC(SA_ERR_USE);
2193
2194 /* at least a sa_bind() has to be performed */
2195 if (sa->fdSocket == -1)
2196 return SA_RC(SA_ERR_USE);
2197
2198 /* if timeout is enabled, perform explicit/smart blocking instead
2199 of implicitly/hard blocking in the recvfrom(2) system call */
2200 if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_READ])) {
2201 FD_ZERO(&fds);
2202 FD_SET(sa->fdSocket, &fds);
2203 memcpy(&tv, &sa->tvTimeout[SA_TIMEOUT_READ], sizeof(struct timeval));
2204 do {
2205 k = SA_SC_CALL_5(sa, select, sa->fdSocket+1, &fds, (fd_set *)NULL, (fd_set *)NULL, &tv);
2206 } while (k == -1 && errno == EINTR);
2207 if (k == 0)
2208 errno = ETIMEDOUT;
2209 if (k <= 0)
2210 return SA_RC(SA_ERR_SYS);
2211 }
2212
2213 /* perform receive operation on underlying socket */
2214 sa_size = (socklen_t)sizeof(sa_buf);
2215 if ((n = SA_SC_CALL_6(sa, recvfrom, sa->fdSocket, buf, buflen, 0,
2216 (struct sockaddr *)&sa_buf, &sa_size)) == -1)
2217 return SA_RC(SA_ERR_SYS);
2218
2219 /* create result address object */
2220 if ((rv = sa_addr_create(raddr)) != SA_OK)
2221 return rv;
2222 if ((rv = sa_addr_s2a(*raddr, (struct sockaddr *)&sa_buf, sa_size)) != SA_OK) {
2223 (void)sa_addr_destroy(*raddr);
2224 return rv;
2225 }
2226
2227 /* pass actual number of received bytes to caller */
2228 if (bufdone != NULL)
2229 *bufdone = (size_t)n;
2230
2231 return SA_OK;
2232 }
2233
2234 /* send data via socket */
2235 sa_rc_t sa_send(sa_t *sa, sa_addr_t *raddr, const char *buf, size_t buflen, size_t *bufdone)
2236 {
2237 ssize_t n;
2238 int k;
2239 fd_set fds;
2240 sa_rc_t rv;
2241 struct timeval tv;
2242
2243 /* argument sanity check(s) */
2244 if (sa == NULL || buf == NULL || buflen == 0 || raddr == NULL)
2245 return SA_RC(SA_ERR_ARG);
2246
2247 /* sending is only possible for datagram communication */
2248 if (sa->eType != SA_TYPE_DATAGRAM)
2249 return SA_RC(SA_ERR_USE);
2250
2251 /* lazy creation of underlying socket */
2252 if (sa->fdSocket == -1)
2253 if ((rv = sa_socket_init(sa, raddr->nFamily)) != SA_OK)
2254 return rv;
2255
2256 /* if timeout is enabled, perform explicit/smart blocking instead
2257 of implicitly/hard blocking in the sendto(2) system call */
2258 if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_WRITE])) {
2259 FD_ZERO(&fds);
2260 FD_SET(sa->fdSocket, &fds);
2261 memcpy(&tv, &sa->tvTimeout[SA_TIMEOUT_WRITE], sizeof(struct timeval));
2262 do {
2263 k = SA_SC_CALL_5(sa, select, sa->fdSocket+1, (fd_set *)NULL, &fds, (fd_set *)NULL, &tv);
2264 } while (k == -1 && errno == EINTR);
2265 if (k == 0)
2266 errno = ETIMEDOUT;
2267 if (k <= 0)
2268 return SA_RC(SA_ERR_SYS);
2269 }
2270
2271 /* perform send operation on underlying socket */
2272 if ((n = SA_SC_CALL_6(sa, sendto, sa->fdSocket, buf, buflen, 0, raddr->saBuf, raddr->slBuf)) == -1)
2273 return SA_RC(SA_ERR_SYS);
2274
2275 /* pass actual number of sent bytes to caller */
2276 if (bufdone != NULL)
2277 *bufdone = (size_t)n;
2278
2279 return SA_OK;
2280 }
2281
2282 /* send formatted string to socket (convenience function) */
2283 sa_rc_t sa_sendf(sa_t *sa, sa_addr_t *raddr, const char *cpFmt, ...)
2284 {
2285 va_list ap;
2286 va_list apbak;
2287 int nBuf;
2288 char *cpBuf;
2289 sa_rc_t rv;
2290 char caBuf[1024];
2291
2292 /* argument sanity check(s) */
2293 if (sa == NULL || raddr == NULL || cpFmt == NULL)
2294 return SA_RC(SA_ERR_ARG);
2295
2296 /* format string into temporary buffer */
2297 va_start(ap, cpFmt);
2298 va_copy(apbak, ap);
2299 if ((nBuf = sa_mvsnprintf(NULL, 0, cpFmt, ap)) == -1)
2300 return SA_RC(SA_ERR_FMT);
2301 va_copy(ap, apbak);
2302 if ((nBuf+1) > (int)sizeof(caBuf)) {
2303 /* requires a larger buffer, so allocate dynamically */
2304 if ((cpBuf = (char *)malloc((size_t)(nBuf+1))) == NULL)
2305 return SA_RC(SA_ERR_MEM);
2306 }
2307 else {
2308 /* fits into small buffer, so allocate statically */
2309 cpBuf = caBuf;
2310 }
2311 rv = SA_OK;
2312 if (sa_mvsnprintf(cpBuf, (size_t)(nBuf+1), cpFmt, ap) == -1)
2313 rv = SA_ERR_FMT;
2314 va_end(ap);
2315
2316 /* pass-through to sa_send() */
2317 if (rv == SA_OK)
2318 rv = sa_send(sa, raddr, cpBuf, (size_t)nBuf, NULL);
2319
2320 /* cleanup dynamically allocated buffer */
2321 if ((nBuf+1) > (int)sizeof(caBuf))
2322 free(cpBuf);
2323
2324 return rv;
2325 }
2326
2327 /* return error string */
2328 char *sa_error(sa_rc_t rv)
2329 {
2330 char *sz;
2331
2332 /* translate result value into corresponding string */
2333 if (rv == SA_OK) sz = "Everything Ok";
2334 else if (rv == SA_ERR_ARG) sz = "Invalid Argument";
2335 else if (rv == SA_ERR_USE) sz = "Invalid Use Or Context";
2336 else if (rv == SA_ERR_MEM) sz = "Not Enough Memory";
2337 else if (rv == SA_ERR_MTC) sz = "Matching Failed";
2338 else if (rv == SA_ERR_EOF) sz = "End Of Communication";
2339 else if (rv == SA_ERR_TMT) sz = "Communication Timeout";
2340 else if (rv == SA_ERR_SYS) sz = "Operating System Error";
2341 else if (rv == SA_ERR_NET) sz = "Networking Error";
2342 else if (rv == SA_ERR_FMT) sz = "Formatting Error";
2343 else if (rv == SA_ERR_IMP) sz = "Implementation Not Available";
2344 else if (rv == SA_ERR_INT) sz = "Internal Error";
2345 else sz = "Invalid Result Code";
2346 return sz;
2347 }
2348
2349