What's new

Reversing the web node reboot feature

  • SNBForums Code of Conduct

    SNBForums is a community for everyone, no matter what their level of experience.

    Please be tolerant and patient of others, especially newcomers. We are all here to share and learn!

    The rules are simple: Be patient, be nice, be helpful or be gone!

cyruz

Occasional Visitor
Hi guys,

for scripting reasons (Apple Shortcuts to be honest), I needed to restart a mesh node from the main, but I did not want to rely on cascading SSH connections.

I tried to understand how the reboot from the web page works and these are my findings:

The reboot event triggered by the click brought me to the httpApi.nvramSet call:

Code:
httpApi.nvramSet({
"device_list" : (specific_node_data.mac).toUpperCase(),
"action_mode": "device_reboot"
});

Searching for the action mode device_reboot in the Merlin repo, I didn't get any significant result. Strange, because after reading some code related to the http daemon, I found that there is a reference to this in the asuswrt-merlin.ng/release/src/router/httpd/web.c :

Code:
if (!strcmp(action_mode, "device_reboot")) {
    event_id = EID_HTTPD_REBOOT;
} else if (!strcmp(action_mode, "re_reconnect")) {
    event_id = EID_HTTPD_RE_RECONNECT;
} else if (!strcmp(action_mode, "force_roaming")) {
    if (client_mac) {
        event_id = EID_HTTPD_FORCE_ROAMING;
        strlcat(data, "{", sizeof(data));
        memset(value, 0, sizeof(value));
        snprintf(value, sizeof(value), "\"%s\":\"%s\"", STA, client_mac);
        strlcat(data, value, sizeof(data));
        if (block_time) {
            memset(value, 0, sizeof(value));
            snprintf(value, sizeof(value), ",\"%s\":\"%s\"", BLOCK_TIME, block_time);
            strlcat(data, value, sizeof(data));
        }

        if (target_ap) {
            memset(value, 0, sizeof(value));
            snprintf(value, sizeof(value), ",\"%s\":\"%s\"", TARGET_AP, target_ap);
            strlcat(data, value, sizeof(data));
        }
        strlcat(data, "}", sizeof(data));
    }
    else
        dbg("no client mac\n");
}
else
    dbg("can't find event id\n");

if (event_id > 0) {
    if (strlen(data) == 0)
        strlcpy(data, "{}", sizeof(data));

    snprintf(event_msg, sizeof(event_msg), HTTPD_ACTION_MSG,
        event_id, mac_list, data);
    send_cfgmnt_event(event_msg);
}

So the string HTTPD_ACTION_MSG is formatted with an event id, a mac address list and some arbitrary empty data.
Found the definitions in asuswrt-merlin.ng/release/src/router/cfg_mnt/cfg_event.h:

Code:
#ifndef __CFG_EVENT_H__
#define __CFG_EVENT_H__

#define WEVENT_PREFIX	"wevent"
#define HTTPD_PREFIX	"httpd"
#define RC_PREFIX		"rc"
#define ETHEVENT_PREFIX	"ethevent"
#define EVENT_ID	"eid"
#define MAC_ADDR	"mac_addr"
#define IF_NAME		"if_name"
#define SLAVE_MAC	"slave_mac"
#define LOGIN_IP		"login_ip"
#define OB_STATUS	"ob_status"
#define OB_KEY	"ob_key"
#define RE_MAC		"re_mac"
#define NEW_RE_MAC	"new_re_mac"
#define VSIE		"vsie"
#define ASUS_OUI	"F832E4"
#define CONFIG	"config"
#define E_MODEL_NAME	"model_name"
#define E_ETHER_LIST	"ether_list"
#define E_OB_PATH	"ob_path"
#define MAC_LIST	"mac_list"
#define DATA		"data"
#define STA		"sta"
#define BLOCK_TIME	"block_time"
#define TARGET_AP	"target_ap"
#define ROUTERBOOST_PREFIX "routerboost"
#define PRI_MAC_ADDR "pri_mac"
#define SLV_MAC_ADDR "slv_mac"
#ifdef RTCONFIG_AMAS_CENTRAL_OPTMZ
#define BAND_INDEX	"band_index"
#endif
#ifdef RTCONFIG_AMAS_CENTRAL_ADS
#define SEQUENCE	"seq"
#endif
#define WEVENT_GENERIC_MSG	 "{\""WEVENT_PREFIX"\":{\""EVENT_ID"\":\"%d\"}}"
#define WEVENT_MAC_IFNAME_MSG	 "{\""WEVENT_PREFIX"\":{\""EVENT_ID"\":\"%d\",\""MAC_ADDR"\":\"%s\",\""IF_NAME"\":\"%s\"}}"
#define WEVENT_VSIE_MSG	 "{\""WEVENT_PREFIX"\":{\""EVENT_ID"\":\"%d\",\""VSIE"\":\"%s\"}}"
#define HTTPD_GENERIC_MSG	 "{\""HTTPD_PREFIX"\":{\""EVENT_ID"\":\"%d\"}}"
#define HTTPD_SLAVE_MSG	"{\""HTTPD_PREFIX"\":{\""EVENT_ID"\":\"%d\",\""SLAVE_MAC"\":\"%s\"}}"
#define HTTPD_IP_MSG	"{\""HTTPD_PREFIX"\":{\""EVENT_ID"\":\"%d\",\""LOGIN_IP"\":\"%s\"}}"
#define HTTPD_OB_AVAILABLE_MSG	"{\""HTTPD_PREFIX"\":{\""EVENT_ID"\":\"%d\",\""OB_STATUS"\":%d}}"
#define HTTPD_OB_LOCK_MSG	"{\""HTTPD_PREFIX"\":{\""EVENT_ID"\":\"%d\",\""OB_STATUS"\":%d,\""RE_MAC"\":\"%s\",\""NEW_RE_MAC"\":\"%s\"}}"
#define HTTPD_OB_SELECTION_MSG	"{\""HTTPD_PREFIX"\":{\""EVENT_ID"\":\"%d\",\""OB_STATUS"\":%d,\""NEW_RE_MAC"\":\"%s\",\""E_OB_PATH"\":%d}}"
#define HTTPD_CONFIG_CHANGED_MSG	"{\""HTTPD_PREFIX"\":{\""EVENT_ID"\":\"%d\",\""RE_MAC"\":\"%s\",\""CONFIG"\":%s}}"
#define HTTPD_REBOOT_MSG	"{\""HTTPD_PREFIX"\":{\""EVENT_ID"\":\"%d\",\""MAC_LIST"\":%s}}"
#define HTTPD_ACTION_MSG	"{\""HTTPD_PREFIX"\":{\""EVENT_ID"\":\"%d\",\""MAC_LIST"\":%s,\""DATA"\":%s}}"
#define RC_GENERIC_MSG	 	"{\""RC_PREFIX"\":{\""EVENT_ID"\":\"%d\"}}"
#define RC_CONFIG_CHANGED_MSG	"{\""RC_PREFIX"\":{\""EVENT_ID"\":\"%d\",\""CONFIG"\":%s}}"
#ifdef RTCONFIG_AMAS_CENTRAL_OPTMZ
#define RC_OPT_SS_RESULT_MSG	"{\""RC_PREFIX"\":{\""EVENT_ID"\":\"%d\",\""BAND_INDEX"\":%d}}"
#endif
#define ETHEVENT_PROBE_MSG	 "{\""ETHEVENT_PREFIX"\":{\""EVENT_ID"\":\"%d\",\""E_ETHER_LIST"\":%s}}"
#define ETHEVENT_STATUS_MSG	 "{\""ETHEVENT_PREFIX"\":{\""EVENT_ID"\":\"%d\",\""OB_STATUS"\":%d,\""OB_KEY"\":\"%s\"}}"
#define ROUTERBOOST_STATUS_MSG	 "{\""ROUTERBOOST_PREFIX"\":{\""EVENT_ID"\":\"%d\",\""PRI_MAC_ADDR"\":\"%s\",\""SLV_MAC_ADDR"\":\"%s\"}}"
#ifdef RTCONFIG_AMAS_CENTRAL_ADS
#define RC_ADS_DS_MSG	"{\""RC_PREFIX"\":{\""EVENT_ID"\":\"%d\",\""SEQUENCE"\":%d}}"
#endif

/* source */
#define FROM_NONE	0x0
#define FROM_WIRELESS	0x1
#define FROM_ETHERNET	0x2

enum httpdEventType {
	EID_HTTPD_NONE = 0,
	EID_HTTPD_FW_CHECK = 1,
	EID_HTTPD_FW_UPGRADE,
	EID_HTTPD_REMOVE_SLAVE,
	EID_HTTPD_RESET_DEFAULT,
	EID_HTTPD_ONBOARDING,
	EID_HTTPD_CONFIG_CHANGED,
	EID_HTTPD_START_WPS,
#ifdef RTCONFIG_BHCOST_OPT
	EID_HTTPD_SELF_OPTIMIZE,
#endif
	EID_HTTPD_REBOOT,
	EID_HTTPD_RE_RECONNECT,
	EID_HTTPD_FORCE_ROAMING,
	EID_HTTPD_MAX
};

enum wEventType {
	EID_WEVENT_DEVICE_CONNECTED = 1,
	EID_WEVENT_DEVICE_DISCONNECTED,
	EID_WEVENT_DEVICE_PROBE_REQ,
	EID_WEVENT_DEVICE_RADAR_DETECTED
};

enum ethEventType {
	EID_ETHEVENT_DEVICE_PROBE_REQ = 1,
	EID_ETHEVENT_ONBOARDING_STATUS
};

enum rcEventType {
	EID_RC_WPS_STOP = 1,
	EID_RC_REPORT_PATH,
	EID_RC_GET_TOPOLOGY,
	EID_RC_FEEDBACK,
	EID_RC_RESTART_WIRELESS,
	EID_RC_CONFIG_CHANGED,
	EID_RC_OPT_SS_RESULT,
	EID_RC_OPT_NOTIFY,
#ifdef RTCONFIG_AMAS_CENTRAL_ADS
	EID_RC_REPORT_DS_RESULT,
	EID_RC_REPORT_DS_SWITCH_STA_DISCONN,
#endif
	EID_RC_MAX
};

enum rbEventType {
	EID_RB_STA_CONN = 1,
	EID_RB_STA_DISCONN
};

#endif /* __CFG_EVENT_H__ */
/* End of cfg_event.h */

The EID_HTTPD_REBOOT is part of the httpdEventType enumeration, so the value could be 8 or 9 depending on the definition of RTCONFIG_BHCOST_OPT. I did not investigate this much and went straight to testing with 9.

The final string I came up with, is:

"{\"httpd\":{\"eid\":\"9\",\"mac_list\":[\"xx:xx:xx:xx:xx:xx\"],\"data\":\"{}\"}}"

Sadly all the code related to this cfgmnt is prebuilt, so there is only a definition for the send_cfgmnt_event(event_msg) function in asuswrt-merlin.ng/release/src/router/cfg_mnt/cfg_lib.h :

Code:
extern int send_cfgmnt_event(char *msg);

I found that these binaries are running in the system. More specifically cfg_server is listening on TCP, UDP and UNIX sockets. I tried to send that string to the UNIX socket /var/run/cfgmnt_ipc_socket and it worked.

It would be nice if any of you could try to replicate the same test, and check if it's working or not.

To be precise, you need to install socat (the version already installed does not allow connections to Unix sockets) and pipe that string to it:

Code:
opkg update
opkg install socat
echo "{\"httpd\":{\"eid\":\"9\",\"mac_list\":[\"xx:xx:xx:xx:xx:xx\"],\"data\":\"{}\"}}" | /opt/bin/socat - unix-connect:/var/run/cfgmnt_ipc_socket
 
Last edited:

Latest threads

Support SNBForums w/ Amazon

If you'd like to support SNBForums, just use this link and buy anything on Amazon. Thanks!

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!
Top