38 if (se->
len == len && 0 == memcmp (se->
data, data, len))
45 memcpy (new_se.
data, data, len);
56 client_duid.hardware_type = clib_host_to_net_u16 (1);
66 eth_if = ethernet_get_interface (ðernet_main, hi->hw_if_index);
77 "setting DHCPv6 DUID link-layer address to random value");
80 client_duid.lla[0] = 0xc2;
81 client_duid.lla[1] = 0x18;
82 client_duid.lla[2] = 0x44;
89 #define foreach_dhcpv6_client \ 90 _(DROP, "error-drop") \ 91 _(LOOKUP, "ip6-lookup") 95 #define _(sym,str) DHCPV6_CLIENT_NEXT_##sym, 115 s =
format (s,
"nothing");
128 u32 n_left_from, *from, *to_next;
133 while (n_left_from > 0)
139 while (n_left_from > 0 && n_left_to_next > 0)
144 dhcpv6_option_t *option;
149 u32 next0 = DHCPV6_CLIENT_NEXT_DROP;
154 u8 client_id_present = 0;
172 u32 dhcpv6_ip6_payload_offset =
173 (
u8 *) dhcpv60 - ((
u8 *) ip0 +
sizeof (*ip0));
176 dhcpv6_ip6_payload_offset -
sizeof (*dhcpv60);
182 ia_na_client_state = 0;
192 (dhcpv60->
xid[0] << 16) + (dhcpv60->
xid[1] << 8) +
194 if (ia_na_client_state && ia_na_client_state->
transaction_id == xid)
196 else if (pd_client_state && pd_client_state->
transaction_id == xid)
201 (
"Received DHCPv6 message with wrong Transaction ID");
213 option = (dhcpv6_option_t *) (dhcpv60 + 1);
214 while (options_length > 0)
217 clib_net_to_host_u16 (option->length) +
221 (
"remaining payload length < option length (%d < %d)",
223 clib_net_to_host_u16 (option->length) +
227 u16 oo = clib_net_to_host_u16 (option->option);
228 if (oo == DHCPV6_OPTION_IA_NA || oo == DHCPV6_OPTION_IA_PD)
230 u8 discard_option = 0;
231 dhcpv6_ia_header_t *ia_header = (
void *) option;
232 iaid = clib_net_to_host_u32 (ia_header->iaid);
233 u32 T1 = clib_net_to_host_u32 (ia_header->t1);
234 u32 T2 = clib_net_to_host_u32 (ia_header->t2);
237 if (T1 != 0 && T2 != 0 && T1 > T2)
244 dhcpv6_option_t *inner_option =
245 (
void *) ia_header->data;
246 u16 inner_options_length =
247 clib_net_to_host_u16 (option->length) -
248 (
sizeof (*ia_header) -
sizeof (dhcpv6_option_t));
249 while (inner_options_length > 0)
252 clib_net_to_host_u16 (inner_option->option);
255 else if (inner_oo == DHCPV6_OPTION_IAADDR)
257 dhcpv6_ia_opt_addr_t *iaaddr =
258 (
void *) inner_option;
262 &addresses[n_addresses];
264 clib_net_to_host_u32 (iaaddr->preferred);
266 clib_net_to_host_u32 (iaaddr->valid);
267 address_info->
address = iaaddr->addr;
269 else if (inner_oo == DHCPV6_OPTION_IAPREFIX)
271 dhcpv6_ia_opt_pd_t *iaprefix =
272 (
void *) inner_option;
276 &prefixes[n_prefixes];
278 clib_net_to_host_u32 (iaprefix->preferred);
280 clib_net_to_host_u32 (iaprefix->valid);
282 prefix_info->
prefix = iaprefix->addr;
284 else if (inner_oo == DHCPV6_OPTION_STATUS_CODE)
286 dhcpv6_status_code_t *sc =
287 (
void *) inner_option;
289 clib_net_to_host_u16 (sc->status_code);
291 inner_options_length -=
292 sizeof (*inner_option) +
293 clib_net_to_host_u16 (inner_option->length);
295 (
void *) ((
u8 *) inner_option +
296 sizeof (*inner_option) +
298 (inner_option->length));
301 else if (oo == DHCPV6_OPTION_CLIENTID)
303 if (client_id_present)
306 (
"Duplicate Client ID in received DHVPv6 message");
311 u16 len = clib_net_to_host_u16 (option->length);
312 client_id_present = 1;
314 0 != memcmp (option->data,
319 (
"Unrecognized client DUID inside received DHVPv6 message");
324 else if (oo == DHCPV6_OPTION_SERVERID)
329 (
"Duplicate Server ID in received DHVPv6 message");
334 u16 ol = clib_net_to_host_u16 (option->length);
338 (
"Server DUID (without type code) is longer than 128 octets");
348 else if (oo == DHCPV6_OPTION_PREFERENCE)
352 else if (oo == DHCPV6_OPTION_STATUS_CODE)
354 dhcpv6_status_code_t *sc = (
void *) option;
356 clib_net_to_host_u16 (sc->status_code);
359 sizeof (*option) + clib_net_to_host_u16 (option->length);
361 (
void *) ((
u8 *) option +
sizeof (*option) +
362 clib_net_to_host_u16 (option->length));
365 if (!client_id_present)
368 (
"Missing Client ID in received DHVPv6 message");
374 (
"Missing Server ID in received DHVPv6 message");
417 to_next, n_left_to_next,
430 .name =
"dhcpv6-client",
431 .vector_size =
sizeof (
u32),
437 #define _(s,n) [DHCPV6_CLIENT_NEXT_##s] = n, 453 if (client_duid.duid_type == 0)
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
static vlib_node_registration_t dhcpv6_client_node
(constructor) VLIB_REGISTER_NODE (dhcpv6_client_node)
static uword random_default_seed(void)
Default random seed (unix/linux user-mode)
dhcp6_pd_client_main_t dhcp6_pd_client_main
vnet_main_t * vnet_get_main(void)
vnet_interface_main_t interface_main
dhcp6_pd_client_state_t * client_state_by_sw_if_index
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static void generate_client_duid(void)
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
int dhcp6_pd_publish_report(prefix_report_t *r)
#define clib_memcpy(d, s, n)
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
vl_api_interface_index_t sw_if_index
#define foreach_dhcpv6_client
vnet_hw_interface_t * hw_interfaces
dhcp6_ia_na_client_main_t dhcp6_ia_na_client_main
u32 server_index_get_or_create(u8 *data, u16 len)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
dhcp6_ia_na_client_state_t * client_state_by_sw_if_index
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
dhcpv6_duid_ll_string_t client_duid
#define CLIENT_DUID_LENGTH
#define VLIB_REGISTER_NODE(x,...)
#define DHCPV6_CLIENT_IAID
#define vec_free(V)
Free vector's memory (no header).
void udp_unregister_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u8 is_ip4)
#define clib_warning(format, args...)
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
vlib_main_t vlib_node_runtime_t * node
struct dhcpv6_client_trace_t_ dhcpv6_client_trace_t
per-packet trace data
dhcp6_report_common_t body
static vlib_main_t * vlib_get_main(void)
dhcp6_client_common_main_t dhcp6_client_common_main
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
int dhcp6_publish_report(address_report_t *r)
VLIB buffer representation.
dhcp6_address_info_t * addresses
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
void dhcp6_clients_enable_disable(u8 enable)
static u32 random_u32(u32 *seed)
32-bit random number generator
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
void udp_register_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u32 node_index, u8 is_ip4)
dhcp6_report_common_t body
static uword dhcpv6_client_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
dhcp6_prefix_info_t * prefixes
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
static u8 * format_dhcpv6_client_trace(u8 *s, va_list *args)