From 426cc077e027740b8395bd904e5fce99c568e911 Mon Sep 17 00:00:00 2001 From: Suvendhu Hansa Date: Wed, 5 Mar 2025 18:08:38 +0530 Subject: [PATCH] obuspa: controller provisioning via dhcp --- .../udhcpc.user.d/udhcpc_obuspa_opt125.user | 447 +++++++++++++----- 1 file changed, 320 insertions(+), 127 deletions(-) diff --git a/obuspa/files/etc/udhcpc.user.d/udhcpc_obuspa_opt125.user b/obuspa/files/etc/udhcpc.user.d/udhcpc_obuspa_opt125.user index d95a94573..9d264be22 100644 --- a/obuspa/files/etc/udhcpc.user.d/udhcpc_obuspa_opt125.user +++ b/obuspa/files/etc/udhcpc.user.d/udhcpc_obuspa_opt125.user @@ -7,6 +7,7 @@ PROV_CODE="" RETRY_MIN_INTERVAL="5" RETRY_INTERVAL_MUL="2000" ENDPOINT_ID="" +CONTROLLER_DISCOVERED=0 log() { @@ -101,15 +102,25 @@ get_vivsoi() { # assign the value found in sub option case "${sub_opt_id}" in - "25") URL=$(echo -n $sub_opt_val | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf && echo '') + "25") + URL=$(echo -n $sub_opt_val | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf && echo '') + CONTROLLER_DISCOVERED=1 ;; - "26") PROV_CODE=$(echo -n $sub_opt_val | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf && echo '') + "26") + PROV_CODE=$(echo -n $sub_opt_val | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf && echo '') + CONTROLLER_DISCOVERED=1 ;; - "27") RETRY_MIN_INTERVAL=$(echo -n $sub_opt_val | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf && echo '') + "27") + RETRY_MIN_INTERVAL=$(echo -n $sub_opt_val | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf && echo '') + CONTROLLER_DISCOVERED=1 ;; - "28") RETRY_INTERVAL_MUL=$(echo -n $sub_opt_val | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf && echo '') + "28") + RETRY_INTERVAL_MUL=$(echo -n $sub_opt_val | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf && echo '') + CONTROLLER_DISCOVERED=1 ;; - "29") ENDPOINT_ID=$(echo -n $sub_opt_val | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf && echo '') + "29") + ENDPOINT_ID=$(echo -n $sub_opt_val | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf && echo '') + CONTROLLER_DISCOVERED=1 ;; esac @@ -144,6 +155,20 @@ get_access_role() echo "$mode" } +get_agent_topic() +{ + AgentEndpointID="$(uci -q get obuspa.localagent.EndpointID)" + if [ -z "${AgentEndpointID}" ]; then + serial=$(get_serial_from_db) + oui=$(get_oui_from_db) + AgentEndpointID=$(echo "${oui}-${serial//+/%2B}") + fi + + topic_base=$(echo "${AgentEndpointID}" | sed -E 's/[^[:alnum:]]/_/g') + agent_topic="/usp/${topic_base}/endpoint" + echo "${agent_topic}" +} + config_load obuspa config_get_bool enable_obuspa global enabled 1 config_get wan_intf global interface @@ -171,7 +196,7 @@ if [ "${wan_intf}" == "${INTERFACE}" ]; then get_vivsoi "$opt125" "$len" fi - if [ -z "$URL" ] || [ -z "$ENDPOINT_ID" ]; then + if [ "${CONTROLLER_DISCOVERED}" -eq 0 ]; then return 0 fi @@ -180,151 +205,319 @@ if [ "${wan_intf}" == "${INTERFACE}" ]; then port="" topic="" is_fqdn=1 + offered_proto="" + mtp_encrypt="" + dhcp_controller="" + dhcp_mtp="" + dhcp_mqtt="" - case $URL in - ws://*) is_fqdn=0;; - wss://*) is_fqdn=0;; - mqtt://*) is_fqdn=0;; - mqtts://*) is_fqdn=0;; - *) is_fqdn=1 - esac; + if [ -n "$URL" ]; then + case $URL in + ws://*) is_fqdn=0;; + wss://*) is_fqdn=0;; + mqtt://*) is_fqdn=0;; + mqtts://*) is_fqdn=0;; + *://*) return 0;; + *) is_fqdn=1 + esac; - if [ ${is_fqdn} -eq 1 ]; then - # This is an FQDN, perform DNS query - nslookup -type=a $URL > /tmp/fqdn_ip - nslookup -type=ptr $URL > /tmp/fqdn_ptr - return 0 - else - proto=$(echo "${URL}" | awk -F: '{print $1}') - dest=$(echo "${URL}" | awk -F/ '{print $3}') - ip=$(echo "${dest}" | awk -F: '{print $1}') - port=$(echo "${dest}" | awk -F: '{print $2}') - topic=$(echo "${URL}" | sed 's/^.*:'"${port}"'/\1/g') + if [ ${is_fqdn} -eq 1 ]; then + case $URL in + *.local*) + # TODO extend for mdns handling + ;; + *) + # This is an FQDN, perform DNS query + nslookup $URL > /tmp/fqdn_ip + nslookup -type=ptr $URL > /tmp/fqdn_ptr + nslookup -type=srv $URL > /tmp/fqdn_srv + nslookup -type=txt $URL > /tmp/fqdn_srv + + # TODO extend to collect information from dns-sd records + ;; + esac + + return 0 + else + proto=$(echo "${URL}" | awk -F: '{print $1}') + dest=$(echo "${URL}" | awk -F/ '{print $3}') + ip=$(echo "${dest}" | awk -F: '{print $1}') + port=$(echo "${dest}" | awk -F: '{print $2}') + topic=$(echo "${URL}" | sed 's/^.*:'"${port}"'/\1/g') + fi fi - offered_proto="" if [ "${proto}" == "mqtt" ] || [ "${proto}" == "mqtts" ]; then offered_proto="MQTT" + if [ "${proto}" == "mqtt" ]; then + mtp_encrypt="TCP/IP" + else + mtp_encrypt="TLS" + fi elif [ "${proto}" == "ws" ] || [ "${proto}" == "wss" ]; then offered_proto="WebSocket" - else - return 0 + if [ "${proto}" == "wss" ]; then + mtp_encrypt="1" + else + mtp_encrypt="0" + fi + fi + + controllers=$(uci -q show obuspa | grep "=controller" | cut -d'=' -f1 | cut -d'.' -f2) + for controller in $controllers; do + dhcp_disc=$(uci -q get obuspa.$controller.dhcp_discovered) + if [ "${dhcp_disc}" -eq 1 ]; then + dhcp_controller="${controller}" + break + fi + done + + if [ -n "${dhcp_controller}" ]; then + cont_proto="$(uci -q get obuspa.$dhcp_controller.Protocol)" + if [ "${cont_proto}" == "MQTT" ]; then + dhcp_mqtt="$(uci -q get obuspa.$dhcp_controller.mqtt)" + + mtps=$(uci -q show obuspa | grep "=mtp" | cut -d'=' -f1 | cut -d'.' -f2) + for mtp in $mtps; do + mtp_mqtt="$(uci -q get obuspa.$mtp.mqtt)" + if [ "${mtp_mqtt}" == "${dhcp_mqtt}" ]; then + dhcp_mtp="${mtp}" + break + fi + done + elif [ "${cont_proto}" == "WebSocket" ]; then + cont_port="$(uci -q get obuspa.$dhcp_controller.Port)" + cont_encr="$(uci -q get obuspa.$dhcp_controller.EnableEncryption)" + + mtps=$(uci -q show obuspa | grep "=mtp" | cut -d'=' -f1 | cut -d'.' -f2) + for mtp in $mtps; do + mtp_port="$(uci -q get obuspa.$mtp.Port)" + mtp_encr="$(uci -q get obuspa.$mtp.EnableEncryption)" + if [ "${mtp_port}" == "${cont_port}" ] && [ "${mtp_encr}" == "${cont_encr}" ]; then + dhcp_mtp="${mtp}" + break + fi + done + fi fi uci_change=0 - mtp_encrypt="0" - ## Handling of controller section - ct_endpoint=$(uci -q get obuspa.dhcpcontroller.EndpointID) - ct_proto=$(uci -q get obuspa.dhcpcontroller.Protocol) - ct_topic=$(uci -q get obuspa.dhcpcontroller.Topic) - ct_enable=$(uci -q get obuspa.dhcpcontroller.Enable) - ct_prov=$(uci -q get obuspa.dhcpcontroller.ProvisioningCode) + proto_changed="0" + + if [ -n "${dhcp_controller}" ]; then + ## Handling of controller section + ct_endpoint=$(uci -q get obuspa.$dhcp_controller.EndpointID) + ct_proto=$(uci -q get obuspa.$dhcp_controller.Protocol) + ct_prov=$(uci -q get obuspa.$dhcp_controller.ProvisioningCode) + + if [ "${ct_proto}" = "MQTT" ]; then + ct_topic=$(uci -q get obuspa.$dhcp_controller.Topic) + else + ct_topic=$(uci -q get obuspa.$dhcp_controller.Path) + fi + + if [ -n "${ENDPOINT_ID}" ] && [ "${ct_endpoint}" != "${ENDPOINT_ID}" ]; then + uci -q set obuspa.$dhcp_controller.EndpointID="${ENDPOINT_ID}" + uci_change=1 + fi + + if [ -n "${offered_proto}" ] && [ "${ct_proto}" != "${offered_proto}" ]; then + uci -q set obuspa.$dhcp_controller.Protocol="${offered_proto}" + if [ "${offered_proto}" != "MQTT" ]; then + uci -q set obuspa.$dhcp_controller.mqtt="" + uci -q set obuspa.$dhcp_controller.Topic="" + uci -q set obuspa.$dhcp_controller.Host="${ip}" + uci -q set obuspa.$dhcp_controller.Port="${port}" + uci -q set obuspa.$dhcp_controller.Path="${ct_topic}" + uci -q set obuspa.$dhcp_controller.EnableEncryption="${mtp_encrypt}" + else + uci -q set obuspa.$dhcp_controller.EnableEncryption="" + uci -q set obuspa.$dhcp_controller.Path="" + uci -q set obuspa.$dhcp_controller.Host="" + uci -q set obuspa.$dhcp_controller.Port="" + + if [ -z "${dhcp_mqtt}" ]; then + uci -q set obuspa.$dhcp_controller.mqtt='dhcpmqtt' + else + uci -q set obuspa.$dhcp_controller.mqtt="${dhcp_mqtt}" + fi + + uci -q set obuspa.$dhcp_controller.Topic="${ct_topic}" + fi + + proto_changed=1 + uci_change=1 + fi + + if [ -n "${topic}" ] && [ "${ct_topic}" != "${topic}" ]; then + protocol="${ct_proto}" + if [ -n "${offered_proto}" ]; then + protocol="${offered_proto}" + fi + + if [ "${protocol}" == "MQTT" ]; then + uci -q set obuspa.$dhcp_controller.Topic="${topic}" + else + uci -q set obuspa.$dhcp_controller.Path="${topic}" + fi + + uci_change=1 + fi + + if [ -n "${PROV_CODE}" ] && [ "${ct_prov}" != "${PROV_CODE}" ]; then + uci -q set obuspa.$dhcp_controller.ProvisioningCode="${PROV_CODE}" + uci_change=1 + fi + + if [ "${proto_changed}" -eq 1 ]; then + if [ "${offered_proto}" == "WebSocket" ]; then + if [ -n "${dhcp_mqtt}" ]; then + uci -q del obuspa.$dhcp_mqtt + fi + + if [ -z "${dhcp_mtp}" ]; then + sec=$(uci -q add obuspa mtp) + uci -q rename obuspa."${sec}"='dhcpmtp' + dhcp_mtp="dhcpmtp" + uci -q set obuspa.$dhcp_mtp.Enable='1' + fi + + uci -q set obuspa.$dhcp_mtp.mqtt='' + uci -q set obuspa.$dhcp_mtp.ResponseTopicConfigured='' + uci -q set obuspa.$dhcp_mtp.Protocol='WebSocket' + uci -q set obuspa.$dhcp_mtp.Port="${port}" + uci -q set obuspa.$dhcp_mtp.EnableEncryption="${mtp_encrypt}" + + uci_change=1 + else + if [ -z "${dhcp_mqtt}" ]; then + sec=$(uci -q add obuspa mqtt) + uci -q rename obuspa."${sec}"='dhcpmqtt' + dhcp_mqtt="dhcpmqtt" + uci -q set obuspa.$dhcp_mqtt.Enable='1' + fi + + uci -q set obuspa.$dhcp_mqtt.BrokerAddress="${ip}" + uci -q set obuspa.$dhcp_mqtt.BrokerPort="${port}" + uci -q set obuspa.$dhcp_mqtt.TransportProtocol="${mtp_encrypt}" + uci -q set obuspa.$dhcp_mqtt.ProtocolVersion='5.0' + + if [ -z "${dhcp_mtp}" ]; then + sec=$(uci -q add obuspa mtp) + uci -q rename obuspa."${sec}"='dhcpmtp' + dhcp_mtp="dhcpmtp" + uci -q set obuspa.$dhcp_mtp.Enable='1' + fi + + agent_topic=$(get_agent_topic) + uci -q set obuspa.$dhcp_mtp.Port="" + uci -q set obuspa.$dhcp_mtp.EnableEncryption="" + uci -q set obuspa.$dhcp_mtp.Protocol='MQTT' + uci -q set obuspa.$dhcp_mtp.ResponseTopicConfigured="${agent_topic}" + uci -q set obuspa.$dhcp_mtp.mqtt="${dhcp_mqtt}" + + uci_change=1 + fi + else + if [ "${ct_proto}" == "WebSocket" ]; then + conf_ip="$(uci -q get obuspa.$dhcp_controller.Host)" + conf_port="$(uci -q get obuspa.$dhcp_mtp.Port)" + conf_encr="$(uci -q get obuspa.$dhcp_mtp.EnableEncryption)" + + if [ -n "${ip}" ] && [ "${conf_ip}" != "${ip}" ]; then + uci -q set obuspa.$dhcp_controller.Host="${ip}" + uci_change=1 + fi + + if [ -n "${port}" ] && [ "${conf_port}" != "${port}" ]; then + uci -q set obuspa.$dhcp_mtp.Port="${port}" + uci -q set obuspa.$dhcp_controller.Port="${port}" + uci_change=1 + fi + + if [ -n "${mtp_encrypt}" ] && [ "${conf_encr}" != "${mtp_encrypt}" ]; then + uci -q set obuspa.$dhcp_mtp.EnableEncryption="${mtp_encrypt}" + uci -q set obuspa.$dhcp_controller.EnableEncryption="${mtp_encrypt}" + uci_change=1 + fi + else + conf_ip="$(uci -q get obuspa.$dhcp_mqtt.BrokerAddress)" + conf_port="$(uci -q get obuspa.$dhcp_mqtt.BrokerPort)" + conf_encr="$(uci -q get obuspa.$dhcp_mqtt.TransportProtocol)" + + if [ -n "${port}" ] && [ "${conf_port}" != "${port}" ]; then + uci -q set obuspa.$dhcp_mqtt.BrokerPort="${port}" + uci_change=1 + fi + + if [ -n "${mtp_encrypt}" ] && [ "${conf_encr}" != "${mtp_encrypt}" ]; then + uci -q set obuspa.$dhcp_mqtt.TransportProtocol="${mtp_encrypt}" + uci_change=1 + fi + + if [ -n "${ip}" ] && [ "${conf_ip}" != "${ip}" ]; then + uci -q set obuspa.$dhcp_mqtt.BrokerAddress="${ip}" + uci_change=1 + fi + fi + fi + else + if [ -n "${dhcp_mtp}" ]; then + uci -q del obuspa.$dhcp_mtp + fi + + if [ -n "${dhcp_mqtt}" ]; then + uci -q del obuspa.$dhcp_mqtt + fi - if [ "${ct_endpoint}" != "${ENDPOINT_ID}" ] || [ "${ct_proto}" != "${offered_proto}" ] || [ "${ct_topic}" != "${topic}" ] || [ "${ct_enable}" != "1" ] || [ "${ct_prov}" != "${PROV_CODE}" ]; then - uci -q del obuspa.dhcpcontroller sec=$(uci -q add obuspa controller) uci -q rename obuspa."${sec}"='dhcpcontroller' + uci -q set obuspa.dhcpcontroller.dhcp_discovered="1" uci -q set obuspa.dhcpcontroller.EndpointID="${ENDPOINT_ID}" uci -q set obuspa.dhcpcontroller.ProvisioningCode="${PROV_CODE}" uci -q set obuspa.dhcpcontroller.Protocol="${offered_proto}" - if [ "${offered_proto}" == "MQTT" ]; then - uci -q set obuspa.dhcpcontroller.Topic="${topic}" - uci -q set obuspa.dhcpcontroller.mqtt='dhcpmqtt' - else - uci -q set obuspa.dhcpcontroller.Path="${topic}" - uci -q set obuspa.dhcpcontroller.Host="${ip}" - uci -q set obuspa.dhcpcontroller.Port="${port}" - if [ "${proto}" == "wss" ]; then - uci -q set obuspa.dhcpcontroller.EnableEncryption='1' - mtp_encrypt="1" + uci -q set obuspa.dhcpcontroller.assigned_role_name="$(get_access_role)" + uci -q set obuspa.dhcpcontroller.Enable='1' + + if [ -n "${offered_proto}" ]; then + if [ "${offered_proto}" == "MQTT" ]; then + uci -q set obuspa.dhcpcontroller.Topic="${topic}" + uci -q set obuspa.dhcpcontroller.mqtt='dhcpmqtt' + + sec=$(uci -q add obuspa mqtt) + uci -q rename obuspa."${sec}"='dhcpmqtt' + uci -q set obuspa.dhcpmqtt.BrokerAddress="${ip}" + uci -q set obuspa.dhcpmqtt.BrokerPort="${port}" + uci -q set obuspa.dhcpmqtt.TransportProtocol="${mtp_encrypt}" + uci -q set obuspa.dhcpmqtt.Enable='1' + uci -q set obuspa.dhcpmqtt.ProtocolVersion='5.0' + + agent_topic=$(get_agent_topic) + sec=$(uci -q add obuspa mtp) + uci -q rename obuspa."${sec}"='dhcpmtp' + uci -q set obuspa.dhcpmtp.Protocol='MQTT' + uci -q set obuspa.dhcpmtp.ResponseTopicConfigured="${agent_topic}" + uci -q set obuspa.dhcpmtp.Enable='1' + uci -q set obuspa.dhcpmtp.mqtt='dhcpmqtt' else - uci -q set obuspa.dhcpcontroller.EnableEncryption='0' - mtp_encrypt="0" + uci -q set obuspa.dhcpcontroller.Path="${topic}" + uci -q set obuspa.dhcpcontroller.Host="${ip}" + uci -q set obuspa.dhcpcontroller.Port="${port}" + uci -q set obuspa.dhcpcontroller.EnableEncryption="${mtp_encrypt}" + + sec=$(uci -q add obuspa mtp) + uci -q rename obuspa."${sec}"='dhcpmtp' + + uci -q set obuspa.dhcpmtp.Protocol='WebSocket' + uci -q set obuspa.dhcpmtp.Port="${port}" + uci -q set obuspa.dhcpmtp.Enable='1' + uci -q set obuspa.dhcpmtp.EnableEncryption="${mtp_encrypt}" fi fi - uci -q set obuspa.dhcpcontroller.assigned_role_name="$(get_access_role)" - uci -q set obuspa.dhcpcontroller.Enable='1' uci_change=1 fi - if [ "${offered_proto}" == "WebSocket" ]; then - ex_mqtt=$(uci -q get obuspa.dhcpmqtt) - if [ -n "${ex_mqtt}" ]; then - uci -q del obuspa.dhcpmqtt - uci_change=1 - fi - - ## Handling of mtp section - ct_proto=$(uci -q get obuspa.dhcpmtp.Protocol) - ct_port=$(uci -q get obuspa.dhcpmtp.Port) - ct_enable=$(uci -q get obuspa.dhcpmtp.Enable) - ct_encrypt=$(uci -q get obuspa.dhcpmtp.EnableEncryption) - - if [ "${ct_proto}" != "WebSocket" ] || [ "${ct_port}" != "${port}" ] || [ "${ct_enable}" != "1" ] || [ "${ct_encrypt}" != "${mtp_encrypt}" ]; then - uci -q del obuspa.dhcpmtp - sec=$(uci -q add obuspa mtp) - uci -q rename obuspa."${sec}"='dhcpmtp' - uci -q set obuspa.dhcpmtp.Protocol='WebSocket' - uci -q set obuspa.dhcpmtp.Port="${port}" - uci -q set obuspa.dhcpmtp.Enable='1' - uci -q set obuspa.dhcpmtp.EnableEncryption="${mtp_encrypt}" - uci_change=1 - fi - else - if [ "${proto}" == "mqtt" ]; then - transport_proto="TCP/IP" - else - transport_proto="TLS" - fi - - ## Handling of mqtt section - ct_address=$(uci -q get obuspa.dhcpmqtt.BrokerAddress) - ct_port=$(uci -q get obuspa.dhcpmqtt.BrokerPort) - ct_proto=$(uci -q get obuspa.dhcpmqtt.TransportProtocol) - ct_enable=$(uci -q get obuspa.dhcpmqtt.Enable) - ct_ver=$(uci -q get obuspa.dhcpmqtt.ProtocolVersion) - - if [ "${ct_address}" != "${ip}" ] || [ "${ct_port}" != "${port}" ] || [ "${ct_proto}" != "${transport_proto}" ] || [ "${ct_enable}" != "1" ] || [ "${ct_ver}" != "5.0" ]; then - uci -q del obuspa.dhcpmqtt - sec=$(uci -q add obuspa mqtt) - uci -q rename obuspa."${sec}"='dhcpmqtt' - uci -q set obuspa.dhcpmqtt.BrokerAddress="${ip}" - uci -q set obuspa.dhcpmqtt.BrokerPort="${port}" - uci -q set obuspa.dhcpmqtt.TransportProtocol="${transport_proto}" - uci -q set obuspa.dhcpmqtt.Enable='1' - uci -q set obuspa.dhcpmqtt.ProtocolVersion='5.0' - uci_change=1 - fi - - ## Handling of mtp section - ct_proto=$(uci -q get obuspa.dhcpmtp.Protocol) - ct_topic=$(uci -q get obuspa.dhcpmtp.ResponseTopicConfigured) - ct_enable=$(uci -q get obuspa.dhcpmtp.Enable) - - config_load obuspa - config_get AgentEndpointID localagent EndpointID "" - if [ -z "${AgentEndpointID}" ]; then - serial=$(get_serial_from_db) - oui=$(get_oui_from_db) - AgentEndpointID=$(echo "${oui}-${serial//+/%2B}") - fi - - topic_base=$(echo "${AgentEndpointID}" | sed -E 's/[^[:alnum:]]/_/g') - agent_topic="/usp/${topic_base}/endpoint" - - if [ "${ct_proto}" != "MQTT" ] || [ "${ct_topic}" != "${agent_topic}" ] || [ "${ct_enable}" != "1" ]; then - uci -q del obuspa.dhcpmtp - sec=$(uci -q add obuspa mtp) - uci -q rename obuspa."${sec}"='dhcpmtp' - uci -q set obuspa.dhcpmtp.Protocol='MQTT' - uci -q set obuspa.dhcpmtp.ResponseTopicConfigured="${agent_topic}" - uci -q set obuspa.dhcpmtp.Enable='1' - uci -q set obuspa.dhcpmtp.mqtt='dhcpmqtt' - uci_change=1 - fi - fi - if [ ${uci_change} -eq 1 ]; then log "# Reloading obuspa as dhcp config changed" ubus call uci commit '{"config":"obuspa"}'