-static uword
-dhcpv6_pd_client_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- dhcp6_pd_client_main_t *cm = &dhcp6_pd_client_main;
-
- dhcpv6_pd_client_next_t next_index;
- u32 n_left_from, *from, *to_next;
- next_index = 0;
- n_left_from = frame->n_vectors;
- from = vlib_frame_vector_args (frame);
-
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
-
- vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- ip6_header_t *ip0;
- u32 options_length;
- dhcpv6_header_t *dhcpv60;
- dhcpv6_option_t *option;
- vlib_buffer_t *b0;
- report_t report;
- u32 next0 = DHCPV6_PD_CLIENT_NEXT_DROP;
- u32 bi0;
- u32 xid;
- u32 sw_if_index;
- u32 iaid;
- u8 client_id_present = 0;
- u8 discard = 0;
-
- dhcp6_pd_client_state_t *client_state = NULL;
-
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
-
- dhcpv60 = vlib_buffer_get_current (b0);
- ip0 = (void *) (b0->data + vnet_buffer (b0)->l3_hdr_offset);
- u32 dhcpv6_ip6_palyoad_offset =
- (u8 *) dhcpv60 - ((u8 *) ip0 + sizeof (*ip0));
- options_length =
- ntohs (ip0->payload_length) - dhcpv6_ip6_palyoad_offset -
- sizeof (*dhcpv60);
-
- memset (&report, 0, sizeof (report));
-
- sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
- if (sw_if_index >= vec_len (cm->client_state_by_sw_if_index))
- client_state = 0;
- else
- client_state = &cm->client_state_by_sw_if_index[sw_if_index];
-
- xid =
- (dhcpv60->xid[0] << 16) + (dhcpv60->xid[1] << 8) +
- dhcpv60->xid[2];
- if (!client_state || client_state->transaction_id != xid)
- {
- clib_warning
- ("Received DHCPv6 message with wrong Transaction ID");
- discard = 1;
- }
-
- report.sw_if_index = sw_if_index;
- report.msg_type = dhcpv60->msg_type;
- report.server_index = ~0;
-
- switch (dhcpv60->msg_type)
- {
- case DHCPV6_MSG_ADVERTISE:
- case DHCPV6_MSG_REPLY:
- option = (dhcpv6_option_t *) (dhcpv60 + 1);
- while (options_length > 0)
- {
- if (options_length <
- ntohs (option->length) + sizeof (*option))
- {
- clib_warning
- ("remaining payload length < option length (%d < %d)",
- options_length,
- ntohs (option->length) + sizeof (*option));
- break;
- }
- u16 oo = ntohs (option->option);
- if (oo == DHCPV6_OPTION_IA_PD)
- {
- u8 discard_ia_pd = 0;
- dhcpv6_ia_header_t *ia_header = (void *) option;
- iaid = ntohl (ia_header->iaid);
- u32 T1 = ntohl (ia_header->t1);
- u32 T2 = ntohl (ia_header->t2);
- if (iaid != DHCPV6_CLIENT_IAID)
- discard_ia_pd = 1;
- if (T1 != 0 && T2 != 0 && T1 > T2)
- discard_ia_pd = 1;
- if (!discard_ia_pd)
- {
- report.T1 = T1;
- report.T2 = T2;
- }
- dhcpv6_option_t *inner_option =
- (void *) ia_header->data;
- u16 inner_options_length =
- ntohs (option->length) - (sizeof (*ia_header) -
- sizeof (dhcpv6_option_t));
- while (inner_options_length > 0)
- {
- u16 inner_oo = ntohs (inner_option->option);
- if (discard_ia_pd)
- ;
- else if (inner_oo == DHCPV6_OPTION_IAPREFIX)
- {
- dhcpv6_ia_opt_pd_t *iaprefix =
- (void *) inner_option;
- vec_validate (report.prefixes,
- report.n_prefixes);
- prefix_info_t *prefix_info =
- &report.prefixes[report.n_prefixes];
- report.n_prefixes++;
- prefix_info->preferred_time =
- ntohl (iaprefix->preferred);
- prefix_info->valid_time =
- ntohl (iaprefix->valid);
- prefix_info->prefix_length = iaprefix->prefix;
- prefix_info->prefix = iaprefix->addr;
- }
- else if (inner_oo == DHCPV6_OPTION_STATUS_CODE)
- {
- dhcpv6_status_code_t *sc =
- (void *) inner_option;
- report.inner_status_code =
- ntohs (sc->status_code);
- }
- inner_options_length -=
- sizeof (*inner_option) +
- ntohs (inner_option->length);
- inner_option =
- (void *) ((u8 *) inner_option +
- sizeof (*inner_option) +
- ntohs (inner_option->length));
- }
- }
- else if (oo == DHCPV6_OPTION_CLIENTID)
- {
- if (client_id_present)
- {
- clib_warning
- ("Duplicate Client ID in received DHVPv6 message");
- discard = 1;
- }
- else
- {
- u16 len = ntohs (option->length);
- client_id_present = 1;
- if (len != CLIENT_DUID_LENGTH ||
- 0 != memcmp (option->data,
- client_duid.bin_string,
- CLIENT_DUID_LENGTH))
- {
- clib_warning
- ("Unrecognized client DUID inside received DHVPv6 message");
- discard = 1;
- }
- }
- }
- else if (oo == DHCPV6_OPTION_SERVERID)
- {
- if (report.server_index != ~0)
- {
- clib_warning
- ("Duplicate Server ID in received DHVPv6 message");
- discard = 1;
- }
- else
- report.server_index =
- server_index_get_or_create (option->data,
- ntohs (option->length));
- }
- else if (oo == DHCPV6_OPTION_PREFERENCE)
- {
- report.preference = option->data[0];
- }
- else if (oo == DHCPV6_OPTION_STATUS_CODE)
- {
- dhcpv6_status_code_t *sc = (void *) option;
- report.status_code = ntohs (sc->status_code);
- }
- options_length -= sizeof (*option) + ntohs (option->length);
- option =
- (void *) ((u8 *) option + sizeof (*option) +
- ntohs (option->length));
- }
-
- if (!client_id_present)
- {
- clib_warning
- ("Missing Client ID in received DHVPv6 message");
- discard = 1;
- }
- if (report.server_index == ~0)
- {
- clib_warning
- ("Missing Server ID in received DHVPv6 message");
- discard = 1;
- }
-
- if (!discard)
- publish_report (&report);
- else
- vec_free (report.prefixes);
-
- break;
- default:
- break;
- }
-
- if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
- {
- dhcpv6_pd_client_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- }
-
- /* verify speculative enqueue, maybe switch current next frame */
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, next0);
- }
-
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
-
- return frame->n_vectors;
-}
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (dhcpv6_pd_client_node, static) = {
- .function = dhcpv6_pd_client_node_fn,
- .name = "dhcpv6-pd-client",
- .vector_size = sizeof (u32),
-
- .n_errors = 0,
-
- .n_next_nodes = DHCPV6_PD_CLIENT_N_NEXT,
- .next_nodes = {
- #define _(s,n) [DHCPV6_PD_CLIENT_NEXT_##s] = n,
- foreach_dhcpv6_pd_client
- #undef _
- },
-
- .format_trace = format_dhcpv6_pd_client_trace,
-};
-/* *INDENT-ON* */
-
-static_always_inline f64
-random_f64_from_to (f64 from, f64 to)
-{
- static u32 seed = 0;
- static u8 seed_set = 0;
- if (!seed_set)
- {
- seed = random_default_seed ();
- seed_set = 1;
- }
- return random_f64 (&seed) * (to - from) + from;
-}
-
-static const ip6_address_t all_dhcp6_relay_agents_and_servers = {
- .as_u8 = {
- 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02}
-};
-