2 This file is part of nss-gns.
4 Parts taken from: nss.c in nss-mdns
16 #include <sys/socket.h>
21 #elif defined(NSS_IPV4_ONLY)
22 #define _nss_mdns_gethostbyname2_r _nss_gns4_minimal_gethostbyname2_r
23 #define _nss_mdns_gethostbyname_r _nss_gns4_minimal_gethostbyname_r
24 #define _nss_mdns_gethostbyaddr_r _nss_gns4_minimal_gethostbyaddr_r
25 #elif defined(NSS_IPV6_ONLY)
26 #define _nss_mdns_gethostbyname2_r _nss_gns6_gethostbyname2_r
27 #define _nss_mdns_gethostbyname_r _nss_gns6_gethostbyname_r
28 #define _nss_mdns_gethostbyaddr_r _nss_gns6_gethostbyaddr_r
30 #define _nss_mdns_gethostbyname2_r _nss_gns_gethostbyname2_r
31 #define _nss_mdns_gethostbyname_r _nss_gns_gethostbyname_r
32 #define _nss_mdns_gethostbyaddr_r _nss_gns_gethostbyaddr_r
35 /* Maximum number of entries to return */
36 #define MAX_ENTRIES 16
38 #define ALIGN(idx) do { \
39 if (idx % sizeof(void*)) \
40 idx += (sizeof(void*) - idx % sizeof(void*)); /* Align on 32 bit boundary */ \
45 int data_len; /* only valid when doing reverse lookup */
47 ipv4_address_t ipv4[MAX_ENTRIES];
48 ipv6_address_t ipv6[MAX_ENTRIES];
49 char *name[MAX_ENTRIES];
54 static void ipv4_callback(const ipv4_address_t *ipv4, void *userdata) {
55 struct userdata *u = userdata;
56 assert(ipv4 && userdata);
58 if (u->count >= MAX_ENTRIES)
61 u->data.ipv4[u->count++] = *ipv4;
62 u->data_len += sizeof(ipv4_address_t);
67 static void ipv6_callback(const ipv6_address_t *ipv6, void *userdata) {
68 struct userdata *u = userdata;
69 assert(ipv6 && userdata);
71 if (u->count >= MAX_ENTRIES)
74 u->data.ipv6[u->count++] = *ipv6;
75 u->data_len += sizeof(ipv6_address_t);
79 static void name_callback(const char*name, void *userdata) {
80 struct userdata *u = userdata;
81 assert(name && userdata);
83 if (u->count >= MAX_ENTRIES)
86 u->data.name[u->count++] = strdup(name);
87 u->data_len += strlen(name)+1;
90 static int ends_with(const char *name, const char* suffix) {
95 if ((ls = strlen(suffix)) > (ln = strlen(name)))
98 return strcasecmp(name+ln-ls, suffix) == 0;
101 static int verify_name_allowed(const char *name) {
102 return ends_with(name, ".gnunet") || ends_with(name, ".zkey");
105 enum nss_status _nss_gns_gethostbyname2_r(
108 struct hostent * result,
115 enum nss_status status = NSS_STATUS_UNAVAIL;
117 size_t address_length, l, idx, astart;
118 void (*ipv4_func)(const ipv4_address_t *ipv4, void *userdata);
119 void (*ipv6_func)(const ipv6_address_t *ipv6, void *userdata);
134 if (af != AF_INET && af != AF_INET6)
138 *h_errnop = NO_RECOVERY;
143 address_length = af == AF_INET ? sizeof(ipv4_address_t) : sizeof(ipv6_address_t);
145 sizeof(char*)+ /* alias names */
146 strlen(name)+1) { /* official name */
149 *h_errnop = NO_RECOVERY;
150 status = NSS_STATUS_TRYAGAIN;
161 ipv4_func = af == AF_INET ? ipv4_callback : NULL;
167 ipv6_func = af == AF_INET6 ? ipv6_callback : NULL;
171 name_allowed = verify_name_allowed(name);
173 if (gns_works && name_allowed) {
176 if ((r = gns_resolve_name(af, name, data)) < 0)
179 if (af == AF_INET && ipv4_func)
180 ipv4_func((ipv4_address_t*) data, &u);
181 if (af == AF_INET6 && ipv6_func)
182 ipv6_func((ipv6_address_t*)data, &u);
184 status = NSS_STATUS_NOTFOUND;
187 #endif /* ENABLE_GNS */
191 *h_errnop = HOST_NOT_FOUND;
196 *((char**) buffer) = NULL;
197 result->h_aliases = (char**) buffer;
201 strcpy(buffer+idx, name);
202 result->h_name = buffer+idx;
203 idx += strlen(name)+1;
207 result->h_addrtype = af;
208 result->h_length = address_length;
210 /* Check if there's enough space for the addresses */
211 if (buflen < idx+u.data_len+sizeof(char*)*(u.count+1)) {
213 *h_errnop = NO_RECOVERY;
214 status = NSS_STATUS_TRYAGAIN;
220 l = u.count*address_length;
221 memcpy(buffer+astart, &u.data, l);
222 /* address_length is a multiple of 32bits, so idx is still aligned
226 /* Address array address_lenght is always a multiple of 32bits */
227 for (i = 0; i < u.count; i++)
228 ((char**) (buffer+idx))[i] = buffer+astart+address_length*i;
229 ((char**) (buffer+idx))[i] = NULL;
230 result->h_addr_list = (char**) (buffer+idx);
232 status = NSS_STATUS_SUCCESS;
238 enum nss_status _nss_gns_gethostbyname_r (
240 struct hostent *result,
246 return _nss_gns_gethostbyname2_r(
256 enum nss_status _nss_gns_gethostbyaddr_r(
260 struct hostent *result,
266 /* we dont do this */
269 enum nss_status status = NSS_STATUS_UNAVAIL;
271 size_t address_length, idx, astart;
274 *h_errnop = NO_RECOVERY;
279 /* Check for address types */
281 *h_errnop = NO_RECOVERY;
283 status = NSS_STATUS_NOTFOUND;