4 Copyright (C) 2006-2009 Jonathan Zarate
10 #include <sys/types.h>
13 #include <arpa/inet.h>
16 // #define DLOG(args...) syslog(LOG_DEBUG, args)
17 #define DLOG(fmt, args...) _dprintf(fmt"\n", args)
19 static void update(int num
, int *dirty
, int force
)
23 char *serv
, *user
, *pass
, *host
, *wild
, *mx
, *bmx
, *cust
;
40 DLOG("%s", __FUNCTION__
);
42 sprintf(s
, "ddns%d", num
);
44 DLOG("%s: cru d %s", __FUNCTION__
, s
);
46 sprintf(s
, "ddnsf%d", num
);
48 DLOG("%s: cru d %s", __FUNCTION__
, s
);
50 sprintf(ddnsx
, "ddnsx%d", num
);
51 sprintf(ddnsx_path
, "/var/lib/mdu/%s", ddnsx
);
52 strlcpy(config
, nvram_safe_get(ddnsx
), sizeof(config
));
54 mkdir("/var/lib/mdu", 0700);
55 sprintf(msg_fn
, "%s.msg", ddnsx_path
);
57 if ((vstrsep(config
, "<", &serv
, &user
, &host
, &wild
, &mx
, &bmx
, &cust
) != 7) || (*serv
== 0)) {
58 DLOG("%s: msg=''\n", __FUNCTION__
);
59 f_write(msg_fn
, NULL
, 0, 0, 0);
63 if ((pass
= strchr(user
, ':')) != NULL
) *pass
++ = 0;
66 for (n
= 120; (n
> 0) && (time(0) < Y2K
); --n
) {
70 syslog(LOG_INFO
, "Time not yet set.");
73 if (!wait_action_idle(10)) {
74 DLOG("%s: !wait_action_idle", __FUNCTION__
);
78 sprintf(cache_nv
, "%s_cache", ddnsx
);
80 DLOG("%s: force=1", __FUNCTION__
);
81 nvram_set(cache_nv
, "");
86 strlcpy(ip
, nvram_safe_get("ddnsx_ip"), sizeof(ip
));
89 if ((get_wan_proto() != WP_DISABLED
) || (ip
[0] == 0)) {
90 DLOG("%s: !check_wanup", __FUNCTION__
);
96 if ((strcmp(serv
, "zoneedit") == 0) || (strcmp(serv
, "tzo") == 0) || (strcmp(serv
, "noip") == 0) || (strcmp(serv
, "dnsomatic") == 0)) {
100 strcpy(ip
+ 1, "dyndns");
103 else if (inet_addr(ip
) == -1) {
104 strcpy(ip
, get_wanip());
107 sprintf(cache_fn
, "%s.cache", ddnsx_path
);
108 f_write_string(cache_fn
, nvram_safe_get(cache_nv
), 0, 0);
110 if (!f_exists(msg_fn
)) {
111 DLOG("%s: !f_exist(%s)", __FUNCTION__
, msg_fn
);
112 f_write(msg_fn
, NULL
, 0, 0, 0);
116 sprintf(conf_fn
, "%s.conf", ddnsx_path
);
117 if ((f
= fopen(conf_fn
, "w")) == NULL
) goto CLEANUP
;
118 // note: options not needed for the service are ignored by mdu
145 if (nvram_get_int("debug_ddns")) {
146 fprintf(f
, "dump /tmp/mdu-%s.txt\n", serv
);
151 exitcode
= eval("mdu", "--service", serv
, "--conf", conf_fn
);
152 DLOG("%s: mdu exitcode=%d", __FUNCTION__
, exitcode
);
154 sprintf(s
, "%s_errors", ddnsx
);
155 if ((exitcode
== 1) || (exitcode
== 2)) {
156 if (nvram_match("ddnsx_retry", "0")) goto CLEANUP
;
162 errors
= nvram_get_int(s
) + 1;
163 if (errors
< 1) errors
= 1;
169 sprintf(v
, "%d", errors
);
178 f_read_string(cache_fn
, s
, sizeof(s
));
179 if ((p
= strchr(s
, '\n')) != NULL
) *p
= 0;
180 t
= strtoul(s
, &p
, 10);
181 if (*p
!= ',') goto CLEANUP
;
183 if (!nvram_match(cache_nv
, s
)) {
184 nvram_set(cache_nv
, s
);
185 if (nvram_get_int("ddnsx_save")) {
186 if (strstr(serv
, "dyndns") == 0) *dirty
= 1;
191 if (((p
= nvram_get("ddnsx_refresh")) != NULL
) && (*p
!= 0)) {
195 if ((n
< 0) || (n
> 90)) n
= 28;
196 t
+= (n
* 86400); // refresh every n days
198 //!!TB - fix: if time is in the past, make it current
199 time_t now
= time(0) + (60 * 5);
200 if (t
< now
) t
= now
;
203 sprintf(s
, "ddnsf%d", num
);
204 sprintf(v
, "%d %d %d %d * ddns-update %d force",
205 tm
->tm_min
, tm
->tm_hour
, tm
->tm_mday
, tm
->tm_mon
+ 1, num
);
206 DLOG("%s: cru a %s %s", __FUNCTION__
, s
, v
);
207 eval("cru", "a", s
, v
);
212 DLOG("%s: SCHED", __FUNCTION__
);
216 DLOG("%s: now: %d:%d errors=%d", __FUNCTION__
, tm
->tm_hour
, tm
->tm_min
, errors
);
219 // need at least 10m spacing for checkip
220 // +1m to not trip over mdu's ip caching
221 // +5m for every error
222 n
= (11 + (errors
* 5));
223 if ((exitcode
== 1) || (exitcode
== 2)) {
224 if (exitcode
== 2) n
= 30;
225 sprintf(s
, "\n#RETRY %d %d\n", n
, errors
); // should be localized in basic-ddns.asp
226 f_write_string(msg_fn
, s
, FW_APPEND
, 0);
227 DLOG("%s: msg='retry n=%d errors=%d'", __FUNCTION__
, n
, errors
);
230 t
= time(0) + (n
* 60);
232 DLOG("%s: sch: %d:%d\n", __FUNCTION__
, tm
->tm_hour
, tm
->tm_min
);
234 sprintf(s
, "ddns%d", num
);
235 sprintf(v
, "%d * * * * ddns-update %d", tm
->tm_min
, num
);
236 DLOG("%s: cru a %s %s", __FUNCTION__
, s
, v
);
237 eval("cru", "a", s
, v
);
239 // sprintf(s, "cru a ddns%d \"*/10 * * * * ddns-update %d\"", num);
244 DLOG("%s: CLEANUP", __FUNCTION__
);
245 simple_unlock("ddns");
248 int ddns_update_main(int argc
, char **argv
)
253 DLOG("%s: %s %s", __FUNCTION__
, (argc
>= 2) ? argv
[1] : "", (argc
>= 3) ? argv
[2] : "");
259 update(0, &dirty
, 0);
260 update(1, &dirty
, 0);
262 else if ((argc
== 2) || (argc
== 3)) {
264 if ((num
== 0) || (num
== 1)) {
265 update(num
, &dirty
, (argc
== 3) && (strcmp(argv
[2], "force") == 0));
268 if (dirty
) nvram_commit_x();
272 void start_ddns(void)
274 DLOG("%s", __FUNCTION__
);
279 simple_unlock("ddns");
280 nvram_unset("ddnsx0_errors");
281 nvram_unset("ddnsx1_errors");
283 xstart("ddns-update");
288 DLOG("%s", __FUNCTION__
);
290 eval("cru", "d", "ddns0");
291 eval("cru", "d", "ddns1");
292 eval("cru", "d", "ddnsf0");
293 eval("cru", "d", "ddnsf1");
294 killall("ddns-update", SIGKILL
);
295 killall("mdu", SIGKILL
);