📄 ipsumdump_ip.cc
字号:
sep = ";"; break; } case IPOPT_TS: { if (opt + opt[1] > end_opt || opt[1] < 4 || opt[2] < 5) goto bad_opt; const uint8_t *o = opt + 4, *ol = opt + opt[1], *op = opt + opt[2] - 1; int flag = opt[3] & 0xF; int size = (flag >= 1 && flag <= 3 ? 8 : 4); sa << sep << "ts"; if (flag == 1) sa << ".ip"; else if (flag == 3) sa << ".preip"; else if (flag != 0) sa << "." << flag; sa << '{'; sep = ""; for (; o + size <= ol; o += 4) { if (o == op) { if (flag != 3) break; sep = "^"; } if (flag != 0) { sa << sep << (int)o[0] << '.' << (int)o[1] << '.' << (int)o[2] << '.' << (int)o[3] << '='; o += 4; } else sa << sep; if (flag == 3 && o > op) sa.pop_back(); else { uint32_t v = (o[0] << 24) | (o[1] << 16) | (o[2] << 8) | o[3]; if (v & 0x80000000U) sa << '!'; sa << (v & 0x7FFFFFFFU); } sep = ","; } if (o == ol && o == op) sa << '^'; sa << '}'; if (o + size <= ol && o == op) sa << '+' << (ol - o) / size; if (opt[3] & 0xF0) sa << '+' << '+' << (opt[3] >> 4); opt = ol; sep = ";"; break; } default: { if (opt + opt[1] > end_opt || opt[1] < 2) goto bad_opt; if (!(mask & DO_IPOPT_UNKNOWN)) goto unknown; sa << sep << (int)(opt[0]); const uint8_t *end_this_opt = opt + opt[1]; char opt_sep = '='; for (opt += 2; opt < end_this_opt; opt++) { sa << opt_sep << (int)(*opt); opt_sep = ':'; } sep = ";"; break; } unknown: opt += (opt[1] >= 2 ? opt[1] : 128); break; } done: if (sa.length() == initial_sa_len) sa << '.'; return; bad_opt: sa.set_length(initial_sa_len); sa << '?';}void unparse_ip_opt(StringAccum& sa, const click_ip* iph, int mask){ unparse_ip_opt(sa, reinterpret_cast<const uint8_t *>(iph + 1), (iph->ip_hl << 2) - sizeof(click_ip), mask);}void unparse_ip_opt_binary(StringAccum& sa, const uint8_t *opt, int opt_len, int mask){ if (mask == (int)DO_IPOPT_ALL) { // store all options sa.append((char)opt_len); sa.append(opt, opt_len); } const uint8_t *end_opt = opt + opt_len; int initial_sa_len = sa.length(); sa.append('\0'); while (opt < end_opt) { // one-byte options if (*opt == IPOPT_EOL) { if (mask & DO_IPOPT_PADDING) sa.append(opt, 1); goto done; } else if (*opt == IPOPT_NOP) { if (mask & DO_IPOPT_PADDING) sa.append(opt, 1); opt++; continue; } // quit copying options if you encounter something obviously invalid if (opt[1] < 2 || opt + opt[1] > end_opt) break; int this_content = (*opt > IPOPT_RA ? (int)DO_IPOPT_UNKNOWN : ip_opt_mask_mapping[*opt]); if (mask & this_content) sa.append(opt, opt[1]); opt += opt[1]; } done: sa[initial_sa_len] = sa.length() - initial_sa_len - 1;}void unparse_ip_opt_binary(StringAccum& sa, const click_ip *iph, int mask){ unparse_ip_opt_binary(sa, reinterpret_cast<const uint8_t *>(iph + 1), (iph->ip_hl << 2) - sizeof(click_ip), mask);}static void append_net_uint32_t(StringAccum &sa, uint32_t u){ sa << (char)(u >> 24) << (char)(u >> 16) << (char)(u >> 8) << (char)u;}static bool ip_opt_ina(PacketOdesc &d, const String &str, const FieldReader *){ if (!str || str.equals(".", 1)) return true; else if (str.equals("-", 1)) return false; const uint8_t *s = reinterpret_cast<const uint8_t *>(str.begin()); const uint8_t *end = reinterpret_cast<const uint8_t *>(str.end()); int contents = DO_IPOPT_ALL; d.sa.clear(); while (1) { const unsigned char *t; uint32_t u1; if (s + 3 < end && memcmp(s, "rr{", 3) == 0 && (contents & DO_IPOPT_ROUTE)) { // record route d.sa << (char)IPOPT_RR; s += 3; parse_route: int sa_pos = d.sa.length() - 1; int pointer = -1; d.sa << '\0' << '\0'; // loop over entries while (1) { if (s < end && *s == '^' && pointer < 0) pointer = d.sa.length() - sa_pos + 1, s++; if (s >= end || !isdigit(*s)) break; for (int i = 0; i < 4; i++) { u1 = 256; s = cp_integer(s, end, 10, &u1) + (i < 3); if (u1 > 255 || (i < 3 && (s > end || s[-1] != '.'))) goto bad_opt; d.sa << (char)u1; } if (s < end && *s == ',') s++; } if (s >= end || *s != '}') // must end with a brace goto bad_opt; d.sa[sa_pos + 2] = (pointer >= 0 ? pointer : d.sa.length() - sa_pos + 1); if (s + 2 < end && s[1] == '+' && isdigit(s[2])) { s = cp_integer(s + 2, end, 10, &u1); if (u1 < 64) d.sa.append_fill('\0', u1 * 4); } else s++; if (d.sa.length() - sa_pos > 255) goto bad_opt; d.sa[sa_pos + 1] = d.sa.length() - sa_pos; } else if (s + 5 < end && memcmp(s, "ssrr{", 5) == 0 && (contents & DO_IPOPT_ROUTE)) { // strict source route option d.sa << (char)IPOPT_SSRR; s += 5; goto parse_route; } else if (s + 5 < end && memcmp(s, "lsrr{", 5) == 0 && (contents & DO_IPOPT_ROUTE)) { // loose source route option d.sa << (char)IPOPT_LSRR; s += 5; goto parse_route; } else if (s + 3 < end && (memcmp(s, "ts{", 3) == 0 || memcmp(s, "ts.", 3) == 0) && (contents & DO_IPOPT_TS)) { // timestamp option int sa_pos = d.sa.length(); d.sa << (char)IPOPT_TS << (char)0 << (char)0 << (char)0; uint32_t top_bit; int flag = -1; if (s[2] == '.') { if (s + 6 < end && memcmp(s + 3, "ip{", 3) == 0) flag = 1, s += 6; else if (s + 9 < end && memcmp(s + 3, "preip{", 6) == 0) flag = 3, s += 9; else if (isdigit(s[3]) && (t = cp_integer(s + 3, end, 0, (uint32_t *)&flag)) && flag <= 15 && t < end && *t == '{') s = t + 1; else goto bad_opt; } else s += 3; int pointer = -1; // loop over timestamp entries while (1) { if (s < end && *s == '^' && pointer < 0) pointer = d.sa.length() - sa_pos + 1, s++; if (s >= end || (!isdigit(*s) && *s != '!')) break; const unsigned char *entry = s; retry_entry: if (flag == 1 || flag == 3 || flag == -2) { // parse IP address for (int i = 0; i < 4; i++) { u1 = 256; s = cp_integer(s, end, 10, &u1) + (i < 3); if (u1 > 255 || (i < 3 && (s > end || s[-1] != '.'))) goto bad_opt; d.sa << (char)u1; } // prespecified IPs if we get here if (pointer >= 0 && flag == -2) flag = 3; // check for valid value: either "=[DIGIT]", "=!", "=?" // (for pointer >= 0) if (s + 1 < end && *s == '=') { if (isdigit(s[1]) || s[1] == '!') s++; else if (s[1] == '?' && pointer >= 0) { d.sa << (char)0 << (char)0 << (char)0 << (char)0; s += 2; goto done_entry; } else goto bad_opt; } else if (pointer >= 0) { d.sa << (char)0 << (char)0 << (char)0 << (char)0; goto done_entry; } else goto bad_opt; } // parse timestamp value assert(s < end); top_bit = 0; if (*s == '!') top_bit = 0x80000000U, s++; if (s >= end || !isdigit(*s)) goto bad_opt; s = cp_integer(s, end, 0, &u1); if (s < end && *s == '.' && flag == -1) { flag = -2; s = entry; goto retry_entry; } else if (flag == -1) flag = 0; u1 |= top_bit; append_net_uint32_t(d.sa, u1); done_entry: // check separator if (s < end && *s == ',') s++; } // done with entries if (s < end && *s++ != '}') goto bad_opt; if (flag == -2) flag = 1; d.sa[sa_pos + 2] = (pointer >= 0 ? pointer : d.sa.length() - sa_pos + 1); if (s + 1 < end && *s == '+' && isdigit(s[1]) && (s = cp_integer(s + 1, end, 0, &u1)) && u1 < 64) d.sa.append_fill('\0', u1 * (flag == 1 || flag == 3 ? 8 : 4)); int overflow = 0; if (s + 2 < end && *s == '+' && s[1] == '+' && isdigit(s[2]) && (s = cp_integer(s + 2, end, 0, &u1)) && u1 < 16) overflow = u1; d.sa[sa_pos + 3] = (overflow << 4) | flag; if (d.sa.length() - sa_pos > 255) goto bad_opt; d.sa[sa_pos + 1] = d.sa.length() - sa_pos; } else if (s < end && isdigit(*s) && (contents & DO_IPOPT_UNKNOWN)) { // unknown option s = cp_integer(s, end, 0, &u1); if (u1 >= 256) goto bad_opt; d.sa << (char)u1; if (s + 1 < end && *s == '=' && isdigit(s[1])) { int pos0 = d.sa.length(); d.sa << (char)0; do { s = cp_integer(s + 1, end, 0, &u1); if (u1 >= 256) goto bad_opt; d.sa << (char)u1; } while (s + 1 < end && *s == ':' && isdigit(s[1])); if (d.sa.length() > pos0 + 254) goto bad_opt; d.sa[pos0] = (char)(d.sa.length() - pos0 + 1); } } else if (s + 3 <= end && memcmp(s, "nop", 3) == 0 && (contents & DO_IPOPT_PADDING)) { d.sa << (char)IPOPT_NOP; s += 3; } else if (s + 3 <= end && memcmp(s, "eol", 3) == 0 && (contents & DO_IPOPT_PADDING) && (s + 3 == end || s[3] != ',')) { d.sa << (char)IPOPT_EOL; s += 3; } else goto bad_opt; if (s >= end) { // check for improper padding while (d.sa.length() > 40 && d.sa[0] == IPOPT_NOP) { memmove(&d.sa[0], &d.sa[1], d.sa.length() - 1); d.sa.pop_back(); } // options too long? if (d.sa.length() > 40) goto bad_opt; // otherwise ok d.vptr[0] = reinterpret_cast<const uint8_t *>(d.sa.begin()); d.vptr[1] = reinterpret_cast<const uint8_t *>(d.sa.end()); return true; } else if (*s != ',' && *s != ';') goto bad_opt; s++; } bad_opt: return false;}static const FieldWriter ip_writers[] = { { "ip_src", B_4NET, T_IP_SRC, ip_prepare, ip_extract, ip_outa, outb }, { "ip_dst", B_4NET, T_IP_DST, ip_prepare, ip_extract, ip_outa, outb }, { "ip_tos", B_1, T_IP_TOS, ip_prepare, ip_extract, num_outa, outb }, { "ip_ttl", B_1, T_IP_TTL, ip_prepare, ip_extract, num_outa, outb }, { "ip_frag", B_1, T_IP_FRAG, ip_prepare, ip_extract, ip_outa, outb }, { "ip_fragoff", B_2, T_IP_FRAGOFF, ip_prepare, ip_extract, ip_outa, outb }, { "ip_id", B_2, T_IP_ID, ip_prepare, ip_extract, num_outa, outb }, { "ip_sum", B_2, T_IP_SUM, ip_prepare, ip_extract, num_outa, outb }, { "ip_proto", B_1, T_IP_PROTO, ip_prepare, ip_extract, ip_outa, outb }, { "ip_hl", B_1, T_IP_HL, ip_prepare, ip_extract, num_outa, outb }, { "ip_len", B_4, T_IP_LEN, ip_prepare, ip_extract, num_outa, outb }, { "ip_capture_len", B_4, T_IP_CAPTURE_LEN, ip_prepare, ip_extract, num_outa, outb }, { "ip_opt", B_SPECIAL, T_IP_OPT, ip_prepare, ip_extract, ip_outa, ip_outb }, { "sport", B_2, T_SPORT, ip_prepare, transport_extract, num_outa, outb }, { "dport", B_2, T_DPORT, ip_prepare, transport_extract, num_outa, outb }};static const FieldReader ip_readers[] = { { "ip_src", B_4NET, T_IP_SRC, order_net, ip_ina, inb, ip_inject }, { "ip_dst", B_4NET, T_IP_DST, order_net, ip_ina, inb, ip_inject }, { "ip_tos", B_1, T_IP_TOS, order_net, num_ina, inb, ip_inject }, { "ip_ttl", B_1, T_IP_TTL, order_net, num_ina, inb, ip_inject }, { "ip_frag", B_1, T_IP_FRAG, order_net - 2, ip_ina, inb, ip_inject }, { "ip_fragoff", B_2, T_IP_FRAGOFF, order_net - 1, ip_ina, inb, ip_inject }, { "ip_id", B_2, T_IP_ID, order_net, num_ina, inb, ip_inject }, { "ip_sum", B_2, T_IP_SUM, order_net + 2, num_ina, inb, ip_inject }, { "ip_proto", B_1, T_IP_PROTO, order_net, ip_ina, inb, ip_inject }, { "ip_hl", B_1, T_IP_HL, order_net - 1, num_ina, inb, ip_inject }, { "ip_len", B_4, T_IP_LEN, order_net + 1, num_ina, inb, ip_inject }, { "ip_opt", B_SPECIAL, T_IP_OPT, order_net, ip_opt_ina, ip_inb, ip_inject }, { "sport", B_2, T_SPORT, order_transp, num_ina, inb, transport_inject }, { "dport", B_2, T_DPORT, order_transp, num_ina, inb, transport_inject }};static const FieldSynonym ip_synonyms[] = { { "length", "ip_len" }, { "ip_p", "ip_proto" }};}void IPSummaryDump_IP::static_initialize(){ using namespace IPSummaryDump; for (size_t i = 0; i < sizeof(ip_writers) / sizeof(ip_writers[0]); ++i) FieldWriter::add(&ip_writers[i]); for (size_t i = 0; i < sizeof(ip_readers) / sizeof(ip_readers[0]); ++i) FieldReader::add(&ip_readers[i]); for (size_t i = 0; i < sizeof(ip_synonyms) / sizeof(ip_synonyms[0]); ++i) FieldSynonym::add(&ip_synonyms[i]);}void IPSummaryDump_IP::static_cleanup(){ using namespace IPSummaryDump; for (size_t i = 0; i < sizeof(ip_writers) / sizeof(ip_writers[0]); ++i) FieldWriter::remove(&ip_writers[i]); for (size_t i = 0; i < sizeof(ip_readers) / sizeof(ip_readers[0]); ++i) FieldReader::remove(&ip_readers[i]); for (size_t i = 0; i < sizeof(ip_synonyms) / sizeof(ip_synonyms[0]); ++i) FieldSynonym::remove(&ip_synonyms[i]);}ELEMENT_REQUIRES(userlevel IPSummaryDump)ELEMENT_PROVIDES(IPSummaryDump_IP)CLICK_ENDDECLS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -