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

📄 ipfieldinfo.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
字号:
/* * ipfieldinfo.{cc,hh} -- IP-packet filter with tcpdumplike syntax * Eddie Kohler * * Copyright (c) 2005 Regents of the University of California * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, subject to the conditions * listed in the Click LICENSE file. These conditions include: you must * preserve this copyright notice, and you cannot mention the copyright * holders in advertising related to the Software without their permission. * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This * notice is a summary of the Click LICENSE file; the license in that file is * legally binding. */#include <click/config.h>#include "ipfieldinfo.hh"#include <click/integers.hh>#include <click/confparse.hh>#include <click/error.hh>#include <stdarg.h>CLICK_DECLS#define BITFIELD(proto, offset, length)			\	(((proto) << IPField::PROTO_SHIFT)		\	| ((offset) << IPField::OFFSET_SHIFT)		\	| (((length) - 1) << IPField::LENGTH_SHIFT)	\	| IPField::MARKER)static const StaticNameDB::Entry ip_fields[] = {    { "df",	BITFIELD(0, 6*8 + 1, 1) },    { "dport",	BITFIELD(IP_PROTO_TCP_OR_UDP, 2*8, 16) },    { "dscp",	BITFIELD(0, 1*8, 6) },    { "dst",	BITFIELD(0, 16*8, 32) },    { "ecn",	BITFIELD(0, 1*8 + 6, 2) },    { "fragoff",BITFIELD(0, 6*8 + 3, 13) },    { "hl",	BITFIELD(0, 4, 4) },    { "id",	BITFIELD(0, 4*8, 16) },    { "len",	BITFIELD(0, 2*8, 16) },    { "mf",	BITFIELD(0, 6*8 + 2, 1) },    { "off",	BITFIELD(0, 6*8, 16) },    { "proto",	BITFIELD(0, 9*8, 8) },    { "rf",	BITFIELD(0, 6*8, 1) },    { "sport",	BITFIELD(IP_PROTO_TCP_OR_UDP, 0, 16) },    { "src",	BITFIELD(0, 12*8, 32) },    { "sum",	BITFIELD(0, 10*8, 16) },    { "tos",	BITFIELD(0, 1*8, 8) },    { "ttl",	BITFIELD(0, 8*8, 8) },    { "vers",	BITFIELD(0, 0, 4) }};static const StaticNameDB::Entry udp_fields[] = {    { "dport",	BITFIELD(IP_PROTO_UDP, 2*8, 16) },    { "len",	BITFIELD(IP_PROTO_UDP, 4*8, 16) },    { "sport",	BITFIELD(IP_PROTO_UDP, 0, 16) },    { "sum",	BITFIELD(IP_PROTO_UDP, 6*8, 16) }};static const StaticNameDB::Entry tcp_fields[] = {    { "ackno",	BITFIELD(IP_PROTO_TCP, 8*8, 32) },    { "ack",	BITFIELD(IP_PROTO_TCP, 13*8+3, 1) },    { "dport",	BITFIELD(IP_PROTO_TCP, 2*8, 16) },    { "fin",	BITFIELD(IP_PROTO_TCP, 13*8+7, 1) },    { "flags",	BITFIELD(IP_PROTO_TCP, 13*8, 8) },    { "hl",	BITFIELD(IP_PROTO_TCP, 12*8, 4) },    { "psh",	BITFIELD(IP_PROTO_TCP, 13*8+4, 1) },    { "push",	BITFIELD(IP_PROTO_TCP, 13*8+4, 1) },    { "rst",	BITFIELD(IP_PROTO_TCP, 13*8+5, 1) },    { "seq",	BITFIELD(IP_PROTO_TCP, 4*8, 32) },    { "seqno",	BITFIELD(IP_PROTO_TCP, 4*8, 32) },    { "sport",	BITFIELD(IP_PROTO_TCP, 0, 16) },    { "sum",	BITFIELD(IP_PROTO_TCP, 16*8, 16) },    { "syn",	BITFIELD(IP_PROTO_TCP, 13*8+6, 1) },    { "urg",	BITFIELD(IP_PROTO_TCP, 13*8+2, 1) },    { "urp",	BITFIELD(IP_PROTO_TCP, 18*8, 16) },    { "win",	BITFIELD(IP_PROTO_TCP, 14*8, 16) }};static const StaticNameDB::Entry icmp_fields[] = {    { "code",	BITFIELD(IP_PROTO_ICMP, 1*8, 8) },    { "sum",	BITFIELD(IP_PROTO_ICMP, 2*8, 16) },    { "type",	BITFIELD(IP_PROTO_ICMP, 0*8, 8) }};static const StaticNameDB::Entry tcp_or_udp_fields[] = {    { "dport",	BITFIELD(IP_PROTO_TCP_OR_UDP, 2*8, 16) },    { "sport",	BITFIELD(IP_PROTO_TCP_OR_UDP, 0, 16) }};IPField::IPField(int proto, int bit_offset, int bit_length){    if (proto >= 0 && proto <= MAX_PROTO && bit_offset >= 0 && bit_length >= 0) {	if (bit_offset <= MAX_OFFSET && bit_length <= MAX_LENGTH + 1)	    _val = (proto << PROTO_SHIFT) | (bit_offset << OFFSET_SHIFT) | ((bit_length - 1) << LENGTH_SHIFT) | MARKER;	else if ((bit_offset & 7) == 0 && (bit_length & 7) == 0 && bit_length <= (MAX_LENGTH + 1) << 3)	    _val = (proto << PROTO_SHIFT) | BYTES | ((bit_offset >> 3) << OFFSET_SHIFT) | (((bit_length >> 3) - 1) << LENGTH_SHIFT) | MARKER;	else	    _val = -1;    } else	_val = -1;}static NameDB *dbs[5];voidIPFieldInfo::static_initialize(){    dbs[0] = new StaticNameDB(NameInfo::T_IP_FIELDNAME, String(), ip_fields, sizeof(ip_fields) / sizeof(ip_fields[0]));    dbs[1] = new StaticNameDB(NameInfo::T_ICMP_FIELDNAME, String(), icmp_fields, sizeof(icmp_fields) / sizeof(icmp_fields[0]));    dbs[2] = new StaticNameDB(NameInfo::T_TCP_FIELDNAME, String(), tcp_fields, sizeof(tcp_fields) / sizeof(tcp_fields[0]));    dbs[3] = new StaticNameDB(NameInfo::T_UDP_FIELDNAME, String(), udp_fields, sizeof(udp_fields) / sizeof(udp_fields[0]));    dbs[4] = new StaticNameDB(NameInfo::T_IP_FIELDNAME + IP_PROTO_TCP_OR_UDP, String(), tcp_or_udp_fields, sizeof(tcp_or_udp_fields) / sizeof(tcp_or_udp_fields[0]));    for (int i = 0; i < 5; i++)	if (dbs[i])	    NameInfo::installdb(dbs[i], 0);}voidIPFieldInfo::static_cleanup(){    for (int i = 0; i < 5; i++)	if (dbs[i]) {	    NameInfo::removedb(dbs[i]);	    delete dbs[i];	    dbs[i] = 0;	}}const char *cp_scanf(const char *begin, const char *end, const char *format, ...){    const char *s, *ss;    bool must_space = false;    uint32_t delimiters[8];    bool know_delimiters = false;        va_list val;    va_start(val, format);        for (s = begin; *format; format++)	if (*format == ' ') {	    if (must_space && format[1] != '%' && (s == end || !isspace((unsigned char) *s)))		goto kill;	    while (s < end && isspace((unsigned char) *s))		s++;	    must_space = false;	} else if (*format == '%') {	    format++;	    switch (*format) {	      case 'u': {		  uint32_t *d = va_arg(val, uint32_t *);		  if ((ss = cp_unsigned(s, end, 0, d)) == s)		      goto kill;		  s = ss;		  must_space = false;		  break;	      }	      case 'N': {		  uint32_t nametype = va_arg(val, uint32_t);		  Element *elt = va_arg(val, Element *);		  const char *w = s;		  while (s < end && !isspace((unsigned char) *s) && (!know_delimiters || !(delimiters[((unsigned char) *s) >> 5] & (1 << (((unsigned char) *s) % 32)))))		      s++;		  uint32_t *store = va_arg(val, uint32_t *);		  if (w == s || !NameInfo::query(nametype, elt, String(w, s), store, sizeof(*store)))		      goto kill;		  must_space = false;		  break;	      }	      case 'D': {		  const char *delim = va_arg(val, const char *);		  if (!know_delimiters)		      memset(delimiters, 0, sizeof(delimiters));		  for (; *delim; delim++)		      delimiters[((unsigned char) *delim) >> 5] |= (1 << (((unsigned char) *delim) % 32));		  know_delimiters = true;		  break;	      }	      case 'B':		if (s != end && (isalnum((unsigned char) *s) || *s == '_'))		    goto kill;		break;	      case '%':		goto normal;	    }	} else {	  normal:	    if (s == end || *s != *format)		goto kill;	    s++;	    must_space = true;	}    va_end(val);    return s;  kill:    va_end(val);    return 0;}static const char * const cp_ip_field_messages[] = {    "expected 'HEADER [NAME] [{OFFSET:LENGTH}] [/PREFIX] [& MASK]'",    "bad offset or length in TCP/IP field",    "bad prefix or mask in TCP/IP field"};static const char *cp_ip_field_helper(const char *begin, int which, ErrorHandler *errh){    if (errh)	errh->error(cp_ip_field_messages[which]);    return begin;}const char *IPField::parse(const char *begin, const char *end, int proto, IPField *result, ErrorHandler *errh, Element *elt){    // determine header, if any    int32_t header = -1;    const char *ehdr;    if ((ehdr = cp_scanf(begin, end, "ip proto %u", &header)))	/* OK */;    else if ((ehdr = cp_scanf(begin, end, "ip%B")))	header = 0;    else if ((ehdr = cp_scanf(begin, end, "%N", NameInfo::T_IP_PROTO, elt, &header)))	/* OK */;    else if ((header = proto) < 0)	return cp_ip_field_helper(begin, 0, errh);    // field name    IPField field(-1);    const char *enam;    if ((enam = cp_scanf(ehdr, end, " %D%N", "/[{&", NameInfo::T_IP_FIELDNAME + header, elt, &field)))	/* OK */;    else	enam = ehdr;    // limitation    int32_t offset = -1, length = -1;    const char *elim;    if ((elim = cp_scanf(enam, end, " [ %u ]", &offset)))	offset *= 8, length = 8;    else if ((elim = cp_scanf(enam, end, " [ %u : %u ]", &offset, &length)))	offset *= 8, length *= 8;    else if ((elim = cp_scanf(enam, end, " [ %u - %u ]", &offset, &length)))	offset *= 8, length = (length - offset + 1) * 8;    else if ((elim = cp_scanf(enam, end, " { %u }", &offset)))	length = 1;    else if ((elim = cp_scanf(enam, end, " { %u : %u }", &offset, &length)))	/* OK */;    else if ((elim = cp_scanf(enam, end, " { %u - %u }", &offset, &length)))	length = length - offset + 1;    else if (!field.ok()) {	click_chatter("%.*s", end - enam, enam); 	return cp_ip_field_helper(begin, 0, errh);}    else	elim = enam;    if (offset >= 0 && length <= 0)	return cp_ip_field_helper(begin, 1, errh);    if (field.ok() && (offset >= field.bit_length() || offset + length > field.bit_length()))	return cp_ip_field_helper(begin, 1, errh);    else if (field.ok() && offset >= 0)	field = IPField(field.proto(), field.bit_offset() + offset, length);    else if (offset >= 0)	field = IPField(header, offset, length);    else if (!field.ok())	return cp_ip_field_helper(begin, 1, errh);        // limitations    const char *epfx, *emask;    if ((epfx = cp_scanf(elim, end, " / %u", &length))) {	if (length > field.bit_length())	    return cp_ip_field_helper(begin, 2, errh);	field = IPField(field.proto(), field.bit_offset(), length);    } else	epfx = elim;    if ((emask = cp_scanf(epfx, end, " & %u", &length))) {	offset = ffs_lsb((uint32_t) length) - 1;	int msb = ffs_lsb((uint32_t) length + (1 << offset)) - 1;	if (length == 0 || ((length + (1 << offset)) & (length + (1 << offset) - 1)) != 0 || msb > field.bit_length())	    return cp_ip_field_helper(begin, 2, errh);	field = IPField(field.proto(), field.bit_offset() + field.bit_length() - msb, msb - offset);    } else	emask = epfx;    *result = field;    return emask;}StringIPField::unparse(Element *elt, bool tcpdump_rules){    if (!ok())	return String::stable_string("<bad>");        String protstr;    int32_t val = proto();    if (val == 0)	protstr = "ip";    else if ((protstr = NameInfo::revquery(NameInfo::T_IP_PROTO, elt, &val, 4)))	/* OK */;    else	protstr = "ip proto " + String(proto());        String s;    if ((s = NameInfo::revquery(NameInfo::T_IP_FIELDNAME + proto(), elt, &_val, 4)))	return protstr + " " + s;    int bo = bit_offset(), bl = bit_length();    for (int container = 8; container < 64 && !tcpdump_rules; container *= 2)	if (bo / container == (bo + bl - 1) / container) {	    IPField x(proto(), bo & ~(container - 1), container);	    if ((s = NameInfo::revquery(NameInfo::T_IP_FIELDNAME + proto(), elt, &x, 4))) {		protstr += " " + s;		bo &= container - 1;		if (bo == 0)		    return protstr + "/" + String(bl);		break;	    }	}    String mask;    if (tcpdump_rules && (bo % 8 != 0 || bl % 8 != 0)	&& bl / 32 == (bo + bl - 1) / 32) {	uint32_t maskval = ((1 << bl) - 1) << (7 - (bo + bl - 1) % 8);	mask = " & " + String(maskval);	bl = (bo % 8 + bl + 7) & ~7;	bo &= ~7;    }    if (bo % 8 == 0 && bl == 8)	return protstr + "[" + String(bo / 8) + "]" + mask;    else if (bo % 8 == 0 && bl % 8 == 0)	return protstr + "[" + String(bo / 8) + ":" + String(bl / 8) + "]" + mask;    else if (bl == 1)	return protstr + "{" + String(bo) + "}" + mask;    else	return protstr + "{" + String(bo) + ":" + String(bl) + "}" + mask;}CLICK_ENDDECLSEXPORT_ELEMENT(IPFieldInfo)

⌨️ 快捷键说明

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