📄 ipsumdump_payload.cc
字号:
// -*- mode: c++; c-basic-offset: 4 -*-/* * ipsumdump_payload.{cc,hh} -- IP network layer IP summary dump unparsers * Eddie Kohler * * Copyright (c) 2002 International Computer Science Institute * Copyright (c) 2004-2008 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 "ipsumdump_payload.hh"#include <click/packet.hh>#include <click/packet_anno.hh>#include <click/md5.h>#include <clicknet/ip.h>#include <clicknet/tcp.h>#include <clicknet/udp.h>#include <click/confparse.hh>#include <click/ipflowid.hh>CLICK_DECLSnamespace IPSummaryDump {enum { T_PAYLOAD_LEN, T_PAYLOAD, T_PAYLOAD_MD5, T_PAYLOAD_MD5_HEX };static void payload_info(Packet *p, const click_ip *iph, int32_t &off, uint32_t &len){ if (iph) { len = ntohs(iph->ip_len); off = p->transport_header_offset(); uint32_t nlen = len + p->network_header_offset(); if (IP_FIRSTFRAG(iph)) switch (iph->ip_p) { case IP_PROTO_TCP: if (p->transport_length() >= 13 && ((uint32_t) off + (p->tcp_header()->th_off << 2) <= nlen || len == 0)) off += (p->tcp_header()->th_off << 2); break; case IP_PROTO_UDP: case IP_PROTO_UDPLITE: if (off + sizeof(click_udp) <= nlen || len == 0) off += sizeof(click_udp); break; } len -= off - p->network_header_offset(); } else { off = 0; len = p->length(); }}static bool payload_extract(PacketDesc &d, const FieldWriter *f){ switch (f->user_data) { case T_PAYLOAD_LEN: { int32_t off; payload_info(d.p, d.iph, off, d.v); if (!d.iph || d.force_extra_length) d.v += EXTRA_LENGTH_ANNO(d.p); return true; } case T_PAYLOAD: case T_PAYLOAD_MD5: case T_PAYLOAD_MD5_HEX: return true; default: return false; }}static void account_payload_len(PacketOdesc &d, int32_t &off, uint32_t plen){ if (!d.is_ip || (d.p->ip_header()->ip_len == 0 && d.want_len == 0)) d.want_len = off + plen; else { click_ip *iph = d.p->ip_header(); uint32_t ip_len = (iph->ip_len ? ntohs(iph->ip_len) : d.want_len) + d.p->network_header_offset(); if (ip_len > off + plen) { int delta = ip_len - (off + plen); click_tcp *tcph = d.p->tcp_header(); if (IP_FIRSTFRAG(iph) && iph->ip_p == IP_PROTO_TCP && tcph->th_off == (sizeof(click_tcp) >> 2)) { int th_delta = delta - (delta & 3); if (th_delta + sizeof(click_tcp) > (15 << 2)) th_delta = (15 << 2) - sizeof(click_tcp); if (!(d.p = d.p->put(th_delta))) return; iph = d.p->ip_header(); // may have shifted unsigned char *tx = d.p->transport_header() + sizeof(click_tcp); memmove(tx + th_delta, tx, d.p->end_data() - (tx + th_delta)); memset(tx, TCPOPT_EOL, th_delta); d.p->tcp_header()->th_off = (sizeof(click_tcp) + th_delta) >> 2; delta -= th_delta; } if (iph->ip_hl == (sizeof(click_ip) >> 2) && delta > 0) { int ip_delta = delta - (delta & 3); if (ip_delta + sizeof(click_ip) > (15 << 2)) ip_delta = (15 << 2) - sizeof(click_ip); if (!(d.p = d.p->put(ip_delta))) return; iph = d.p->ip_header(); // may have shifted unsigned char *nx = d.p->network_header() + sizeof(click_ip); memmove(nx + ip_delta, nx, d.p->end_data() - (nx + ip_delta)); memset(nx, IPOPT_EOL, ip_delta); iph->ip_hl = (sizeof(click_ip) + ip_delta) >> 2; d.p->set_ip_header(iph, sizeof(click_ip) + ip_delta); } } }}static void payload_inject(PacketOdesc &d, const FieldReader *f){ if (d.make_ip(0)) // add default IPFlowID and protocol if nec. d.make_transp(); // don't care if we fail if (!d.p) return; int32_t off; uint32_t len; payload_info(d.p, d.is_ip ? d.p->ip_header() : 0, off, len); switch (f->user_data) { case T_PAYLOAD: { if (!d.vptr[0] || d.vptr[0] == d.vptr[1]) return; uint32_t plen = d.vptr[1] - d.vptr[0]; account_payload_len(d, off, plen); if (!d.p || (d.p->length() - off < plen && !(d.p = d.p->put(plen - (d.p->length() - off))))) return; memcpy(d.p->data() + off, d.vptr[0], plen); break; } case T_PAYLOAD_LEN: account_payload_len(d, off, d.v); break; }}static void payload_outa(const PacketDesc& d, const FieldWriter *f){ switch (f->user_data) { case T_PAYLOAD: case T_PAYLOAD_MD5: case T_PAYLOAD_MD5_HEX: { int32_t off; uint32_t len; payload_info(d.p, d.iph, off, len); if (off + len > (uint32_t) d.p->length()) len = d.p->length() - off; if (f->user_data == T_PAYLOAD) { String s = String::make_stable((const char *)(d.p->data() + off), len); *d.sa << cp_quote(s); } else { md5_state_t pms; md5_init(&pms); md5_append(&pms, (const md5_byte_t *) (d.p->data() + off), len); if (f->user_data == T_PAYLOAD_MD5_HEX) { if (char *buf = d.sa->extend(MD5_DIGEST_SIZE * 2)) { md5_finish(&pms, (md5_byte_t *) buf); const char digits[] = "0123456789abcdef"; for (int i = MD5_DIGEST_SIZE - 1; i >= 0; --i) { int b = (unsigned char) buf[i]; buf[2*i + 1] = digits[b & 15]; buf[2*i] = digits[b >> 4]; } } } else { if (char *buf = d.sa->extend(MD5_TEXT_DIGEST_SIZE)) md5_finish_text(&pms, buf, 1); } md5_free(&pms); } break; } }}static bool payload_ina(PacketOdesc& d, const String &str, const FieldReader *f){ switch (f->user_data) { case T_PAYLOAD: { String s; if (cp_string(str, &s)) { d.sa.clear(); d.sa << s; d.vptr[0] = (const uint8_t *) d.sa.begin(); d.vptr[1] = (const uint8_t *) d.sa.end(); return true; } break; } } return false;}static void payload_outb(const PacketDesc& d, bool, const FieldWriter *f){ switch (f->user_data) { case T_PAYLOAD_MD5: case T_PAYLOAD_MD5_HEX: { int32_t off; uint32_t len; payload_info(d.p, d.iph, off, len); if (off + len > (uint32_t) d.p->length()) len = d.p->length() - off; md5_state_t pms; md5_init(&pms); md5_append(&pms, (const md5_byte_t *) (d.p->data() + off), len); if (char *buf = d.sa->extend(MD5_DIGEST_SIZE)) md5_finish(&pms, (md5_byte_t *) buf); md5_free(&pms); break; } }}static const FieldWriter payload_writers[] = { { "payload_len", B_4, T_PAYLOAD_LEN, ip_prepare, payload_extract, num_outa, outb }, { "payload", B_NOTALLOWED, T_PAYLOAD, ip_prepare, payload_extract, payload_outa, 0 }, { "payload_md5", B_16, T_PAYLOAD_MD5, ip_prepare, payload_extract, payload_outa, payload_outb }, { "payload_md5_hex", B_16, T_PAYLOAD_MD5_HEX, ip_prepare, payload_extract, payload_outa, payload_outb }};static const FieldReader payload_readers[] = { { "payload_len", B_4, T_PAYLOAD_LEN, order_payload + 1, num_ina, inb, payload_inject }, { "payload", B_NOTALLOWED, T_PAYLOAD, order_payload, payload_ina, 0, payload_inject }};static const FieldSynonym payload_synonyms[] = { { "payload_length", "payload_len" }};}void IPSummaryDump_Payload::static_initialize(){ using namespace IPSummaryDump; for (size_t i = 0; i < sizeof(payload_writers) / sizeof(payload_writers[0]); ++i) FieldWriter::add(&payload_writers[i]); for (size_t i = 0; i < sizeof(payload_readers) / sizeof(payload_readers[0]); ++i) FieldReader::add(&payload_readers[i]); for (size_t i = 0; i < sizeof(payload_synonyms) / sizeof(payload_synonyms[0]); ++i) FieldSynonym::add(&payload_synonyms[i]);}void IPSummaryDump_Payload::static_cleanup(){ using namespace IPSummaryDump; for (size_t i = 0; i < sizeof(payload_writers) / sizeof(payload_writers[0]); ++i) FieldWriter::remove(&payload_writers[i]); for (size_t i = 0; i < sizeof(payload_readers) / sizeof(payload_readers[0]); ++i) FieldReader::remove(&payload_readers[i]); for (size_t i = 0; i < sizeof(payload_synonyms) / sizeof(payload_synonyms[0]); ++i) FieldSynonym::remove(&payload_synonyms[i]);}ELEMENT_REQUIRES(userlevel IPSummaryDump)ELEMENT_PROVIDES(IPSummaryDump_Payload)CLICK_ENDDECLS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -