]> andersk Git - openssh.git/blob - openbsd-compat/fake-getaddrinfo.c
- (djm) Support AI_NUMERICHOST in fake-getaddrinfo.c. Needed for recent
[openssh.git] / openbsd-compat / fake-getaddrinfo.c
1 /*
2  * fake library for ssh
3  *
4  * This file includes getaddrinfo(), freeaddrinfo() and gai_strerror().
5  * These funtions are defined in rfc2133.
6  *
7  * But these functions are not implemented correctly. The minimum subset
8  * is implemented for ssh use only. For exapmle, this routine assumes
9  * that ai_family is AF_INET. Don't use it for another purpose.
10  */
11
12 #include "includes.h"
13 #include "xmalloc.h"
14 #include "ssh.h"
15
16 RCSID("$Id$");
17
18 #ifndef HAVE_GAI_STRERROR
19 char *
20 gai_strerror(int err)
21 {
22         switch (err) {
23         case EAI_NODATA:
24                 return ("no address associated with name");
25         case EAI_MEMORY:
26                 return ("memory allocation failure.");
27         case EAI_NONAME:
28                 return ("nodename nor servname provided, or not known");
29         default:
30                 return ("unknown/invalid error.");
31         }
32 }    
33 #endif /* !HAVE_GAI_STRERROR */
34
35 #ifndef HAVE_FREEADDRINFO
36 void
37 freeaddrinfo(struct addrinfo *ai)
38 {
39         struct addrinfo *next;
40
41         for(; ai != NULL;) {
42                 next = ai->ai_next;
43                 free(ai);
44                 ai = next;
45         }
46 }
47 #endif /* !HAVE_FREEADDRINFO */
48
49 #ifndef HAVE_GETADDRINFO
50 static struct
51 addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints)
52 {
53         struct addrinfo *ai;
54
55         ai = xmalloc(sizeof(*ai) + sizeof(struct sockaddr_in));
56         
57         memset(ai, '\0', sizeof(*ai) + sizeof(struct sockaddr_in));
58         
59         ai->ai_addr = (struct sockaddr *)(ai + 1);
60         /* XXX -- ssh doesn't use sa_len */
61         ai->ai_addrlen = sizeof(struct sockaddr_in);
62         ai->ai_addr->sa_family = ai->ai_family = AF_INET;
63
64         ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
65         ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
66         
67         /* XXX: the following is not generally correct, but does what we want */
68         if (hints->ai_socktype)
69                 ai->ai_socktype = hints->ai_socktype;
70         else
71                 ai->ai_socktype = SOCK_STREAM;
72
73         if (hints->ai_protocol)
74                 ai->ai_protocol = hints->ai_protocol;
75
76         return (ai);
77 }
78
79 int
80 getaddrinfo(const char *hostname, const char *servname, 
81     const struct addrinfo *hints, struct addrinfo **res)
82 {
83         struct hostent *hp;
84         struct servent *sp;
85         struct in_addr in;
86         int i;
87         long int port;
88         u_long addr;
89
90         port = 0;
91         if (servname != NULL) {
92                 char *cp;
93
94                 port = strtol(servname, &cp, 10);
95                 if (port > 0 && port <= 65535 && *cp == '\0')
96                         port = htons(port);
97                 else if ((sp = getservbyname(servname, NULL)) != NULL)
98                         port = sp->s_port;
99                 else
100                         port = 0;
101         }
102
103         if (hints && hints->ai_flags & AI_PASSIVE) {
104                 addr = htonl(0x00000000);
105                 if (hostname && inet_aton(hostname, &in) != 0)
106                         addr = in.s_addr;
107                 *res = malloc_ai(port, addr, hints);
108                 return (0);
109         }
110                 
111         if (!hostname) {
112                 *res = malloc_ai(port, htonl(0x7f000001), hints);
113                 return (0);
114         }
115         
116         if (inet_aton(hostname, &in)) {
117                 *res = malloc_ai(port, in.s_addr, hints);
118                 return (0);
119         }
120         
121         /* Don't try DNS if AI_NUMERICHOST is set */
122         if (hints && hints->ai_flags & AI_NUMERICHOST)
123                 return (EAI_NONAME);
124         
125         hp = gethostbyname(hostname);
126         if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
127                 struct addrinfo *cur, *prev;
128
129                 cur = prev = NULL;
130                 for (i = 0; hp->h_addr_list[i]; i++) {
131                         struct in_addr *in = (struct in_addr *)hp->h_addr_list[i];
132
133                         cur = malloc_ai(port, in->s_addr, hints);
134                         if (prev)
135                                 prev->ai_next = cur;
136                         else
137                                 *res = cur;
138
139                         prev = cur;
140                 }
141                 return (0);
142         }
143         
144         return (EAI_NODATA);
145 }
146 #endif /* !HAVE_GETADDRINFO */
This page took 0.053177 seconds and 5 git commands to generate.