2 This file is part of nss-gns.
4 Parts taken from: nss.c in nss-mdns
6 nss-mdns is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
11 nss-mdns is distributed in the hope that it will be useful, but1
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with nss-mdns; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
31 #include <sys/socket.h>
37 #define _nss_mdns_gethostbyname2_r _nss_gns4_minimal_gethostbyname2_r
38 #define _nss_mdns_gethostbyname_r _nss_gns4_minimal_gethostbyname_r
39 #define _nss_mdns_gethostbyaddr_r _nss_gns4_minimal_gethostbyaddr_r
43 #define _nss_mdns_gethostbyname2_r _nss_gns6_gethostbyname2_r
44 #define _nss_mdns_gethostbyname_r _nss_gns6_gethostbyname_r
45 #define _nss_mdns_gethostbyaddr_r _nss_gns6_gethostbyaddr_r
50 #define _nss_mdns_gethostbyname2_r _nss_gns_gethostbyname2_r
51 #define _nss_mdns_gethostbyname_r _nss_gns_gethostbyname_r
52 #define _nss_mdns_gethostbyaddr_r _nss_gns_gethostbyaddr_r
56 /* Maximum number of entries to return */
57 #define MAX_ENTRIES 16
59 #define ALIGN(idx) do { \
60 if (idx % sizeof(void*)) \
61 idx += (sizeof(void*) - idx % sizeof(void*)); /* Align on 32 bit boundary */ \
66 int data_len; /* only valid when doing reverse lookup */
68 ipv4_address_t ipv4[MAX_ENTRIES];
69 ipv6_address_t ipv6[MAX_ENTRIES];
70 char *name[MAX_ENTRIES];
75 static void ipv4_callback(const ipv4_address_t *ipv4, void *userdata) {
76 struct userdata *u = userdata;
77 assert(ipv4 && userdata);
79 if (u->count >= MAX_ENTRIES)
82 u->data.ipv4[u->count++] = *ipv4;
83 u->data_len += sizeof(ipv4_address_t);
88 static void ipv6_callback(const ipv6_address_t *ipv6, void *userdata) {
89 struct userdata *u = userdata;
90 assert(ipv6 && userdata);
92 if (u->count >= MAX_ENTRIES)
95 u->data.ipv6[u->count++] = *ipv6;
96 u->data_len += sizeof(ipv6_address_t);
100 static void name_callback(const char*name, void *userdata) {
101 struct userdata *u = userdata;
102 assert(name && userdata);
104 if (u->count >= MAX_ENTRIES)
107 u->data.name[u->count++] = strdup(name);
108 u->data_len += strlen(name)+1;
111 static int ends_with(const char *name, const char* suffix) {
116 if ((ls = strlen(suffix)) > (ln = strlen(name)))
119 return strcasecmp(name+ln-ls, suffix) == 0;
122 static int verify_name_allowed(const char *name) {
123 return ends_with(name, ".gnunet") || ends_with(name, ".zkey");
126 enum nss_status _nss_gns_gethostbyname2_r(
129 struct hostent * result,
136 enum nss_status status = NSS_STATUS_UNAVAIL;
138 size_t address_length, l, idx, astart;
139 void (*ipv4_func)(const ipv4_address_t *ipv4, void *userdata);
140 void (*ipv6_func)(const ipv6_address_t *ipv6, void *userdata);
155 if (af != AF_INET && af != AF_INET6)
159 *h_errnop = NO_RECOVERY;
164 address_length = af == AF_INET ? sizeof(ipv4_address_t) : sizeof(ipv6_address_t);
166 sizeof(char*)+ /* alias names */
167 strlen(name)+1) { /* official name */
170 *h_errnop = NO_RECOVERY;
171 status = NSS_STATUS_TRYAGAIN;
182 ipv4_func = af == AF_INET ? ipv4_callback : NULL;
188 ipv6_func = af == AF_INET6 ? ipv6_callback : NULL;
192 name_allowed = verify_name_allowed(name);
194 if (gns_works && name_allowed) {
197 if ((r = gns_resolve_name(af, name, data)) < 0)
200 if (af == AF_INET && ipv4_func)
201 ipv4_func((ipv4_address_t*) data, &u);
202 if (af == AF_INET6 && ipv6_func)
203 ipv6_func((ipv6_address_t*)data, &u);
205 status = NSS_STATUS_NOTFOUND;
208 #endif /* ENABLE_GNS */
212 *h_errnop = HOST_NOT_FOUND;
217 *((char**) buffer) = NULL;
218 result->h_aliases = (char**) buffer;
222 strcpy(buffer+idx, name);
223 result->h_name = buffer+idx;
224 idx += strlen(name)+1;
228 result->h_addrtype = af;
229 result->h_length = address_length;
231 /* Check if there's enough space for the addresses */
232 if (buflen < idx+u.data_len+sizeof(char*)*(u.count+1)) {
234 *h_errnop = NO_RECOVERY;
235 status = NSS_STATUS_TRYAGAIN;
241 l = u.count*address_length;
242 memcpy(buffer+astart, &u.data, l);
243 /* address_length is a multiple of 32bits, so idx is still aligned
247 /* Address array address_lenght is always a multiple of 32bits */
248 for (i = 0; i < u.count; i++)
249 ((char**) (buffer+idx))[i] = buffer+astart+address_length*i;
250 ((char**) (buffer+idx))[i] = NULL;
251 result->h_addr_list = (char**) (buffer+idx);
253 status = NSS_STATUS_SUCCESS;
259 enum nss_status _nss_gns_gethostbyname_r (
261 struct hostent *result,
267 return _nss_gns_gethostbyname2_r(
277 enum nss_status _nss_gns_gethostbyaddr_r(
281 struct hostent *result,
287 /* we dont do this */
290 enum nss_status status = NSS_STATUS_UNAVAIL;
292 size_t address_length, idx, astart;
295 *h_errnop = NO_RECOVERY;
300 /* Check for address types */
302 *h_errnop = NO_RECOVERY;
304 status = NSS_STATUS_NOTFOUND;