Created
October 27, 2016 09:47
-
-
Save pandax381/a96b7fc08af533d5d868209d6bb49b17 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <limits.h> | |
#include <nss.h> | |
#include <sys/types.h> | |
#include <netdb.h> | |
#include <errno.h> | |
#include <string.h> | |
#include <assert.h> | |
#include <unistd.h> | |
#include <net/if.h> | |
#include <stdlib.h> | |
#include <arpa/inet.h> | |
#ifdef DEBUG | |
#include <syslog.h> | |
#define DBG_TRACE syslog(LOG_DEBUG, "dbg_trace: %s (%d)\n", __FILE__, __LINE__) | |
#else | |
#define DBG_TRACE | |
#endif | |
#define LOCALADDRESS_IPV4 (htonl(0x7F000002)) | |
#define LOCALADDRESS_IPV6 &in6addr_loopback | |
#define LOOPBACK_INTERFACE "lo" | |
#define ALIGN(a) (((a+sizeof(void*)-1)/sizeof(void*))*sizeof(void*)) | |
#define _public_ __attribute__ ((visibility("default"))) | |
inline size_t PROTO_ADDRESS_SIZE(int proto) { | |
assert(proto == AF_INET || proto == AF_INET6); | |
return proto == AF_INET6 ? 16 : 4; | |
} | |
enum nss_status | |
_nss_dummy_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp) _public_; | |
enum nss_status | |
_nss_dummy_gethostbyname3_r (const char *name, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp, char **canonp) _public_; | |
enum nss_status | |
_nss_dummy_gethostbyname2_r (const char *name, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop) _public_; | |
enum nss_status | |
_nss_dummy_gethostbyname_r (const char *name, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop) _public_; | |
enum nss_status | |
_nss_dummy_gethostbyaddr2_r (const void* addr, socklen_t len, int af, struct hostent *host, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp) _public_; | |
enum nss_status | |
_nss_dummy_gethostbyaddr_r (const void* addr, socklen_t len, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop) _public_; | |
enum nss_status | |
_nss_dummy_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp) | |
{ | |
unsigned index; | |
size_t n, offset, size; | |
char *hostname; | |
struct gaih_addrtuple *tuple, *prev = NULL; | |
DBG_TRACE; | |
index = if_nametoindex(LOOPBACK_INTERFACE); | |
n = strlen(name) + 1; | |
size = ALIGN(n) + ALIGN(sizeof(struct gaih_addrtuple)) * 2; | |
if (buflen < size) { | |
*errnop = ENOMEM; | |
*h_errnop = NO_RECOVERY; | |
return NSS_STATUS_TRYAGAIN; | |
} | |
/* hostname */ | |
hostname = buffer; | |
memcpy(hostname, name, n); | |
offset = ALIGN(n); | |
/* AF_INET6 */ | |
tuple = (struct gaih_addrtuple*) (buffer + offset); | |
tuple->next = prev; | |
tuple->name = hostname; | |
tuple->family = AF_INET6; | |
memcpy(tuple->addr, LOCALADDRESS_IPV6, PROTO_ADDRESS_SIZE(AF_INET6)); | |
tuple->scopeid = (uint32_t) index; | |
offset += ALIGN(sizeof(struct gaih_addrtuple)); | |
prev = tuple; | |
/* AF_INET */ | |
tuple = (struct gaih_addrtuple*) (buffer + offset); | |
tuple->next = prev; | |
tuple->name = hostname; | |
tuple->family = AF_INET; | |
*(uint32_t*) tuple->addr = LOCALADDRESS_IPV4; | |
tuple->scopeid = (uint32_t) index; | |
offset += ALIGN(sizeof(struct gaih_addrtuple)); | |
prev = tuple; | |
assert(offset == size); | |
*pat = prev; | |
if (ttlp) | |
*ttlp = 0; | |
return NSS_STATUS_SUCCESS; | |
} | |
static enum nss_status | |
fill_in_hostent (const char *name, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp, char **canonp) | |
{ | |
size_t n, offset, size; | |
char *addr, *hostname, *aliases, *addr_list; | |
size_t alen; | |
DBG_TRACE; | |
alen = PROTO_ADDRESS_SIZE(af); | |
n = strlen(name) + 1; | |
size = ALIGN(n) + sizeof(char*) + ALIGN(alen) + sizeof(char*) * 2; | |
if (buflen < size) { | |
*errnop = ENOMEM; | |
*h_errnop = NO_RECOVERY; | |
return NSS_STATUS_TRYAGAIN; | |
} | |
/* hostname */ | |
hostname = buffer; | |
memcpy(hostname, name, n); | |
offset = ALIGN(n); | |
/* aliases (empty) */ | |
aliases = buffer + offset; | |
*(char**) aliases = NULL; | |
offset += sizeof(char*); | |
/* address */ | |
addr = buffer + offset; | |
if (af == AF_INET) | |
*(uint32_t*) addr = LOCALADDRESS_IPV4; | |
else | |
memcpy(addr, LOCALADDRESS_IPV6, alen); | |
offset += ALIGN(alen); | |
/* address list */ | |
addr_list = buffer + offset; | |
((char**) addr_list)[0] = addr; | |
((char**) addr_list)[1] = NULL; | |
offset += sizeof(char*) * 2; | |
assert(offset == size); | |
result->h_name = hostname; | |
result->h_aliases = (char**) aliases; | |
result->h_addrtype = af; | |
result->h_length = alen; | |
result->h_addr_list = (char**) addr_list; | |
if (ttlp) | |
*ttlp = 0; | |
if (canonp) | |
*canonp = hostname; | |
return NSS_STATUS_SUCCESS; | |
} | |
enum nss_status | |
_nss_dummy_gethostbyname3_r (const char *name, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp, char **canonp) | |
{ | |
DBG_TRACE; | |
if (af == AF_UNSPEC) | |
af = AF_INET; | |
if (af != AF_INET && af != AF_INET6) { | |
*errnop = EINVAL; | |
*h_errnop = NO_RECOVERY; | |
return NSS_STATUS_UNAVAIL; | |
} | |
return fill_in_hostent(name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp); | |
} | |
enum nss_status | |
_nss_dummy_gethostbyname2_r (const char *name, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop) | |
{ | |
DBG_TRACE; | |
return _nss_dummy_gethostbyname3_r(name, af, result, buffer, buflen, errnop, h_errnop, NULL, NULL); | |
} | |
enum nss_status | |
_nss_dummy_gethostbyname_r (const char *name, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop) | |
{ | |
DBG_TRACE; | |
return _nss_dummy_gethostbyname2_r(name, AF_UNSPEC, result, buffer, buflen, errnop, h_errnop); | |
} | |
enum nss_status | |
_nss_dummy_gethostbyaddr2_r (const void* addr, socklen_t len, int af, struct hostent *host, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp) | |
{ | |
char name[HOST_NAME_MAX+1]; | |
DBG_TRACE; | |
if (len != PROTO_ADDRESS_SIZE(af)) { | |
*errnop = EINVAL; | |
*h_errnop = NO_RECOVERY; | |
return NSS_STATUS_UNAVAIL; | |
} | |
if (af != AF_INET && af != AF_INET6) { | |
*errnop = EAFNOSUPPORT; | |
*h_errnop = NO_DATA; | |
return NSS_STATUS_UNAVAIL; | |
} | |
memset(name, 0, sizeof(name)); | |
if (gethostname(name, sizeof(name) - 1) == -1) { | |
*errnop = errno; | |
*h_errnop = NO_RECOVERY; | |
return NSS_STATUS_UNAVAIL; | |
} | |
return fill_in_hostent(name, af, host, buffer, buflen, errnop, h_errnop, ttlp, NULL); | |
} | |
enum nss_status | |
_nss_dummy_gethostbyaddr_r (const void* addr, socklen_t len, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop) | |
{ | |
DBG_TRACE; | |
return _nss_dummy_gethostbyaddr2_r(addr, len, af, result, buffer, buflen, errnop, h_errnop, NULL); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Build & Install
Configuration
Test