diff options
author | Damien Miller <djm@mindrot.org> | 2003-06-05 18:52:47 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2003-06-05 18:52:47 +1000 |
commit | c28e38d23a3d074e02c1f63b64569a31d499a0e8 (patch) | |
tree | f3e1582ecddf28f770a1ed84c26d64177e735656 /openbsd-compat/fake-rfc2553.c | |
parent | b95bb7f9b13905ade12cac848e34339ae8a1cc2f (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.c | 189 |
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 | |||
9 | RCSID("$Id: fake-rfc2553.c,v 1.1 2003/06/05 08:52:48 djm Exp $"); | ||
10 | |||
11 | #ifndef HAVE_GETNAMEINFO | ||
12 | int 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 | ||
49 | char * | ||
50 | gai_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 | ||
66 | void | ||
67 | freeaddrinfo(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 | ||
80 | static struct | ||
81 | addrinfo *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 | |||
111 | int | ||
112 | getaddrinfo(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 */ | ||