systemd: merge branch 'systemd'
authorBeniamino Galvani <bgalvani@redhat.com>
Sun, 5 Jul 2015 10:04:21 +0000 (12:04 +0200)
committerBeniamino Galvani <bgalvani@redhat.com>
Wed, 8 Jul 2015 15:39:46 +0000 (17:39 +0200)
39 files changed:
1  2 
src/Makefile.am
src/systemd/nm-sd-adapt.h
src/systemd/src/basic/async.h
src/systemd/src/basic/fileio.c
src/systemd/src/basic/fileio.h
src/systemd/src/basic/hostname-util.c
src/systemd/src/basic/hostname-util.h
src/systemd/src/basic/in-addr-util.c
src/systemd/src/basic/in-addr-util.h
src/systemd/src/basic/list.h
src/systemd/src/basic/log.h
src/systemd/src/basic/macro.h
src/systemd/src/basic/path-util.c
src/systemd/src/basic/path-util.h
src/systemd/src/basic/random-util.c
src/systemd/src/basic/random-util.h
src/systemd/src/basic/refcnt.h
src/systemd/src/basic/siphash24.c
src/systemd/src/basic/siphash24.h
src/systemd/src/basic/socket-util.h
src/systemd/src/basic/sparse-endian.h
src/systemd/src/basic/strv.c
src/systemd/src/basic/strv.h
src/systemd/src/basic/time-util.c
src/systemd/src/basic/time-util.h
src/systemd/src/basic/unaligned.h
src/systemd/src/basic/utf8.c
src/systemd/src/basic/utf8.h
src/systemd/src/basic/util.c
src/systemd/src/basic/util.h
src/systemd/src/libsystemd-network/dhcp-identifier.c
src/systemd/src/libsystemd-network/dhcp-identifier.h
src/systemd/src/libsystemd-network/sd-dhcp-client.c
src/systemd/src/libsystemd-network/sd-dhcp-lease.c
src/systemd/src/libsystemd-network/sd-dhcp6-client.c
src/systemd/src/libsystemd-network/sd-ipv4ll.c
src/systemd/src/libsystemd/sd-id128/sd-id128.c
src/systemd/src/shared/dns-domain.c
src/systemd/src/shared/dns-domain.h

diff --cc src/Makefile.am
@@@ -45,89 -48,6 +45,96 @@@ AM_CPPFLAGS =                               
  # primarily for its side effect of removing duplicates.
  AM_CPPFLAGS += $(foreach d,$(sort $(dir $(libNetworkManager_la_SOURCES))),-I$(top_srcdir)/src/$d)
  
-       systemd/src/shared/async.h \
-       systemd/src/shared/time-util.h \
-       systemd/src/shared/siphash24.h \
-       systemd/src/shared/time-util.c \
-       systemd/src/shared/socket-util.h \
-       systemd/src/shared/sparse-endian.h \
-       systemd/src/shared/macro.h \
-       systemd/src/shared/refcnt.h \
-       systemd/src/shared/util.c \
-       systemd/src/shared/in-addr-util.c \
-       systemd/src/shared/siphash24.c \
-       systemd/src/shared/util.h \
-       systemd/src/shared/in-addr-util.h \
-       systemd/src/shared/list.h \
-       systemd/src/shared/log.h \
-       systemd/src/shared/fileio.h \
-       systemd/src/shared/fileio.c \
-       systemd/src/shared/path-util.c \
-       systemd/src/shared/path-util.h \
-       systemd/src/shared/strv.h \
-       systemd/src/shared/strv.c \
-       systemd/src/shared/unaligned.h \
-       systemd/src/shared/utf8.h \
-       systemd/src/shared/utf8.c \
 +noinst_LTLIBRARIES = \
 +      libNetworkManager.la \
 +      libnm-iface-helper.la \
 +      libsystemd-nm.la
 +
 +######################
 +# libsystemd-nm
 +######################
 +
 +SYSTEMD_NM_CFLAGS = \
 +      -I$(top_srcdir)/src/systemd/src/systemd \
 +      -I$(top_srcdir)/src/systemd/src/libsystemd-network \
++      -I$(top_srcdir)/src/systemd/src/basic \
 +      -I$(top_srcdir)/src/systemd/src/shared \
 +      -I$(top_srcdir)/src/systemd
 +
 +libsystemd_nm_la_SOURCES = \
 +      systemd/src/libsystemd/sd-id128/sd-id128.c \
 +      systemd/src/libsystemd-network/dhcp-identifier.c \
 +      systemd/src/libsystemd-network/dhcp-identifier.h \
 +      systemd/src/libsystemd-network/dhcp-network.c \
 +      systemd/src/libsystemd-network/dhcp-packet.c \
 +      systemd/src/libsystemd-network/dhcp-internal.h \
 +      systemd/src/libsystemd-network/dhcp6-network.c \
 +      systemd/src/libsystemd-network/dhcp6-lease-internal.h \
 +      systemd/src/libsystemd-network/dhcp6-option.c \
 +      systemd/src/libsystemd-network/network-internal.c \
 +      systemd/src/libsystemd-network/sd-dhcp-lease.c \
 +      systemd/src/libsystemd-network/sd-dhcp-client.c \
 +      systemd/src/libsystemd-network/dhcp-option.c \
 +      systemd/src/libsystemd-network/network-internal.h \
 +      systemd/src/libsystemd-network/sd-dhcp6-lease.c \
 +      systemd/src/libsystemd-network/dhcp-protocol.h \
 +      systemd/src/libsystemd-network/dhcp6-internal.h \
 +      systemd/src/libsystemd-network/dhcp6-protocol.h \
 +      systemd/src/libsystemd-network/dhcp-lease-internal.h \
 +      systemd/src/libsystemd-network/sd-dhcp6-client.c \
 +      systemd/src/libsystemd-network/ipv4ll-internal.h \
 +      systemd/src/libsystemd-network/sd-ipv4ll.c \
 +      systemd/src/libsystemd-network/ipv4ll-packet.c \
 +      systemd/src/libsystemd-network/ipv4ll-network.c \
++      systemd/src/basic/async.h \
++      systemd/src/basic/time-util.h \
++      systemd/src/basic/siphash24.h \
++      systemd/src/basic/time-util.c \
++      systemd/src/basic/socket-util.h \
++      systemd/src/basic/sparse-endian.h \
++      systemd/src/basic/macro.h \
++      systemd/src/basic/refcnt.h \
++      systemd/src/basic/util.c \
++      systemd/src/basic/in-addr-util.c \
++      systemd/src/basic/siphash24.c \
++      systemd/src/basic/util.h \
++      systemd/src/basic/in-addr-util.h \
++      systemd/src/basic/list.h \
++      systemd/src/basic/log.h \
++      systemd/src/basic/fileio.h \
++      systemd/src/basic/fileio.c \
++      systemd/src/basic/path-util.c \
++      systemd/src/basic/path-util.h \
++      systemd/src/basic/strv.h \
++      systemd/src/basic/strv.c \
++      systemd/src/basic/unaligned.h \
++      systemd/src/basic/utf8.h \
++      systemd/src/basic/utf8.c \
++      systemd/src/basic/hostname-util.h \
++      systemd/src/basic/hostname-util.c \
++      systemd/src/basic/random-util.h \
++      systemd/src/basic/random-util.c \
++      systemd/src/shared/dns-domain.c \
++      systemd/src/shared/dns-domain.h \
 +      systemd/src/systemd/sd-dhcp-lease.h \
 +      systemd/src/systemd/sd-dhcp-client.h \
 +      systemd/src/systemd/sd-id128.h \
 +      systemd/src/systemd/sd-dhcp6-lease.h \
 +      systemd/src/systemd/sd-dhcp6-client.h \
 +      systemd/src/systemd/sd-event.h \
 +      systemd/src/systemd/_sd-common.h \
 +      systemd/src/systemd/sd-ipv4ll.h \
 +      systemd/nm-sd-adapt.h \
 +      systemd/nm-sd-adapt.c
 +
 +libsystemd_nm_la_CPPFLAGS = \
 +      -I$(top_srcdir)/include \
 +      $(SYSTEMD_NM_CFLAGS) \
 +      $(GLIB_CFLAGS)
 +
 +libsystemd_nm_la_LIBADD = \
 +      $(GLIB_LIBS)
 +
  ###########################################
  # NetworkManager
  ###########################################
index 929ddc6,0000000..2419fe6
mode 100644,000000..100644
--- /dev/null
@@@ -1,127 -1,0 +1,127 @@@
- G_STMT_START { \
 +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 +/* This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License as published by
 + * the Free Software Foundation; either version 2, or (at your option)
 + * any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License along
 + * with this program; if not, write to the Free Software Foundation, Inc.,
 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + *
 + * Copyright (C) 2014 Red Hat, Inc.
 + */
 +
 +#ifndef NM_SD_ADAPT_H
 +#define NM_SD_ADAPT_H
 +
 +#include <config.h>
 +
 +#include <glib.h>
 +
 +#include <netinet/in.h>
 +#include <stdbool.h>
 +#include <syslog.h>
 +#include <string.h>
 +#include <stdio.h>
 +#include <errno.h>
 +#include <elf.h>
 +#ifdef HAVE_SYS_AUXV_H
 +#include <sys/auxv.h>
 +#endif
 +#include <unistd.h>
 +#include <sys/syscall.h>
 +
 +#include <net/if_arp.h>
 +#include <sys/resource.h>
 +
 +#include "nm-logging.h"
 +
 +/* Missing in Linux 3.2.0, in Ubuntu 12.04 */
 +#ifndef BPF_XOR
 +#define BPF_XOR 0xa0
 +#endif
 +
 +/*****************************************************************************/
 +
 +static inline NMLogLevel
 +_slog_level_to_nm (int slevel)
 +{
 +    switch (slevel) {
 +    case LOG_DEBUG:   return LOGL_DEBUG;
 +      case LOG_WARNING: return LOGL_WARN;
 +      case LOG_CRIT:
 +      case LOG_ERR:     return LOGL_ERR;
 +      case LOG_INFO:
 +      case LOG_NOTICE:
 +      default:          return LOGL_INFO;
 +      }
 +}
 +
 +#define log_internal(level, error, file, line, func, format, ...) \
 +({ \
 +      int _nm_e = (error); \
 +      NMLogLevel _nm_l = _slog_level_to_nm ((level)); \
 +      if (nm_logging_enabled (_nm_l, LOGD_DHCP)) { \
 +              const char *_nm_location = strrchr ((""file), '/'); \
 +              \
 +              _nm_log_impl (_nm_location ? _nm_location + 1 : (""file), (line), (func), _nm_l, LOGD_DHCP, _nm_e, ("%s"format), "sd-dhcp: ", ## __VA_ARGS__); \
 +      } \
 +      (_nm_e > 0 ? -_nm_e : _nm_e); \
 +})
 +
 +#define log_full_errno(level, error, ...) \
 +({ \
 +      log_internal(level, error, __FILE__, __LINE__, __func__, __VA_ARGS__); \
 +})
 +
 +#define log_assert_failed(text, file, line, func) \
 +G_STMT_START { \
 +      log_internal (LOG_CRIT, 0, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Aborting.", text, file, line, func); \
 +      g_assert_not_reached (); \
 +} G_STMT_END
 +
 +#define log_assert_failed_return(text, file, line, func) \
- } G_STMT_END
++({ \
 +      log_internal (LOG_DEBUG, 0, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Ignoring.", text, file, line, func); \
 +      g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, text); \
++      (void) 0; \
++})
 +
 +/*****************************************************************************/
 +
 +/* Can't include both net/if.h and linux/if.h; so have to define this here */
 +#ifndef IFNAMSIZ
 +#define IFNAMSIZ 16
 +#endif
 +
 +#ifndef MAX_HANDLE_SZ
 +#define MAX_HANDLE_SZ 128
 +#endif
 +
 +#define noreturn G_GNUC_NORETURN
 +
 +/*
 + * Some toolchains (E.G. uClibc 0.9.33 and earlier) don't export
 + * CLOCK_BOOTTIME even though the kernel supports it, so provide a
 + * local definition
 + */
 +#ifndef CLOCK_BOOTTIME
 +#define CLOCK_BOOTTIME 7
 +#endif
 +
 +#include "sd-id128.h"
 +#include "sparse-endian.h"
 +#include "async.h"
 +#include "util.h"
 +
 +static inline pid_t gettid(void) {
 +        return (pid_t) syscall(SYS_gettid);
 +}
 +
 +#endif /* NM_SD_ADAPT_H */
 +
Simple merge
Simple merge
Simple merge
index 0000000,e336f26..e7e07c1
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,193 +1,197 @@@
+ /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+ /***
+   This file is part of systemd.
+   Copyright 2015 Lennart Poettering
+   systemd is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2.1 of the License, or
+   (at your option) any later version.
+   systemd is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   Lesser General Public License for more details.
+   You should have received a copy of the GNU Lesser General Public License
+   along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ ***/
++#include "nm-sd-adapt.h"
++
+ #include <sys/utsname.h>
+ #include <ctype.h>
+ #include "util.h"
+ #include "hostname-util.h"
+ bool hostname_is_set(void) {
+         struct utsname u;
+         assert_se(uname(&u) >= 0);
+         if (isempty(u.nodename))
+                 return false;
+         /* This is the built-in kernel default host name */
+         if (streq(u.nodename, "(none)"))
+                 return false;
+         return true;
+ }
+ char* gethostname_malloc(void) {
+         struct utsname u;
+         assert_se(uname(&u) >= 0);
+         if (isempty(u.nodename) || streq(u.nodename, "(none)"))
+                 return strdup(u.sysname);
+         return strdup(u.nodename);
+ }
+ static bool hostname_valid_char(char c) {
+         return
+                 (c >= 'a' && c <= 'z') ||
+                 (c >= 'A' && c <= 'Z') ||
+                 (c >= '0' && c <= '9') ||
+                 c == '-' ||
+                 c == '_' ||
+                 c == '.';
+ }
+ bool hostname_is_valid(const char *s) {
+         const char *p;
+         bool dot;
+         if (isempty(s))
+                 return false;
+         /* Doesn't accept empty hostnames, hostnames with trailing or
+          * leading dots, and hostnames with multiple dots in a
+          * sequence. Also ensures that the length stays below
+          * HOST_NAME_MAX. */
+         for (p = s, dot = true; *p; p++) {
+                 if (*p == '.') {
+                         if (dot)
+                                 return false;
+                         dot = true;
+                 } else {
+                         if (!hostname_valid_char(*p))
+                                 return false;
+                         dot = false;
+                 }
+         }
+         if (dot)
+                 return false;
+         if (p-s > HOST_NAME_MAX)
+                 return false;
+         return true;
+ }
+ char* hostname_cleanup(char *s, bool lowercase) {
+         char *p, *d;
+         bool dot;
+         assert(s);
+         for (p = s, d = s, dot = true; *p; p++) {
+                 if (*p == '.') {
+                         if (dot)
+                                 continue;
+                         *(d++) = '.';
+                         dot = true;
+                 } else if (hostname_valid_char(*p)) {
+                         *(d++) = lowercase ? tolower(*p) : *p;
+                         dot = false;
+                 }
+         }
+         if (dot && d > s)
+                 d[-1] = 0;
+         else
+                 *d = 0;
+         strshorten(s, HOST_NAME_MAX);
+         return s;
+ }
+ bool is_localhost(const char *hostname) {
+         assert(hostname);
+         /* This tries to identify local host and domain names
+          * described in RFC6761 plus the redhatism of .localdomain */
+         return streq(hostname, "localhost") ||
+                streq(hostname, "localhost.") ||
+                streq(hostname, "localdomain.") ||
+                streq(hostname, "localdomain") ||
+                endswith(hostname, ".localhost") ||
+                endswith(hostname, ".localhost.") ||
+                endswith(hostname, ".localdomain") ||
+                endswith(hostname, ".localdomain.");
+ }
++#if 0 /* NM_IGNORED */
+ int sethostname_idempotent(const char *s) {
+         char buf[HOST_NAME_MAX + 1] = {};
+         assert(s);
+         if (gethostname(buf, sizeof(buf)) < 0)
+                 return -errno;
+         if (streq(buf, s))
+                 return 0;
+         if (sethostname(s, strlen(s)) < 0)
+                 return -errno;
+         return 1;
+ }
+ int read_hostname_config(const char *path, char **hostname) {
+         _cleanup_fclose_ FILE *f = NULL;
+         char l[LINE_MAX];
+         char *name = NULL;
+         assert(path);
+         assert(hostname);
+         f = fopen(path, "re");
+         if (!f)
+                 return -errno;
+         /* may have comments, ignore them */
+         FOREACH_LINE(l, f, return -errno) {
+                 truncate_nl(l);
+                 if (l[0] != '\0' && l[0] != '#') {
+                         /* found line with value */
+                         name = hostname_cleanup(l, false);
+                         name = strdup(name);
+                         if (!name)
+                                 return -ENOMEM;
+                         break;
+                 }
+         }
+         if (!name)
+                 /* no non-empty line found */
+                 return -ENOENT;
+         *hostname = name;
+         return 0;
+ }
++#endif /* NM_IGNORED */
index 0000000,0c4763c..ccd6803
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,39 +1,41 @@@
+ /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+ #pragma once
+ /***
+   This file is part of systemd.
+   Copyright 2010-2015 Lennart Poettering
+   systemd is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2.1 of the License, or
+   (at your option) any later version.
+   systemd is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   Lesser General Public License for more details.
+   You should have received a copy of the GNU Lesser General Public License
+   along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ ***/
++#include "nm-sd-adapt.h"
++
+ #include <stdbool.h>
+ #include "macro.h"
+ bool hostname_is_set(void);
+ char* gethostname_malloc(void);
+ bool hostname_is_valid(const char *s) _pure_;
+ char* hostname_cleanup(char *s, bool lowercase);
+ bool is_localhost(const char *hostname);
+ int sethostname_idempotent(const char *s);
+ int read_hostname_config(const char *path, char **hostname);
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
  #include "util.h"
  #include "log.h"
  #include "strv.h"
 +#endif /* NM_IGNORED */
  #include "path-util.h"
 +#if 0 /* NM_IGNORED */
  #include "missing.h"
+ #include "fileio.h"
  
  bool path_is_absolute(const char *p) {
          return p[0] == '/';
@@@ -721,4 -817,37 +824,38 @@@ int fsck_exists(const char *fstype) 
  
          return 0;
  }
+ char *prefix_root(const char *root, const char *path) {
+         char *n, *p;
+         size_t l;
+         /* If root is passed, prefixes path with it. Otherwise returns
+          * it as is. */
+         assert(path);
+         /* First, drop duplicate prefixing slashes from the path */
+         while (path[0] == '/' && path[1] == '/')
+                 path++;
+         if (isempty(root) || path_equal(root, "/"))
+                 return strdup(path);
+         l = strlen(root) + 1 + strlen(path) + 1;
+         n = new(char, l);
+         if (!n)
+                 return NULL;
+         p = stpcpy(n, root);
+         while (p > n && p[-1] == '/')
+                 p--;
+         if (path[0] != '/')
+                 *(p++) = '/';
+         strcpy(p, path);
+         return n;
+ }
 +#endif /* NM_IGNORED */
Simple merge
index 0000000,b230044..8d6f2eb
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,129 +1,137 @@@
+ /***
+   This file is part of systemd.
+   Copyright 2010 Lennart Poettering
+   systemd is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2.1 of the License, or
+   (at your option) any later version.
+   systemd is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   Lesser General Public License for more details.
+   You should have received a copy of the GNU Lesser General Public License
+   along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ ***/
++#include "nm-sd-adapt.h"
++
+ #include <stdint.h>
+ #include <errno.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>
+ #include <time.h>
+ #ifdef HAVE_SYS_AUXV_H
+ #include <sys/auxv.h>
+ #endif
+ #include <linux/random.h>
+ #include "random-util.h"
+ #include "time-util.h"
++#if 0 /* NM_IGNORED */
+ #include "missing.h"
++#endif
+ #include "util.h"
+ int dev_urandom(void *p, size_t n) {
++#if 0 /* NM_IGNORED */
+         static int have_syscall = -1;
+         _cleanup_close_ int fd = -1;
+         int r;
+         /* Gathers some randomness from the kernel. This call will
+          * never block, and will always return some data from the
+          * kernel, regardless if the random pool is fully initialized
+          * or not. It thus makes no guarantee for the quality of the
+          * returned entropy, but is good enough for or usual usecases
+          * of seeding the hash functions for hashtable */
+         /* Use the getrandom() syscall unless we know we don't have
+          * it, or when the requested size is too large for it. */
+         if (have_syscall != 0 || (size_t) (int) n != n) {
+                 r = getrandom(p, n, GRND_NONBLOCK);
+                 if (r == (int) n) {
+                         have_syscall = true;
+                         return 0;
+                 }
+                 if (r < 0) {
+                         if (errno == ENOSYS)
+                                 /* we lack the syscall, continue with
+                                  * reading from /dev/urandom */
+                                 have_syscall = false;
+                         else if (errno == EAGAIN)
+                                 /* not enough entropy for now. Let's
+                                  * remember to use the syscall the
+                                  * next time, again, but also read
+                                  * from /dev/urandom for now, which
+                                  * doesn't care about the current
+                                  * amount of entropy.  */
+                                 have_syscall = true;
+                         else
+                                 return -errno;
+                 } else
+                         /* too short read? */
+                         return -ENODATA;
+         }
++#else /* NM_IGNORED */
++        _cleanup_close_ int fd = -1;
++#endif /* NM_IGNORED */
+         fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
+         if (fd < 0)
+                 return errno == ENOENT ? -ENOSYS : -errno;
+         return loop_read_exact(fd, p, n, true);
+ }
+ void initialize_srand(void) {
+         static bool srand_called = false;
+         unsigned x;
+ #ifdef HAVE_SYS_AUXV_H
+         void *auxv;
+ #endif
+         if (srand_called)
+                 return;
+         x = 0;
+ #ifdef HAVE_SYS_AUXV_H
+         /* The kernel provides us with a bit of entropy in auxv, so
+          * let's try to make use of that to seed the pseudo-random
+          * generator. It's better than nothing... */
+         auxv = (void*) getauxval(AT_RANDOM);
+         if (auxv)
+                 x ^= *(unsigned*) auxv;
+ #endif
+         x ^= (unsigned) now(CLOCK_REALTIME);
+         x ^= (unsigned) gettid();
+         srand(x);
+         srand_called = true;
+ }
+ void random_bytes(void *p, size_t n) {
+         uint8_t *q;
+         int r;
+         r = dev_urandom(p, n);
+         if (r >= 0)
+                 return;
+         /* If some idiot made /dev/urandom unavailable to us, he'll
+          * get a PRNG instead. */
+         initialize_srand();
+         for (q = p; q < (uint8_t*) p + n; q ++)
+                 *q = rand();
+ }
index 0000000,f7862c8..3575ee9
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,38 +1,40 @@@
+ #pragma once
+ /***
+   This file is part of systemd.
+   Copyright 2010 Lennart Poettering
+   systemd is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2.1 of the License, or
+   (at your option) any later version.
+   systemd is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   Lesser General Public License for more details.
+   You should have received a copy of the GNU Lesser General Public License
+   along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ ***/
++#include "nm-sd-adapt.h"
++
+ #include <stdint.h>
+ int dev_urandom(void *p, size_t n);
+ void random_bytes(void *p, size_t n);
+ void initialize_srand(void);
+ static inline uint64_t random_u64(void) {
+         uint64_t u;
+         random_bytes(&u, sizeof(u));
+         return u;
+ }
+ static inline uint32_t random_u32(void) {
+         uint32_t u;
+         random_bytes(&u, sizeof(u));
+         return u;
+ }
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
  #include "env-util.h"
  #include "fileio.h"
  #include "device-nodes.h"
++#endif /* NM_IGNORED */
  #include "utf8.h"
++#if 0 /* NM_IGNORED */
  #include "gunicode.h"
  #include "virt.h"
  #include "def.h"
  #include "sparse-endian.h"
+ #include "formats-util.h"
+ #include "process-util.h"
+ #include "random-util.h"
+ #include "terminal-util.h"
+ #include "hostname-util.h"
+ #include "signal-util.h"
 +#endif /* NM_IGNORED */
  
  /* Put this test here for a lack of better place */
  assert_cc(EAGAIN == EWOULDBLOCK);
@@@ -381,10 -391,11 +402,12 @@@ int parse_uid(const char *s, uid_t* ret
          if (uid == (uid_t) 0xFFFF)
                  return -ENXIO;
  
-         *ret_uid = uid;
+         if (ret_uid)
+                 *ret_uid = uid;
          return 0;
  }
 +#endif /* NM_IGNORED */
  
  int safe_atou(const char *s, unsigned *ret_u) {
          char *x = NULL;
@@@ -1113,42 -771,6 +786,7 @@@ int readlink_and_canonicalize(const cha
  
          return 0;
  }
- int reset_all_signal_handlers(void) {
-         int sig, r = 0;
-         for (sig = 1; sig < _NSIG; sig++) {
-                 struct sigaction sa = {
-                         .sa_handler = SIG_DFL,
-                         .sa_flags = SA_RESTART,
-                 };
-                 /* These two cannot be caught... */
-                 if (sig == SIGKILL || sig == SIGSTOP)
-                         continue;
-                 /* On Linux the first two RT signals are reserved by
-                  * glibc, and sigaction() will return EINVAL for them. */
-                 if ((sigaction(sig, &sa, NULL) < 0))
-                         if (errno != EINVAL && r == 0)
-                                 r = -errno;
-         }
-         return r;
- }
- int reset_signal_mask(void) {
-         sigset_t ss;
-         if (sigemptyset(&ss) < 0)
-                 return -errno;
-         if (sigprocmask(SIG_SETMASK, &ss, NULL) < 0)
-                 return -errno;
-         return 0;
- }
 +#endif /* NM_IGNORED */
  
  char *strstrip(char *s) {
          char *e;
@@@ -1781,120 -1491,128 +1512,130 @@@ bool fstype_is_network(const char *fsty
          return nulstr_contains(table, fstype);
  }
  
- int chvt(int vt) {
-         _cleanup_close_ int fd;
+ int flush_fd(int fd) {
+         struct pollfd pollfd = {
+                 .fd = fd,
+                 .events = POLLIN,
+         };
  
-         fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
-         if (fd < 0)
-                 return -errno;
+         for (;;) {
+                 char buf[LINE_MAX];
+                 ssize_t l;
+                 int r;
  
-         if (vt < 0) {
-                 int tiocl[2] = {
-                         TIOCL_GETKMSGREDIRECT,
-                         0
-                 };
+                 r = poll(&pollfd, 1, 0);
+                 if (r < 0) {
+                         if (errno == EINTR)
+                                 continue;
  
-                 if (ioctl(fd, TIOCLINUX, tiocl) < 0)
                          return -errno;
  
-                 vt = tiocl[0] <= 0 ? 1 : tiocl[0];
-         }
+                 } else if (r == 0)
+                         return 0;
  
-         if (ioctl(fd, VT_ACTIVATE, vt) < 0)
-                 return -errno;
+                 l = read(fd, buf, sizeof(buf));
+                 if (l < 0) {
  
-         return 0;
+                         if (errno == EINTR)
+                                 continue;
+                         if (errno == EAGAIN)
+                                 return 0;
+                         return -errno;
+                 } else if (l == 0)
+                         return 0;
+         }
  }
  
- int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
-         struct termios old_termios, new_termios;
-         char c, line[LINE_MAX];
+ void safe_close_pair(int p[]) {
+         assert(p);
  
-         assert(f);
-         assert(ret);
+         if (p[0] == p[1]) {
+                 /* Special case pairs which use the same fd in both
+                  * directions... */
+                 p[0] = p[1] = safe_close(p[0]);
+                 return;
+         }
  
-         if (tcgetattr(fileno(f), &old_termios) >= 0) {
-                 new_termios = old_termios;
+         p[0] = safe_close(p[0]);
+         p[1] = safe_close(p[1]);
+ }
  
-                 new_termios.c_lflag &= ~ICANON;
-                 new_termios.c_cc[VMIN] = 1;
-                 new_termios.c_cc[VTIME] = 0;
++#endif /* NM_IGNORED */
+ ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
+         uint8_t *p = buf;
+         ssize_t n = 0;
  
-                 if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) {
-                         size_t k;
+         assert(fd >= 0);
+         assert(buf);
  
-                         if (t != USEC_INFINITY) {
-                                 if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0) {
-                                         tcsetattr(fileno(f), TCSADRAIN, &old_termios);
-                                         return -ETIMEDOUT;
-                                 }
-                         }
+         while (nbytes > 0) {
+                 ssize_t k;
  
-                         k = fread(&c, 1, 1, f);
+                 k = read(fd, p, nbytes);
+                 if (k < 0) {
+                         if (errno == EINTR)
+                                 continue;
  
-                         tcsetattr(fileno(f), TCSADRAIN, &old_termios);
+                         if (errno == EAGAIN && do_poll) {
  
-                         if (k <= 0)
-                                 return -EIO;
+                                 /* We knowingly ignore any return value here,
+                                  * and expect that any error/EOF is reported
+                                  * via read() */
  
-                         if (need_nl)
-                                 *need_nl = c != '\n';
+                                 fd_wait_for_event(fd, POLLIN, USEC_INFINITY);
+                                 continue;
+                         }
  
-                         *ret = c;
-                         return 0;
+                         return n > 0 ? n : -errno;
                  }
-         }
-         if (t != USEC_INFINITY) {
-                 if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0)
-                         return -ETIMEDOUT;
-         }
  
-         errno = 0;
-         if (!fgets(line, sizeof(line), f))
-                 return errno ? -errno : -EIO;
+                 if (k == 0)
+                         return n;
  
-         truncate_nl(line);
+                 p += k;
+                 nbytes -= k;
+                 n += k;
+         }
  
-         if (strlen(line) != 1)
-                 return -EBADMSG;
+         return n;
+ }
  
-         if (need_nl)
-                 *need_nl = false;
+ int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll) {
+         ssize_t n;
  
-         *ret = line[0];
+         n = loop_read(fd, buf, nbytes, do_poll);
+         if (n < 0)
+                 return n;
+         if ((size_t) n != nbytes)
+                 return -EIO;
          return 0;
  }
  
- int ask_char(char *ret, const char *replies, const char *text, ...) {
-         int r;
-         assert(ret);
-         assert(replies);
-         assert(text);
-         for (;;) {
-                 va_list ap;
-                 char c;
-                 bool need_nl = true;
++#if 0 /* NM_IGNORED */
+ int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
+         const uint8_t *p = buf;
  
-                 if (on_tty())
-                         fputs(ANSI_HIGHLIGHT_ON, stdout);
+         assert(fd >= 0);
+         assert(buf);
  
-                 va_start(ap, text);
-                 vprintf(text, ap);
-                 va_end(ap);
+         errno = 0;
  
-                 if (on_tty())
-                         fputs(ANSI_HIGHLIGHT_OFF, stdout);
+         do {
+                 ssize_t k;
  
-                 fflush(stdout);
+                 k = write(fd, p, nbytes);
+                 if (k < 0) {
+                         if (errno == EINTR)
+                                 continue;
  
-                 r = read_one_char(stdin, &c, USEC_INFINITY, &need_nl);
-                 if (r < 0) {
+                         if (errno == EAGAIN && do_poll) {
+                                 /* We knowingly ignore any return value here,
+                                  * and expect that any error/EOF is reported
+                                  * via write() */
  
-                         if (r == -EBADMSG) {
-                                 puts("Bad input, please try again.");
+                                 fd_wait_for_event(fd, POLLOUT, USEC_INFINITY);
                                  continue;
                          }
  
@@@ -4112,6 -2449,6 +2472,7 @@@ bool nulstr_contains(const char*nulstr
  bool plymouth_running(void) {
          return access("/run/plymouth/pid", F_OK) >= 0;
  }
++#endif /* NM_IGNORED */
  
  char* strshorten(char *s, size_t l) {
          assert(s);
  
          return s;
  }
- #endif /* NM_IGNORED */
- static bool hostname_valid_char(char c) {
-         return
-                 (c >= 'a' && c <= 'z') ||
-                 (c >= 'A' && c <= 'Z') ||
-                 (c >= '0' && c <= '9') ||
-                 c == '-' ||
-                 c == '_' ||
-                 c == '.';
- }
- bool hostname_is_valid(const char *s) {
-         const char *p;
-         bool dot;
-         if (isempty(s))
-                 return false;
-         /* Doesn't accept empty hostnames, hostnames with trailing or
-          * leading dots, and hostnames with multiple dots in a
-          * sequence. Also ensures that the length stays below
-          * HOST_NAME_MAX. */
-         for (p = s, dot = true; *p; p++) {
-                 if (*p == '.') {
-                         if (dot)
-                                 return false;
-                         dot = true;
-                 } else {
-                         if (!hostname_valid_char(*p))
-                                 return false;
-                         dot = false;
-                 }
-         }
-         if (dot)
-                 return false;
-         if (p-s > HOST_NAME_MAX)
-                 return false;
-         return true;
- }
  
- char* hostname_cleanup(char *s, bool lowercase) {
-         char *p, *d;
-         bool dot;
-         for (p = s, d = s, dot = true; *p; p++) {
-                 if (*p == '.') {
-                         if (dot)
-                                 continue;
-                         *(d++) = '.';
-                         dot = true;
-                 } else if (hostname_valid_char(*p)) {
-                         *(d++) = lowercase ? tolower(*p) : *p;
-                         dot = false;
-                 }
-         }
-         if (dot && d > s)
-                 d[-1] = 0;
-         else
-                 *d = 0;
-         strshorten(s, HOST_NAME_MAX);
-         return s;
- }
 +#if 0 /* NM_IGNORED */
  bool machine_name_is_valid(const char *s) {
  
          if (!hostname_is_valid(s))
@@@ -4283,59 -2544,14 +2570,15 @@@ int fopen_temporary(const char *path, F
          return 0;
  }
  
- int terminal_vhangup_fd(int fd) {
-         assert(fd >= 0);
-         if (ioctl(fd, TIOCVHANGUP) < 0)
-                 return -errno;
-         return 0;
- }
- int terminal_vhangup(const char *name) {
-         _cleanup_close_ int fd;
-         fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
-         if (fd < 0)
-                 return fd;
-         return terminal_vhangup_fd(fd);
- }
- int vt_disallocate(const char *name) {
-         int fd, r;
-         unsigned u;
-         /* Deallocate the VT if possible. If not possible
-          * (i.e. because it is the active one), at least clear it
-          * entirely (including the scrollback buffer) */
-         if (!startswith(name, "/dev/"))
-                 return -EINVAL;
-         if (!tty_is_vc(name)) {
-                 /* So this is not a VT. I guess we cannot deallocate
-                  * it then. But let's at least clear the screen */
-                 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
-                 if (fd < 0)
-                         return fd;
-                 loop_write(fd,
-                            "\033[r"    /* clear scrolling region */
-                            "\033[H"    /* move home */
-                            "\033[2J",  /* clear screen */
-                            10, false);
-                 safe_close(fd);
-                 return 0;
-         }
 +#if 0 /* NM_IGNORED */
+ int symlink_atomic(const char *from, const char *to) {
+         _cleanup_free_ char *t = NULL;
+         int r;
  
-         if (!startswith(name, "/dev/tty"))
-                 return -EINVAL;
+         assert(from);
+         assert(to);
  
-         r = safe_atou(name+8, &u);
+         r = tempfn_random(to, NULL, &t);
          if (r < 0)
                  return r;
  
@@@ -7022,8 -5001,7 +5041,8 @@@ int tempfn_xxxxxx(const char *p, const 
          return 0;
  }
  
- int tempfn_random(const char *p, char **ret) {
 +#if 0 /* NM_IGNORED */
+ int tempfn_random(const char *p, const char *extra, char **ret) {
          const char *fn;
          char *t, *x;
          uint64_t u;
@@@ -8114,4 -5956,96 +5999,97 @@@ int rename_noreplace(int olddirfd, cons
  
          return 0;
  }
+ char *shell_maybe_quote(const char *s) {
+         const char *p;
+         char *r, *t;
+         assert(s);
+         /* Encloses a string in double quotes if necessary to make it
+          * OK as shell string. */
+         for (p = s; *p; p++)
+                 if (*p <= ' ' ||
+                     *p >= 127 ||
+                     strchr(SHELL_NEED_QUOTES, *p))
+                         break;
+         if (!*p)
+                 return strdup(s);
+         r = new(char, 1+strlen(s)*2+1+1);
+         if (!r)
+                 return NULL;
+         t = r;
+         *(t++) = '"';
+         t = mempcpy(t, s, p - s);
+         for (; *p; p++) {
+                 if (strchr(SHELL_NEED_ESCAPE, *p))
+                         *(t++) = '\\';
+                 *(t++) = *p;
+         }
+         *(t++)= '"';
+         *t = 0;
+         return r;
+ }
+ int parse_mode(const char *s, mode_t *ret) {
+         char *x;
+         long l;
+         assert(s);
+         assert(ret);
+         errno = 0;
+         l = strtol(s, &x, 8);
+         if (errno != 0)
+                 return -errno;
+         if (!x || x == s || *x)
+                 return -EINVAL;
+         if (l < 0 || l  > 07777)
+                 return -ERANGE;
+         *ret = (mode_t) l;
+         return 0;
+ }
+ int mount_move_root(const char *path) {
+         assert(path);
+         if (chdir(path) < 0)
+                 return -errno;
+         if (mount(path, "/", NULL, MS_MOVE, NULL) < 0)
+                 return -errno;
+         if (chroot(".") < 0)
+                 return -errno;
+         if (chdir("/") < 0)
+                 return -errno;
+         return 0;
+ }
+ int reset_uid_gid(void) {
+         if (setgroups(0, NULL) < 0)
+                 return -errno;
+         if (setresgid(0, 0, 0) < 0)
+                 return -errno;
+         if (setresuid(0, 0, 0) < 0)
+                 return -errno;
+         return 0;
+ }
 +#endif /* NM_IGNORED */
  #include <sys/inotify.h>
  #include <sys/statfs.h>
  
- #if 0 /* NM_IGNORED */
- #if SIZEOF_PID_T == 4
- #  define PID_PRI PRIi32
- #elif SIZEOF_PID_T == 2
- #  define PID_PRI PRIi16
- #else
- #  error Unknown pid_t size
- #endif
- #define PID_FMT "%" PID_PRI
- #if SIZEOF_UID_T == 4
- #  define UID_FMT "%" PRIu32
- #elif SIZEOF_UID_T == 2
- #  define UID_FMT "%" PRIu16
- #else
- #  error Unknown uid_t size
- #endif
- #if SIZEOF_GID_T == 4
- #  define GID_FMT "%" PRIu32
- #elif SIZEOF_GID_T == 2
- #  define GID_FMT "%" PRIu16
- #else
- #  error Unknown gid_t size
- #endif
- #if SIZEOF_TIME_T == 8
- #  define PRI_TIME PRIi64
- #elif SIZEOF_TIME_T == 4
- #  define PRI_TIME PRIu32
- #else
- #  error Unknown time_t size
- #endif
- #if SIZEOF_RLIM_T == 8
- #  define RLIM_FMT "%" PRIu64
- #elif SIZEOF_RLIM_T == 4
- #  define RLIM_FMT "%" PRIu32
- #else
- #  error Unknown rlim_t size
- #endif
- #endif /* NM_IGNORED */
  #include "macro.h"
 +#if 0 /* NM_IGNORED */
  #include "missing.h"
 +#endif /* NM_IGNORED */
  #include "time-util.h"
++#if 0 /* NM_IGNORED */
+ #include "formats-util.h"
++#endif /* NM_IGNORED */
  
  /* What is interpreted as whitespace? */
  #define WHITESPACE " \t\n\r"
@@@ -980,13 -790,8 +796,10 @@@ int container_get_leader(const char *ma
  int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *root_fd);
  int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int root_fd);
  
- bool pid_is_alive(pid_t pid);
- bool pid_is_unwaited(pid_t pid);
 +#if 0 /* NM_IGNORED */
  int getpeercred(int fd, struct ucred *ucred);
  int getpeersec(int fd, char **ret);
 +#endif /* NM_IGNORED */
  
  int writev_safe(int fd, const struct iovec *w, int j);
  
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
  
  #include "sd-id128.h"
- #if 0 /* NM_IGNORED a*/
++#if 0 /* NM_IGNORED */
  #include "libudev.h"
  #include "udev-util.h"
  
@@@ -63,8 -59,7 +64,8 @@@ int dhcp_identifier_set_duid_en(struct 
  }
  
  
- int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, uint32_t *_id) {
+ int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id) {
 +#if 0 /* NM_IGNORED */
          /* name is a pointer to memory in the udev_device struct, so must
             have the same scope */
          _cleanup_udev_device_unref_ struct udev_device *device = NULL;
@@@ -710,23 -678,11 +720,23 @@@ int sd_dhcp_lease_save(sd_dhcp_lease *l
          if (r >= 0)
                  serialize_dhcp_routes(f, "ROUTES", routes, r);
  
 +        r = sd_dhcp_lease_get_vendor_specific(lease, &data);
 +        if (r >= 0) {
 +                _cleanup_free_ char *option_hex = NULL;
 +
 +                option_hex = hexmem(data, r);
 +                if (!option_hex) {
 +                        r = -ENOMEM;
 +                        goto finish;
 +                }
 +                fprintf(f, "VENDOR_SPECIFIC=%s\n", option_hex);
 +        }
 +
          r = sd_dhcp_lease_get_client_id(lease, &client_id, &client_id_len);
          if (r >= 0) {
 -                _cleanup_free_ char *client_id_hex;
 +                _cleanup_free_ char *client_id_hex = NULL;
  
-                 client_id_hex = hexmem (client_id, client_id_len);
+                 client_id_hex = hexmem(client_id, client_id_len);
                  if (!client_id_hex) {
                          r = -ENOMEM;
                          goto finish;
  #include <sys/ioctl.h>
  #include <linux/if_infiniband.h>
  
 +#if 0 /* NM_IGNORED */
  #include "udev.h"
  #include "udev-util.h"
 +#endif /* NM_IGNORED */
  #include "util.h"
  #include "refcnt.h"
+ #include "random-util.h"
  
  #include "network-internal.h"
  #include "sd-dhcp6-client.h"
@@@ -28,8 -26,8 +28,9 @@@
  #include "util.h"
  #include "macro.h"
  #include "sd-id128.h"
+ #include "random-util.h"
  
 +#if 0 /* NM_IGNORED */
  _public_ char *sd_id128_to_string(sd_id128_t id, char s[33]) {
          unsigned n;
  
index 0000000,20a44ce..59fb3f9
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,613 +1,617 @@@
+ /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+ /***
+   This file is part of systemd.
+   Copyright 2014 Lennart Poettering
+   systemd is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2.1 of the License, or
+   (at your option) any later version.
+   systemd is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   Lesser General Public License for more details.
+   You should have received a copy of the GNU Lesser General Public License
+   along with systemd; If not, see <http://www.gnu.org/licenses/>.
+  ***/
++#include "nm-sd-adapt.h"
++
+ #ifdef HAVE_LIBIDN
+ #include <idna.h>
+ #include <stringprep.h>
+ #endif
+ #include "dns-domain.h"
+ int dns_label_unescape(const char **name, char *dest, size_t sz) {
+         const char *n;
+         char *d;
+         int r = 0;
+         assert(name);
+         assert(*name);
+         assert(dest);
+         n = *name;
+         d = dest;
+         for (;;) {
+                 if (*n == '.') {
+                         n++;
+                         break;
+                 }
+                 if (*n == 0)
+                         break;
+                 if (sz <= 0)
+                         return -ENOSPC;
+                 if (r >= DNS_LABEL_MAX)
+                         return -EINVAL;
+                 if (*n == '\\') {
+                         /* Escaped character */
+                         n++;
+                         if (*n == 0)
+                                 /* Ending NUL */
+                                 return -EINVAL;
+                         else if (*n == '\\' || *n == '.') {
+                                 /* Escaped backslash or dot */
+                                 *(d++) = *(n++);
+                                 sz--;
+                                 r++;
+                         } else if (n[0] >= '0' && n[0] <= '9') {
+                                 unsigned k;
+                                 /* Escaped literal ASCII character */
+                                 if (!(n[1] >= '0' && n[1] <= '9') ||
+                                     !(n[2] >= '0' && n[2] <= '9'))
+                                         return -EINVAL;
+                                 k = ((unsigned) (n[0] - '0') * 100) +
+                                         ((unsigned) (n[1] - '0') * 10) +
+                                         ((unsigned) (n[2] - '0'));
+                                 /* Don't allow CC characters or anything that doesn't fit in 8bit */
+                                 if (k < ' ' || k > 255 || k == 127)
+                                         return -EINVAL;
+                                 *(d++) = (char) k;
+                                 sz--;
+                                 r++;
+                                 n += 3;
+                         } else
+                                 return -EINVAL;
+                 } else if ((uint8_t) *n >= (uint8_t) ' ' && *n != 127) {
+                         /* Normal character */
+                         *(d++) = *(n++);
+                         sz--;
+                         r++;
+                 } else
+                         return -EINVAL;
+         }
+         /* Empty label that is not at the end? */
+         if (r == 0 && *n)
+                 return -EINVAL;
+         if (sz >= 1)
+                 *d = 0;
+         *name = n;
+         return r;
+ }
+ int dns_label_escape(const char *p, size_t l, char **ret) {
+         _cleanup_free_ char *s = NULL;
+         char *q;
+         int r;
+         assert(p);
+         assert(ret);
+         if (l > DNS_LABEL_MAX)
+                 return -EINVAL;
+         s = malloc(l * 4 + 1);
+         if (!s)
+                 return -ENOMEM;
+         q = s;
+         while (l > 0) {
+                 if (*p == '.' || *p == '\\') {
+                         /* Dot or backslash */
+                         *(q++) = '\\';
+                         *(q++) = *p;
+                 } else if (*p == '_' ||
+                            *p == '-' ||
+                            (*p >= '0' && *p <= '9') ||
+                            (*p >= 'a' && *p <= 'z') ||
+                            (*p >= 'A' && *p <= 'Z')) {
+                         /* Proper character */
+                         *(q++) = *p;
+                 } else if ((uint8_t) *p >= (uint8_t) ' ' && *p != 127) {
+                         /* Everything else */
+                         *(q++) = '\\';
+                         *(q++) = '0' + (char) ((uint8_t) *p / 100);
+                         *(q++) = '0' + (char) (((uint8_t) *p / 10) % 10);
+                         *(q++) = '0' + (char) ((uint8_t) *p % 10);
+                 } else
+                         return -EINVAL;
+                 p++;
+                 l--;
+         }
+         *q = 0;
+         *ret = s;
+         r = q - s;
+         s = NULL;
+         return r;
+ }
+ int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
+ #ifdef HAVE_LIBIDN
+         _cleanup_free_ uint32_t *input = NULL;
+         size_t input_size;
+         const char *p;
+         bool contains_8bit = false;
+         assert(encoded);
+         assert(decoded);
+         assert(decoded_max >= DNS_LABEL_MAX);
+         if (encoded_size <= 0)
+                 return 0;
+         for (p = encoded; p < encoded + encoded_size; p++)
+                 if ((uint8_t) *p > 127)
+                         contains_8bit = true;
+         if (!contains_8bit)
+                 return 0;
+         input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
+         if (!input)
+                 return -ENOMEM;
+         if (idna_to_ascii_4i(input, input_size, decoded, 0) != 0)
+                 return -EINVAL;
+         return strlen(decoded);
+ #else
+         return 0;
+ #endif
+ }
+ int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
+ #ifdef HAVE_LIBIDN
+         size_t input_size, output_size;
+         _cleanup_free_ uint32_t *input = NULL;
+         _cleanup_free_ char *result = NULL;
+         uint32_t *output = NULL;
+         size_t w;
+         /* To be invoked after unescaping */
+         assert(encoded);
+         assert(decoded);
+         if (encoded_size < sizeof(IDNA_ACE_PREFIX)-1)
+                 return 0;
+         if (memcmp(encoded, IDNA_ACE_PREFIX, sizeof(IDNA_ACE_PREFIX) -1) != 0)
+                 return 0;
+         input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
+         if (!input)
+                 return -ENOMEM;
+         output_size = input_size;
+         output = newa(uint32_t, output_size);
+         idna_to_unicode_44i(input, input_size, output, &output_size, 0);
+         result = stringprep_ucs4_to_utf8(output, output_size, NULL, &w);
+         if (!result)
+                 return -ENOMEM;
+         if (w <= 0)
+                 return 0;
+         if (w+1 > decoded_max)
+                 return -EINVAL;
+         memcpy(decoded, result, w+1);
+         return w;
+ #else
+         return 0;
+ #endif
+ }
+ int dns_name_normalize(const char *s, char **_ret) {
+         _cleanup_free_ char *ret = NULL;
+         size_t n = 0, allocated = 0;
+         const char *p = s;
+         bool first = true;
+         int r;
+         assert(s);
+         for (;;) {
+                 _cleanup_free_ char *t = NULL;
+                 char label[DNS_LABEL_MAX];
+                 int k;
+                 r = dns_label_unescape(&p, label, sizeof(label));
+                 if (r < 0)
+                         return r;
+                 if (r == 0) {
+                         if (*p != 0)
+                                 return -EINVAL;
+                         break;
+                 }
+                 k = dns_label_undo_idna(label, r, label, sizeof(label));
+                 if (k < 0)
+                         return k;
+                 if (k > 0)
+                         r = k;
+                 r = dns_label_escape(label, r, &t);
+                 if (r < 0)
+                         return r;
+                 if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1))
+                         return -ENOMEM;
+                 if (!first)
+                         ret[n++] = '.';
+                 else
+                         first = false;
+                 memcpy(ret + n, t, r);
+                 n += r;
+         }
+         if (n > DNS_NAME_MAX)
+                 return -EINVAL;
+         if (!GREEDY_REALLOC(ret, allocated, n + 1))
+                 return -ENOMEM;
+         ret[n] = 0;
+         if (_ret) {
+                 *_ret = ret;
+                 ret = NULL;
+         }
+         return 0;
+ }
++#if 0 /* NM_IGNORED */
+ unsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_SIZE]) {
+         const char *p = s;
+         unsigned long ul = hash_key[0];
+         int r;
+         assert(p);
+         while (*p) {
+                 char label[DNS_LABEL_MAX+1];
+                 int k;
+                 r = dns_label_unescape(&p, label, sizeof(label));
+                 if (r < 0)
+                         break;
+                 k = dns_label_undo_idna(label, r, label, sizeof(label));
+                 if (k < 0)
+                         break;
+                 if (k > 0)
+                         r = k;
+                 label[r] = 0;
+                 ascii_strlower(label);
+                 ul = ul * hash_key[1] + ul + string_hash_func(label, hash_key);
+         }
+         return ul;
+ }
+ int dns_name_compare_func(const void *a, const void *b) {
+         const char *x = a, *y = b;
+         int r, q, k, w;
+         assert(a);
+         assert(b);
+         for (;;) {
+                 char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1];
+                 if (*x == 0 && *y == 0)
+                         return 0;
+                 r = dns_label_unescape(&x, la, sizeof(la));
+                 q = dns_label_unescape(&y, lb, sizeof(lb));
+                 if (r < 0 || q < 0)
+                         return r - q;
+                 k = dns_label_undo_idna(la, r, la, sizeof(la));
+                 w = dns_label_undo_idna(lb, q, lb, sizeof(lb));
+                 if (k < 0 || w < 0)
+                         return k - w;
+                 if (k > 0)
+                         r = k;
+                 if (w > 0)
+                         r = w;
+                 la[r] = lb[q] = 0;
+                 r = strcasecmp(la, lb);
+                 if (r != 0)
+                         return r;
+         }
+ }
+ const struct hash_ops dns_name_hash_ops = {
+         .hash = dns_name_hash_func,
+         .compare = dns_name_compare_func
+ };
+ int dns_name_equal(const char *x, const char *y) {
+         int r, q, k, w;
+         assert(x);
+         assert(y);
+         for (;;) {
+                 char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1];
+                 if (*x == 0 && *y == 0)
+                         return true;
+                 r = dns_label_unescape(&x, la, sizeof(la));
+                 if (r < 0)
+                         return r;
+                 k = dns_label_undo_idna(la, r, la, sizeof(la));
+                 if (k < 0)
+                         return k;
+                 if (k > 0)
+                         r = k;
+                 q = dns_label_unescape(&y, lb, sizeof(lb));
+                 if (q < 0)
+                         return q;
+                 w = dns_label_undo_idna(lb, q, lb, sizeof(lb));
+                 if (w < 0)
+                         return w;
+                 if (w > 0)
+                         q = w;
+                 la[r] = lb[q] = 0;
+                 if (strcasecmp(la, lb))
+                         return false;
+         }
+ }
+ int dns_name_endswith(const char *name, const char *suffix) {
+         const char *n, *s, *saved_n = NULL;
+         int r, q, k, w;
+         assert(name);
+         assert(suffix);
+         n = name;
+         s = suffix;
+         for (;;) {
+                 char ln[DNS_LABEL_MAX+1], ls[DNS_LABEL_MAX+1];
+                 r = dns_label_unescape(&n, ln, sizeof(ln));
+                 if (r < 0)
+                         return r;
+                 k = dns_label_undo_idna(ln, r, ln, sizeof(ln));
+                 if (k < 0)
+                         return k;
+                 if (k > 0)
+                         r = k;
+                 if (!saved_n)
+                         saved_n = n;
+                 q = dns_label_unescape(&s, ls, sizeof(ls));
+                 if (q < 0)
+                         return q;
+                 w = dns_label_undo_idna(ls, q, ls, sizeof(ls));
+                 if (w < 0)
+                         return w;
+                 if (w > 0)
+                         q = w;
+                 if (r == 0 && q == 0)
+                         return true;
+                 if (r == 0 && saved_n == n)
+                         return false;
+                 ln[r] = ls[q] = 0;
+                 if (r != q || strcasecmp(ln, ls)) {
+                         /* Not the same, let's jump back, and try with the next label again */
+                         s = suffix;
+                         n = saved_n;
+                         saved_n = NULL;
+                 }
+         }
+ }
+ int dns_name_reverse(int family, const union in_addr_union *a, char **ret) {
+         const uint8_t *p;
+         int r;
+         assert(a);
+         assert(ret);
+         p = (const uint8_t*) a;
+         if (family == AF_INET)
+                 r = asprintf(ret, "%u.%u.%u.%u.in-addr.arpa", p[3], p[2], p[1], p[0]);
+         else if (family == AF_INET6)
+                 r = asprintf(ret, "%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.ip6.arpa",
+                              hexchar(p[15] & 0xF), hexchar(p[15] >> 4), hexchar(p[14] & 0xF), hexchar(p[14] >> 4),
+                              hexchar(p[13] & 0xF), hexchar(p[13] >> 4), hexchar(p[12] & 0xF), hexchar(p[12] >> 4),
+                              hexchar(p[11] & 0xF), hexchar(p[11] >> 4), hexchar(p[10] & 0xF), hexchar(p[10] >> 4),
+                              hexchar(p[ 9] & 0xF), hexchar(p[ 9] >> 4), hexchar(p[ 8] & 0xF), hexchar(p[ 8] >> 4),
+                              hexchar(p[ 7] & 0xF), hexchar(p[ 7] >> 4), hexchar(p[ 6] & 0xF), hexchar(p[ 6] >> 4),
+                              hexchar(p[ 5] & 0xF), hexchar(p[ 5] >> 4), hexchar(p[ 4] & 0xF), hexchar(p[ 4] >> 4),
+                              hexchar(p[ 3] & 0xF), hexchar(p[ 3] >> 4), hexchar(p[ 2] & 0xF), hexchar(p[ 2] >> 4),
+                              hexchar(p[ 1] & 0xF), hexchar(p[ 1] >> 4), hexchar(p[ 0] & 0xF), hexchar(p[ 0] >> 4));
+         else
+                 return -EAFNOSUPPORT;
+         if (r < 0)
+                 return -ENOMEM;
+         return 0;
+ }
+ int dns_name_address(const char *p, int *family, union in_addr_union *address) {
+         int r;
+         assert(p);
+         assert(family);
+         assert(address);
+         r = dns_name_endswith(p, "in-addr.arpa");
+         if (r < 0)
+                 return r;
+         if (r > 0) {
+                 uint8_t a[4];
+                 unsigned i;
+                 for (i = 0; i < ELEMENTSOF(a); i++) {
+                         char label[DNS_LABEL_MAX+1];
+                         r = dns_label_unescape(&p, label, sizeof(label));
+                         if (r < 0)
+                                 return r;
+                         if (r == 0)
+                                 return -EINVAL;
+                         if (r > 3)
+                                 return -EINVAL;
+                         r = safe_atou8(label, &a[i]);
+                         if (r < 0)
+                                 return r;
+                 }
+                 r = dns_name_equal(p, "in-addr.arpa");
+                 if (r <= 0)
+                         return r;
+                 *family = AF_INET;
+                 address->in.s_addr = htobe32(((uint32_t) a[3] << 24) |
+                                              ((uint32_t) a[2] << 16) |
+                                              ((uint32_t) a[1] << 8) |
+                                               (uint32_t) a[0]);
+                 return 1;
+         }
+         r = dns_name_endswith(p, "ip6.arpa");
+         if (r < 0)
+                 return r;
+         if (r > 0) {
+                 struct in6_addr a;
+                 unsigned i;
+                 for (i = 0; i < ELEMENTSOF(a.s6_addr); i++) {
+                         char label[DNS_LABEL_MAX+1];
+                         int x, y;
+                         r = dns_label_unescape(&p, label, sizeof(label));
+                         if (r <= 0)
+                                 return r;
+                         if (r != 1)
+                                 return -EINVAL;
+                         x = unhexchar(label[0]);
+                         if (x < 0)
+                                 return -EINVAL;
+                         r = dns_label_unescape(&p, label, sizeof(label));
+                         if (r <= 0)
+                                 return r;
+                         if (r != 1)
+                                 return -EINVAL;
+                         y = unhexchar(label[0]);
+                         if (y < 0)
+                                 return -EINVAL;
+                         a.s6_addr[ELEMENTSOF(a.s6_addr) - i - 1] = (uint8_t) y << 4 | (uint8_t) x;
+                 }
+                 r = dns_name_equal(p, "ip6.arpa");
+                 if (r <= 0)
+                         return r;
+                 *family = AF_INET6;
+                 address->in6 = a;
+                 return 1;
+         }
+         return 0;
+ }
+ int dns_name_root(const char *name) {
+         char label[DNS_LABEL_MAX+1];
+         int r;
+         assert(name);
+         r = dns_label_unescape(&name, label, sizeof(label));
+         if (r < 0)
+                 return r;
+         return r == 0 && *name == 0;
+ }
+ int dns_name_single_label(const char *name) {
+         char label[DNS_LABEL_MAX+1];
+         int r;
+         assert(name);
+         r = dns_label_unescape(&name, label, sizeof(label));
+         if (r < 0)
+                 return r;
+         if (r == 0)
+                 return 0;
+         r = dns_label_unescape(&name, label, sizeof(label));
+         if (r < 0)
+                 return r;
+         return r == 0 && *name == 0;
+ }
++#endif /* NM_IGNORED */
index 0000000,00caf5d..4e50b15
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,59 +1,65 @@@
+ /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+ /***
+   This file is part of systemd.
+   Copyright 2014 Lennart Poettering
+   systemd is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2.1 of the License, or
+   (at your option) any later version.
+   systemd is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   Lesser General Public License for more details.
+   You should have received a copy of the GNU Lesser General Public License
+   along with systemd; If not, see <http://www.gnu.org/licenses/>.
+  ***/
+ #pragma once
++#include "nm-sd-adapt.h"
++#if 0 /* NM_IGNORED */
+ #include "hashmap.h"
+ #include "in-addr-util.h"
++#endif /* NM_IGNORED */
+ #define DNS_LABEL_MAX 63
+ #define DNS_NAME_MAX 255
+ int dns_label_unescape(const char **name, char *dest, size_t sz);
+ int dns_label_escape(const char *p, size_t l, char **ret);
+ int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
+ int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
+ int dns_name_normalize(const char *s, char **_ret);
+ static inline int dns_name_is_valid(const char *s) {
+         int r;
+         r = dns_name_normalize(s, NULL);
+         if (r == -EINVAL)
+                 return 0;
+         if (r < 0)
+                 return r;
+         return 1;
+ }
++#if 0 /* NM_IGNORED */
+ unsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_SIZE]);
+ int dns_name_compare_func(const void *a, const void *b);
+ extern const struct hash_ops dns_name_hash_ops;
+ int dns_name_equal(const char *x, const char *y);
+ int dns_name_endswith(const char *name, const char *suffix);
+ int dns_name_reverse(int family, const union in_addr_union *a, char **ret);
+ int dns_name_address(const char *p, int *family, union in_addr_union *a);
+ int dns_name_root(const char *name);
+ int dns_name_single_label(const char *name);
++
++#endif /* NM_IGNORED */