/* DESC: This script will execute commands received by SMS. * Copyright (C) 2012 NetModule AG, Switzerland * * sms-commands: * <reboot>: reboot netmodule router * <connect>: configure wanlink 0 permanent * <disconnect>: configure wanlink 0 disable * <status>: get system status summary * <output [1|2] [on|off]> set dio n on or off */ INTERVAL = 10; /* only run every 10 seconds */ MAXMSG = 5; /* process max. 5 msgs */ MAXAGE = 300; /* message mustn't be older than 5 mins */ MAXLINES = 32; /* max. number of lines in msg (incl. header) */ AUTH = 1; /* perform authentication */ ADMPWD = ""; /* password used for authentication */ IGNORECASE = 1; /* ignore upper-/lower-case */ SENDERS = mkarray(/* "+123456789" */); /* allowed senders */ /* check if we should perform authentication */ if (argc == 2 && argv[1] == "noauth") { AUTH = 0; } /* retrieve password */ if (AUTH) { if (strlen(ADMPWD) == 0) { /* use configured admin password */ ADMPWD = nb_config_get("admin.password"); if (strlen(ADMPWD) > 0) { nb_syslog("using admin password for authentication"); } else { /* not there -> use a default password instead */ nb_syslog("using default password for authentication"); ADMPWD = "admin01"; } } if (IGNORECASE) ADMPWD = tolower(ADMPWD); } /* split a message into an array */ array split(string msg) { args=mkarray(); pos=strchr(msg, "\r"); if(pos==0) msg=""; if(pos>0) msg=left(msg, pos); pos=strchr(msg, "\n"); if(pos==0) msg=""; if(pos>0) msg=left(msg, pos); for(n=0;;) { pos=strchr(msg, " "); if(is_void(pos)) pos=strchr(msg, "\t"); if(is_void(pos)) pos=strchr(msg, "\f"); if(pos==0) { msg=trim(msg); } else if(pos>0) { args[n++]=trim(left(msg, pos)); msg=trim(substr(msg, pos)); } else { if(msg!="") args[n++]=trim(msg); break; } } return args; } /* parse message */ array parse (string msg) { /* read by line */ lnr = 0; ishdr = 1; tlnr = 0; allowed = (length(SENDERS) == 0) ? 1 : 0; lp = msg; for (lnr = 0; lnr < MAXLINES && strlen(lp) > 0; lnr++) { pos = strchr(lp, "\n"); if (is_void(pos)) pos = strlen(lp); line = left(lp, pos); lp = substr(lp, pos + 1); if (strlen(line) == 0) { /* saw header separator */ ishdr = 0; continue; } if (ishdr) { /* saw header line */ if (left(line, 5) == "Sent:") { /* check age of message */ sentdate = trim(substr(line, 5)); sent = strptime(sentdate, "%Y-%m-%d %H:%M:%S"); if (!is_void(sent)) { /* got a valid sent date */ now = localtime(time()); age = mktime(now) - mktime(sent); nb_syslog("message has been sent %ds ago", age); if (age > MAXAGE) { nb_syslog("rejecting too old message"); return mkarray(); } } else { nb_syslog("time check has been omitted"); } } else if (left(line, 5) == "From:") { from = substr(line, 6); if (length(SENDERS) > 0) { for (s = 0; s < length(SENDERS); s++) { sender = SENDERS[s]; if (left(from, strlen(sender)) == sender) { allowed = 1; break; } } } if (allowed == 0) { nb_syslog("rejecting message from unknown sender %s", from); return mkarray(); } else { nb_syslog("sender %s can pass", from); } } } else { /* saw text line */ if (IGNORECASE) line = tolower(line); if (AUTH && tlnr == 0) { /* first line of message must contain the password */ if (left(line, strlen(ADMPWD)) != ADMPWD) { nb_syslog("authentication failed"); return mkarray(); } else { nb_syslog("authentication succeeded"); } } else if ((AUTH && tlnr == 1) || (!AUTH && tlnr == 0)) { /* this line must contain the command */ return split(line); } else { break; } tlnr++; } } nb_syslog("no command detected"); return mkarray(); } int setdio (string port, string newstate) { if (port != "1" && port != "2") { nb_syslog("invalid DIO port %s\n", port); return -1; } if (newstate == "on") { st = 1; } else if (newstate == "off") { st = 0; } else { nb_syslog("invalid new DIO state %s\n", newstate); return -1; } rc = nb_dio_set(sprintf("out%s", port), st); if (rc) { nb_syslog("Unable to set state %s for DIO output port %s\n", newstate, port); return -1; } else { nb_syslog("Setting state %s for DIO output port %s\n", newstate, port); return 0; } } /* check if we got stressed */ LASTFILE = "/tmp/sms-control.last"; last = 0; fp = fopen(LASTFILE, "r"); if (fp) { /* we have been run at least one time */ str = fread(fp, 32); if (str) last = (int) str; fclose(fp); } now = mktime(localtime(time())); elapsed = now - last; if (elapsed > 0 && elapsed < INTERVAL) { nb_syslog("we have ben run %d seconds ago. skipping.", elapsed); exit(0); } /* record timestamp */ fp = fopen(LASTFILE, "w+"); if (fp) { str = sprintf("%d", now); fwrite(fp, str); fclose(fp); } /* read inbox */ msgs = nb_sms_list(); nr_msgs = length(msgs); if (nr_msgs == 0) { nb_syslog("there are no messages in your inbox"); exit(0); } nb_syslog("you have %d message(s) in your inbox", nr_msgs); /* track states */ reboot = 0; /* only process latest messages */ start = nr_msgs - MAXMSG; if (start < 0) start = 0; for (i=start; i<nr_msgs; i++) { msg = nb_sms_retrieve(msgs[i]); if (!msg) continue; nb_syslog("processing message %d of %d (ID %s)", i, nr_msgs, msgs[i]); args = parse(msg); if ((is_array(args)) && (length(args) > 0)) { if (args[0] == "") { nb_syslog("no command"); } else if ((args[0] == "reboot") && (length(args) == 1)) { nb_syslog("reboot command received"); reboot = 1; } else if ((args[0] == "connect") && (length(args) == 1)) { nb_syslog("connect command received"); if (nb_config_get("wanlink.0.mode") == "1") { nb_syslog("already connecting"); } else { /* enable first wanlink */ nb_config_set("wanlink.0.mode=1"); } } else if ((args[0] == "disconnect") && (length(args) == 1)) { nb_syslog("disconnect command received"); if (nb_config_get("wanlink.0.mode") == "0") { nb_syslog("already disconnecting"); } else { /* disable first wanlink */ nb_config_set("wanlink.0.mode=0"); } } else if ((args[0] == "status") && (length(args) == 1)) { nb_syslog("status command received"); rcpt = nb_sms_header(msgs[i], "From"); if (rcpt) { id = nb_sms_send(rcpt, nb_status_summary()); if (!id) { nb_syslog("unable to send status message to %s", rcpt); } else { nb_syslog("successfully queued status message to %s (ID %s)", rcpt, id); } } } else if ((args[0] == "output") && (length(args) == 3)) { nb_syslog("dio out command received"); setdio(args[1], args[2]); } else { nb_syslog("command <%s> not supported", msg); } } else { nb_syslog("ignoring invalid message"); } /* delete message */ ret = nb_sms_delete(msgs[i]); if (ret == 0) nb_syslog("deleted message %s", msgs[i]); } if (reboot == 1) { /* trigger reboot */ nb_syslog("rebooting system"); nb_reboot(); } exit(0);