📄 ipsumdump_ip.cc
字号:
// -*- mode: c++; c-basic-offset: 4 -*-/* * ipsumdump_ip.{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_ip.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_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_IP_HL };namespace IPSummaryDump {static bool ip_extract(PacketDesc& d, const FieldWriter *f){ int network_length = d.p->network_length(); switch (f->user_data) { // IP header properties#define CHECK(l) do { if (!d.iph || network_length < (l)) return field_missing(d, MISSING_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); if (IP_ISFRAG(d.iph)) d.v = (IP_FIRSTFRAG(d.iph) ? 'F' : 'f'); else d.v = (d.iph->ip_off & htons(IP_DF) ? '!' : '.'); 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, (d.iph ? d.iph->ip_hl << 2 : 20)); if (d.iph->ip_hl <= 5) d.vptr[0] = d.vptr[1] = 0; else { d.vptr[0] = (const uint8_t *) (d.iph + 1); d.vptr[1] = d.vptr[0] + (d.iph->ip_hl << 2) - sizeof(click_ip); } return true; case T_IP_LEN: if (d.iph) d.v = ntohs(d.iph->ip_len); else d.v = d.p->length(); if (d.force_extra_length) d.v += EXTRA_LENGTH_ANNO(d.p); return true; case T_IP_HL: CHECK(1); d.v = d.iph->ip_hl << 2; 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 inline bool ip_proto_has_udp_ports(int ip_p){ return ip_p == IP_PROTO_TCP || ip_p == IP_PROTO_UDP || ip_p == IP_PROTO_DCCP || ip_p == IP_PROTO_UDPLITE;}static void ip_inject(PacketOdesc& d, const FieldReader *f){ if (!d.make_ip(0)) return; click_ip *iph = d.p->ip_header(); switch (f->user_data) { // IP header properties case T_IP_SRC: iph->ip_src.s_addr = d.v; break; case T_IP_DST: iph->ip_dst.s_addr = d.v; break; case T_IP_TOS: iph->ip_tos = d.v; break; case T_IP_TTL: iph->ip_ttl = d.v; break; case T_IP_FRAG: case T_IP_FRAGOFF: iph->ip_off = htons(d.v); break; case T_IP_ID: iph->ip_id = htons(d.v); break; case T_IP_SUM: iph->ip_sum = htons(d.v); break; case T_IP_PROTO: iph->ip_p = d.v; break; case T_IP_OPT: { if (!d.vptr[0]) return; int olen = d.vptr[1] - d.vptr[0]; int ip_hl = (sizeof(click_ip) + olen + 3) & ~3; if (d.p->network_length() < ip_hl) { if (!(d.p = d.p->put(ip_hl - d.p->network_length()))) return; iph = d.p->ip_header(); } if (ip_hl > (int) (iph->ip_hl << 2)) { d.p->set_ip_header(iph, ip_hl); iph->ip_hl = ip_hl >> 2; } memcpy(d.p->network_header() + sizeof(click_ip), d.vptr[0], olen); memset(d.p->network_header() + sizeof(click_ip) + olen, IPOPT_EOL, ip_hl - olen); break; }#if 0 case T_IP_CAPTURE_LEN: { uint32_t allow_len = (iph ? network_length : d.p->length()); uint32_t len = (iph ? ntohs(iph->ip_len) : allow_len); d.v = (len < allow_len ? len : allow_len); break; }#endif case T_IP_HL: d.v = (d.v + 3) & ~3; if ((int) d.v > (int) (iph->ip_hl << 2)) { int more = d.v - (iph->ip_hl << 2); if (!(d.p = d.p->put(more))) return; iph = d.p->ip_header(); d.p->set_ip_header(iph, d.v); memset(d.p->transport_header() - more, IPOPT_EOL, more); } iph->ip_hl = d.v >> 2; break; case T_IP_LEN: d.want_len = d.p->network_header_offset() + d.v; break; }}static void ip_outa(const PacketDesc& d, const FieldWriter *f){ switch (f->user_data) { 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 << '+'; if (d.v & IP_DF) *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[0]) *d.sa << '.'; else unparse_ip_opt(*d.sa, d.vptr[0], d.vptr[1] - d.vptr[0], DO_IPOPT_ALL_NOPAD); break; }}static bool ip_ina(PacketOdesc& d, const String &s, const FieldReader *f){ switch (f->user_data) { case T_IP_SRC: case T_IP_DST: { IPAddress a; if (cp_ip_address(s, &a, d.e)) { d.v = a.addr(); return true; } break; } case T_IP_FRAG: case T_IP_FRAGOFF: { if (s.length() == 1) { if (s[0] == '.') { d.v = 0; return true; } else if (s[0] == '!') { d.v = IP_DF; return true; } else if (s[0] == 'F') { d.v = IP_MF; return true; } else if (s[0] == 'f') { d.v = 100; // arbitrary nonzero offset return true; } } d.v = 0; const char *new_end = cp_integer(s.begin(), s.end(), 0, &d.v); if (d.minor_version > 0) d.v >>= 3; for (; new_end != s.end(); ++new_end) if (*new_end == '!') d.v |= IP_DF; else if (*new_end == '+') d.v |= IP_MF; else break; if (new_end == s.end() && s.length()) return true; break; } case T_IP_PROTO: if (s.equals("T", 1)) { d.v = IP_PROTO_TCP; return true; } else if (s.equals("U", 1)) { d.v = IP_PROTO_UDP; return true; } else if (s.equals("I", 1)) { d.v = IP_PROTO_ICMP; return true; } else if (cp_integer(s, &d.v) && d.v < 256) return true; break;#if 0 case T_IP_OPT: if (!d.vptr[0]) *d.sa << '.'; else unparse_ip_opt(*d.sa, d.vptr[0], d.vptr[1] - d.vptr[0], DO_IPOPT_ALL_NOPAD); break;#endif } return false;}static void ip_outb(const PacketDesc& d, bool ok, const FieldWriter *f){ if (f->user_data == T_IP_OPT) { if (!ok || !d.vptr) *d.sa << '\0'; else unparse_ip_opt_binary(*d.sa, d.vptr[0], d.vptr[1] - d.vptr[0], DO_IPOPT_ALL); }}static const uint8_t* ip_inb(PacketOdesc& d, const uint8_t *s, const uint8_t *ends, const FieldReader *f){ if (f->user_data == T_IP_OPT && s + s[0] + 1 <= ends) { d.vptr[0] = s + 1; d.vptr[1] = d.vptr[0] + s[0]; return s + s[0] + 1; } else return ends;}static bool transport_extract(PacketDesc& d, const FieldWriter *f){ Packet* p = d.p; switch (f->user_data) { // TCP/UDP header properties case T_SPORT: case T_DPORT: { bool dport = (f->user_data == T_DPORT); if (d.iph && p->network_length() > (int)(d.iph->ip_hl << 2) && IP_FIRSTFRAG(d.iph) && ip_proto_has_udp_ports(d.iph->ip_p) && p->transport_length() >= (dport ? 4 : 2)) { const click_udp *udph = p->udp_header(); d.v = ntohs(dport ? udph->uh_dport : udph->uh_sport); return true; } return field_missing(d, IP_PROTO_TCP_OR_UDP, dport ? 4 : 2); } } return false;}static void transport_inject(PacketOdesc& d, const FieldReader *f){ if (!d.make_ip(0) || !d.make_transp()) return; click_ip *iph = d.p->ip_header(); if (iph->ip_p && !ip_proto_has_udp_ports(iph->ip_p)) return; switch (f->user_data) { // TCP/UDP header properties case T_SPORT: d.p->udp_header()->uh_sport = htons(d.v); break; case T_DPORT: d.p->udp_header()->uh_dport = htons(d.v); break; }}#define U DO_IPOPT_UNKNOWNstatic int ip_opt_mask_mapping[] = { DO_IPOPT_PADDING, DO_IPOPT_PADDING, // EOL, NOP U, U, U, U, U, // 2, 3, 4, 5, 6 DO_IPOPT_ROUTE, // RR U, U, U, U, U, U, U, U, U, U, U, U, U, // 8-20 U, U, U, U, U, U, U, U, U, U, // 21-30 U, U, U, U, U, U, U, U, U, U, // 31-40 U, U, U, U, U, U, U, U, U, U, // 41-50 U, U, U, U, U, U, U, U, U, U, // 51-60 U, U, U, U, U, U, U, // 61-67 DO_IPOPT_TS, U, U, // TS, 69-70 U, U, U, U, U, U, U, U, U, U, // 71-80 U, U, U, U, U, U, U, U, U, U, // 81-90 U, U, U, U, U, U, U, U, U, U, // 91-100 U, U, U, U, U, U, U, U, U, U, // 101-110 U, U, U, U, U, U, U, U, U, U, // 111-120 U, U, U, U, U, U, U, U, U, // 121-129 DO_IPOPT_UNKNOWN, DO_IPOPT_ROUTE, // SECURITY, LSRR U, U, U, U, // 132-135 DO_IPOPT_UNKNOWN, DO_IPOPT_ROUTE, // SATID, SSRR U, U, U, // 138-140 U, U, U, U, U, U, U, // 141-147 DO_IPOPT_UNKNOWN // RA};#undef Uvoid unparse_ip_opt(StringAccum& sa, const uint8_t* opt, int opt_len, int mask){ int initial_sa_len = sa.length(); const uint8_t *end_opt = opt + opt_len; const char *sep = ""; while (opt < end_opt) switch (*opt) { case IPOPT_EOL: if (mask & DO_IPOPT_PADDING) sa << sep << "eol"; goto done; case IPOPT_NOP: if (mask & DO_IPOPT_PADDING) { sa << sep << "nop"; sep = ";"; } opt++; break; case IPOPT_RR: if (opt + opt[1] > end_opt || opt[1] < 3 || opt[2] < 4) goto bad_opt; if (!(mask & DO_IPOPT_ROUTE)) goto unknown; sa << sep << "rr"; goto print_route; case IPOPT_LSRR: if (opt + opt[1] > end_opt || opt[1] < 3 || opt[2] < 4) goto bad_opt; if (!(mask & DO_IPOPT_ROUTE)) goto unknown; sa << sep << "lsrr"; goto print_route; case IPOPT_SSRR: if (opt + opt[1] > end_opt || opt[1] < 3 || opt[2] < 4) goto bad_opt; if (!(mask & DO_IPOPT_ROUTE)) goto unknown; sa << sep << "ssrr"; goto print_route; print_route: { const uint8_t *o = opt + 3, *ol = opt + opt[1], *op = opt + opt[2] - 1; sep = ""; sa << '{'; for (; o + 4 <= ol; o += 4) { if (o == op) { if (opt[0] == IPOPT_RR) break; sep = "^"; } sa << sep << (int)o[0] << '.' << (int)o[1] << '.' << (int)o[2] << '.' << (int)o[3]; sep = ","; } if (o == ol && o == op && opt[0] != IPOPT_RR) sa << '^'; sa << '}'; if (o + 4 <= ol && o == op && opt[0] == IPOPT_RR) sa << '+' << (ol - o) / 4; opt = ol;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -