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

📄 ipsumdumpinfo.cc

📁 Click is a modular router toolkit. To use it you ll need to know how to compile and install the sof
💻 CC
字号:
// -*- mode: c++; c-basic-offset: 4 -*-/* * ipsumdumpinfo.{cc,hh} -- information used by IP summary dump elements * Eddie Kohler * * Copyright (c) 2002 International Computer Science Institute * Copyright (c) 2004 Regents of the University of California * Copyright (c) 2008 Meraki, Inc. * * 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 "ipsumdumpinfo.hh"#include <click/packet.hh>#include <click/packet_anno.hh>#include <click/confparse.hh>#include <click/ipflowid.hh>#include <clicknet/ip.h>#include <clicknet/tcp.h>#include <clicknet/udp.h>CLICK_DECLSstatic Vector<const void *> *writers;static Vector<const void *> *readers;static Vector<const void *> *synonyms;static void field_add(Vector<const void *> *&vec, const void *value){    if (!vec)	vec = new Vector<const void *>;    vec->push_back(value);}static void field_remove(Vector<const void *> *&vec, const void *value){    if (vec) {	const void **x = find(vec->begin(), vec->end(), value);	if (x != vec->end())	    vec->erase(x);    }}static const void *field_find(Vector<const void *> *&vec, const String &name){    if (vec)	for (const void **x = vec->begin(); x != vec->end(); ++x) {	    const IPSummaryDump::FieldSynonym *fs = reinterpret_cast<const IPSummaryDump::FieldSynonym *>(*x);	    if (name == fs->name)		return *x;	}    return 0;}void IPSummaryDumpInfo::static_cleanup(){    delete writers;    delete readers;    delete synonyms;    writers = readers = synonyms = 0;}/////////////////////// PARSINGnamespace IPSummaryDump {void FieldWriter::add(const FieldWriter *w){    field_add(writers, w);}void FieldWriter::remove(const FieldWriter *w){    field_remove(writers, w);}void FieldReader::add(const FieldReader *r){    field_add(readers, r);}void FieldReader::remove(const FieldReader *r){    field_remove(readers, r);}void FieldSynonym::add(const FieldSynonym *s){    field_add(synonyms, s);}void FieldSynonym::remove(const FieldSynonym *s){    field_remove(synonyms, s);}static String update_name(const String &name){    // change spaces to underscores    const char *s = find(name, ' ');    if (s != name.end())	return name.substring(name.begin(), s) + "_"	    + name.substring(s + 1, name.end());    // change "X" to "ip_X"    if (find(name, '_') == name.end())	return "ip_" + name;    // not found    return String();}static bool none_extract(PacketDesc &, const FieldWriter *){    return false;}const FieldReader null_reader = {    "none", B_0, 0, order_anno,    num_ina, inb, 0};const FieldWriter null_writer = {    "none", B_0, 0,    0, none_extract, num_outa, outb};const FieldReader *FieldReader::find(const String &name){    if (const void *x = field_find(synonyms, name)) {	const FieldSynonym *s = reinterpret_cast<const FieldSynonym *>(x);	return find(s->synonym);    }    if (const void *x = field_find(readers, name))	return reinterpret_cast<const FieldReader *>(x);    if (String new_name = update_name(name))	return find(new_name);    return 0;}const FieldWriter *FieldWriter::find(const String &name){    if (const void *x = field_find(synonyms, name)) {	const FieldSynonym *s = reinterpret_cast<const FieldSynonym *>(x);	return find(s->synonym);    }    if (const void *x = field_find(writers, name))	return reinterpret_cast<const FieldWriter *>(x);    if (String new_name = update_name(name))	return find(new_name);    return 0;}static const char *field_missing_proto_name(int proto){    switch (proto) {      case IP_PROTO_TCP:	return "TCP";      case IP_PROTO_UDP:	return "UDP";      case IP_PROTO_ICMP:	return "ICMP";      case IP_PROTO_TCP_OR_UDP:	return "TCP/UDP";      default:	return "?";    }}bool hard_field_missing(const PacketDesc &d, int proto, int l){    if (d.bad_sa && !*d.bad_sa) {	if (proto == MISSING_ETHERNET)	    *d.bad_sa << "!bad Ethernet header\n";	else if (!d.iph)	    *d.bad_sa << "!bad no IP header\n";	else if (proto == MISSING_IP)	    *d.bad_sa << "!bad truncated IP header capture\n";	else if (d.p->network_length() > (int) offsetof(click_ip, ip_p)		 && ((proto > MISSING_IP && proto < 256		      && d.iph->ip_p != proto)		     || (proto == IP_PROTO_TCP_OR_UDP			 && d.iph->ip_p != IP_PROTO_TCP			 && d.iph->ip_p != IP_PROTO_UDP)))	    // wrong protocol is a silent error, not a bad packet	    return false;	else if (!IP_FIRSTFRAG(d.iph))	    *d.bad_sa << "!bad fragmented " << field_missing_proto_name(proto) << " header\n";	else if ((int) (d.p->transport_length() + EXTRA_LENGTH_ANNO(d.p)) >= l)	    *d.bad_sa << "!bad truncated " << field_missing_proto_name(proto) << " header capture\n";	else	    *d.bad_sa << "!bad truncated " << field_missing_proto_name(proto) << " header\n";    }    return false;}#ifdef i386# define PUT4NET(p, d)	*reinterpret_cast<uint32_t *>((p)) = (d)# define PUT4(p, d)	*reinterpret_cast<uint32_t *>((p)) = htonl((d))# define PUT2(p, d)	*reinterpret_cast<uint16_t *>((p)) = htons((d))# define GET4NET(p)	*reinterpret_cast<const uint32_t *>((p))# define GET4(p)	ntohl(*reinterpret_cast<const uint32_t *>((p)))# define GET2(p)	ntohs(*reinterpret_cast<const uint16_t *>((p)))#else# define PUT4NET(p, d)	do { uint32_t d__ = ntohl((d)); (p)[0] = d__>>24; (p)[1] = d__>>16; (p)[2] = d__>>8; (p)[3] = d__; } while (0)# define PUT4(p, d)	do { (p)[0] = (d)>>24; (p)[1] = (d)>>16; (p)[2] = (d)>>8; (p)[3] = (d); } while (0)# define PUT2(p, d)	do { (p)[0] = (d)>>8; (p)[1] = (d); } while (0)# define GET4NET(p)	htonl((p)[0]<<24 | (p)[1]<<16 | (p)[2]<<8 | (p)[3])# define GET4(p)	((p)[0]<<24 | (p)[1]<<16 | (p)[2]<<8 | (p)[3])# define GET2(p)	((p)[0]<<8 | (p)[1])#endif#define PUT1(p, d)	((p)[0] = (d))void num_outa(const PacketDesc& d, const FieldWriter *f){    if (f->type == B_8) {#if HAVE_INT64_TYPES	uint64_t v = ((uint64_t) d.u32[1] << 32) | d.u32[0];	*d.sa << v;#else	// XXX silently truncate large numbers	*d.sa << d.u32[0];#endif    } else	*d.sa << d.v;}bool num_ina(PacketOdesc& d, const String &s, const FieldReader *f){#if HAVE_INT64_TYPES    if (f->type == B_8) {	uint64_t v;	if (!cp_integer(s, &v))	    return false;	d.u32[0] = v;	d.u32[1] = v >> 32;	return true;    }#else    // XXX die on large numbers#endif    if (!cp_integer(s, &d.v))	return false;    if ((f->type == B_1 && d.v > 255) || (f->type == B_2 && d.v > 65535))	return false;    return true;}void outb(const PacketDesc& d, bool, const FieldWriter *f){    switch (f->type) {      case B_0:	break;      case B_1: {	  char* c = d.sa->extend(1);	  PUT1(c, d.v);	  break;      }      case B_2: {	  char* c = d.sa->extend(2);	  PUT2(c, d.v);	  break;      }      case B_4: {	  char* c = d.sa->extend(4);	  PUT4(c, d.v);	  break;      }      case B_6PTR: {	  char* c = d.sa->extend(6);	  memcpy(c, d.vptr, 6);	  break;      }      case B_8: {	  char* c = d.sa->extend(8);	  PUT4(c, d.u32[1]);	  PUT4(c + 4, d.u32[0]);	  break;      }      case B_4NET: {	  char* c = d.sa->extend(4);	  PUT4NET(c, d.v);	  break;      }    }}const uint8_t *inb(PacketOdesc& d, const uint8_t *s, const uint8_t *end, const FieldReader *f){    d.v = 0;    switch (f->type) {      case B_0:	return s;      case B_1:	if (s >= end)	    goto bad;	d.v = s[0];	return s + 1;      case B_2:	if (s + 1 >= end)	    goto bad;	d.v = GET2(s);	return s + 2;      case B_4:	if (s + 3 >= end)	    goto bad;	d.v = GET4(s);	return s + 4;    case B_6PTR:	if (s + 5 >= end)	    goto bad;	memcpy(d.u8, s, 6);	return s + 6;      case B_8:	if (s + 7 >= end)	    goto bad;	d.u32[1] = GET4(s);	d.u32[0] = GET4(s + 4);	return s + 8;      case B_4NET:	if (s + 3 >= end)	    goto bad;	d.v = GET4NET(s);	return s + 4;      bad:      default:	d.clear_values();	return end;    }}void ip_prepare(PacketDesc& d, const FieldWriter *){    Packet* p = d.p;    d.iph = (p->has_network_header() ? p->ip_header() : 0);    d.tcph = (p->has_transport_header() ? p->tcp_header() : 0);    d.udph = (p->has_transport_header() ? p->udp_header() : 0);    d.icmph = (p->has_transport_header() ? p->icmp_header() : 0);#define BAD(msg, hdr) do { if (d.bad_sa && !*d.bad_sa) *d.bad_sa << "!bad " << msg << '\n'; hdr = 0; } while (0)#define BAD2(msg, val, hdr) do { if (d.bad_sa && !*d.bad_sa) *d.bad_sa << "!bad " << msg << val << '\n'; hdr = 0; } while (0)    // check IP header    if (!d.iph)	/* nada */;    else if (p->network_length() < (int) offsetof(click_ip, ip_id))	BAD("truncated IP header", d.iph);    else if (d.iph->ip_v != 4)	BAD2("IP version ", d.iph->ip_v, d.iph);    else if (d.iph->ip_hl < (sizeof(click_ip) >> 2))	BAD2("IP header length ", d.iph->ip_hl, d.iph);    else if (ntohs(d.iph->ip_len) < (d.iph->ip_hl << 2))	BAD2("IP length ", ntohs(d.iph->ip_len), d.iph);    else {	// truncate packet length to IP length if necessary	int ip_len = ntohs(d.iph->ip_len);	if (p->network_length() > ip_len) {	    SET_EXTRA_LENGTH_ANNO(p, EXTRA_LENGTH_ANNO(p) + p->network_length() - ip_len);	    p->take(p->network_length() - ip_len);	} else if (d.careful_trunc && p->network_length() + EXTRA_LENGTH_ANNO(p) < (uint32_t) ip_len) {	    /* This doesn't actually kill the IP header. */	    int scratch;	    BAD2("truncated IP missing ", (ntohs(d.iph->ip_len) - p->network_length() - EXTRA_LENGTH_ANNO(p)), scratch);	}    }    // check TCP header    if (!d.iph || !d.tcph	|| p->network_length() <= (int)(d.iph->ip_hl << 2)	|| d.iph->ip_p != IP_PROTO_TCP	|| !IP_FIRSTFRAG(d.iph))	d.tcph = 0;    else if (p->transport_length() > 12	     && d.tcph->th_off < (sizeof(click_tcp) >> 2))	BAD2("TCP header length ", d.tcph->th_off, d.tcph);    // check UDP header    if (!d.iph || !d.udph	|| p->network_length() <= (int)(d.iph->ip_hl << 2)	|| d.iph->ip_p != IP_PROTO_UDP	|| !IP_FIRSTFRAG(d.iph))	d.udph = 0;    // check ICMP header    if (!d.iph || !d.icmph	|| p->network_length() <= (int)(d.iph->ip_hl << 2)	|| d.iph->ip_p != IP_PROTO_ICMP	|| !IP_FIRSTFRAG(d.iph))	d.icmph = 0;#undef BAD#undef BAD2    // Adjust extra length, since we calculate lengths here based on ip_len.    if (d.iph && EXTRA_LENGTH_ANNO(p) > 0) {	uint32_t full_len = p->length() + EXTRA_LENGTH_ANNO(p);	uint32_t ip_len = p->network_header_offset() + ntohs(d.iph->ip_len);	SET_EXTRA_LENGTH_ANNO(p, full_len > ip_len ? full_len - ip_len : 0);    }}bool PacketOdesc::hard_make_ip(){    if (!is_ip)	return false;    if (!p->has_network_header())	p->set_network_header(p->data(), 0);    if (p->network_length() < (int) sizeof(click_ip)) {	if (!(p = p->put(sizeof(click_ip) - p->network_length())))	    return false;	p->set_network_header(p->network_header(), sizeof(click_ip));	click_ip *iph = p->ip_header();	iph->ip_v = 4;	iph->ip_hl = sizeof(click_ip) >> 2;	iph->ip_p = default_ip_p;	iph->ip_len = 0;	iph->ip_off = 0;	iph->ip_ttl = 100;	if (default_ip_flowid) {	    iph->ip_src.s_addr = default_ip_flowid->saddr().addr();	    iph->ip_dst.s_addr = default_ip_flowid->daddr().addr();	}    }    return true;}bool PacketOdesc::hard_make_transp(){    click_ip *iph = p->ip_header();    if (IP_FIRSTFRAG(iph)) {	int len;	switch (iph->ip_p) {	case IP_PROTO_TCP:	    len = sizeof(click_tcp);	    break;	case IP_PROTO_UDP:	case IP_PROTO_UDPLITE:	    len = sizeof(click_udp);	    break;	case IP_PROTO_DCCP:	    len = 12;	    break;	default:	    return true;	}	if (want_len > 0	    && want_len < (uint32_t) p->transport_header_offset() + len)	    len = want_len - p->transport_header_offset();	if (p->transport_length() < len) {	    int xlen = (len < 4 ? 4 : len);	    if (!(p = p->put(xlen - p->transport_length())))		return false;	    if (p->ip_header()->ip_p == IP_PROTO_TCP && len >= 13)		p->tcp_header()->th_off = sizeof(click_tcp) >> 2;	    if (default_ip_flowid) {		click_udp *udph = p->udp_header();		udph->uh_sport = default_ip_flowid->sport();		udph->uh_dport = default_ip_flowid->dport();	    }	    if (xlen > len)		p->take(xlen - len);	}    }    return true;}const char tcp_flags_word[] = "FSRPAUECN";const uint8_t tcp_flag_mapping[256] = {    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x0-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x1-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x2-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x3-    0, 5, 0, 8, 0, 7, 1, 0, 0, 0, 0, 0, 0, 0, 9, 0, // 0x4-    4, 0, 3, 2, 0, 6, 0, 8, 7, 8, 0, 0, 0, 0, 0, 0, // 0x5-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x6-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x7-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x8-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x9-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xA-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xB-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xC-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xD-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xE-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  // 0xF-};}ELEMENT_REQUIRES(userlevel)ELEMENT_PROVIDES(IPSummaryDumpInfo)ELEMENT_PROVIDES(IPSummaryDump)CLICK_ENDDECLS

⌨️ 快捷键说明

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