summaryrefslogtreecommitdiff
path: root/openbsd-compat/fake-rfc2553.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2003-06-05 18:52:47 +1000
committerDamien Miller <djm@mindrot.org>2003-06-05 18:52:47 +1000
commitc28e38d23a3d074e02c1f63b64569a31d499a0e8 (patch)
treef3e1582ecddf28f770a1ed84c26d64177e735656 /openbsd-compat/fake-rfc2553.c
parentb95bb7f9b13905ade12cac848e34339ae8a1cc2f (diff)
- (djm) Merge all the openbsd/fake-* into fake-rfc2553.[ch]
Diffstat (limited to 'openbsd-compat/fake-rfc2553.c')
-rw-r--r--openbsd-compat/fake-rfc2553.c189
1 files changed, 189 insertions, 0 deletions
diff --git a/openbsd-compat/fake-rfc2553.c b/openbsd-compat/fake-rfc2553.c
new file mode 100644
index 000000000..ca13a40bc
--- /dev/null
+++ b/openbsd-compat/fake-rfc2553.c
@@ -0,0 +1,189 @@
1/*
2 * Pseudo-implementation of RFC2553 name / address resolution functions
3 *
4 * But these functions are not implemented correctly. The minimum subset
5 * is implemented for ssh use only. For exapmle, this routine assumes
6 * that ai_family is AF_INET. Don't use it for another purpose.
7 */
8
9RCSID("$Id: fake-rfc2553.c,v 1.1 2003/06/05 08:52:48 djm Exp $");
10
11#ifndef HAVE_GETNAMEINFO
12int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
13 size_t hostlen, char *serv, size_t servlen, int flags)
14{
15 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
16 struct hostent *hp;
17 char tmpserv[16];
18
19 if (serv != NULL) {
20 snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port));
21 if (strlcpy(serv, tmpserv, servlen) >= servlen)
22 return (EAI_MEMORY);
23 }
24
25 if (host != NULL) {
26 if (flags & NI_NUMERICHOST) {
27 if (strlcpy(host, inet_ntoa(sin->sin_addr),
28 hostlen) >= hostlen)
29 return (EAI_MEMORY);
30 else
31 return (0);
32 } else {
33 hp = gethostbyaddr((char *)&sin->sin_addr,
34 sizeof(struct in_addr), AF_INET);
35 if (hp == NULL)
36 return (EAI_NODATA);
37
38 if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
39 return (EAI_MEMORY);
40 else
41 return (0);
42 }
43 }
44 return (0);
45}
46#endif /* !HAVE_GETNAMEINFO */
47
48#ifndef HAVE_GAI_STRERROR
49char *
50gai_strerror(int err)
51{
52 switch (err) {
53 case EAI_NODATA:
54 return ("no address associated with name");
55 case EAI_MEMORY:
56 return ("memory allocation failure.");
57 case EAI_NONAME:
58 return ("nodename nor servname provided, or not known");
59 default:
60 return ("unknown/invalid error.");
61 }
62}
63#endif /* !HAVE_GAI_STRERROR */
64
65#ifndef HAVE_FREEADDRINFO
66void
67freeaddrinfo(struct addrinfo *ai)
68{
69 struct addrinfo *next;
70
71 for(; ai != NULL;) {
72 next = ai->ai_next;
73 free(ai);
74 ai = next;
75 }
76}
77#endif /* !HAVE_FREEADDRINFO */
78
79#ifndef HAVE_GETADDRINFO
80static struct
81addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints)
82{
83 struct addrinfo *ai;
84
85 ai = malloc(sizeof(*ai) + sizeof(struct sockaddr_in));
86 if (ai == NULL)
87 return (NULL);
88
89 memset(ai, '\0', sizeof(*ai) + sizeof(struct sockaddr_in));
90
91 ai->ai_addr = (struct sockaddr *)(ai + 1);
92 /* XXX -- ssh doesn't use sa_len */
93 ai->ai_addrlen = sizeof(struct sockaddr_in);
94 ai->ai_addr->sa_family = ai->ai_family = AF_INET;
95
96 ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
97 ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
98
99 /* XXX: the following is not generally correct, but does what we want */
100 if (hints->ai_socktype)
101 ai->ai_socktype = hints->ai_socktype;
102 else
103 ai->ai_socktype = SOCK_STREAM;
104
105 if (hints->ai_protocol)
106 ai->ai_protocol = hints->ai_protocol;
107
108 return (ai);
109}
110
111int
112getaddrinfo(const char *hostname, const char *servname,
113 const struct addrinfo *hints, struct addrinfo **res)
114{
115 struct hostent *hp;
116 struct servent *sp;
117 struct in_addr in;
118 int i;
119 long int port;
120 u_long addr;
121
122 port = 0;
123 if (servname != NULL) {
124 char *cp;
125
126 port = strtol(servname, &cp, 10);
127 if (port > 0 && port <= 65535 && *cp == '\0')
128 port = htons(port);
129 else if ((sp = getservbyname(servname, NULL)) != NULL)
130 port = sp->s_port;
131 else
132 port = 0;
133 }
134
135 if (hints && hints->ai_flags & AI_PASSIVE) {
136 addr = htonl(0x00000000);
137 if (hostname && inet_aton(hostname, &in) != 0)
138 addr = in.s_addr;
139 *res = malloc_ai(port, addr, hints);
140 if (*res == NULL)
141 return (EAI_MEMORY);
142 return (0);
143 }
144
145 if (!hostname) {
146 *res = malloc_ai(port, htonl(0x7f000001), hints);
147 if (*res == NULL)
148 return (EAI_MEMORY);
149 return (0);
150 }
151
152 if (inet_aton(hostname, &in)) {
153 *res = malloc_ai(port, in.s_addr, hints);
154 if (*res == NULL)
155 return (EAI_MEMORY);
156 return (0);
157 }
158
159 /* Don't try DNS if AI_NUMERICHOST is set */
160 if (hints && hints->ai_flags & AI_NUMERICHOST)
161 return (EAI_NONAME);
162
163 hp = gethostbyname(hostname);
164 if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
165 struct addrinfo *cur, *prev;
166
167 cur = prev = *res = NULL;
168 for (i = 0; hp->h_addr_list[i]; i++) {
169 struct in_addr *in = (struct in_addr *)hp->h_addr_list[i];
170
171 cur = malloc_ai(port, in->s_addr, hints);
172 if (cur == NULL) {
173 if (*res != NULL)
174 freeaddrinfo(*res);
175 return (EAI_MEMORY);
176 }
177 if (prev)
178 prev->ai_next = cur;
179 else
180 *res = cur;
181
182 prev = cur;
183 }
184 return (0);
185 }
186
187 return (EAI_NODATA);
188}
189#endif /* !HAVE_GETADDRINFO */