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