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