- if ((o->option == 0xFF) && ((u8 *)o <= end))
- {
- vnet_main_t *vnm = vnet_get_main();
- u16 old_l0, new_l0;
- ip4_address_t _ia0, * ia0 = &_ia0;
- dhcp_vss_t *vss;
- vnet_sw_interface_t *swif;
- sw_if_index = 0;
- original_sw_if_index = 0;
-
- original_sw_if_index = sw_if_index =
- vnet_buffer(b0)->sw_if_index[VLIB_RX];
- swif = vnet_get_sw_interface (vnm, sw_if_index);
- if (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
- sw_if_index = swif->unnumbered_sw_if_index;
-
- /*
- * Get the first ip4 address on the [client-side]
- * RX interface, if not unnumbered. otherwise use
- * the loopback interface's ip address.
- */
- ia0 = ip4_interface_first_address(&ip4_main, sw_if_index, 0);
-
- if (ia0 == 0)
- {
- error0 = DHCP_PROXY_ERROR_NO_INTERFACE_ADDRESS;
- next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_DROP;
- pkts_no_interface_address++;
- goto do_trace;
- }
-
- /* Add option 82 */
- o->option = 82; /* option 82 */
- o->length = 12; /* 12 octets to follow */
- o->data[0] = 1; /* suboption 1, circuit ID (=FIB id) */
- o->data[1] = 4; /* length of suboption */
- u32 *o_ifid = (u32 *) &o->data[2];
+ space_left = vlib_buffer_chain_linearize (vm, b0);
+ /* cant parse chains...
+ * and we need some space for option 82*/
+ if ((b0->flags & VLIB_BUFFER_NEXT_PRESENT) != 0 ||
+ space_left < VPP_DHCP_OPTION82_SIZE)
+ {
+ error0 = DHCP_PROXY_ERROR_PKT_TOO_BIG;
+ next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_DROP;
+ pkts_too_big++;
+ goto do_trace;
+ }
+
+ server = &proxy->dhcp_servers[0];
+ vlib_buffer_advance (b0, -(sizeof (*ip0)));
+ ip0 = vlib_buffer_get_current (b0);
+
+ /* disable UDP checksum */
+ u0->checksum = 0;
+ sum0 = ip0->checksum;
+ old0 = ip0->dst_address.as_u32;
+ new0 = server->dhcp_server.ip4.as_u32;
+ ip0->dst_address.as_u32 = server->dhcp_server.ip4.as_u32;
+ sum0 = ip_csum_update (sum0, old0, new0,
+ ip4_header_t /* structure */ ,
+ dst_address /* changed member */ );
+ ip0->checksum = ip_csum_fold (sum0);
+
+ sum0 = ip0->checksum;
+ old0 = ip0->src_address.as_u32;
+ new0 = proxy->dhcp_src_address.ip4.as_u32;
+ ip0->src_address.as_u32 = new0;
+ sum0 = ip_csum_update (sum0, old0, new0,
+ ip4_header_t /* structure */ ,
+ src_address /* changed member */ );
+ ip0->checksum = ip_csum_fold (sum0);
+
+ /* Send to DHCP server via the configured FIB */
+ vnet_buffer (b0)->sw_if_index[VLIB_TX] = server->server_fib_index;
+
+ h0->gateway_ip_address = proxy->dhcp_src_address.ip4;
+ pkts_to_server++;
+
+ o = h0->options;
+ end = (void *) vlib_buffer_get_tail (b0);
+
+ /* TLVs are not performance-friendly... */
+ while (o->option != DHCP_PACKET_OPTION_END && o < end)
+ {
+ if (DHCP_PACKET_OPTION_MSG_TYPE == o->option)
+ {
+ if (DHCP_PACKET_DISCOVER == o->data[0])
+ {
+ is_discover = 1;
+ }
+ }
+ o = (dhcp_option_t *) (o->data + o->length);
+ }
+
+ if (o->option == DHCP_PACKET_OPTION_END && o <= end)
+ {
+ vnet_main_t *vnm = vnet_get_main ();
+ u16 old_l0, new_l0;
+ ip4_address_t _ia0, *ia0 = &_ia0;
+ dhcp_vss_t *vss;
+ vnet_sw_interface_t *swif;
+
+ original_sw_if_index = sw_if_index =
+ vnet_buffer (b0)->sw_if_index[VLIB_RX];
+ swif = vnet_get_sw_interface (vnm, sw_if_index);
+ if (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
+ sw_if_index = swif->unnumbered_sw_if_index;
+
+ /*
+ * Get the first ip4 address on the [client-side]
+ * RX interface, if not unnumbered. otherwise use
+ * the loopback interface's ip address.
+ */
+ ia0 = ip4_interface_first_address (&ip4_main, sw_if_index, 0);
+
+ if (ia0 == 0)
+ {
+ error0 = DHCP_PROXY_ERROR_NO_INTERFACE_ADDRESS;
+ next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_DROP;
+ pkts_no_interface_address++;
+ goto do_trace;
+ }
+
+ /* Add option 82 */
+ o->option = 82; /* option 82 */
+ o->length = 12; /* 12 octets to follow */
+ o->data[0] = 1; /* suboption 1, circuit ID (=FIB id) */
+ o->data[1] = 4; /* length of suboption */
+ u32 *o_ifid = (u32 *) & o->data[2];