1/* 2 ASUS features: 3 - traffic limiter for wan interface 4 5 Copyright (C) ASUSTek. Computer Inc. 6*/ 7 8#include <rc.h> 9#include <math.h> 10 11#ifdef RTCONFIG_TRAFFIC_LIMITER 12 13#define IFPATH_MAX 64 14 15static int traffic_limiter_is_first = 1; 16 17void traffic_limiter_sendSMS(const char *type, int unit) 18{ 19 char phone[32], message[IFPATH_MAX]; 20 char *at_cmd[] = {"modem_status.sh", "send_sms", phone, message, NULL}; 21 char buf[32]; 22 23 snprintf(buf, sizeof(buf), "tl%d_%s_max", unit, type); 24 snprintf(phone, sizeof(phone), "%s", nvram_safe_get("modem_sms_phone")); 25 26 if (strcmp(type, "alert") == 0) 27 snprintf(message, sizeof(message), "%s %s bytes.", nvram_safe_get("modem_sms_message1"), nvram_safe_get(buf)); 28 else if (strcmp(type, "limit") == 0) 29 snprintf(message, sizeof(message), "%s %s bytes.", nvram_safe_get("modem_sms_message2"), nvram_safe_get(buf)); 30 31#ifdef RTCONFIG_INTERNAL_GOBI 32 stop_lteled(); 33#endif 34 _eval(at_cmd, ">/tmp/modem_action.ret", 0, NULL); 35#ifdef RTCONFIG_INTERNAL_GOBI 36 start_lteled(); 37#endif 38} 39 40static double traffic_limiter_get_max(const char *type, int unit) 41{ 42 char path[IFPATH_MAX]; 43 char buf[32]; 44 45 snprintf(path, sizeof(path), "/tmp/tl%d_%s_max", unit, type); 46 if (f_read_string(path, buf, sizeof(buf)) > 0) 47 return atof(buf); 48 49 return 0; 50} 51 52static void traffic_limiter_set_max(const char *type, int unit, double value) 53{ 54 char path[IFPATH_MAX]; 55 char buf[32]; 56 57 snprintf(path, sizeof(path), "/tmp/tl%d_%s_max", unit, type); 58 snprintf(buf, sizeof(buf), "%.9g", value); 59 60 f_write_string(path, buf, 0, 0); 61} 62 63static void _traffic_limiter_recover_connect(char *wan_if, int unit) 64{ 65 /* recover wan connection function */ 66 int debug = nvram_get_int("tl_debug"); 67 68 if (debug) dbg("[TRAFFIC LIMITER] %s recover connect\n", wan_if); 69 70 update_wan_state(wan_if, WAN_STATE_CONNECTED, 0); 71 //start_wan_if(unit); 72 traffic_limiter_clear_bit("limit", unit); 73} 74 75void reset_traffic_limiter_counter(int force) 76{ 77 // force = 0 : check limit line 78 // force = 1 : not to check limit line 79 80 /* recover connection when changing limit line or disable limit line */ 81 char tmp1[32], tmp2[32], tmp3[32]; 82 char prefix[sizeof("tlXXXXXXXX_")], wan_if[sizeof("wanXXXXXXXX_")]; 83 int unit; 84 double val; 85 86 /* check daul wan mode */ 87 if (traffic_limiter_dualwan_check(nvram_safe_get("wans_mode")) == 0) 88 return; 89 90 for (unit = TL_UNIT_S; unit < TL_UNIT_E; ++unit) { 91 snprintf(prefix, sizeof(prefix), "tl%d_", unit); 92 snprintf(wan_if, sizeof(wan_if), "wan%d_", unit); 93 strcat_r(prefix, "limit_max", tmp1); 94 strcat_r(prefix, "alert_max", tmp2); 95 strcat_r(prefix, "limit_enable", tmp3); 96 97 if (force == 1) { 98 /* if cycle detect, not to check limit line */ 99 if (!is_wan_connect(unit)) 100 _traffic_limiter_recover_connect(wan_if, unit); 101 } else if (force == 0) { 102 /* if traffic limit disable limit line and wan disconnect */ 103 if (nvram_get_int(tmp3) == 0 && !is_wan_connect(unit)) 104 _traffic_limiter_recover_connect(wan_if, unit); 105 } 106 107 // when limit line changes 108 val = nvram_get_double(tmp1); 109 if (fabs(val - traffic_limiter_get_max("limit", unit)) > 1.0/1024) { 110 traffic_limiter_set_max("limit", unit, val); 111 _traffic_limiter_recover_connect(wan_if, unit); 112 } 113 114 // reset counter when alert line changes 115 val = nvram_get_double(tmp2); 116 if (fabs(val - traffic_limiter_get_max("alert", unit)) > 1.0/1024) { 117 traffic_limiter_set_max("alert", unit, val); 118 // clear bit 119 traffic_limiter_clear_bit("alert", unit); 120 traffic_limiter_clear_bit("count", unit); 121 } 122 } 123} 124 125static void traffic_limiter_cycle_detect(void) 126{ 127 struct tm t1, t2; 128 time_t date_start = nvram_get_int("tl_date_start"); 129 time_t now, new_date; 130 char buf[32]; 131 132 int debug = nvram_get_int("tl_debug"); 133 134 /* current timestamp */ 135 time(&now); 136 137 /* transfer format into tm */ 138 localtime_r(&now, &t1); 139 localtime_r(&date_start, &t2); 140 141 if (debug) dbg("t1: %d-%d-%d, %d:%d:%d\n", t1.tm_year+1900, t1.tm_mon+1, t1.tm_mday, t1.tm_hour, t1.tm_min, t1.tm_sec); 142 if (debug) dbg("t2: %d-%d-%d, %d:%d:%d\n", t2.tm_year+1900, t2.tm_mon+1, t2.tm_mday, t2.tm_hour, t2.tm_min, t2.tm_sec); 143 144 if ((t1.tm_mon == (t2.tm_mon+1)) && (t1.tm_mday == t2.tm_mday)) { 145 // step1. save database 146 hm_traffic_limiter_save(); 147 148 // setp2. update tl_date_start 149 t1.tm_hour = 0; 150 t1.tm_min = 0; 151 t1.tm_sec = 0; 152 new_date = mktime(&t1); 153 154 snprintf(buf, sizeof(buf), "%ld", new_date); 155 nvram_set("tl_date_start", buf); 156 if (debug) dbg("buf=%s, %d-%d-%d, %d:%d:%d\n", buf, t1.tm_year+1900, t1.tm_mon+1, t1.tm_mday, t1.tm_hour, t1.tm_min, t1.tm_sec); 157 158 // step3. recover connection 159 reset_traffic_limiter_counter(1); 160 } 161} 162 163void traffic_limiter_limitdata_check(void) 164{ 165 if (nvram_get_int("tl_enable") == 0) 166 return; 167 168 /* wanduck to upadte traffic limiter data into /jffs/tld/xxx/tmp */ 169 if (traffic_limiter_is_first) { 170 /* after hardware or software reboot, save final data last time */ 171 eval("traffic_limiter", "-c"); 172 traffic_limiter_is_first = 0; 173 } else { 174 /* normal query and upate data */ 175 eval("traffic_limiter", "-q"); 176 } 177 178 /* when tl_cycle is reached, upadte timestamp and start_wan_if() */ 179 traffic_limiter_cycle_detect(); 180} 181 182int traffic_limiter_wanduck_check(int unit) 183{ 184 /* wanduck to check which interface's function and limit are enabled */ 185 int ret = 0, save = 0; 186 unsigned int val; 187 188 val = traffic_limiter_read_bit("limit"); 189 190 /* primary wan */ 191 if (unit == 0 && nvram_get_int("tl0_limit_enable") && (val & 0x1)) { 192 ret = 1; 193 save = 1; 194 } 195 196 /* secondary wan */ 197 if (unit == 1 && nvram_get_int("tl1_limit_enable") && (val & 0x2)) { 198 ret = 1; 199 save = 1; 200 } 201 202 /* save database */ 203 if (save) 204 eval("traffic_limiter", "-w"); 205 206 return ret; 207} 208 209void init_traffic_limiter(void) 210{ 211 traffic_limiter_is_first = 1; 212 traffic_limiter_set_max("limit", 0, nvram_get_double("tl0_limit_max")); 213 traffic_limiter_set_max("alert", 0, nvram_get_double("tl0_alert_max")); 214 traffic_limiter_set_max("limit", 1, nvram_get_double("tl1_limit_max")); 215 traffic_limiter_set_max("alert", 1, nvram_get_double("tl1_alert_max")); 216} 217#endif 218