Below is the critical pieces of code to add DHCP125 options supports
static int add_vendor_specific_sub_option(uint8_t *sub_options, uint8_t sub_code, const uint8_t *sub_value)
{/* sub options: Code + Len + Data */
int lindex = 0;
int lsize;
int sub_options_size;
int sub_value_len;
sub_value_len = str_len(sub_value);
/* FIXME, check, is it overload */
sub_options[lindex + OPT_CODE] = sub_code;
sub_options[lindex + OPT_LEN] = (uint8_t) sub_value_len;
memcpy(sub_options + lindex + OPT_DATA, sub_value, sub_value_len);
sub_options_size = lsub_value_len + OPT_DATA;
return sub_options_size;
}
/* add OPTION(125) vendor specific option into DHCP options */
int add_vendor_specific_option(uint8_t *optionptr,
uint32_t vendor_enterprise_code,
const uint8_t *device_manufacture_oui,
const uint8_t *device_serial_number,
const uint8_t *device_product_class)
{
uint8_t vendor_option[128] = {0};
int vendor_option_len;
int vendor_enterprise_code_len = 4; /* sizeof vendor enterprise code */
int sub_options_size_index;
int sub_options_size = 0;
uint8_t *sub_options;
vendor_option[OPT_CODE] = DHCP_FACTORY_OPTS;
*((uint32_t *)(vendor_option + OPT_DATA)) = htonl(vendor_enterprise_code);
/* add vendor specific sub options */
sub_options_size_index = OPT_DATA + vendor_enterprise_code_len;
sub_options = vendor_option + (sub_options_size_index );
sub_options_size = add_vendor_specific_sub_option(sub_options, 1, device_manufacture_oui);
sub_options_size = add_vendor_specific_sub_option(sub_options, 2, device_serial_number);
sub_options_size = add_vendor_specific_sub_option(sub_options, 3, device_product_class);
/* update vendor sub options length */
vendor_option[sub_options_size_index] = (uint8_t)sub_options_size;
/* update vendor option(125) length */
vendor_option_len = vendor_enterprise_code_len + (1 + sub_options_size);
vendor_option[OPT_LEN] = (uint8_t)vendor_option_len;
return add_option_string(optionptr, vendor_option);
}
/*If the gateway DHCPACK response message includes the Gateway Identity carried in the V-I Vendor-Specific
Information DHCP Option ,the Device record the received value in the GatewayInfo*/
int get_vendor_specific_option(struct dhcpMessage *packet,
int oui_code, uint8_t *device_manufacture_oui, uint32_t *device_manufacture_oui_size,
int serial_number_code, uint8_t *device_serial_number, uint32_t *device_serial_number_size,
int product_class_code, uint8_t *device_product_class, uint32_t *device_product_class_size)
{
uint8_t *vendor_options = NULL;
uint32_t vendor_options_size= 0;
uint8_t *vendor_sub_total_options = NULL;
uint32_t vendor_sub_options_total_size = 0;
const uint8_t *vendor_sub_option = NULL;
uint32_t vendor_sub_option_size = 0;
if ((vendor_options = get_option(packet, DHCP_FACTORY_OPTS)) == NULL) {
/* TODO, log error msg */
return -1;
}
vendor_options_size = vendor_options[-1];
vendor_sub_options_total_size = vendor_options[4];
/* TODO, check (vendor_options_size == (vendor_sub_options_total_size + 4 + 1) */
vendor_sub_total_options = vendor_options + 4 + 1; /* sizeof vendor enterprise code + sub options len byte */
/* 4.gateway_manufacture_oui */
vendor_sub_option = get_vendor_specific_sub_option(vendor_sub_total_options, vendor_sub_options_total_size, oui_code);
vendor_sub_option_size = vendor_sub_option[-1];
if (*device_manufacture_oui_size > vendor_sub_option_size) {
memcpy(device_manufacture_oui, vendor_sub_option, vendor_sub_option_size);
device_manufacture_oui[vendor_sub_option_size] = '\0';
*device_manufacture_oui_size = vendor_sub_option_size;
} else {
/* TODO, log error msg */
*device_manufacture_oui_size = 0;
}
/* 5. gateway_serial_number */
vendor_sub_option = get_vendor_specific_sub_option(vendor_sub_total_options, vendor_sub_options_total_size, serial_number_code);
vendor_sub_option_size = vendor_sub_option[-1];
if (*device_serial_number_size > vendor_sub_option_size) {
memcpy(device_serial_number, vendor_sub_option, vendor_sub_option_size);
device_serial_number[vendor_sub_option_size] = '\0';
*device_serial_number_size = vendor_sub_option_size;
} else {
/* TODO, log error msg */
*device_serial_number_size = 0;
}
/* 6. gateway_product_class */
vendor_sub_option = get_vendor_specific_sub_option(vendor_sub_total_options, vendor_sub_options_total_size, product_class_code);
vendor_sub_option_size = vendor_sub_option[-1];
if (*device_product_class_size > vendor_sub_option_size) {
memcpy(device_product_class, vendor_sub_option, vendor_sub_option_size);
device_product_class[vendor_sub_option_size] = '\0';
*device_product_class_size = vendor_sub_option_size;
} else {
/* TODO, log error msg */
*device_product_class_size = 0;
}
return 0;
}
another things,we must sent DHCP125 request to server ,so that dhcp server can response DHCP125 infor to client , when client sent discover and request phase, call add_vendor_specific_option function is needed:
/* Broadcast a DHCP discover packet to the network, with an optionally requested IP */
int send_discover(uint32_t xid, uint32_t requested)
{
struct dhcpMessage packet;
init_packet(&packet, DHCPDISCOVER);
packet.xid = xid;
if (requested)
add_simple_option(packet.options, DHCP_REQUESTED_IP, requested);
/*******************ADD TO DHCP 125******************************/
//add_simple_option(packet.options, DHCP_FACTORY_OPTS, htons(VENDOR_FACTORY_SUBOPTIONS));
bb_info_msg("Try to add VENDOR OPTION(125) into DHCP options.");
get_device_identify();
/* try to add VENDOR OPTION(125) into DHCP options.
* You can add you vendor sub options */
add_vendor_specific_option(packet.options,
VENDOR_FACTORY_SUBOPTIONS,,
device_ouiPtr,
device_serial_NumberPtr,
device_productClassPtr);
/* (const uint8_t *)"module",
(const uint8_t *)"xx:xx:xx:xx:xx:xx",
(const uint8_t *)" Wireless Repeater");*/
/******************* ADD END ***********************************/
bb_info_msg("Try to add DHCP_MAX_SIZE OPTION(57) into DHCP options.");
/* Explicitly saying that we want RFC-compliant packets helps
* some buggy DHCP servers to NOT send bigger packets */
add_simple_option(packet.options, DHCP_MAX_SIZE, htons(576));
bb_info_msg("Try to add dhcp requires parameters OPTION(55) into DHCP options.");
add_param_req_option(&packet);
bb_info_msg("Sending discover...");
return udhcp_send_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST,
SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex);
}
/* Broadcasts a DHCP request message */
int send_selecting(uint32_t xid, uint32_t server, uint32_t requested)
{
struct dhcpMessage packet;
struct in_addr addr;
char lan_ipaddr[64] = {0};
init_packet(&packet, DHCPREQUEST);
packet.xid = xid;
add_simple_option(packet.options, DHCP_REQUESTED_IP, requested);
/******************* ADD TO SUPPORT TR111******************************/
get_device_identify();
/* try to add VENDOR OPTION(125) into DHCP options.
* You can add you vendor sub options */
bb_info_msg("Try to add VENDOR OPTION(125) into DHCP options.");
add_vendor_specific_option(packet.options,
VENDOR_FACTORY_SUBOPTIONS,
device_ouiPtr,
device_serial_NumberPtr,
device_productClassPtr);
/* (const uint8_t *)"module",
(const uint8_t *)"xx:xx:xx:xx:xx:xx",
(const uint8_t *)" Wireless Repeater");*/
/******************* ADD END ***********************************/
add_simple_option(packet.options, DHCP_SERVER_ID, server);
add_param_req_option(&packet);
addr.s_addr = requested;
bb_info_msg("Sending select for %s...", inet_ntoa(addr));
sprintf(lan_ipaddr, "nvram_set 2860 lan_ipaddr %s", inet_ntoa(addr));
bb_info_msg("%s",lan_ipaddr);
system(lan_ipaddr);
return udhcp_send_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST,
SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex);
}