1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
--- lib/hostname.c.orig Wed Aug 16 09:38:40 2000
+++ lib/hostname.c Wed Aug 30 13:27:33 2000
@@ -17,6 +17,11 @@
#define S5_HOSTLIST_SIZE 256
#define S5_HOSTALIASES_SIZE 16
+/* wrapper for KAME-special getnameinfo() */
+#ifndef NI_WITHSCOPEID
+#define NI_WITHSCOPEID 0
+#endif
+
struct hostEntry {
char name[S5_HOSTNAME_SIZE];
};
@@ -398,6 +403,129 @@
lsInWrapFunction = 0;
lsInWrapHostname = 0;
return &h;
+}
+#endif
+
+#if defined(HAVE_GETADDRINFO) && defined(HAVE_GETNAMEINFO)
+/* wrapper around the getaddrinfo call. */
+/* similar to getaddrinfo() except for: */
+/* *** if getaddrinfo() fails, then it returns a pointer to a addrinfo */
+/* structure filled with a special value, so that SOCKSxxxxxx() will */
+/* realize that this host was unresolved and fill in the protocol */
+/* accordingly... */
+/* */
+/* returns an error number on failure; 0 on success */
+int LIBPREFIX(getaddrinfo)(const char *hostname, const char *servname,
+ const struct addrinfo *hints,
+ struct addrinfo **aip) {
+ static char numaddrbuf[MAXHOSTNAMELEN];
+ static struct addrinfo *ai;
+ char *local, *fake;
+ int error = 0, i;
+ int addrlen, namelen, family;
+
+#ifdef FOR_SHARED_LIBRARY
+ if (lsInRLDFunctions || lsInWrapFunction || lsInWrapHostname) return REAL(getaddrinfo)(hostname, servname, hints, aip);
+#endif
+
+ lsInWrapFunction = 1;
+ lsInWrapHostname = 1;
+ LIBPREFIX2(init)("libsocks5");
+ S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS getaddrinfo: looking up %s", hostname);
+
+ fake = getenv("SOCKS5_FAKEALLHOSTS");
+ local = getenv("SOCKS5_LOCALDNSONLY");
+
+ if (!fake &&
+ (error = REAL(getaddrinfo)(hostname, servname, hints, aip)) == NULL) {
+ getnameinfo((*aip)->ai_addr, (*aip)->ai_addrlen, numaddrbuf,
+ sizeof(numaddrbuf) - 1, NULL, 0,
+ NI_NUMERICHOST|NI_WITHSCOPEID);
+ S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS getaddrinfo: REAL: %s", numaddrbuf);
+
+ lsInWrapFunction = 0;
+ lsInWrapHostname = 0;
+ return error;
+ }
+
+ /* If your DNS is the same as the socks server, don't fake a correct */
+ /* lookup when you know it won't work... */
+ if (local) {
+ S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS getaddrinfo: REAL: Fake not configured");
+ lsInWrapFunction = 0;
+ lsInWrapHostname = 0;
+ return (error != 0) ? error : EAI_FAIL;
+ }
+
+ /* Fill in some UNRESOLVED values and let the daemon resolve it */
+ if ((i = GetFakeHost(hostname)) <= 0) {
+ S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "SOCKS getaddrinfo: Get fake host failed");
+ lsInWrapFunction = 0;
+ lsInWrapHostname = 0;
+ return (error != 0) ? error : EAI_FAIL;
+ }
+
+ /* create fake for AF_INET. AF_INET6 support is not yet */
+ if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET) {
+ addrlen = sizeof(struct sockaddr_in);
+ family = AF_INET;
+ ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + addrlen);
+ if (ai == NULL)
+ return EAI_MEMORY;
+ memcpy(ai, hints, sizeof(struct addrinfo));
+ ai->ai_family = family;
+ ai->ai_addr = (struct sockaddr *)(ai + 1);
+ memset(ai->ai_addr, 0, addrlen);
+ ai->ai_addr->sa_len = addrlen;
+ ai->ai_addrlen = addrlen;
+ ai->ai_addr->sa_family = family;
+ if (servname != NULL) {
+ struct servent *sp;
+ const char *p;
+ int is_number, port;
+
+ p = servname;
+ is_number = 1;
+ while (*p) {
+ if (!isdigit(*p))
+ is_number = 0;
+ p++;
+ }
+ if (is_number) {
+ port = htons(atoi(servname));
+ if (port < 0 || port > 65535) {
+ free(ai);
+ return EAI_SERVICE;
+ }
+ } else {
+ sp = getservbyname(servname, NULL);
+ if (sp == NULL) {
+ free(ai);
+ return EAI_SERVICE;
+ }
+ port = sp->s_port;
+ }
+ ((struct sockaddr_in *)ai->ai_addr)->sin_port = port;
+ }
+ ((struct sockaddr_in *)ai->ai_addr)->sin_addr.s_addr = htonl(i);
+ if ((hints->ai_flags & AI_CANONNAME) != 0) {
+ ai->ai_canonname = (char *)malloc(strlen(hostname) + 1);
+ if (ai->ai_canonname == NULL) {
+ free(ai);
+ return EAI_MEMORY;
+ }
+ strncpy(ai->ai_canonname, hostname, strlen(hostname) + 1);
+ }
+ } else
+ return EAI_FAMILY;
+ *aip = ai;
+
+ getnameinfo((*aip)->ai_addr, (*aip)->ai_addrlen, numaddrbuf,
+ sizeof(numaddrbuf) - 1, NULL, 0, NI_NUMERICHOST);
+ S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS getaddrinfo: FAKE: %s", numaddrbuf);
+ lsInWrapFunction = 0;
+ lsInWrapHostname = 0;
+ return 0;
}
#endif
|