6 #define LIBSOCKET_VERSION 2.4 8 #define LIBSOCKET_LINUX 0 10 #define LIBSOCKET_LINUX 1 12 #define LIBSOCKET_FREEBSD 0 13 #define LIBSOCKET_SUNOS 0 18 #include <netinet/in.h> 23 #include <sys/ioctl.h> 24 #include <sys/socket.h> 25 #include <sys/types.h> 80 #define LIBSOCKET_BACKLOG \ 84 #define LIBSOCKET_TCP 1 85 #define LIBSOCKET_UDP 2 87 #define LIBSOCKET_IPv4 3 88 #define LIBSOCKET_IPv6 4 89 #define LIBSOCKET_BOTH \ 93 #define LIBSOCKET_READ 1 94 #define LIBSOCKET_WRITE 2 96 #define LIBSOCKET_NUMERIC \ 103 #define debug_write(str) \ 105 int verbose_errno_save = errno; \ 106 write(2, str, strlen(str)); \ 107 errno = verbose_errno_save; \ 111 #define _TRADITIONAL_RDNS 131 if (return_value < 0) {
133 errbuf = strerror(errno);
156 char proto_osi3,
int flags) {
157 int sfd, return_value;
158 struct addrinfo hint, *result, *result_check;
160 const char *errstring;
163 if (host == NULL || service == NULL)
return -1;
165 memset(&hint, 0,
sizeof hint);
168 switch (proto_osi3) {
170 hint.ai_family = AF_INET;
173 hint.ai_family = AF_INET6;
176 hint.ai_family = AF_UNSPEC;
183 hint.ai_socktype = SOCK_STREAM;
185 if (0 != (return_value = getaddrinfo(host, service, &hint, &result))) {
187 errstring = gai_strerror(return_value);
188 debug_write(errstring);
196 for (result_check = result; result_check != NULL;
197 result_check = result_check->ai_next)
200 sfd = socket(result_check->ai_family, result_check->ai_socktype | flags,
201 result_check->ai_protocol);
206 if (-1 != connect(sfd, result_check->ai_addr,
207 result_check->ai_addrlen))
215 if (result_check == NULL)
219 "create_inet_stream_socket: Could not connect to any address!\n");
221 int errno_saved = errno;
224 freeaddrinfo(result);
229 freeaddrinfo(result);
253 if (proto_osi3 != LIBSOCKET_IPv4 && proto_osi3 != LIBSOCKET_IPv6) {
256 "create_inet_dgram_socket: osi3 argument invalid for DGRAM " 262 switch (proto_osi3) {
264 sfd = socket(AF_INET, SOCK_DGRAM | flags, 0);
267 sfd = socket(AF_INET6, SOCK_DGRAM | flags, 0);
304 const char *host,
const char *service,
306 struct sockaddr_storage oldsock;
307 struct addrinfo *result, *result_check, hint;
308 socklen_t oldsocklen =
sizeof(
struct sockaddr_storage);
311 const char *errstring;
314 if (sfd < 0)
return -1;
316 if (buf == NULL)
return -1;
318 if (size == 0)
return 0;
320 if (host == NULL || service == NULL)
return -1;
322 if (-1 ==
check_error(getsockname(sfd, (
struct sockaddr *)&oldsock,
323 (socklen_t *)&oldsocklen)))
326 memset(&hint, 0,
sizeof(
struct addrinfo));
333 hint.ai_family = oldsock.ss_family;
334 hint.ai_socktype = SOCK_DGRAM;
336 if (0 != (return_value = getaddrinfo(host, service, &hint, &result))) {
338 errstring = gai_strerror(return_value);
339 debug_write(errstring);
344 for (result_check = result; result_check != NULL;
345 result_check = result_check->ai_next)
348 if (-1 != (return_value = sendto(
349 sfd, buf, size, sendto_flags, result_check->ai_addr,
350 result_check->ai_addrlen)))
358 freeaddrinfo(result);
386 char *src_host,
size_t src_host_len,
387 char *src_service,
size_t src_service_len,
388 int recvfrom_flags,
int numeric) {
389 struct sockaddr_storage client;
391 #ifdef _TRADITIONAL_RDNS 392 struct sockaddr_storage oldsockaddr;
393 socklen_t oldsockaddrlen =
sizeof(
struct sockaddr_storage);
402 #ifndef _TRADITIONAL_RDNS 409 if (sfd < 0)
return -1;
411 if (buffer == NULL || size == 0)
414 memset(buffer, 0, size);
416 if (src_host) memset(src_host, 0, src_host_len);
417 if (src_service) memset(src_service, 0, src_service_len);
419 socklen_t stor_addrlen =
sizeof(
struct sockaddr_storage);
421 if (-1 ==
check_error(bytes = recvfrom(sfd, buffer, size, recvfrom_flags,
422 (
struct sockaddr *)&client,
426 if (src_host_len > 0 ||
431 if (numeric == LIBSOCKET_NUMERIC) {
432 numeric = NI_NUMERICHOST | NI_NUMERICSERV;
436 #ifndef _TRADITIONAL_RDNS 438 (retval = getnameinfo(
439 (
struct sockaddr *)&client,
sizeof(
struct sockaddr_storage),
440 src_host, src_host_len, src_service, src_service_len,
444 errstr = gai_strerror(retval);
452 #ifdef _TRADITIONAL_RDNS 453 if (-1 ==
check_error(getsockname(sfd, (
struct sockaddr *)&oldsockaddr,
458 sizeof(
struct sockaddr_storage))
462 if (oldsockaddr.ss_family == AF_INET) {
463 addrptr = &(((
struct sockaddr_in *)&client)->sin_addr);
464 addrlen =
sizeof(
struct in_addr);
465 sport = ntohs(((
struct sockaddr_in *)&client)->sin_port);
466 }
else if (oldsockaddr.ss_family == AF_INET6) {
467 addrptr = &(((
struct sockaddr_in6 *)&client)->sin6_addr);
468 addrlen =
sizeof(
struct in6_addr);
469 sport = ntohs(((
struct sockaddr_in6 *)&client)->sin6_port);
473 (he = gethostbyaddr(addrptr, addrlen, oldsockaddr.ss_family))) {
478 strncpy(src_host, he->h_name, src_host_len);
479 snprintf(src_service, src_service_len,
"%u", sport);
501 struct addrinfo *result, *result_check, hint;
502 struct sockaddr_storage oldsockaddr;
503 struct sockaddr deconnect;
504 socklen_t oldsockaddrlen =
sizeof(
struct sockaddr_storage);
507 const char *errstring;
510 if (sfd < 0)
return -1;
517 memset(&deconnect, 0,
sizeof(
struct sockaddr));
519 deconnect.sa_family = AF_UNSPEC;
521 if (
check_error(connect(sfd, &deconnect,
sizeof(
struct sockaddr))))
527 if (-1 ==
check_error(getsockname(sfd, (
struct sockaddr *)&oldsockaddr,
532 sizeof(
struct sockaddr_storage))
535 memset(&hint, 0,
sizeof(
struct addrinfo));
537 hint.ai_family = ((
struct sockaddr_in *)&oldsockaddr)
540 hint.ai_socktype = SOCK_DGRAM;
542 if (0 != (return_value = getaddrinfo(host, service, &hint, &result))) {
544 errstring = gai_strerror(return_value);
545 debug_write(errstring);
553 for (result_check = result; result_check != NULL;
554 result_check = result_check->ai_next)
557 if (-1 != (return_value = connect(
558 sfd, result_check->ai_addr,
559 result_check->ai_addrlen)))
569 if (result_check == NULL)
573 "connect_inet_dgram_socket: Could not connect to any address!\n");
575 freeaddrinfo(result);
579 freeaddrinfo(result);
596 if (sfd < 0)
return -1;
620 if (sfd < 0)
return -1;
622 if ((method != LIBSOCKET_READ) && (method != LIBSOCKET_WRITE) &&
623 (method != (LIBSOCKET_READ | LIBSOCKET_WRITE)))
626 if (method & LIBSOCKET_READ)
628 if (-1 ==
check_error(shutdown(sfd, SHUT_RD)))
return -1;
634 if (-1 ==
check_error(shutdown(sfd, SHUT_WR)))
return -1;
671 char proto_osi4,
char proto_osi3,
int flags) {
672 int sfd, domain, type, retval;
673 struct addrinfo *result, *result_check, hints;
681 if (bind_addr == NULL || bind_port == NULL)
return -1;
683 switch (proto_osi4) {
693 switch (proto_osi3) {
707 memset(&hints, 0,
sizeof(
struct addrinfo));
709 hints.ai_socktype = type;
710 hints.ai_family = domain;
711 hints.ai_flags = AI_PASSIVE;
713 if (0 != (retval = getaddrinfo(bind_addr, bind_port, &hints, &result))) {
715 errstr = gai_strerror(retval);
723 for (result_check = result; result_check != NULL;
724 result_check = result_check->ai_next)
727 sfd = socket(result_check->ai_family, result_check->ai_socktype | flags,
728 result_check->ai_protocol);
733 retval = bind(sfd, result_check->ai_addr,
734 (socklen_t)result_check->ai_addrlen);
742 if (type == LIBSOCKET_TCP) retval = listen(sfd, LIBSOCKET_BACKLOG);
751 if (result_check == NULL) {
754 "create_inet_server_socket: Could not bind to any address!\n");
756 freeaddrinfo(result);
762 freeaddrinfo(result);
792 char *src_service,
size_t src_service_len,
793 int flags,
int accept_flags) {
794 struct sockaddr_storage client_info;
797 #ifndef _TRADITIONAL_RDNS 801 #ifdef _TRADITIONAL_RDNS 802 struct sockaddr_storage oldsockaddr;
803 socklen_t oldsockaddrlen =
sizeof(
struct sockaddr_storage);
813 socklen_t addrlen =
sizeof(
struct sockaddr_storage);
818 check_error((client_sfd = accept4(sfd, (
struct sockaddr *)&client_info,
819 &addrlen, accept_flags))))
823 check_error((client_sfd = accept(sfd, (
struct sockaddr *)&client_info,
828 if (src_host_len > 0 ||
833 if (flags == LIBSOCKET_NUMERIC) {
834 flags = NI_NUMERICHOST | NI_NUMERICSERV;
839 #ifndef _TRADITIONAL_RDNS 840 if (0 != (retval = getnameinfo(
841 (
struct sockaddr *)&client_info,
842 sizeof(
struct sockaddr_storage), src_host, src_host_len,
843 src_service, src_service_len,
847 errstr = gai_strerror(retval);
853 #ifdef _TRADITIONAL_RDNS 854 if (-1 ==
check_error(getsockname(sfd, (
struct sockaddr *)&oldsockaddr,
859 sizeof(
struct sockaddr_storage))
863 if (oldsockaddr.ss_family == AF_INET) {
864 addrptr = &(((
struct sockaddr_in *)&client_info)->sin_addr);
865 in_addrlen =
sizeof(
struct in_addr);
866 sport = ntohs(((
struct sockaddr_in *)&client_info)->sin_port);
867 }
else if (oldsockaddr.ss_family == AF_INET6) {
868 addrptr = &(((
struct sockaddr_in6 *)&client_info)->sin6_addr);
869 in_addrlen =
sizeof(
struct in6_addr);
870 sport = ntohs(((
struct sockaddr_in6 *)&client_info)->sin6_port);
874 (he = gethostbyaddr(addrptr, in_addrlen, oldsockaddr.ss_family))) {
879 strncpy(src_host, he->h_name, src_host_len);
880 snprintf(src_service, src_service_len,
"%u", sport);
904 struct addrinfo hint, *result;
906 const char *errstring;
910 if (hostname == NULL)
return -1;
912 memset(&hint, 0,
sizeof hint);
914 hint.ai_family = AF_UNSPEC;
916 if (0 != (return_value = getaddrinfo(hostname,
"0", &hint, &result))) {
918 errstring = gai_strerror(return_value);
919 debug_write(errstring);
924 if (result == NULL)
return -1;
926 if (result->ai_family == AF_INET) {
928 }
else if (result->ai_family == AF_INET6) {
963 #ifdef LIBSOCKET_LINUX 965 const char *if_name) {
966 int sfd, return_value;
967 struct sockaddr maddr, localif;
968 struct addrinfo hints, *result;
969 struct ip_mreqn mreq4;
970 struct ipv6_mreq mreq6;
972 struct ifreq interface;
974 memset(&maddr, 0,
sizeof(maddr));
975 memset(&localif, 0,
sizeof(localif));
976 memset(&mreq4, 0,
sizeof(mreq4));
977 memset(&mreq6, 0,
sizeof(mreq6));
978 memset(&hints, 0,
sizeof(hints));
979 memset(&interface, 0,
sizeof(interface));
982 group, port, LIBSOCKET_UDP, LIBSOCKET_BOTH, 0))) {
986 hints.ai_socktype = SOCK_DGRAM;
987 hints.ai_family = AF_UNSPEC;
989 if (0 != (return_value = getaddrinfo(group, port, &hints, &result))) {
990 int errno_saved = errno;
992 const char *errstring = gai_strerror(return_value);
993 debug_write(errstring);
1001 if (result->ai_family == AF_INET) {
1003 mreq4.imr_multiaddr = ((
struct sockaddr_in *)result->ai_addr)->sin_addr;
1005 if (if_name == NULL) {
1006 mreq4.imr_ifindex = 0;
1007 any.s_addr = INADDR_ANY;
1008 mreq4.imr_address = any;
1010 memcpy(interface.ifr_name, if_name,
1011 strlen(if_name) > IFNAMSIZ ? IFNAMSIZ : strlen(if_name));
1013 if (-1 ==
check_error(ioctl(sfd, SIOCGIFINDEX, &interface))) {
1014 int errno_saved = errno;
1016 errno = errno_saved;
1020 mreq4.imr_ifindex = interface.ifr_ifindex;
1023 if (-1 ==
check_error(setsockopt(sfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
1024 &mreq4,
sizeof(
struct ip_mreqn)))) {
1025 int errno_saved = errno;
1027 errno = errno_saved;
1030 if (-1 ==
check_error(setsockopt(sfd, IPPROTO_IP, IP_MULTICAST_IF,
1031 &mreq4,
sizeof(
struct ip_mreqn)))) {
1032 int errno_saved = errno;
1034 errno = errno_saved;
1040 }
else if (result->ai_family == AF_INET6) {
1041 mreq6.ipv6mr_multiaddr =
1042 ((
struct sockaddr_in6 *)result->ai_addr)->sin6_addr;
1043 mreq6.ipv6mr_interface = 0;
1045 if (if_name == NULL)
1046 mreq6.ipv6mr_interface = 0;
1048 memcpy(interface.ifr_name, if_name,
1049 strlen(if_name) > IFNAMSIZ ? IFNAMSIZ : strlen(if_name));
1051 if (-1 ==
check_error(ioctl(sfd, SIOCGIFINDEX, &interface))) {
1052 int errno_saved = errno;
1054 errno = errno_saved;
1058 mreq6.ipv6mr_interface = interface.ifr_ifindex;
1061 if (-1 ==
check_error(setsockopt(sfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
1062 &mreq6,
sizeof(
struct ipv6_mreq)))) {
1063 int errno_saved = errno;
1065 errno = errno_saved;
1068 if (-1 ==
check_error(setsockopt(sfd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
1069 &mreq6.ipv6mr_interface,
1070 sizeof(mreq6.ipv6mr_interface)))) {
1071 int errno_saved = errno;
1073 errno = errno_saved;
int create_inet_server_socket(const char *bind_addr, const char *bind_port, char proto_osi4, char proto_osi3, int flags)
Create a TCP or UDP server socket.
int get_address_family(const char *hostname)
Look up which address families a host supports.
ssize_t sendto_inet_dgram_socket(int sfd, const void *buf, size_t size, const char *host, const char *service, int sendto_flags)
This function is the equivalent to sendto(2)
int destroy_inet_socket(int sfd)
Close a socket.
int create_multicast_socket(const char *group, const char *port, const char *if_name)
Create a datagram socket and join to the multicast group address.
int accept_inet_stream_socket(int sfd, char *src_host, size_t src_host_len, char *src_service, size_t src_service_len, int flags, int accept_flags)
Accept a connection attempt on a server socket.
int create_inet_stream_socket(const char *host, const char *service, char proto_osi3, int flags)
Create and connect a new TCP/IP socket.
int shutdown_inet_stream_socket(int sfd, int method)
Perform a shutdown(2) call on a socket.
static signed int check_error(int return_value)
Checks return value for error.
int connect_inet_dgram_socket(int sfd, const char *host, const char *service)
Connect a UDP socket.
ssize_t recvfrom_inet_dgram_socket(int sfd, void *buffer, size_t size, char *src_host, size_t src_host_len, char *src_service, size_t src_service_len, int recvfrom_flags, int numeric)
Receive data from a UDP/IP socket.
int create_inet_dgram_socket(char proto_osi3, int flags)
Creates a new UDP/IP socket.