netinet{,6}: Assert in{,6}_inithead() are only used for system routing tables.
[dragonfly.git] / contrib / ldns / compat / fake-rfc2553.c
1 /* From openssh 4.3p2 filename openbsd-compat/fake-rfc2553.h */
2 /*
3  * Copyright (C) 2000-2003 Damien Miller.  All rights reserved.
4  * Copyright (C) 1999 WIDE Project.  All rights reserved.
5  * 
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the project nor the names of its contributors
15  *    may be used to endorse or promote products derived from this software
16  *    without specific prior written permission.
17  * 
18  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30
31 /*
32  * Pseudo-implementation of RFC2553 name / address resolution functions
33  *
34  * But these functions are not implemented correctly. The minimum subset
35  * is implemented for ssh use only. For example, this routine assumes
36  * that ai_family is AF_INET. Don't use it for another purpose.
37  */
38
39 #include <ldns/config.h>
40 #include <ldns/common.h>
41 #include <unistd.h>
42 #include <string.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include "compat/fake-rfc2553.h"
46
47 #ifndef HAVE_GETNAMEINFO
48 int getnameinfo(const struct sockaddr *sa, size_t ATTR_UNUSED(salen), char *host, 
49                 size_t hostlen, char *serv, size_t servlen, int flags)
50 {
51         struct sockaddr_in *sin = (struct sockaddr_in *)sa;
52         struct hostent *hp;
53         char tmpserv[16];
54
55         if (serv != NULL) {
56                 snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port));
57                 if (strlcpy(serv, tmpserv, servlen) >= servlen)
58                         return (EAI_MEMORY);
59         }
60
61         if (host != NULL) {
62                 if (flags & NI_NUMERICHOST) {
63                         if (strlcpy(host, inet_ntoa(sin->sin_addr),
64                             hostlen) >= hostlen)
65                                 return (EAI_MEMORY);
66                         else
67                                 return (0);
68                 } else {
69                         hp = gethostbyaddr((char *)&sin->sin_addr, 
70                             sizeof(struct in_addr), AF_INET);
71                         if (hp == NULL)
72                                 return (EAI_NODATA);
73                         
74                         if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
75                                 return (EAI_MEMORY);
76                         else
77                                 return (0);
78                 }
79         }
80         return (0);
81 }
82 #endif /* !HAVE_GETNAMEINFO */
83
84 #ifndef HAVE_GAI_STRERROR
85 #ifdef HAVE_CONST_GAI_STRERROR_PROTO
86 const char *
87 #else
88 char *
89 #endif
90 gai_strerror(int err)
91 {
92         switch (err) {
93         case EAI_NODATA:
94                 return ("no address associated with name");
95         case EAI_MEMORY:
96                 return ("memory allocation failure.");
97         case EAI_NONAME:
98                 return ("nodename nor servname provided, or not known");
99         default:
100                 return ("unknown/invalid error.");
101         }
102 }    
103 #endif /* !HAVE_GAI_STRERROR */
104
105 #ifndef HAVE_FREEADDRINFO
106 void
107 freeaddrinfo(struct addrinfo *ai)
108 {
109         struct addrinfo *next;
110
111         for(; ai != NULL;) {
112                 next = ai->ai_next;
113                 free(ai);
114                 ai = next;
115         }
116 }
117 #endif /* !HAVE_FREEADDRINFO */
118
119 #ifndef HAVE_GETADDRINFO
120 static struct
121 addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints)
122 {
123         struct addrinfo *ai;
124
125         ai = malloc(sizeof(*ai) + sizeof(struct sockaddr_in));
126         if (ai == NULL)
127                 return (NULL);
128         
129         memset(ai, '\0', sizeof(*ai) + sizeof(struct sockaddr_in));
130         
131         ai->ai_addr = (struct sockaddr *)(ai + 1);
132         /* XXX -- ssh doesn't use sa_len */
133         ai->ai_addrlen = sizeof(struct sockaddr_in);
134         ai->ai_addr->sa_family = ai->ai_family = AF_INET;
135
136         ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
137         ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
138         
139         /* XXX: the following is not generally correct, but does what we want */
140         if (hints->ai_socktype)
141                 ai->ai_socktype = hints->ai_socktype;
142         else
143                 ai->ai_socktype = SOCK_STREAM;
144
145         if (hints->ai_protocol)
146                 ai->ai_protocol = hints->ai_protocol;
147
148         return (ai);
149 }
150
151 int
152 getaddrinfo(const char *hostname, const char *servname, 
153     const struct addrinfo *hints, struct addrinfo **res)
154 {
155         struct hostent *hp;
156         struct servent *sp;
157         struct in_addr in;
158         int i;
159         long int port;
160         u_long addr;
161
162         port = 0;
163         if (servname != NULL) {
164                 char *cp;
165
166                 port = strtol(servname, &cp, 10);
167                 if (port > 0 && port <= 65535 && *cp == '\0')
168                         port = htons(port);
169                 else if ((sp = getservbyname(servname, NULL)) != NULL)
170                         port = sp->s_port;
171                 else
172                         port = 0;
173         }
174
175         if (hints && hints->ai_flags & AI_PASSIVE) {
176                 addr = htonl(0x00000000);
177                 if (hostname && inet_aton(hostname, &in) != 0)
178                         addr = in.s_addr;
179                 *res = malloc_ai(port, addr, hints);
180                 if (*res == NULL) 
181                         return (EAI_MEMORY);
182                 return (0);
183         }
184                 
185         if (!hostname) {
186                 *res = malloc_ai(port, htonl(0x7f000001), hints);
187                 if (*res == NULL) 
188                         return (EAI_MEMORY);
189                 return (0);
190         }
191         
192         if (inet_aton(hostname, &in)) {
193                 *res = malloc_ai(port, in.s_addr, hints);
194                 if (*res == NULL) 
195                         return (EAI_MEMORY);
196                 return (0);
197         }
198         
199         /* Don't try DNS if AI_NUMERICHOST is set */
200         if (hints && hints->ai_flags & AI_NUMERICHOST)
201                 return (EAI_NONAME);
202         
203         hp = gethostbyname(hostname);
204         if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
205                 struct addrinfo *cur, *prev;
206
207                 cur = prev = *res = NULL;
208                 for (i = 0; hp->h_addr_list[i]; i++) {
209                         struct in_addr *in = (struct in_addr *)hp->h_addr_list[i];
210
211                         cur = malloc_ai(port, in->s_addr, hints);
212                         if (cur == NULL) {
213                                 if (*res != NULL)
214                                         freeaddrinfo(*res);
215                                 return (EAI_MEMORY);
216                         }
217                         if (prev)
218                                 prev->ai_next = cur;
219                         else
220                                 *res = cur;
221
222                         prev = cur;
223                 }
224                 return (0);
225         }
226         
227         return (EAI_NODATA);
228 }
229 #endif /* !HAVE_GETADDRINFO */