- h0 = vlib_buffer_get_current (b0);
-
- /*
- * udp_local hands us the DHCPV6 header.
- */
- u0 = (void *)h0 -(sizeof(*u0));
- ip0 = (void *)u0 -(sizeof(*ip0));
- e_h0 = (void *)ip0 - ethernet_buffer_header_size(b0);
-
- clib_memcpy(client_src_mac, e_h0->src_address, 6);
-
- switch (h0->u.msg_type) {
- case DHCPV6_MSG_SOLICIT:
- case DHCPV6_MSG_REQUEST:
- case DHCPV6_MSG_CONFIRM:
- case DHCPV6_MSG_RENEW:
- case DHCPV6_MSG_REBIND:
- case DHCPV6_MSG_RELEASE:
- case DHCPV6_MSG_DECLINE:
- case DHCPV6_MSG_INFORMATION_REQUEST:
- case DHCPV6_MSG_RELAY_FORW:
- /* send to server */
- break;
- case DHCPV6_MSG_RELAY_REPL:
- /* send to client */
- next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_SEND_TO_CLIENT;
- error0 = 0;
- pkts_to_client++;
- goto do_enqueue;
- default:
- /* drop the packet */
- pkts_wrong_msg_type++;
- error0 = DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE;
- next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
- goto do_trace;
-
- }
-
- /* Send to DHCPV6 server via the configured FIB */
- rx_sw_if_index = sw_if_index = vnet_buffer(b0)->sw_if_index[VLIB_RX];
- rx_fib_idx = im->mfib_index_by_sw_if_index [rx_sw_if_index];
- proxy = dhcp_get_proxy(dpm, rx_fib_idx, FIB_PROTOCOL_IP6);
-
- if (PREDICT_FALSE (NULL == proxy))
- {
- error0 = DHCPV6_PROXY_ERROR_NO_SERVER;
- next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
- pkts_no_server++;
- goto do_trace;
- }
-
- server = &proxy->dhcp_servers[0];
- server_fib_idx = server->server_fib_index;
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = server_fib_idx;
-
-
- /* relay-option header pointer */
- vlib_buffer_advance(b0, -(sizeof(*fwd_opt)));
- fwd_opt = vlib_buffer_get_current(b0);
- /* relay message header pointer */
- vlib_buffer_advance(b0, -(sizeof(*r1)));
- r1 = vlib_buffer_get_current(b0);
-
- vlib_buffer_advance(b0, -(sizeof(*u1)));
- u1 = vlib_buffer_get_current(b0);
-
- vlib_buffer_advance(b0, -(sizeof(*ip1)));
- ip1 = vlib_buffer_get_current(b0);
-
- /* fill in all that rubbish... */
- len = clib_net_to_host_u16(u0->length) - sizeof(udp_header_t);
- copy_ip6_address(&r1->peer_addr, &ip0->src_address);
-
- r1->msg_type = DHCPV6_MSG_RELAY_FORW;
- fwd_opt->length = clib_host_to_net_u16(len);
- fwd_opt->option = clib_host_to_net_u16(DHCPV6_OPTION_RELAY_MSG);
-
- r1->hop_count++;
- r1->hop_count = (h0->u.msg_type != DHCPV6_MSG_RELAY_FORW) ? 0 : r1->hop_count;
-
- if (PREDICT_FALSE(r1->hop_count >= HOP_COUNT_LIMIT))
- {
- error0 = DHCPV6_RELAY_PKT_DROP_MAX_HOPS;
- next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
- pkts_no_exceeding_max_hop++;
- goto do_trace;
- }
-
-
- /* If relay-fwd and src address is site or global unicast address */
- if (h0->u.msg_type == DHCPV6_MSG_RELAY_FORW &&
- ((ip0->src_address.as_u8[0] & 0xe0) == 0x20 ||
- (ip0->src_address.as_u8[0] & 0xfe) == 0xfc))
- {
- /* Set link address to zero */
- r1->link_addr.as_u64[0] = 0;
- r1->link_addr.as_u64[1] = 0;
- goto link_address_set;
- }
-
- /* if receiving interface is unnumbered, use receiving interface
- * IP address as link address, otherwise use the loopback interface
- * IP address as link address.
- */
-
- swif = vnet_get_sw_interface (vnm, rx_sw_if_index);
- if (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
- sw_if_index = swif->unnumbered_sw_if_index;
-
- ia0 = ip6_interface_first_global_or_site_address(&ip6_main, sw_if_index);
- if (ia0 == 0)
- {
- error0 = DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS;
- next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
- pkts_no_interface_address++;
- goto do_trace;
- }
-
- copy_ip6_address(&r1->link_addr, ia0);
-
- link_address_set:
- fl = vlib_buffer_get_free_list (vm, vlib_buffer_get_free_list_index (b0));
-
- if ((b0->current_length+sizeof(*id1)+sizeof(*vss1)+sizeof(*cmac))
- > fl->n_data_bytes)
- {
- error0 = DHCPV6_PROXY_ERROR_PKT_TOO_BIG;
- next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
- pkts_too_big++;
- goto do_trace;
- }
-
- id1 = (dhcpv6_int_id_t *) (((uword) ip1) + b0->current_length);
- b0->current_length += (sizeof (*id1));
-
- id1->opt.option = clib_host_to_net_u16(DHCPV6_OPTION_INTERFACE_ID);
- id1->opt.length = clib_host_to_net_u16(sizeof(rx_sw_if_index));
- id1->int_idx = clib_host_to_net_u32(rx_sw_if_index);
-
- u1->length =0;
- if (h0->u.msg_type != DHCPV6_MSG_RELAY_FORW)
- {
- cmac = (dhcpv6_client_mac_t *) (((uword) ip1) + b0->current_length);
- b0->current_length += (sizeof (*cmac));
- cmac->opt.length =clib_host_to_net_u16(sizeof(*cmac) -
- sizeof(cmac->opt));
- cmac->opt.option = clib_host_to_net_u16(DHCPV6_OPTION_CLIENT_LINK_LAYER_ADDRESS);
- cmac->link_type = clib_host_to_net_u16(1); /* ethernet */
- clib_memcpy(cmac->data, client_src_mac, 6);
- u1->length += sizeof(*cmac);
- }
-
- vss = dhcp_get_vss_info(dpm, rx_fib_idx, FIB_PROTOCOL_IP6);
-
- if (vss)
+ h0 = vlib_buffer_get_current (b0);
+
+ /*
+ * udp_local hands us the DHCPV6 header.
+ */
+ u0 = (void *) h0 - (sizeof (*u0));
+ ip0 = (void *) u0 - (sizeof (*ip0));
+ e_h0 = (void *) ip0 - ethernet_buffer_header_size (b0);
+
+ clib_memcpy (client_src_mac, e_h0->src_address, 6);
+
+ switch (h0->u.msg_type)
+ {
+ case DHCPV6_MSG_SOLICIT:
+ case DHCPV6_MSG_REQUEST:
+ case DHCPV6_MSG_CONFIRM:
+ case DHCPV6_MSG_RENEW:
+ case DHCPV6_MSG_REBIND:
+ case DHCPV6_MSG_RELEASE:
+ case DHCPV6_MSG_DECLINE:
+ case DHCPV6_MSG_INFORMATION_REQUEST:
+ case DHCPV6_MSG_RELAY_FORW:
+ /* send to server */
+ break;
+ case DHCPV6_MSG_RELAY_REPL:
+ /* send to client */
+ next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_SEND_TO_CLIENT;
+ error0 = 0;
+ pkts_to_client++;
+ goto do_enqueue;
+ default:
+ /* drop the packet */
+ pkts_wrong_msg_type++;
+ error0 = DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE;
+ next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
+ goto do_trace;
+
+ }
+
+ /* Send to DHCPV6 server via the configured FIB */
+ rx_sw_if_index = sw_if_index =
+ vnet_buffer (b0)->sw_if_index[VLIB_RX];
+ rx_fib_idx = im->mfib_index_by_sw_if_index[rx_sw_if_index];
+ proxy = dhcp_get_proxy (dpm, rx_fib_idx, FIB_PROTOCOL_IP6);
+
+ if (PREDICT_FALSE (NULL == proxy))
+ {
+ error0 = DHCPV6_PROXY_ERROR_NO_SERVER;
+ next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
+ pkts_no_server++;
+ goto do_trace;
+ }
+
+ server = &proxy->dhcp_servers[0];
+ server_fib_idx = server->server_fib_index;
+ vnet_buffer (b0)->sw_if_index[VLIB_TX] = server_fib_idx;
+
+
+ /* relay-option header pointer */
+ vlib_buffer_advance (b0, -(sizeof (*fwd_opt)));
+ fwd_opt = vlib_buffer_get_current (b0);
+ /* relay message header pointer */
+ vlib_buffer_advance (b0, -(sizeof (*r1)));
+ r1 = vlib_buffer_get_current (b0);
+
+ vlib_buffer_advance (b0, -(sizeof (*u1)));
+ u1 = vlib_buffer_get_current (b0);
+
+ vlib_buffer_advance (b0, -(sizeof (*ip1)));
+ ip1 = vlib_buffer_get_current (b0);
+
+ /* fill in all that rubbish... */
+ len = clib_net_to_host_u16 (u0->length) - sizeof (udp_header_t);
+ copy_ip6_address (&r1->peer_addr, &ip0->src_address);
+
+ r1->msg_type = DHCPV6_MSG_RELAY_FORW;
+ fwd_opt->length = clib_host_to_net_u16 (len);
+ fwd_opt->option = clib_host_to_net_u16 (DHCPV6_OPTION_RELAY_MSG);
+
+ r1->hop_count++;
+ r1->hop_count =
+ (h0->u.msg_type != DHCPV6_MSG_RELAY_FORW) ? 0 : r1->hop_count;
+
+ if (PREDICT_FALSE (r1->hop_count >= HOP_COUNT_LIMIT))
+ {
+ error0 = DHCPV6_RELAY_PKT_DROP_MAX_HOPS;
+ next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
+ pkts_no_exceeding_max_hop++;
+ goto do_trace;
+ }
+
+
+ /* If relay-fwd and src address is site or global unicast address */
+ if (h0->u.msg_type == DHCPV6_MSG_RELAY_FORW &&
+ ((ip0->src_address.as_u8[0] & 0xe0) == 0x20 ||
+ (ip0->src_address.as_u8[0] & 0xfe) == 0xfc))
+ {
+ /* Set link address to zero */
+ r1->link_addr.as_u64[0] = 0;
+ r1->link_addr.as_u64[1] = 0;
+ goto link_address_set;
+ }
+
+ /* if receiving interface is unnumbered, use receiving interface
+ * IP address as link address, otherwise use the loopback interface
+ * IP address as link address.
+ */
+
+ swif = vnet_get_sw_interface (vnm, rx_sw_if_index);
+ if (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
+ sw_if_index = swif->unnumbered_sw_if_index;
+
+ ia0 =
+ ip6_interface_first_global_or_site_address (&ip6_main,
+ sw_if_index);
+ if (ia0 == 0)
+ {
+ error0 = DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS;
+ next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
+ pkts_no_interface_address++;
+ goto do_trace;
+ }
+
+ copy_ip6_address (&r1->link_addr, ia0);
+
+ link_address_set:
+ fl =
+ vlib_buffer_get_free_list (vm,
+ vlib_buffer_get_free_list_index (b0));
+
+ if ((b0->current_length + sizeof (*id1) + sizeof (*vss1) +
+ sizeof (*cmac)) > fl->n_data_bytes)
+ {
+ error0 = DHCPV6_PROXY_ERROR_PKT_TOO_BIG;
+ next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
+ pkts_too_big++;
+ goto do_trace;
+ }
+
+ id1 = (dhcpv6_int_id_t *) (((uword) ip1) + b0->current_length);
+ b0->current_length += (sizeof (*id1));
+
+ id1->opt.option = clib_host_to_net_u16 (DHCPV6_OPTION_INTERFACE_ID);
+ id1->opt.length = clib_host_to_net_u16 (sizeof (rx_sw_if_index));
+ id1->int_idx = clib_host_to_net_u32 (rx_sw_if_index);
+
+ u1->length = 0;
+ if (h0->u.msg_type != DHCPV6_MSG_RELAY_FORW)
+ {
+ cmac =
+ (dhcpv6_client_mac_t *) (((uword) ip1) + b0->current_length);
+ b0->current_length += (sizeof (*cmac));
+ cmac->opt.length = clib_host_to_net_u16 (sizeof (*cmac) -
+ sizeof (cmac->opt));
+ cmac->opt.option =
+ clib_host_to_net_u16
+ (DHCPV6_OPTION_CLIENT_LINK_LAYER_ADDRESS);
+ cmac->link_type = clib_host_to_net_u16 (1); /* ethernet */
+ clib_memcpy (cmac->data, client_src_mac, 6);
+ u1->length += sizeof (*cmac);
+ }
+
+ vss = dhcp_get_vss_info (dpm, rx_fib_idx, FIB_PROTOCOL_IP6);
+
+ if (vss)