Skip to content

Instantly share code, notes, and snippets.

@pandax381
Last active November 16, 2016 08:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pandax381/069cc5a1b208383534cd88900ac3d501 to your computer and use it in GitHub Desktop.
Save pandax381/069cc5a1b208383534cd88900ac3d501 to your computer and use it in GitHub Desktop.
libnss-dummy-go
package main
/*
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#include <netdb.h>
#include <nss.h>
#include <syslog.h>
static void
debug(const char *s) {
syslog(LOG_DEBUG, "[cgo] %s", s);
}
#define DUMMY_ADDR_IPV4 (htonl(0x7f000002))
#define DUMMY_ADDR_IPV6 &in6addr_loopback
#define DUMMY_INTERFACE "lo"
#define ALIGN(x) (((x+sizeof(void*)-1)/sizeof(void*))*sizeof(void*))
static inline size_t ADDRLEN (int proto) {
return proto == AF_INET6 ? sizeof(struct in6_addr) : sizeof(struct in_addr);
}
static int
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;
index = if_nametoindex(DUMMY_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, DUMMY_ADDR_IPV6, ADDRLEN(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 = DUMMY_ADDR_IPV4;
tuple->scopeid = (uint32_t) index;
offset += ALIGN(sizeof(struct gaih_addrtuple));
prev = tuple;
*pat = prev;
if (ttlp)
*ttlp = 0;
return NSS_STATUS_SUCCESS;
}
static int
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;
alen = ADDRLEN(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 = DUMMY_ADDR_IPV4;
else
memcpy(addr, DUMMY_ADDR_IPV6, ADDRLEN(AF_INET6));
offset += ALIGN(alen);
// address list
addr_list = buffer + offset;
((char**) addr_list)[0] = addr;
((char**) addr_list)[1] = NULL;
offset += sizeof(char*) * 2;
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;
}
*/
import "C"
import (
"os"
"unsafe"
)
func debug (s string) {
p := C.CString(s)
defer C.free(unsafe.Pointer(p))
C.debug(p)
}
//export _nss_dummy_gethostbyname4_r
func _nss_dummy_gethostbyname4_r (name *C.char, pat **C.struct_gaih_addrtuple, buffer *C.char, buflen C.size_t, errnop *C.int, h_errnop *C.int, ttlp *C.int32_t) C.int {
debug("_nss_dummy_gethostbyname4_r")
return C.nss_dummy_gethostbyname4_r(name, pat, buffer, buflen, errnop, h_errnop, ttlp)
}
func fill_in_hostent (name *C.char, af C.int, result *C.struct_hostent, buffer *C.char, buflen C.size_t, errnop *C.int, h_errnop *C.int, ttlp *C.int32_t, canonp **C.char) C.int {
return C.fill_in_hostent(name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp)
}
//export _nss_dummy_gethostbyname3_r
func _nss_dummy_gethostbyname3_r (name *C.char, af C.int, result *C.struct_hostent, buffer *C.char, buflen C.size_t, errnop *C.int, h_errnop *C.int, ttlp *C.int32_t, canonp **C.char) C.int {
debug("_nss_dummy_gethostbyname3_r")
if af == C.AF_UNSPEC {
af = C.AF_INET
}
if af != C.AF_INET && af != C.AF_INET6 {
*errnop = C.EINVAL
*h_errnop = C.NO_RECOVERY
return C.NSS_STATUS_UNAVAIL
}
return fill_in_hostent(name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp)
}
//export _nss_dummy_gethostbyname2_r
func _nss_dummy_gethostbyname2_r (name *C.char, af C.int, result *C.struct_hostent, buffer *C.char, buflen C.size_t, errnop *C.int, h_errnop *C.int) C.int {
debug("_nss_dummy_gethostbyname2_r")
return _nss_dummy_gethostbyname3_r(name, af, result, buffer, buflen, errnop, h_errnop, nil, nil)
}
//export _nss_dummy_gethostbyname_r
func _nss_dummy_gethostbyname_r (name *C.char, result *C.struct_hostent, buffer *C.char, buflen C.size_t, errnop *C.int, h_errnop *C.int) C.int {
debug("_nss_dummy_gethostbyname_r")
return _nss_dummy_gethostbyname2_r(name, C.AF_INET, result, buffer, buflen, errnop, h_errnop)
}
//export _nss_dummy_gethostbyaddr2_r
func _nss_dummy_gethostbyaddr2_r (addr unsafe.Pointer, len C.socklen_t, af C.int, result *C.struct_hostent, buffer *C.char, buflen C.size_t, errnop *C.int, h_errnop *C.int, ttlp *C.int32_t) C.int {
debug("_nss_dummy_gethostbyaddr2_r")
if len != C.socklen_t(C.ADDRLEN(af)) {
*errnop = C.EINVAL
*h_errnop = C.NO_RECOVERY
return C.NSS_STATUS_UNAVAIL
}
if af != C.AF_INET && af != C.AF_INET6 {
*errnop = C.EAFNOSUPPORT
*h_errnop = C.NO_DATA
return C.NSS_STATUS_UNAVAIL
}
name, err := os.Hostname()
if err != nil {
panic(err)
}
p := C.CString(name)
defer C.free(unsafe.Pointer(p))
return fill_in_hostent(p, af, result, buffer, buflen, errnop, h_errnop, ttlp, nil)
}
//export _nss_dummy_gethostbyaddr_r
func _nss_dummy_gethostbyaddr_r (addr unsafe.Pointer, len C.socklen_t, af C.int, result *C.struct_hostent, buffer *C.char, buflen C.size_t, errnop *C.int, h_errnop *C.int) C.int {
debug("_nss_dummy_gethostbyaddr_r")
return _nss_dummy_gethostbyaddr2_r(addr, len, af, result, buffer, buflen, errnop, h_errnop, nil)
}
func main() {
}
@pandax381
Copy link
Author

pandax381 commented Nov 1, 2016

build & install

$ go build -buildmode=c-shared -o libnss_dummy.so.2 main.go
$ sudo cp libnss_dummy.so.2 /usr/lib

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment