TR111 and TR069 function development note (3)

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);
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章