dhcp: add generic DUID infrastructure

Add infrastructure for generating DUID-LLT from a given device MAC and
passing it around to the DHCP client implementations.

Thanks to Mathieu Trudel-Lapierre for bug fixes in the
unescaping code, which were merged into this commit.
This commit is contained in:
Dan Williams
2012-06-15 16:26:53 -05:00
parent c4e519bd78
commit dc518cf86b
7 changed files with 240 additions and 11 deletions

View File

@@ -22,6 +22,7 @@
#include <glib.h>
#include <glib/gi18n.h>
#include <string.h>
#include <ctype.h>
#include "nm-dhcp-dhclient-utils.h"
@@ -255,3 +256,75 @@ nm_dhcp_dhclient_create_config (const char *interface,
return g_string_free (new_contents, FALSE);
}
/* Roughly follow what dhclient's quotify_buf() and pretty_escape() functions do */
char *
nm_dhcp_dhclient_escape_duid (const GByteArray *duid)
{
char *escaped;
const guint8 *s = duid->data;
char *d;
d = escaped = g_malloc0 ((duid->len * 4) + 1);
while (s < (duid->data + duid->len)) {
if (!g_ascii_isprint (*s)) {
*d++ = '\\';
*d++ = '0' + ((*s >> 6) & 0x7);
*d++ = '0' + ((*s >> 3) & 0x7);
*d++ = '0' + (*s++ & 0x7);
} else if (*s == '"' || *s == '\'' || *s == '$' ||
*s == '`' || *s == '\\' || *s == '|' ||
*s == '&') {
*d++ = '\\';
*d++ = *s++;
} else
*d++ = *s++;
}
return escaped;
}
static inline gboolean
isoctal (const guint8 *p)
{
return ( p[0] >= '0' && p[0] <= '3'
&& p[1] >= '0' && p[1] <= '7'
&& p[2] >= '0' && p[2] <= '7');
}
GByteArray *
nm_dhcp_dhclient_unescape_duid (const char *duid)
{
GByteArray *unescaped;
const guint8 *p = (const guint8 *) duid;
guint i, len;
guint8 octal;
len = strlen (duid);
unescaped = g_byte_array_sized_new (len);
for (i = 0; i < len; i++) {
if (p[i] == '\\') {
i++;
if (isdigit (p[i])) {
/* Octal escape sequence */
if (i + 2 >= len || !isoctal (p + i))
goto error;
octal = ((p[i] - '0') << 6) + ((p[i + 1] - '0') << 3) + (p[i + 2] - '0');
g_byte_array_append (unescaped, &octal, 1);
i += 2;
} else {
/* One of ", ', $, `, \, |, or & */
g_warn_if_fail (p[i] == '"' || p[i] == '\'' || p[i] == '$' ||
p[i] == '`' || p[i] == '\\' || p[i] == '|' ||
p[i] == '&');
g_byte_array_append (unescaped, &p[i], 1);
}
} else
g_byte_array_append (unescaped, &p[i], 1);
}
return unescaped;
error:
g_byte_array_free (unescaped, TRUE);
return NULL;
}