summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/libbsm/Makefile4
-rw-r--r--lib/libc/net/getaddrinfo.346
-rw-r--r--lib/libc/net/getaddrinfo.c163
-rw-r--r--lib/libstand/Makefile2
-rw-r--r--lib/libstand/uuid_from_string.c132
-rw-r--r--lib/libstand/uuid_to_string.c111
6 files changed, 425 insertions, 33 deletions
diff --git a/lib/libbsm/Makefile b/lib/libbsm/Makefile
index 488cbe6..037def7 100644
--- a/lib/libbsm/Makefile
+++ b/lib/libbsm/Makefile
@@ -48,6 +48,7 @@ MAN= libbsm.3 \
au_free_token.3 \
au_io.3 \
au_mask.3 \
+ au_notify.3 \
au_open.3 \
au_socket_type.3 \
au_token.3 \
@@ -112,6 +113,9 @@ MLINKS= libbsm.3 bsm.3 \
au_mask.3 au_preselect.3 \
au_mask.3 getauditflagsbin.3 \
au_mask.3 getauditflagschar.3 \
+ au_notify.3 au_get_state.3 \
+ au_notify.3 au_notify_initialize.3 \
+ au_notify.3 au_notify_terminate.3 \
au_open.3 au_close.3 \
au_open.3 au_close_buffer.3 \
au_open.3 au_close_token.3 \
diff --git a/lib/libc/net/getaddrinfo.3 b/lib/libc/net/getaddrinfo.3
index 1d6cb56..69601e6 100644
--- a/lib/libc/net/getaddrinfo.3
+++ b/lib/libc/net/getaddrinfo.3
@@ -18,7 +18,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 5, 2015
+.Dd December 19, 2015
.Dt GETADDRINFO 3
.Os
.Sh NAME
@@ -130,11 +130,13 @@ field to which the
parameter points shall be set to zero
or be the bitwise-inclusive OR of one or more of the values
.Dv AI_ADDRCONFIG ,
+.Dv AI_ALL ,
.Dv AI_CANONNAME ,
.Dv AI_NUMERICHOST ,
-.Dv AI_NUMERICSERV
+.Dv AI_NUMERICSERV ,
+.Dv AI_PASSIVE
and
-.Dv AI_PASSIVE .
+.Dv AI_V4MAPPED .
For a UNIX-domain address,
.Fa ai_flags
is ignored.
@@ -146,6 +148,25 @@ bit is set, IPv4 addresses shall be returned only if
an IPv4 address is configured on the local system,
and IPv6 addresses shall be returned only if
an IPv6 address is configured on the local system.
+.It Dv AI_ALL
+If the
+.Dv AI_ALL
+flag is used with the
+.Dv AI_V4MAPPED
+flag, then
+.Fn getaddrinfo
+shall return all matching IPv6 and IPv4 addresses.
+.Pp
+For example, when using the DNS, queries are made for both AAAA records and A records, and
+.Fn getaddrinfo
+returns the combined results of both queries.
+Any IPv4 addresses found are returned as IPv4-mapped IPv6 addresses.
+.Pp
+The
+.Dv AI_ALL
+flag without the
+.Dv AI_V4MAPPED
+flag is ignored.
.It Dv AI_CANONNAME
If the
.Dv AI_CANONNAME
@@ -210,6 +231,25 @@ loopback address if
is the null pointer and
.Dv AI_PASSIVE
is not set.
+.It Dv AI_V4MAPPED
+If the
+.Dv AI_V4MAPPED
+flag is specified along with an ai_family of
+.Dv AF_INET6 ,
+then
+.Fn getaddrinfo
+shall return IPv4-mapped IPv6 addresses on finding no matching IPv6 addresses (
+.Fa ai_addrlen
+shall be 16).
+.Pp
+For example, when using the DNS, if no AAAA records are found then a query is made for A records and any found are returned as IPv4-mapped IPv6 addresses.
+.Pp
+The
+.Dv AI_V4MAPPED
+flag shall be ignored unless
+.Fa ai_family
+equals
+.Dv AF_INET6 .
.El
.El
.Pp
diff --git a/lib/libc/net/getaddrinfo.c b/lib/libc/net/getaddrinfo.c
index ab6b65f..ed1a388 100644
--- a/lib/libc/net/getaddrinfo.c
+++ b/lib/libc/net/getaddrinfo.c
@@ -93,6 +93,7 @@ __FBSDID("$FreeBSD$");
#include <stdarg.h>
#include <nsswitch.h>
#include "un-namespace.h"
+#include "netdb_private.h"
#include "libc_private.h"
#ifdef NS_CACHING
#include "nscache.h"
@@ -470,6 +471,24 @@ getaddrinfo(const char *hostname, const char *servname,
}
/*
+ * RFC 3493: AI_ALL and AI_V4MAPPED are effective only against
+ * AF_INET6 query. They need to be ignored if specified in other
+ * occassions.
+ */
+ switch (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) {
+ case AI_V4MAPPED:
+ case AI_ALL | AI_V4MAPPED:
+#ifdef INET6
+ if (pai->ai_family != AF_INET6)
+ pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED);
+ break;
+#endif
+ case AI_ALL:
+ pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED);
+ break;
+ }
+
+ /*
* check for special cases. (1) numeric servname is disallowed if
* socktype/protocol are left unspecified. (2) servname is disallowed
* for raw and other inet{,6} sockets.
@@ -778,10 +797,9 @@ match_addrselectpolicy(struct sockaddr *addr, struct policyhead *head)
memset(&key, 0, sizeof(key));
key.sin6_family = AF_INET6;
key.sin6_len = sizeof(key);
- key.sin6_addr.s6_addr[10] = 0xff;
- key.sin6_addr.s6_addr[11] = 0xff;
- memcpy(&key.sin6_addr.s6_addr[12],
- &((struct sockaddr_in *)addr)->sin_addr, 4);
+ _map_v4v6_address(
+ (char *)&((struct sockaddr_in *)addr)->sin_addr,
+ (char *)&key.sin6_addr);
break;
default:
return(NULL);
@@ -861,6 +879,16 @@ set_source(struct ai_order *aio, struct policyhead *ph)
if ((s = _socket(ai.ai_family, ai.ai_socktype | SOCK_CLOEXEC,
ai.ai_protocol)) < 0)
return; /* give up */
+#ifdef INET6
+ if (ai.ai_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai.ai_addr;
+ int off = 0;
+
+ if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
+ (void)_setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
+ (char *)&off, sizeof(off));
+ }
+#endif
if (_connect(s, ai.ai_addr, ai.ai_addrlen) < 0)
goto cleanup;
srclen = ai.ai_addrlen;
@@ -1199,7 +1227,7 @@ explore_numeric(const struct addrinfo *pai, const char *hostname,
const char *servname, struct addrinfo **res, const char *canonname)
{
const struct afd *afd;
- struct addrinfo *ai;
+ struct addrinfo *ai, ai0;
int error;
char pton[PTON_MAX], path[PATH_MAX], *p;
@@ -1236,8 +1264,17 @@ explore_numeric(const struct addrinfo *pai, const char *hostname,
p = pton;
break;
default:
- if (inet_pton(afd->a_af, hostname, pton) != 1)
- return 0;
+ if (inet_pton(afd->a_af, hostname, pton) != 1) {
+ if (pai->ai_family != AF_INET6 ||
+ (pai->ai_flags & AI_V4MAPPED) != AI_V4MAPPED)
+ return 0;
+ if (inet_aton(hostname, (struct in_addr *)pton) != 1)
+ return 0;
+ afd = &afdl[N_INET];
+ ai0 = *pai;
+ ai0.ai_family = AF_INET;
+ pai = &ai0;
+ }
p = pton;
break;
}
@@ -1354,6 +1391,15 @@ get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
{
char *p;
struct addrinfo *ai;
+#ifdef INET6
+ struct in6_addr mapaddr;
+
+ if (afd->a_af == AF_INET && (pai->ai_flags & AI_V4MAPPED) != 0) {
+ afd = &afdl[N_INET6];
+ _map_v4v6_address(addr, (char *)&mapaddr);
+ addr = (char *)&mapaddr;
+ }
+#endif
ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
+ (afd->a_socklen));
@@ -2192,7 +2238,7 @@ addr4sort(struct addrinfo *sentinel, res_state res)
static int
_dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
{
- struct addrinfo *ai;
+ struct addrinfo *ai, ai0;
querybuf *buf, *buf2;
const char *hostname;
const struct addrinfo *pai;
@@ -2222,6 +2268,13 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
return NS_NOTFOUND;
}
+ if (pai->ai_family == AF_INET6 &&
+ (pai->ai_flags & AI_V4MAPPED) == AI_V4MAPPED) {
+ ai0 = *pai;
+ ai0.ai_family = AF_UNSPEC;
+ pai = &ai0;
+ }
+
switch (pai->ai_family) {
case AF_UNSPEC:
q.name = hostname;
@@ -2277,9 +2330,12 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
cur = cur->ai_next;
}
}
- ai = getanswer(buf, q.n, q.name, q.qtype, pai, res);
- if (ai)
- cur->ai_next = ai;
+ if (!ai || pai->ai_family != AF_UNSPEC ||
+ (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) != AI_V4MAPPED) {
+ ai = getanswer(buf, q.n, q.name, q.qtype, pai, res);
+ if (ai)
+ cur->ai_next = ai;
+ }
free(buf);
free(buf2);
if (sentinel.ai_next == NULL)
@@ -2361,6 +2417,9 @@ found:
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = 0;
hints.ai_flags = AI_NUMERICHOST;
+ if (pai->ai_family == AF_INET6 &&
+ (pai->ai_flags & AI_V4MAPPED) == AI_V4MAPPED)
+ hints.ai_flags |= AI_V4MAPPED;
error = getaddrinfo(addr, "0", &hints, &res0);
if (error)
goto again;
@@ -2388,6 +2447,20 @@ found:
return res0;
}
+static struct addrinfo *
+_getht(FILE **hostf, const char *name, const struct addrinfo *pai,
+ struct addrinfo *cur)
+{
+ struct addrinfo *p;
+
+ while ((p = _gethtent(hostf, name, pai)) != NULL) {
+ cur->ai_next = p;
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ }
+ return (cur);
+}
+
/*ARGSUSED*/
static int
_files_getaddrinfo(void *rv, void *cb_data, va_list ap)
@@ -2395,7 +2468,6 @@ _files_getaddrinfo(void *rv, void *cb_data, va_list ap)
const char *name;
const struct addrinfo *pai;
struct addrinfo sentinel, *cur;
- struct addrinfo *p;
FILE *hostf = NULL;
name = va_arg(ap, char *);
@@ -2405,11 +2477,19 @@ _files_getaddrinfo(void *rv, void *cb_data, va_list ap)
cur = &sentinel;
_sethtent(&hostf);
- while ((p = _gethtent(&hostf, name, pai)) != NULL) {
- cur->ai_next = p;
- while (cur && cur->ai_next)
- cur = cur->ai_next;
- }
+ if (pai->ai_family == AF_INET6 &&
+ (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) == AI_V4MAPPED) {
+ struct addrinfo ai0 = *pai;
+
+ ai0.ai_flags &= ~AI_V4MAPPED;
+ cur = _getht(&hostf, name, &ai0, cur);
+ if (sentinel.ai_next == NULL) {
+ _sethtent(&hostf);
+ ai0.ai_flags |= AI_V4MAPPED;
+ cur = _getht(&hostf, name, &ai0, cur);
+ }
+ } else
+ cur = _getht(&hostf, name, pai, cur);
_endhtent(&hostf);
*((struct addrinfo **)rv) = sentinel.ai_next;
@@ -2469,6 +2549,9 @@ nextline:
hints = *pai;
hints.ai_flags = AI_NUMERICHOST;
+ if (pai->ai_family == AF_INET6 &&
+ (pai->ai_flags & AI_V4MAPPED) == AI_V4MAPPED)
+ hints.ai_flags |= AI_V4MAPPED;
error = getaddrinfo(addr, NULL, &hints, &res0);
if (error == 0) {
for (res = res0; res; res = res->ai_next) {
@@ -2516,15 +2599,46 @@ _yp_getaddrinfo(void *rv, void *cb_data, va_list ap)
memset(&sentinel, 0, sizeof(sentinel));
cur = &sentinel;
+ /* ipnodes.byname can hold both IPv4/v6 */
+ r = yp_match(ypdomain, "ipnodes.byname", name,
+ (int)strlen(name), &ypbuf, &ypbuflen);
+ if (r == 0) {
+ ai = _yphostent(ypbuf, pai);
+ if (ai) {
+ cur->ai_next = ai;
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ }
+ free(ypbuf);
+ }
+
+ if (ai != NULL) {
+ struct sockaddr_in6 *sin6;
+
+ switch (ai->ai_family) {
+ case AF_INET:
+ goto done;
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)ai->ai_addr;
+ if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
+ goto done;
+ break;
+ }
+ }
+
/* hosts.byname is only for IPv4 (Solaris8) */
- if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) {
+ if (pai->ai_family == AF_UNSPEC || pai->ai_family == AF_INET ||
+ ((pai->ai_family == AF_INET6 &&
+ (pai->ai_flags & AI_V4MAPPED) == AI_V4MAPPED) &&
+ (ai == NULL || (pai->ai_flags & AI_ALL) == AI_ALL))) {
r = yp_match(ypdomain, "hosts.byname", name,
(int)strlen(name), &ypbuf, &ypbuflen);
if (r == 0) {
struct addrinfo ai4;
ai4 = *pai;
- ai4.ai_family = AF_INET;
+ if (pai->ai_family == AF_UNSPEC)
+ ai4.ai_family = AF_INET;
ai = _yphostent(ypbuf, &ai4);
if (ai) {
cur->ai_next = ai;
@@ -2535,16 +2649,7 @@ _yp_getaddrinfo(void *rv, void *cb_data, va_list ap)
}
}
- /* ipnodes.byname can hold both IPv4/v6 */
- r = yp_match(ypdomain, "ipnodes.byname", name,
- (int)strlen(name), &ypbuf, &ypbuflen);
- if (r == 0) {
- ai = _yphostent(ypbuf, pai);
- if (ai)
- cur->ai_next = ai;
- free(ypbuf);
- }
-
+done:
if (sentinel.ai_next == NULL) {
RES_SET_H_ERRNO(__res_state(), HOST_NOT_FOUND);
return NS_NOTFOUND;
diff --git a/lib/libstand/Makefile b/lib/libstand/Makefile
index 44d5834..a69a935 100644
--- a/lib/libstand/Makefile
+++ b/lib/libstand/Makefile
@@ -69,7 +69,7 @@ SRCS+= syncicache.c
# uuid functions from libc
.PATH: ${LIBC_SRC}/uuid
-SRCS+= uuid_equal.c uuid_is_nil.c
+SRCS+= uuid_create_nil.c uuid_equal.c uuid_from_string.c uuid_is_nil.c uuid_to_string.c
# _setjmp/_longjmp
.PATH: ${LIBSTAND_SRC}/${MACHINE_CPUARCH}
diff --git a/lib/libstand/uuid_from_string.c b/lib/libstand/uuid_from_string.c
new file mode 100644
index 0000000..2d5a6dd
--- /dev/null
+++ b/lib/libstand/uuid_from_string.c
@@ -0,0 +1,132 @@
+/*-
+ * Copyright (c) 2015 M. Warner Losh
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Note: some comments taken from lib/libc/uuid/uuid_from_string.c
+ * Copyright (c) 2002 Marcel Moolenaar
+ * Copyright (c) 2002 Hiten Mahesh Pandya
+ */
+
+
+#include <stand.h>
+#include <uuid.h>
+
+static int
+hex2int(int ch)
+{
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ if (ch >= 'a' && ch <= 'f')
+ return 10 + ch - 'a';
+ if (ch >= 'A' && ch <= 'F')
+ return 10 + ch - 'A';
+ return 16;
+}
+
+static uint32_t
+fromhex(const char *s, int len, int *ok)
+{
+ uint32_t v;
+ int i, h;
+
+ if (!*ok)
+ return 0;
+ v = 0;
+ for (i = 0; i < 8; i++) {
+ h = hex2int(s[i]);
+ if (h == 16) {
+ *ok = 0;
+ return v;
+ }
+ v = (v << 4) | h;
+ }
+ return v;
+}
+
+/*
+ * uuid_from_string() - convert a string representation of an UUID into
+ * a binary representation.
+ * See also:
+ * http://www.opengroup.org/onlinepubs/009629399/uuid_from_string.htm
+ *
+ * NOTE: The sequence field is in big-endian, while the time fields are in
+ * native byte order.
+ *
+ * 01234567-89ab-cdef-0123-456789abcdef
+ * 000000000011111111112222222222333333
+ * 012345678901234567890123456789012345
+ * - - - -
+ * hhhhhhhh-hhhh-hhhh-bbbb-bbbbbbbbbbbb
+ *
+ */
+void
+uuid_from_string(const char *s, uuid_t *u, uint32_t *status)
+{
+ int ok = 1;
+ int n;
+
+ if (s == NULL || *s == '\0') {
+ uuid_create_nil(u, status);
+ return;
+ }
+
+ if (status != NULL)
+ *status = uuid_s_invalid_string_uuid;
+ if (strlen(s) != 36)
+ return;
+ /* Only support new format, check for all the right dashes */
+ if (s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-')
+ return;
+ /* native byte order */
+ u->time_low = fromhex(s , 8, &ok);
+ u->time_mid = fromhex(s + 9, 4, &ok);
+ u->time_hi_and_version = fromhex(s + 14, 4, &ok);
+ /* Big endian, but presented as a whole number so decode as such */
+ u->clock_seq_hi_and_reserved = fromhex(s + 19, 2, &ok);
+ u->clock_seq_low = fromhex(s + 21, 2, &ok);
+ u->node[0] = fromhex(s + 24, 2, &ok);
+ u->node[1] = fromhex(s + 26, 2, &ok);
+ u->node[2] = fromhex(s + 28, 2, &ok);
+ u->node[3] = fromhex(s + 30, 2, &ok);
+ u->node[4] = fromhex(s + 32, 2, &ok);
+ u->node[5] = fromhex(s + 34, 2, &ok);
+ if (!ok)
+ return;
+
+ /* We have a successful scan. Check semantics... */
+ n = u->clock_seq_hi_and_reserved;
+ if ((n & 0x80) != 0x00 && /* variant 0? */
+ (n & 0xc0) != 0x80 && /* variant 1? */
+ (n & 0xe0) != 0xc0) { /* variant 2? */
+ if (status != NULL)
+ *status = uuid_s_bad_version;
+ } else {
+ if (status != NULL)
+ *status = uuid_s_ok;
+ }
+}
diff --git a/lib/libstand/uuid_to_string.c b/lib/libstand/uuid_to_string.c
new file mode 100644
index 0000000..efe921c
--- /dev/null
+++ b/lib/libstand/uuid_to_string.c
@@ -0,0 +1,111 @@
+/*-
+ * Copyright (c) 2015 M. Warner Losh
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+
+/*
+ * Note: some comments taken from lib/libc/uuid/uuid_to_string.c
+ * Copyright (c) 2002,2005 Marcel Moolenaar
+ * Copyright (c) 2002 Hiten Mahesh Pandya
+ */
+
+#include <stand.h>
+#include <uuid.h>
+
+/*
+ * Dump len characters into *buf from val as hex and update *buf
+ */
+static void
+tohex(char **buf, int len, uint32_t val)
+{
+ static const char *hexstr = "0123456789abcdef";
+ char *walker = *buf;
+ int i;
+
+ for (i = len - 1; i >= 0; i++) {
+ walker[i] = hexstr[val & 0xf];
+ val >>= 4;
+ }
+ *buf = walker + len;
+}
+
+/*
+ * uuid_to_string() - Convert a binary UUID into a string representation.
+ * See also:
+ * http://www.opengroup.org/onlinepubs/009629399/uuid_to_string.htm
+ *
+ * NOTE: The references given above do not have a status code for when
+ * the string could not be allocated. The status code has been
+ * taken from the Hewlett-Packard implementation.
+ *
+ * NOTE: we don't support u == NULL for a nil UUID, sorry.
+ *
+ * NOTE: The sequence field is in big-endian, while the time fields are in
+ * native byte order.
+ *
+ * hhhhhhhh-hhhh-hhhh-bbbb-bbbbbbbbbbbb
+ * 01234567-89ab-cdef-0123-456789abcdef
+ */
+void
+uuid_to_string(const uuid_t *u, char **s, uint32_t *status)
+{
+ uuid_t nil;
+ char *w;
+
+ if (status != NULL)
+ *status = uuid_s_ok;
+ if (s == NULL) /* Regular version does this odd-ball behavior too */
+ return;
+ w = *s = malloc(37);
+ if (*s == NULL) {
+ if (status != NULL)
+ *status = uuid_s_no_memory;
+ return;
+ }
+ if (u == NULL) {
+ u = &nil;
+ uuid_create_nil(&nil, NULL);
+ }
+ /* native */
+ tohex(&w, 8, u->time_low);
+ *w++ = '-';
+ tohex(&w, 4, u->time_mid);
+ *w++ = '-';
+ tohex(&w, 4, u->time_hi_and_version);
+ *w++ = '-';
+ /* Big endian, so do a byte at a time */
+ tohex(&w, 2, u->clock_seq_hi_and_reserved);
+ tohex(&w, 2, u->clock_seq_low);
+ *w++ = '-';
+ tohex(&w, 2, u->node[0]);
+ tohex(&w, 2, u->node[1]);
+ tohex(&w, 2, u->node[2]);
+ tohex(&w, 2, u->node[3]);
+ tohex(&w, 2, u->node[4]);
+ tohex(&w, 2, u->node[5]);
+ *w++ - '\0';
+}
OpenPOWER on IntegriCloud