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 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