DEFINITIONS
This source file includes following functions.
- inet_ntop
- getnameinfo
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 #include "config.h"
38 #include <sys/types.h>
39 #ifndef NT
40 #if defined(__BEOS__)
41 # include <net/socket.h>
42 #else
43 # include <sys/socket.h>
44 #endif
45 #include <netinet/in.h>
46 #if defined(HAVE_ARPA_INET_H)
47 #include <arpa/inet.h>
48 #endif
49 #if defined(HAVE_ARPA_NAMESER_H)
50 #include <arpa/nameser.h>
51 #endif
52 #include <netdb.h>
53 #if defined(HAVE_RESOLV_H)
54 #include <resolv.h>
55 #endif
56 #endif
57 #ifdef NT
58 #include <winsock2.h>
59 #include <stdio.h>
60 #define snprintf _snprintf
61 #endif
62
63 #include <string.h>
64 #include <stddef.h>
65
66 #ifdef SOCKS5
67 #include <socks.h>
68 #endif
69
70 #include "addrinfo.h"
71 #include "sockport.h"
72
73 #define SUCCESS 0
74 #define ANY 0
75 #define YES 1
76 #define NO 0
77
78 struct sockinet {
79 u_char si_len;
80 u_char si_family;
81 u_short si_port;
82 };
83
84 static struct afd {
85 int a_af;
86 int a_addrlen;
87 int a_socklen;
88 int a_off;
89 } afdl [] = {
90 #ifdef INET6
91 #define N_INET6 0
92 {PF_INET6, sizeof(struct in6_addr),
93 sizeof(struct sockaddr_in6),
94 offsetof(struct sockaddr_in6, sin6_addr)},
95 #define N_INET 1
96 #else
97 #define N_INET 0
98 #endif
99 {PF_INET, sizeof(struct in_addr),
100 sizeof(struct sockaddr_in),
101 offsetof(struct sockaddr_in, sin_addr)},
102 {0, 0, 0, 0},
103 };
104
105 #define ENI_NOSOCKET 0
106 #define ENI_NOSERVNAME 1
107 #define ENI_NOHOSTNAME 2
108 #define ENI_MEMORY 3
109 #define ENI_SYSTEM 4
110 #define ENI_FAMILY 5
111 #define ENI_SALEN 6
112
113 #ifndef HAVE_INET_NTOP
114 static const char *
115 inet_ntop(af, addr, numaddr, numaddr_len)
116 int af;
117 const void *addr;
118 char *numaddr;
119 size_t numaddr_len;
120 {
121 #ifdef HAVE_INET_NTOA
122 struct in_addr in;
123 memcpy(&in.s_addr, addr, sizeof(in.s_addr));
124 snprintf(numaddr, numaddr_len, "%s", inet_ntoa(in));
125 #else
126 unsigned long x = ntohl(*(unsigned long*)addr);
127 snprintf(numaddr, numaddr_len, "%d.%d.%d.%d",
128 (int) (x>>24) & 0xff, (int) (x>>16) & 0xff,
129 (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff);
130 #endif
131 return numaddr;
132 }
133 #endif
134
135 int
136 getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
137 const struct sockaddr *sa;
138 size_t salen;
139 char *host;
140 size_t hostlen;
141 char *serv;
142 size_t servlen;
143 int flags;
144 {
145 struct afd *afd;
146 struct servent *sp;
147 struct hostent *hp;
148 u_short port;
149 int family, len, i;
150 char *addr, *p;
151 u_long v4a;
152 #ifdef INET6
153 u_char pfx;
154 #endif
155 int h_error;
156 char numserv[512];
157 char numaddr[512];
158
159 if (sa == NULL)
160 return ENI_NOSOCKET;
161
162 len = SA_LEN(sa);
163 if (len != salen) return ENI_SALEN;
164
165 family = sa->sa_family;
166 for (i = 0; afdl[i].a_af; i++)
167 if (afdl[i].a_af == family) {
168 afd = &afdl[i];
169 goto found;
170 }
171 return ENI_FAMILY;
172
173 found:
174 if (len != afd->a_socklen) return ENI_SALEN;
175
176 port = ((struct sockinet *)sa)->si_port;
177 addr = (char *)sa + afd->a_off;
178
179 if (serv == NULL || servlen == 0) {
180
181 } else if (flags & NI_NUMERICSERV) {
182 snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
183 if (strlen(numserv) + 1 > servlen)
184 return ENI_MEMORY;
185 strcpy(serv, numserv);
186 } else {
187 #if defined(HAVE_GETSERVBYPORT)
188 sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
189 if (sp) {
190 if (strlen(sp->s_name) + 1 > servlen)
191 return ENI_MEMORY;
192 strcpy(serv, sp->s_name);
193 } else
194 return ENI_NOSERVNAME;
195 #else
196 return ENI_NOSERVNAME;
197 #endif
198 }
199
200 switch (sa->sa_family) {
201 case AF_INET:
202 v4a = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
203 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
204 flags |= NI_NUMERICHOST;
205 v4a >>= IN_CLASSA_NSHIFT;
206 if (v4a == 0)
207 flags |= NI_NUMERICHOST;
208 break;
209 #ifdef INET6
210 case AF_INET6:
211 pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr8[0];
212 if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
213 flags |= NI_NUMERICHOST;
214 break;
215 #endif
216 }
217 if (host == NULL || hostlen == 0) {
218
219 } else if (flags & NI_NUMERICHOST) {
220 if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
221 == NULL)
222 return ENI_SYSTEM;
223 if (strlen(numaddr) > hostlen)
224 return ENI_MEMORY;
225 strcpy(host, numaddr);
226 } else {
227 #ifdef INET6
228 hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
229 #else
230 hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
231 h_error = h_errno;
232 #endif
233
234 if (hp) {
235 if (flags & NI_NOFQDN) {
236 p = strchr(hp->h_name, '.');
237 if (p) *p = '\0';
238 }
239 if (strlen(hp->h_name) + 1 > hostlen) {
240 #ifdef INET6
241 freehostent(hp);
242 #endif
243 return ENI_MEMORY;
244 }
245 strcpy(host, hp->h_name);
246 #ifdef INET6
247 freehostent(hp);
248 #endif
249 } else {
250 if (flags & NI_NAMEREQD)
251 return ENI_NOHOSTNAME;
252 if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
253 == NULL)
254 return ENI_NOHOSTNAME;
255 if (strlen(numaddr) > hostlen)
256 return ENI_MEMORY;
257 strcpy(host, numaddr);
258 }
259 }
260 return SUCCESS;
261 }