GNUnet  0.11.x
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_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 
57 enum 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 
184 finish:
185  return status;
186 }
187 
188 
200 enum nss_status
202  struct hostent *result,
203  char *buffer,
204  size_t buflen,
205  int *errnop,
206  int *h_errnop)
207 {
208  return _nss_gns_gethostbyname2_r (name,
209  AF_UNSPEC,
210  result,
211  buffer,
212  buflen,
213  errnop,
214  h_errnop);
215 }
216 
217 
232 enum nss_status
233 _nss_gns_gethostbyaddr_r (const void*addr,
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 }
#define ALIGN(idx)
macro to align idx to 32bit boundary
Definition: nss_gns.c:39
static struct LoggingHandle * l
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
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
uint16_t status
See PRISM_STATUS_*-constants.
static int result
Global testing status.
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
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&#39;t do this so we always return NSS_STATUS_UNAVAIL.
Definition: nss_gns.c:233
const char * name
int data_len
Definition: nss_gns_query.h:46
union userdata::@21 data
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...