#include "DHCPDUID.h"
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <CoreFoundation/CFString.h>
#include "util.h"
#include "cfutil.h"
STATIC CFStringRef
DHCPDUIDCopyDescription(const DHCPDUIDRef duid, int duid_len)
{
int required_len;
CFMutableStringRef str;
DHCPDUIDType type;
str = CFStringCreateMutable(NULL, 0);
required_len = offsetof(DHCPDUID_LLT, hardware_type);
if (duid_len < required_len) {
goto too_short;
}
type = DHCPDUIDGetType(duid);
switch (type) {
case kDHCPDUIDTypeLLT:
required_len = offsetof(DHCPDUID_LLT, linklayer_address);
if (duid_len < required_len) {
goto too_short;
}
CFStringAppendFormat(str,
NULL,
CFSTR("DUID LLT HW %d Time %u Addr "),
DHCPDUID_LLTGetHardwareType(&duid->llt),
DHCPDUID_LLTGetTime(&duid->llt));
my_CFStringAppendBytesAsHex(str, duid->llt.linklayer_address,
duid_len - required_len, ':');
break;
case kDHCPDUIDTypeEN:
required_len = offsetof(DHCPDUID_EN, identifier);
if (duid_len < required_len) {
goto too_short;
}
CFStringAppendFormat(str, NULL, CFSTR("DUID EN Num %d Id "),
DHCPDUID_ENGetEnterpriseNumber(&duid->en));
my_CFStringAppendBytesAsHex(str, duid->en.identifier,
duid_len - required_len, ':');
break;
case kDHCPDUIDTypeLL:
required_len = offsetof(DHCPDUID_LL, linklayer_address);
if (duid_len < required_len) {
goto too_short;
}
CFStringAppendFormat(str, NULL,
CFSTR("DUID LL HW %d Addr "),
DHCPDUID_LLGetHardwareType(&duid->ll));
my_CFStringAppendBytesAsHex(str, duid->ll.linklayer_address,
duid_len - required_len, ':');
break;
default:
CFStringAppendFormat(str, NULL, CFSTR("DUID (unrecognized type=%d): "),
type);
my_CFStringAppendBytesAsHex(str, (const uint8_t *)duid, duid_len, ' ');
break;
}
return (str);
too_short:
CFStringAppendFormat(str, NULL,
CFSTR("DUID too short (%d < %d), Data = { "),
duid_len, required_len);
my_CFStringAppendBytesAsHex(str, (const uint8_t *)duid, duid_len, ' ');
CFStringAppendCString(str, " }", kCFStringEncodingASCII);
return (str);
}
char *
DHCPDUIDToString(const DHCPDUIDRef duid, int duid_len)
{
char * cstr;
CFStringRef str;
str = DHCPDUIDCopyDescription(duid, duid_len);
if (str == NULL) {
return (NULL);
}
cstr = my_CFStringToCString(str, kCFStringEncodingASCII);
CFRelease(str);
return (cstr);
}
void
DHCPDUIDFPrint(FILE * file, const DHCPDUIDRef duid, int duid_len)
{
char * descr;
descr = DHCPDUIDToString(duid, duid_len);
if (descr != NULL) {
fprintf(file, "%s", descr);
free(descr);
}
return;
}
bool
DHCPDUIDIsValid(const DHCPDUIDRef duid, int duid_len)
{
int required_len;
DHCPDUIDType type;
required_len = offsetof(DHCPDUID_LLT, hardware_type);
if (duid_len < required_len) {
return (FALSE);
}
type = DHCPDUIDGetType(duid);
switch (type) {
case kDHCPDUIDTypeLLT:
required_len = offsetof(DHCPDUID_LLT, linklayer_address);
if (duid_len <= required_len) {
return (FALSE);
}
break;
case kDHCPDUIDTypeEN:
required_len = offsetof(DHCPDUID_EN, identifier);
if (duid_len <= required_len) {
return (FALSE);
}
break;
case kDHCPDUIDTypeLL:
required_len = offsetof(DHCPDUID_LL, linklayer_address);
if (duid_len <= required_len) {
return (FALSE);
}
break;
default:
break;
}
return (TRUE);
}