/* * Helper for iptables_fw_destroy * @param table The table to search * @param chain The chain in that table to search * @param mention A word to find and delete in rules in the given table+chain */ int iptables_fw_destroy_mention( const char * table, const char * chain, const char * mention ) { FILE *p = NULL; char *command = NULL; char *command2 = NULL; char line[MAX_BUF]; char rulenum[10]; char *victim = safe_strdup(mention); int deleted = 0; iptables_insert_gateway_id(&victim); debug(LOG_DEBUG, "Attempting to destroy all mention of %s from %s.%s", victim, table, chain); safe_asprintf(&command, "iptables -t %s -L %s -n --line-numbers -v", table, chain); iptables_insert_gateway_id(&command); if ((p = popen(command, "r"))) { /* Skip first 2 lines */ while (!feof(p) && fgetc(p) != '\n'); while (!feof(p) && fgetc(p) != '\n'); /* Loop over entries */ while (fgets(line, sizeof(line), p)) { /* Look for victim */ if (strstr(line, victim)) { /* Found victim - Get the rule number into rulenum*/ if (sscanf(line, "%9[0-9]", rulenum) == 1) { /* Delete the rule: */ debug(LOG_DEBUG, "Deleting rule %s from %s.%s because it mentions %s", rulenum, table, chain, victim); safe_asprintf(&command2, "-t %s -D %s %s", table, chain, rulenum); iptables_do_command(command2); free(command2); deleted = 1; /* Do not keep looping - the captured rulenums will no longer be accurate */ break; } } } pclose(p); } free(command); free(victim); if (deleted) { /* Recurse just in case there are more in the same table+chain */ iptables_fw_destroy_mention(table, chain, mention); } return (deleted); }
/** @internal * */ static int iptables_do_command(const char *format, ...) { va_list vlist; char *fmt_cmd; char *cmd; int rc; va_start(vlist, format); safe_vasprintf(&fmt_cmd, format, vlist); va_end(vlist); safe_asprintf(&cmd, "iptables %s", fmt_cmd); free(fmt_cmd); iptables_insert_gateway_id(&cmd); debug(LOG_DEBUG, "Executing command: %s", cmd); rc = execute(cmd, fw_quiet); if (rc != 0) { // If quiet, do not display the error if (fw_quiet == 0) debug(LOG_ERR, "iptables command failed(%d): %s", rc, cmd); else if (fw_quiet == 1) debug(LOG_DEBUG, "iptables command failed(%d): %s", rc, cmd); } free(cmd); return rc; }
// add by lijg, 2013-05-30, Find keyword @mention in firewall rule table = @table and chain = @chain // return : 0 - not found, 1 - found it . int iptables_fw_find_mention( const char * table, const char * chain, const char * mention ) { FILE *p = NULL; char *command = NULL; char line[MAX_BUF]; char *victim = safe_strdup(mention); int found = 0; // 1.1 @victim="WiFiDog_br-lan_Trusted" iptables_insert_gateway_id(&victim); debug(LOG_DEBUG, "Attempting to find all mention of %s from %s.%s", victim, table, chain); safe_asprintf(&command, "iptables -t %s -L %s -n --line-numbers -v", table, chain); iptables_insert_gateway_id(&command); //1.2 执行命令 iptables -t mangle -L PREROUTING -n --line-numbers -v, 逐行输出链中规则 if ((p = popen(command, "r"))) { /* Skip first 2 lines */ while (!feof(p) && fgetc(p) != '\n'); while (!feof(p) && fgetc(p) != '\n'); /* Loop over entries */ while (fgets(line, sizeof(line), p)) { // 匹配链中每条规则 /* Look for victim */ if (strstr(line, victim)) { // 根据客户端IP地址进行匹配 found = 1; break; } } pclose(p); } free(command); free(victim); return (found); }
/** Update the counters of all the clients in the client list */ int iptables_fw_counters_update(void) { FILE *output; char *script, ip[16], rc; unsigned long long int counter; t_client *p1; struct in_addr tempaddr; debug(LOG_DEBUG, "begin iptables_fw_counters_update"); /* Look for outgoing traffic */ // modified by lijg , 2013-05-18, 修改获取上行流量 safe_asprintf(&script, "%s %s", "iptables", "-v -n -x -t mangle -L " TABLE_WIFIDOG_OUTGOING); iptables_insert_gateway_id(&script); output = popen(script, "r"); free(script); if (!output) { debug(LOG_ERR, "popen(): %s", strerror(errno)); return -1; } /* skip the first two lines */ while (('\n' != fgetc(output)) && !feof(output)) ; while (('\n' != fgetc(output)) && !feof(output)) ; while (output && !(feof(output))) { rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %15[0-9.] %*s %*s %*s %*s %*s %*s", &counter, ip); //rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %15[0-9.] %*s %*s %*s %*s %*s 0x%*u", &counter, ip); //debug(LOG_DEBUG, "outgoing >> %s -- %llu (%u)", ip, counter, rc); if (2 == rc && EOF != rc) { /* Sanity*/ if (!inet_aton(ip, &tempaddr)) { debug(LOG_WARNING, "I was supposed to read an IP address but instead got [%s] - ignoring it", ip); continue; } debug(LOG_DEBUG, "Read outgoing traffic for %s: Bytes=%llu", ip, counter); LOCK_CLIENT_LIST(); if ((p1 = client_list_find_by_ip(ip))) { if ((p1->counters.outgoing - p1->counters.outgoing_history) < counter) { p1->counters.outgoing = p1->counters.outgoing_history + counter; p1->counters.last_updated = time(NULL); debug(LOG_DEBUG, "%s - Updated counter.outgoing to %llu bytes. Updated last_updated to %d", ip, counter, p1->counters.last_updated); } } else { debug(LOG_ERR, "iptables_fw_counters_update(): Could not find %s in client list, this should not happen unless if the gateway crashed", ip); debug(LOG_ERR, "Preventively deleting firewall rules for %s in table %s", ip, TABLE_WIFIDOG_OUTGOING); iptables_fw_destroy_mention("mangle", TABLE_WIFIDOG_OUTGOING, ip); debug(LOG_ERR, "Preventively deleting firewall rules for %s in table %s", ip, TABLE_WIFIDOG_INCOMING); iptables_fw_destroy_mention("mangle", TABLE_WIFIDOG_INCOMING, ip); } UNLOCK_CLIENT_LIST(); } } pclose(output); /* Look for incoming traffic */ safe_asprintf(&script, "%s %s", "iptables", "-v -n -x -t mangle -L " TABLE_WIFIDOG_INCOMING); iptables_insert_gateway_id(&script); output = popen(script, "r"); free(script); if (!output) { debug(LOG_ERR, "popen(): %s", strerror(errno)); return -1; } /* skip the first two lines */ while (('\n' != fgetc(output)) && !feof(output)) ; while (('\n' != fgetc(output)) && !feof(output)) ; while (output && !(feof(output))) { rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %*s %15[0-9.]", &counter, ip); if (2 == rc && EOF != rc) { /* Sanity*/ if (!inet_aton(ip, &tempaddr)) { debug(LOG_WARNING, "I was supposed to read an IP address but instead got [%s] - ignoring it", ip); continue; } debug(LOG_DEBUG, "Read incoming traffic for %s: Bytes=%llu", ip, counter); LOCK_CLIENT_LIST(); if ((p1 = client_list_find_by_ip(ip))) { if ((p1->counters.incoming - p1->counters.incoming_history) < counter) { p1->counters.incoming = p1->counters.incoming_history + counter; debug(LOG_DEBUG, "%s - Updated counter.incoming to %llu bytes", ip, counter); } } else { debug(LOG_ERR, "iptables_fw_counters_update(): Could not find %s in client list, this should not happen unless if the gateway crashed", ip); debug(LOG_ERR, "Preventively deleting firewall rules for %s in table %s", ip, TABLE_WIFIDOG_OUTGOING); iptables_fw_destroy_mention("mangle", TABLE_WIFIDOG_OUTGOING, ip); debug(LOG_ERR, "Preventively deleting firewall rules for %s in table %s", ip, TABLE_WIFIDOG_INCOMING); iptables_fw_destroy_mention("mangle", TABLE_WIFIDOG_INCOMING, ip); } UNLOCK_CLIENT_LIST(); } } pclose(output); debug(LOG_DEBUG, "end iptables_fw_counters_update\n\n"); return 1; }
/** Update the counters of all the clients in the client list */ int iptables_fw_counters_update(void) { FILE *output; char *script, ip[16], rc; unsigned long long int counter; t_client *p1; struct in_addr tempaddr; int fd; /* Look for outgoing traffic */ safe_asprintf(&script, "%s %s", "iptables", "-v -n -x -t mangle -L " TABLE_WIFIDOG_OUTGOING); iptables_insert_gateway_id(&script); output = popen(script, "r"); free(script); if (!output) { debug(LOG_ERR, "popen(): %s", strerror(errno)); return -1; } fprintf(stderr,"popen:"); /* skip the first two lines */ while (('\n' != fgetc(output)) && !feof(output)) ; while (('\n' != fgetc(output)) && !feof(output)) ; /*set nonblocking -> would need to change fscanf against read and buffer and other parsing logic fd = fileno(output); fcntl(fd, F_SETFL, O_NONBLOCK); */ while (output && !(feof(output))) { fprintf(stderr,"#"); rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %15[0-9.] %*s %*s %*s %*s %*s %*s", &counter, ip); //rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %15[0-9.] %*s %*s %*s %*s %*s 0x%*u", &counter, ip); fprintf(stderr,"!"); if (2 == rc && EOF != rc) { /* Sanity*/ if (!inet_aton(ip, &tempaddr)) { debug(LOG_WARNING, "I was supposed to read an IP address but instead got [%s] - ignoring it", ip); continue; } debug(LOG_DEBUG, "Read outgoing traffic for %s: Bytes=%llu", ip, counter); //here we deadlock sometimes,... LOCK_CLIENT_LIST(); if ((p1 = client_list_find_by_ip(ip))) { if ((p1->counters.outgoing - p1->counters.outgoing_history) < counter) { p1->counters.outgoing = p1->counters.outgoing_history + counter; p1->counters.last_updated = time(NULL); debug(LOG_DEBUG, "%s - Updated counter.outgoing to %llu bytes. Updated last_updated to %d", ip, counter, p1->counters.last_updated); } } else { debug(LOG_ERR, "Could not find %s in client list", ip); } UNLOCK_CLIENT_LIST(); } } pclose(output); /* Look for incoming traffic */ safe_asprintf(&script, "%s %s", "iptables", "-v -n -x -t mangle -L " TABLE_WIFIDOG_INCOMING); iptables_insert_gateway_id(&script); output = popen(script, "r"); free(script); if (!output) { debug(LOG_ERR, "popen(): %s", strerror(errno)); return -1; } fprintf(stderr,"popen:"); /* skip the first two lines */ while (('\n' != fgetc(output)) && !feof(output)) ; while (('\n' != fgetc(output)) && !feof(output)) ; while (output && !(feof(output))) { fprintf(stderr,"#"); rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %*s %15[0-9.]", &counter, ip); fprintf(stderr,"!"); if (2 == rc && EOF != rc) { /* Sanity*/ if (!inet_aton(ip, &tempaddr)) { debug(LOG_WARNING, "I was supposed to read an IP address but instead got [%s] - ignoring it", ip); continue; } debug(LOG_DEBUG, "Read incoming traffic for %s: Bytes=%llu", ip, counter); LOCK_CLIENT_LIST(); if ((p1 = client_list_find_by_ip(ip))) { if ((p1->counters.incoming - p1->counters.incoming_history) < counter) { p1->counters.incoming = p1->counters.incoming_history + counter; debug(LOG_DEBUG, "%s - Updated counter.incoming to %llu bytes", ip, counter); } } else { debug(LOG_ERR, "Could not find %s in client list", ip); } UNLOCK_CLIENT_LIST(); } } pclose(output); return 1; }
/** Update the counters of all the clients in the client list */ int iptables_fw_counters_update(void) { FILE *output; char *script, ip[16], rc, mac[18]; unsigned long long int counter; t_client *p1; struct in_addr tempaddr; const s_config *config = config_get_config(); /* Look for outgoing traffic */ safe_asprintf(&script, "%s %s", "iptables", "-v -n -x -t mangle -L " CHAIN_OUTGOING); iptables_insert_gateway_id(&script); output = popen(script, "r"); free(script); if (!output) { debug(LOG_ERR, "popen(): %s", strerror(errno)); return -1; } /* skip the first two lines */ while (('\n' != fgetc(output)) && !feof(output)) ; while (('\n' != fgetc(output)) && !feof(output)) ; while (output && !(feof(output))) { //3554 390634 MARK all -- * * 0.0.0.0/0 0.0.0.0/0 MAC C0:38:96:96:74:7D MARK set 0x3 /*rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %15[0-9.] %*s %*s %*s %*s %*s %*s", &counter, ip);*/ //rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %15[0-9.] %*s %*s %*s %*s %*s 0x%*u", &counter, ip); rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %15[0-9.] %*s %*s %17[0-9a-fA-F:] %*s %*s 0x%*u", &counter, ip, mac); if (3 == rc && EOF != rc) { /* Sanity */ if (!inet_aton(ip, &tempaddr)) { debug(LOG_WARNING, "I was supposed to read an IP address but instead got [%s] - ignoring it", ip); continue; } debug(LOG_DEBUG, "Read outgoing traffic for %s(%s): Bytes=%llu", ip, mac, counter); LOCK_CLIENT_LIST(); if ((p1 = client_list_find_by_ip(ip))) { p1->counters.active_duration--; if ((p1->counters.outgoing - p1->counters.outgoing_history) < counter) { p1->counters.outgoing_delta = p1->counters.outgoing_history + counter - p1->counters.outgoing; p1->counters.outgoing = p1->counters.outgoing_history + counter; p1->counters.last_updated = time(NULL); debug(LOG_DEBUG, "%s(%s) - Outgoing traffic %llu bytes, updated counter.outgoing to %llu bytes. Updated last_updated to %d", ip, mac, counter, p1->counters.outgoing, p1->counters.last_updated); } } else { debug(LOG_ERR, "iptables_fw_counters_update(): Could not find %s(%s) in client list, this should not happen unless if the gateway crashed", ip, mac); debug(LOG_ERR, "Preventively deleting firewall rules for %s(%s) in table %s", ip, mac, CHAIN_OUTGOING); iptables_fw_destroy_mention("mangle", CHAIN_OUTGOING, ip); debug(LOG_ERR, "Preventively deleting firewall rules for %s(%s) in table %s", ip, mac, CHAIN_INCOMING); iptables_fw_destroy_mention("mangle", CHAIN_INCOMING, ip); } UNLOCK_CLIENT_LIST(); } } pclose(output); /* Look for incoming traffic */ safe_asprintf(&script, "%s %s", "iptables", "-v -n -x -t mangle -L " CHAIN_INCOMING); iptables_insert_gateway_id(&script); output = popen(script, "r"); free(script); if (!output) { debug(LOG_ERR, "popen(): %s", strerror(errno)); return -1; } /* skip the first two lines */ while (('\n' != fgetc(output)) && !feof(output)) ; while (('\n' != fgetc(output)) && !feof(output)) ; while (output && !(feof(output))) { rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %*s %15[0-9.]", &counter, ip); if (2 == rc && EOF != rc) { /* Sanity */ if (!inet_aton(ip, &tempaddr)) { debug(LOG_WARNING, "I was supposed to read an IP address but instead got [%s] - ignoring it", ip); continue; } debug(LOG_DEBUG, "Read incoming traffic for %s: Bytes=%llu", ip, counter); LOCK_CLIENT_LIST(); if ((p1 = client_list_find_by_ip(ip))) { if ((p1->counters.incoming - p1->counters.incoming_history) < counter) { p1->counters.incoming_delta = p1->counters.incoming_history + counter - p1->counters.incoming; p1->counters.incoming = p1->counters.incoming_history + counter; debug(LOG_DEBUG, "%s - Incoming traffic %llu bytes, Updated counter.incoming to %llu bytes", ip, counter, p1->counters.incoming); } } else { debug(LOG_ERR, "iptables_fw_counters_update(): Could not find %s in client list, this should not happen unless if the gateway crashed", ip); debug(LOG_ERR, "Preventively deleting firewall rules for %s in table %s", ip, CHAIN_OUTGOING); iptables_fw_destroy_mention("mangle", CHAIN_OUTGOING, ip); debug(LOG_ERR, "Preventively deleting firewall rules for %s in table %s", ip, CHAIN_INCOMING); iptables_fw_destroy_mention("mangle", CHAIN_INCOMING, ip); } UNLOCK_CLIENT_LIST(); } } pclose(output); return 1; }
void notify_client_disconnect(char *mac, char *ifname) { t_client *client; t_redir_node *node; FILE *output; char *script, ip[16], rc; unsigned long long int counter; struct in_addr tempaddr; int ifIndex = get_ifIndex(ifname); // printf("Client Disconnected\n"); LOCK_REDIR(); node = redir_list_find(mac); if (node && node->redir_pending) { UNLOCK_REDIR(); safe_asprintf(&script, "%s %s", "iptables", "-v -n -x -t mangle -L " CHAIN_OUTGOING); iptables_insert_gateway_id(&script); output = popen(script, "r"); free(script); if (!output) { debug(LOG_ERR, "popen(): %s", strerror(errno)); return -1; } /* skip the first two lines */ while (('\n' != fgetc(output)) && !feof(output)) ; while (('\n' != fgetc(output)) && !feof(output)) ; while (output && !(feof(output))) { rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %15[0-9.] %*s %*s %17[0-9a-fA-F:] %*s %*s 0x%*u", &counter, ip, mac); if (3 == rc && EOF != rc) { /* Sanity */ if (!inet_aton(ip, &tempaddr)) { debug(LOG_WARNING, "I was supposed to read an IP address but instead got [%s] - ignoring it", ip); continue; } debug(LOG_DEBUG, "Read outgoing traffic for %s(%s): Bytes=%llu", ip, mac, counter); LOCK_CLIENT_LIST(); if ((client = client_list_find_by_ip(ip))) { client->counters.outgoing = client->counters.outgoing_history + counter; client->counters.last_updated = time(NULL); UNLOCK_CLIENT_LIST(); pclose(output); return; } } } UNLOCK_CLIENT_LIST(); pclose(output); } if(node) if(node->ifindex != ifIndex) debug(LOG_NOTICE,"%s: %s connected to idx %d, recv'd disconnect evt from idx %d\n",__func__, mac, node->ifindex, ifIndex); if (node && (node->ifindex == ifIndex)) { if (node->redir_pending) { char command[100]; char fmac[13]; formatmacaddr(mac, &fmac); node->redir_pending = 0; debug(LOG_NOTICE,"%s: recv'd disconnect evt for %s from idx %d\n",__func__, mac, node->ifindex); snprintf(command,100,"echo %s > /proc/sys/net/bridge/bridge-http-redirect-del-mac",fmac); // printf("%s",command); execute(command,0); if (node->route_added) { memset(command, 0, sizeof(command)); sprintf(command, "/bin/ip route del %s/32 src %s dev %s", node->host_ip, node->dev_ip, node->dev); //printf("\nexecuting %s\n", command); execute(command, 0); } fw_mark_mangle(mac,0); } debug(LOG_NOTICE,"%s: removing node list for %s from idx %d\n",__func__, mac, node->ifindex); redir_list_delete(node); } UNLOCK_REDIR(); LOCK_CLIENT_LIST(); client = client_list_find_by_mac(mac); if (client) { /*fw_deny_raw(client->ip, client->mac, client->fw_connection_state);*/ iptables_fw_access(FW_ACCESS_DENY, client->ip, client->mac, client->fw_connection_state); client_list_delete(client); } UNLOCK_CLIENT_LIST(); }