/*
- * Copyright (C) Stefan Metzmacher 2007 <metze@samba.org>
- * Copyright (C) Guenther Deschner 2009 <gd@samba.org>
- * Copyright (C) Andreas Schneider 2013 <asn@samba.org>
+ * BSD 3-Clause License
*
+ * Copyright (c) 2007, Stefan Metzmacher <metze@samba.org>
+ * Copyright (c) 2009, Guenther Deschner <gd@samba.org>
+ * Copyright (c) 2014-2015, Michael Adam <obnox@samba.org>
+ * Copyright (c) 2015, Robin Hack <hack.robin@gmail.com>
+ * Copyright (c) 2013-2018, Andreas Schneider <asn@samba.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#define PRINTF_ATTRIBUTE(a,b)
#endif /* HAVE_ATTRIBUTE_PRINTF_FORMAT */
+#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
+#define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
+#else
+#define CONSTRUCTOR_ATTRIBUTE
+#endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
+
#ifdef HAVE_DESTRUCTOR_ATTRIBUTE
#define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
#else
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
#endif
+#ifndef discard_const
+#define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
+#endif
+
+#ifndef discard_const_p
+#define discard_const_p(type, ptr) ((type *)discard_const(ptr))
+#endif
+
#ifdef HAVE_IPV6
#define NWRAP_INET_ADDRSTRLEN INET6_ADDRSTRLEN
#else
NWRAP_UNLOCK(nwrap_initialized); \
} while (0);
+static void nwrap_init(void);
+
static void nwrap_thread_prepare(void)
{
+ nwrap_init();
NWRAP_LOCK_ALL;
}
NWRAP_LOG_TRACE
};
-#ifdef NDEBUG
-# define NWRAP_LOG(...)
+#ifndef HAVE_GETPROGNAME
+static const char *getprogname(void)
+{
+#if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
+ return program_invocation_short_name;
+#elif defined(HAVE_GETEXECNAME)
+ return getexecname();
#else
+ return NULL;
+#endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
+}
+#endif /* HAVE_GETPROGNAME */
static void nwrap_log(enum nwrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
# define NWRAP_LOG(dbglvl, ...) nwrap_log((dbglvl), __func__, __VA_ARGS__)
va_list va;
const char *d;
unsigned int lvl = 0;
- int pid = getpid();
+ const char *prefix = "NWRAP";
+ const char *progname = getprogname();
d = getenv("NSS_WRAPPER_DEBUGLEVEL");
if (d != NULL) {
lvl = atoi(d);
}
+ if (lvl < dbglvl) {
+ return;
+ }
+
va_start(va, format);
vsnprintf(buffer, sizeof(buffer), format, va);
va_end(va);
- if (lvl >= dbglvl) {
- switch (dbglvl) {
- case NWRAP_LOG_ERROR:
- fprintf(stderr,
- "NWRAP_ERROR(%d) - %s: %s\n",
- pid, func, buffer);
- break;
- case NWRAP_LOG_WARN:
- fprintf(stderr,
- "NWRAP_WARN(%d) - %s: %s\n",
- pid, func, buffer);
- break;
- case NWRAP_LOG_DEBUG:
- fprintf(stderr,
- "NWRAP_DEBUG(%d) - %s: %s\n",
- pid, func, buffer);
- break;
- case NWRAP_LOG_TRACE:
- fprintf(stderr,
- "NWRAP_TRACE(%d) - %s: %s\n",
- pid, func, buffer);
- break;
- }
+ switch (dbglvl) {
+ case NWRAP_LOG_ERROR:
+ prefix = "NWRAP_ERROR";
+ break;
+ case NWRAP_LOG_WARN:
+ prefix = "NWRAP_WARN";
+ break;
+ case NWRAP_LOG_DEBUG:
+ prefix = "NWRAP_DEBUG";
+ break;
+ case NWRAP_LOG_TRACE:
+ prefix = "NWRAP_TRACE";
+ break;
}
+
+ if (progname == NULL) {
+ progname = "<unknown>";
+ }
+
+ fprintf(stderr,
+ "%s[%s (%u)] - %s: %s\n",
+ prefix,
+ progname,
+ (unsigned int)getpid(),
+ func,
+ buffer);
}
-#endif /* NDEBUG NWRAP_LOG */
struct nwrap_libc_fns {
struct passwd *(*_libc_getpwnam)(const char *name);
int (*_libc_getpwuid_r)(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result);
void (*_libc_setpwent)(void);
struct passwd *(*_libc_getpwent)(void);
-#ifdef HAVE_SOLARIS_GETPWENT_R
+#ifdef HAVE_GETPWENT_R
+# ifdef HAVE_SOLARIS_GETPWENT_R
struct passwd *(*_libc_getpwent_r)(struct passwd *pwbuf, char *buf, size_t buflen);
-#else
+# else /* HAVE_SOLARIS_GETPWENT_R */
int (*_libc_getpwent_r)(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp);
-#endif
+# endif /* HAVE_SOLARIS_GETPWENT_R */
+#endif /* HAVE_GETPWENT_R */
void (*_libc_endpwent)(void);
int (*_libc_initgroups)(const char *user, gid_t gid);
struct group *(*_libc_getgrnam)(const char *name);
int (*_libc_getgrgid_r)(gid_t gid, struct group *grp, char *buf, size_t buflen, struct group **result);
void (*_libc_setgrent)(void);
struct group *(*_libc_getgrent)(void);
-#ifdef HAVE_SOLARIS_GETGRENT_R
+#ifdef HAVE_GETGRENT_R
+# ifdef HAVE_SOLARIS_GETGRENT_R
struct group *(*_libc_getgrent_r)(struct group *group, char *buf, size_t buflen);
-#else
+# else /* HAVE_SOLARIS_GETGRENT_R */
int (*_libc_getgrent_r)(struct group *group, char *buf, size_t buflen, struct group **result);
-#endif
+# endif /* HAVE_SOLARIS_GETGRENT_R */
+#endif /* HAVE_GETGRENT_R */
void (*_libc_endgrent)(void);
int (*_libc_getgrouplist)(const char *user, gid_t group, gid_t *groups, int *ngroups);
NSS_STATUS (*_nss_getgrent_r)(struct group *result, char *buffer,
size_t buflen, int *errnop);
NSS_STATUS (*_nss_endgrent)(void);
+ NSS_STATUS (*_nss_gethostbyaddr_r)(const void *addr, socklen_t addrlen,
+ int af, struct hostent *result,
+ char *buffer, size_t buflen,
+ int *errnop, int *h_errnop);
+ NSS_STATUS (*_nss_gethostbyname2_r)(const char *name, int af,
+ struct hostent *result,
+ char *buffer, size_t buflen,
+ int *errnop, int *h_errnop);
};
struct nwrap_backend {
struct nwrap_module_nss_fns *fns;
};
+struct nwrap_vector;
+
struct nwrap_ops {
struct passwd * (*nw_getpwnam)(struct nwrap_backend *b,
const char *name);
struct group *grdst, char *buf,
size_t buflen, struct group **grdstp);
void (*nw_endgrent)(struct nwrap_backend *b);
+ struct hostent *(*nw_gethostbyaddr)(struct nwrap_backend *b,
+ const void *addr,
+ socklen_t len, int type);
+ struct hostent *(*nw_gethostbyname)(struct nwrap_backend *b,
+ const char *name);
+ struct hostent *(*nw_gethostbyname2)(struct nwrap_backend *b,
+ const char *name, int af);
+ int (*nw_gethostbyname2_r)(struct nwrap_backend *b,
+ const char *name, int af,
+ struct hostent *hedst,
+ char *buf, size_t buflen,
+ struct hostent **hedstp);
};
/* Public prototypes */
struct group *grdst, char *buf,
size_t buflen, struct group **grdstp);
static void nwrap_files_endgrent(struct nwrap_backend *b);
+static struct hostent *nwrap_files_gethostbyaddr(struct nwrap_backend *b,
+ const void *addr,
+ socklen_t len, int type);
+static struct hostent *nwrap_files_gethostbyname(struct nwrap_backend *b,
+ const char *name);
+static struct hostent *nwrap_files_gethostbyname2(struct nwrap_backend *b,
+ const char *name, int af);
+static int nwrap_files_gethostbyname2_r(struct nwrap_backend *b,
+ const char *name, int af,
+ struct hostent *hedst,
+ char *buf, size_t buflen,
+ struct hostent **hedstp);
/* prototypes for module backend */
static void nwrap_module_endgrent(struct nwrap_backend *b);
static int nwrap_module_initgroups(struct nwrap_backend *b,
const char *user, gid_t group);
+static struct hostent *nwrap_module_gethostbyaddr(struct nwrap_backend *b,
+ const void *addr,
+ socklen_t len, int type);
+static struct hostent *nwrap_module_gethostbyname(struct nwrap_backend *b,
+ const char *name);
+static struct hostent *nwrap_module_gethostbyname2(struct nwrap_backend *b,
+ const char *name, int af);
+static int nwrap_module_gethostbyname2_r(struct nwrap_backend *b,
+ const char *name, int af,
+ struct hostent *hedst,
+ char *buf, size_t buflen,
+ struct hostent **hedstp);
struct nwrap_ops nwrap_files_ops = {
.nw_getpwnam = nwrap_files_getpwnam,
.nw_getgrent = nwrap_files_getgrent,
.nw_getgrent_r = nwrap_files_getgrent_r,
.nw_endgrent = nwrap_files_endgrent,
+ .nw_gethostbyaddr = nwrap_files_gethostbyaddr,
+ .nw_gethostbyname = nwrap_files_gethostbyname,
+ .nw_gethostbyname2 = nwrap_files_gethostbyname2,
+ .nw_gethostbyname2_r = nwrap_files_gethostbyname2_r,
};
struct nwrap_ops nwrap_module_ops = {
.nw_getgrent = nwrap_module_getgrent,
.nw_getgrent_r = nwrap_module_getgrent_r,
.nw_endgrent = nwrap_module_endgrent,
+ .nw_gethostbyaddr = nwrap_module_gethostbyaddr,
+ .nw_gethostbyname = nwrap_module_gethostbyname,
+ .nw_gethostbyname2 = nwrap_module_gethostbyname2,
+ .nw_gethostbyname2_r = nwrap_module_gethostbyname2_r,
};
struct nwrap_libc {
};
struct nwrap_main {
- int num_backends;
+ size_t num_backends;
struct nwrap_backend *backends;
struct nwrap_libc *libc;
};
struct nwrap_he {
struct nwrap_cache *cache;
- struct nwrap_vector entdata;
+ struct nwrap_vector entries;
+ struct nwrap_vector lists;
int num;
int idx;
* NWRAP PROTOTYPES
*********************************************************/
-static void nwrap_init(void);
static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line);
static void nwrap_gr_unload(struct nwrap_cache *nwrap);
+void nwrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
void nwrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
/*********************************************************
NWRAP_LIBSOCKET,
};
-#ifndef NDEBUG
static const char *nwrap_str_lib(enum nwrap_lib lib)
{
switch (lib) {
/* Compiler would warn us about unhandled enum value if we get here */
return "unknown";
}
-#endif
static void *nwrap_load_lib_handle(enum nwrap_lib lib)
{
int i;
#ifdef RTLD_DEEPBIND
- flags |= RTLD_DEEPBIND;
+ const char *env_preload = getenv("LD_PRELOAD");
+ const char *env_deepbind = getenv("NSS_WRAPPER_DISABLE_DEEPBIND");
+ bool enable_deepbind = true;
+
+ /* Don't do a deepbind if we run with libasan */
+ if (env_preload != NULL && strlen(env_preload) < 1024) {
+ const char *p = strstr(env_preload, "libasan.so");
+ if (p != NULL) {
+ enable_deepbind = false;
+ }
+ }
+
+ if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
+ enable_deepbind = false;
+ }
+
+ if (enable_deepbind) {
+ flags |= RTLD_DEEPBIND;
+ }
#endif
switch (lib) {
return nwrap_main_global->libc->fns->_libc_getpwent();
}
-#ifdef HAVE_SOLARIS_GETPWENT_R
+#ifdef HAVE_GETPWENT_R
+# ifdef HAVE_SOLARIS_GETPWENT_R
static struct passwd *libc_getpwent_r(struct passwd *pwdst,
char *buf,
int buflen)
buf,
buflen);
}
-#else /* HAVE_SOLARIS_GETPWENT_R */
+# else /* HAVE_SOLARIS_GETPWENT_R */
static int libc_getpwent_r(struct passwd *pwdst,
char *buf,
size_t buflen,
buflen,
pwdstp);
}
-#endif /* HAVE_SOLARIS_GETPWENT_R */
+# endif /* HAVE_SOLARIS_GETPWENT_R */
+#endif /* HAVE_GETPWENT_R */
static void libc_endpwent(void)
{
}
#ifdef HAVE_GETGRENT_R
-#ifdef HAVE_SOLARIS_GETGRENT_R
+# ifdef HAVE_SOLARIS_GETGRENT_R
static struct group *libc_getgrent_r(struct group *group,
char *buf,
size_t buflen)
buf,
buflen);
}
-#else /* !HAVE_SOLARIS_GETGRENT_R */
+# else /* HAVE_SOLARIS_GETGRENT_R */
static int libc_getgrent_r(struct group *group,
char *buf,
size_t buflen,
buflen,
result);
}
-#endif /* HAVE_SOLARIS_GETGRENT_R */
+# endif /* HAVE_SOLARIS_GETGRENT_R */
#endif /* HAVE_GETGRENT_R */
static void libc_endgrent(void)
static void *nwrap_load_module_fn(struct nwrap_backend *b,
const char *fn_name)
{
- void *res;
- char *s;
+ void *res = NULL;
+ char *s = NULL;
+ int rc;
- if (!b->so_handle) {
+ if (b->so_handle == NULL) {
NWRAP_LOG(NWRAP_LOG_ERROR, "No handle");
return NULL;
}
- if (asprintf(&s, "_nss_%s_%s", b->name, fn_name) == -1) {
+ rc = asprintf(&s, "_nss_%s_%s", b->name, fn_name);
+ if (rc == -1) {
NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
return NULL;
}
res = dlsym(b->so_handle, s);
- if (!res) {
+ if (res == NULL) {
NWRAP_LOG(NWRAP_LOG_ERROR,
"Cannot find function %s in %s",
s, b->so_path);
nwrap_load_module_fn(b, "getgrent_r");
*(void **)(&fns->_nss_endgrent) =
nwrap_load_module_fn(b, "endgrent");
+ *(void **)(&fns->_nss_gethostbyaddr_r) =
+ nwrap_load_module_fn(b, "gethostbyaddr_r");
+ *(void **)(&fns->_nss_gethostbyname2_r) =
+ nwrap_load_module_fn(b, "gethostbyname2_r");
return fns;
}
static bool nwrap_module_init(const char *name,
struct nwrap_ops *ops,
const char *so_path,
- int *num_backends,
+ size_t *num_backends,
struct nwrap_backend **backends)
{
struct nwrap_backend *b;
static void nwrap_libc_init(struct nwrap_main *r)
{
- r->libc = malloc(sizeof(struct nwrap_libc));
+ r->libc = calloc(1, sizeof(struct nwrap_libc));
if (r->libc == NULL) {
printf("Failed to allocate memory for libc");
exit(-1);
}
- ZERO_STRUCTP(r->libc);
- r->libc->fns = malloc(sizeof(struct nwrap_libc_fns));
+ r->libc->fns = calloc(1, sizeof(struct nwrap_libc_fns));
if (r->libc->fns == NULL) {
printf("Failed to allocate memory for libc functions");
exit(-1);
}
- ZERO_STRUCTP(r->libc->fns);
}
static void nwrap_backend_init(struct nwrap_main *r)
const char *env;
char *endptr;
size_t max_hostents_tmp;
+ int ok;
NWRAP_LOCK(nwrap_initialized);
if (nwrap_initialized) {
nwrap_initialized = true;
- /* Initialize pthread_atfork handlers */
- pthread_atfork(&nwrap_thread_prepare, &nwrap_thread_parent,
- &nwrap_thread_child);
-
env = getenv("NSS_WRAPPER_MAX_HOSTENTS");
if (env != NULL) {
- max_hostents_tmp = (size_t)strtol(env, &endptr, 10);
- if (((env != '\0') && (endptr == '\0')) ||
+ max_hostents_tmp = (size_t)strtoul(env, &endptr, 10);
+ if ((*env == '\0') ||
+ (*endptr != '\0') ||
(max_hostents_tmp == 0)) {
NWRAP_LOG(NWRAP_LOG_DEBUG,
"Error parsing NSS_WRAPPER_MAX_HOSTENTS "
NWRAP_LOG(NWRAP_LOG_DEBUG,
"Initializing hash table of size %lu items.",
(unsigned long)max_hostents);
- if (hcreate(max_hostents) == 0) {
+ ok = hcreate(max_hostents);
+ if (!ok) {
NWRAP_LOG(NWRAP_LOG_ERROR,
"Failed to initialize hash table");
- goto done;
+ exit(-1);
}
nwrap_main_global = &__nwrap_main_global;
nwrap_he_global.cache->parse_line = nwrap_he_parse_line;
nwrap_he_global.cache->unload = nwrap_he_unload;
-done:
/* We hold all locks here so we can use NWRAP_UNLOCK_ALL. */
NWRAP_UNLOCK_ALL;
}
NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]\n", pw->pw_gid);
+#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
+ pw->pw_class = discard_const_p(char, "");
+
+ NWRAP_LOG(NWRAP_LOG_TRACE, "class[%s]", pw->pw_class);
+#endif /* HAVE_STRUCT_PASSWD_PW_CLASS */
+
+#ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
+ pw->pw_change = 0;
+
+ NWRAP_LOG(NWRAP_LOG_TRACE,
+ "change[%lu]",
+ (unsigned long)pw->pw_change);
+#endif /* HAVE_STRUCT_PASSWD_PW_CHANGE */
+
+#ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
+ pw->pw_expire = 0;
+
+ NWRAP_LOG(NWRAP_LOG_TRACE,
+ "expire[%lu]",
+ (unsigned long)pw->pw_expire);
+#endif /* HAVE_STRUCT_PASSWD_PW_EXPIRE */
+
/* gecos */
p = strchr(c, ':');
if (!p) {
dst->pw_passwd = buf + ofs;
dst->pw_uid = src->pw_uid;
dst->pw_gid = src->pw_gid;
+#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
+ ofs = PTR_DIFF(src->pw_class, first);
+ dst->pw_class = buf + ofs;
+#endif /* HAVE_STRUCT_PASSWD_PW_CLASS */
+
+#ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
+ dst->pw_change = 0;
+#endif /* HAVE_STRUCT_PASSWD_PW_CHANGE */
+
+#ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
+ dst->pw_expire = 0;
+#endif /* HAVE_STRUCT_PASSWD_PW_EXPIRE */
+
ofs = PTR_DIFF(src->pw_gecos, first);
dst->pw_gecos = buf + ofs;
ofs = PTR_DIFF(src->pw_dir, first);
}
gr->gr_mem[0] = NULL;
- for(nummem=0; p; nummem++) {
+ for(nummem = 0; p != NULL && p[0] != '\0'; nummem++) {
char **m;
size_t m_size;
c = p;
static int nwrap_gr_copy_r(const struct group *src, struct group *dst,
char *buf, size_t buflen, struct group **dstp)
{
- char *first;
- char **lastm;
- char *last = NULL;
- off_t ofsb;
- off_t ofsm;
- off_t ofs;
+ char *p = NULL;
+ uintptr_t align = 0;
+ unsigned int gr_mem_cnt = 0;
unsigned i;
+ size_t total_len;
+ size_t gr_name_len = strlen(src->gr_name) + 1;
+ size_t gr_passwd_len = strlen(src->gr_passwd) + 1;
+ union {
+ char *ptr;
+ char **data;
+ } g_mem;
+
+ for (i = 0; src->gr_mem[i] != NULL; i++) {
+ gr_mem_cnt++;
+ }
+
+ /* Align the memory for storing pointers */
+ align = __alignof__(char *) - ((p - (char *)0) % __alignof__(char *));
+ total_len = align +
+ (1 + gr_mem_cnt) * sizeof(char *) +
+ gr_name_len + gr_passwd_len;
+
+ if (total_len > buflen) {
+ errno = ERANGE;
+ return -1;
+ }
+ buflen -= total_len;
- first = src->gr_name;
+ /* gr_mem */
+ p = buf + align;
+ g_mem.ptr = p;
+ dst->gr_mem = g_mem.data;
- lastm = src->gr_mem;
- while (*lastm) {
- last = *lastm;
- lastm++;
- }
+ /* gr_name */
+ p += (1 + gr_mem_cnt) * sizeof(char *);
+ dst->gr_name = p;
- if (last == NULL) {
- last = src->gr_passwd;
- }
- while (*last) last++;
+ /* gr_passwd */
+ p += gr_name_len;
+ dst->gr_passwd = p;
- ofsb = PTR_DIFF(last + 1, first);
- ofsm = PTR_DIFF(lastm + 1, src->gr_mem);
+ /* gr_mem[x] */
+ p += gr_passwd_len;
- if ((ofsb + ofsm) > (off_t) buflen) {
- return ERANGE;
+ /* gr_gid */
+ dst->gr_gid = src->gr_gid;
+
+ memcpy(dst->gr_name, src->gr_name, gr_name_len);
+
+ memcpy(dst->gr_passwd, src->gr_passwd, gr_passwd_len);
+
+ /* Set the terminating entry */
+ dst->gr_mem[gr_mem_cnt] = NULL;
+
+ /* Now add the group members content */
+ total_len = 0;
+ for (i = 0; i < gr_mem_cnt; i++) {
+ size_t len = strlen(src->gr_mem[i]) + 1;
+
+ dst->gr_mem[i] = p;
+ total_len += len;
+ p += len;
}
- memcpy(buf, first, ofsb);
- memcpy(buf + ofsb, src->gr_mem, ofsm);
+ if (total_len > buflen) {
+ errno = ERANGE;
+ return -1;
+ }
- ofs = PTR_DIFF(src->gr_name, first);
- dst->gr_name = buf + ofs;
- ofs = PTR_DIFF(src->gr_passwd, first);
- dst->gr_passwd = buf + ofs;
- dst->gr_gid = src->gr_gid;
+ for (i = 0; i < gr_mem_cnt; i++) {
+ size_t len = strlen(src->gr_mem[i]) + 1;
- dst->gr_mem = (char **)(buf + ofsb);
- for (i=0; src->gr_mem[i]; i++) {
- ofs = PTR_DIFF(src->gr_mem[i], first);
- dst->gr_mem[i] = buf + ofs;
+ memcpy(dst->gr_mem[i],
+ src->gr_mem[i],
+ len);
}
- if (dstp) {
+ if (dstp != NULL) {
*dstp = dst;
}
ENTRY e;
ENTRY *p;
struct nwrap_entlist *el;
+ bool ok;
if (h_name == NULL) {
NWRAP_LOG(NWRAP_LOG_ERROR, "h_name NULL - can't add");
p = hsearch(e, ENTER);
if (p == NULL) {
- NWRAP_LOG(NWRAP_LOG_ERROR, "Hash table is full!");
+ NWRAP_LOG(NWRAP_LOG_ERROR,
+ "Hash table is full (%s)!",
+ strerror(errno));
+ return false;
+ }
+
+ ok = nwrap_vector_add_item(&(nwrap_he_global.lists), (void *)el);
+ if (!ok) {
+ NWRAP_LOG(NWRAP_LOG_ERROR,
+ "Failed to add list entry to vector.");
return false;
}
for (cursor = el; cursor->next != NULL; cursor = cursor->next)
{
if (cursor->ed == ed) {
- return false;
+ /* The entry already exists in this list. */
+ return true;
}
}
if (cursor->ed == ed) {
- return false;
+ /* The entry already exists in this list. */
+ return true;
}
el_new = nwrap_entlist_init(ed);
}
ip = i;
- nwrap_vector_add_item(&(ed->nwrap_addrdata),
- (void *const)ed->addr.host_addr);
+ ok = nwrap_vector_add_item(&(ed->nwrap_addrdata),
+ (void *const)ed->addr.host_addr);
+ if (!ok) {
+ NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add addrdata to vector");
+ free(ed);
+ return false;
+ }
ed->ht.h_addr_list = nwrap_vector_head(&ed->nwrap_addrdata);
p++;
aliases_count += 1;
}
- nwrap_vector_add_item(&(nwrap_he->entdata), (void *const)ed);
+ ok = nwrap_vector_add_item(&(nwrap_he->entries), (void *const)ed);
+ if (!ok) {
+ NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add entry to vector");
+ free(ed);
+ return false;
+ }
ed->aliases_count = aliases_count;
/* Inventarize item */
struct nwrap_he *nwrap_he =
(struct nwrap_he *)nwrap->private_data;
struct nwrap_entdata *ed;
+ struct nwrap_entlist *el;
size_t i;
+ int rc;
- nwrap_vector_foreach (ed, nwrap_he->entdata, i)
+ nwrap_vector_foreach (ed, nwrap_he->entries, i)
{
SAFE_FREE(ed->nwrap_addrdata.items);
SAFE_FREE(ed->ht.h_aliases);
SAFE_FREE(ed);
}
- SAFE_FREE(nwrap_he->entdata.items);
- nwrap_he->entdata.count = nwrap_he->entdata.capacity = 0;
+ SAFE_FREE(nwrap_he->entries.items);
+ nwrap_he->entries.count = nwrap_he->entries.capacity = 0;
+
+ nwrap_vector_foreach(el, nwrap_he->lists, i)
+ {
+ while (el != NULL) {
+ struct nwrap_entlist *el_next;
+
+ el_next = el->next;
+ SAFE_FREE(el);
+ el = el_next;
+ }
+ }
+ SAFE_FREE(nwrap_he->lists.items);
+ nwrap_he->lists.count = nwrap_he->lists.capacity = 0;
nwrap_he->num = 0;
nwrap_he->idx = 0;
+
+ /*
+ * If we unload the file, the pointers in the hash table point to
+ * invalid memory. So we need to destroy the hash table and recreate
+ * it.
+ */
+ hdestroy();
+ rc = hcreate(max_hostents);
+ if (rc == 0) {
+ NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to initialize hash table");
+ exit(-1);
+ }
}
}
/* hosts functions */
-static int nwrap_files_gethostbyname(const char *name, int af,
- struct hostent *result,
- struct nwrap_vector *addr_list)
+static int nwrap_files_internal_gethostbyname(const char *name, int af,
+ struct hostent *result,
+ struct nwrap_vector *addr_list)
{
struct nwrap_entlist *el;
struct hostent *he;
name_len = strlen(name);
if (name_len < sizeof(canon_name) && name[name_len - 1] == '.') {
- strncpy(canon_name, name, name_len - 1);
+ memcpy(canon_name, name, name_len - 1);
+ canon_name[name_len] = '\0';
name = canon_name;
}
return -1;
}
-#ifdef HAVE_GETHOSTBYNAME_R
-static int nwrap_gethostbyname_r(const char *name,
- struct hostent *ret,
- char *buf, size_t buflen,
- struct hostent **result, int *h_errnop)
+static int nwrap_files_gethostbyname2_r(struct nwrap_backend *b,
+ const char *name, int af,
+ struct hostent *hedst,
+ char *buf, size_t buflen,
+ struct hostent **hedstp)
{
struct nwrap_vector *addr_list = malloc(sizeof(struct nwrap_vector));
+ union {
+ char *ptr;
+ char **list;
+ } g;
int rc;
+ (void) b; /* unused */
+ (void) af; /* unused */
+
if (addr_list == NULL) {
NWRAP_LOG(NWRAP_LOG_ERROR,
"Unable to allocate memory for address list");
ZERO_STRUCTP(addr_list);
- rc = nwrap_files_gethostbyname(name, AF_UNSPEC, ret, addr_list);
+ rc = nwrap_files_internal_gethostbyname(name, AF_UNSPEC, hedst,
+ addr_list);
if (rc == -1) {
- *h_errnop = h_errno;
if (addr_list->items != NULL) {
free(addr_list->items);
}
free(addr_list->items);
free(addr_list);
- ret->h_addr_list = (char **)buf;
- *result = ret;
+ g.ptr = buf;
+ hedst->h_addr_list = g.list;
+ *hedstp = hedst;
return 0;
}
+#ifdef HAVE_GETHOSTBYNAME_R
+static int nwrap_gethostbyname_r(const char *name,
+ struct hostent *ret,
+ char *buf, size_t buflen,
+ struct hostent **result, int *h_errnop)
+{
+ int rc;
+ size_t i;
+
+ for (i=0; i < nwrap_main_global->num_backends; i++) {
+ struct nwrap_backend *b = &nwrap_main_global->backends[i];
+ rc = b->ops->nw_gethostbyname2_r(b, name, AF_UNSPEC, ret,
+ buf, buflen, result);
+ if (rc == 0) {
+ return 0;
+ }
+ }
+ *h_errnop = h_errno;
+ return ENOENT;
+}
+
int gethostbyname_r(const char *name,
struct hostent *ret,
char *buf, size_t buflen,
}
#endif
+#ifdef HAVE_GETHOSTBYNAME2_R
+static int nwrap_gethostbyname2_r(const char *name, int af,
+ struct hostent *ret,
+ char *buf, size_t buflen,
+ struct hostent **result, int *h_errnop)
+{
+ int rc;
+ size_t i;
+
+ for (i=0; i < nwrap_main_global->num_backends; i++) {
+ struct nwrap_backend *b = &nwrap_main_global->backends[i];
+ rc = b->ops->nw_gethostbyname2_r(b, name, af, ret,
+ buf, buflen, result);
+ if (rc == 0) {
+ return 0;
+ }
+ }
+ *h_errnop = h_errno;
+ return ENOENT;
+}
+
+int gethostbyname2_r(const char *name, int af,
+ struct hostent *ret,
+ char *buf, size_t buflen,
+ struct hostent **result, int *h_errnop)
+{
+ if (!nss_wrapper_hosts_enabled()) {
+ return libc_gethostbyname2_r(name, af, ret, buf, buflen,
+ result, h_errnop);
+ }
+
+ return nwrap_gethostbyname2_r(name, af, ret, buf, buflen, result,
+ h_errnop);
+}
+#endif
+
static int nwrap_files_getaddrinfo(const char *name,
unsigned short port,
const struct addrinfo *hints,
}
name_len = strlen(name);
- if (name_len < DNS_NAME_MAX && name[name_len - 1] == '.') {
- strncpy(canon_name, name, name_len - 1);
+ if (name_len < sizeof(canon_name) && name[name_len - 1] == '.') {
+ memcpy(canon_name, name, name_len - 1);
+ canon_name[name_len] = '\0';
name = canon_name;
}
return rc;
}
-static struct hostent *nwrap_files_gethostbyaddr(const void *addr,
+static struct hostent *nwrap_files_gethostbyaddr(struct nwrap_backend *b,
+ const void *addr,
socklen_t len, int type)
{
struct hostent *he;
size_t i;
bool ok;
+ (void) b; /* unused */
(void) len; /* unused */
ok = nwrap_files_cache_reload(nwrap_he_global.cache);
return NULL;
}
- nwrap_vector_foreach(ed, nwrap_he_global.entdata, i)
+ nwrap_vector_foreach(ed, nwrap_he_global.entries, i)
{
he = &(ed->ht);
if (he->h_addrtype != type) {
char *buf, size_t buflen,
struct hostent **result, int *h_errnop)
{
- *result = nwrap_files_gethostbyaddr(addr, len, type);
+ size_t i;
+ for (i=0; i < nwrap_main_global->num_backends; i++) {
+ struct nwrap_backend *b = &nwrap_main_global->backends[i];
+ *result = b->ops->nw_gethostbyaddr(b, addr, len, type);
+ if (*result != NULL) {
+ break;
+ }
+ }
+
if (*result != NULL) {
memset(buf, '\0', buflen);
*ret = **result;
return 0;
- } else {
- *h_errnop = h_errno;
- return -1;
}
+
+ *h_errnop = h_errno;
+ return -1;
}
int gethostbyaddr_r(const void *addr, socklen_t len, int type,
return NULL;
}
- he = &((struct nwrap_entdata *)nwrap_he_global.entdata.items[nwrap_he_global.idx++])->ht;
+ he = &((struct nwrap_entdata *)nwrap_he_global.entries.items[nwrap_he_global.idx++])->ht;
NWRAP_LOG(NWRAP_LOG_DEBUG, "return hosts[%s]", he->h_name);
{
int ret;
- (void) b; /* unused */
- (void) pwdst; /* unused */
- (void) pwdstp; /* unused */
+ *pwdstp = NULL;
if (!b->fns->_nss_getpwnam_r) {
return NSS_STATUS_NOTFOUND;
ret = b->fns->_nss_getpwnam_r(name, pwdst, buf, buflen, &errno);
switch (ret) {
case NSS_STATUS_SUCCESS:
+ *pwdstp = pwdst;
return 0;
case NSS_STATUS_NOTFOUND:
if (errno != 0) {
{
int ret;
- (void) pwdstp; /* unused */
+ *pwdstp = NULL;
if (!b->fns->_nss_getpwuid_r) {
return ENOENT;
ret = b->fns->_nss_getpwuid_r(uid, pwdst, buf, buflen, &errno);
switch (ret) {
case NSS_STATUS_SUCCESS:
+ *pwdstp = pwdst;
return 0;
case NSS_STATUS_NOTFOUND:
if (errno != 0) {
{
int ret;
- (void) pwdstp; /* unused */
+ *pwdstp = NULL;
if (!b->fns->_nss_getpwent_r) {
return ENOENT;
ret = b->fns->_nss_getpwent_r(pwdst, buf, buflen, &errno);
switch (ret) {
case NSS_STATUS_SUCCESS:
+ *pwdstp = pwdst;
return 0;
case NSS_STATUS_NOTFOUND:
if (errno != 0) {
{
int ret;
- (void) grdstp; /* unused */
+ *grdstp = NULL;
if (!b->fns->_nss_getgrnam_r) {
return ENOENT;
ret = b->fns->_nss_getgrnam_r(name, grdst, buf, buflen, &errno);
switch (ret) {
case NSS_STATUS_SUCCESS:
+ *grdstp = grdst;
return 0;
case NSS_STATUS_NOTFOUND:
if (errno != 0) {
{
int ret;
- (void) grdstp; /* unused */
+ *grdstp = NULL;
if (!b->fns->_nss_getgrgid_r) {
return ENOENT;
ret = b->fns->_nss_getgrgid_r(gid, grdst, buf, buflen, &errno);
switch (ret) {
case NSS_STATUS_SUCCESS:
+ *grdstp = grdst;
return 0;
case NSS_STATUS_NOTFOUND:
if (errno != 0) {
{
int ret;
- (void) grdstp; /* unused */
+ *grdstp = NULL;
if (!b->fns->_nss_getgrent_r) {
return ENOENT;
ret = b->fns->_nss_getgrent_r(grdst, buf, buflen, &errno);
switch (ret) {
case NSS_STATUS_SUCCESS:
+ *grdstp = grdst;
return 0;
case NSS_STATUS_NOTFOUND:
if (errno != 0) {
b->fns->_nss_endgrent();
}
+static struct hostent *nwrap_module_gethostbyaddr(struct nwrap_backend *b,
+ const void *addr,
+ socklen_t len, int type)
+{
+ static struct hostent he;
+ static char *buf = NULL;
+ static size_t buflen = 1000;
+ NSS_STATUS status;
+
+ if (b->fns->_nss_gethostbyaddr_r == NULL) {
+ return NULL;
+ }
+
+ if (buf == NULL) {
+ buf = (char *)malloc(buflen);
+ if (buf == NULL) {
+ return NULL;
+ }
+ }
+again:
+ status = b->fns->_nss_gethostbyaddr_r(addr, len, type, &he,
+ buf, buflen, &errno, &h_errno);
+ if (status == NSS_STATUS_TRYAGAIN) {
+ char *p = NULL;
+
+ buflen *= 2;
+ p = (char *)realloc(buf, buflen);
+ if (p == NULL) {
+ SAFE_FREE(buf);
+ return NULL;
+ }
+ buf = p;
+ goto again;
+ }
+ if (status == NSS_STATUS_NOTFOUND) {
+ SAFE_FREE(buf);
+ return NULL;
+ }
+ if (status != NSS_STATUS_SUCCESS) {
+ SAFE_FREE(buf);
+ return NULL;
+ }
+
+ return &he;
+}
+
+static int nwrap_module_gethostbyname2_r(struct nwrap_backend *b,
+ const char *name, int af,
+ struct hostent *hedst,
+ char *buf, size_t buflen,
+ struct hostent **hedstp)
+{
+ NSS_STATUS status;
+
+ *hedstp = NULL;
+
+ if (b->fns->_nss_gethostbyname2_r == NULL) {
+ return ENOENT;
+ }
+
+ status = b->fns->_nss_gethostbyname2_r(name, af, hedst,
+ buf, buflen, &errno, &h_errno);
+ switch (status) {
+ case NSS_STATUS_SUCCESS:
+ *hedstp = hedst;
+ return 0;
+ case NSS_STATUS_NOTFOUND:
+ if (errno != 0) {
+ return errno;
+ }
+ return ENOENT;
+ case NSS_STATUS_TRYAGAIN:
+ if (errno != 0) {
+ return errno;
+ }
+ return ERANGE;
+ default:
+ if (errno != 0) {
+ return errno;
+ }
+ return status;
+ }
+}
+
+static struct hostent *nwrap_module_gethostbyname(struct nwrap_backend *b,
+ const char *name)
+{
+ static struct hostent he;
+ static char *buf = NULL;
+ static size_t buflen = 1000;
+ NSS_STATUS status;
+
+ if (b->fns->_nss_gethostbyname2_r == NULL) {
+ return NULL;
+ }
+
+ if (buf == NULL) {
+ buf = (char *)malloc(buflen);
+ if (buf == NULL) {
+ return NULL;
+ }
+ }
+
+again:
+ status = b->fns->_nss_gethostbyname2_r(name, AF_UNSPEC, &he,
+ buf, buflen, &errno, &h_errno);
+ if (status == NSS_STATUS_TRYAGAIN) {
+ char *p = NULL;
+
+ buflen *= 2;
+ p = (char *)realloc(buf, buflen);
+ if (p == NULL) {
+ SAFE_FREE(buf);
+ return NULL;
+ }
+ buf = p;
+ goto again;
+ }
+ if (status == NSS_STATUS_NOTFOUND) {
+ SAFE_FREE(buf);
+ return NULL;
+ }
+ if (status != NSS_STATUS_SUCCESS) {
+ SAFE_FREE(buf);
+ return NULL;
+ }
+
+ return &he;
+}
+
+static struct hostent *nwrap_module_gethostbyname2(struct nwrap_backend *b,
+ const char *name, int af)
+{
+ static struct hostent he;
+ static char *buf = NULL;
+ static size_t buflen = 1000;
+ NSS_STATUS status;
+
+ if (b->fns->_nss_gethostbyname2_r == NULL) {
+ return NULL;
+ }
+
+ if (buf == NULL) {
+ buf = (char *)malloc(buflen);
+ if (buf == NULL) {
+ return NULL;
+ }
+ }
+
+again:
+ status = b->fns->_nss_gethostbyname2_r(name, af, &he,
+ buf, buflen, &errno, &h_errno);
+ if (status == NSS_STATUS_TRYAGAIN) {
+ char *p = NULL;
+
+ buflen *= 2;
+ p = (char *)realloc(buf, buflen);
+ if (p == NULL) {
+ SAFE_FREE(buf);
+ return NULL;
+ }
+ buf = p;
+ goto again;
+ }
+ if (status == NSS_STATUS_NOTFOUND) {
+ SAFE_FREE(buf);
+ return NULL;
+ }
+ if (status != NSS_STATUS_SUCCESS) {
+ SAFE_FREE(buf);
+ return NULL;
+ }
+
+ return &he;
+}
+
/****************************************************************************
* GETPWNAM
***************************************************************************/
static struct passwd *nwrap_getpwnam(const char *name)
{
- int i;
+ size_t i;
struct passwd *pwd;
for (i=0; i < nwrap_main_global->num_backends; i++) {
static int nwrap_getpwnam_r(const char *name, struct passwd *pwdst,
char *buf, size_t buflen, struct passwd **pwdstp)
{
- int i,ret;
+ size_t i;
+ int ret;
for (i=0; i < nwrap_main_global->num_backends; i++) {
struct nwrap_backend *b = &nwrap_main_global->backends[i];
static struct passwd *nwrap_getpwuid(uid_t uid)
{
- int i;
+ size_t i;
struct passwd *pwd;
for (i=0; i < nwrap_main_global->num_backends; i++) {
static int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst,
char *buf, size_t buflen, struct passwd **pwdstp)
{
- int i,ret;
+ size_t i;
+ int ret;
for (i=0; i < nwrap_main_global->num_backends; i++) {
struct nwrap_backend *b = &nwrap_main_global->backends[i];
static void nwrap_setpwent(void)
{
- int i;
+ size_t i;
for (i=0; i < nwrap_main_global->num_backends; i++) {
struct nwrap_backend *b = &nwrap_main_global->backends[i];
static struct passwd *nwrap_getpwent(void)
{
- int i;
+ size_t i;
struct passwd *pwd;
for (i=0; i < nwrap_main_global->num_backends; i++) {
* GETPWENT_R
***************************************************************************/
+#ifdef HAVE_GETPWENT_R
static int nwrap_getpwent_r(struct passwd *pwdst, char *buf,
size_t buflen, struct passwd **pwdstp)
{
- int i,ret;
+ size_t i;
+ int ret;
for (i=0; i < nwrap_main_global->num_backends; i++) {
struct nwrap_backend *b = &nwrap_main_global->backends[i];
return ENOENT;
}
-#ifdef HAVE_SOLARIS_GETPWENT_R
+# ifdef HAVE_SOLARIS_GETPWENT_R
struct passwd *getpwent_r(struct passwd *pwdst, char *buf, int buflen)
{
struct passwd *pwdstp = NULL;
return pwdstp;
}
-#else /* HAVE_SOLARIS_GETPWENT_R */
+# else /* HAVE_SOLARIS_GETPWENT_R */
int getpwent_r(struct passwd *pwdst, char *buf,
size_t buflen, struct passwd **pwdstp)
{
return nwrap_getpwent_r(pwdst, buf, buflen, pwdstp);
}
-#endif /* HAVE_SOLARIS_GETPWENT_R */
+# endif /* HAVE_SOLARIS_GETPWENT_R */
+#endif /* HAVE_GETPWENT_R */
/****************************************************************************
* ENDPWENT
static void nwrap_endpwent(void)
{
- int i;
+ size_t i;
for (i=0; i < nwrap_main_global->num_backends; i++) {
struct nwrap_backend *b = &nwrap_main_global->backends[i];
static int nwrap_initgroups(const char *user, gid_t group)
{
- int i;
+ size_t i;
for (i=0; i < nwrap_main_global->num_backends; i++) {
struct nwrap_backend *b = &nwrap_main_global->backends[i];
static struct group *nwrap_getgrnam(const char *name)
{
- int i;
+ size_t i;
struct group *grp;
for (i=0; i < nwrap_main_global->num_backends; i++) {
static int nwrap_getgrnam_r(const char *name, struct group *grdst,
char *buf, size_t buflen, struct group **grdstp)
{
- int i, ret;
+ size_t i;
+ int ret;
for (i=0; i < nwrap_main_global->num_backends; i++) {
struct nwrap_backend *b = &nwrap_main_global->backends[i];
static struct group *nwrap_getgrgid(gid_t gid)
{
- int i;
+ size_t i;
struct group *grp;
for (i=0; i < nwrap_main_global->num_backends; i++) {
static int nwrap_getgrgid_r(gid_t gid, struct group *grdst,
char *buf, size_t buflen, struct group **grdstp)
{
- int i,ret;
+ size_t i;
+ int ret;
for (i=0; i < nwrap_main_global->num_backends; i++) {
struct nwrap_backend *b = &nwrap_main_global->backends[i];
static void nwrap_setgrent(void)
{
- int i;
+ size_t i;
for (i=0; i < nwrap_main_global->num_backends; i++) {
struct nwrap_backend *b = &nwrap_main_global->backends[i];
static struct group *nwrap_getgrent(void)
{
- int i;
+ size_t i;
struct group *grp;
for (i=0; i < nwrap_main_global->num_backends; i++) {
* GETGRENT_R
***************************************************************************/
+#ifdef HAVE_GETGRENT_R
static int nwrap_getgrent_r(struct group *grdst, char *buf,
size_t buflen, struct group **grdstp)
{
- int i,ret;
+ size_t i;
+ int ret;
for (i=0; i < nwrap_main_global->num_backends; i++) {
struct nwrap_backend *b = &nwrap_main_global->backends[i];
return ENOENT;
}
-#ifdef HAVE_SOLARIS_GETGRENT_R
+# ifdef HAVE_SOLARIS_GETGRENT_R
struct group *getgrent_r(struct group *src, char *buf, int buflen)
{
struct group *grdstp = NULL;
return grdstp;
}
-#else /* HAVE_SOLARIS_GETGRENT_R */
+# else /* HAVE_SOLARIS_GETGRENT_R */
int getgrent_r(struct group *src, char *buf,
size_t buflen, struct group **grdstp)
{
return nwrap_getgrent_r(src, buf, buflen, grdstp);
}
-#endif /* HAVE_SOLARIS_GETGRENT_R */
+# endif /* HAVE_SOLARIS_GETGRENT_R */
+#endif /* HAVE_GETGRENT_R */
/****************************************************************************
* ENDGRENT
static void nwrap_endgrent(void)
{
- int i;
+ size_t i;
for (i=0; i < nwrap_main_global->num_backends; i++) {
struct nwrap_backend *b = &nwrap_main_global->backends[i];
}
#endif /* HAVE_SOLARIS_ENDHOSTENT */
+
#ifdef BSD
/* BSD implementation stores data in thread local storage but GLIBC does not */
static __thread struct hostent user_he;
static struct hostent user_he;
static struct nwrap_vector user_addrlist;
#endif /* BSD */
+
+static struct hostent *nwrap_files_gethostbyname(struct nwrap_backend *b,
+ const char *name)
+{
+ int ret;
+
+ (void) b; /* unused */
+
+ ret = nwrap_files_internal_gethostbyname(name, AF_UNSPEC, &user_he,
+ &user_addrlist);
+ if (ret == 0) {
+ return &user_he;
+ }
+
+ return NULL;
+}
+
static struct hostent *nwrap_gethostbyname(const char *name)
{
- if (nwrap_files_gethostbyname(name, AF_UNSPEC, &user_he, &user_addrlist) == -1) {
- return NULL;
+ size_t i;
+ struct hostent *he = NULL;
+
+ for (i=0; i < nwrap_main_global->num_backends; i++) {
+ struct nwrap_backend *b = &nwrap_main_global->backends[i];
+ he = b->ops->nw_gethostbyname(b, name);
+ if (he != NULL) {
+ return he;
+ }
}
- return &user_he;
+
+ return NULL;
}
struct hostent *gethostbyname(const char *name)
static struct hostent user_he2;
static struct nwrap_vector user_addrlist2;
#endif /* BSD */
+
+static struct hostent *nwrap_files_gethostbyname2(struct nwrap_backend *b,
+ const char *name, int af)
+{
+ int ret;
+
+ (void) b; /* unused */
+
+ ret = nwrap_files_internal_gethostbyname(name, af, &user_he2,
+ &user_addrlist2);
+ if (ret == 0) {
+ return &user_he2;
+ }
+
+ return NULL;
+}
+
static struct hostent *nwrap_gethostbyname2(const char *name, int af)
{
- if (nwrap_files_gethostbyname(name, af, &user_he2, &user_addrlist2) == -1) {
- return NULL;
+ size_t i;
+ struct hostent *he = NULL;
+
+ for (i=0; i < nwrap_main_global->num_backends; i++) {
+ struct nwrap_backend *b = &nwrap_main_global->backends[i];
+ he = b->ops->nw_gethostbyname2(b, name, af);
+ if (he != NULL) {
+ return he;
+ }
}
- return &user_he2;
+
+ return NULL;
}
struct hostent *gethostbyname2(const char *name, int af)
static struct hostent *nwrap_gethostbyaddr(const void *addr,
socklen_t len, int type)
{
- return nwrap_files_gethostbyaddr(addr, len, type);
+ size_t i;
+ struct hostent *he = NULL;
+
+ for (i=0; i < nwrap_main_global->num_backends; i++) {
+ struct nwrap_backend *b = &nwrap_main_global->backends[i];
+ he = b->ops->nw_gethostbyaddr(b, addr, len, type);
+ if (he != NULL) {
+ return he;
+ }
+ }
+
+ return NULL;
}
struct hostent *gethostbyaddr(const void *addr,
switch (he->h_addrtype) {
case AF_INET:
{
- struct sockaddr_in *sinp =
- (struct sockaddr_in *) ai->ai_addr;
+ union {
+ struct sockaddr *sa;
+ struct sockaddr_in *in;
+ } addr;
- memset(sinp, 0, sizeof(struct sockaddr_in));
+ addr.sa = ai->ai_addr;
- sinp->sin_port = htons(port);
- sinp->sin_family = AF_INET;
+ memset(addr.in, 0, sizeof(struct sockaddr_in));
- memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
- memcpy(&sinp->sin_addr, he->h_addr_list[0], he->h_length);
+ addr.in->sin_port = htons(port);
+ addr.in->sin_family = AF_INET;
+
+ memset(addr.in->sin_zero,
+ '\0',
+ sizeof (addr.in->sin_zero));
+ memcpy(&(addr.in->sin_addr),
+ he->h_addr_list[0],
+ he->h_length);
}
break;
#ifdef HAVE_IPV6
case AF_INET6:
{
- struct sockaddr_in6 *sin6p =
- (struct sockaddr_in6 *) ai->ai_addr;
+ union {
+ struct sockaddr *sa;
+ struct sockaddr_in6 *in6;
+ } addr;
+
+ addr.sa = ai->ai_addr;
- memset(sin6p, 0, sizeof(struct sockaddr_in6));
+ memset(addr.in6, 0, sizeof(struct sockaddr_in6));
- sin6p->sin6_port = htons(port);
- sin6p->sin6_family = AF_INET6;
+ addr.in6->sin6_port = htons(port);
+ addr.in6->sin6_family = AF_INET6;
- memcpy(&sin6p->sin6_addr,
+ memcpy(&addr.in6->sin6_addr,
he->h_addr_list[0],
he->h_length);
}
socklen_t addrlen;
uint16_t port;
sa_family_t type;
+ size_t i;
if (sa == NULL || salen < sizeof(sa_family_t)) {
return EAI_FAMILY;
type = sa->sa_family;
switch (type) {
- case AF_INET:
- if (salen < sizeof(struct sockaddr_in))
+ case AF_INET: {
+ union {
+ const struct sockaddr *sa;
+ const struct sockaddr_in *in;
+ } a;
+
+ if (salen < sizeof(struct sockaddr_in)) {
return EAI_FAMILY;
- addr = &((const struct sockaddr_in *)sa)->sin_addr;
- addrlen = sizeof(((const struct sockaddr_in *)sa)->sin_addr);
- port = ntohs(((const struct sockaddr_in *)sa)->sin_port);
+ }
+
+ a.sa = sa;
+
+ addr = &(a.in->sin_addr);
+ addrlen = sizeof(a.in->sin_addr);
+ port = ntohs(a.in->sin_port);
break;
+ }
#ifdef HAVE_IPV6
- case AF_INET6:
- if (salen < sizeof(struct sockaddr_in6))
+ case AF_INET6: {
+ union {
+ const struct sockaddr *sa;
+ const struct sockaddr_in6 *in6;
+ } a;
+
+ if (salen < sizeof(struct sockaddr_in6)) {
return EAI_FAMILY;
- addr = &((const struct sockaddr_in6 *)sa)->sin6_addr;
- addrlen = sizeof(((const struct sockaddr_in6 *)sa)->sin6_addr);
- port = ntohs(((const struct sockaddr_in6 *)sa)->sin6_port);
+ }
+
+ a.sa = sa;
+
+ addr = &(a.in6->sin6_addr);
+ addrlen = sizeof(a.in6->sin6_addr);
+ port = ntohs(a.in6->sin6_port);
break;
+ }
#endif
default:
return EAI_FAMILY;
if (host != NULL) {
he = NULL;
if ((flags & NI_NUMERICHOST) == 0) {
- he = nwrap_files_gethostbyaddr(addr, addrlen, type);
+ for (i=0; i < nwrap_main_global->num_backends; i++) {
+ struct nwrap_backend *b = &nwrap_main_global->backends[i];
+ he = b->ops->nw_gethostbyaddr(b, addr, addrlen, type);
+ if (he != NULL) {
+ break;
+ }
+ }
if ((flags & NI_NAMEREQD) && (he == NULL || he->h_name == NULL))
return EAI_NONAME;
}
if (he != NULL && he->h_name != NULL) {
if (strlen(he->h_name) >= hostlen)
return EAI_OVERFLOW;
- strcpy(host, he->h_name);
+ snprintf(host, hostlen, "%s", he->h_name);
if (flags & NI_NOFQDN)
host[strcspn(host, ".")] = '\0';
} else {
if (service != NULL) {
if (strlen(service->s_name) >= servlen)
return EAI_OVERFLOW;
- strcpy(serv, service->s_name);
+ snprintf(serv, servlen, "%s", service->s_name);
} else {
if (snprintf(serv, servlen, "%u", port) >= (int) servlen)
return EAI_OVERFLOW;
return nwrap_gethostname(name, len);
}
+/****************************
+ * CONSTRUCTOR
+ ***************************/
+void nwrap_constructor(void)
+{
+ /*
+ * If we hold a lock and the application forks, then the child
+ * is not able to unlock the mutex and we are in a deadlock.
+ *
+ * Setting these handlers should prevent such deadlocks.
+ */
+ pthread_atfork(&nwrap_thread_prepare,
+ &nwrap_thread_parent,
+ &nwrap_thread_child);
+
+ /* Do not call nwrap_init() here. */
+}
+
/****************************
* DESTRUCTOR
***************************/
*/
void nwrap_destructor(void)
{
- int i;
+ size_t i;
NWRAP_LOCK_ALL;
if (nwrap_main_global != NULL) {
struct nwrap_main *m = nwrap_main_global;
/* libc */
- SAFE_FREE(m->libc->fns);
- if (m->libc->handle != NULL) {
- dlclose(m->libc->handle);
- }
- if (m->libc->nsl_handle != NULL) {
- dlclose(m->libc->nsl_handle);
- }
- if (m->libc->sock_handle != NULL) {
- dlclose(m->libc->sock_handle);
+ if (m->libc != NULL) {
+ SAFE_FREE(m->libc->fns);
+ if (m->libc->handle != NULL) {
+ dlclose(m->libc->handle);
+ }
+ if (m->libc->nsl_handle != NULL) {
+ dlclose(m->libc->nsl_handle);
+ }
+ if (m->libc->sock_handle != NULL) {
+ dlclose(m->libc->sock_handle);
+ }
+ SAFE_FREE(m->libc);
}
- SAFE_FREE(m->libc);
/* backends */
- for (i = 0; i < m->num_backends; i++) {
- struct nwrap_backend *b = &(m->backends[i]);
+ if (m->backends != NULL) {
+ for (i = 0; i < m->num_backends; i++) {
+ struct nwrap_backend *b = &(m->backends[i]);
- if (b->so_handle != NULL) {
- dlclose(b->so_handle);
+ if (b->so_handle != NULL) {
+ dlclose(b->so_handle);
+ }
+ SAFE_FREE(b->fns);
}
- SAFE_FREE(b->fns);
+ SAFE_FREE(m->backends);
}
- SAFE_FREE(m->backends);
}
if (nwrap_pw_global.cache != NULL) {
nwrap_pw_global.num = 0;
}
+#if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
+ if (nwrap_sp_global.cache != NULL) {
+ struct nwrap_cache *c = nwrap_sp_global.cache;
+
+ nwrap_files_cache_unload(c);
+ if (c->fd >= 0) {
+ fclose(c->fp);
+ c->fd = -1;
+ }
+
+ nwrap_sp_global.num = 0;
+ }
+#endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
+
if (nwrap_he_global.cache != NULL) {
struct nwrap_cache *c = nwrap_he_global.cache;
nwrap_he_global.num = 0;
}
+ free(user_addrlist.items);
+#ifdef HAVE_GETHOSTBYNAME2
+ free(user_addrlist2.items);
+#endif
+
hdestroy();
NWRAP_UNLOCK_ALL;
}