static vlib_node_registration_t dhcp_client_process_node;
static void
+dhcp_client_add_rx_address (dhcp_client_main_t * dcm, dhcp_client_t * c)
+{
+ /* Install a local entry for the offered address */
+ fib_prefix_t rx =
+ {
+ .fp_len = 32,
+ .fp_addr.ip4 = c->leased_address,
+ .fp_proto = FIB_PROTOCOL_IP4,
+ };
+
+ fib_table_entry_special_add(fib_table_get_index_for_sw_if_index(
+ FIB_PROTOCOL_IP4,
+ c->sw_if_index),
+ &rx,
+ FIB_SOURCE_DHCP,
+ (FIB_ENTRY_FLAG_LOCAL));
+
+ /* And add the server's address as uRPF exempt so we can accept
+ * local packets from it */
+ fib_prefix_t server =
+ {
+ .fp_len = 32,
+ .fp_addr.ip4 = c->dhcp_server,
+ .fp_proto = FIB_PROTOCOL_IP4,
+ };
+
+ fib_table_entry_special_add(fib_table_get_index_for_sw_if_index(
+ FIB_PROTOCOL_IP4,
+ c->sw_if_index),
+ &server,
+ FIB_SOURCE_URPF_EXEMPT,
+ (FIB_ENTRY_FLAG_DROP));
+}
+
+static void
+dhcp_client_remove_rx_address (dhcp_client_main_t * dcm, dhcp_client_t * c)
+{
+ fib_prefix_t rx =
+ {
+ .fp_len = 32,
+ .fp_addr.ip4 = c->leased_address,
+ .fp_proto = FIB_PROTOCOL_IP4,
+ };
+
+ fib_table_entry_special_remove(fib_table_get_index_for_sw_if_index(
+ FIB_PROTOCOL_IP4,
+ c->sw_if_index),
+ &rx,
+ FIB_SOURCE_DHCP);
+ fib_prefix_t server =
+ {
+ .fp_len = 32,
+ .fp_addr.ip4 = c->dhcp_server,
+ .fp_proto = FIB_PROTOCOL_IP4,
+ };
+
+ fib_table_entry_special_remove(fib_table_get_index_for_sw_if_index(
+ FIB_PROTOCOL_IP4,
+ c->sw_if_index),
+ &server,
+ FIB_SOURCE_URPF_EXEMPT);
+}
+
+static void
dhcp_client_acquire_address (dhcp_client_main_t * dcm, dhcp_client_t * c)
{
/*
/* parse through the packet, learn what we can */
if (dhcp->your_ip_address.as_u32)
c->leased_address.as_u32 = dhcp->your_ip_address.as_u32;
-
+
+ c->dhcp_server.as_u32 = dhcp->server_ip_address.as_u32;
+
o = (dhcp_option_t *) dhcp->options;
while (o->option != 0xFF /* end of options */ &&
c->next_transmit = now + 5.0;
break;
}
+ /*
+ * in order to accept unicasted ACKs we need to configure the offered
+ * address on the interface. However, at this point we may not know the
+ * subnet-mask (an OFFER may not contain it). So add a temporary receice
+ * and uRPF excempt entry
+ */
+ dhcp_client_add_rx_address (dcm, c);
+
/* Received an offer, go send a request */
c->state = DHCP_REQUEST;
c->retry_count = 0;
/* OK, we own the address (etc), add to the routing table(s) */
if (c->state == DHCP_REQUEST)
{
- void (*fp)(u32, u32, u8 *, u8, u8 *, u8 *, u8 *) = c->event_callback;
+ void (*fp)(u32, u32, u8 *, u8, u8, u8 *, u8 *, u8 *) = c->event_callback;
+ /* replace the temporary RX address with the correct subnet */
+ dhcp_client_remove_rx_address (dcm, c);
dhcp_client_acquire_address (dcm, c);
/*
(*fp) (c->client_index, /* clinet index */
c->pid,
c->hostname,
+ c->subnet_mask_width,
0, /* is_ipv6 */
(u8 *)&c->leased_address, /* host IP address */
(u8 *)&c->router_address, /* router IP address */
o = (dhcp_option_t * )dhcp->options;
/* Send option 53, the DHCP message type */
- o->option = 53;
+ o->option = DHCP_PACKET_OPTION_MSG_TYPE;
o->length = 1;
o->data[0] = type;
o = (dhcp_option_t *) (((uword) o) + (o->length + 2));
o = (dhcp_option_t *) (((uword) o) + (o->length + 2));
}
+ /* send option 61, client_id */
+ if (vec_len (c->client_identifier))
+ {
+ o->option = 61;
+ o->length = vec_len (c->client_identifier);
+ clib_memcpy (o->data, c->client_identifier,
+ vec_len (c->client_identifier));
+ o = (dhcp_option_t *) (((uword) o) + (o->length + 2));
+ }
+
/* $$ maybe send the client s/w version if anyone cares */
/*
c->sw_if_index),
&all_1s,
FIB_SOURCE_DHCP,
- FIB_ENTRY_FLAG_LOCAL,
- ADJ_INDEX_INVALID);
+ FIB_ENTRY_FLAG_LOCAL);
/*
* enable the interface to RX IPv4 packets
1,
FIB_ROUTE_PATH_FLAG_NONE);
}
+ dhcp_client_remove_rx_address (dcm, c);
+ dhcp_client_release_address (dcm, c);
ip4_sw_interface_enable_disable (c->sw_if_index, 0);
vec_free (c->option_55_data);
dhcp_client_config (vlib_main_t * vm,
u32 sw_if_index,
u8 * hostname,
+ u8 * client_id,
u32 is_add,
u32 client_index,
void * event_callback,
a->event_callback = event_callback;
vec_validate(a->hostname, strlen((char *)hostname) - 1);
strncpy((char *)a->hostname, (char *)hostname, vec_len(a->hostname));
- a->client_identifier = format (0, "vpe 1.0%c", 0);
+ vec_validate(a->client_identifier, strlen((char *)client_id) - 1);
+ strncpy((char *)a->client_identifier, (char *)client_id, vec_len(a->client_identifier));
+
/*
* Option 55 request list. These data precisely match
* the Ubuntu dhcp client. YMMV.