📄 classifiernetfilter.cc
字号:
void ClassifierNetfilter::_addRule( RuleInfo &rinfo, int test ){ int rule_id, nAttributes, i, argc = 0; char **attributes, **params, *param; struct ipt_entry fw, *e = NULL; int invert = 0; unsigned int nsaddrs = 0, ndaddrs = 0; struct in_addr *saddrs = NULL, *daddrs = NULL; int c, valid; const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL; unsigned int options = 0; int ret = 1; struct iptables_match *m = NULL; struct iptables_target *target = NULL; const char *jumpto = ""; char *protocol = NULL; char **argv; struct netfilter_rule_entry *nfre;#ifdef LOOPFULL maxid++; return;#endif // extract filter rule information from RuleInfo object rule_id = rinfo.getId(); // MLOG( "ClassifierNetfilter : adding Rule #%d", rule_id ); attributes = rinfo.getFilter()->getNames( &nAttributes); params = rinfo.getFilter()->getValues( &nAttributes ); if (rule_id<0 || nAttributes<0 || attributes == NULL || params == NULL ) throw MyErr( "invalid filter rule description" ); #ifdef CLASS_DEBUG cout << *(rinfo.getFilter()) << "\n"; // dump filter spec#endif // emulate getopt // allocate some space for optarg, argv //if (optarg) //seems to be dangerous assumption // free(optarg); optarg = new char[256]; argv = new char*[nAttributes*2]; optind = 1; for (i = 0; i<nAttributes; i++) { invert = check_for_invert(params[i], ¶m); if (invert) { argv[argc] = new char[strlen(inv_symbol)+1]; strcpy(argv[argc++], inv_symbol); } if (param != NULL) { argv[argc] = new char[strlen(param)+1]; strcpy(argv[argc++], param); } } /* Suppress error messages: we may add new options if we demand-load a protocol. */ opterr = 0; // initialize data structures memset(&fw, 0, sizeof(fw)); shostnetworkmask = "0.0.0.0/0"; dhostnetworkmask = "0.0.0.0/0"; // reset used flag for matches, used = 1 means used by current rule for (m = iptables_matches; m; m = m->next) { m->used = 0; } // target is _always_ ULOG ->load it jumpto = parse_target(def_targetname); if ((target = find_target(jumpto, DONT_LOAD))) { // initialize data and flags target->tflags = 0; memset(target->t->data, 0, target->size); target->init(target->t, &fw.nfcache); target->used = 1; } else { if ((target = find_target(jumpto, LOAD_MUST_SUCCEED))) { size_t size;#ifdef CLASS_DEBUG fprintf(stderr, "%s loaded\n", jumpto);#endif size = IPT_ALIGN(sizeof(struct ipt_entry_target)) + target->size; target->t = (struct ipt_entry_target *) fw_calloc(1, size); target->t->u.target_size = size; strcpy(target->t->u.user.name, jumpto); // call init function target->init(target->t, &fw.nfcache); target->used = 1; } else throw MyErr("cant load %s target", def_targetname); } #ifdef CLASS_DEBUG fprintf(stderr, "rule target initialized\n");#endif // configure target, set nlgroup c = translate_option((char *)param_names[defp_nlgroup], target->option_offset); if (c<0) throw MyErr("Unknown arg `%s'", param_names[defp_nlgroup]); sprintf(optarg, "%d", nlgroup);#ifdef CLASS_DEBUG fprintf(stderr, "nlgroup option resolved to %d, arg is %s\n", c, optarg);#endif if (!(target->parse(c - target->option_offset, argv, invert, &target->tflags, &fw, &target->t))) { throw MyErr("Unknown arg `%s'", param_names[defp_nlgroup]); } // set rule id c = translate_option((char *)param_names[defp_prefix], target->option_offset); if (c<0) throw MyErr("Unknown arg `%s'", param_names[defp_prefix]); sprintf(optarg, "%d", rule_id);#ifdef CLASS_DEBUG fprintf(stderr, "prefix option resolved to %d, arg is %s\n", c, optarg);#endif if (!(target->parse(c - target->option_offset, argv, invert, &target->tflags, &fw, &target->t))) { throw MyErr("Unknown arg `%s'", param_names[defp_prefix]); } // default cprange c = translate_option((char *)param_names[defp_cprange], target->option_offset); if (c<0) throw MyErr("Unknown arg `%s'", param_names[defp_cprange]); sprintf(optarg, "%d", cprange);#ifdef CLASS_DEBUG fprintf(stderr, "cprange option resolved to %d, arg is %s\n", c, optarg);#endif if (!(target->parse(c - target->option_offset, argv, invert, &target->tflags, &fw, &target->t))) { throw MyErr("Unknown arg `%s'", param_names[defp_cprange]); } // default qthreshold c = translate_option((char *)param_names[defp_qthreshold], target->option_offset); if (c<0) throw MyErr("Unknown arg `%s'", param_names[defp_qthreshold]); sprintf(optarg, "%d", qthres);#ifdef CLASS_DEBUG fprintf(stderr, "qthreshold option resolved to %d, arg is %s\n", c, optarg);#endif if (!(target->parse(c - target->option_offset, argv, invert, &target->tflags, &fw, &target->t))) { throw MyErr("Unknown arg `%s'", param_names[defp_qthreshold]); } // reset target (ulog) flags to allow cprange and qthreshold config by // rule target->tflags = 0; // check the given attributes + parse and check the parameter values for (i = 0; i<nAttributes; i++ ) { invert = check_for_invert(params[i], ¶m); if (invert) optind++; if (!strcmp( attributes[i], "nofilter" ) ) { // ignore 'nofilter' } else if (!strcmp( attributes[i], param_names[defp_bidir] ) ) { // ignore at this point } else if (!strcmp( attributes[i], param_names[defp_srcipmask] ) ) { set_inverse(defp_srcipmask, &fw.ip.invflags, invert); shostnetworkmask = param; fw.nfcache | = NFC_IP_DST; } else if (!strcmp( attributes[i], param_names[defp_dstipmask] ) ) { set_inverse(defp_dstipmask, &fw.ip.invflags, invert); dhostnetworkmask = param; fw.nfcache | = NFC_IP_DST; } else if (!strcmp( attributes[i], param_names[defp_iniface] ) ) { set_inverse(defp_iniface, &fw.ip.invflags, invert); parse_interface(param, fw.ip.iniface, fw.ip.iniface_mask); fw.nfcache | = NFC_IP_IF_IN; } else if (!strcmp( attributes[i], param_names[defp_outiface] ) ) { set_inverse(defp_outiface, &fw.ip.invflags, invert); parse_interface(param, fw.ip.outiface, fw.ip.outiface_mask); fw.nfcache | = NFC_IP_IF_OUT; } else if (!strcmp( attributes[i], param_names[defp_match] ) ) { size_t size; if (invert) exit_error(PARAMETER_PROBLEM, "unexpected !flag before %s", param_names[defp_match]); if ((m = find_match(param, DONT_LOAD))) { // initialize data and flags m->mflags = 0; memset(m->m->data, 0, m->size); m->init(m->m, &fw.nfcache); m->used = 1; } else { if ((m = find_match(param, LOAD_MUST_SUCCEED))) { size = IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size; m->m = (struct ipt_entry_match *) fw_calloc(1, size); m->m->u.match_size = size; strcpy(m->m->u.user.name, m->name); // call init function m->init(m->m, &fw.nfcache); m->used = 1; } } } else if (!strcmp( attributes[i], param_names[defp_prot] ) ) { set_inverse(defp_prot, &fw.ip.invflags, invert); /* Canonicalize into lower case */ for (protocol = param; *protocol; protocol++) *protocol = tolower(*protocol); protocol = param; fw.ip.proto = parse_protocol(protocol); if ((fw.ip.proto == 0) && (fw.ip.invflags & IPT_INV_PROTO)) exit_error(PARAMETER_PROBLEM, "rule would never match protocol"); fw.nfcache | = NFC_IP_PROTO; } else { // must be a module specific option or ULOG option // set matches according to protocol if (m == NULL && protocol) { if ((m = find_proto(protocol, DONT_LOAD, options & 0x01))) { // initialize data and flags m->mflags = 0; memset(m->m->data, 0, m->size); m->init(m->m, &fw.nfcache); m->used = 1; } else { if ((m = find_proto(protocol, TRY_LOAD, options & 0x01))) { size_t size;#ifdef CLASS_DEBUG fprintf(stderr, "loading %s module\n", protocol);#endif size = IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size; m->m = (struct ipt_entry_match *) fw_calloc(1, size); m->m->u.match_size = size; strcpy(m->m->u.user.name, m->name); m->init(m->m, &fw.nfcache); m->used = 1; } else { exit_error(PARAMETER_PROBLEM, "Error loading %s module", protocol); } } } valid = 0;#ifdef CLASS_DEBUG fprintf(stderr, "Parsing %s option\n", attributes[i]);#endif for (m = iptables_matches; m; m = m->next) { if (m->used) { c = translate_option(attributes[i], m->option_offset); if (c > 0) { strcpy(optarg, param); // if protocol is inverse options for this protocol makes no sense if (fw.ip.invflags & IPT_INV_PROTO) { exit_error(PARAMETER_PROBLEM, "Option specified for negative protocol match '%s'", protocol); } if (m->parse(c - m->option_offset, argv, invert, &m->mflags, &fw, &fw.nfcache, &m->m)) { valid = 1; break; } } } } // following target parameters: qthreshold, cprange if (!valid) { c = translate_option(attributes[i], target->option_offset); if (c > 0) { strcpy(optarg, param); if (target->parse(c - target->option_offset, argv, invert, &target->tflags, &fw, &target->t)) { valid = 1; } } } if (!valid) exit_error(PARAMETER_PROBLEM, "Unknown arg `%s'", attributes[i]); } optind++; } // final check for all modules used for (m = iptables_matches; m; m = m->next) { if (m->used) { m->final_check(m->mflags); } } if (target) target->final_check(target->tflags); // parse source and destination address+mask if (shostnetworkmask) parse_hostnetworkmask(shostnetworkmask, &saddrs, &(fw.ip.smsk), &nsaddrs); if (dhostnetworkmask) parse_hostnetworkmask(dhostnetworkmask, &daddrs, &(fw.ip.dmsk), &ndaddrs);#ifdef CLASS_DEBUG fprintf(stderr, "all parameters parsed\n");#endif // FIXME: dont support this right now /* if ((nsaddrs > 1 || ndaddrs > 1) && (fw.ip.invflags & (IPT_INV_SRCIP | IPT_INV_DSTIP))) exit_error(PARAMETER_PROBLEM, "!not allowed with multiple" " source or destination IP addresses"); */ // check for valid interface specs according to target chain if (strcmp(chain, "PREROUTING") == 0 || strcmp(chain, "INPUT") == 0 || strcmp(chain, "PROMISCUOUS") ) { if (fw.nfcache & NFC_IP_IF_OUT) exit_error(PARAMETER_PROBLEM, "Can't use %s with %s\n", param_names[defp_outiface], chain); } if (strcmp(chain, "POSTROUTING") == 0 || strcmp(chain, "OUTPUT") == 0 || strcmp(chain, "PROMISCUOUS") ) { if (fw.nfcache & NFC_IP_IF_IN) exit_error(PARAMETER_PROBLEM, "Can't use %s with %s\n", param_names[defp_iniface], chain); } // do generate because we know that we have a target e = generate_entry(&fw, iptables_matches, target->t);#ifdef CLASS_DEBUG fprintf(stderr, "new entry generated\n");#endif nfre = alloc_rule_entry(e, nsaddrs, saddrs, ndaddrs, daddrs);#ifdef CLASS_DEBUG fprintf(stderr, "new rule entry allocated\n");#endif // install NetFilter rule ret = append_entry(chain, e, nsaddrs, saddrs, ndaddrs, daddrs, options, iptc_h); if (!ret) { delete_rule_entry(nfre); exit_error(PARAMETER_PROBLEM, "%s\n", iptc_strerror(errno)); } ret = iptc_commit(iptc_h); // respawn handle, thanx rusty *iptc_h = iptc_init(table); if (!ret) { delete_rule_entry(nfre); exit_error(PARAMETER_PROBLEM, "%s\n", iptc_strerror(errno)); } // if success ->add filter rule to internal rule list rule_list.insert(make_pair(rule_id, nfre)); stats.rules++; // if in test mode immediatly delete the rule // FIXME: maybe escape earlier because of performance if (test) { this->delRule(rule_id); } saveDelete(optarg; for (i = 0; i<argc; i++) { saveDelete(argv[i]; } saveDelete(argv;}/* ------------------------- delRule ------------------------- */void ClassifierNetfilter::delRule( int ruleID ){ int ret = 1; unsigned int options = 0; struct netfilter_rule_entry *nfre; rule_map_itor_t itor; MLOG( "ClassifierNetfilter : removing Rule #%d", ruleID ); // get rule ipt_entry#ifdef CLASS_DEBUG fprintf(stderr, "delete rule %d\n", ruleID);#endif#ifdef LOOPFULL maxid--; return;#endif // delete all rules with that ruleID // there could be 1 rule in case of unidir match or // 2 rules in case of bidir match while ((itor = rule_list.find(ruleID)) != rule_list.end()) { nfre = itor->second;#ifdef CLASS_DEBUG fprintf(stderr, "rule %d found\n", ruleID);#endif // delete NetFilter rule ret = delete_entry(chain, nfre->e, nfre->nsaddrs, &nfre->saddrs, nfre->ndaddrs, &nfre->daddrs, options, iptc_h); if (!ret) exit_error(PARAMETER_PROBLEM, "%s\n", iptc_strerror(errno)); ret = iptc_commit(iptc_h); // respawn handle, thanx rusty *iptc_h = iptc_init(table); if (!ret) exit_error(PARAMETER_PROBLEM, "%s\n", iptc_strerror(errno)); #ifdef CLASS_DEBUG fprintf(stderr, "rule deleted from netfilter\n");#endif // delete entry from internal rule_list delete_rule_entry(nfre); rule_list.erase(itor); stats.rules--;#ifdef CLASS_DEBUG fprintf(stderr, "rule deleted from internal list\n");#endif }}/* ------------------------- getStats ------------------------- */ClassifierStats *ClassifierNetfilter::getStats(){ // adjust values return &stats;}/* ------------------------- dump ------------------------- */void ClassifierNetfilter::dump( ostream &os ){ os << "Classifier dump : packets " << stats.packets << endl; os << " bytes " << stats.bytes << endl; os << " rules " << stats.rules << endl; // write classifier information to os stream}/* ------------------------- operator<< ------------------------- */ostream& operator<< ( ostream &os, ClassifierNetfilter &cl ){ cl.dump(os); return os;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -