mirror of https://gitee.com/openkylin/libvirt.git
nss: FreeBSD support
* tools/nss/libvirt_nss.[ch]: add BSD-comptabile wrappers and register via the nss_module_register() interface * m4/virt-nss.m4: add checks if we're building NSS for FreeBSD * tools/Makefile.am: handle target library name differences, as Linux needs libnss_libvirt.so.2 and FreeBSD needs nss_libvirt.so.1. Also, different syms files have to be used as Linux needs to export all the methods while FreeBSD only needs to have nss_module_register() * tests/nsstest.c, tests/nssmock.c: s/__linux__/NSS/ * tests/nssmock.c: pass int instead of mode_t to va_arg() to please gcc 4.8 * libvirt_nss_bsd.syms: FreeBSD syms file
This commit is contained in:
parent
e23a640c42
commit
45408cd892
|
@ -23,6 +23,7 @@ AC_DEFUN([LIBVIRT_CHECK_NSS],[
|
||||||
[enable Name Servie Switch plugin for resolving guest IP addresses])],
|
[enable Name Servie Switch plugin for resolving guest IP addresses])],
|
||||||
[], [with_nss_plugin=check])
|
[], [with_nss_plugin=check])
|
||||||
|
|
||||||
|
bsd_nss=no
|
||||||
fail=0
|
fail=0
|
||||||
if test "x$with_nss_plugin" != "xno" ; then
|
if test "x$with_nss_plugin" != "xno" ; then
|
||||||
AC_CHECK_HEADERS([nss.h], [
|
AC_CHECK_HEADERS([nss.h], [
|
||||||
|
@ -39,11 +40,26 @@ AC_DEFUN([LIBVIRT_CHECK_NSS],[
|
||||||
|
|
||||||
if test "x$with_nss_plugin" = "xyes" ; then
|
if test "x$with_nss_plugin" = "xyes" ; then
|
||||||
AC_DEFINE_UNQUOTED([NSS], 1, [whether nss plugin is enabled])
|
AC_DEFINE_UNQUOTED([NSS], 1, [whether nss plugin is enabled])
|
||||||
|
|
||||||
|
AC_CHECK_TYPE([struct gaih_addrtuple],
|
||||||
|
[AC_DEFINE([HAVE_STRUCT_GAIH_ADDRTUPLE], [1],
|
||||||
|
[Defined if struct gaih_addrtuple exists in nss.h])],
|
||||||
|
[], [[#include <nss.h>
|
||||||
|
]])
|
||||||
|
|
||||||
|
AC_CHECK_TYPES([ns_mtab, nss_module_unregister_fn],
|
||||||
|
[AC_DEFINE([HAVE_BSD_NSS],
|
||||||
|
[1],
|
||||||
|
[whether using BSD style NSS])
|
||||||
|
bsd_nss=yes
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
[#include <nsswitch.h>])
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AM_CONDITIONAL(WITH_NSS, [test "x$with_nss_plugin" = "xyes"])
|
AM_CONDITIONAL(WITH_NSS, [test "x$with_nss_plugin" = "xyes"])
|
||||||
|
AM_CONDITIONAL(WITH_BSD_NSS, [test "x$bsd_nss" = "xyes"])
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN([LIBVIRT_RESULT_NSS],[
|
AC_DEFUN([LIBVIRT_RESULT_NSS],[
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef NSS
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
# include <dlfcn.h>
|
# include <dlfcn.h>
|
||||||
|
@ -107,7 +107,7 @@ open(const char *path, int flags, ...)
|
||||||
va_list ap;
|
va_list ap;
|
||||||
mode_t mode;
|
mode_t mode;
|
||||||
va_start(ap, flags);
|
va_start(ap, flags);
|
||||||
mode = va_arg(ap, mode_t);
|
mode = va_arg(ap, int);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
ret = realopen(newpath ? newpath : path, flags, mode);
|
ret = realopen(newpath ? newpath : path, flags, mode);
|
||||||
} else {
|
} else {
|
||||||
|
@ -136,5 +136,5 @@ opendir(const char *path)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
/* Nothing to override on non-__linux__ platforms */
|
/* Nothing to override if NSS plugin is not enabled */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
#include "testutils.h"
|
#include "testutils.h"
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef NSS
|
||||||
|
|
||||||
# include <stdbool.h>
|
# include <stdbool.h>
|
||||||
# include <arpa/inet.h>
|
# include <arpa/inet.h>
|
||||||
|
|
|
@ -417,8 +417,22 @@ CLEANFILES += wireshark/src/plugin.c
|
||||||
|
|
||||||
endif WITH_WIRESHARK_DISSECTOR
|
endif WITH_WIRESHARK_DISSECTOR
|
||||||
|
|
||||||
|
if WITH_BSD_NSS
|
||||||
|
LIBVIRT_NSS_SYMBOL_FILE = \
|
||||||
|
$(srcdir)/nss/libvirt_nss_bsd.syms
|
||||||
|
NSS_SO_VER = 1
|
||||||
|
|
||||||
|
install-exec-hook:
|
||||||
|
cd $(DESTDIR)$(libdir) && \
|
||||||
|
$(LN_S) libnss_libvirt.so.$(NSS_SO_VER) nss_libvirt.so.$(NSS_SO_VER)
|
||||||
|
|
||||||
|
uninstall-local:
|
||||||
|
rm $(DESTDIR)$(libdir)/libnss_libvirt.so.$(NSS_SO_VER)
|
||||||
|
else ! WITH_BSD_NSS
|
||||||
LIBVIRT_NSS_SYMBOL_FILE = \
|
LIBVIRT_NSS_SYMBOL_FILE = \
|
||||||
$(srcdir)/nss/libvirt_nss.syms
|
$(srcdir)/nss/libvirt_nss.syms
|
||||||
|
NSS_SO_VER = 2
|
||||||
|
endif ! WITH_BSD_NSS
|
||||||
|
|
||||||
LIBVIRT_NSS_SOURCES = \
|
LIBVIRT_NSS_SOURCES = \
|
||||||
nss/libvirt_nss.c \
|
nss/libvirt_nss.c \
|
||||||
|
@ -449,7 +463,7 @@ nss_libnss_libvirt_la_LDFLAGS = \
|
||||||
-export-dynamic \
|
-export-dynamic \
|
||||||
-avoid-version \
|
-avoid-version \
|
||||||
-shared \
|
-shared \
|
||||||
-shrext .so.2
|
-shrext .so.$(NSS_SO_VER)
|
||||||
|
|
||||||
nss_libnss_libvirt_la_LIBADD = \
|
nss_libnss_libvirt_la_LIBADD = \
|
||||||
nss/libnss_libvirt_impl.la
|
nss/libnss_libvirt_impl.la
|
||||||
|
|
|
@ -29,11 +29,16 @@
|
||||||
|
|
||||||
#include "libvirt_nss.h"
|
#include "libvirt_nss.h"
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <resolv.h>
|
#include <resolv.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#if defined(HAVE_BSD_NSS)
|
||||||
|
# include <nsswitch.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "virlease.h"
|
#include "virlease.h"
|
||||||
#include "viralloc.h"
|
#include "viralloc.h"
|
||||||
#include "virfile.h"
|
#include "virfile.h"
|
||||||
|
@ -65,7 +70,7 @@ do { \
|
||||||
|
|
||||||
#define LEASEDIR LOCALSTATEDIR "/lib/libvirt/dnsmasq/"
|
#define LEASEDIR LOCALSTATEDIR "/lib/libvirt/dnsmasq/"
|
||||||
|
|
||||||
#define ALIGN(x) (((x) + __SIZEOF_POINTER__ - 1) & ~(__SIZEOF_POINTER__ - 1))
|
#define LIBVIRT_ALIGN(x) (((x) + __SIZEOF_POINTER__ - 1) & ~(__SIZEOF_POINTER__ - 1))
|
||||||
#define FAMILY_ADDRESS_SIZE(family) ((family) == AF_INET6 ? 16 : 4)
|
#define FAMILY_ADDRESS_SIZE(family) ((family) == AF_INET6 ? 16 : 4)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -256,7 +261,7 @@ static inline void *
|
||||||
move_and_align(void *buf, size_t len, size_t *idx)
|
move_and_align(void *buf, size_t len, size_t *idx)
|
||||||
{
|
{
|
||||||
char *buffer = buf;
|
char *buffer = buf;
|
||||||
size_t move = ALIGN(len);
|
size_t move = LIBVIRT_ALIGN(len);
|
||||||
|
|
||||||
if (!idx)
|
if (!idx)
|
||||||
return buffer + move;
|
return buffer + move;
|
||||||
|
@ -321,7 +326,7 @@ _nss_libvirt_gethostbyname3_r(const char *name, int af, struct hostent *result,
|
||||||
* b) alias
|
* b) alias
|
||||||
* c) addresses
|
* c) addresses
|
||||||
* d) NULL stem */
|
* d) NULL stem */
|
||||||
need = ALIGN(nameLen + 1) + naddr * ALIGN(alen) + (naddr + 2) * sizeof(char*);
|
need = LIBVIRT_ALIGN(nameLen + 1) + naddr * LIBVIRT_ALIGN(alen) + (naddr + 2) * sizeof(char*);
|
||||||
|
|
||||||
if (buflen < need) {
|
if (buflen < need) {
|
||||||
*errnop = ENOMEM;
|
*errnop = ENOMEM;
|
||||||
|
@ -383,6 +388,7 @@ _nss_libvirt_gethostbyname3_r(const char *name, int af, struct hostent *result,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_STRUCT_GAIH_ADDRTUPLE
|
||||||
enum nss_status
|
enum nss_status
|
||||||
_nss_libvirt_gethostbyname4_r(const char *name, struct gaih_addrtuple **pat,
|
_nss_libvirt_gethostbyname4_r(const char *name, struct gaih_addrtuple **pat,
|
||||||
char *buffer, size_t buflen, int *errnop,
|
char *buffer, size_t buflen, int *errnop,
|
||||||
|
@ -426,7 +432,7 @@ _nss_libvirt_gethostbyname4_r(const char *name, struct gaih_addrtuple **pat,
|
||||||
/* We need space for:
|
/* We need space for:
|
||||||
* a) name
|
* a) name
|
||||||
* b) addresses */
|
* b) addresses */
|
||||||
need = ALIGN(nameLen + 1) + naddr * ALIGN(sizeof(struct gaih_addrtuple));
|
need = LIBVIRT_ALIGN(nameLen + 1) + naddr * LIBVIRT_ALIGN(sizeof(struct gaih_addrtuple));
|
||||||
|
|
||||||
if (buflen < need) {
|
if (buflen < need) {
|
||||||
*errnop = ENOMEM;
|
*errnop = ENOMEM;
|
||||||
|
@ -474,3 +480,128 @@ _nss_libvirt_gethostbyname4_r(const char *name, struct gaih_addrtuple **pat,
|
||||||
cleanup:
|
cleanup:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#endif /* HAVE_STRUCT_GAIH_ADDRTUPLE */
|
||||||
|
|
||||||
|
#if defined(HAVE_BSD_NSS)
|
||||||
|
NSS_METHOD_PROTOTYPE(_nss_compat_getaddrinfo);
|
||||||
|
NSS_METHOD_PROTOTYPE(_nss_compat_gethostbyname2_r);
|
||||||
|
|
||||||
|
ns_mtab methods[] = {
|
||||||
|
{ NSDB_HOSTS, "getaddrinfo", _nss_compat_getaddrinfo, NULL },
|
||||||
|
{ NSDB_HOSTS, "gethostbyname", _nss_compat_gethostbyname2_r, NULL },
|
||||||
|
{ NSDB_HOSTS, "gethostbyname2_r", _nss_compat_gethostbyname2_r, NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
aiforaf(const char *name, int af, struct addrinfo *pai, struct addrinfo **aip)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct hostent resolved;
|
||||||
|
char buf[1024] = { 0 };
|
||||||
|
int err, herr;
|
||||||
|
struct addrinfo hints, *res0, *res;
|
||||||
|
char **addrList;
|
||||||
|
|
||||||
|
if ((ret = _nss_libvirt_gethostbyname2_r(name, af, &resolved,
|
||||||
|
buf, sizeof(buf),
|
||||||
|
&err, &herr)) != NS_SUCCESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
addrList = resolved.h_addr_list;
|
||||||
|
while (*addrList) {
|
||||||
|
virSocketAddr sa;
|
||||||
|
char *ipAddr = NULL;
|
||||||
|
void *address = *addrList;
|
||||||
|
|
||||||
|
memset(&sa, 0, sizeof(sa));
|
||||||
|
if (resolved.h_addrtype == AF_INET) {
|
||||||
|
virSocketAddrSetIPv4AddrNetOrder(&sa, *((uint32_t *) address));
|
||||||
|
} else {
|
||||||
|
virSocketAddrSetIPv6AddrNetOrder(&sa, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
ipAddr = virSocketAddrFormat(&sa);
|
||||||
|
|
||||||
|
hints = *pai;
|
||||||
|
hints.ai_flags = AI_NUMERICHOST;
|
||||||
|
hints.ai_family = af;
|
||||||
|
|
||||||
|
if (getaddrinfo(ipAddr, NULL, &hints, &res0)) {
|
||||||
|
addrList++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (res = res0; res; res = res->ai_next)
|
||||||
|
res->ai_flags = pai->ai_flags;
|
||||||
|
|
||||||
|
(*aip)->ai_next = res0;
|
||||||
|
while ((*aip)->ai_next)
|
||||||
|
*aip = (*aip)->ai_next;
|
||||||
|
|
||||||
|
addrList++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_nss_compat_getaddrinfo(void *retval, void *mdata ATTRIBUTE_UNUSED, va_list ap)
|
||||||
|
{
|
||||||
|
struct addrinfo sentinel, *cur, *ai;
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
name = va_arg(ap, char *);
|
||||||
|
ai = va_arg(ap, struct addrinfo *);
|
||||||
|
|
||||||
|
memset(&sentinel, 0, sizeof(sentinel));
|
||||||
|
cur = &sentinel;
|
||||||
|
|
||||||
|
if ((ai->ai_family == AF_UNSPEC) || (ai->ai_family == AF_INET6))
|
||||||
|
aiforaf(name, AF_INET6, ai, &cur);
|
||||||
|
if ((ai->ai_family == AF_UNSPEC) || (ai->ai_family == AF_INET))
|
||||||
|
aiforaf(name, AF_INET, ai, &cur);
|
||||||
|
|
||||||
|
if (sentinel.ai_next == NULL) {
|
||||||
|
h_errno = HOST_NOT_FOUND;
|
||||||
|
return NS_NOTFOUND;
|
||||||
|
}
|
||||||
|
*((struct addrinfo **)retval) = sentinel.ai_next;
|
||||||
|
|
||||||
|
return NS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_nss_compat_gethostbyname2_r(void *retval, void *mdata ATTRIBUTE_UNUSED, va_list ap)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
const char *name;
|
||||||
|
int af;
|
||||||
|
struct hostent *result;
|
||||||
|
char *buffer;
|
||||||
|
size_t buflen;
|
||||||
|
int *errnop;
|
||||||
|
int *herrnop;
|
||||||
|
|
||||||
|
name = va_arg(ap, const char *);
|
||||||
|
af = va_arg(ap, int);
|
||||||
|
result = va_arg(ap, struct hostent *);
|
||||||
|
buffer = va_arg(ap, char *);
|
||||||
|
buflen = va_arg(ap, size_t);
|
||||||
|
errnop = va_arg(ap, int *);
|
||||||
|
herrnop = va_arg(ap, int *);
|
||||||
|
|
||||||
|
ret = _nss_libvirt_gethostbyname2_r(
|
||||||
|
name, af, result, buffer, buflen, errnop, herrnop);
|
||||||
|
*(struct hostent **)retval = (ret == NS_SUCCESS) ? result : NULL;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ns_mtab*
|
||||||
|
nss_module_register(const char *name ATTRIBUTE_UNUSED, unsigned int *size,
|
||||||
|
nss_module_unregister_fn *unregister)
|
||||||
|
{
|
||||||
|
*size = sizeof(methods) / sizeof(methods[0]);
|
||||||
|
*unregister = NULL;
|
||||||
|
return methods;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_BSD_NSS */
|
||||||
|
|
|
@ -45,8 +45,17 @@ enum nss_status
|
||||||
_nss_libvirt_gethostbyname3_r(const char *name, int af, struct hostent *result,
|
_nss_libvirt_gethostbyname3_r(const char *name, int af, struct hostent *result,
|
||||||
char *buffer, size_t buflen, int *errnop,
|
char *buffer, size_t buflen, int *errnop,
|
||||||
int *herrnop, int32_t *ttlp, char **canonp);
|
int *herrnop, int32_t *ttlp, char **canonp);
|
||||||
|
# ifdef HAVE_STRUCT_GAIH_ADDRTUPLE
|
||||||
enum nss_status
|
enum nss_status
|
||||||
_nss_libvirt_gethostbyname4_r(const char *name, struct gaih_addrtuple **pat,
|
_nss_libvirt_gethostbyname4_r(const char *name, struct gaih_addrtuple **pat,
|
||||||
char *buffer, size_t buflen, int *errnop,
|
char *buffer, size_t buflen, int *errnop,
|
||||||
int *herrnop, int32_t *ttlp);
|
int *herrnop, int32_t *ttlp);
|
||||||
|
# endif /* HAVE_STRUCT_GAIH_ADDRTUPLE */
|
||||||
|
|
||||||
|
# if defined(HAVE_BSD_NSS)
|
||||||
|
ns_mtab*
|
||||||
|
nss_module_register(const char *name, unsigned int *size,
|
||||||
|
nss_module_unregister_fn *unregister);
|
||||||
|
# endif /* HAVE_BSD_NSS */
|
||||||
|
|
||||||
#endif /* __LIBVIRT_NSS_H__ */
|
#endif /* __LIBVIRT_NSS_H__ */
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
#
|
||||||
|
# Officially exported symbols.
|
||||||
|
#
|
||||||
|
|
||||||
|
{
|
||||||
|
global:
|
||||||
|
nss_module_register;
|
||||||
|
local: *;
|
||||||
|
};
|
Loading…
Reference in New Issue