1 /** @file
2 Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
3 This program and the accompanying materials are licensed and made available under
4 the terms and conditions of the BSD License that accompanies this distribution.
5 The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php.
7
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
10
11
12 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
13 * All rights reserved.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 * 3. Neither the name of the project nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38
39 * Issues to be discussed:
40 * - Thread safe-ness must be checked
41 * - Return values. There seems to be no standard for return value (RFC2133)
42 * but INRIA implementation returns EAI_xxx defined for getaddrinfo().
43 **/
44
45 #if 0
46 #include <sys/types.h>
47 #include <sys/socket.h>
48 #include <netinet/in.h>
49 #include <arpa/inet.h>
50 #include <arpa/nameser.h>
51 #include <netdb.h>
52 #include <resolv.h>
53 #include <string.h>
54 #include <stddef.h>
55
56 #include "addrinfo.h"
57 #endif
58
59 #define SUCCESS 0
60 #define YES 1
61 #define NO 0
62
63 static struct gni_afd {
64 int a_af;
65 int a_addrlen;
66 int a_socklen;
67 int a_off;
68 } gni_afdl [] = {
69 #ifdef ENABLE_IPV6
70 {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
71 offsetof(struct sockaddr_in6, sin6_addr)},
72 #endif
73 {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
74 offsetof(struct sockaddr_in, sin_addr)},
75 {0, 0, 0},
76 };
77
78 struct gni_sockinet {
79 u_char si_len;
80 u_char si_family;
81 u_short si_port;
82 };
83
84 #define ENI_NOSOCKET 0
85 #define ENI_NOSERVNAME 1
86 #define ENI_NOHOSTNAME 2
87 #define ENI_MEMORY 3
88 #define ENI_SYSTEM 4
89 #define ENI_FAMILY 5
90 #define ENI_SALEN 6
91
92 /* forward declaration to make gcc happy */
93 int getnameinfo Py_PROTO((const struct sockaddr *, size_t, char *, size_t,
94 char *, size_t, int));
95
96 int
getnameinfo(sa,salen,host,hostlen,serv,servlen,flags)97 getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
98 const struct sockaddr *sa;
99 size_t salen;
100 char *host;
101 size_t hostlen;
102 char *serv;
103 size_t servlen;
104 int flags;
105 {
106 struct gni_afd *gni_afd;
107 struct servent *sp;
108 struct hostent *hp;
109 u_short port;
110 int family, len, i;
111 char *addr, *p;
112 u_long v4a;
113 #ifdef ENABLE_IPV6
114 u_char pfx;
115 int h_error;
116 #endif
117 char numserv[512];
118 char numaddr[512];
119
120 if (sa == NULL)
121 return ENI_NOSOCKET;
122
123 #ifdef HAVE_SOCKADDR_SA_LEN
124 len = sa->sa_len;
125 if (len != salen) return ENI_SALEN;
126 #else
127 len = salen;
128 #endif
129
130 family = sa->sa_family;
131 for (i = 0; gni_afdl[i].a_af; i++)
132 if (gni_afdl[i].a_af == family) {
133 gni_afd = &gni_afdl[i];
134 goto found;
135 }
136 return ENI_FAMILY;
137
138 found:
139 if (len != gni_afd->a_socklen) return ENI_SALEN;
140
141 port = ((struct gni_sockinet *)sa)->si_port; /* network byte order */
142 addr = (char *)sa + gni_afd->a_off;
143
144 if (serv == NULL || servlen == 0) {
145 /* what we should do? */
146 } else if (flags & NI_NUMERICSERV) {
147 sprintf(numserv, "%d", ntohs(port));
148 if (strlen(numserv) > servlen)
149 return ENI_MEMORY;
150 strcpy(serv, numserv);
151 } else {
152 sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
153 if (sp) {
154 if (strlen(sp->s_name) > servlen)
155 return ENI_MEMORY;
156 strcpy(serv, sp->s_name);
157 } else
158 return ENI_NOSERVNAME;
159 }
160
161 switch (sa->sa_family) {
162 case AF_INET:
163 v4a = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
164 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
165 flags |= NI_NUMERICHOST;
166 v4a >>= IN_CLASSA_NSHIFT;
167 if (v4a == 0 || v4a == IN_LOOPBACKNET)
168 flags |= NI_NUMERICHOST;
169 break;
170 #ifdef ENABLE_IPV6
171 case AF_INET6:
172 pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr8[0];
173 if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
174 flags |= NI_NUMERICHOST;
175 break;
176 #endif
177 }
178 if (host == NULL || hostlen == 0) {
179 /* what should we do? */
180 } else if (flags & NI_NUMERICHOST) {
181 if (inet_ntop(gni_afd->a_af, addr, numaddr, sizeof(numaddr))
182 == NULL)
183 return ENI_SYSTEM;
184 if (strlen(numaddr) > hostlen)
185 return ENI_MEMORY;
186 strcpy(host, numaddr);
187 } else {
188 #ifdef ENABLE_IPV6
189 hp = getipnodebyaddr(addr, gni_afd->a_addrlen, gni_afd->a_af, &h_error);
190 #else
191 hp = gethostbyaddr(addr, gni_afd->a_addrlen, gni_afd->a_af);
192 //h_error = h_errno;
193 #endif
194
195 if (hp) {
196 if (flags & NI_NOFQDN) {
197 p = strchr(hp->h_name, '.');
198 if (p) *p = '\0';
199 }
200 if (strlen(hp->h_name) > hostlen) {
201 #ifdef ENABLE_IPV6
202 freehostent(hp);
203 #endif
204 return ENI_MEMORY;
205 }
206 strcpy(host, hp->h_name);
207 #ifdef ENABLE_IPV6
208 freehostent(hp);
209 #endif
210 } else {
211 if (flags & NI_NAMEREQD)
212 return ENI_NOHOSTNAME;
213 if (inet_ntop(gni_afd->a_af, addr, numaddr, sizeof(numaddr))
214 == NULL)
215 return ENI_NOHOSTNAME;
216 if (strlen(numaddr) > hostlen)
217 return ENI_MEMORY;
218 strcpy(host, numaddr);
219 }
220 }
221 return SUCCESS;
222 }
223