Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
aa1b9df2cb | ||
|
f3af1239a9 | ||
|
1da09e49e5 | ||
|
a8e8cced6d | ||
|
2efe207dde | ||
|
5d7715551d | ||
|
5d9148a900 | ||
|
4f7363efbc | ||
|
173b90368e | ||
|
5f433adfed | ||
|
52cbc8f87d | ||
|
c8bfdc15e6 | ||
|
5526afb56d | ||
|
be4efc0fd5 | ||
|
ab4fb353b6 | ||
|
5ecd5ac51d | ||
|
d888e4ebf4 | ||
|
1c265b9628 | ||
|
346474a43b | ||
|
ce655fdac8 |
12
Makefile
12
Makefile
@@ -15,12 +15,15 @@ sysconfdir=$(prefix)/etc
|
||||
|
||||
SRCS = $(sort $(wildcard src/*.c))
|
||||
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/hostentdb.o src/hash.o
|
||||
|
||||
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 =
|
||||
PIC = -fPIC
|
||||
AR = $(CROSS_COMPILE)ar
|
||||
@@ -30,8 +33,6 @@ LDSO_SUFFIX = so
|
||||
LD_SET_SONAME = -Wl,-soname=
|
||||
INSTALL_FLAGS = -D -m
|
||||
|
||||
-include config.mak
|
||||
|
||||
LDSO_PATHNAME = libproxychains4.$(LDSO_SUFFIX)
|
||||
|
||||
SHARED_LIBS = $(LDSO_PATHNAME)
|
||||
@@ -39,6 +40,7 @@ ALL_LIBS = $(SHARED_LIBS)
|
||||
PXCHAINS = proxychains4
|
||||
ALL_TOOLS = $(PXCHAINS)
|
||||
|
||||
-include config.mak
|
||||
|
||||
CFLAGS+=$(USER_CFLAGS) $(MAC_CFLAGS)
|
||||
CFLAGS_MAIN=-DLIB_DIR=\"$(libdir)\" -DSYSCONFDIR=\"$(sysconfdir)\" -DDLL_NAME=\"$(LDSO_PATHNAME)\"
|
||||
@@ -70,4 +72,4 @@ $(ALL_TOOLS): $(OBJS)
|
||||
$(CC) src/main.o src/common.o -o $(PXCHAINS)
|
||||
|
||||
|
||||
.PHONY: all clean install
|
||||
.PHONY: all clean install install-config
|
||||
|
69
README
69
README
@@ -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
|
||||
in dynamically linked programs via a preloaded DLL and redirects the
|
||||
connections through SOCKS4a/5 or HTTP proxies.
|
||||
in DYNAMICALLY LINKED programs via a preloaded DLL (dlsym(), LD_PRELOAD)
|
||||
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 ***********
|
||||
|
||||
this program works only on dynamically linked programs.
|
||||
also both proxychains and the program to call must use
|
||||
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.
|
||||
this program can be used to circumvent censorship.
|
||||
doing so can be VERY DANGEROUS in certain countries.
|
||||
|
||||
*********************************
|
||||
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 ***
|
||||
|
||||
# needs a working C compiler, preferably gcc
|
||||
./configure
|
||||
./configure --prefix=/usr --sysconfdir=/etc
|
||||
make
|
||||
[optional] sudo make install
|
||||
[optional] sudo make install-config (installs proxychains.conf)
|
||||
|
||||
if you dont install, you can use proxychains from the build directory
|
||||
like this: ./proxychains4 -f src/proxychains.conf telnet google.com 80
|
||||
@@ -29,6 +53,14 @@ ProxyChains ver 4.3 README
|
||||
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:
|
||||
- fixes programs that do dns-lookups in child processes (fork()ed),
|
||||
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 ).
|
||||
exact order (as they appear in the list )
|
||||
dynamic order (smart exclude dead proxies from chain)
|
||||
* You can use it with any TCP client application, even network scanners
|
||||
yes, yes - you can make portscan via proxy (or chained proxies)
|
||||
for example with Nmap scanner by fyodor (www.insecire.org/nmap).
|
||||
proxychains nmap -sT -PO -p 80 -iR (find some webservers through proxy)
|
||||
* You can use it with most TCP client applications, possibly even network
|
||||
scanners, as long as they use standard libc functionality.
|
||||
pcap based scanning does not work.
|
||||
* You can use it with servers, like squid, sendmail, or whatever.
|
||||
* DNS resolving through proxy.
|
||||
|
||||
@@ -90,13 +121,13 @@ Configuration:
|
||||
--------------
|
||||
|
||||
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.
|
||||
2) ./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:
|
||||
|
||||
|
11
configure
vendored
11
configure
vendored
@@ -34,7 +34,11 @@ parsearg() {
|
||||
}
|
||||
|
||||
ismac() {
|
||||
uname -s | grep Darwin
|
||||
uname -s | grep Darwin >/dev/null
|
||||
}
|
||||
|
||||
isbsd() {
|
||||
uname -s | grep BSD >/dev/null
|
||||
}
|
||||
|
||||
while true ; do
|
||||
@@ -78,10 +82,15 @@ echo libdir=$libdir>>config.mak
|
||||
echo includedir=$includedir>>config.mak
|
||||
echo sysconfdir=$sysconfdir>>config.mak
|
||||
if ismac ; then
|
||||
echo NO_AS_NEEDED=>>config.mak
|
||||
echo LDSO_SUFFIX=dylib>>config.mak
|
||||
echo MAC_CFLAGS+=-DIS_MAC=1>>config.mak
|
||||
echo LD_SET_SONAME=-Wl,-install_name,>>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
|
||||
|
||||
echo done, now run make \&\& make install
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <errno.h>
|
||||
#include "allocator_thread.h"
|
||||
#include "shm.h"
|
||||
#include "debug.h"
|
||||
@@ -147,8 +148,8 @@ struct at_msghdr {
|
||||
|
||||
static pthread_t allocator_thread;
|
||||
static pthread_attr_t allocator_thread_attr;
|
||||
static int req_pipefd[2];
|
||||
static int resp_pipefd[2];
|
||||
int req_pipefd[2];
|
||||
int resp_pipefd[2];
|
||||
|
||||
static int wait_data(int readfd) {
|
||||
PFUNC();
|
||||
@@ -158,7 +159,13 @@ static int wait_data(int readfd) {
|
||||
int ret;
|
||||
while((ret = select(readfd+1, &fds, NULL, NULL, NULL)) <= 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;
|
||||
}
|
||||
}
|
||||
|
@@ -6,10 +6,14 @@
|
||||
|
||||
#define MSG_LEN_MAX 256
|
||||
|
||||
extern int req_pipefd[2];
|
||||
extern int resp_pipefd[2];
|
||||
|
||||
void at_init(void);
|
||||
void at_close(void);
|
||||
size_t at_get_host_for_ip(ip_type ip, char* readbuf);
|
||||
ip_type at_get_ip_for_host(char* host, size_t len);
|
||||
|
||||
//RcB: DEP "allocator_thread.c"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@@ -82,6 +82,7 @@ int connect_proxy_chain (int sock, ip_type target_ip, unsigned short target_port
|
||||
|
||||
void proxychains_write_log(char *str, ...);
|
||||
|
||||
typedef int (*close_t)(int);
|
||||
typedef int (*connect_t)(int, const struct sockaddr *, socklen_t);
|
||||
typedef struct hostent* (*gethostbyname_t)(const char *);
|
||||
typedef int (*freeaddrinfo_t)(struct addrinfo *);
|
||||
@@ -123,4 +124,5 @@ void core_unload(void);
|
||||
|
||||
//RcB: DEP "core.c"
|
||||
//RcB: DEP "libproxychains.c"
|
||||
//RcB: LINK "-Wl,--no-as-needed -ldl -lpthread"
|
||||
//RcB: LINK "-Wl,--no-as-needed -ldl -lpthread"
|
||||
|
||||
|
@@ -10,4 +10,5 @@
|
||||
|
||||
# define PFUNC() do { PDEBUG("pid[%d]:%s\n", getpid(), __FUNCTION__); } while(0)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@@ -2,6 +2,8 @@
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
#include <stdlib.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "ip_type.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) {
|
||||
#ifndef IS_BSD
|
||||
struct hostent* hp;
|
||||
while((hp = gethostent()))
|
||||
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])) });
|
||||
}
|
||||
#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) {
|
||||
@@ -53,4 +60,4 @@ ip_type hdb_get(struct hostent_list *hl, char* host) {
|
||||
}
|
||||
}
|
||||
return ip_type_invalid;
|
||||
}
|
||||
}
|
||||
|
@@ -45,6 +45,7 @@
|
||||
#define SOCKFAMILY(x) (satosin(x)->sin_family)
|
||||
#define MAX_CHAIN 512
|
||||
|
||||
close_t true_close;
|
||||
connect_t true_connect;
|
||||
gethostbyname_t true_gethostbyname;
|
||||
getaddrinfo_t true_getaddrinfo;
|
||||
@@ -113,6 +114,7 @@ static void do_init(void) {
|
||||
SETUP_SYM(freeaddrinfo);
|
||||
SETUP_SYM(gethostbyaddr);
|
||||
SETUP_SYM(getnameinfo);
|
||||
SETUP_SYM(close);
|
||||
|
||||
init_l = 1;
|
||||
}
|
||||
@@ -282,6 +284,16 @@ static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_typ
|
||||
|
||||
/******* 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) {
|
||||
PFUNC();
|
||||
int socktype = 0, flags = 0, ret = 0;
|
||||
@@ -381,32 +393,31 @@ void freeaddrinfo(struct addrinfo *res) {
|
||||
return;
|
||||
}
|
||||
|
||||
// work around a buggy prototype in GLIBC. according to the bugtracker it has been fixed in git at 02 May 2011.
|
||||
// 2.14 came out in June 2011 so that should be the first fixed version
|
||||
#if defined(__GLIBC__) && (__GLIBC__ < 3) && (__GLIBC_MINOR__ < 14)
|
||||
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
|
||||
int pc_getnameinfo(const struct sockaddr *sa, socklen_t salen,
|
||||
char *host, socklen_t hostlen, char *serv,
|
||||
socklen_t servlen, int flags)
|
||||
{
|
||||
char ip_buf[16];
|
||||
int ret = 0;
|
||||
|
||||
INIT();
|
||||
|
||||
PDEBUG("getnameinfo: %s %s\n", host, serv);
|
||||
PFUNC();
|
||||
|
||||
if(!proxychains_resolver) {
|
||||
ret = true_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
|
||||
} else {
|
||||
if(salen < sizeof(struct sockaddr_in) || SOCKFAMILY(*sa) != AF_INET)
|
||||
return EAI_FAMILY;
|
||||
if(hostlen) {
|
||||
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;
|
||||
}
|
||||
|
13
src/nameinfo.c
Normal file
13
src/nameinfo.c
Normal 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);
|
||||
}
|
||||
|
@@ -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 "$@"
|
@@ -1,8 +1,10 @@
|
||||
#!/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=4.2.2.2
|
||||
DNS_SERVER=8.8.8.8
|
||||
|
||||
|
||||
if [ $# = 0 ] ; then
|
||||
@@ -12,5 +14,5 @@ if [ $# = 0 ] ; then
|
||||
fi
|
||||
|
||||
|
||||
export LD_PRELOAD=libproxychains.so
|
||||
dig $1 @$DNS_SERVER +tcp | awk '/A.+[0-9]+\.[0-9]+\.[0-9]/{print $5;}'
|
||||
export LD_PRELOAD=libproxychains4.so
|
||||
dig $1 @$DNS_SERVER +tcp | awk '/A.?[0-9]+\.[0-9]+\.[0-9]/{print $5;}'
|
||||
|
83
tests/test_getnameinfo.c
Normal file
83
tests/test_getnameinfo.c
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user