int BandwidthController::setCostlyAlert(const char *costName, int64_t bytes, int64_t *alertBytes) { char *alertQuotaCmd; char *chainName; int res = 0; char *alertName; if (!isIfaceName(costName)) { ALOGE("setCostlyAlert: Invalid costName \"%s\"", costName); return -1; } if (!bytes) { ALOGE("Invalid bytes value. 1..max_int64."); return -1; } asprintf(&alertName, "%sAlert", costName); if (*alertBytes) { res = updateQuota(alertName, *alertBytes); } else { asprintf(&chainName, "bw_costly_%s", costName); asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, "-A", chainName, bytes, alertName); res |= runIpxtablesCmd(alertQuotaCmd, IptJumpNoAdd); free(alertQuotaCmd); free(chainName); } *alertBytes = bytes; free(alertName); return res; }
int BandwidthController::setCostlyAlert(const char *costName, int64_t bytes, int64_t *alertBytes) { char *alertQuotaCmd; char *chainNameAndPos; int res = 0; char *alertName; if (!bytes) { LOGE("Invalid bytes value. 1..max_int64."); return -1; } asprintf(&alertName, "%sAlert", costName); if (*alertBytes) { res = updateQuota(alertName, *alertBytes); } else { asprintf(&chainNameAndPos, "costly_%s %d", costName, ALERT_RULE_POS_IN_COSTLY_CHAIN); asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, "-I", chainNameAndPos, bytes, alertName, alertName); res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd); free(alertQuotaCmd); free(chainNameAndPos); } *alertBytes = bytes; free(alertName); return res; }
int BandwidthController::setGlobalAlert(int64_t bytes) { const char *alertName = ALERT_GLOBAL_NAME; int res = 0; if (!bytes) { ALOGE("Invalid bytes value. 1..max_int64."); return -1; } if (globalAlertBytes) { res = updateQuota(alertName, bytes); } else { res = runIptablesAlertCmd(IptOpInsert, alertName, bytes); if (globalAlertTetherCount) { ALOGV("setGlobalAlert for %d tether", globalAlertTetherCount); res |= runIptablesAlertFwdCmd(IptOpInsert, alertName, bytes); } } globalAlertBytes = bytes; return res; }
int BandwidthController::setInterfaceQuota(const char *iface, int64_t maxBytes) { char ifn[MAX_IFACENAME_LEN]; int res = 0; std::string ifaceName; const char *costName; std::list<QuotaInfo>::iterator it; std::string quotaCmd; if (!isIfaceName(iface)) return -1; if (!maxBytes) { /* Don't talk about -1, deprecate it. */ ALOGE("Invalid bytes value. 1..max_int64."); return -1; } if (maxBytes == -1) { return removeInterfaceQuota(iface); } if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) { ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN); return -1; } ifaceName = ifn; costName = iface; /* Insert ingress quota. */ for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) { if (it->ifaceName == ifaceName) break; } if (it == quotaIfaces.end()) { /* Preparing the iface adds a penalty/happy box check */ res |= prepCostlyIface(ifn, QuotaUnique); /* * The rejecting quota limit should go after the penalty/happy box checks * or else a naughty app could just eat up the quota. * So we append here. */ quotaCmd = makeIptablesQuotaCmd(IptOpAppend, costName, maxBytes); res |= runIpxtablesCmd(quotaCmd.c_str(), IptJumpReject); if (res) { ALOGE("Failed set quota rule"); goto fail; } quotaIfaces.push_front(QuotaInfo(ifaceName, maxBytes, 0)); } else { res |= updateQuota(costName, maxBytes); if (res) { ALOGE("Failed update quota for %s", iface); goto fail; } it->quota = maxBytes; } return 0; fail: /* * TODO(jpa): once we get rid of iptables in favor of rtnetlink, reparse * rules in the kernel to see which ones need cleaning up. * For now callers needs to choose if they want to "ndc bandwidth enable" * which resets everything. */ removeInterfaceSharedQuota(ifn); return -1; }
int BandwidthController::setInterfaceSharedQuota(const char *iface, int64_t maxBytes) { char ifn[MAX_IFACENAME_LEN]; int res = 0; std::string quotaCmd; std::string ifaceName; ; const char *costName = "shared"; std::list<std::string>::iterator it; if (!maxBytes) { /* Don't talk about -1, deprecate it. */ ALOGE("Invalid bytes value. 1..max_int64."); return -1; } if (!isIfaceName(iface)) return -1; if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) { ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN); return -1; } ifaceName = ifn; if (maxBytes == -1) { return removeInterfaceSharedQuota(ifn); } /* Insert ingress quota. */ for (it = sharedQuotaIfaces.begin(); it != sharedQuotaIfaces.end(); it++) { if (*it == ifaceName) break; } if (it == sharedQuotaIfaces.end()) { res |= prepCostlyIface(ifn, QuotaShared); if (sharedQuotaIfaces.empty()) { quotaCmd = makeIptablesQuotaCmd(IptOpInsert, costName, maxBytes); res |= runIpxtablesCmd(quotaCmd.c_str(), IptJumpReject); if (res) { ALOGE("Failed set quota rule"); goto fail; } sharedQuotaBytes = maxBytes; } sharedQuotaIfaces.push_front(ifaceName); } if (maxBytes != sharedQuotaBytes) { res |= updateQuota(costName, maxBytes); if (res) { ALOGE("Failed update quota for %s", costName); goto fail; } sharedQuotaBytes = maxBytes; } return 0; fail: /* * TODO(jpa): once we get rid of iptables in favor of rtnetlink, reparse * rules in the kernel to see which ones need cleaning up. * For now callers needs to choose if they want to "ndc bandwidth enable" * which resets everything. */ removeInterfaceSharedQuota(ifn); return -1; }