mirror of
https://dev.iopsys.eu/bbf/icwmp.git
synced 2026-01-27 17:17:17 +01:00
cherry-pick dhcp option43 handling
This commit is contained in:
parent
44571036d1
commit
91e473e780
3 changed files with 142 additions and 143 deletions
20
README.md
20
README.md
|
|
@ -543,6 +543,26 @@ This script then writes the gateway identity in `/var/state/cwmp` if CWMP is ena
|
|||
|
||||
Datamodel (libbbf) API's reads the gateway information from `/var/state/cwmp` to populate Device.GatewayInfo. object. If gateway information is not available in `/var/state/cwmp` then it reads the 'db' (Same source used for Device.DeviceInfo. object) and maps that data to populate Device.GatewayInfo. object.
|
||||
|
||||
## Provisioning of CWMP Agent through DHCP Server
|
||||
If CPE receives DHCP option 43 in DHCP offer from upstream network it exposes the same in its UBUS method (e.g. ifstatus wan).
|
||||
|
||||
```bash
|
||||
root@iopsys-44d43771b000:~# ifstatus wan
|
||||
{
|
||||
...
|
||||
...
|
||||
"data": {
|
||||
"vendorspecinf": "XXXXXXXXXXXXXXXXXXX"
|
||||
}
|
||||
}
|
||||
```
|
||||
CWMP Agent uses DHCP option 43 for provisioning if CWMP and DHCP discovery is enabled in the device. ICWMPD package adds a [DHCP client hook script](files/etc/udhcpc.user.d/udhcpc_icwmp_opt43.user), which parses DHCP option 43 value to extract informations like ACS URL, minimum interval for session retry, retry interval multiplier for session retry and provisioning code that specifies the primary service provider and other provisioning information, which may be used by the ACS to determine service provider-specific customization and provisioning parameters.
|
||||
This script then writes the provisioning information in `/etc/config/cwmp`.
|
||||
|
||||
CWMP Agent reads the provisioning information from `/etc/config/cwmp` before starting a session.
|
||||
|
||||
> Note: If in any time ACS configures `Device.ManagementServer.URL` then DHCP discovery is disabled automatically.
|
||||
|
||||
## Dependencies
|
||||
|
||||
To successfully build icwmp, the following libraries are needed:
|
||||
|
|
|
|||
143
config.c
143
config.c
|
|
@ -23,144 +23,6 @@
|
|||
|
||||
pthread_mutex_t mutex_config_load = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
void get_dhcp_vend_info_cb(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg)
|
||||
{
|
||||
if (req == NULL || msg == NULL)
|
||||
return;
|
||||
|
||||
char **v_info = (char **)req->priv;
|
||||
if (v_info == NULL)
|
||||
return;
|
||||
|
||||
struct blob_attr *param;
|
||||
size_t rem;
|
||||
|
||||
enum {
|
||||
E_VENDOR_INFO,
|
||||
__E_MAX
|
||||
};
|
||||
|
||||
const struct blobmsg_policy p[__E_MAX] = {
|
||||
{ "vendorspecinf", BLOBMSG_TYPE_STRING },
|
||||
};
|
||||
|
||||
blobmsg_for_each_attr(param, msg, rem) {
|
||||
if (strcmp(blobmsg_name(param), "data") == 0) {
|
||||
struct blob_attr *tb[__E_MAX] = {NULL};
|
||||
if (blobmsg_parse(p, __E_MAX, tb, blobmsg_data(param), blobmsg_len(param)) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tb[E_VENDOR_INFO]) {
|
||||
char *info = blobmsg_get_string(tb[E_VENDOR_INFO]);
|
||||
if (info == NULL)
|
||||
info = "";
|
||||
int len = strlen(info) + 1;
|
||||
*v_info = (char *)malloc(len);
|
||||
if (*v_info == NULL)
|
||||
return;
|
||||
|
||||
memset(*v_info, 0, len);
|
||||
snprintf(*v_info, len, "%s", info);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool configure_dhcp_options(char *vendspecinf)
|
||||
{
|
||||
if (vendspecinf == NULL) {
|
||||
CWMP_LOG(DEBUG, "No vendor specific info found");
|
||||
return false;
|
||||
}
|
||||
|
||||
// extract url from vendor info
|
||||
int len = CWMP_STRLEN(vendspecinf) + 1;
|
||||
char vend_info[len];
|
||||
memset(vend_info, 0, len);
|
||||
snprintf(vend_info, len, "%s", vendspecinf);
|
||||
|
||||
if (strncmp(vend_info, "http://", 7) == 0 || strncmp(vend_info, "https://", 8) == 0) {
|
||||
uci_set_value_by_path(UCI_DHCP_ACS_URL, vend_info, UCI_STANDARD_CONFIG);
|
||||
CWMP_LOG(DEBUG, "dhcp url: %s", vend_info);
|
||||
cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool update_uci = false;
|
||||
char *temp = strtok(vend_info, " ");
|
||||
while (temp) {
|
||||
if (strncmp(temp, "1=", 2) == 0) {
|
||||
char *pos = temp + 2;
|
||||
if (CWMP_STRLEN(pos)) {
|
||||
uci_set_value_by_path(UCI_DHCP_ACS_URL, pos, UCI_STANDARD_CONFIG);
|
||||
CWMP_LOG(DEBUG, "dhcp url: %s", pos);
|
||||
update_uci = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(temp, "2=", 2) == 0) {
|
||||
char *pos = temp + 2;
|
||||
if (CWMP_STRLEN(pos)) {
|
||||
uci_set_value_by_path(UCI_DHCP_CPE_PROV_CODE, pos, UCI_STANDARD_CONFIG);
|
||||
update_uci = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(temp, "3=", 2) == 0) {
|
||||
char *pos = temp + 2;
|
||||
if (CWMP_STRLEN(pos)) {
|
||||
uci_set_value_by_path(UCI_DHCP_ACS_RETRY_MIN_WAIT_INTERVAL, pos, UCI_STANDARD_CONFIG);
|
||||
update_uci = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(temp, "4=", 2) == 0) {
|
||||
char *pos = temp + 2;
|
||||
if (CWMP_STRLEN(pos)) {
|
||||
uci_set_value_by_path(UCI_DHCP_ACS_RETRY_INTERVAL_MULTIPLIER, pos, UCI_STANDARD_CONFIG);
|
||||
update_uci = true;
|
||||
}
|
||||
}
|
||||
|
||||
temp = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
if (update_uci)
|
||||
cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG);
|
||||
|
||||
cwmp_uci_reinit();
|
||||
return update_uci;
|
||||
}
|
||||
|
||||
static void get_dhcp_vendor_info(char *intf)
|
||||
{
|
||||
if (intf == NULL)
|
||||
return;
|
||||
|
||||
char ubus_obj[100] = {0};
|
||||
snprintf(ubus_obj, sizeof(ubus_obj), "network.interface.%s", intf);
|
||||
|
||||
struct blob_buf b;
|
||||
memset(&b, 0, sizeof(struct blob_buf));
|
||||
blob_buf_init(&b, 0);
|
||||
|
||||
char *vendor_info = NULL;
|
||||
if (icwmp_ubus_invoke(ubus_obj, "status", b.head, get_dhcp_vend_info_cb, &vendor_info) == 0) {
|
||||
CWMP_LOG(DEBUG, "vendor info: %s", vendor_info);
|
||||
configure_dhcp_options(vendor_info);
|
||||
}
|
||||
|
||||
FREE(vendor_info);
|
||||
|
||||
blob_buf_free(&b);
|
||||
}
|
||||
|
||||
static char* get_value_from_uci_option(struct uci_option *tb) {
|
||||
if (tb == NULL)
|
||||
return NULL;
|
||||
|
|
@ -333,13 +195,8 @@ int get_global_config(struct config *conf)
|
|||
|
||||
bool discovery_enable = false;
|
||||
error = uci_get_value(UCI_DHCP_DISCOVERY_PATH, &value);
|
||||
|
||||
// now read the vendor info from ifstatus before reading the DHCP_ACS_URL from uci
|
||||
if (error == CWMP_OK && value != NULL) {
|
||||
discovery_enable = uci_str_to_bool(value);
|
||||
if (discovery_enable == true && conf->default_wan_iface != NULL) {
|
||||
get_dhcp_vendor_info(conf->default_wan_iface);
|
||||
}
|
||||
}
|
||||
FREE(value);
|
||||
|
||||
|
|
|
|||
122
files/etc/udhcpc.user.d/udhcpc_icwmp_opt43.user
Normal file
122
files/etc/udhcpc.user.d/udhcpc_icwmp_opt43.user
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
#!/bin/sh
|
||||
|
||||
. /lib/functions.sh
|
||||
|
||||
DHCP_ACS_URL=""
|
||||
DHCP_PROV_CODE=""
|
||||
MIN_WAIT_INVL=""
|
||||
INVL_MULTIPLIER=""
|
||||
|
||||
get_opt43() {
|
||||
# Check if option value is in encapsulated form
|
||||
local opt43="$1"
|
||||
local len="$2"
|
||||
|
||||
[ "$len" -gt "2" ] || return
|
||||
|
||||
first_byte=${opt43:0:2}
|
||||
first_byte=$(printf "%d\n" "0x$first_byte")
|
||||
|
||||
if [ $len -ge 4 ] && [ $first_byte -ge 1 ] && [ $first_byte -le 4 ]; then
|
||||
# it is in encapsulated form
|
||||
# opt43 encapsulated vendor-specific option has data in below format
|
||||
# Code Len Data item Code Len Data item Code
|
||||
# +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
# | T1 | n | d1 | d2 | ... | T2 | n | D1 | D2 | ... | ... |
|
||||
# +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
|
||||
#hex-string 2 character=1 Byte
|
||||
# length in hex string will be twice of actual Byte length
|
||||
|
||||
data="${opt43}"
|
||||
rem_len="${len}"
|
||||
# parsing of suboption of option 43
|
||||
while [ $rem_len -gt 0 ]; do
|
||||
# get the suboption id
|
||||
sub_opt_id=${data:0:2}
|
||||
sub_opt_id=$(printf "%d\n" "0x$sub_opt_id")
|
||||
|
||||
# get the length of suboption
|
||||
sub_opt_len=${data:2:2}
|
||||
sub_opt_len=$(printf "%d\n" "0x$sub_opt_len")
|
||||
sub_opt_len=$(( sub_opt_len * 2 ))
|
||||
|
||||
# get the value of sub option starting 4 means starting after length
|
||||
sub_opt_val=${data:4:${sub_opt_len}}
|
||||
|
||||
# assign the value found in sub option
|
||||
case "${sub_opt_id}" in
|
||||
"1") DHCP_ACS_URL=$(echo -n $sub_opt_val | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf && echo '')
|
||||
;;
|
||||
"2") DHCP_PROV_CODE=$(echo -n $sub_opt_val | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf && echo '')
|
||||
;;
|
||||
"3") MIN_WAIT_INVL=$(echo -n $sub_opt_val | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf && echo '')
|
||||
;;
|
||||
"4") INVL_MULTIPLIER=$(echo -n $sub_opt_val | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf && echo '')
|
||||
;;
|
||||
esac
|
||||
|
||||
# add 2 bytes for sub_opt id and sub_opt len field
|
||||
sub_opt_end=$(( sub_opt_len + 4 ))
|
||||
|
||||
# fetch next sub option hex string
|
||||
data=${data:${sub_opt_end}:${len}}
|
||||
|
||||
# update the remaining sub option hex string length
|
||||
rem_len=$((rem_len - sub_opt_end))
|
||||
done
|
||||
else
|
||||
DHCP_ACS_URL=$(echo -n $opt43 | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf && echo '')
|
||||
fi
|
||||
}
|
||||
|
||||
config_load cwmp
|
||||
config_get_bool enable_cwmp cpe enable 1
|
||||
config_get wan_intf cpe default_wan_interface "wan"
|
||||
config_get dhcp_discovery acs dhcp_discovery "0"
|
||||
|
||||
discovery_enable=0
|
||||
if [ "$dhcp_discovery" = "1" ] || [ "$dhcp_discovery" = "true" ] || [ "$dhcp_discovery" = "enable" ]; then
|
||||
discovery_enable=1
|
||||
fi
|
||||
|
||||
if [ "$enable_cwmp" = "0" ] || [ "$discovery_enable" = "0" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ "${wan_intf}" == "${INTERFACE}" ]; then
|
||||
if [ -n "$opt43" ]; then
|
||||
len=$(printf "$opt43"|wc -c)
|
||||
get_opt43 "$opt43" "$len"
|
||||
fi
|
||||
|
||||
if [ -z "$DHCP_ACS_URL" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
sec=$(uci -q get cwmp.acs)
|
||||
if [ -z "${sec}" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
uci -q set cwmp.acs.dhcp_url="$DHCP_ACS_URL"
|
||||
|
||||
if [ -n "$MIN_WAIT_INVL" ]; then
|
||||
uci -q set cwmp.acs.dhcp_retry_min_wait_interval="$MIN_WAIT_INVL"
|
||||
fi
|
||||
|
||||
if [ -n "$INVL_MULTIPLIER" ]; then
|
||||
uci -q set cwmp.acs.dhcp_retry_interval_multiplier="$INVL_MULTIPLIER"
|
||||
fi
|
||||
uci -q commit cwmp
|
||||
|
||||
sec=$(uci -q get cwmp.cpe)
|
||||
if [ -z "${sec}" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ -n "$DHCP_PROV_CODE" ]; then
|
||||
uci -q set cwmp.cpe.dhcp_provisioning_code="$DHCP_PROV_CODE"
|
||||
uci -q commit cwmp
|
||||
fi
|
||||
fi
|
||||
Loading…
Add table
Reference in a new issue