⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ipfilter.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
📖 第 1 页 / 共 3 页
字号:
      blank_ok = false;      next++;    }    pos = next;  }  if (!blank_ok)    errh->error("missing term");  finish_expr_subtree(tree);  return pos;}static intparse_brackets(IPFilter::Primitive& prim, const Vector<String>& words, int pos,	       ErrorHandler* errh){  int first_pos = pos + 1;  String combination;  for (pos++; pos < words.size() && words[pos] != "]"; pos++)    combination += words[pos];  if (pos >= words.size()) {    errh->error("missing ']'");    return first_pos;  }  pos++;  // parse 'combination'  int fieldpos, len = 1;  const char* colon = find(combination.begin(), combination.end(), ':');  const char* comma = find(combination.begin(), combination.end(), ',');  if (colon < combination.end() - 1) {    if (cp_integer(combination.begin(), colon, 0, &fieldpos) == colon	&& cp_integer(colon + 1, combination.end(), 0, &len) == combination.end())      goto non_syntax_error;  } else if (comma < combination.end() - 1) {    int pos2;    if (cp_integer(combination.begin(), comma, 0, &fieldpos) == comma	&& cp_integer(comma + 1, combination.end(), 0, &pos2) == combination.end()) {      len = pos2 - fieldpos + 1;      goto non_syntax_error;    }  } else if (cp_integer(combination, &fieldpos))    goto non_syntax_error;  errh->error("syntax error after '[', expected '[POS]' or '[POS:LEN]'");  return pos; non_syntax_error:  if (len < 1 || len > 4)    errh->error("LEN in '[POS:LEN]' out of range, should be between 1 and 4");  else if ((fieldpos & ~3) != ((fieldpos + len - 1) & ~3))    errh->error("field [%d:%d] does not fit in a single word", fieldpos, len);  else if (prim._transp_proto == IPFilter::UNKNOWN)    prim.set_type(IPFilter::TYPE_FIELD | ((fieldpos*8) << IPFilter::FIELD_OFFSET_SHIFT) | ((len*8 - 1) << IPFilter::FIELD_LENGTH_SHIFT), errh);  else    prim.set_type(IPFilter::TYPE_FIELD | (prim._transp_proto << IPFilter::FIELD_PROTO_SHIFT) | ((fieldpos*8) << IPFilter::FIELD_OFFSET_SHIFT) | ((len*8 - 1) << IPFilter::FIELD_LENGTH_SHIFT), errh);  return pos;}intIPFilter::parse_factor(const Vector<String> &words, int pos,		       Vector<int> &tree, Primitive &prev_prim,		       bool negated, ErrorHandler *errh){  // return immediately on last word, ")", "||", "or", "?", ":"  if (pos >= words.size() || words[pos] == ")" || words[pos] == "||" || words[pos] == "or" || words[pos] == "?" || words[pos] == ":")    return pos;  // easy cases    // 'true' and 'false'  if (words[pos] == "true") {    add_expr(tree, 0, 0, 0);    if (negated)      negate_expr_subtree(tree);    return pos + 1;  }  if (words[pos] == "false") {    add_expr(tree, 0, 0, 0);    if (!negated)      negate_expr_subtree(tree);    return pos + 1;  }  // ! factor  if (words[pos] == "not" || words[pos] == "!") {    int next = parse_factor(words, pos + 1, tree, prev_prim, !negated, errh);    if (next == pos + 1)      errh->error("missing factor after '%s'", words[pos].c_str());    return next;  }  // ( expr )  if (words[pos] == "(") {    int next = parse_expr(words, pos + 1, tree, prev_prim, errh);    if (next == pos + 1)      errh->error("missing expression after '('");    if (next >= 0) {      if (next >= words.size() || words[next] != ")")	errh->error("missing ')'");      else	next++;      if (negated)	negate_expr_subtree(tree);    }    return next;  }  // hard case    // expect quals [relop] data  int first_pos = pos;  Primitive prim;  // collect qualifiers  for (; pos < words.size(); pos++) {    String wd = words[pos];    uint32_t wdata;    int wt = lookup(wd, 0, UNKNOWN, wdata, 0);    if (wt >= 0 && wt == TYPE_TYPE) {      prim.set_type(wdata, errh);      if ((wdata & TYPE_FIELD) && (wdata & FIELD_PROTO_MASK))	prim.set_transp_proto((wdata & FIELD_PROTO_MASK) >> FIELD_PROTO_SHIFT, errh);    } else if (wt >= 0 && wt == TYPE_PROTO)      prim.set_transp_proto(wdata, errh);    else if (wt != -1)      break;    else if (wd == "src") {      if (pos < words.size() - 2 && (words[pos+2] == "dst" || words[pos+2] == "dest")) {	if (words[pos+1] == "and" || words[pos+1] == "&&") {	  prim.set_srcdst(SD_AND, errh);	  pos += 2;	} else if (words[pos+1] == "or" || words[pos+1] == "||") {	  prim.set_srcdst(SD_OR, errh);	  pos += 2;	} else	  prim.set_srcdst(SD_SRC, errh);      } else	prim.set_srcdst(SD_SRC, errh);    } else if (wd == "dst" || wd == "dest")      prim.set_srcdst(SD_DST, errh);        else if (wd == "ip")      /* nada */;        else if (wd == "not" || wd == "!")      negated = !negated;          else      break;  }  // prev_prim is not relevant if there were any qualifiers  if (pos != first_pos)    prev_prim.clear();  // optional [] syntax  String wd = (pos >= words.size() - 1 ? String() : words[pos]);  if (wd == "[" && pos > first_pos && prim._type == TYPE_NONE) {    pos = parse_brackets(prim, words, pos, errh);    wd = (pos >= words.size() - 1 ? String() : words[pos]);  }  // optional bitmask  uint32_t provided_mask = 0;  if (wd == "&" && pos < words.size() - 1      && cp_unsigned(words[pos + 1], &provided_mask)) {      pos += 2;      wd = (pos >= words.size() - 1 ? String() : words[pos]);      if (provided_mask == 0)	  errh->error("bitmask of 0 ignored");  }    // optional relational operation  pos++;  if (wd == "=" || wd == "==")    /* nada */;  else if (wd == "!=")    prim._op_negated = true;  else if (wd == ">")    prim._op = OP_GT;  else if (wd == "<")    prim._op = OP_LT;  else if (wd == ">=") {    prim._op = OP_LT;    prim._op_negated = true;  } else if (wd == "<=") {    prim._op = OP_GT;    prim._op_negated = true;  } else    pos--;    // now collect the actual data  if (pos < words.size()) {    wd = words[pos];    uint32_t wdata;    int wt = lookup(wd, prim._type, prim._transp_proto, wdata, errh);    pos++;        if (wt == -2)		// ambiguous or incorrect word type      /* absorb word, but do nothing */      prim._type = -2;    else if (wt != -1 && wt != TYPE_TYPE) {      prim._data = wt;      prim._u.u = wdata;    } else if (cp_integer(wd, &prim._u.i))      prim._data = TYPE_INT;      else if (cp_ip_address(wd, prim._u.c, this)) {      if (pos < words.size() - 1 && words[pos] == "mask"	  && cp_ip_address(words[pos+1], prim._mask.c, this)) {	pos += 2;	prim._data = TYPE_NET;      } else if (prim._type == TYPE_NET && cp_ip_prefix(wd, prim._u.c, prim._mask.c, this))	prim._data = TYPE_NET;      else	prim._data = TYPE_HOST;        } else if (cp_ip_prefix(wd, prim._u.c, prim._mask.c, this))      prim._data = TYPE_NET;    else {      if (prim._op != OP_EQ || prim._op_negated)	errh->error("dangling operator near '%s'", wd.cc());      pos--;    }  }  if (pos == first_pos) {    errh->error("empty term near '%s'", wd.cc());    return pos;  }    // add if it is valid  if (prim.check(prev_prim, provided_mask, errh) >= 0) {    prim.add_exprs(this, tree);    if (negated)      negate_expr_subtree(tree);    prev_prim = prim;  }  return pos;}intIPFilter::configure(Vector<String> &conf, ErrorHandler *errh){  int before_nerrors = errh->nerrors();  _output_everything = -1;  // requires packet headers be aligned  _align_offset = 0;  Vector<int> tree;  init_expr_subtree(tree);    // [QUALS] [host|net|port|proto] [data]  // QUALS ::= src | dst | src and dst | src or dst | \empty  //        |  ip | icmp | tcp | udp  for (int argno = 0; argno < conf.size(); argno++) {    Vector<String> words;    separate_text(cp_unquote(conf[argno]), words);    if (words.size() == 0) {      errh->error("empty pattern %d", argno);      continue;    }    PrefixErrorHandler cerrh(errh, "pattern " + String(argno) + ": ");        // get slot    int slot = noutputs();    {      String slotwd = words[0];      if (slotwd == "allow") {	slot = 0;	if (noutputs() == 0)	  cerrh.error("'allow' is meaningless, element has zero outputs");      } else if (slotwd == "deny") {	slot = noutputs();	if (noutputs() > 1)	  cerrh.warning("meaning of 'deny' has changed (now it means 'drop')");      } else if (slotwd == "drop")	slot = noutputs();      else if (cp_integer(slotwd, &slot)) {	if (slot < 0 || slot >= noutputs()) {	  cerrh.error("slot '%d' out of range", slot);	  slot = noutputs();	}      } else	cerrh.error("unknown slot ID '%s'", slotwd.cc());    }    start_expr_subtree(tree);    // check for "-"    if (words.size() == 1 || (words.size() == 2 && words[1] == "-")	|| (words.size() == 2 && words[1] == "any")	|| (words.size() == 2 && words[1] == "all"))      add_expr(tree, 0, 0, 0);    else {      // start with a blank primitive      Primitive prev_prim;            int pos = parse_expr(words, 1, tree, prev_prim, &cerrh);      if (pos < words.size())	cerrh.error("garbage after expression at '%s'", words[pos].c_str());    }        finish_expr_subtree(tree, C_AND, -slot);  }  finish_expr_subtree(tree, C_OR, -noutputs(), -noutputs());    //{ String sxxx = program_string(this, 0); click_chatter("%s", sxxx.cc()); }  optimize_exprs(errh);  //{ String sxxx = program_string(this, 0); click_chatter("%s", sxxx.cc()); }  return (errh->nerrors() == before_nerrors ? 0 : -1);}//// RUNNING//voidIPFilter::length_checked_push(Packet *p){  const unsigned char *neth_data = (const unsigned char *)p->ip_header();  const unsigned char *transph_data = (const unsigned char *)p->transport_header();  int packet_length = p->length() + TRANSP_FAKE_OFFSET - p->transport_header_offset();  Expr *ex = &_exprs[0];	// avoid bounds checking  int pos = 0;    do {    int off = ex[pos].offset;    unsigned data;    if (off + 4 > packet_length)      goto check_length;       length_ok:    if (off >= TRANSP_FAKE_OFFSET)      data = *(const unsigned *)(transph_data + off - TRANSP_FAKE_OFFSET);    else      data = *(const unsigned *)(neth_data + off);    if ((data & ex[pos].mask.u)	== ex[pos].value.u)      pos = ex[pos].yes;    else      pos = ex[pos].no;    continue;       check_length:    if (ex[pos].offset < packet_length) {      unsigned available = packet_length - ex[pos].offset;      if (!(ex[pos].mask.c[3]	    || (ex[pos].mask.c[2] && available <= 2)	    || (ex[pos].mask.c[1] && available == 1)))	goto length_ok;    }    pos = ex[pos].no;  } while (pos > 0);    checked_output_push(-pos, p);}voidIPFilter::push(int, Packet *p){  const unsigned char *neth_data = (const unsigned char *)p->ip_header();  const unsigned char *transph_data = (const unsigned char *)p->transport_header();  Expr *ex;  int pos = 0;    if (_output_everything >= 0) {    // must use checked_output_push because the output number might be    // out of range    pos = -_output_everything;    goto found;  } else if (p->length() + TRANSP_FAKE_OFFSET - p->transport_header_offset() < _safe_length) {    // common case never checks packet length    length_checked_push(p);    return;  }    ex = &_exprs[0];	// avoid bounds checking    do {    int off = ex[pos].offset;    unsigned data;    if (off >= TRANSP_FAKE_OFFSET)      data = *(const unsigned *)(transph_data + off - TRANSP_FAKE_OFFSET);    else      data = *(const unsigned *)(neth_data + off);    if ((data & ex[pos].mask.u)	== ex[pos].value.u)      pos = ex[pos].yes;    else      pos = ex[pos].no;  } while (pos > 0);   found:  checked_output_push(-pos, p);}CLICK_ENDDECLSELEMENT_REQUIRES(Classifier)EXPORT_ELEMENT(IPFilter)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -