4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 * @file datausage-tool.c
22 * @desc Implement Performance API. Command line utility.
31 #include "data_usage.h"
32 #include "resourced.h"
33 #include "rd-network.h"
45 RESOURCED_DATA_USAGE_DETAILS,
48 RESOURCED_GET_RESTRICTIONS,
49 RESOURCED_SET_OPTIONS,
50 RESOURCED_GET_OPTIONS,
52 RESOURCED_REMOVE_QUOTA,
53 RESOURCED_RESTRICTION_STATE,
57 data_usage_selection_rule du_rule;
60 resourced_roaming_type roaming_type;
64 static resourced_ret_c convert_roaming(const char *str,
65 resourced_roaming_type *roaming)
68 return RESOURCED_ERROR_INVALID_PARAMETER;
70 if (!strcmp(optarg, "enabled")) {
71 *roaming = RESOURCED_ROAMING_ENABLE;
72 return RESOURCED_ERROR_NONE;
75 if (!strcmp(optarg, "disabled")) {
76 *roaming = RESOURCED_ROAMING_DISABLE;
77 return RESOURCED_ERROR_NONE;
80 if (!strcmp(optarg, "unknown")) {
81 *roaming = RESOURCED_ROAMING_UNKNOWN;
82 return RESOURCED_ERROR_NONE;
84 return RESOURCED_ERROR_INVALID_PARAMETER;
87 static void print_version()
89 printf("Version number: %d.%d-%d\n", MAJOR_VERSION, MINOR_VERSION,
93 static void print_usage()
95 puts("run_rsml [Options]");
96 puts(" Application options:");
97 puts(" possible ordering values: ");
98 puts("\t\tappid - order by application id (package name) "
100 puts("\t\tappiddesc - order by application id (package name) "
102 puts("\t\tiface - ascending ordering by network interface name");
103 puts("\t\tifacedesc - descending ordering by network interface name");
104 puts("-a [--apply-rst] <package name> - apply restriction");
105 puts("-e [--exclude-rst] <package name> - exclude restriction");
106 puts("-R [--restrictions] <incoming>,<outgoing> "
107 "- restrictions to apply");
108 puts("-r [--revert-rst] <package name> - revert restriction");
109 puts("-l [--list-app-rst] - list of restricted applications");
110 puts("-g [--get] - get counters and restriction for application");
111 puts("-v [--version] - program version");
112 puts("-h [--help] - application help");
113 puts("-u [--data-usage] - data usage");
114 puts("-f [--from] <timestamp> - starting timestamp "
115 "for data usage requests");
116 puts("-t [--to] <timestamp> - ending timestamp "
117 "for data usage requests");
118 puts("-i [--interface] <iface> - interface name");
119 puts("-d [--data-usage-details] [<appid>] - data usage details "
120 "total/for application");
121 puts("-G [--granularity] <seconds> - split data usage results "
122 "into chunks of <seconds>");
123 puts("-O [--options] <set|get> set or get options");
124 puts(" In case of set options:");
125 puts(" -W [--wifi] <1|0> enable or disable wifi");
126 puts(" -D [--datacall] <1|0> enable or disable datacall");
127 puts(" -T [--datausagetimer] <1|0> enable or disable datausage timer");
128 puts(" -L [--datacalllogging] <1|0> enable or disable datacall logging");
129 puts(" -M [--roaming] <enalbled|disabled|unknown> enable or disable "
130 " roaming, unknown by default");
131 puts(" -q [--quota] <appid> ");
132 puts(" -Q [--remove-quota] <appid> ");
133 puts(" -s [--rst-state] <pkgid> ");
136 static enum run_rsml_cmd parse_cmd(int argc, char **argv,
137 struct arg_param *param)
139 const char *optstring = "hvla:e:g:uf:t:i:d::G:R:r:O:q:Q:M:s:";
141 const struct option options[] = {
142 {"help", no_argument, 0, 'h'},
143 {"list-app-rst", no_argument, 0, 'l'},
144 {"version", no_argument, 0, 'v'},
145 {"apply-rst", required_argument, 0, 'a'},
146 {"exclude-rst", required_argument, 0, 'e'},
147 {"revert-rst", required_argument, 0, 'r'},
148 {"get", required_argument, 0, 'g'},
149 {"data-usage", no_argument, 0, 'u'},
150 {"from", required_argument, 0, 'f'},
151 {"to", required_argument, 0, 't'},
152 {"interface", required_argument, 0, 'i'},
153 {"data-usage-details", optional_argument, 0, 'd'},
154 {"granularity", required_argument, 0, 'G'},
155 {"restrictions", required_argument, 0, 'R'},
156 {"options", required_argument, 0, 'O'},
157 {"quota", required_argument, 0, 'q'},
158 {"remove-quota", required_argument, 0, 'Q'},
159 {"roaming", required_argument, 0, 'M'},
160 {"rst-state", required_argument, 0, 's'},
164 int longindex, retval;
165 enum run_rsml_cmd cmd = UNDEFINED;
166 resourced_iface_type iftype;
169 getopt_long(argc, argv, optstring, options,
170 &longindex)) != -1) {
181 printf("apply-rst option requeres an argument.");
184 cmd = RESOURCED_APPLY;
185 param->app_id = strdup(optarg);
189 printf("exclude-rst option requeres an argument.");
192 cmd = RESOURCED_EXCLUDE;
193 param->app_id = strdup(optarg);
199 cmd = RESOURCED_DATA_USAGE;
203 printf("from option requeres an argument.");
206 if (sscanf(optarg, "%ld", ¶m->du_rule.from) != 1) {
207 printf("Failed to parse 'from' timestamp: %s\n",
214 printf("to option requeres an argument.");
217 if (sscanf(optarg, "%ld", ¶m->du_rule.to) != 1) {
218 printf("Failed to parse 'to' timestamp: %s\n",
225 printf("interface option requeres an argument.");
228 iftype = convert_iftype(optarg);
229 if (iftype == RESOURCED_IFACE_UNKNOWN) {
230 printf("Unknown network interface!\n");
234 /* TODO change internal param structure */
235 param->du_rule.iftype = iftype;
239 printf("roaming option requeres an argument.");
242 resourced_ret_c ret_code = convert_roaming(optarg,
243 ¶m->roaming_type);
245 if (ret_code != RESOURCED_ERROR_NONE) {
246 printf("Wrong argument of roaming: %s, roaming "
247 "can only be enabled or disabled\n", optarg);
252 cmd = RESOURCED_DATA_USAGE_DETAILS;
254 param->app_id = strdup(optarg);
258 printf("granularity option requeres an argument.");
261 if (sscanf(optarg, "%d", ¶m->du_rule.granularity) !=
263 printf("Failed to parse granularity: %s\n",
270 printf("revert-rst option requeres an argument.");
273 cmd = RESOURCED_REVERT;
274 param->app_id = strdup(optarg);
277 cmd = RESOURCED_GET_RESTRICTIONS;
281 printf("restrictions option requeres an argument.");
287 ¶m->send_limit) != 2) {
288 printf("Failed to parse restrictions\n"
289 "expected 2 integer numbers separated with commas without spaces\n"
290 "got \"%s\"\n", optarg);
296 printf("options option requeres an argument.");
299 if (optarg && strcmp(optarg, "set") == 0)
300 cmd = RESOURCED_SET_OPTIONS;
301 else if (optarg && strcmp(optarg, "get") == 0)
302 cmd = RESOURCED_GET_OPTIONS;
306 printf("Quota option requeres an argument.");
309 cmd = RESOURCED_SET_QUOTA;
310 param->app_id = strdup(optarg);
315 printf("Remove quota option requeres an argument.");
318 cmd = RESOURCED_REMOVE_QUOTA;
319 param->app_id = strdup(optarg);
323 printf("Restriction state requeres an argument.");
326 cmd = RESOURCED_RESTRICTION_STATE;
327 param->app_id = strdup(optarg);
330 printf("Unknown option %c\n", (char)retval);
338 /* common callback for data usage and data usage details
339 * user_data is NULL for data usage
340 * user_data is a non-NULL
341 * (but not necessarily meaningful) for data usage details
343 resourced_cb_ret data_usage_callback(const data_usage_info *info, void *user_data)
345 /*TODO rewrite this hack*/
347 printf("iftype %d\n", info->iftype);
349 printf("%s\n", info->app_id ? info->app_id : UNKNOWN_APP);
351 if (info->interval) {
354 ctime_r(&info->interval->from, buf);
356 ctime_r(&info->interval->to, buf);
359 printf("<entire interval>\t");
361 printf("%ld/%ld\t%ld/%ld/%u/%u/%s\n", info->foreground.cnt.incoming_bytes,
362 info->background.cnt.incoming_bytes,
363 info->foreground.cnt.outgoing_bytes,
364 info->background.cnt.outgoing_bytes,
365 info->roaming, info->hw_net_protocol_type,
367 return RESOURCED_CONTINUE;
370 static inline int is_valid_range32(const int64_t value)
372 return value >= 0 && value <= 2147483647; /* 2Gb */
375 /* callback for restriction details
377 resourced_cb_ret restriction_callback(const resourced_restriction_info *info,
380 printf("appid: %s, iftype: %d, rst_state %d, rcv_limit %d, "
381 "send_limit %d, roaming %d\n",
382 info->app_id ? info->app_id : UNKNOWN_APP,
383 info->iftype, info->rst_state,
384 info->rcv_limit, info->send_limit, info->roaming);
385 return RESOURCED_CONTINUE;
388 const char *state_representation[] = {
395 const char *convert_restriction_state(network_restriction_state state) {
396 if (state <= NETWORK_RESTRICTION_UNDEFINDED
397 || state >= NETWORK_RESTRICTION_MAX_VALUE) {
398 fprintf(stderr, "state not in range %d", state);
402 return state_representation[state];
405 void print_restriction_state(resourced_restriction_state state)
407 const char *state_str = convert_restriction_state(state);
409 printf("\nRestriction state: %s\n", state_str);
412 int main(int argc, char **argv)
415 struct arg_param param;
416 enum run_rsml_cmd cmd = UNDEFINED;
422 memset(¶m, 0, sizeof(struct arg_param));
423 cmd = parse_cmd(argc, argv, ¶m);
425 case RESOURCED_APPLY:
428 resourced_net_restrictions net_rst = {0,};
430 if (!param.du_rule.iftype) {
431 fprintf(stderr, "Apply restriction command requires -i\n");
432 err = RESOURCED_ERROR_INVALID_PARAMETER;
435 if (!is_valid_range32(param.send_limit)) {
436 fprintf(stderr, "Send limit should be in range 0 - 2Gb");
437 err = RESOURCED_ERROR_INVALID_PARAMETER;
439 if (!is_valid_range32(param.rcv_limit)) {
440 fprintf(stderr, "Rcv limit should be in range 0 - 2Gb");
441 err = RESOURCED_ERROR_INVALID_PARAMETER;
447 net_rst.send_limit = param.send_limit;
448 net_rst.rcv_limit = param.rcv_limit;
449 net_rst.iftype = param.du_rule.iftype;
451 ret_code = set_net_restriction(param.app_id,
453 if (ret_code != RESOURCED_ERROR_NONE) {
454 fprintf(stderr, "Failed to set restriction\n");
461 case RESOURCED_EXCLUDE:
463 resourced_net_restrictions rst = {0,};
464 rst.iftype = param.du_rule.iftype;
465 rst.roaming = param.roaming_type;
467 ret_code = set_net_exclusion(param.app_id,
469 if (ret_code != RESOURCED_ERROR_NONE)
473 case RESOURCED_DATA_USAGE:
474 if (param.du_rule.from && param.du_rule.to) {
475 data_usage_foreach(¶m.du_rule, data_usage_callback,
478 fprintf(stderr, "Data usage commands require both "
479 "--from and --to\n");
482 case RESOURCED_DATA_USAGE_DETAILS:
483 if (param.du_rule.from && param.du_rule.to) {
484 /* see description for data_usage_callback above */
485 data_usage_details_foreach(param.app_id, ¶m.du_rule,
489 fprintf(stderr, "Data usage commands require both "
490 "--from and --to\n");
493 case RESOURCED_REVERT:
494 if (param.du_rule.iftype)
495 ret_code = remove_restriction_by_iftype(
496 param.app_id, param.du_rule.iftype);
498 fprintf(stderr, "Revert restriction commands require -i\n");
499 if (ret_code != RESOURCED_ERROR_NONE)
502 case RESOURCED_GET_RESTRICTIONS:
503 printf("Applications are restricted now:\n");
504 ret_code = restrictions_foreach(restriction_callback, NULL);
506 case RESOURCED_SET_OPTIONS:
508 resourced_options options = {0};
509 ret_code = set_resourced_options(&options);
512 case RESOURCED_GET_OPTIONS:
514 resourced_options options = {0};
515 ret_code = get_resourced_options(&options);
518 case RESOURCED_SET_QUOTA:
520 data_usage_quota quota = { 0 };
521 if (!param.du_rule.from || !param.du_rule.to) {
522 fprintf(stderr, "Quota command requires all of this options: "
523 "--from, --to and --roaming\n");
527 /* TODO in case of refactoring, use internal command line structure instead of public structure for holding param */
528 time_t quota_start_time = time(NULL);
529 quota.start_time = "a_start_time;
530 quota.snd_quota = param.send_limit;
531 quota.rcv_quota = param.rcv_limit;
532 quota.iftype = param.du_rule.iftype;
533 quota.time_period = param.du_rule.to - param.du_rule.from;
534 quota.roaming_type = param.roaming_type;
535 if (set_datausage_quota(param.app_id, "a) !=
536 RESOURCED_ERROR_NONE) {
537 fprintf(stderr, "Failed to apply quota!\n");
541 case RESOURCED_REMOVE_QUOTA:
543 struct datausage_quota_reset_rule rule = {0};
545 rule.app_id = param.app_id;
546 rule.iftype = param.du_rule.iftype;
547 rule.roaming = param.roaming_type;
549 if (remove_datausage_quota(&rule) != RESOURCED_ERROR_NONE) {
550 fprintf(stderr, "Failed to remove quota!\n");
554 case RESOURCED_RESTRICTION_STATE:
556 resourced_restriction_state state;
557 if (!param.du_rule.iftype) {
558 fprintf(stderr, "Exclude restriction commands require -i\n");
559 ret_code = RESOURCED_ERROR_INVALID_PARAMETER;
563 ret_code = get_restriction_state(param.app_id,
564 param.du_rule.iftype, &state);
566 print_restriction_state(state);
570 ret_code = RESOURCED_ERROR_INVALID_PARAMETER;