00001
00002
00003
00004
00005 #include <stdlib.h>
00006 #include <stdio.h>
00007 #include <errno.h>
00008 #include <unistd.h>
00009 #include <string.h>
00010 #include <strings.h>
00011
00012 #include <toolbox/carpal.h>
00013 #include <toolbox/net.h>
00014 #include <toolbox/misc.h>
00015
00016 #ifndef HAVE_GETADDRINFO
00017
00018
00019 struct u_addrinfo_s
00020 {
00021 int ai_flags;
00022 int ai_family;
00023 int ai_socktype;
00024 int ai_protocol;
00025
00026 char *ai_canonname;
00027 u_socklen_t ai_addrlen;
00028 struct sockaddr *ai_addr;
00029 struct u_addrinfo_s *ai_next;
00030 };
00031 #endif
00032
00033
00034 struct u_net_addr_s
00035 {
00036 int opts;
00037 u_net_mode_t mode;
00038 u_addrinfo_t *addr;
00039 u_addrinfo_t *cur;
00040 };
00041
00042
00043 static int na_new (u_net_mode_t mode, u_net_addr_t **pa);
00044 static void ai_free (u_addrinfo_t *ai);
00045 #ifndef NO_SCTP
00046 static int sctp_enable_events (int s, int opts);
00047 #endif
00048 static int bind_reuse_addr (int s);
00049
00050
00051 static int do_resolv (
00052 int rf (const char *, const char *, const char *, u_addrinfo_t *ai),
00053 const char *host, const char *port, const char *path, int family,
00054 int type, int proto, u_addrinfo_t **pai);
00055 #ifndef NO_UNIXSOCK
00056
00057 static int resolv_sun (const char *dummy1, const char *dummy2, const char *path,
00058 u_addrinfo_t *ai);
00059 #endif
00060 static int ai_resolv (const char *host, const char *port, const char *path,
00061 int family, int type, int proto, int passive, u_addrinfo_t **pai);
00062
00063 #ifndef HAVE_GETADDRINFO
00064 static int resolv_sin (const char *host, const char *port, const char *dummy,
00065 u_addrinfo_t *ai);
00066 #ifndef NO_IPV6
00067 static int resolv_sin6 (const char *host, const char *port, const char *dummy,
00068 u_addrinfo_t *ai);
00069 #endif
00070 static int resolv_port (const char *s_port, uint16_t *pin_port);
00071 #endif
00072
00073
00074 static int do_sock (
00075 int f(struct sockaddr *, u_socklen_t, int, int, int, int, int,
00076 struct timeval *),
00077 struct u_net_addr_s *a, int backlog, u_addrinfo_t **pai,
00078 struct timeval *timeout);
00079 static int do_csock (struct sockaddr *sad, u_socklen_t sad_len, int domain,
00080 int type, int protocol, int opts, int dummy,
00081 struct timeval *timeout);
00082 static int do_ssock (struct sockaddr *sad, u_socklen_t sad_len, int domain,
00083 int type, int protocol, int opts, int backlog,
00084 struct timeval *dummy);
00085
00086
00087 struct u_net_scheme_map_s
00088 {
00089 int addr_family;
00090 int sock_type;
00091 int proto;
00092 };
00093 typedef struct u_net_scheme_map_s u_net_scheme_map_t;
00094
00095 static int scheme_mapper (const char *scheme, u_net_scheme_map_t *map);
00096 static int uri2addr (u_uri_t *u, u_net_scheme_map_t *m, u_net_addr_t *a);
00097 static inline int update_timeout (struct timeval *timeout,
00098 struct timeval *tstart);
00099
00228 int u_net_uri2addr (const char *uri, u_net_mode_t mode, u_net_addr_t **pa)
00229 {
00230 const char *s;
00231 u_uri_t *u = NULL;
00232 u_net_scheme_map_t smap;
00233 u_net_addr_t *a = NULL;
00234
00235 dbg_return_if (uri == NULL, ~0);
00236 dbg_return_if (pa == NULL, ~0);
00237
00238
00239
00240 dbg_err_if (u_uri_crumble(uri, U_URI_OPT_NONE, &u));
00241 dbg_err_if ((s = u_uri_get_scheme(u)) == NULL);
00242 dbg_err_ifm (scheme_mapper(s, &smap), "unsupported URI scheme: %s", s);
00243
00244
00245 dbg_err_sif (na_new(mode, &a));
00246
00247
00248 dbg_err_if (uri2addr(u, &smap, a));
00249
00250 u_uri_free(u);
00251
00252 *pa = a;
00253
00254 return 0;
00255 err:
00256 if (u)
00257 u_uri_free(u);
00258 if (a)
00259 u_net_addr_free(a);
00260 return ~0;
00261 }
00262
00278 int u_net_sd_by_addr_ex (u_net_addr_t *a, struct timeval *timeout)
00279 {
00280 dbg_return_if (a == NULL, ~1);
00281
00282 switch (a->mode)
00283 {
00284 case U_NET_SSOCK:
00285 return do_sock(do_ssock, a, U_NET_BACKLOG, &a->cur, timeout);
00286 case U_NET_CSOCK:
00287 return do_sock(do_csock, a, 0, &a->cur, timeout);
00288 default:
00289 dbg_return_ifm (1, -1, "unknown socket mode %d", a->mode);
00290 }
00291 }
00292
00296 int u_net_sd_by_addr (u_net_addr_t *a)
00297 {
00298 return u_net_sd_by_addr_ex(a, NULL);
00299 }
00300
00312 int u_net_sd_ex (const char *uri, u_net_mode_t mode, int opts,
00313 struct timeval *timeout)
00314 {
00315 int s = -1;
00316 u_net_addr_t *a = NULL;
00317
00318
00319 dbg_return_if (uri == NULL, -1);
00320
00321
00322
00323 dbg_err_if (u_net_uri2addr(uri, mode, &a));
00324
00325
00326 u_net_addr_set_opts(a, opts);
00327
00328
00329 s = u_net_sd_by_addr_ex(a, timeout);
00330
00331
00332 u_net_addr_free(a);
00333
00334 return s;
00335 err:
00336 if (s != -1)
00337 (void) close(s);
00338 if (a)
00339 u_net_addr_free(a);
00340
00341 return -1;
00342 }
00343
00347 int u_net_sd (const char *uri, u_net_mode_t mode, int opts)
00348 {
00349 return u_net_sd_ex(uri, mode, opts, NULL);
00350 }
00351
00361 int u_net_addr_can_accept (u_net_addr_t *a)
00362 {
00363 dbg_return_if (a == NULL, 0);
00364 dbg_return_if (a->cur == NULL, 0);
00365
00366 switch (a->cur->ai_socktype)
00367 {
00368 case SOCK_STREAM:
00369 case SOCK_SEQPACKET:
00370 return (a->mode == U_NET_SSOCK) ? 1 : 0;
00371 default:
00372 return 0;
00373 }
00374 }
00375
00388 void u_net_addr_set_opts (u_net_addr_t *a, int opts)
00389 {
00390 dbg_return_if (a == NULL, );
00391 a->opts = opts;
00392 return;
00393 }
00394
00408 void u_net_addr_add_opts (u_net_addr_t *a, int opts)
00409 {
00410 dbg_return_if (a == NULL, );
00411 a->opts |= opts;
00412 return;
00413 }
00414
00425 void u_net_addr_free (u_net_addr_t *a)
00426 {
00427 dbg_return_if (a == NULL, );
00428
00429
00430 ai_free(a->addr);
00431
00432
00433 u_free(a);
00434 return;
00435 }
00436
00438 int u_accept (int sd, struct sockaddr *addr, u_socklen_t *addrlen)
00439 {
00440 int ad;
00441
00442 again:
00443 if ((ad = accept(sd, addr, addrlen)) == -1 && (errno == EINTR))
00444 goto again;
00445
00446 #ifdef U_NET_TRACE
00447 u_dbg("accept(%d, %p, %d) = %d", sd, addr, addrlen, ad);
00448 #endif
00449
00450
00451 dbg_err_sif (ad == -1);
00452 err:
00453 return ad;
00454 }
00455
00457 int u_socket (int domain, int type, int protocol)
00458 {
00459 int s = socket(domain, type, protocol);
00460
00461 #ifdef U_NET_TRACE
00462 u_dbg("socket(%d, %d, %d) = %d", domain, type, protocol, s);
00463 #endif
00464
00465
00466 dbg_err_sif (s == -1);
00467 err:
00468 return s;
00469 }
00470
00472 int u_connect (int sd, const struct sockaddr *addr, u_socklen_t addrlen)
00473 {
00474 return u_connect_ex(sd, addr, addrlen, NULL);
00475 }
00476
00496 int u_connect_ex (int sd, const struct sockaddr *addr, u_socklen_t addrlen,
00497 struct timeval *timeout)
00498 {
00499 int rc;
00500 u_socklen_t rc_len = sizeof rc;
00501 struct timeval tstart, tcopy, *ptcopy = timeout ? &tcopy : NULL;
00502 fd_set writefds;
00503
00504 dbg_return_if (sd < 0, -1);
00505 dbg_return_if (addr == NULL, -1);
00506 dbg_return_if (addrlen == 0, -1);
00507
00508 if (timeout)
00509 {
00510 dbg_err_if (u_net_set_nonblocking(sd));
00511 dbg_err_sif (gettimeofday(&tstart, NULL) == -1);
00512 }
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 nop_return_if ((rc = connect(sd, addr, addrlen)) == 0, 0);
00524 dbg_err_sif (errno != EINTR && errno != EINPROGRESS);
00525
00526
00527
00528
00529 FD_ZERO(&writefds);
00530 FD_SET(sd, &writefds);
00531
00532 for (;;)
00533 {
00534
00535
00536
00537
00538
00539 if (timeout)
00540 tcopy = *timeout;
00541
00542
00543
00544 if ((rc = select(sd + 1, NULL, &writefds, NULL, ptcopy)) > 0)
00545 break;
00546
00547
00548 if (rc == 0)
00549 {
00550 errno = ETIMEDOUT;
00551 dbg_err("connection timeouted on socket %d", sd);
00552 }
00553
00554
00555
00556 dbg_err_sif (rc == -1 && errno != EINTR);
00557
00558
00559 if (timeout)
00560 {
00561 dbg_err_if (update_timeout(timeout, &tstart));
00562
00563
00564 if (timeout->tv_sec < 0)
00565 {
00566 errno = ETIMEDOUT;
00567 dbg_err("negative timeout on socket %d.", sd);
00568 }
00569 }
00570 }
00571
00572
00573
00574 dbg_err_sif (u_getsockopt(sd, SOL_SOCKET, SO_ERROR, &rc, &rc_len) == -1);
00575 if (rc)
00576 {
00577 errno = rc;
00578 warn_err("error detected on socket %d: %s", sd, strerror(errno));
00579 }
00580
00581 if (timeout)
00582 (void) u_net_unset_nonblocking(sd);
00583
00584 return 0;
00585 err:
00586 if (timeout)
00587 (void) u_net_unset_nonblocking(sd);
00588
00589 return (errno == ETIMEDOUT) ? -2 : -1;
00590 }
00591
00593 int u_bind (int sd, const struct sockaddr *addr, u_socklen_t addrlen)
00594 {
00595 int rc = bind(sd, addr, addrlen);
00596
00597 #ifdef U_NET_TRACE
00598 u_dbg("bind(%d, %p, %d) = %d", sd, addr, addrlen, rc);
00599 #endif
00600
00601
00602 dbg_err_sif (rc == -1);
00603 err:
00604 return rc;
00605 }
00606
00608 int u_listen (int sd, int backlog)
00609 {
00610 int rc = listen(sd, backlog);
00611
00612 #ifdef U_NET_TRACE
00613 u_dbg("listen(%d, %d) = %d", sd, backlog, rc);
00614 #endif
00615
00616
00617 dbg_err_sif (rc == -1);
00618 err:
00619 return rc;
00620 }
00621
00623 int u_setsockopt (int sd, int lev, int name, const void *val, u_socklen_t len)
00624 {
00625 #ifdef HAVE_SETSOCKOPT
00626 int rc = setsockopt(sd, lev, name, val, len);
00627
00628 #ifdef U_NET_TRACE
00629 u_dbg("setsockopt(%d, %d, %d, %p, %d) = %d", sd, lev, name, val, len, rc);
00630 #endif
00631
00632 dbg_err_sif (rc == -1);
00633 err:
00634 return rc;
00635 #else
00636 u_unused_args(sd, lev, name, val, len);
00637 u_info("setsockopt not implemented on this platform");
00638 return -1;
00639 #endif
00640 }
00641
00643 int u_getsockopt (int sd, int lev, int name, void *val, u_socklen_t *len)
00644 {
00645 #ifdef HAVE_GETSOCKOPT
00646 int rc = getsockopt(sd, lev, name, val, len);
00647
00648 #ifdef U_NET_TRACE
00649 u_dbg("getsockopt(%d, %d, %d, %p, %p) = %d", sd, lev, name, val, len, rc);
00650 #endif
00651
00652 dbg_err_sif (rc == -1);
00653 err:
00654 return rc;
00655 #else
00656 u_unused_args(sd, lev, name, val, len);
00657 u_info("getsockopt not implemented on this platform");
00658 return -1;
00659 #endif
00660 }
00661
00670 int u_net_set_nonblocking (int s)
00671 {
00672 #ifdef HAVE_FCNTL
00673 int flags;
00674
00675 dbg_err_sif ((flags = fcntl(s, F_GETFL, 0)) == -1);
00676 flags |= O_NONBLOCK;
00677 dbg_err_sif (fcntl(s, F_SETFL, flags) == -1);
00678 #else
00679 warn_err("missing fcntl(2): can't set socket %d as non blocking", s);
00680 #endif
00681
00682 return 0;
00683 err:
00684 return ~0;
00685 }
00686 int u_net_unset_nonblocking (int s)
00695 {
00696 #ifdef HAVE_FCNTL
00697 int flags;
00698
00699 dbg_err_sif ((flags = fcntl(s, F_GETFL, 0)) == -1);
00700 flags &= ~O_NONBLOCK;
00701 dbg_err_sif (fcntl(s, F_SETFL, flags) == -1);
00702 #else
00703 warn_err("missing fcntl(2): can't reset non-blocking bit on socket %d", s);
00704 #endif
00705
00706 return 0;
00707 err:
00708 return ~0;
00709 }
00710
00719 int u_net_nagle_off (int s)
00720 {
00721 #if defined(HAVE_TCP_NODELAY) && !defined(__minix)
00722 int y = 1;
00723
00724 dbg_return_if (s < 0, ~0);
00725
00726 dbg_err_if (u_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &y, sizeof y) == -1);
00727
00728 return 0;
00729 err:
00730 return ~0;
00731 #else
00732 u_unused_args(s);
00733 u_dbg("TCP_NODELAY not supported on this platform");
00734 return 0;
00735 #endif
00736 }
00737
00739 const char *u_inet_ntop (int af, const void *src, char *dst, u_socklen_t len)
00740 {
00741 const unsigned char *p = (const unsigned char *) src;
00742
00743 if (af == AF_INET)
00744 {
00745 char s[U_INET_ADDRSTRLEN];
00746
00747 dbg_if (u_snprintf(s, sizeof s, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]));
00748
00749 if (u_strlcpy(dst, s, len))
00750 {
00751 errno = ENOSPC;
00752 return NULL;
00753 }
00754
00755 return dst;
00756 }
00757 #ifndef NO_IPV6
00758 if (af == AF_INET6)
00759 return inet_ntop(af, src, dst, len);
00760 #endif
00761
00762 errno = EAFNOSUPPORT;
00763 return NULL;
00764 }
00765
00767 const char *u_sa_ntop (const struct sockaddr *sa, char *d, size_t dlen)
00768 {
00769 char a[256];
00770
00771 dbg_err_if (sa == NULL);
00772 dbg_err_if (d == NULL);
00773 dbg_err_if (dlen == 0);
00774
00775 switch (sa->sa_family)
00776 {
00777 case AF_INET:
00778 {
00779 const struct sockaddr_in *s4 = (const struct sockaddr_in *) sa;
00780 dbg_err_if (!u_inet_ntop(AF_INET, &s4->sin_addr, a, sizeof a));
00781 dbg_if (u_snprintf(d, dlen, "%s:%d", a, ntohs(s4->sin_port)));
00782 break;
00783 }
00784 #ifndef NO_IPV6
00785 case AF_INET6:
00786 {
00787 const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) sa;
00788 dbg_err_if (!u_inet_ntop(AF_INET6, &s6->sin6_addr, a, sizeof a));
00789 dbg_if (u_snprintf(d, dlen, "[%s]:%d", a, ntohs(s6->sin6_port)));
00790 break;
00791 }
00792 #endif
00793 #ifndef NO_UNIXSOCK
00794 case AF_UNIX:
00795 {
00796 const struct sockaddr_un *su = (const struct sockaddr_un *) sa;
00797 dbg_if (u_strlcpy(d, su->sun_path, dlen));
00798 break;
00799 }
00800 #endif
00801 default:
00802 dbg_err("unhandled socket type");
00803 }
00804
00805 return d;
00806 err:
00807 return "(sockaddr conversion failed)";
00808 }
00809
00814
00815
00816 static int do_sock (
00817 int wf (struct sockaddr *, u_socklen_t, int, int, int, int, int,
00818 struct timeval *),
00819 struct u_net_addr_s *a, int backlog, u_addrinfo_t **pai,
00820 struct timeval *timeout)
00821 {
00822 int sock_type, sd = -1;
00823 u_addrinfo_t *ap;
00824 char h[1024];
00825
00826 dbg_return_if ((ap = a->addr) == NULL, ~0);
00827
00828 for ( ; ap != NULL; ap = ap->ai_next)
00829 {
00830 #ifndef NO_SCTP
00831
00832
00833
00834 sock_type = (ap->ai_protocol == IPPROTO_SCTP &&
00835 (a->opts & U_NET_OPT_SCTP_ONE_TO_MANY)) ?
00836 SOCK_SEQPACKET : ap->ai_socktype;
00837 #else
00838 sock_type = ap->ai_socktype;
00839 #endif
00840
00841 if ((sd = wf(ap->ai_addr, ap->ai_addrlen, ap->ai_family, sock_type,
00842 ap->ai_protocol, a->opts, backlog, timeout)) >= 0)
00843 {
00844
00845
00846
00847 u_info("%s %s", (wf == do_ssock) ? "bind succeeded for"
00848 : "connect succeeded to", (ap->ai_family == AF_UNIX)
00849 ? ap->ai_canonname : u_sa_ntop(ap->ai_addr, h, sizeof h));
00850
00851
00852
00853 if (pai)
00854 *pai = ap;
00855
00856 break;
00857 }
00858 }
00859
00860 if (sd == -1)
00861 {
00862 u_addrinfo_t *wai = a->addr;
00863
00864 u_info("could not %s %s", (wf == do_ssock) ? "bind" : "connect to",
00865 (wai->ai_family == AF_UNIX) ? wai->ai_canonname
00866 : u_sa_ntop(wai->ai_addr, h, sizeof h));
00867 }
00868
00869 return sd;
00870 }
00871
00872 static int do_csock (struct sockaddr *sad, u_socklen_t sad_len, int domain,
00873 int type, int protocol, int opts, int dummy, struct timeval *timeout)
00874 {
00875 int s = -1;
00876 #ifdef HAVE_SO_BROADCAST
00877 int bc = 1;
00878 #endif
00879
00880 u_unused_args(dummy);
00881
00882 dbg_return_if (sad == NULL, -1);
00883
00884 dbg_err_sif ((s = u_socket(domain, type, protocol)) == -1);
00885
00886 if ((type == SOCK_DGRAM) && (opts & U_NET_OPT_DGRAM_BROADCAST))
00887 {
00888 #ifdef HAVE_SO_BROADCAST
00889 dbg_err_sif (u_setsockopt(s, SOL_SOCKET, SO_BROADCAST,
00890 &bc, sizeof bc) == -1);
00891 #else
00892 u_warn("SO_BROADCAST is not defined on this platform");
00893 #endif
00894 }
00895
00896 #ifndef NO_SCTP
00897 if (opts & U_NET_OPT_SCTP_ONE_TO_MANY)
00898 dbg_err_sif (sctp_enable_events(s, opts));
00899 #endif
00900
00901
00902
00903
00904
00905 if (!(opts & U_NET_OPT_DONT_CONNECT))
00906 dbg_err_sif (u_connect_ex(s, sad, sad_len, timeout) < 0);
00907
00908 return s;
00909 err:
00910 U_CLOSE(s);
00911 return -1;
00912 }
00913
00914 static int do_ssock (struct sockaddr *sad, u_socklen_t sad_len, int domain,
00915 int type, int protocol, int opts, int backlog, struct timeval *dummy)
00916 {
00917 int s = -1;
00918
00919 dbg_return_if (sad == NULL, -1);
00920 u_unused_args(dummy);
00921
00922 dbg_err_sif ((s = u_socket(domain, type, protocol)) == -1);
00923
00924
00925
00926
00927
00928 if (domain != AF_UNIX && !(opts & U_NET_OPT_DONT_REUSE_ADDR))
00929 dbg_err_if (bind_reuse_addr(s));
00930
00931 #ifndef NO_SCTP
00932 if (opts & U_NET_OPT_SCTP_ONE_TO_MANY)
00933 dbg_err_sif (sctp_enable_events(s, opts));
00934 #endif
00935
00936 dbg_err_sif (u_bind(s, (struct sockaddr *) sad, sad_len) == -1);
00937
00938
00939 if (type == SOCK_STREAM || type == SOCK_SEQPACKET)
00940 dbg_err_sif (u_listen(s, backlog) == -1);
00941
00942 return s;
00943 err:
00944 U_CLOSE(s);
00945 return -1;
00946 }
00947
00948
00949
00950 static int bind_reuse_addr (int s)
00951 {
00952 int y = 1;
00953
00954 dbg_return_if (s < 0, -1);
00955
00956 dbg_err_if (u_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &y, sizeof y) == -1);
00957
00958 return 0;
00959 err:
00960 return ~0;
00961 }
00962
00963 #ifndef NO_SCTP
00964
00965 static int sctp_enable_events (int s, int o)
00966 {
00967 struct sctp_event_subscribe e;
00968
00969 e.sctp_data_io_event =
00970 (o & U_NET_OPT_SCTP_DATA_IO_EVENT) ? 1 : 0;
00971
00972 e.sctp_association_event =
00973 (o & U_NET_OPT_SCTP_ASSOCIATION_EVENT) ? 1 : 0;
00974
00975 e.sctp_address_event =
00976 (o & U_NET_OPT_SCTP_ADDRESS_EVENT) ? 1 : 0;
00977
00978 e.sctp_send_failure_event =
00979 (o & U_NET_OPT_SCTP_SEND_FAILURE_EVENT) ? 1 : 0;
00980
00981 e.sctp_peer_error_event =
00982 (o & U_NET_OPT_SCTP_PEER_ERROR_EVENT) ? 1 : 0;
00983
00984 e.sctp_shutdown_event =
00985 (o & U_NET_OPT_SCTP_SHUTDOWN_EVENT) ? 1 : 0;
00986
00987 e.sctp_partial_delivery_event =
00988 (o & U_NET_OPT_SCTP_PARTIAL_DELIVERY_EVENT) ? 1 : 0;
00989
00990 e.sctp_adaptation_layer_event =
00991 (o & U_NET_OPT_SCTP_ADAPTATION_LAYER_EVENT) ? 1 : 0;
00992
00993 e.sctp_authentication_event =
00994 (o & U_NET_OPT_SCTP_AUTHENTICATION_EVENT) ? 1 : 0;
00995
00996 dbg_err_if (u_setsockopt(s, IPPROTO_SCTP, SCTP_EVENTS, &e, sizeof e) == -1);
00997
00998 return 0;
00999 err:
01000 return ~0;
01001 }
01002 #endif
01003
01004 static int scheme_mapper (const char *scheme, u_net_scheme_map_t *map)
01005 {
01006 dbg_return_if (scheme == NULL, ~0);
01007 dbg_return_if (map == NULL, ~0);
01008
01009 if (!strcasecmp(scheme, "tcp4") || !strcasecmp(scheme, "tcp"))
01010 {
01011 map->addr_family = AF_INET;
01012 map->sock_type = SOCK_STREAM;
01013 map->proto = IPPROTO_TCP;
01014 }
01015 else if (!strcasecmp(scheme, "udp4") || !strcasecmp(scheme, "udp"))
01016 {
01017 map->addr_family = AF_INET;
01018 map->sock_type = SOCK_DGRAM;
01019 map->proto = IPPROTO_UDP;
01020 }
01021 #ifndef NO_SCTP
01022 else if (!strcasecmp(scheme, "sctp4") || !strcasecmp(scheme, "sctp"))
01023 {
01024 map->addr_family = AF_INET;
01025
01026
01027 map->sock_type = SOCK_STREAM;
01028 map->proto = IPPROTO_SCTP;
01029 }
01030 #endif
01031 #ifndef NO_UNIXSOCK
01032 else if (!strcasecmp(scheme, "unix"))
01033 {
01034 map->addr_family = AF_UNIX;
01035 map->sock_type = SOCK_STREAM;
01036 map->proto = 0;
01037 }
01038 #endif
01039 #ifndef NO_IPV6
01040 else if (!strcasecmp(scheme, "tcp6"))
01041 {
01042 map->addr_family = AF_INET6;
01043 map->sock_type = SOCK_STREAM;
01044 map->proto = IPPROTO_TCP;
01045 }
01046 else if (!strcasecmp(scheme, "udp6"))
01047 {
01048 map->addr_family = AF_INET6;
01049 map->sock_type = SOCK_DGRAM;
01050 map->proto = IPPROTO_UDP;
01051 }
01052 #ifndef NO_SCTP
01053 else if (!strcasecmp(scheme, "sctp6"))
01054 {
01055 map->addr_family = AF_INET6;
01056
01057
01058 map->sock_type = SOCK_STREAM;
01059 map->proto = IPPROTO_SCTP;
01060 }
01061 #endif
01062 #endif
01063 else
01064 return ~0;
01065
01066 return 0;
01067 }
01068
01069
01070
01071 static int na_new (u_net_mode_t mode, u_net_addr_t **pa)
01072 {
01073 u_net_addr_t *a = NULL;
01074
01075 dbg_return_if (pa == NULL, ~0);
01076 dbg_return_if (!U_NET_IS_MODE(mode), ~0);
01077
01078 dbg_err_sif ((a = u_zalloc(sizeof(u_net_addr_t))) == NULL);
01079
01080 a->mode = mode;
01081 a->opts = 0;
01082 a->addr = NULL;
01083 a->cur = NULL;
01084
01085 *pa = a;
01086
01087 return 0;
01088 err:
01089 if (a)
01090 u_net_addr_free(a);
01091 return ~0;
01092 }
01093
01094
01095 static int uri2addr (u_uri_t *u, u_net_scheme_map_t *m, u_net_addr_t *a)
01096 {
01097 dbg_return_if (u == NULL, ~0);
01098 dbg_return_if (m == NULL, ~0);
01099 dbg_return_if (a == NULL, ~0);
01100
01101 return ai_resolv(u_uri_get_host(u), u_uri_get_port(u), u_uri_get_path(u),
01102 m->addr_family, m->sock_type, m->proto,
01103 (a->mode == U_NET_SSOCK) ? 1 : 0, &a->addr);
01104 }
01105
01106
01107 static int do_resolv (
01108 int rf (const char *, const char *, const char *, u_addrinfo_t *ai),
01109 const char *host, const char *port, const char *path, int family,
01110 int type, int proto, u_addrinfo_t **pai)
01111 {
01112 u_addrinfo_t *ai = NULL;
01113
01114
01115 dbg_return_if (rf == NULL, ~0);
01116 dbg_return_if (pai == NULL, ~0);
01117
01118 dbg_err_sif ((ai = u_zalloc(sizeof *ai)) == NULL);
01119
01120
01121 ai->ai_flags = 0;
01122 ai->ai_family = family;
01123 ai->ai_socktype = type;
01124 ai->ai_protocol = proto;
01125
01126
01127 dbg_err_if (rf(host, port, path, ai));
01128
01129 *pai = ai;
01130
01131 return 0;
01132 err:
01133 if (ai)
01134 ai_free(ai);
01135 return ~0;
01136 }
01137
01138 #ifndef NO_UNIXSOCK
01139 static int resolv_sun (const char *dummy1, const char *dummy2,
01140 const char *path, u_addrinfo_t *ai)
01141 {
01142 char *cname = NULL;
01143
01144
01145
01146 struct sockaddr_un *sunix = NULL;
01147
01148 u_unused_args(dummy1, dummy2);
01149
01150 dbg_return_if (path == NULL, ~0);
01151 dbg_return_if (ai == NULL, ~0);
01152
01153 dbg_err_sif ((sunix = u_zalloc(sizeof *sunix)) == NULL);
01154
01155 sunix->sun_family = AF_UNIX;
01156 dbg_err_ifm (u_strlcpy(sunix->sun_path, path, sizeof sunix->sun_path),
01157 "%s too long", path);
01158
01159 ai->ai_protocol = 0;
01160 ai->ai_addr = (struct sockaddr *) sunix;
01161 ai->ai_addrlen = sizeof *sunix;
01162 ai->ai_next = NULL;
01163
01164
01165 dbg_err_sif ((cname = u_strdup(path)) == NULL);
01166 ai->ai_canonname = cname;
01167
01168 return 0;
01169 err:
01170 U_FREE(sunix);
01171 U_FREE(cname);
01172 return ~0;
01173 }
01174 #endif
01175
01176 static void ai_free (u_addrinfo_t *ai)
01177 {
01178 nop_return_if (ai == NULL, );
01179
01180 #ifdef HAVE_GETADDRINFO
01181 if (ai->ai_family == AF_UNIX)
01182 {
01183 #endif
01184
01185
01186 U_FREE(ai->ai_addr);
01187 U_FREE(ai->ai_canonname);
01188 u_free(ai);
01189 #ifdef HAVE_GETADDRINFO
01190 }
01191 else
01192 freeaddrinfo(ai);
01193 #endif
01194
01195 return;
01196 }
01197
01198 #ifdef HAVE_GETADDRINFO
01199 static int ai_resolv (const char *host, const char *port, const char *path,
01200 int family, int type, int proto, int passive, u_addrinfo_t **pai)
01201 {
01202 int e;
01203 const char *hostname, *servname;
01204 struct addrinfo hints, *ai = NULL;
01205
01206
01207 dbg_return_if (pai == NULL, ~0);
01208
01209
01210
01211 if (family == AF_UNIX)
01212 {
01213 return do_resolv(resolv_sun, NULL, NULL, path, family, type,
01214 proto, pai);
01215 }
01216
01217 dbg_return_if (host == NULL, ~0);
01218 dbg_return_if (port == NULL, ~0);
01219
01220
01221
01222
01223 hostname = !strcmp(host, "*") ? NULL : host;
01224 servname = !strcmp(port, "*") ? NULL : port;
01225
01226 memset(&hints, 0, sizeof hints);
01227
01228 hints.ai_flags = passive ? AI_PASSIVE : 0;
01229 hints.ai_flags |= hostname ? AI_CANONNAME : 0;
01230
01231 hints.ai_family = family;
01232 hints.ai_socktype = type;
01233 hints.ai_protocol = proto;
01234
01235 switch ((e = getaddrinfo(hostname, servname, &hints, &ai)))
01236 {
01237 case 0:
01238 break;
01239 case EAI_SYSTEM:
01240 dbg_err_sifm (1, "getaddrinfo failed");
01241 default:
01242 dbg_err_ifm (1, "getaddrinfo failed: %s", gai_strerror(e));
01243 }
01244
01245 *pai = ai;
01246
01247 return 0;
01248 err:
01249 if (ai)
01250 ai_free(ai);
01251 return ~0;
01252 }
01253
01254 #else
01255
01256 static int ai_resolv (const char *host, const char *port, const char *path,
01257 int family, int type, int proto, int passive, u_addrinfo_t **pai)
01258 {
01259 u_unused_args(passive);
01260
01261
01262 switch (family)
01263 {
01264 case AF_INET:
01265 return do_resolv(resolv_sin, host, port, NULL, family, type,
01266 proto, pai);
01267 #ifndef NO_UNIXSOCK
01268 case AF_UNIX:
01269 return do_resolv(resolv_sun, NULL, NULL, path, family, type,
01270 proto, pai);
01271 #endif
01272 #ifndef NO_IPV6
01273 case AF_INET6:
01274 return do_resolv(resolv_sin6, host, port, NULL, family, type,
01275 proto, pai);
01276 #endif
01277 default:
01278 dbg_return_ifm (1, ~0, "address family not supported");
01279 }
01280 }
01281
01282 static int resolv_sin (const char *host, const char *port,
01283 const char *dummy, u_addrinfo_t *ai)
01284 {
01285 in_addr_t saddr;
01286 char *cname = NULL;
01287 struct hostent *hp = NULL;
01288 struct sockaddr_in *sin = NULL;
01289
01290 u_unused_args(dummy);
01291
01292 dbg_return_if (ai == NULL, ~0);
01293 dbg_return_if (host == NULL, ~0);
01294 dbg_return_if (port == NULL, ~0);
01295
01296 dbg_err_sif ((sin = u_zalloc(sizeof *sin)) == NULL);
01297
01298 sin->sin_family = AF_INET;
01299 dbg_err_if (resolv_port(port, &sin->sin_port));
01300
01301
01302 if (!strcmp(host, "*"))
01303 sin->sin_addr.s_addr = htonl(INADDR_ANY);
01304 else
01305 {
01306 if (strspn(host, "0123456789.") != strlen(host))
01307 {
01308 dbg_err_ifm ((hp = gethostbyname(host)) == NULL,
01309 "%s: %d", host, h_errno);
01310 dbg_err_if (hp->h_addrtype != AF_INET);
01311 memcpy(&sin->sin_addr.s_addr, hp->h_addr, sizeof(in_addr_t));
01312 }
01313 else if ((saddr = inet_addr(host)) != INADDR_NONE)
01314 sin->sin_addr.s_addr = saddr;
01315 else
01316 dbg_err("invalid host name: \'%s\'", host);
01317 }
01318
01319 ai->ai_addr = (struct sockaddr *) sin;
01320 ai->ai_addrlen = sizeof *sin;
01321 ai->ai_next = NULL;
01322
01323
01324 dbg_err_sif ((cname = u_strdup(host)) == NULL);
01325 ai->ai_canonname = cname;
01326
01327 return 0;
01328 err:
01329 U_FREE(sin);
01330 U_FREE(cname);
01331 return ~0;
01332 }
01333
01334 #ifndef NO_IPV6
01335 static int resolv_sin6 (const char *host, const char *port,
01336 const char *dummy, u_addrinfo_t *ai)
01337 {
01338 char *cname = NULL;
01339 struct hostent *hp = NULL;
01340 struct sockaddr_in6 *sin6 = NULL;
01341
01342 u_unused_args(dummy);
01343
01344 dbg_return_if (ai == NULL, ~0);
01345 dbg_return_if (host == NULL, ~0);
01346 dbg_return_if (port == NULL, ~0);
01347
01348 dbg_err_sif ((sin6 = u_zalloc(sizeof *sin6)) == NULL);
01349
01350 #ifdef SIN6_LEN
01351
01352
01353 sin6->sin6_len = sizeof *sin6;
01354 #endif
01355 sin6->sin6_family = AF_INET6;
01356 dbg_err_if (resolv_port(port, &sin6->sin6_port));
01357 sin6->sin6_flowinfo = 0;
01358
01359
01360 if (!strcmp(host, "*"))
01361 sin6->sin6_addr = in6addr_any;
01362 else
01363 {
01364
01365 if (!strchr(host, ':'))
01366 {
01367
01368
01369
01370 dbg_err_ifm ((hp = gethostbyname2(host, AF_INET6)) == NULL,
01371 "%s: %d", host, h_errno);
01372 dbg_err_if (hp->h_addrtype != AF_INET6);
01373 dbg_err_if (hp->h_length != sizeof(struct in6_addr));
01374 memcpy(&sin6->sin6_addr, hp->h_addr, hp->h_length);
01375 }
01376 else
01377 {
01378 switch (inet_pton(AF_INET6, host, &sin6->sin6_addr))
01379 {
01380 case -1:
01381 dbg_strerror(errno);
01382
01383 case 0:
01384 dbg_err("invalid IPv6 host name: \'%s\'", host);
01385
01386 default:
01387 break;
01388 }
01389 }
01390 }
01391
01392 ai->ai_addr = (struct sockaddr *) sin6;
01393 ai->ai_addrlen = sizeof *sin6;
01394 ai->ai_next = NULL;
01395
01396
01397 dbg_err_sif ((cname = u_strdup(host)) == NULL);
01398 ai->ai_canonname = cname;
01399
01400 return 0;
01401 err:
01402 U_FREE(sin6);
01403 U_FREE(cname);
01404 return ~0;
01405 }
01406 #endif
01407
01408
01409
01410 static int resolv_port (const char *s_port, uint16_t *pin_port)
01411 {
01412 int i_port;
01413 struct servent *se;
01414
01415 dbg_return_if (s_port == NULL, ~0);
01416 dbg_return_if (pin_port == NULL, ~0);
01417
01418
01419 if (!strcmp(s_port, "*"))
01420 {
01421 *pin_port = (uint16_t) 0;
01422 }
01423 else if (strspn(s_port, "0123456789") == strlen(s_port))
01424 {
01425 dbg_err_if (u_atoi(s_port, &i_port));
01426 dbg_err_ifm (i_port < 0 || i_port > 65535, "%s out of range", s_port);
01427 *pin_port = htons((uint16_t) i_port);
01428 }
01429 else
01430 {
01431 dbg_err_if ((se = getservbyname(s_port, NULL)) == NULL);
01432 *pin_port = (uint16_t) se->s_port;
01433 }
01434
01435 return 0;
01436 err:
01437 return ~0;
01438 }
01439 #endif
01440
01441 static inline int update_timeout (struct timeval *timeout,
01442 struct timeval *tstart)
01443 {
01444 struct timeval now, telapsed;
01445
01446 dbg_return_if (timeout == NULL, ~0);
01447 dbg_return_if (tstart == NULL, ~0);
01448
01449 dbg_err_sif (gettimeofday(&now, NULL) == -1);
01450
01451
01452 u_timersub(&now, tstart, &telapsed);
01453
01454
01455 u_timersub(timeout, &telapsed, timeout);
01456
01457
01458 *tstart = now;
01459
01460 return 0;
01461 err:
01462 return ~0;
01463 }