1 /*
2 * aprsc
3 *
4 * (c) Matti Aarnio, OH2MQK, <oh2mqk@sral.fi>
5 *
6 * This program is licensed under the BSD license, which can be found
7 * in the file LICENSE.
8 *
9 */
10 /*
11 * Generalized adaptation to ZMailer libc fill-in use by
12 * Matti Aarnio <mea@nic.funet.fi> 2000
13 *
14 * The original version taken from glibc-2.1.92 on 1-Aug-2000
15 *
16 * This is SERIOUSLY LOBOTIMIZED to be usable in environments WITHOUT
17 * threaded versions of getservbyname(), and friends, plus ridding
18 * __alloca() calls as they are VERY GCC specific, which isn't a good
19 * thing for ZMailer. (Also DE-ANSIfied to K&R style..)
20 *
21 * Original reason for having getaddrinfo() API in ZMailer was
22 * to support IPv6 universe -- and that is still the reason. This
23 * adaptation module is primarily for those systems which don't have
24 * this IPv6 API, but there are also some systems (all those using
25 * the original INNER NET code -- glibc 2.0/2.1/2.2(?) especially)
26 * which have faulty error condition processing in them. Specifically
27 * plain simple TIMEOUTS on queries are not handled properly!
28 *
29 * Now that Linuxes have caught up at libc level, we no longer have
30 * a reason to support kernel things which don't exist at libc level.
31 * (Running ZMailer on Linux with libc5 is not supported in sense of
32 * supporting IPv6 at the kernel..)
33 *
34 *
35 * THIS getnameinfo() FUNCTION IS NOT USED IN ZMAILER, BUT IS
36 * SUPPLIED JUST TO COMPLETE THE API IN CASE IT WILL SOMETIME BECOME
37 * USED...
38 *
39 */
40
41 /* The Inner Net License, Version 2.00
42
43 The author(s) grant permission for redistribution and use in source and
44 binary forms, with or without modification, of the software and documentation
45 provided that the following conditions are met:
46
47 0. If you receive a version of the software that is specifically labelled
48 as not being for redistribution (check the version message and/or README),
49 you are not permitted to redistribute that version of the software in any
50 way or form.
51 1. All terms of the all other applicable copyrights and licenses must be
52 followed.
53 2. Redistributions of source code must retain the authors' copyright
54 notice(s), this list of conditions, and the following disclaimer.
55 3. Redistributions in binary form must reproduce the authors' copyright
56 notice(s), this list of conditions, and the following disclaimer in the
57 documentation and/or other materials provided with the distribution.
58 4. All advertising materials mentioning features or use of this software
59 must display the following acknowledgement with the name(s) of the
60 authors as specified in the copyright notice(s) substituted where
61 indicated:
62
63 This product includes software developed by <name(s)>, The Inner
64 Net, and other contributors.
65
66 5. Neither the name(s) of the author(s) nor the names of its contributors
67 may be used to endorse or promote products derived from this software
68 without specific prior written permission.
69
70 THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY
71 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
72 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
73 DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
74 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
75 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
76 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
77 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
78 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
79 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
80
81 If these license terms cause you a real problem, contact the author. */
82
83 /* This software is Copyright 1996 by Craig Metz, All Rights Reserved. */
84
85 # include "ac-defs.h" /* autoconfig environment */
86
87 #include <sys/param.h>
88 #include <sys/types.h>
89 #include <errno.h>
90 #include <stdio.h>
91 #include <string.h>
92 #include <unistd.h>
93 #include <sys/socket.h>
94 #include <net/if.h>
95 #include <netinet/in.h>
96 #include <arpa/inet.h>
97 #include <arpa/nameser.h> /* Sol 2.6 barfs without this.. */
98 #include <resolv.h>
99 #ifdef HAVE_SYS_UN_H
100 #include <sys/un.h>
101 #endif
102 #include <sys/utsname.h>
103 #include <netdb.h>
104 #if !defined(EAI_AGAIN) || !defined(AI_NUMERICHOST)
105 # include "netdb6.h"
106 #endif
107
108
109 #ifndef min
110 # define min(x,y) (((x) > (y)) ? (y) : (x))
111 #endif /* min */
112
113 #ifndef AF_LOCAL
114 # ifdef AF_UNIX
115 # define AF_LOCAL AF_UNIX
116 # define PF_LOCAL PF_UNIX
117 # endif
118 #endif
119
120 static char * nrl_domainname __((void));
121 static char *
nrl_domainname()122 nrl_domainname ()
123 {
124 static char *domain;
125 static int not_first;
126 char hostnamebuf[MAXHOSTNAMELEN];
127
128 if (! not_first) {
129 char *c;
130 struct hostent *h;
131
132 not_first = 1;
133
134 h = gethostbyname ("localhost");
135
136 if (h && (c = strchr (h->h_name, '.')))
137 domain = strdup (++c);
138 else {
139 /* The name contains no domain information. Use the name
140 now to get more information. */
141 gethostname (hostnamebuf, MAXHOSTNAMELEN);
142
143 c = strchr (hostnamebuf, '.');
144 if (c)
145 domain = strdup (++c);
146 else {
147 h = gethostbyname(hostnamebuf);
148
149 if (h && (c = strchr(h->h_name, '.')))
150 domain = strdup (++c);
151 else {
152 struct in_addr in_addr;
153
154 in_addr.s_addr = htonl (0x7f000001);
155
156
157 h = gethostbyaddr((const char *) &in_addr,
158 sizeof (struct in_addr),
159 AF_INET);
160
161 if (h && (c = strchr (h->h_name, '.')))
162 domain = strdup (++c);
163 }
164 }
165 }
166 }
167
168 return domain;
169 }
170
171 /* This is NASTY, GLIBC has changed the type after instroducing
172 this function, Sol (2.)8 has 'int', of upcoming POSIX standard
173 revision I don't know.. */
174
175 #ifndef GETNAMEINFOFLAGTYPE
176 # if defined(__GLIBC__) && defined(__GLIBC_MINOR__)
177 # if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 2
178 /* I am not sure that it was already 2.2(.0) that had
179 this change, but 2.2.2 has it... */
180 # define GETNAMEINFOFLAGTYPE unsigned int
181 # else
182 # define GETNAMEINFOFLAGTYPE int
183 # endif
184 # else
185 # define GETNAMEINFOFLAGTYPE int
186 # endif
187 #endif
188
189 #if 0
190
191 int
192 getnameinfo __((const struct sockaddr *sa, size_t addrlen, char *host,
193 size_t hostlen, char *serv, size_t servlen,
194 GETNAMEINFOFLAGTYPE flags));
195
196 int
197 getnameinfo (sa, addrlen, host, hostlen, serv, servlen, flags)
198 const struct sockaddr *sa;
199 size_t addrlen;
200 char *host;
201 size_t hostlen;
202 char *serv;
203 size_t servlen;
204 GETNAMEINFOFLAGTYPE flags;
205 {
206 int serrno = errno;
207 int ok = 0;
208
209 if (sa == NULL || addrlen < sizeof (sa->sa_family))
210 return -1;
211
212 switch (sa->sa_family) {
213 #ifdef AF_LOCAL
214 case AF_LOCAL:
215 if (addrlen < (size_t) (((struct sockaddr_un *) NULL)->sun_path))
216 return -1;
217 break;
218 #endif
219 case AF_INET:
220 if (addrlen < sizeof (struct sockaddr_in))
221 return -1;
222 break;
223 default:
224 return -1;
225 }
226
227 if (host != NULL && hostlen > 0)
228 switch (sa->sa_family) {
229 case AF_INET:
230 if (!(flags & NI_NUMERICHOST)) {
231 struct hostent *h;
232
233 h = gethostbyaddr((void *) &(((struct sockaddr_in *)sa)->sin_addr),
234 sizeof(struct in_addr), AF_INET);
235 if (h) {
236 if (flags & NI_NOFQDN) {
237 char *c;
238 if ((c = nrl_domainname ()) && (c = strstr(h->h_name, c))
239 && (c != h->h_name) && (*(--c) == '.')) {
240 strncpy (host, h->h_name,
241 min(hostlen, (size_t) (c - h->h_name)));
242 host[min(hostlen - 1, (size_t) (c - h->h_name))] = '\0';
243 ok = 1;
244 } else {
245 strncpy (host, h->h_name, hostlen);
246 ok = 1;
247 }
248 } else {
249 strncpy (host, h->h_name, hostlen);
250 ok = 1;
251 }
252 }
253 }
254
255 if (!ok) {
256 if (flags & NI_NAMEREQD) {
257 return -1;
258 } else {
259 const char *c;
260 c = inet_ntop (AF_INET,
261 (void *) &(((struct sockaddr_in *) sa)->sin_addr),
262 host, hostlen);
263 if (!c) {
264 return -1;
265 }
266 }
267 ok = 1;
268 }
269 break;
270
271 #ifdef AF_LOCAL
272 case AF_LOCAL:
273 if (!(flags & NI_NUMERICHOST)) {
274 struct utsname utsname;
275
276 if (!uname (&utsname)) {
277 strncpy (host, utsname.nodename, hostlen);
278 break;
279 }
280 }
281
282 if (flags & NI_NAMEREQD) {
283 return -1;
284 }
285
286 strncpy (host, "localhost", hostlen);
287 break;
288 #endif
289
290 default:
291 return -1;
292 }
293
294 if (serv && (servlen > 0))
295 switch (sa->sa_family) {
296 case AF_INET:
297 if (!(flags & NI_NUMERICSERV)) {
298 struct servent *s;
299 s = getservbyport(((struct sockaddr_in *) sa)->sin_port,
300 ((flags & NI_DGRAM) ? "udp" : "tcp"));
301 if (s) {
302 strncpy (serv, s->s_name, servlen);
303 break;
304 }
305 }
306 {
307 char decbuf[30];
308 sprintf(decbuf, "%d", ntohs (((struct sockaddr_in *) sa)->sin_port));
309 strncpy(serv, decbuf, servlen);
310 serv[servlen-1] = 0;
311 }
312 break;
313
314 #ifdef AF_LOCAL
315 case AF_LOCAL:
316 strncpy (serv, ((struct sockaddr_un *) sa)->sun_path, servlen);
317 break;
318 #endif
319 }
320
321 if (host && (hostlen > 0))
322 host[hostlen-1] = 0;
323 if (serv && (servlen > 0))
324 serv[servlen-1] = 0;
325 errno = serrno;
326 return 0;
327 }
328 #endif
329