#ifndef _S_BSDP_H
#define _S_BSDP_H
#include <mach/boolean.h>
#include <string.h>
#include <sys/types.h>
#include "dhcp.h"
#include "dhcp_options.h"
#define BOOT_IMAGE_ID_NULL ((bsdp_image_id_t)0)
#define BSDP_IMAGE_INDEX_MAX 0xffff
#define BSDP_IMAGE_ATTRIBUTES_INSTALL ((u_int16_t)0x8000)
#define BSDP_IMAGE_ATTRIBUTES_KIND_MASK ((u_int16_t)0x7f00)
#define BSDP_IMAGE_ATTRIBUTES_KIND_MAX 0x7f
#define BSDP_PRIORITY_MIN ((bsdp_priority_t) 0)
#define BSDP_PRIORITY_MAX ((bsdp_priority_t) 65535)
#define BSDP_PRIORITY_BASE ((bsdp_priority_t) 32768)
#define BSDP_VENDOR_CLASS_ID "AAPLBSDPC"
#define BSDP_VERSION_1_0 ((unsigned short)0x0100)
#define BSDP_VERSION_1_1 ((unsigned short)0x0101)
#define BSDP_VERSION_0_0 ((unsigned short)0x0)
typedef enum {
bsdp_image_kind_MacOS9 = 0,
bsdp_image_kind_MacOSX = 1,
bsdp_image_kind_MacOSXServer = 2,
bsdp_image_kind_Diagnostics = 3,
} bsdp_image_kind_t;
#define BSDP_IMAGE_NAME_MAX (DHCP_OPTION_SIZE_MAX - 2 * OPTION_OFFSET - 5)
typedef struct {
u_int8_t boot_image_id[4];
u_int8_t name_length;
u_int8_t name[0];
} bsdp_image_description_t;
typedef u_int16_t bsdp_priority_t;
typedef u_int16_t bsdp_version_t;
typedef u_int32_t bsdp_image_id_t;
static __inline__ u_int16_t
bsdp_image_index(bsdp_image_id_t image_id)
{
return (image_id & 0xffff);
}
static __inline__ u_int16_t
bsdp_image_attributes(bsdp_image_id_t image_id)
{
return (image_id >> 16);
}
static __inline__ bsdp_image_id_t
bsdp_image_id_make(u_int16_t index, u_int16_t attributes)
{
return (index | ((bsdp_image_id_t)attributes << 16));
}
static __inline__ boolean_t
bsdp_image_index_is_server_local(u_int16_t index)
{
return (index < 4096);
}
static __inline__ boolean_t
bsdp_image_identifier_is_server_local(u_int32_t identifier)
{
return (bsdp_image_index_is_server_local(bsdp_image_index(identifier)));
}
static __inline__ boolean_t
bsdp_image_identifier_is_install(u_int32_t identifier)
{
if ((bsdp_image_attributes(identifier) & BSDP_IMAGE_ATTRIBUTES_INSTALL)
!= 0) {
return (TRUE);
}
return (FALSE);
}
static __inline__ bsdp_image_kind_t
bsdp_image_kind_from_attributes(u_int16_t attr)
{
return ((attr & BSDP_IMAGE_ATTRIBUTES_KIND_MASK) >> 8);
}
static __inline__ u_int16_t
bsdp_image_attributes_from_kind(bsdp_image_kind_t kind)
{
return ((kind << 8) & BSDP_IMAGE_ATTRIBUTES_KIND_MASK);
}
typedef enum {
bsdptag_message_type_e = 1,
bsdptag_version_e = 2,
bsdptag_server_identifier_e = 3,
bsdptag_server_priority_e = 4,
bsdptag_reply_port_e = 5,
bsdptag_boot_image_list_path_e = 6,
bsdptag_default_boot_image_e = 7,
bsdptag_selected_boot_image_e = 8,
bsdptag_boot_image_list_e = 9,
bsdptag_netboot_1_0_firmware_e = 10,
bsdptag_image_attributes_filter_list_e = 11,
bsdptag_max_message_size_e = 12,
bsdptag_first_e = 1,
bsdptag_last_e = 12,
bsdptag_shadow_mount_path_e = 128,
bsdptag_shadow_file_path_e = 129,
bsdptag_machine_name_e = 130,
} bsdptag_t;
static __inline__ dhcptype_t
bsdptag_type(bsdptag_t tag)
{
dhcptype_t type = dhcptype_none_e;
switch (tag) {
case bsdptag_message_type_e:
type = dhcptype_uint8_e;
break;
case bsdptag_server_identifier_e:
type = dhcptype_ip_e;
break;
case bsdptag_version_e:
case bsdptag_server_priority_e:
case bsdptag_reply_port_e:
type = dhcptype_uint16_e;
break;
case bsdptag_machine_name_e:
case bsdptag_boot_image_list_path_e:
case bsdptag_shadow_file_path_e:
case bsdptag_shadow_mount_path_e:
type = dhcptype_string_e;
break;
case bsdptag_default_boot_image_e:
case bsdptag_selected_boot_image_e:
type = dhcptype_uint32_e;
break;
case bsdptag_boot_image_list_e:
type = dhcptype_opaque_e;
break;
case bsdptag_netboot_1_0_firmware_e:
type = dhcptype_none_e;
break;
case bsdptag_image_attributes_filter_list_e:
type = dhcptype_uint16_mult_e;
break;
case bsdptag_max_message_size_e:
type = dhcptype_uint16_e;
break;
default:
break;
}
return (type);
}
static __inline__ const char *
bsdptag_name(bsdptag_t tag)
{
static const char * names[] = {
NULL,
"message type",
"version",
"server identifier",
"server priority",
"reply port",
"boot image list path",
"default boot image",
"selected boot image",
"boot image list",
"netboot 1.0 firmware",
"image attributes filter list",
"maximum message size",
};
if (tag >= bsdptag_first_e && tag <= bsdptag_last_e) {
return (names[tag]);
}
switch (tag) {
case bsdptag_shadow_mount_path_e:
return "shadow mount path";
case bsdptag_shadow_file_path_e:
return "shadow file path";
case bsdptag_machine_name_e:
return "machine name";
default:
break;
}
return ("<unknown>");
}
typedef enum {
bsdp_msgtype_none_e = 0,
bsdp_msgtype_list_e = 1,
bsdp_msgtype_select_e = 2,
bsdp_msgtype_failed_e = 3,
} bsdp_msgtype_t;
static __inline__ const char *
bsdp_msgtype_names(bsdp_msgtype_t type)
{
static const char * names[] = {
"<none>",
"LIST",
"SELECT",
"FAILED",
};
if (type >= bsdp_msgtype_none_e && type <= bsdp_msgtype_failed_e)
return (names[type]);
return ("<unknown>");
}
static __inline__ boolean_t
bsdp_parse_class_id(void * buf, int buf_len, char * arch,
char * sysid)
{
int len;
u_char * scan;
*arch = '\0';
*sysid = '\0';
len = strlen(BSDP_VENDOR_CLASS_ID);
if (buf_len < len || memcmp(buf, BSDP_VENDOR_CLASS_ID, len))
return (FALSE);
buf_len -= len;
scan = (u_char *)buf + len;
if (buf_len == 0)
return (TRUE);
if (*scan != '/')
return (FALSE);
for (scan++, buf_len--; buf_len && *scan != '/'; scan++, buf_len--) {
switch (*scan) {
case '\n':
case '\0':
return (FALSE);
default:
break;
}
*arch++ = *scan;
}
*arch = '\0';
if (*scan != '/') {
return (FALSE);
}
for (scan++, buf_len--; buf_len; scan++, buf_len--) {
switch (*scan) {
case '\n':
case '\0':
return (FALSE);
default:
break;
}
*sysid++ = *scan;
}
*sysid = '\0';
return (TRUE);
}
#endif