Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
*.o
/libnss_docker.so.2
/test
/dockerip
15 changes: 13 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
DESTDIR ?=
NSSDIR ?= /usr/lib
BINDIR ?= /usr/bin


STRIP = strip
CC = gcc
CFLAGS = -fPIC -Wall -Werror -ggdb `pkg-config --cflags glib-2.0`
LDFLAGS = `pkg-config --libs glib-2.0`
Expand All @@ -12,22 +15,30 @@ MODULE = libnss_docker.so.2

BINS = \
$(MODULE) \
test
test dockerip

$(MODULE): $(OBJS) Makefile
$(CC) -fPIC -shared -o $@ -Wl,-soname,$@ $< $(LDFLAGS)

TEST_OBJS = \
test.o

INSPECT_OBJS = \
dockerip.o

test: $(TEST_OBJS) $(MODULE) Makefile
$(CC) -o $@ $< $(LDFLAGS)

dockerip: $(INSPECT_OBJS) $(MODULE) Makefile
$(CC) -o $@ $<
$(STRIP) $@

all: $(BINS)

install: all
mkdir -p $(DESTDIR)$(NSSDIR)
mkdir -p $(DESTDIR)$(NSSDIR) $(DESTDIR)$(BINDIR)
install -m 0644 $(MODULE) $(DESTDIR)$(NSSDIR)/$(MODULE)
install -g docker -m 2755 dockerip $(DESTDIR)$(BINDIR)/dockerip
ldconfig

clean:
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ This is still a work in progress!
Installing
==========

git clone git@github.com:danni/docker-nss.git
Ensure `make`, `gcc`, and `libglib2.0-dev` are installed on the system.

git clone git@github.com:weng-lab/docker-nss.git
cd docker-nss
sudo make all install
sudo sed -i -re 's/^(hosts: .*$)/\1 docker/' /etc/nsswitch.conf
Expand Down
14 changes: 14 additions & 0 deletions dockerip.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include <unistd.h>
#include <string.h>
#include <stdio.h>

int main(int argc, char** argv)
{
// run if one argument was supplied that does not start with '-'
if (argc == 2 && strnlen(argv[1], 255) > 2 && argv[1][0] != '-') {
const char* myargs[] = { "/usr/bin/docker", "inspect", "--format={{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}", argv[1] };
return execlp(myargs[0], myargs[0], myargs[1], myargs[2], myargs[3], NULL);
}
printf("usage: %s <container>\n", argv[0]);
return 1;
}
165 changes: 62 additions & 103 deletions nss.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,185 +29,144 @@
/* define a suffix that containers have */
#define SUFFIX ".docker"

#define ALIGN(a) (((a+sizeof(void*)-1)/sizeof(void*))*sizeof(void*))

static void
pack_hostent(struct hostent *result,
char *buffer,
size_t buflen,
const char *name,
const void *addr)
#define ALIGN(a) (((a + sizeof(void*) - 1) / sizeof(void*)) * sizeof(void*))

static void pack_hostent(struct hostent* result, char* buffer, size_t buflen,
const char* name, const void* addr)
{
char *aliases, *r_addr, *addrlist;
char* aliases, *r_addr, *addrlist;
size_t l, idx;

/* we can't allocate any memory, the buffer is where we need to
* return things we want to use
*
* 1st, the hostname */
* return things we want to use
*
* 1st, the hostname */
l = strlen(name);
result->h_name = buffer;
memcpy (result->h_name, name, l);
memcpy(result->h_name, name, l);
buffer[l] = '\0';

idx = ALIGN (l+1);
idx = ALIGN(l + 1);

/* 2nd, the empty aliases array */
aliases = buffer + idx;
*(char **) aliases = NULL;
idx += sizeof (char*);
*(char**)aliases = NULL;
idx += sizeof(char*);

result->h_aliases = (char **) aliases;
result->h_aliases = (char**)aliases;

result->h_addrtype = AF_INET;
result->h_length = sizeof (struct in_addr);
result->h_length = sizeof(struct in_addr);

/* 3rd, address */
r_addr = buffer + idx;
memcpy(r_addr, addr, result->h_length);
idx += ALIGN (result->h_length);
idx += ALIGN(result->h_length);

/* 4th, the addresses ptr array */
addrlist = buffer + idx;
((char **) addrlist)[0] = r_addr;
((char **) addrlist)[1] = NULL;
((char**)addrlist)[0] = r_addr;
((char**)addrlist)[1] = NULL;

result->h_addr_list = (char **) addrlist;
result->h_addr_list = (char**)addrlist;
}

static gboolean
lookup_container_ip (const char *name,
struct in_addr *addr)
static gboolean lookup_container_ip(const char* name, struct in_addr* addr)
{
char *stdout_s, *name_s;
char* stdout_s, *name_s;
int exit_status;
gboolean success = FALSE;

/* remove the suffix */
name_s = g_strdup (name);
name_s = g_strdup(name);
*strrchr(name_s, '.') = '\0';

char *argv[] = {
"docker",
"inspect",
"-format={{.NetworkSettings.IPAddress}}",
name_s,
NULL,
};

if (!g_spawn_sync(NULL,
argv,
NULL,
G_SPAWN_STDERR_TO_DEV_NULL | G_SPAWN_SEARCH_PATH,
NULL, NULL,
&stdout_s, NULL,
&exit_status,
NULL))
{
goto finally;
}

if (exit_status != 0)
{
char* argv[] = { "/usr/bin/dockerip", name_s, NULL, };

if (!g_spawn_sync(NULL, argv, NULL,
G_SPAWN_STDERR_TO_DEV_NULL | G_SPAWN_SEARCH_PATH, NULL,
NULL, &stdout_s, NULL, &exit_status, NULL)) {
goto finally;
}
}

stdout_s = g_strstrip (stdout_s);
success = inet_aton (stdout_s, addr);
if (exit_status != 0) {
goto finally;
}

stdout_s = g_strstrip(stdout_s);
success = inet_aton(stdout_s, addr);

finally:

g_free (name_s);
g_free (stdout_s);
g_free(name_s);
g_free(stdout_s);

return success;
}

enum nss_status
_nss_docker_gethostbyname2_r (const char *name,
int af,
struct hostent *result,
char *buffer,
size_t buflen,
int *errnop,
int *h_errnop)
enum nss_status _nss_docker_gethostbyname2_r(const char* name, int af,
struct hostent* result,
char* buffer, size_t buflen,
int* errnop, int* h_errnop)
{
struct in_addr addr;

if (af != AF_INET)
{
if (af != AF_INET) {
*errnop = EAFNOSUPPORT;
*h_errnop = NO_DATA;
return NSS_STATUS_UNAVAIL;
}
}

if (!g_str_has_suffix(name, SUFFIX))
{
if (!g_str_has_suffix(name, SUFFIX)) {
*errnop = ENOENT;
*h_errnop = HOST_NOT_FOUND;
return NSS_STATUS_NOTFOUND;
}
}

if (!lookup_container_ip (name, &addr))
{
if (!lookup_container_ip(name, &addr)) {
*errnop = ENOENT;
*h_errnop = HOST_NOT_FOUND;
return NSS_STATUS_NOTFOUND;
}
}

pack_hostent(result, buffer, buflen, name, &addr);

return NSS_STATUS_SUCCESS;
}

enum nss_status
_nss_docker_gethostbyname_r (const char *name,
struct hostent *result,
char *buffer,
size_t buflen,
int *errnop,
int *h_errnop)
enum nss_status _nss_docker_gethostbyname_r(const char* name,
struct hostent* result,
char* buffer, size_t buflen,
int* errnop, int* h_errnop)
{
return _nss_docker_gethostbyname2_r(name,
AF_INET,
result,
buffer,
buflen,
errnop,
h_errnop);
return _nss_docker_gethostbyname2_r(name, AF_INET, result, buffer, buflen,
errnop, h_errnop);
}

enum nss_status
_nss_docker_gethostbyaddr_r (const void *addr,
socklen_t len,
int af,
struct hostent *result,
char *buffer,
size_t buflen,
int *errnop,
int *h_errnop)
enum nss_status _nss_docker_gethostbyaddr_r(const void* addr, socklen_t len,
int af, struct hostent* result,
char* buffer, size_t buflen,
int* errnop, int* h_errnop)
{
if (af != AF_INET)
{
if (af != AF_INET) {
*errnop = EAFNOSUPPORT;
*h_errnop = NO_DATA;
return NSS_STATUS_UNAVAIL;
}
}

if (len != sizeof (struct in_addr))
{
if (len != sizeof(struct in_addr)) {
*errnop = EINVAL;
*h_errnop = NO_RECOVERY;
return NSS_STATUS_UNAVAIL;
}
}

/* FIXME: need to implement reverse lookups */
*errnop = EAFNOSUPPORT;
*h_errnop = NO_DATA;
return NSS_STATUS_UNAVAIL;
/*
pack_hostent(result, buffer, buflen, "container.docker", addr);
pack_hostent(result, buffer, buflen, "container.docker", addr);

return NSS_STATUS_SUCCESS;
*/
return NSS_STATUS_SUCCESS;
*/
}
Loading