📄 ipsumdump_ip.cc
字号:
// -*- mode: c++; c-basic-offset: 4 -*-/* * ipsumdump_general.{cc,hh} -- general IP summary dump unparsers * Eddie Kohler * * Copyright (c) 2002 International Computer Science Institute * Copyright (c) 2004 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 "ipsumdumpinfo.hh"#include <click/packet.hh>#include <click/packet_anno.hh>#include <clicknet/ip.h>#include <clicknet/tcp.h>#include <clicknet/udp.h>#include <click/confparse.hh>CLICK_DECLSenum { T_IP_SRC, T_IP_DST, T_IP_TOS, T_IP_TTL, T_IP_FRAG, T_IP_FRAGOFF, T_IP_ID, T_IP_SUM, T_IP_PROTO, T_IP_OPT, T_IP_LEN, T_IP_CAPTURE_LEN, T_SPORT, T_DPORT, T_PAYLOAD_LEN, T_PAYLOAD };namespace IPSummaryDump {void ip_prepare(PacketDesc& d){ Packet* p = d.p; d.iph = p->ip_header(); d.tcph = p->tcp_header(); d.udph = p->udp_header(); #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;#undef BAD#undef BAD2 // Adjust extra length, since we calculate lengths here based on ip_len. if (d.iph && EXTRA_LENGTH_ANNO(p) > 0) { int32_t full_len = p->length() + EXTRA_LENGTH_ANNO(p); if (ntohs(d.iph->ip_len) + 8 >= full_len - p->network_header_offset()) SET_EXTRA_LENGTH_ANNO(p, 0); else { full_len = full_len - ntohs(d.iph->ip_len); SET_EXTRA_LENGTH_ANNO(p, full_len); } }}static bool ip_extract(PacketDesc& d, int thunk){ int network_length = d.p->network_length(); switch (thunk & ~B_TYPEMASK) { // IP header properties#define CHECK(l) do { if (!d.iph || network_length < (l)) return field_missing(d, MISSING_IP, "IP", (l)); } while (0) case T_IP_SRC: CHECK(16); d.v = d.iph->ip_src.s_addr; return true; case T_IP_DST: CHECK(20); d.v = d.iph->ip_dst.s_addr; return true; case T_IP_TOS: CHECK(2); d.v = d.iph->ip_tos; return true; case T_IP_TTL: CHECK(9); d.v = d.iph->ip_ttl; return true; case T_IP_FRAG: CHECK(8); d.v = (IP_ISFRAG(d.iph) ? (IP_FIRSTFRAG(d.iph) ? 'F' : 'f') : '.'); return true; case T_IP_FRAGOFF: CHECK(8); d.v = ntohs(d.iph->ip_off); return true; case T_IP_ID: CHECK(6); d.v = ntohs(d.iph->ip_id); return true; case T_IP_SUM: CHECK(12); d.v = ntohs(d.iph->ip_sum); return true; case T_IP_PROTO: CHECK(10); d.v = d.iph->ip_p; return true; case T_IP_OPT: if (!d.iph || (d.iph->ip_hl > 5 && network_length < (int)(d.iph->ip_hl << 2))) return field_missing(d, MISSING_IP, "IP", (d.iph ? d.iph->ip_hl << 2 : 20)); if (d.iph->ip_hl <= 5) d.vptr = 0, d.v2 = 0; else { d.vptr = (const uint8_t *) (d.iph + 1); d.v2 = (d.iph->ip_hl << 2) - sizeof(click_ip); } return true; case T_IP_LEN: if (d.iph) d.v = ntohs(d.iph->ip_len) + (d.force_extra_length ? EXTRA_LENGTH_ANNO(d.p) : 0); else d.v = d.p->length() + EXTRA_LENGTH_ANNO(d.p); return true; case T_IP_CAPTURE_LEN: { uint32_t allow_len = (d.iph ? network_length : d.p->length()); uint32_t len = (d.iph ? ntohs(d.iph->ip_len) : allow_len); d.v = (len < allow_len ? len : allow_len); return true; }#undef CHECK default: return false; }}static void ip_outa(const PacketDesc& d, int thunk){ switch (thunk & ~B_TYPEMASK) { case T_IP_SRC: case T_IP_DST: *d.sa << IPAddress(d.v); break; case T_IP_FRAG: *d.sa << (char) d.v; break; case T_IP_FRAGOFF: *d.sa << ((d.v & IP_OFFMASK) << 3); if (d.v & IP_MF) *d.sa << '+'; break; case T_IP_PROTO: switch (d.v) { case IP_PROTO_TCP: *d.sa << 'T'; break; case IP_PROTO_UDP: *d.sa << 'U'; break; case IP_PROTO_ICMP: *d.sa << 'I'; break; default: *d.sa << d.v; break; } break; case T_IP_OPT: if (!d.vptr) *d.sa << '.'; else unparse_ip_opt(*d.sa, d.vptr, d.v2, DO_IPOPT_ALL_NOPAD); break; }}static void ip_outb(const PacketDesc& d, bool ok, int thunk){ if ((thunk & ~B_TYPEMASK) == T_IP_OPT) { if (!ok || !d.vptr) *d.sa << '\0'; else unparse_ip_opt_binary(*d.sa, d.vptr, d.v2, DO_IPOPT_ALL); }}static const uint8_t* ip_inb(PacketDesc& d, const uint8_t *s, const uint8_t *ends, int thunk){ if ((thunk & ~B_TYPEMASK) == T_IP_OPT && s + s[0] + 1 <= ends) { d.vptr = s + 1; d.v2 = s[0]; return s + s[0] + 1; } else return ends;}static bool transport_extract(PacketDesc& d, int thunk){ Packet* p = d.p; switch (thunk & ~B_TYPEMASK) { // TCP/UDP header properties#define CHECK(l) do { if ((!d.tcph && !d.udph) || p->transport_length() < (l)) return field_missing(d, MISSING_IP_TRANSPORT, "transport", (l)); } while (0) case T_SPORT: CHECK(2); d.v = ntohs(p->udp_header()->uh_sport); return true; case T_DPORT: CHECK(4); d.v = ntohs(p->udp_header()->uh_dport); return true;#undef CHECK case T_PAYLOAD_LEN: if (d.iph) { int32_t off = p->network_header_length(); if (d.tcph && p->transport_length() >= 13) off += (d.tcph->th_off << 2); else if (d.udph) off += sizeof(click_udp); else if (IP_FIRSTFRAG(d.iph) && (d.iph->ip_p == IP_PROTO_TCP || d.iph->ip_p == IP_PROTO_UDP)) off = ntohs(d.iph->ip_len); d.v = ntohs(d.iph->ip_len) - off + (d.force_extra_length ? EXTRA_LENGTH_ANNO(p) : 0); } else d.v = p->length() + EXTRA_LENGTH_ANNO(p); return true; case T_PAYLOAD: return true; default: return false; }}static void transport_outa(const PacketDesc& d, int thunk){ switch (thunk & ~B_TYPEMASK) { case T_PAYLOAD: { int32_t off; uint32_t len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -