53 #define EPROTO_UNSPECFAIL __einfo_error ( EINFO_EPROTO_UNSPECFAIL ) 54 #define EINFO_EPROTO_UNSPECFAIL \ 55 __einfo_uniqify ( EINFO_EPROTO, 1, "Unspecified server failure" ) 56 #define EPROTO_NOADDRSAVAIL __einfo_error ( EINFO_EPROTO_NOADDRSAVAIL ) 57 #define EINFO_EPROTO_NOADDRSAVAIL \ 58 __einfo_uniqify ( EINFO_EPROTO, 2, "No addresses available" ) 59 #define EPROTO_NOBINDING __einfo_error ( EINFO_EPROTO_NOBINDING ) 60 #define EINFO_EPROTO_NOBINDING \ 61 __einfo_uniqify ( EINFO_EPROTO, 3, "Client record unavailable" ) 62 #define EPROTO_NOTONLINK __einfo_error ( EINFO_EPROTO_NOTONLINK ) 63 #define EINFO_EPROTO_NOTONLINK \ 64 __einfo_uniqify ( EINFO_EPROTO, 4, "Prefix not on link" ) 65 #define EPROTO_USEMULTICAST __einfo_error ( EINFO_EPROTO_USEMULTICAST ) 66 #define EINFO_EPROTO_USEMULTICAST \ 67 __einfo_uniqify ( EINFO_EPROTO, 5, "Use multicast address" ) 68 #define EPROTO_STATUS( status ) \ 69 EUNIQ ( EINFO_EPROTO, ( (status) & 0x0f ), EPROTO_UNSPECFAIL, \ 70 EPROTO_NOADDRSAVAIL, EPROTO_NOBINDING, \ 71 EPROTO_NOTONLINK, EPROTO_USEMULTICAST ) 102 size_t remaining =
options->len;
106 while ( remaining >=
sizeof (
option->header ) ) {
109 remaining -=
sizeof (
option->header );
111 if ( data_len > remaining ) {
121 option = ( ( (
void * )
option->header.data ) + data_len );
122 remaining -= data_len;
138 unsigned int code,
const void *expected,
177 status_code = &
option->status_code;
181 ( sizeof ( *status_code ) -
sizeof ( status_code->
header ) ) ) {
215 if (
len < (
sizeof ( *ia_na ) -
sizeof ( ia_na->
header ) ) )
239 if (
len < (
sizeof ( *iaaddr ) -
sizeof ( iaaddr->
header ) ) )
307 len =
sizeof ( *lease );
310 return sizeof ( *lease );
341 if (
len > option_len )
379 data = ( ( (
void * ) dhcpv6set ) +
sizeof ( *dhcpv6set ) );
429 static char buf[ 12 ];
567 DBGC ( dhcpv6,
"DHCPv6 %s entering %s state\n", dhcpv6->
netdev->
name,
588 static const char default_user_class[4] = {
'i',
'P',
'X',
'E' };
593 if ( actual_len >= 0 )
597 if (
len >
sizeof ( default_user_class ) )
598 len =
sizeof ( default_user_class );
600 return sizeof ( default_user_class );
619 size_t client_id_len;
620 size_t server_id_len;
622 size_t user_class_string_len;
623 size_t user_class_len;
629 client_id_len = (
sizeof ( *client_id ) +
631 server_id_len = ( dhcpv6->
server_duid ? (
sizeof ( *server_id ) +
634 ia_na_len =
sizeof ( *ia_na );
636 ia_na_len +=
sizeof ( *iaaddr );
641 user_class_len = (
sizeof ( *user_class ) +
643 user_class_string_len );
644 elapsed_len =
sizeof ( *elapsed );
645 total_len = (
sizeof ( *dhcphdr ) + client_id_len + server_id_len +
647 user_class_len + elapsed_len );
660 client_id =
iob_put ( iobuf, client_id_len );
663 sizeof ( client_id->
header ) );
668 if ( server_id_len ) {
669 server_id =
iob_put ( iobuf, server_id_len );
672 sizeof ( server_id->
header ) );
679 ia_na =
iob_put ( iobuf, ia_na_len );
682 sizeof ( ia_na->
header ) );
687 iaaddr = ( (
void * ) ia_na->
options );
690 sizeof ( iaaddr->
header ));
704 user_class =
iob_put ( iobuf, user_class_len );
707 sizeof ( user_class->
header ) );
710 user_class_string_len );
713 elapsed =
iob_put ( iobuf, elapsed_len );
716 sizeof ( elapsed->
header ) );
725 DBGC ( dhcpv6,
"DHCPv6 %s could not transmit: %s\n",
775 if (
iob_len ( iobuf ) <
sizeof ( *dhcphdr ) ) {
776 DBGC ( dhcpv6,
"DHCPv6 %s received packet too short (%zd " 777 "bytes, min %zd bytes)\n", dhcpv6->
netdev->
name,
784 DBGC ( dhcpv6,
"DHCPv6 %s received %s from %s\n",
797 DBGC ( dhcpv6,
"DHCPv6 %s received %s without correct client " 808 DBGC ( dhcpv6,
"DHCPv6 %s received %s without correct server " 816 DBGC ( dhcpv6,
"DHCPv6 %s received %s while expecting %s\n",
825 DBGC ( dhcpv6,
"DHCPv6 %s received %s with error status: %s\n",
836 &dhcpv6->
lease ) ) != 0 ) {
837 DBGC ( dhcpv6,
"DHCPv6 %s received %s with unusable " 845 DBGC ( dhcpv6,
"DHCPv6 %s received %s is for %s\n",
855 DBGC ( dhcpv6,
"DHCPv6 %s received %s missing server " 881 DBGC ( dhcpv6,
"DHCPv6 %s could not register settings: %s\n",
940 dhcpv6 =
zalloc (
sizeof ( *dhcpv6 ) );
953 memset ( &addresses, 0,
sizeof ( addresses ) );
954 addresses.client.sin6.sin6_family =
AF_INET6;
956 addresses.server.sin6.sin6_family =
AF_INET6;
966 DBGC ( dhcpv6,
"DHCPv6 %s could not create DUID-UUID: %s\n",
968 goto err_client_duid;
973 DBGC ( dhcpv6,
"DHCPv6 %s has XID %02x%02x%02x\n", dhcpv6->
netdev->
name,
974 dhcpv6->
xid[0], dhcpv6->
xid[1], dhcpv6->
xid[2] );
982 &addresses.server.sa,
983 &addresses.client.sa ) ) != 0 ) {
984 DBGC ( dhcpv6,
"DHCPv6 %s could not open socket: %s\n",
986 goto err_open_socket;
1004 .description =
"Boot filename",
1006 .type = &setting_type_string,
1013 .description =
"DNS search list",
1015 .type = &setting_type_dnssl,
uint8_t rx_type
Current expected received packet type.
static struct dhcpv6_session_state dhcpv6_solicit
DHCPv6 solicitation state.
struct dhcpv6_session_state * next
Next state (or NULL to terminate)
#define DHCPV6_SERVER_ID
DHCPv6 server identifier option.
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
static int dhcpv6_tx(struct dhcpv6_session *dhcpv6)
Transmit current request.
#define EINVAL
Invalid argument.
An object interface operation.
#define SETTING_IP_EXTRA
IPv4 additional settings.
#define DHCPV6_BOOTFILE_PARAM
DHCPv6 bootfile parameters option.
Record received server ID.
struct arbelprm_rc_send_wqe rc
void intf_close(struct interface *intf, int rc)
Close an object interface.
char string[0]
User class string.
#define DHCPV6_SOLICIT
DHCPv6 solicitation.
#define iob_put(iobuf, len)
#define TICKS_PER_SEC
Number of ticks per second.
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
#define DHCPV6_ELAPSED_TIME
DHCPv6 elapsed time option.
#define AF_INET6
IPv6 Internet addresses.
int xfer_deliver_iob(struct interface *intf, struct io_buffer *iobuf)
Deliver datagram as I/O buffer without metadata.
DHCP unique identifier based on UUID (DUID-UUID)
static void start_timer_nodelay(struct retry_timer *timer)
Start timer with no delay.
uint8_t ll_addr_len
Link-layer address length.
static struct interface_descriptor dhcpv6_xfer_desc
DHCPv6 data transfer interface descriptor.
struct interface xfer
Data transfer interface.
const struct settings_scope dhcpv6_scope
IPv6 settings scope.
struct interface job
Job control interface.
char * inet6_ntoa(const struct in6_addr *in)
Convert IPv6 address to standard notation.
static void dhcpv6_set_state(struct dhcpv6_session *dhcpv6, struct dhcpv6_session_state *state)
Transition to new DHCPv6 session state.
static struct interface_operation dhcpv6_job_op[]
DHCPv6 job control interface operations.
uint32_t next
Next descriptor address.
Include leased IPv6 address within request.
static uint8_t dhcpv6_request_options_data[]
Raw option data for options common to all DHCPv6 requests.
#define DHCPV6_IA_NA
DHCPv6 identity association for non-temporary address (IA_NA) option.
#define ref_init(refcnt, free)
Initialise a reference counter.
int xfer_open_socket(struct interface *intf, int semantics, struct sockaddr *peer, struct sockaddr *local)
Open socket.
struct settings * parent
Parent settings block.
struct dhcpv6_option header
Option header.
#define DHCP_ARCH_CLIENT_NDI
DHCP client network device interface.
uint8_t duid[0]
DHCP unique identifier (DUID)
#define DHCPV6_USER_CLASS
DHCPv6 user class option.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
size_t len
Length of data buffer.
uint64_t address
Base address.
struct dhcpv6_option options[0]
IA_NA options.
uint32_t type
Operating system type.
uint16_t status
Status code.
static int dhcpv6_status_code(struct dhcpv6_option_list *options)
Get DHCPv6 status code.
#define EPROTO_STATUS(status)
#define __einfo_errortab(einfo)
static int dhcpv6_check_duid(struct dhcpv6_option_list *options, unsigned int code, const void *expected, size_t len)
Check DHCPv6 client or server identifier.
uint32_t iaid
Identity association identifier (IAID)
#define DHCPV6_VENDOR_CLASS_PXE
DHCPv6 PXE vendor class.
#define DHCPV6_SETTINGS_NAME
DHCPv6 settings block name.
static int dhcpv6_applies(struct settings *settings __unused, const struct setting *setting)
Check applicability of DHCPv6 setting.
uint32_t iaid
Identity association ID.
#define ENOENT
No such file or directory.
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
struct net_device * netdev
Network device being configured.
#define DHCPV6_INFORMATION_REQUEST
DHCPv6 information request.
static const char * dhcpv6_type_name(unsigned int type)
Name a DHCPv6 packet type.
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
int fetch_raw_setting(struct settings *settings, const struct setting *setting, void *data, size_t len)
Fetch value of setting.
uint8_t options[0]
DHCP options.
uint32_t xid
Transaction ID.
uint8_t tx_type
Current transmitted packet type.
static struct settings_operations dhcpv6_settings_operations
DHCPv6 settings operations.
#define offsetof(type, field)
Get offset of a field within a structure.
Address assigned via DHCPv6.
#define DHCPV6_VENDOR_CLASS
DHCPv6 vendor class option.
static void dhcpv6_finished(struct dhcpv6_session *dhcpv6, int rc)
Terminate DHCPv6 session.
DHCPv6 user class option.
#define DHCPV6_REPLY
DHCPv6 reply.
struct in6_addr lease
Leased IPv6 address.
unsigned int scope_id
Scope ID.
static struct settings * netdev_settings(struct net_device *netdev)
Get per-netdevice configuration settings block.
static void settings_init(struct settings *settings, struct settings_operations *op, struct refcnt *refcnt, const struct settings_scope *default_scope)
Initialise a settings block.
Record received IPv6 address.
#define DHCPV6_DWORD_VALUE(value)
Construct a DHCPv6 dword value.
Data transfer interfaces.
u32 crc32_le(u32 seed, const void *data, size_t len)
Calculate 32-bit little-endian CRC checksum.
struct dhcpv6_option header
Option header.
struct dhcpv6_session_state * state
Current session state.
uint64_t tag
Setting tag, if applicable.
#define ENOMEM
Not enough space.
struct in6_addr lease
Leased address.
#define DHCPV6_CLIENT_ID
DHCPv6 client identifier option.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
const struct setting filename6_setting __setting(SETTING_BOOT, filename)
Boot filename setting.
DHCP client architecture definitions.
uint32_t valid
Valid lifetime (in seconds)
#define DHCP_ARCH_CLIENT_ARCHITECTURE
DHCP client architecture.
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
#define container_of(ptr, type, field)
Get containing structure.
A long option, as used for getopt_long()
struct dhcpv6_option options[0]
IAADDR options.
struct settings settings
Settings block.
struct dhcpv6_option header
Option header.
#define DHCPV6_ADVERTISE
DHCPv6 advertisement.
struct dhcpv6_option_list options
Option list.
static struct net_device * netdev
void * server_duid
Server DUID, if known.
struct refcnt refcnt
Reference counter.
dhcpv6_session_state_flags
DHCPv6 session state flags.
#define IN6_IS_ADDR_UNSPECIFIED(addr)
static struct interface_operation dhcpv6_xfer_op[]
DHCPv6 data transfer interface operations.
static void dhcpv6_free(struct refcnt *refcnt)
Free DHCPv6 session.
static void dhcpv6_timer_expired(struct retry_timer *timer, int fail)
Handle timer expiry.
static __always_inline void off_t userptr_t src
#define DHCPV6_CODE(code)
Construct a DHCPv6 option code.
Generalized socket address structure.
An object interface descriptor.
static struct dhcpv6_session_state dhcpv6_information_request
DHCPv6 information request state.
char * strerror(int errno)
Retrieve string representation of error number.
static void(* free)(struct refcnt *refcnt))
static int dhcpv6_fetch_lease(struct dhcpv6_settings *dhcpv6set, void *data, size_t len)
Fetch value of DHCPv6 leased address.
void * zalloc(size_t size)
Allocate cleared memory.
uint32_t rebind
Rebind time (in seconds)
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
#define EINFO_EPROTO_NOADDRSAVAIL
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Settings block operations.
#define DHCPV6_DNS_SERVERS
DHCPv6 DNS recursive name server option.
struct in6_addr address
IPv6 address.
#define SETTING_BOOT
Generic boot settings.
Data transfer interface opening.
DHCPv6 client or server identifier option.
DHCPv6 identity association address (IAADDR) option.
static struct net_device * netdev_get(struct net_device *netdev)
Get reference to network device.
#define DHCPV6_OPTION_REQUEST
DHCPv6 option request option.
#define DHCPV6_REQUEST
DHCPv6 request.
struct retry_timer timer
Retransmission timer.
#define DHCPV6_DOMAIN_LIST
DHCPv6 domain search list option.
void * malloc(size_t size)
Allocate memory.
int rc
Current timeout status code.
DHCPv6 status code option.
static int dhcpv6_fetch(struct settings *settings, struct setting *setting, void *data, size_t len)
Fetch value of DHCPv6 setting.
void start_timer(struct retry_timer *timer)
Start timer.
static int dhcpv6_rx(struct dhcpv6_session *dhcpv6, struct io_buffer *iobuf, struct xfer_metadata *meta)
Receive new data.
Network device management.
#define __unused
Declare a variable or data structure as unused.
uint32_t renew
Renew time (in seconds)
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
int order
Sibling ordering.
struct refcnt refcnt
Reference count.
void stop_timer(struct retry_timer *timer)
Stop timer.
char name[NETDEV_NAME_LEN]
Name of this network device.
size_t server_duid_len
Server DUID length.
uint16_t len
Length of the data field.
uint8_t code
Response code.
uint8_t unused[32]
Unused.
#define ENOTTY
Inappropriate I/O control operation.
unsigned long start
Start time (in ticks)
struct dhcpv6_option header
Option header.
void * data
Start of data.
struct dhcpv6_duid_uuid client_duid
Client DUID.
static void ipv6_all_dhcp_relay_and_servers(struct in6_addr *addr)
Construct all-DHCP-relay-agents-and-servers multicast address.
uint8_t xid[3]
Transaction ID.
#define DHCPV6_WORD(value)
Construct a word-valued DHCPv6 option.
uint8_t data[48]
Additional event data.
static const union dhcpv6_any_option * dhcpv6_option(struct dhcpv6_option_list *options, unsigned int code)
Find DHCPv6 option.
#define DHCPV6_CLIENT_PORT
DHCPv6 client port.
static int dhcpv6_register(struct in6_addr *lease, struct dhcpv6_option_list *options, struct settings *parent)
Register DHCPv6 options as network device settings.
static struct interface_descriptor dhcpv6_job_desc
DHCPv6 job control interface descriptor.
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
#define DHCPV6_STRING(...)
Construct a DHCPv6 option from a list of characters.
int(* applies)(struct settings *settings, const struct setting *setting)
Check applicability of setting.
#define DHCPV6_DUID_UUID
DHCP unique identifier based on UUID (DUID-UUID)
int register_settings(struct settings *settings, struct settings *parent, const char *name)
Register settings block.
int fetch_uuid_setting(struct settings *settings, const struct setting *setting, union uuid *uuid)
Fetch value of UUID setting.
#define DHCPV6_SERVER_PORT
DHCPv6 server port.
typeof(acpi_finder=acpi_find)
ACPI table finder.
#define DHCP_VENDOR_PXECLIENT(arch, ndi)
Vendor class identifier for PXE clients.
#define DHCPV6_IAADDR
DHCPv6 identity association address (IAADDR) option.
uint8_t ll_addr[MAX_LL_ADDR_LEN]
Link-layer address.
uint16_t elapsed
Elapsed time, in centiseconds.
unsigned long currticks(void)
Get current system time in ticks.
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
const struct settings_scope * scope
Setting scope (or NULL)
static size_t dhcpv6_user_class(void *data, size_t len)
Get DHCPv6 user class.
#define DHCPV6_STATUS_CODE
DHCPv6 status code option.
uint32_t preferred
Preferred lifetime (in seconds)
Include identity association within request.
struct dhcpv6_option header
Option header.
int setting_cmp(const struct setting *a, const struct setting *b)
Compare two settings.
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
#define DHCPV6_CLIENT_ARCHITECTURE
DHCPv6 client system architecture option.
DHCPv6 identity association for non-temporary address (IA_NA) option.
static struct dhcpv6_session_state dhcpv6_request
DHCPv6 request state.
#define NULL
NULL pointer (VOID *)
#define ETIMEDOUT
Connection timed out.
const void * data
Data buffer.
int start_dhcpv6(struct interface *job, struct net_device *netdev, int stateful)
Start DHCPv6.
struct bofm_section_header done
static int dhcpv6_iaaddr(struct dhcpv6_option_list *options, uint32_t iaid, struct in6_addr *address)
Get DHCPv6 identity association address.
struct ll_protocol * ll_protocol
Link-layer protocol.
struct dhcpv6_user_class user_class[0]
User class.
#define DHCPV6_BOOTFILE_URL
DHCPv6 bootfile URI option.
#define ref_put(refcnt)
Drop reference to object.
Dynamic Host Configuration Protocol for IPv6.
struct errortab dhcpv6_errors [] __errortab
Human-readable error messages.
#define DHCPV6_CLIENT_NDI
DHCPv6 client network interface identifier option.
void * memset(void *dest, int character, size_t len) __nonnull
struct dhcpv6_option header
Option header.
#define DHCPV6_OPTION(...)
Construct a DHCPv6 option from a list of bytes.
DHCPv6 elapsed time option.