GNUnet 0.21.0
nss_gns.c
Go to the documentation of this file.
1/***
2 This file is part of nss-gns.
3
4 Parts taken from: nss.c in nss-mdns
5
6 nss-mdns is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 3 of the License,
9 or (at your option) any later version.
10
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.
15
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 USA.
20 ***/
21
22#include <gnunet_private_config.h>
23#include <unistd.h>
24#include <errno.h>
25#include <string.h>
26#include <assert.h>
27#include <netdb.h>
28#include <sys/socket.h>
29#include <nss.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <errno.h>
33
34#include "nss_gns_query.h"
35
36#include <arpa/inet.h>
37
39#define ALIGN(idx) do { \
40 if (idx % sizeof(void*)) \
41 idx += (sizeof(void*) - idx % sizeof(void*)); /* Align on 32 bit boundary */ \
42} while (0)
43
44
57enum nss_status
59 int af,
60 struct hostent *result,
61 char *buffer,
62 size_t buflen,
63 int *errnop,
64 int *h_errnop)
65{
66 struct userdata u;
67 enum nss_status status = NSS_STATUS_UNAVAIL;
68 int i;
69 size_t address_length;
70 size_t l;
71 size_t idx;
72 size_t astart;
73
74 if (af == AF_UNSPEC)
75#ifdef NSS_IPV6_ONLY
76 af = AF_INET6;
77#else
78 af = AF_INET;
79#endif
80
81#ifdef NSS_IPV4_ONLY
82 if (af != AF_INET)
83#elif NSS_IPV6_ONLY
84 if (af != AF_INET6)
85#else
86 if ((af != AF_INET) &&
87 (af != AF_INET6))
88#endif
89 {
90 *errnop = EINVAL;
91 *h_errnop = NO_RECOVERY;
92
93 goto finish;
94 }
95
96 address_length = (af == AF_INET) ? sizeof(ipv4_address_t) :
97 sizeof(ipv6_address_t);
98 if (buflen <
99 sizeof(char*) /* alias names */
100 + strlen (name) + 1)
101 { /* official name */
102 *errnop = ERANGE;
103 *h_errnop = NO_RECOVERY;
104 status = NSS_STATUS_TRYAGAIN;
105
106 goto finish;
107 }
108 u.count = 0;
109 u.data_len = 0;
110 i = gns_resolve_name (af,
111 name,
112 &u);
113 if (-1 == i)
114 {
115 *errnop = errno;
116 status = NSS_STATUS_UNAVAIL;
117 *h_errnop = NO_RECOVERY;
118 goto finish;
119 }
120 if (-2 == i)
121 {
122 *errnop = ENOENT;
123 *h_errnop = NO_RECOVERY;
124 status = NSS_STATUS_UNAVAIL;
125 goto finish;
126 }
127 if (-3 == i)
128 {
129 *errnop = ETIMEDOUT;
130 *h_errnop = HOST_NOT_FOUND;
131 status = NSS_STATUS_NOTFOUND;
132 goto finish;
133 }
134 if (0 == u.count)
135 {
136 *errnop = 0; /* success */
137 *h_errnop = NO_DATA; /* success */
138 status = NSS_STATUS_NOTFOUND;
139 goto finish;
140 }
141 /* Alias names */
142 *((char **) buffer) = NULL;
143 result->h_aliases = (char **) buffer;
144 idx = sizeof(char*);
145
146 /* Official name */
147 strcpy (buffer + idx,
148 name);
149 result->h_name = buffer + idx;
150 idx += strlen (name) + 1;
151
152 ALIGN (idx);
153
154 result->h_addrtype = af;
155 result->h_length = address_length;
156
157 /* Check if there's enough space for the addresses */
158 if (buflen < idx + u.data_len + sizeof(char*) * (u.count + 1))
159 {
160 *errnop = ERANGE;
161 *h_errnop = NO_RECOVERY;
162 status = NSS_STATUS_TRYAGAIN;
163 goto finish;
164 }
165 /* Addresses */
166 astart = idx;
167 l = u.count * address_length;
168 if (0 != l)
169 memcpy (buffer + astart,
170 &u.data,
171 l);
172 /* address_length is a multiple of 32bits, so idx is still aligned
173 * correctly */
174 idx += l;
175
176 /* Address array address_length is always a multiple of 32bits */
177 for (i = 0; i < u.count; i++)
178 ((char **) (buffer + idx))[i] = buffer + astart + address_length * i;
179 ((char **) (buffer + idx))[i] = NULL;
180 result->h_addr_list = (char **) (buffer + idx);
181
182 status = NSS_STATUS_SUCCESS;
183
184finish:
185 return status;
186}
187
188
200enum nss_status
202 struct hostent *result,
203 char *buffer,
204 size_t buflen,
205 int *errnop,
206 int *h_errnop)
207{
209 AF_UNSPEC,
210 result,
211 buffer,
212 buflen,
213 errnop,
214 h_errnop);
215}
216
217
232enum nss_status
234 int len,
235 int af,
236 struct hostent *result,
237 char *buffer,
238 size_t buflen,
239 int *errnop,
240 int *h_errnop)
241{
242 (void) addr;
243 (void) len;
244 (void) af;
245 (void) result;
246 (void) buffer;
247 (void) buflen;
248 *errnop = EINVAL;
249 *h_errnop = NO_RECOVERY;
250 /* NOTE we allow to leak this into DNS so no NOTFOUND */
251 return NSS_STATUS_UNAVAIL;
252}
static mp_limb_t u[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]
static char * name
Name (label) of the records to list.
static int status
The program status; 0 for success.
Definition: gnunet-nse.c:38
static int result
Global testing status.
enum nss_status _nss_gns_gethostbyname_r(const char *name, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop)
The gethostbyname hook executed by nsswitch.
Definition: nss_gns.c:201
enum nss_status _nss_gns_gethostbyname2_r(const char *name, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop)
The gethostbyname hook executed by nsswitch.
Definition: nss_gns.c:58
#define ALIGN(idx)
macro to align idx to 32bit boundary
Definition: nss_gns.c:39
enum nss_status _nss_gns_gethostbyaddr_r(const void *addr, int len, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop)
The gethostbyaddr hook executed by nsswitch We can't do this so we always return NSS_STATUS_UNAVAIL.
Definition: nss_gns.c:233
int gns_resolve_name(int af, const char *name, struct userdata *u)
Wrapper function that uses gnunet-gns cli tool to resolve an IPv4/6 address.
Definition: nss_gns_query.c:58