1
0
mirror of https://github.com/rofl0r/proxychains-ng synced 2026-05-15 18:12:34 +08:00

Compare commits

...

26 Commits

14 changed files with 244 additions and 83 deletions
+12 -10
View File
@@ -15,12 +15,15 @@ sysconfdir=$(prefix)/etc
SRCS = $(sort $(wildcard src/*.c)) SRCS = $(sort $(wildcard src/*.c))
OBJS = $(SRCS:.c=.o) OBJS = $(SRCS:.c=.o)
LOBJS = src/core.o src/common.o src/libproxychains.o src/shm.o \ LOBJS = src/nameinfo.o \
src/core.o src/common.o src/libproxychains.o src/shm.o \
src/allocator_thread.o src/ip_type.o src/stringdump.o \ src/allocator_thread.o src/ip_type.o src/stringdump.o \
src/hostentdb.o src/hash.o src/hostentdb.o src/hash.o
CFLAGS += -Wall -O0 -g -std=c99 -D_GNU_SOURCE -pipe CFLAGS += -Wall -O0 -g -std=c99 -D_GNU_SOURCE -pipe
LDFLAGS = -shared -fPIC -Wl,--no-as-needed -ldl -lpthread NO_AS_NEEDED = -Wl,--no-as-needed
LIBDL = -ldl
LDFLAGS = -shared -fPIC $(NO_AS_NEEDED) $(LIBDL) -lpthread
INC = INC =
PIC = -fPIC PIC = -fPIC
AR = $(CROSS_COMPILE)ar AR = $(CROSS_COMPILE)ar
@@ -30,8 +33,6 @@ LDSO_SUFFIX = so
LD_SET_SONAME = -Wl,-soname= LD_SET_SONAME = -Wl,-soname=
INSTALL_FLAGS = -D -m INSTALL_FLAGS = -D -m
-include config.mak
LDSO_PATHNAME = libproxychains4.$(LDSO_SUFFIX) LDSO_PATHNAME = libproxychains4.$(LDSO_SUFFIX)
SHARED_LIBS = $(LDSO_PATHNAME) SHARED_LIBS = $(LDSO_PATHNAME)
@@ -39,6 +40,7 @@ ALL_LIBS = $(SHARED_LIBS)
PXCHAINS = proxychains4 PXCHAINS = proxychains4
ALL_TOOLS = $(PXCHAINS) ALL_TOOLS = $(PXCHAINS)
-include config.mak
CFLAGS+=$(USER_CFLAGS) $(MAC_CFLAGS) CFLAGS+=$(USER_CFLAGS) $(MAC_CFLAGS)
CFLAGS_MAIN=-DLIB_DIR=\"$(libdir)\" -DSYSCONFDIR=\"$(sysconfdir)\" -DDLL_NAME=\"$(LDSO_PATHNAME)\" CFLAGS_MAIN=-DLIB_DIR=\"$(libdir)\" -DSYSCONFDIR=\"$(sysconfdir)\" -DDLL_NAME=\"$(LDSO_PATHNAME)\"
@@ -47,13 +49,13 @@ CFLAGS_MAIN=-DLIB_DIR=\"$(libdir)\" -DSYSCONFDIR=\"$(sysconfdir)\" -DDLL_NAME=\"
all: $(ALL_LIBS) $(ALL_TOOLS) all: $(ALL_LIBS) $(ALL_TOOLS)
install-config: install-config:
install -d $(DESTDIR)/$(sysconfdir) install -d $(DESTDIR)$(sysconfdir)
install $(INSTALL_FLAGS) 644 src/proxychains.conf $(DESTDIR)/$(sysconfdir)/ install $(INSTALL_FLAGS) 644 src/proxychains.conf $(DESTDIR)$(sysconfdir)/
install: install:
install -d $(DESTDIR)/$(bindir)/ $(DESTDIR)/$(libdir)/ install -d $(DESTDIR)$(bindir)/ $(DESTDIR)$(libdir)/
install $(INSTALL_FLAGS) 755 $(ALL_TOOLS) $(DESTDIR)/$(bindir)/ install $(INSTALL_FLAGS) 755 $(ALL_TOOLS) $(DESTDIR)$(bindir)/
install $(INSTALL_FLAGS) 644 $(ALL_LIBS) $(DESTDIR)/$(libdir)/ install $(INSTALL_FLAGS) 644 $(ALL_LIBS) $(DESTDIR)$(libdir)/
clean: clean:
rm -f $(ALL_LIBS) rm -f $(ALL_LIBS)
@@ -70,4 +72,4 @@ $(ALL_TOOLS): $(OBJS)
$(CC) src/main.o src/common.o -o $(PXCHAINS) $(CC) src/main.o src/common.o -o $(PXCHAINS)
.PHONY: all clean install .PHONY: all clean install install-config
+54 -19
View File
@@ -1,27 +1,51 @@
ProxyChains ver 4.3 README ProxyChains-NG ver 4.5 README
========================== =============================
ProxyChains is a UNIX program, that hooks network-related libc functions ProxyChains is a UNIX program, that hooks network-related libc functions
in dynamically linked programs via a preloaded DLL and redirects the in DYNAMICALLY LINKED programs via a preloaded DLL (dlsym(), LD_PRELOAD)
connections through SOCKS4a/5 or HTTP proxies. and redirects the connections through SOCKS4a/5 or HTTP proxies.
It supports TCP only (no UDP/ICMP etc).
The way it works is basically a HACK; so it is possible that it doesn't
work with your program, especially when it's a script, or starts
numerous processes like background daemons or uses dlopen() to load
"modules" (bug in glibc dynlinker).
It should work with simple compiled (C/C++) dynamically linked programs
though.
If your program doesn't work with proxychains, consider using an
iptables based solution instead; this is much more robust.
Supported Platforms: Linux, BSD, Mac.
*********** ATTENTION *********** *********** ATTENTION ***********
this program works only on dynamically linked programs. this program can be used to circumvent censorship.
also both proxychains and the program to call must use doing so can be VERY DANGEROUS in certain countries.
the same dynamic linker (i.e. same libc).
why ? because in order to hook to libc functions like
connect(), dynamic loader facilities are used, namely
dl_sym() and LD_PRELOAD.
********************************* ALWAYS MAKE SURE THAT PROXYCHAINS WORKS AS EXPECTED
BEFORE USING IT FOR ANYTHING SERIOUS.
this involves both the program and the proxy that you're going to
use.
for example, you can connect to some "what is my ip" service
like ifconfig.me to make sure that it's not using your real ip.
ONLY USE PROXYCHAINS IF YOU KNOW WHAT YOU'RE DOING.
THE AUTHORS AND MAINTAINERS OF PROXYCHAINS DO NOT TAKE ANY
RESPONSIBILITY FOR ANY ABUSE OR MISUSE OF THIS SOFTWARE AND
THE RESULTING CONSEQUENCES.
*** Installation *** *** Installation ***
# needs a working C compiler, preferably gcc # needs a working C compiler, preferably gcc
./configure ./configure --prefix=/usr --sysconfdir=/etc
make make
[optional] sudo make install [optional] sudo make install
[optional] sudo make install-config (installs proxychains.conf)
if you dont install, you can use proxychains from the build directory if you dont install, you can use proxychains from the build directory
like this: ./proxychains4 -f src/proxychains.conf telnet google.com 80 like this: ./proxychains4 -f src/proxychains.conf telnet google.com 80
@@ -29,6 +53,14 @@ ProxyChains ver 4.3 README
Changelog: Changelog:
---------- ----------
Version 4.5:
- hook close() to prevent OpenSSH from messing with internal infrastructure.
this caused ssh client to segfault when proxified.
Version 4.4:
- FreeBSD port
- fixes some installation issues on Debian and Mac.
Version 4.3: Version 4.3:
- fixes programs that do dns-lookups in child processes (fork()ed), - fixes programs that do dns-lookups in child processes (fork()ed),
like irssi. to achieve this, support for compilation without pthreads like irssi. to achieve this, support for compilation without pthreads
@@ -78,10 +110,9 @@ Some cool features:
random order from the list ( user defined length of chain ). random order from the list ( user defined length of chain ).
exact order (as they appear in the list ) exact order (as they appear in the list )
dynamic order (smart exclude dead proxies from chain) dynamic order (smart exclude dead proxies from chain)
* You can use it with any TCP client application, even network scanners * You can use it with most TCP client applications, possibly even network
yes, yes - you can make portscan via proxy (or chained proxies) scanners, as long as they use standard libc functionality.
for example with Nmap scanner by fyodor (www.insecire.org/nmap). pcap based scanning does not work.
proxychains nmap -sT -PO -p 80 -iR (find some webservers through proxy)
* You can use it with servers, like squid, sendmail, or whatever. * You can use it with servers, like squid, sendmail, or whatever.
* DNS resolving through proxy. * DNS resolving through proxy.
@@ -90,13 +121,13 @@ Configuration:
-------------- --------------
proxychains looks for config file in following order: proxychains looks for config file in following order:
1) file listed in environment variable ${PROXYCHAINS_CONF_FILE} or 1) file listed in environment variable PROXYCHAINS_CONF_FILE or
provided as a -f argument to proxychains script or binary. provided as a -f argument to proxychains script or binary.
2) ./proxychains.conf 2) ./proxychains.conf
3) $(HOME)/.proxychains/proxychains.conf 3) $(HOME)/.proxychains/proxychains.conf
4) /etc/proxychains.conf ** 4) $(sysconfdir)/proxychains.conf **
**see more in /etc/proxychains.conf ** usually /etc/proxychains.conf
Usage Example: Usage Example:
@@ -119,3 +150,7 @@ Usage Example:
in this example it will resolve targethost.com through proxy(or chained proxies) in this example it will resolve targethost.com through proxy(or chained proxies)
specified by proxychains.conf specified by proxychains.conf
Community:
----------
#proxychains on irc.freenode.net
Vendored
+10 -1
View File
@@ -34,7 +34,11 @@ parsearg() {
} }
ismac() { ismac() {
uname -s | grep Darwin uname -s | grep Darwin >/dev/null
}
isbsd() {
uname -s | grep BSD >/dev/null
} }
while true ; do while true ; do
@@ -78,10 +82,15 @@ echo libdir=$libdir>>config.mak
echo includedir=$includedir>>config.mak echo includedir=$includedir>>config.mak
echo sysconfdir=$sysconfdir>>config.mak echo sysconfdir=$sysconfdir>>config.mak
if ismac ; then if ismac ; then
echo NO_AS_NEEDED=>>config.mak
echo LDSO_SUFFIX=dylib>>config.mak echo LDSO_SUFFIX=dylib>>config.mak
echo MAC_CFLAGS+=-DIS_MAC=1>>config.mak echo MAC_CFLAGS+=-DIS_MAC=1>>config.mak
echo LD_SET_SONAME=-Wl,-install_name,>>config.mak echo LD_SET_SONAME=-Wl,-install_name,>>config.mak
echo INSTALL_FLAGS=-m>>config.mak echo INSTALL_FLAGS=-m>>config.mak
elif isbsd ; then
echo LIBDL=>>config.mak
echo "CFLAGS+=-DIS_BSD">>config.mak
echo INSTALL_FLAGS=-m>>config.mak
fi fi
echo done, now run make \&\& make install echo done, now run make \&\& make install
+10 -3
View File
@@ -8,6 +8,7 @@
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <errno.h>
#include "allocator_thread.h" #include "allocator_thread.h"
#include "shm.h" #include "shm.h"
#include "debug.h" #include "debug.h"
@@ -147,8 +148,8 @@ struct at_msghdr {
static pthread_t allocator_thread; static pthread_t allocator_thread;
static pthread_attr_t allocator_thread_attr; static pthread_attr_t allocator_thread_attr;
static int req_pipefd[2]; int req_pipefd[2];
static int resp_pipefd[2]; int resp_pipefd[2];
static int wait_data(int readfd) { static int wait_data(int readfd) {
PFUNC(); PFUNC();
@@ -158,7 +159,13 @@ static int wait_data(int readfd) {
int ret; int ret;
while((ret = select(readfd+1, &fds, NULL, NULL, NULL)) <= 0) { while((ret = select(readfd+1, &fds, NULL, NULL, NULL)) <= 0) {
if(ret < 0) { if(ret < 0) {
perror("select2"); int e = errno;
if(e == EINTR) continue;
#ifdef __GLIBC__
char emsg[1024];
char* x = strerror_r(errno, emsg, sizeof emsg);
dprintf(2, "select2: %s\n", x);
#endif
return 0; return 0;
} }
} }
+5 -1
View File
@@ -6,10 +6,14 @@
#define MSG_LEN_MAX 256 #define MSG_LEN_MAX 256
extern int req_pipefd[2];
extern int resp_pipefd[2];
void at_init(void); void at_init(void);
void at_close(void); void at_close(void);
size_t at_get_host_for_ip(ip_type ip, char* readbuf); size_t at_get_host_for_ip(ip_type ip, char* readbuf);
ip_type at_get_ip_for_host(char* host, size_t len); ip_type at_get_ip_for_host(char* host, size_t len);
//RcB: DEP "allocator_thread.c" //RcB: DEP "allocator_thread.c"
#endif #endif
+3 -1
View File
@@ -82,6 +82,7 @@ int connect_proxy_chain (int sock, ip_type target_ip, unsigned short target_port
void proxychains_write_log(char *str, ...); void proxychains_write_log(char *str, ...);
typedef int (*close_t)(int);
typedef int (*connect_t)(int, const struct sockaddr *, socklen_t); typedef int (*connect_t)(int, const struct sockaddr *, socklen_t);
typedef struct hostent* (*gethostbyname_t)(const char *); typedef struct hostent* (*gethostbyname_t)(const char *);
typedef int (*freeaddrinfo_t)(struct addrinfo *); typedef int (*freeaddrinfo_t)(struct addrinfo *);
@@ -123,4 +124,5 @@ void core_unload(void);
//RcB: DEP "core.c" //RcB: DEP "core.c"
//RcB: DEP "libproxychains.c" //RcB: DEP "libproxychains.c"
//RcB: LINK "-Wl,--no-as-needed -ldl -lpthread" //RcB: LINK "-Wl,--no-as-needed -ldl -lpthread"
+2 -1
View File
@@ -10,4 +10,5 @@
# define PFUNC() do { PDEBUG("pid[%d]:%s\n", getpid(), __FUNCTION__); } while(0) # define PFUNC() do { PDEBUG("pid[%d]:%s\n", getpid(), __FUNCTION__); } while(0)
#endif #endif
+8 -1
View File
@@ -2,6 +2,8 @@
#include <string.h> #include <string.h>
#include <netdb.h> #include <netdb.h>
#include <stdlib.h> #include <stdlib.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "ip_type.h" #include "ip_type.h"
#include "hash.h" #include "hash.h"
@@ -26,11 +28,16 @@ static void hdb_add(struct hostent_list* hl, char* host, ip_type ip) {
} }
static void hdb_fill(struct hostent_list *hl) { static void hdb_fill(struct hostent_list *hl) {
#ifndef IS_BSD
struct hostent* hp; struct hostent* hp;
while((hp = gethostent())) while((hp = gethostent()))
if(hp->h_addrtype == AF_INET && hp->h_length == sizeof(in_addr_t)) { if(hp->h_addrtype == AF_INET && hp->h_length == sizeof(in_addr_t)) {
hdb_add(hl, hp->h_name, (ip_type) { .as_int = *((in_addr_t*)(hp->h_addr_list[0])) }); hdb_add(hl, hp->h_name, (ip_type) { .as_int = *((in_addr_t*)(hp->h_addr_list[0])) });
} }
#else
/* FreeBSD hangs on gethostent(). since this feature is not crucial, we just do nothing */
(void) hl;
#endif
} }
void hdb_init(struct hostent_list *hl) { void hdb_init(struct hostent_list *hl) {
@@ -53,4 +60,4 @@ ip_type hdb_get(struct hostent_list *hl, char* host) {
} }
} }
return ip_type_invalid; return ip_type_invalid;
} }
+35 -15
View File
@@ -45,6 +45,7 @@
#define SOCKFAMILY(x) (satosin(x)->sin_family) #define SOCKFAMILY(x) (satosin(x)->sin_family)
#define MAX_CHAIN 512 #define MAX_CHAIN 512
close_t true_close;
connect_t true_connect; connect_t true_connect;
gethostbyname_t true_gethostbyname; gethostbyname_t true_gethostbyname;
getaddrinfo_t true_getaddrinfo; getaddrinfo_t true_getaddrinfo;
@@ -113,6 +114,7 @@ static void do_init(void) {
SETUP_SYM(freeaddrinfo); SETUP_SYM(freeaddrinfo);
SETUP_SYM(gethostbyaddr); SETUP_SYM(gethostbyaddr);
SETUP_SYM(getnameinfo); SETUP_SYM(getnameinfo);
SETUP_SYM(close);
init_l = 1; init_l = 1;
} }
@@ -166,7 +168,11 @@ static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_typ
*ct = DYNAMIC_TYPE; *ct = DYNAMIC_TYPE;
env = get_config_path(getenv(PROXYCHAINS_CONF_FILE_ENV_VAR), buff, sizeof(buff)); env = get_config_path(getenv(PROXYCHAINS_CONF_FILE_ENV_VAR), buff, sizeof(buff));
file = fopen(env, "r"); if( ( file = fopen(env, "r") ) == NULL )
{
perror("couldnt read configuration file");
exit(1);
}
env = getenv(PROXYCHAINS_QUIET_MODE_ENV_VAR); env = getenv(PROXYCHAINS_QUIET_MODE_ENV_VAR);
if(env && *env == '1') if(env && *env == '1')
@@ -186,7 +192,12 @@ static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_typ
sscanf(buff, "%s %s %d %s %s", type, host, &port_n, pd[count].user, pd[count].pass); sscanf(buff, "%s %s %d %s %s", type, host, &port_n, pd[count].user, pd[count].pass);
pd[count].ip.as_int = (uint32_t) inet_addr(host); in_addr_t host_ip = inet_addr(host);
if(host_ip == INADDR_NONE) {
fprintf(stderr, "proxy %s has invalid value or is not numeric\n", host);
exit(1);
}
pd[count].ip.as_int = (uint32_t) host_ip;
pd[count].port = htons((unsigned short) port_n); pd[count].port = htons((unsigned short) port_n);
if(!strcmp(type, "http")) { if(!strcmp(type, "http")) {
@@ -282,6 +293,16 @@ static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_typ
/******* HOOK FUNCTIONS *******/ /******* HOOK FUNCTIONS *******/
int close(int fd) {
/* prevent rude programs (like ssh) from closing our pipes */
if(fd != req_pipefd[0] && fd != req_pipefd[1] &&
fd != resp_pipefd[0] && fd != resp_pipefd[1]) {
return true_close(fd);
}
errno = EINTR;
return -1;
}
int connect(int sock, const struct sockaddr *addr, unsigned int len) { int connect(int sock, const struct sockaddr *addr, unsigned int len) {
PFUNC(); PFUNC();
int socktype = 0, flags = 0, ret = 0; int socktype = 0, flags = 0, ret = 0;
@@ -381,32 +402,31 @@ void freeaddrinfo(struct addrinfo *res) {
return; return;
} }
// work around a buggy prototype in GLIBC. according to the bugtracker it has been fixed in git at 02 May 2011. int pc_getnameinfo(const struct sockaddr *sa, socklen_t salen,
// 2.14 came out in June 2011 so that should be the first fixed version char *host, socklen_t hostlen, char *serv,
#if defined(__GLIBC__) && (__GLIBC__ < 3) && (__GLIBC_MINOR__ < 14) socklen_t servlen, int flags)
int getnameinfo(const struct sockaddr *sa,
socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, unsigned int flags)
#else
int getnameinfo(const struct sockaddr *sa,
socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags)
#endif
{ {
char ip_buf[16]; char ip_buf[16];
int ret = 0; int ret = 0;
INIT(); INIT();
PDEBUG("getnameinfo: %s %s\n", host, serv); PFUNC();
if(!proxychains_resolver) { if(!proxychains_resolver) {
ret = true_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); ret = true_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
} else { } else {
if(salen < sizeof(struct sockaddr_in) || SOCKFAMILY(*sa) != AF_INET)
return EAI_FAMILY;
if(hostlen) { if(hostlen) {
pc_stringfromipv4((unsigned char*) &(SOCKADDR_2(*sa)), ip_buf); pc_stringfromipv4((unsigned char*) &(SOCKADDR_2(*sa)), ip_buf);
strncpy(host, ip_buf, hostlen); if(snprintf(host, hostlen, "%s", ip_buf) >= hostlen)
return EAI_OVERFLOW;
}
if(servlen) {
if(snprintf(serv, servlen, "%d", ntohs(SOCKPORT(*sa))) >= servlen)
return EAI_OVERFLOW;
} }
if(servlen)
snprintf(serv, servlen, "%d", ntohs(SOCKPORT(*sa)));
} }
return ret; return ret;
} }
+13
View File
@@ -0,0 +1,13 @@
#include <sys/socket.h>
extern int pc_getnameinfo(const void *sa, socklen_t salen,
char *host, socklen_t hostlen, char *serv,
socklen_t servlen, int flags);
int getnameinfo(const void *sa, socklen_t salen,
char *host, socklen_t hostlen, char *serv,
socklen_t servlen, int flags) {
return pc_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
}
-26
View File
@@ -1,26 +0,0 @@
#!/bin/sh
echo "ProxyChains-3.1 (http://proxychains.sf.net)"
usage() {
echo " usage:"
echo " $0 [h] [f config-file] <prog> [args]"
exit
}
if [ $# = 0 ] ; then
usage
fi
if [ $1 = "-h" ]; then
usage
fi
if [ "$1" = "-f" ]; then
export PROXYCHAINS_CONF_FILE=$2;
shift;
shift;
fi
export LD_PRELOAD=libproxychains.so.3
exec "$@"
+3 -1
View File
@@ -77,9 +77,11 @@ tcp_connect_time_out 8000
# localnet 192.168.0.0/255.255.0.0 # localnet 192.168.0.0/255.255.0.0
# ProxyList format # ProxyList format
# type host port [user pass] # type ip port [user pass]
# (values separated by 'tab' or 'blank') # (values separated by 'tab' or 'blank')
# #
# only numeric ipv4 addresses are valid
#
# #
# Examples: # Examples:
# #
+6 -4
View File
@@ -1,8 +1,10 @@
#!/bin/sh #!/bin/sh
# This script is called by proxychains to resolve DNS names # This is a legacy script that uses "dig" to do DNS lookups via TCP.
# it is not actively maintained since proxychains no longer depends
# on it. i leave it here as a bonus.
# DNS server used to resolve names # DNS server used to resolve names
DNS_SERVER=4.2.2.2 DNS_SERVER=8.8.8.8
if [ $# = 0 ] ; then if [ $# = 0 ] ; then
@@ -12,5 +14,5 @@ if [ $# = 0 ] ; then
fi fi
export LD_PRELOAD=libproxychains.so export LD_PRELOAD=libproxychains4.so
dig $1 @$DNS_SERVER +tcp | awk '/A.+[0-9]+\.[0-9]+\.[0-9]/{print $5;}' dig $1 @$DNS_SERVER +tcp | awk '/A.?[0-9]+\.[0-9]+\.[0-9]/{print $5;}'
+83
View File
@@ -0,0 +1,83 @@
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define satosin(x) ((struct sockaddr_in *) &(x))
#define SOCKADDR(x) (satosin(x)->sin_addr.s_addr)
#define SOCKADDR_2(x) (satosin(x)->sin_addr)
#define SOCKPORT(x) (satosin(x)->sin_port)
#define SOCKFAMILY(x) (satosin(x)->sin_family)
int main() {
struct sockaddr a = {0}, *sa = &a;
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
SOCKPORT(a) = htons(80);
memcpy( &( (struct sockaddr_in*) sa ) ->sin_addr , (char[]) {127,0,0,1}, 4);
int ret;
if ((ret = getnameinfo(sa, 0, hbuf, sizeof(hbuf), sbuf,
sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) == 0)
printf("host=%s, serv=%s\n", hbuf, sbuf);
else
printf("%s\n", gai_strerror(ret));
assert(ret == EAI_FAMILY);
if ((ret = getnameinfo(sa, sizeof a, hbuf, sizeof(hbuf), sbuf,
sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) == 0)
printf("host=%s, serv=%s\n", hbuf, sbuf);
else
printf("%s\n", gai_strerror(ret));
assert(ret == EAI_FAMILY);
SOCKFAMILY(a) = AF_INET;
if ((ret = getnameinfo(sa, sizeof a, hbuf, 1, sbuf,
sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) == 0)
printf("host=%s, serv=%s\n", hbuf, sbuf);
else
printf("%s\n", gai_strerror(ret));
assert(ret == EAI_OVERFLOW);
if ((ret = getnameinfo(sa, sizeof a, hbuf, 0, sbuf,
1, NI_NUMERICHOST | NI_NUMERICSERV)) == 0)
printf("host=%s, serv=%s\n", hbuf, sbuf);
else
printf("%s\n", gai_strerror(ret));
assert(ret == EAI_OVERFLOW);
if ((ret = getnameinfo(sa, sizeof a, hbuf, 0, sbuf,
sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) == 0)
printf("host=%s, serv=%s\n", hbuf, sbuf);
else
printf("%s\n", gai_strerror(ret));
assert(ret == 0);
if ((ret = getnameinfo(sa, sizeof a, hbuf, sizeof hbuf, sbuf,
0, NI_NUMERICHOST | NI_NUMERICSERV)) == 0)
printf("host=%s, serv=%s\n", hbuf, sbuf);
else
printf("%s\n", gai_strerror(ret));
assert(ret == 0);
if ((ret = getnameinfo(sa, sizeof a, hbuf, sizeof(hbuf), sbuf,
sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) == 0)
printf("host=%s, serv=%s\n", hbuf, sbuf);
else
printf("%s\n", gai_strerror(ret));
assert(ret == 0);
return 0;
}