{"id":2456,"date":"2021-07-12T17:22:08","date_gmt":"2021-07-13T01:22:08","guid":{"rendered":"http:\/\/wonghoi.humgar.com\/blog\/?p=2456"},"modified":"2021-07-12T17:22:53","modified_gmt":"2021-07-13T01:22:53","slug":"asus-wrt-merlin-firmware-ddns-update-interval-hack","status":"publish","type":"post","link":"https:\/\/wonghoi.humgar.com\/blog\/2021\/07\/12\/asus-wrt-merlin-firmware-ddns-update-interval-hack\/","title":{"rendered":"Asus-wrt Merlin Firmware DDNS update interval hack"},"content":{"rendered":"\n<p>The &#8220;WAN &#8211; DDNS&#8221; page only allows users to set the DDNS updater to check as frequently as every 30 minutes. My DDNS provider does not have an update frequency limit, so I&#8217;d like to have the update client check for every 1 minute.  The setting is called &#8220;Verify every&#8221;:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"845\" height=\"85\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-7.png\" alt=\"\" class=\"wp-image-2457\" srcset=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-7.png 845w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-7-300x30.png 300w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-7-768x77.png 768w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-7-840x85.png 840w\" sizes=\"auto, (max-width: 845px) 100vw, 845px\" \/><\/figure>\n\n\n\n<p>Attempting to set it to every 1 minute gives this error message:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"642\" height=\"122\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-10.png\" alt=\"\" class=\"wp-image-2460\" srcset=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-10.png 642w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-10-300x57.png 300w\" sizes=\"auto, (max-width: 642px) 100vw, 642px\" \/><\/figure>\n\n\n\n<p>I searched for the &#8220;WAN-DDNS&#8221; config webpage file (<code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">Advanced_ASUSDDNS_Content.asp<\/code>) in the firmware source code, and found that it&#8217;s under <code>\/www<\/code> folder in the router&#8217;s linux root.<\/p>\n\n\n\n<p>Since &#8220;Verify every&#8221; is such generic words, and Github does not support exact phrase match in search (I use &#8220;<code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">in:file<\/code>&#8221; specifier in the search box), I pick &#8220;WAN IP and hostname verification&#8221; (the closest setting which I expect the code to be in the proximity of the one corresponding to &#8220;Verify every&#8221;) so it has more unique keywords. The first jump:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"446\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-11-1024x446.png\" alt=\"\" class=\"wp-image-2461\" srcset=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-11-1024x446.png 1024w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-11-300x131.png 300w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-11-768x335.png 768w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-11.png 1347w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Since it&#8217;s just a dictionary files, we search for the associated internal variable name <br>&#8220;<code>DDNS_verification_enable<\/code>&#8221; which points to the this line in <code>Advanced_ASUSDDNS_Content.asp<\/code>:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"227\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-12-1024x227.png\" alt=\"\" class=\"wp-image-2462\" srcset=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-12-1024x227.png 1024w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-12-300x67.png 300w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-12-768x170.png 768w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-12.png 1357w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Since this name appeared nowhere else, I traced the &#8220;<code>id<\/code>&#8221; attribute above, which is &#8220;<code>check_ddns_field<\/code>&#8221; and I see a Javascript (.js) <a href=\"https:\/\/github.com\/RMerl\/asuswrt-merlin\/blob\/263449f32bf292fb6bc5a08cd645e61a7fb10485\/release\/src\/router\/www\/general.js\" target=\"_blank\" rel=\"noreferrer noopener\">file<\/a> that process the data from the web page forms:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"367\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-13-1024x367.png\" alt=\"\" class=\"wp-image-2463\" srcset=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-13-1024x367.png 1024w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-13-300x107.png 300w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-13-768x275.png 768w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-13.png 1363w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>The variable <code>check_ddns_field<\/code> appears in the if-else-if branches of change_ddns_settings(), so one of the few next few variables after it is likely to correspond to &#8220;Verify with&#8221;. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"518\" height=\"1024\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-17-518x1024.png\" alt=\"\" class=\"wp-image-2467\" srcset=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-17-518x1024.png 518w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-17-152x300.png 152w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-17-768x1518.png 768w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-17-777x1536.png 777w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-17.png 940w\" sizes=\"auto, (max-width: 518px) 100vw, 518px\" \/><\/figure>\n\n\n\n<p>The variable name showed up in 4 branches of <code>if-elseif-else<\/code> switches (switching DDNS service providers), which <code>ddns_regular_period<\/code> comes right after<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"503\" height=\"60\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-18.png\" alt=\"\" class=\"wp-image-2468\" srcset=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-18.png 503w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-18-300x36.png 300w\" sizes=\"auto, (max-width: 503px) 100vw, 503px\" \/><\/figure>\n\n\n\n<p>Searching for the class member (or struct field) <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"246\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-19-1024x246.png\" alt=\"\" class=\"wp-image-2469\" srcset=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-19-1024x246.png 1024w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-19-300x72.png 300w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-19-768x184.png 768w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-19.png 1109w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Bingo. Here&#8217;s the entry value range check code. I&#8217;ll change the &#8220;30&#8221; minutes to &#8220;1&#8221; minute to enable checking at 1 minute intervals (which I think it&#8217;s reasonably responsive for testing and general use).<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>I&#8217;d prefer to check if the input range check is there out of feasibility (i.e. what is the smallest increment) or it&#8217;s just set to prevent people from getting banned by the DDNS provider for checking too frequently. I looked into the last occurrence of <code>ddns_regular_period<\/code> and found this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"104\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-21-1024x104.png\" alt=\"\" class=\"wp-image-2471\" srcset=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-21-1024x104.png 1024w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-21-300x30.png 300w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-21-768x78.png 768w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-21-1536x155.png 1536w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-21.png 1552w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Which means the web forms is updating NVRAM (environmental) variable of the same name <code>ddns_regular_period<\/code>, which appears to be called only in <a href=\"https:\/\/github.com\/RMerl\/asuswrt-merlin\/blob\/263449f32bf292fb6bc5a08cd645e61a7fb10485\/release\/src\/router\/rc\/watchdog.c\">watchdog.c<\/a>:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"139\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-23-1024x139.png\" alt=\"\" class=\"wp-image-2473\" srcset=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-23-1024x139.png 1024w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-23-300x41.png 300w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-23-768x104.png 768w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-23.png 1365w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>And Dang! The code enforces if the ddns_regular_period (on NVRAM) is set to be less than the original 30 minute minimum (invalid condition), it&#8217;d be set to the default 60 minutes (1 hr). <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"326\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-24-1024x326.png\" alt=\"\" class=\"wp-image-2474\" srcset=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-24-1024x326.png 1024w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-24-300x96.png 300w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-24-768x245.png 768w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-24.png 1249w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>It&#8217;s actually sloppy coding because the defaults are specified in struct fields in <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">defaults.c<\/code>:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"189\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-25-1024x189.png\" alt=\"\" class=\"wp-image-2475\" srcset=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-25-1024x189.png 1024w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-25-300x55.png 300w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-25-768x141.png 768w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-25.png 1396w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>yet that 60 minutes is hard-coded in <code>watchdog.c<\/code>. That means if I don&#8217;t catch it and only changed the default in one place, the behavior will not be what I expected given the right conditions. This is an example of why software feature expansion are likely to break things. If you have solid code, bugs on updates are likely to happen.<\/p>\n\n\n\n<p>I was curious why it says <code>(period*2)<\/code><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"449\" height=\"39\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-26.png\" alt=\"\" class=\"wp-image-2476\" srcset=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-26.png 449w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-26-300x26.png 300w\" sizes=\"auto, (max-width: 449px) 100vw, 449px\" \/><\/figure>\n\n\n\n<p>and suspected the <code>ddns_check_count<\/code> is incremented in 30 second (half-minute) interval. Since it&#8217;s <code>watchdog.c<\/code>, my natural guess is that the watchdog checks every 30 seconds for these event hooks. Turns out the notes (comments) in the code has &#8220;30 seconds periods&#8221; noted everywhere.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"857\" height=\"1024\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-27-857x1024.png\" alt=\"\" class=\"wp-image-2477\" srcset=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-27-857x1024.png 857w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-27-251x300.png 251w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-27-768x917.png 768w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-27.png 1055w\" sizes=\"auto, (max-width: 857px) 100vw, 857px\" \/><\/figure>\n\n\n\n<p>I searched a little bit more about linux watchdogs and found this useful <a rel=\"noreferrer noopener\" href=\"https:\/\/www.jann.cc\/2013\/02\/02\/linux_watchdog.html\" target=\"_blank\">webpage<\/a> which explained how it works. I didn&#8217;t see <code>\/dev\/watchdog<\/code> in my router&#8217;s <code>rootfs<\/code> (root file system) so I assumed it&#8217;s a hardware watchdog (embedded linux, so duh). <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"977\" height=\"856\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-28.png\" alt=\"\" class=\"wp-image-2478\" srcset=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-28.png 977w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-28-300x263.png 300w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-28-768x673.png 768w\" sizes=\"auto, (max-width: 977px) 100vw, 977px\" \/><\/figure>\n\n\n\n<p>I was about to dig up the hardware manual for the chipset for my router, but I search for they string <em>HW_RTC_WATCHDOG&nbsp;<\/em> first and it showed up in linux kernel code (duh):<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"759\" height=\"1024\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-29-759x1024.png\" alt=\"\" class=\"wp-image-2479\" srcset=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-29-759x1024.png 759w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-29-222x300.png 222w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-29-768x1037.png 768w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-29-1138x1536.png 1138w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-29.png 1287w\" sizes=\"auto, (max-width: 759px) 100vw, 759px\" \/><\/figure>\n\n\n\n<p>Note that the <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">HW_RTC_WATCHDOG <\/code>is a register in this code base, not the number of seconds from <a rel=\"noreferrer noopener\" href=\"https:\/\/www.jann.cc\/2013\/02\/02\/linux_watchdog.html\" target=\"_blank\">Christian&#8217;s Blog<\/a>. i.e. they are completely different things, but it provided a good keyword lead for me to start digging.<\/p>\n\n\n\n<p>The code seems to be the same for various kernel version so I picked any one of them to understand the behavior. First occurrence is in <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">wdt_enable()<\/code>:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"357\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-30-1024x357.png\" alt=\"\" class=\"wp-image-2480\" srcset=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-30-1024x357.png 1024w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-30-300x104.png 300w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-30-768x267.png 768w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-30.png 1057w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>The other places are suspend\/resume, so I&#8217;ll ignore those for now. Note that <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">wdt_enable()<\/code> is a static function, so only need to search within the same file. The only active place that calls it is <code>wdt_ping()<\/code>:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"761\" height=\"146\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-31.png\" alt=\"\" class=\"wp-image-2481\" srcset=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-31.png 761w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-31-300x58.png 300w\" sizes=\"auto, (max-width: 761px) 100vw, 761px\" \/><\/figure>\n\n\n\n<p>So there are only 2 things I&#8217;ll need to find out: <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">heartbeat <\/code>and <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">WDOG_COUNTER_RATE<\/code>:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"794\" height=\"231\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-32.png\" alt=\"\" class=\"wp-image-2482\" srcset=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-32.png 794w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-32-300x87.png 300w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2021\/04\/image-32-768x223.png 768w\" sizes=\"auto, (max-width: 794px) 100vw, 794px\" \/><\/figure>\n\n\n\n<p>&#8230;. unfinished<\/p>\n\n\n\n<p><a href=\"https:\/\/bitsum.com\/firmware_mod_kit.htm\">https:\/\/bitsum.com\/firmware_mod_kit.htm<\/a><\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>While it&#8217;s a lot of useful learning about Embedded Linux and hunting down source code, for the meantime, given that namecheap does not care if you blindly update every minute, it&#8217;s easier to just set up a cron job that runs at every N minutes using curl\/wget.<\/p>\n\n\n\n<p>dd-wrt has a place for you to enter the cron scripts with the web interface, but you might need to log into the router using SSH and <a href=\"https:\/\/www.cyberciti.biz\/faq\/how-to-add-cron-job-on-asuswrt-merlin-wifi-router\/\">register the cron job yourself<\/a>:<\/p>\n\n\n\n<p>The core command is called &#8216;<code>cru<\/code>&#8216;, which typing it in the command prompt will show you the very simple usage:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\nadmin@Router:\/tmp\/home\/root# cru\n\nCron Utility\nadd:    cru a &lt;unique id> &lt;\"min hour day month week command\">\ndelete: cru d &lt;unique id>\nlist:   cru l<\/code><\/pre>\n\n\n\n<p><code>&lt;unique id><\/code> is just a tag that you make up to name your task. Again the one-liner command needs to be direct absolute path. My &#8216;<code>curl<\/code>&#8216; program is located in <code>\/usr\/sbin<\/code>, so the command is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cru a ncddns * * * * * \/usr\/sbin\/curl \"https:\/\/dynamicdns.park-your-domain.com\/update?host={subdomain or @ for root}&amp;domain={registered domain name}&amp;password={DDNS-specific password generated by namecheap's domain administration page under Advanced DNS}\"<\/code><\/pre>\n\n\n\n<p>The &#8220;<code>* * * * *<\/code>&#8221; refers to run at every &#8220;minute, hour, date of month, month, date of week&#8221;, in other words, run at every minute in every waking moment. The wild card * means ALL-OF.<\/p>\n\n\n\n<p>Cron job registration through CRU is not persistent, so to make it survive reboots, add the above cru command as a line to <code>\/jffs\/scripts\/services-start<\/code> script. It should be executable by default, if not, make sure you set it to be executable or it won&#8217;t run.<\/p>\n<div class=\"pvc_clear\"><\/div><p id=\"pvc_stats_2456\" class=\"pvc_stats all  \" data-element-id=\"2456\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> <img loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif\" border=0 \/><\/p><div class=\"pvc_clear\"><\/div>","protected":false},"excerpt":{"rendered":"<p>The &#8220;WAN &#8211; DDNS&#8221; page only allows users to set the DDNS updater to check as frequently as every 30 minutes. My DDNS provider does not have an update frequency limit, so I&#8217;d like to have the update client check &hellip; <a href=\"https:\/\/wonghoi.humgar.com\/blog\/2021\/07\/12\/asus-wrt-merlin-firmware-ddns-update-interval-hack\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n<div class=\"pvc_clear\"><\/div>\n<p id=\"pvc_stats_2456\" class=\"pvc_stats all  \" data-element-id=\"2456\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> <img loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif\" border=0 \/><\/p>\n<div class=\"pvc_clear\"><\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[44,39],"tags":[],"class_list":["post-2456","post","type-post","status-publish","format-standard","hentry","category-hardware","category-linux"],"_links":{"self":[{"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/posts\/2456","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/comments?post=2456"}],"version-history":[{"count":4,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/posts\/2456\/revisions"}],"predecessor-version":[{"id":2636,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/posts\/2456\/revisions\/2636"}],"wp:attachment":[{"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/media?parent=2456"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/categories?post=2456"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/tags?post=2456"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}