From 005624f44f60dc6e3048e30cc163409e8df7ecc1 Mon Sep 17 00:00:00 2001 From: llsth Date: Sat, 15 Aug 2015 00:07:22 +0200 Subject: [PATCH] Initial AmigaOS changes --- .gitignore | 1 + README | 52 ----- config.h | 85 +++++++ doc/fping.txt | 173 ++++++++++++++ readme | 26 +++ src/fping.c | 149 ++++++++++-- src/fping.h | 5 + src/inet_ntohl.c | 30 +++ src/inet_ntop.c | 144 ++++++++++++ src/inet_pton.c | 299 ++++++++++++++++++++++++ src/net_getaddrinfo.c | 531 ++++++++++++++++++++++++++++++++++++++++++ src/net_getaddrinfo.h | 220 +++++++++++++++++ 12 files changed, 1640 insertions(+), 75 deletions(-) delete mode 100644 README create mode 100644 config.h create mode 100644 doc/fping.txt create mode 100644 readme create mode 100644 src/inet_ntohl.c create mode 100644 src/inet_ntop.c create mode 100644 src/inet_pton.c create mode 100644 src/net_getaddrinfo.c create mode 100644 src/net_getaddrinfo.h diff --git a/.gitignore b/.gitignore index 3c1e5c9..c842452 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ stamp-h1 doc/fping.8 doc/fping6.8 ci/build +*.kdev4 diff --git a/README b/README deleted file mode 100644 index d21c868..0000000 --- a/README +++ /dev/null @@ -1,52 +0,0 @@ -fping 3 README --------------- -fping is a program to send ICMP echo probes to network hosts, similar to ping, -but much better performing when pinging multiple hosts. fping has a long long -story: Roland Schemers did publish a first version of it in 1992 and it has -established itself since then as a standard tool. - -Current maintainer: - David Schweikert - -Website: - http://fping.org/ - -Mailing-list: - https://groups.google.com/group/fping-users - - -Installation ------------- -If you want to install fping from source, proceed as follows: - -1. Run ./configure with the correct arguments - (see: ./configure --help) - -2. Run make; make install - -3. Make fping either setuid, or, if under Linux: - - sudo setcap cap_net_raw+ep fping - -4. Have a look at the fping(8) manual for usage help - (fping -h will also give a minimal help output) - - -IPv6 support ------------- -You can can compile fping with support for IPv6 addresses. A separate binary -is used for that, called fping6. To build it, use ./configure --enable-ipv6 -(possibly combined with --enable-ipv4 to also build fping for IPv4). E.g.: - - # ./configure --prefix=/usr/local --enable-ipv4 --enable-ipv6 - # make - # make install - # sudo setcap cap_net_raw+ep /usr/local/bin/fping* - - -Credits -------- -Original author: Roland Schemers (schemers@stanford.edu) -Previous maintainer: RL "Bob" Morgan (morgan@stanford.edu) -Initial IPv6 Support: Jeroen Massar (jeroen@unfix.org / jeroen@ipng.nl) -Other contributors: see ChangeLog diff --git a/config.h b/config.h new file mode 100644 index 0000000..f4ec76c --- /dev/null +++ b/config.h @@ -0,0 +1,85 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + + +#ifndef CONFIG_H +#define CONFIG_H + +#include "net_getaddrinfo.h" + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_INTTYPES_H */ + +/* Define to 1 if you have the `nsl' library (-lnsl). */ +/* #undef HAVE_LIBNSL */ + +/* Define to 1 if you have the `socket' library (-lsocket). */ +#define HAVE_LIBSOCKET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STDINT_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_FILE_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SELECT_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Name of package */ +#define PACKAGE "fping" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "fping" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "fping 3.10" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "fping" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "3.10" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "3.10" + + +/* some OSes do not define this ... lets take a wild guess */ + +#ifndef INADDR_NONE +# define INADDR_NONE 0xffffffffU +#endif + +#endif /* CONFIG_H */ + + diff --git a/doc/fping.txt b/doc/fping.txt new file mode 100644 index 0000000..a2c6568 --- /dev/null +++ b/doc/fping.txt @@ -0,0 +1,173 @@ + +NAME + fping - send ICMP ECHO_REQUEST packets to network hosts + +SYNOPSIS + fping [ options ] [ systems... ] fping6 [ options ] [ systems... ] + +DESCRIPTION + fping is a program like ping which uses the Internet Control Message + Protocol (ICMP) echo request to determine if a target host is + responding. fping differs from ping in that you can specify any number + of targets on the command line, or specify a file containing the lists + of targets to ping. Instead of sending to one target until it times + out or replies, fping will send out a ping packet and move on to the + next target in a round-robin fashion. In the default mode, if a target + replies, it is noted and removed from the list of targets to check; if + a target does not respond within a certain time limit and/or retry + limit it is designated as unreachable. fping also supports sending a + specified number of pings to a target, or looping indefinitely (as in + ping ). Unlike ping, fping is meant to be used in scripts, so its + output is designed to be easy to parse. + + The binary named fping6 is the same as fping, except that it uses IPv6 + addresses instead of IPv4. + +OPTIONS + -a Show systems that are alive. + + -A Display targets by address rather than DNS name. + + -b n Number of bytes of ping data to send. The minimum size (normally + 12) allows room for the data that fping needs to do its work + (sequence number, timestamp). The reported received data size + includes the IP header (normally 20 bytes) and ICMP header (8 + bytes), so the minimum total size is 40 bytes. Default is 56, as + in ping. Maximum is the theoretical maximum IP datagram size + (64K), though most systems limit this to a smaller, system- + dependent number. + + -B n Backoff factor. In the default mode, fping sends several requests + to a target before giving up, waiting longer for a reply on each + successive request. This parameter is the value by which the wait + time (-t) is multiplied on each successive request; it must be + entered as a floating-point number (x.y). The default is 1.5. + + -c n Number of request packets to send to each target. In this mode, a + line is displayed for each received response (this can suppressed + with -q or -Q). Also, statistics about responses for each target + are displayed when all requests have been sent (or when + interrupted). + + -C n Similar to -c, but the per-target statistics are displayed in a + format designed for automated response-time statistics gathering. + For example: + + % fping -C 5 -q somehost + somehost : 91.7 37.0 29.2 - 36.8 + + shows the response time in milliseconds for each of the five + requests, with the "-" indicating that no response was received to + the fourth request. + + -d Use DNS to lookup address of return ping packet. This allows you + to give fping a list of IP addresses as input and print hostnames + in the output. + + -D Add Unix timestamps in front of output lines generated with in + looping or counting modes (-l, -c, or -C). + + -e Show elapsed (round-trip) time of packets. + + -f Read list of targets from a file. This option can only be used by + the root user. Regular users should pipe in the file via stdin: + + % fping < targets_file + + -g addr/mask + Generate a target list from a supplied IP netmask, or a starting + and ending IP. Specify the netmask or start/end in the targets + portion of the command line. If a network with netmask is given, + the network and broadcast addresses will be excluded. ex. To ping + the network 192.168.1.0/24, the specified command line could look + like either: + + fping -g 192.168.1.0/24 + + or + + fping -g 192.168.1.1 192.168.1.254 + + -h Print usage message. + + -i n The minimum amount of time (in milliseconds) between sending a + ping packet to any target (default is 25). + + -l Loop sending packets to each target indefinitely. Can be + interrupted with Ctrl-C; statistics about responses for each + target are then displayed. + + -m Send pings to each of a target host's multiple interfaces. + + -n Same as -d. + + -p  + In looping or counting modes (-l, -c, or -C), this parameter sets + the time in milliseconds that fping waits between successive + packets to an individual target. Default is 1000. + + -q Quiet. Don't show per-probe results, but only the final summary. + Also don't show ICMP error messages. + + -Q n Like -q, but show summary results every n seconds. + + -r n Retry limit (default 3). This is the number of times an attempt at + pinging a target will be made, not including the first try. + + -s Print cumulative statistics upon exit. + + -S addr + Set source address. + + -I if + Set the interface (requires SO_BINDTODEVICE support) + + -t n Initial target timeout in milliseconds (default 500). In the + default mode, this is the amount of time that fping waits for a + response to its first request. Successive timeouts are multiplied + by the backoff factor specified with -B. Note that this option + has no effect looping or counting modes (-l, -c, or -C). + + -T n Ignored (for compatibility with fping 2.4). + + -u Show targets that are unreachable. + + -O n Set the typ of service flag (TOS). n can be either decimal or + hexadecimal (0xh) format. + + -v Print fping version information. + + -H n Set the IP TTL field (time to live hops). + +AUTHORS + · Roland J. Schemers III, Stanford University, concept and versions + 1.x + + · RL "Bob" Morgan, Stanford University, versions 2.x + + · David Papp, versions 2.3x and up + + · David Schweikert, versions 3.0 and up + + fping website:  + +DIAGNOSTICS + Exit status is 0 if all the hosts are reachable, 1 if some hosts were + unreachable, 2 if any IP addresses were not found, 3 for invalid + command line arguments, and 4 for a system call failure. + +RESTRICTIONS + If certain options are used (i.e, a low value for -i and -t, and a high + value for -r) it is possible to flood the network. This program must be + installed as setuid root in order to open up a raw socket, or must be + run by root. In order to stop mere mortals from hosing the network, + normal users can't specify the following: + + · -i n, where n < 10 msec + + · -r n, where n > 20 + + · -t n, where n < 250 msec + + + 2014-05-04 diff --git a/readme b/readme new file mode 100644 index 0000000..03c1265 --- /dev/null +++ b/readme @@ -0,0 +1,26 @@ +fping 3 README +-------------- + +fping is a program to send ICMP echo probes to network hosts, similar to ping, +but much better performing when pinging multiple hosts. fping has a long long +story: Roland Schemers did publish a first version of it in 1992 and it has +established itself since then as a standard tool. + +Current maintainer: + David Schweikert + +Website: + http://fping.org/ + +Mailing-list: + https://groups.google.com/group/fping-users + + +Credits +------- + +AmigaOS maintainer Carsten Larsen (carsten.larsen@mail.com) +Original author: Roland Schemers (schemers@stanford.edu) +Previous maintainer: RL "Bob" Morgan (morgan@stanford.edu) +Initial IPv6 Support: Jeroen Massar (jeroen@unfix.org / jeroen@ipng.nl) +Other contributors: see ChangeLog diff --git a/src/fping.c b/src/fping.c index 7c01694..7ecdfa4 100644 --- a/src/fping.c +++ b/src/fping.c @@ -38,6 +38,72 @@ extern "C" #include "fping.h" #include "options.h" +//--------------------------------------------------------------------------// +// NOTE: Quickfixes +//--------------------------------------------------------------------------// + +int h_errno; + +#include "unistd.h" +uid_t getuid () { return 1; } +int setuid (uid_t id) { return 1; } + +#define OPEN_ERROR "Cannot open %s.\n" +#define OPEN_VER_ERROR "Cannot open %s (%ld.0)\n" +#define DOSLIB_NAME "dos.library" +#define DOSLIB_REV 37L +#define UTILLIB_NAME "utility.library" +#define UTILLIB_REV 37L +#define BSDLIB_NAME "bsdsocket.library" +#define BSDLIB_REV 03L +#define USERGROUPLIB_NAME "usergroup.library" +#define USERGROUPLIB_REV 00L + +# include +#include "clib/exec_protos.h" +struct Library *DOSBase; +struct Library *SocketBase; + +void amiga_open_error(char *name) +{ + printf(OPEN_ERROR, name); +} + +void amiga_open_lib_error(char *name, int version) +{ + printf(OPEN_VER_ERROR, name, version); +} + +void close_libs() +{ + if (DOSBase != NULL) { + CloseLibrary(DOSBase); + DOSBase = NULL; + } + + if (SocketBase != NULL) { + CloseLibrary(SocketBase); + SocketBase = NULL; + } +} + +int open_libs() +{ + atexit(close_libs); + + if(!(DOSBase = OpenLibrary((STRPTR)DOSLIB_NAME, DOSLIB_REV))) { + amiga_open_lib_error(DOSLIB_NAME, DOSLIB_REV); + return 5; + } + + if(!(SocketBase = OpenLibrary((STRPTR)BSDLIB_NAME, BSDLIB_REV))) { + amiga_open_lib_error(BSDLIB_NAME, BSDLIB_REV); + return 5; + } +} + +//--------------------------------------------------------------------------// + /* if compiling for Windows, use this separate set (too difficult to ifdef all the autoconf defines) */ #ifdef WIN32 @@ -259,7 +325,6 @@ unsigned int perhost_interval = DEFAULT_PERHOST_INTERVAL * 100; float backoff = DEFAULT_BACKOFF_FACTOR; unsigned int ping_data_size = DEFAULT_PING_DATA_SIZE; unsigned int ping_pkt_size; -char *ping_buffer; unsigned int count = 1; unsigned int trials; unsigned int report_interval = 0; @@ -301,7 +366,6 @@ int elapsed_flag, version_flag, count_flag, loop_flag; int per_recv_flag, report_all_rtts_flag, name_flag, addr_flag, backoff_flag; int multif_flag; int timestamp_flag = 0; -int random_data_flag = 0; #if defined( DEBUG ) || defined( _DEBUG ) int randomly_lose_flag, sent_times_flag, trace_flag, print_per_system_flag; int lose_factor; @@ -322,6 +386,7 @@ void crash_and_burn( char *message ); void errno_crash_and_burn( char *message ); char *get_host_by_address( struct in_addr in ); int in_cksum( unsigned short *p, int n ); +void u_sleep( int u_sec ); int recvfrom_wto ( int s, char *buf, int len, FPING_SOCKADDR *saddr, long timo ); void remove_job( HOST_ENTRY *h ); int send_ping( int s, HOST_ENTRY *h ); @@ -367,6 +432,7 @@ int main( int argc, char **argv ) int tos = 0; HOST_ENTRY *cursor; + open_libs(); s = open_ping_socket(); if((uid = getuid())) { @@ -382,7 +448,7 @@ int main( int argc, char **argv ) /* get command line options */ - while( ( c = getopt( argc, argv, "gedhlmnqusaAvDRz:t:H:i:p:f:r:c:b:C:Q:B:S:I:T:O:" ) ) != EOF ) + while( ( c = getopt( argc, argv, "gedhlmnqusaAvDz:t:H:i:p:f:r:c:b:C:Q:B:S:I:T:O:" ) ) != EOF ) { switch( c ) { @@ -478,10 +544,6 @@ int main( int argc, char **argv ) timestamp_flag = 1; break; - case 'R': - random_data_flag = 1; - break; - case 'l': loop_flag = 1; backoff_flag = 0; @@ -823,10 +885,7 @@ int main( int argc, char **argv ) }/* FOR */ ping_pkt_size = ping_data_size + SIZE_ICMP_HDR; - ping_buffer = ( char* )malloc( ( size_t )ping_pkt_size ); - if( !ping_buffer ) - crash_and_burn( "can't malloc ping packet" ); - + signal( SIGINT, finish ); gettimeofday( &start_time, &tz ); @@ -1402,19 +1461,18 @@ void print_global_stats( void ) int send_ping( int s, HOST_ENTRY *h ) { + char *buffer; FPING_ICMPHDR *icp; int n; int myseq; int ret = 1; - if (random_data_flag) { - for (n = 0; n < ping_pkt_size; ++n) { - ping_buffer[n] = random() & 0xFF; - } - } else { - memset( ping_buffer, 0, ping_pkt_size * sizeof( char ) ); - } - icp = ( FPING_ICMPHDR* )ping_buffer; + buffer = ( char* )malloc( ( size_t )ping_pkt_size ); + if( !buffer ) + crash_and_burn( "can't malloc ping packet" ); + + memset( buffer, 0, ping_pkt_size * sizeof( char ) ); + icp = ( FPING_ICMPHDR* )buffer; gettimeofday( &h->last_send_time, &tz ); myseq = seqmap_add(h->i, h->num_sent, &h->last_send_time); @@ -1440,7 +1498,7 @@ int send_ping( int s, HOST_ENTRY *h ) printf( "sending [%d] to %s\n", h->num_sent, h->host ); #endif /* DEBUG || _DEBUG */ - n = sendto( s, ping_buffer, ping_pkt_size, 0, + n = sendto( s, buffer, ping_pkt_size, 0, ( struct sockaddr* )&h->saddr, sizeof( FPING_SOCKADDR ) ); if( @@ -1449,8 +1507,12 @@ int send_ping( int s, HOST_ENTRY *h ) && errno != EHOSTDOWN #endif ) { - if( verbose_flag ) { - print_warning( "%s: error while sending ping: %s\n", h->host, strerror( errno ) ); + if( verbose_flag || unreachable_flag ) { + printf( "%s", h->host ); + if( verbose_flag ) + printf( " error while sending ping: %s\n", strerror( errno ) ); + + printf( "\n" ); } if( !loop_flag ) @@ -1474,6 +1536,7 @@ int send_ping( int s, HOST_ENTRY *h ) h->waiting++; num_pingsent++; last_send_time = h->last_send_time; + free( buffer ); return(ret); } @@ -2406,6 +2469,47 @@ char * sprint_tm( int t ) return( buf ); } +/************************************************************ + + Function: u_sleep + +************************************************************* + + Inputs: int u_sec + + Description: + +************************************************************/ + +void u_sleep( int u_sec ) +{ + int nfound; + struct timeval to; + fd_set readset, writeset; + +select_again: + to.tv_sec = u_sec / 1000000; + to.tv_usec = u_sec - ( to.tv_sec * 1000000 ); + + FD_ZERO( &readset ); + FD_ZERO( &writeset ); + + nfound = select( 0, &readset, &writeset, NULL, &to ); + if(nfound < 0) { + if(errno == EINTR) { + /* interrupted system call: redo the select */ + goto select_again; + } + else { + errno_crash_and_burn( "select" ); + } + } + + return; + +} /* u_sleep() */ + + /************************************************************ Function: recvfrom_wto @@ -2629,7 +2733,6 @@ void usage(int is_error) fprintf(out, " -q quiet (don't show per-target/per-ping results)\n" ); fprintf(out, " -Q n same as -q, but show summary every n seconds\n" ); fprintf(out, " -r n number of retries (default %d)\n", DEFAULT_RETRY ); - fprintf(out, " -R random packet data (to foil link data compression)\n" ); fprintf(out, " -s print final stats\n" ); fprintf(out, " -S addr set source address\n" ); fprintf(out, " -t n individual target initial timeout (in millisec) (default %d)\n", timeout / 100 ); diff --git a/src/fping.h b/src/fping.h index 113be63..e54eba6 100644 --- a/src/fping.h +++ b/src/fping.h @@ -25,4 +25,9 @@ void errno_crash_and_burn( char *message ); int open_ping_socket(); void socket_set_src_addr(int s, FPING_INADDR src_addr); +// NOTE: Quickfix +#include "clib/exec_protos.h" +extern struct Library *SocketBase; +#include "clib/amitcp_protos.h" + #endif diff --git a/src/inet_ntohl.c b/src/inet_ntohl.c new file mode 100644 index 0000000..d6bfeb0 --- /dev/null +++ b/src/inet_ntohl.c @@ -0,0 +1,30 @@ +/* $NetBSD: ntohl.c,v 1.3 2012/03/21 20:02:56 he Exp $ */ + +/* + * Written by J.T. Conklin . + * Public domain. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: ntohl.c,v 1.3 2012/03/21 20:02:56 he Exp $"); +#endif + +#include + +#ifndef uint32_t +# define uint32_t u_int32_t +#endif + +#undef ntohl + +uint32_t +ntohl(uint32_t x) +{ +#if BYTE_ORDER == LITTLE_ENDIAN + u_char *s = (void *)&x; + return (uint32_t)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]); +#else + return x; +#endif +} diff --git a/src/inet_ntop.c b/src/inet_ntop.c new file mode 100644 index 0000000..5c5b794 --- /dev/null +++ b/src/inet_ntop.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +__RCSID("$Heimdal: inet_ntop.c 21005 2007-06-08 01:54:35Z lha $" + "$NetBSD: inet_ntop.c,v 1.2 2008/03/22 08:37:21 mlelstv Exp $"); +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifndef INET_ADDRSTRLEN +# define INET_ADDRSTRLEN 16 +#endif + +/* + * + */ + +static const char * +inet_ntop_v4 (const void *src, char *dst, size_t size) +{ + const char digits[] = "0123456789"; + int i; + struct in_addr *addr = (struct in_addr *)src; + u_long a = ntohl(addr->s_addr); + const char *orig_dst = dst; + + if (size < INET_ADDRSTRLEN) { + errno = ENOSPC; + return NULL; + } + for (i = 0; i < 4; ++i) { + int n = (a >> (24 - i * 8)) & 0xFF; + int non_zerop = 0; + + if (non_zerop || n / 100 > 0) { + *dst++ = digits[n / 100]; + n %= 100; + non_zerop = 1; + } + if (non_zerop || n / 10 > 0) { + *dst++ = digits[n / 10]; + n %= 10; + non_zerop = 1; + } + *dst++ = digits[n]; + if (i != 3) + *dst++ = '.'; + } + *dst++ = '\0'; + return orig_dst; +} + +#ifdef HAVE_IPV6 +static const char * +inet_ntop_v6 (const void *src, char *dst, size_t size) +{ + const char xdigits[] = "0123456789abcdef"; + int i; + const struct in6_addr *addr = (struct in6_addr *)src; + const u_char *ptr = addr->s6_addr; + const char *orig_dst = dst; + + if (size < INET6_ADDRSTRLEN) { + errno = ENOSPC; + return NULL; + } + for (i = 0; i < 8; ++i) { + int non_zerop = 0; + + if (non_zerop || (ptr[0] >> 4)) { + *dst++ = xdigits[ptr[0] >> 4]; + non_zerop = 1; + } + if (non_zerop || (ptr[0] & 0x0F)) { + *dst++ = xdigits[ptr[0] & 0x0F]; + non_zerop = 1; + } + if (non_zerop || (ptr[1] >> 4)) { + *dst++ = xdigits[ptr[1] >> 4]; + non_zerop = 1; + } + *dst++ = xdigits[ptr[1] & 0x0F]; + if (i != 7) + *dst++ = ':'; + ptr += 2; + } + *dst++ = '\0'; + return orig_dst; +} +#endif /* HAVE_IPV6 */ + +const char * +inet_ntop(int af, const void *src, char *dst, size_t size) +{ + switch (af) { + case AF_INET : + return inet_ntop_v4 (src, dst, size); +#ifdef HAVE_IPV6 + case AF_INET6 : + return inet_ntop_v6 (src, dst, size); +#endif + default : + errno = EAFNOSUPPORT; + return NULL; + } +} diff --git a/src/inet_pton.c b/src/inet_pton.c new file mode 100644 index 0000000..ac7034d --- /dev/null +++ b/src/inet_pton.c @@ -0,0 +1,299 @@ +/* $NetBSD: inet_pton.c,v 1.9 2007/07/23 11:45:52 lukem Exp $ */ +/* from NetBSD: inet_pton.c,v 1.3 2006/09/26 05:59:18 lukem Exp */ + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef uint32_t +# define uint32_t u_int32_t +#endif + +#if !defined(NS_INADDRSZ) +# define NS_INADDRSZ 4 +#endif +#if !defined(NS_IN6ADDRSZ) +# define NS_IN6ADDRSZ 16 +#endif +#if !defined(NS_INT16SZ) +# define NS_INT16SZ 2 +#endif + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static int inet_pton4(const char *src, unsigned char *dst, int pton); +#ifdef INET6 +static int inet_pton6(const char *src, unsigned char *dst); +#endif /* INET6 */ + +/* int + * inet_pton(af, src, dst) + * convert from presentation format (which usually means ASCII printable) + * to network format (which is usually some kind of binary format). + * return: + * 1 if the address was valid for the specified address family + * 0 if the address wasn't valid (`dst' is untouched in this case) + * -1 if some other error occurred (`dst' is untouched in this case, too) + * author: + * Paul Vixie, 1996. + */ +int +inet_pton(int af, const char *src, void *dst) +{ + + switch (af) { + case AF_INET: + return (inet_pton4(src, dst, 1)); +#ifdef INET6 + case AF_INET6: + return (inet_pton6(src, dst)); +#endif /* INET6 */ + default: + errno = EAFNOSUPPORT; + return (-1); + } + /* NOTREACHED */ +} + +/* int + * inet_pton4(src, dst, pton) + * when last arg is 0: inet_aton(). with hexadecimal, octal and shorthand. + * when last arg is 1: inet_pton(). decimal dotted-quad only. + * return: + * 1 if `src' is a valid input, else 0. + * notice: + * does not touch `dst' unless it's returning 1. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton4(const char *src, unsigned char *dst, int pton) +{ + uint32_t val; + unsigned int digit, base; + int n; + unsigned char c; + unsigned int parts[4]; + register unsigned int *pp = parts; + + c = *src; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, isdigit=decimal. + */ + if (!isdigit(c)) + return (0); + val = 0; base = 10; + if (c == '0') { + c = *++src; + if (c == 'x' || c == 'X') + base = 16, c = *++src; + else if (isdigit(c) && c != '9') + base = 8; + } + /* inet_pton() takes decimal only */ + if (pton && base != 10) + return (0); + for (;;) { + if (isdigit(c)) { + digit = c - '0'; + if (digit >= base) + break; + val = (val * base) + digit; + c = *++src; + } else if (base == 16 && isxdigit(c)) { + digit = c + 10 - (islower(c) ? 'a' : 'A'); + if (digit >= 16) + break; + val = (val << 4) | digit; + c = *++src; + } else + break; + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + * a (with a treated as 32 bits) + */ + if (pp >= parts + 3) + return (0); + *pp++ = val; + c = *++src; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && !isspace(c)) + return (0); + /* + * Concoct the address according to + * the number of parts specified. + */ + n = pp - parts + 1; + /* inet_pton() takes dotted-quad only. it does not take shorthand. */ + if (pton && n != 4) + return (0); + switch (n) { + + case 0: + return (0); /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (parts[0] > 0xff || val > 0xffffff) + return (0); + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if ((parts[0] | parts[1]) > 0xff || val > 0xffff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if ((parts[0] | parts[1] | parts[2] | val) > 0xff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + if (dst) { + val = htonl(val); + memcpy(dst, &val, NS_INADDRSZ); + } + return (1); +} + +#ifdef INET6 +/* int + * inet_pton6(src, dst) + * convert presentation level address to network order binary form. + * return: + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * notice: + * (1) does not touch `dst' unless it's returning 1. + * (2) :: in a full address is silently ignored. + * credit: + * inspired by Mark Andrews. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton6(const char *src, unsigned char *dst) +{ + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + unsigned int val; + + memset((tp = tmp), '\0', NS_IN6ADDRSZ); + endp = tp + NS_IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + return (0); + curtok = src; + saw_xdigit = 0; + val = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return (0); + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return (0); + colonp = tp; + continue; + } else if (*src == '\0') + return (0); + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (unsigned char) (val >> 8) & 0xff; + *tp++ = (unsigned char) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + inet_pton4(curtok, tp, 1) > 0) { + tp += NS_INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return (0); + } + if (saw_xdigit) { + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (unsigned char) (val >> 8) & 0xff; + *tp++ = (unsigned char) val & 0xff; + } + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + if (tp == endp) + return (0); + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + return (0); + memcpy(dst, tmp, NS_IN6ADDRSZ); + return (1); +} +#endif /* INET6 */ diff --git a/src/net_getaddrinfo.c b/src/net_getaddrinfo.c new file mode 100644 index 0000000..6ca5175 --- /dev/null +++ b/src/net_getaddrinfo.c @@ -0,0 +1,531 @@ +/* + * Copyright (c) 2015 Carsten Larsen + * Copyright (c) 2001, 02 Motoyuki Kasahara + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * This program provides getaddrinfo() and getnameinfo() described in + * RFC2133, 2553 and 3493. These functions are mainly used for IPv6 + * application to resolve hostname or address. + * + * This program is designed to be working on traditional IPv4 systems + * which don't have those functions. Therefore, this implementation + * supports IPv4 only. + * + * This program is useful for application which should support both IPv6 + * and traditional IPv4 systems. Use genuine getaddrinfo() and getnameinfo() + * provided by system if the system supports IPv6. Otherwise, use this + * implementation. + * + * This program also provides freeaddrinfo() and gai_strerror(). + * + * Restriction: + * getaddrinfo() and getnameinfo() of this program are NOT thread + * safe, unless the cpp macro ENABLE_PTHREAD is defined. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "net_getaddrinfo.h" + +#ifdef ENABLE_PTHREAD +#include +#endif + +#ifdef ENABLE_NLS +#include +#endif + +#ifdef ENABLE_NLS +#define _(string) gettext(string) +#ifdef gettext_noop +#define N_(string) gettext_noop(string) +#else +#define N_(string) (string) +#endif +#else +#define gettext(string) (string) +#define _(string) (string) +#define N_(string) (string) +#endif + +// NOTE: Quickfix +#include "clib/exec_protos.h" +extern struct Library *SocketBase; +#include "clib/amitcp_protos.h" + +/* + * Error messages for gai_strerror(). + */ +static char *eai_errlist[] = { + N_("Success"), + + /* EAI_ADDRFAMILY */ + N_("Address family for hostname not supported"), + + /* EAI_AGAIN */ + N_("Temporary failure in name resolution"), + + /* EAI_BADFLAGS */ + N_("Invalid value for ai_flags"), + + /* EAI_FAIL */ + N_("Non-recoverable failure in name resolution"), + + /* EAI_FAMILY */ + N_("ai_family not supported"), + + /* EAI_MEMORY */ + N_("Memory allocation failure"), + + /* EAI_NONAME */ + N_("hostname nor servname provided, or not known"), + + /* EAI_OVERFLOW */ + N_("An argument buffer overflowed"), + + /* EAI_SERVICE */ + N_("servname not supported for ai_socktype"), + + /* EAI_SOCKTYPE */ + N_("ai_socktype not supported"), + + /* EAI_SYSTEM */ + N_("System error returned in errno") +}; + +/* + * Default hints for getaddrinfo(). + */ +static struct addrinfo default_hints = { + 0, PF_UNSPEC, 0, 0, 0, NULL, NULL, NULL +}; + +/* + * Mutex. + */ +#ifdef ENABLE_PTHREAD +static pthread_mutex_t gai_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif + +/* + * Declaration of static functions. + */ +#ifdef __STDC__ +static int is_integer(const char *); +static int is_address(const char *); +static int itoa_length(int); +#else +static int is_integer(); +static int is_address(); +static int itoa_length(); +#endif + +/* + * gai_strerror(). + */ +const char * +gai_strerror(ecode) +int ecode; +{ + if (ecode < 0 || ecode > EAI_SYSTEM) + return _("Unknown error"); + + return gettext(eai_errlist[ecode]); +} + +/* + * freeaddrinfo(). + */ +void +freeaddrinfo(ai) +struct addrinfo *ai; +{ + struct addrinfo *next_ai; + + while (ai != NULL) { + if (ai->ai_canonname != NULL) + free(ai->ai_canonname); + if (ai->ai_addr != NULL) + free(ai->ai_addr); + next_ai = ai->ai_next; + free(ai); + ai = next_ai; + } +} + +/* + * Return 1 if the string `s' represents an integer. + */ +static int +is_integer(s) +const char *s; +{ + if (*s == '-' || *s == '+') + s++; + if (*s < '0' || '9' < *s) + return 0; + + s++; + while ('0' <= *s && *s <= '9') + s++; + + return (*s == '\0'); +} + +/* + * Return 1 if the string `s' represents an IPv4 address. + * Unlike inet_addr(), it doesn't permit malformed nortation such + * as "192.168". + */ +static int +is_address(s) +const char *s; +{ + const static char delimiters[] = {'.', '.', '.', '\0'}; + int i, j; + int octet; + + for (i = 0; i < 4; i++) { + if (*s == '0' && *(s + 1) != delimiters[i]) + return 0; + for (j = 0, octet = 0; '0' <= *s && *s <= '9' && j < 3; s++, j++) + octet = octet * 10 + (*s - '0'); + if (j == 0 || octet > 255 || *s != delimiters[i]) + return 0; + s++; + } + + return 1; +} + +/* + * Calcurate length of the string `s', where `s' is set by + * sprintf(s, "%d", n). + */ +static int +itoa_length(n) +int n; +{ + int result = 1; + + if (n < 0) { + n = -n; + result++; + } + + while (n >= 10) { + result++; + n /= 10; + } + + return result; +} + +/* + * getaddrinfo(). + */ +int +getaddrinfo(nodename, servname, hints, res) +const char *nodename; +const char *servname; +const struct addrinfo *hints; +struct addrinfo **res; +{ + struct addrinfo *head_res = NULL; + struct addrinfo *tail_res = NULL; + struct addrinfo *new_res; + struct sockaddr_in *sa_in; + struct in_addr **addr_list; + struct in_addr *addr_list_buf[2]; + struct in_addr addr_buf; + struct in_addr **ap; + struct servent *servent; + struct hostent *hostent; + const char *canonname = NULL; + in_port_t port; + int saved_h_errno; + int result = 0; + +#ifdef ENABLE_PTHREAD + pthread_mutex_lock(&gai_mutex); +#endif + + saved_h_errno = h_errno; + + if (nodename == NULL && servname == NULL) { + result = EAI_NONAME; + goto end; + } + + if (hints != NULL) { + if (hints->ai_family != PF_INET && hints->ai_family != PF_UNSPEC) { + result = EAI_FAMILY; + goto end; + } + if (hints->ai_socktype != SOCK_DGRAM + && hints->ai_socktype != SOCK_STREAM + && hints->ai_socktype != 0) { + result = EAI_SOCKTYPE; + goto end; + } + } else { + hints = &default_hints; + } + + if (servname != NULL) { + if (is_integer(servname)) + port = htons(atoi(servname)); + else { + if (hints->ai_flags & AI_NUMERICSERV) { + result = EAI_NONAME; + goto end; + } + + if (hints->ai_socktype == SOCK_DGRAM) + servent = getservbyname((char*)servname, (char*)"udp"); + else if (hints->ai_socktype == SOCK_STREAM) + servent = getservbyname((char*)servname, (char*)"tcp"); + else if (hints->ai_socktype == 0) + servent = getservbyname((char*)servname, (char*)"tcp"); + else { + result = EAI_SOCKTYPE; + goto end; + } + + if (servent == NULL) { + result = EAI_SERVICE; + goto end; + } + port = servent->s_port; + } + } else { + port = htons(0); + } + + if (nodename != NULL) { + if (is_address(nodename)) { + addr_buf.s_addr = inet_addr(nodename); + addr_list_buf[0] = &addr_buf; + addr_list_buf[1] = NULL; + addr_list = addr_list_buf; + + if (hints->ai_flags & AI_CANONNAME + && !(hints->ai_flags & AI_NUMERICHOST)) { + hostent = gethostbyaddr((char *)&addr_buf, + sizeof(struct in_addr), AF_INET); + if (hostent != NULL) + canonname = hostent->h_name; + else + canonname = nodename; + } + } else { + if (hints->ai_flags & AI_NUMERICHOST) { + result = EAI_NONAME; + goto end; + } + + hostent = gethostbyname(nodename); + if (hostent == NULL) { + switch (h_errno) { + case HOST_NOT_FOUND: + case NO_DATA: + result = EAI_NONAME; + goto end; + case TRY_AGAIN: + result = EAI_AGAIN; + goto end; + default: + result = EAI_FAIL; + goto end; + } + } + addr_list = (struct in_addr **)hostent->h_addr_list; + + if (hints->ai_flags & AI_CANONNAME) + canonname = hostent->h_name; + } + } else { + if (hints->ai_flags & AI_PASSIVE) + addr_buf.s_addr = htonl(INADDR_ANY); + else + addr_buf.s_addr = htonl(0x7F000001); + addr_list_buf[0] = &addr_buf; + addr_list_buf[1] = NULL; + addr_list = addr_list_buf; + } + + for (ap = addr_list; *ap != NULL; ap++) { + new_res = (struct addrinfo *)malloc(sizeof(struct addrinfo)); + if (new_res == NULL) { + if (head_res != NULL) + freeaddrinfo(head_res); + result = EAI_MEMORY; + goto end; + } + + new_res->ai_family = PF_INET; + new_res->ai_socktype = hints->ai_socktype; + new_res->ai_protocol = hints->ai_protocol; + new_res->ai_addr = NULL; + new_res->ai_addrlen = sizeof(struct sockaddr_in); + new_res->ai_canonname = NULL; + new_res->ai_next = NULL; + + new_res->ai_addr = (struct sockaddr *) + malloc(sizeof(struct sockaddr_in)); + if (new_res->ai_addr == NULL) { + free(new_res); + if (head_res != NULL) + freeaddrinfo(head_res); + result = EAI_MEMORY; + goto end; + } + + sa_in = (struct sockaddr_in *)new_res->ai_addr; + memset(sa_in, 0, sizeof(struct sockaddr_in)); + sa_in->sin_family = PF_INET; + sa_in->sin_port = port; + memcpy(&sa_in->sin_addr, *ap, sizeof(struct in_addr)); + + if (head_res == NULL) + head_res = new_res; + else + tail_res->ai_next = new_res; + tail_res = new_res; + } + + if (canonname != NULL && head_res != NULL) { + head_res->ai_canonname = (char *)malloc(strlen(canonname) + 1); + if (head_res->ai_canonname != NULL) + strcpy(head_res->ai_canonname, canonname); + } + + *res = head_res; + +end: + h_errno = saved_h_errno; +#ifdef ENABLE_PTHREAD + pthread_mutex_unlock(&gai_mutex); +#endif + return result; +} + +int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *node, socklen_t nodelen, char *serv, socklen_t servlen, int flags) { + + const struct sockaddr_in *sa_in = (const struct sockaddr_in *)sa; + struct hostent *hostent; + struct servent *servent; + char *ntoa_address; + int saved_h_errno; + int result = 0; + +#ifdef ENABLE_PTHREAD + pthread_mutex_lock(&gai_mutex); +#endif + + saved_h_errno = h_errno; + + if (sa_in->sin_family != PF_INET) { + result = EAI_FAMILY; + goto end; + } else if (node == NULL && serv == NULL) { + result = EAI_NONAME; + goto end; + } + + if (serv != NULL && servlen > 0) { + if (flags & NI_NUMERICSERV) + servent = NULL; + else if (flags & NI_DGRAM) + servent = getservbyport(sa_in->sin_port, "udp"); + else + servent = getservbyport(sa_in->sin_port, "tcp"); + + if (servent != NULL) { + if (servlen <= strlen(servent->s_name)) { + result = EAI_OVERFLOW; + goto end; + } + strcpy(serv, servent->s_name); + } else { + if (servlen <= itoa_length(ntohs(sa_in->sin_port))) { + result = EAI_OVERFLOW; + goto end; + } + sprintf(serv, "%d", ntohs(sa_in->sin_port)); + } + } + + if (node != NULL && nodelen > 0) { + if (flags & NI_NUMERICHOST) + hostent = NULL; + else { + hostent = gethostbyaddr((char *)&sa_in->sin_addr, + sizeof(struct in_addr), AF_INET); + } + if (hostent != NULL) { + if (nodelen <= strlen(hostent->h_name)) { + result = EAI_OVERFLOW; + goto end; + } + strcpy(node, hostent->h_name); + } else { + if (flags & NI_NAMEREQD) { + result = EAI_NONAME; + goto end; + } +#ifndef AOS3 + ntoa_address = inet_ntoa(sa_in->sin_addr); +#else + ntoa_address = inet_ntoa((LONG)sa_in->sin_addr.s_addr); +#endif + if (nodelen <= strlen(ntoa_address)) { + result = EAI_OVERFLOW; + goto end; + } + strcpy(node, ntoa_address); + } + + } + +end: + h_errno = saved_h_errno; +#ifdef ENABLE_PTHREAD + pthread_mutex_unlock(&gai_mutex); +#endif + return result; +} diff --git a/src/net_getaddrinfo.h b/src/net_getaddrinfo.h new file mode 100644 index 0000000..4781e0a --- /dev/null +++ b/src/net_getaddrinfo.h @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2015 Carsten Larsen + * Copyright (c) 2001, 02 Motoyuki Kasahara + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef GETADDRINFO_H +#define GETADDRINFO_H + +#include +#include + +/********************************************************************/ +/* + * Undefine all the macros. + * might defines some of them. + */ +#ifdef EAI_ADDRFAMILY +#undef EAI_ADDRFAMILY +#endif +#ifdef EAI_AGAIN +#undef EAI_AGAIN +#endif +#ifdef EAI_BADFLAGS +#undef EAI_BADFLAGS +#endif +#ifdef EAI_FAIL +#undef EAI_FAIL +#endif +#ifdef EAI_FAMILY +#undef EAI_FAMILY +#endif +#ifdef EAI_MEMORY +#undef EAI_MEMORY +#endif +#ifdef EAI_NONAME +#undef EAI_NONAME +#endif +#ifdef EAI_OVERFLOW +#undef EAI_OVERFLOW +#endif +#ifdef EAI_SERVICE +#undef EAI_SERVICE +#endif +#ifdef EAI_SOCKTYPE +#undef EAI_SOCKTYPE +#endif +#ifdef EAI_SYSTEM +#undef EAI_SYSTEM +#endif + +#ifdef AI_PASSIVE +#undef AI_PASSIVE +#endif +#ifdef AI_CANONNAME +#undef AI_CANONNAME +#endif +#ifdef AI_NUMERICHOST +#undef AI_NUMERICHOST +#endif +#ifdef AI_NUMERICSERV +#undef AI_NUMERICSERV +#endif +#ifdef AI_V4MAPPED +#undef AI_V4MAPPED +#endif +#ifdef AI_ALL +#undef AI_ALL +#endif +#ifdef AI_ADDRCONFIG +#undef AI_ADDRCONFIG +#endif +#ifdef AI_DEFAULT +#undef AI_DEFAULT +#endif + +#ifdef NI_NOFQDN +#undef NI_NOFQDN +#endif +#ifdef NI_NUMERICHOST +#undef NI_NUMERICHOST +#endif +#ifdef NI_NAMEREQD +#undef NI_NAMEREQD +#endif +#ifdef NI_NUMERICSERV +#undef NI_NUMERICSERV +#endif +#ifdef NI_NUMERICSCOPE +#undef NI_NUMERICSCOPE +#endif + +#ifdef NI_DGRAM +#undef NI_DGRAM +#endif +#ifdef NI_MAXHOST +#undef NI_MAXHOST +#endif +#ifdef NI_MAXSERV +#undef NI_MAXSERV +#endif + +/* + * Fake struct and function names. + * might declares all or some of them. + */ +/* +#if defined(HAVE_GETADDRINFO) || defined(HAVE_GETNAMEINFO) +#define addrinfo my_addrinfo +#define gai_strerror my_gai_strerror +#define freeaddrinfo my_freeaddrinfo +#define getaddrinfo my_getaddrinfo +#define getnameinfo my_getnameinfo +#endif +*/ + +/********************************************************************/ +/* + * Error codes. + */ +#define EAI_ADDRFAMILY 1 +#define EAI_AGAIN 2 +#define EAI_BADFLAGS 3 +#define EAI_FAIL 4 +#define EAI_FAMILY 5 +#define EAI_MEMORY 6 +#define EAI_NONAME 7 +#define EAI_OVERFLOW 8 +#define EAI_SERVICE 9 +#define EAI_SOCKTYPE 10 +#define EAI_SYSTEM 11 + +/* + * Flags for getaddrinfo(). + */ +#define AI_ADDRCONFIG 0x0001 +#define AI_ALL 0x0002 +#define AI_CANONNAME 0x0004 +#define AI_NUMERICHOST 0x0008 +#define AI_NUMERICSERV 0x0010 +#define AI_PASSIVE 0x0020 +#define AI_V4MAPPED 0x0040 +#define AI_DEFAULT (AI_V4MAPPED | AI_ADDRCONFIG) + +/* + * Flags for getnameinfo(). + */ +#define NI_DGRAM 0x0001 +#define NI_NAMEREQD 0x0002 +#define NI_NOFQDN 0x0004 +#define NI_NUMERICHOST 0x0008 +#define NI_NUMERICSCOPE 0x0010 +#define NI_NUMERICSERV 0x0020 + +/* + * Maximum length of FQDN and servie name for getnameinfo(). + */ +#define NI_MAXHOST 1025 +#define NI_MAXSERV 32 + +/* + * Address families and Protocol families. + */ +#ifndef AF_UNSPEC +#define AF_UNSPEC AF_INET +#endif +#ifndef PF_UNSPEC +#define PF_UNSPEC PF_INET +#endif + +#ifdef AOS3 +/* + * struct addrinfo. + */ +struct addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + socklen_t ai_addrlen; + char *ai_canonname; + struct sockaddr *ai_addr; + struct addrinfo *ai_next; +}; +#endif + +// NOTE: Quickfix +#include +typedef u_int16_t in_port_t; +typedef unsigned int sa_family_t; + +const char* gai_strerror(int); +void freeaddrinfo(struct addrinfo *); +int getaddrinfo(const char *, const char *, const struct addrinfo *, struct addrinfo **); +int getnameinfo(const struct sockaddr *, socklen_t, char *, socklen_t, char *, socklen_t, int); + +#endif