📄 ipsumdump_tcp.cc
字号:
break; case TCPOPT_SACK: { if (opt + opt[1] > end_opt || (opt[1] % 8 != 2)) goto bad_opt; if (!(mask & DO_TCPOPT_SACK)) goto unknown; const uint8_t *end_sack = opt + opt[1]; for (opt += 2; opt < end_sack; opt += 8) { uint32_t buf[2]; memcpy(&buf[0], opt, 8); sa << sep << "sack" << ntohl(buf[0]) << '-' << ntohl(buf[1]); sep = ";"; } break; } case TCPOPT_TIMESTAMP: { if (opt + opt[1] > end_opt || opt[1] != TCPOLEN_TIMESTAMP) goto bad_opt; if (!(mask & DO_TCPOPT_TIMESTAMP)) goto unknown; uint32_t buf[2]; memcpy(&buf[0], opt + 2, 8); sa << sep << "ts" << ntohl(buf[0]) << ':' << ntohl(buf[1]); opt += TCPOLEN_TIMESTAMP; sep = ";"; break; } default: { if (opt + opt[1] > end_opt || opt[1] < 2) goto bad_opt; if (!(mask & DO_TCPOPT_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_tcp_opt(StringAccum& sa, const click_tcp* tcph, int mask){ unparse_tcp_opt(sa, reinterpret_cast<const uint8_t *>(tcph + 1), (tcph->th_off << 2) - sizeof(click_tcp), mask);}void unparse_tcp_opt_binary(StringAccum& sa, const uint8_t* opt, int opt_len, int mask){ if (mask == (int)DO_TCPOPT_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 == TCPOPT_EOL) { if (mask & DO_TCPOPT_PADDING) sa.append(opt, 1); goto done; } else if (*opt == TCPOPT_NOP) { if (mask & DO_TCPOPT_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 > TCPOPT_TIMESTAMP ? (int)DO_TCPOPT_UNKNOWN : tcp_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_tcp_opt_binary(StringAccum& sa, const click_tcp *tcph, int mask){ unparse_tcp_opt_binary(sa, reinterpret_cast<const uint8_t *>(tcph + 1), (tcph->th_off << 2) - sizeof(click_tcp), 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 tcp_opt_ina(PacketOdesc &d, const String &str, const FieldReader *f){ 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_TCPOPT_ALL; if (f->user_data == T_TCP_SACK) contents = DO_TCPOPT_SACK; else if (f->user_data == T_TCP_NTOPT) contents = DO_TCPOPT_NTALL; d.sa.clear(); while (1) { uint32_t u1, u2; if (s + 3 < end && memcmp(s, "mss", 3) == 0 && (contents & DO_TCPOPT_MSS)) { u1 = 0x10000U; // bad value s = cp_integer(s + 3, end, 0, &u1); if (u1 <= 0xFFFFU) d.sa << (char)TCPOPT_MAXSEG << (char)TCPOLEN_MAXSEG << (char)(u1 >> 8) << (char)u1; else goto bad_opt; } else if (s + 6 < end && memcmp(s, "wscale", 6) == 0 && (contents & DO_TCPOPT_WSCALE)) { u1 = 256; // bad value s = cp_integer(s + 6, end, 0, &u1); if (u1 <= 255) d.sa << (char)TCPOPT_WSCALE << (char)TCPOLEN_WSCALE << (char)u1; else goto bad_opt; } else if (s + 6 <= end && memcmp(s, "sackok", 6) == 0 && (contents & DO_TCPOPT_SACK)) { d.sa << (char)TCPOPT_SACK_PERMITTED << (char)TCPOLEN_SACK_PERMITTED; s += 6; } else if (s + 4 < end && memcmp(s, "sack", 4) == 0 && (contents & DO_TCPOPT_SACK)) { // combine adjacent SACK options into a block int sa_pos = d.sa.length(); d.sa << (char)TCPOPT_SACK << (char)0; s += 4; while (1) { const unsigned char *t = cp_integer(s, end, 0, &u1); if (t >= end || (*t != ':' && *t != '-')) goto bad_opt; t = cp_integer(t + 1, end, 0, &u2); append_net_uint32_t(d.sa, u1); append_net_uint32_t(d.sa, u2); if (t < s + 3) // at least 1 digit in each block goto bad_opt; s = t; if (s + 5 >= end || memcmp(s, ",sack", 5) != 0) break; s += 5; } d.sa[sa_pos + 1] = (char)(d.sa.length() - sa_pos); } else if (s + 2 < end && memcmp(s, "ts", 2) == 0 && (contents & DO_TCPOPT_TIMESTAMP)) { const unsigned char *t = cp_integer(s + 2, end, 0, &u1); if (t >= end || *t != ':') goto bad_opt; t = cp_integer(t + 1, end, 0, &u2); if (d.sa.length() == 0) d.sa << (char)TCPOPT_NOP << (char)TCPOPT_NOP; d.sa << (char)TCPOPT_TIMESTAMP << (char)TCPOLEN_TIMESTAMP; append_net_uint32_t(d.sa, u1); append_net_uint32_t(d.sa, u2); if (t < s + 5) // at least 1 digit in each block goto bad_opt; s = t; } else if (s < end && isdigit(*s) && (contents & DO_TCPOPT_UNKNOWN)) { 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_TCPOPT_PADDING)) { d.sa << (char)TCPOPT_NOP; s += 3; } else if (s + 3 <= end && strncmp((const char *) s, "eol", 3) == 0 && (contents & DO_TCPOPT_PADDING) && (s + 3 == end || s[3] != ',')) { d.sa << (char)TCPOPT_EOL; s += 3; } else goto bad_opt; if (s >= end || isspace(*s)) { // check for improper padding while (d.sa.length() > 40 && d.sa[0] == TCPOPT_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 tcp_writers[] = { { "tcp_seq", B_4, T_TCP_SEQ, ip_prepare, tcp_extract, num_outa, outb }, { "tcp_ack", B_4, T_TCP_ACK, ip_prepare, tcp_extract, num_outa, outb }, { "tcp_off", B_1, T_TCP_OFF, ip_prepare, tcp_extract, num_outa, outb }, { "tcp_flags", B_1, T_TCP_FLAGS, ip_prepare, tcp_extract, tcp_outa, outb }, { "tcp_window", B_2, T_TCP_WINDOW, ip_prepare, tcp_extract, num_outa, outb }, { "tcp_urp", B_2, T_TCP_URP, ip_prepare, tcp_extract, num_outa, outb }, { "tcp_opt", B_SPECIAL, T_TCP_OPT, ip_prepare, tcp_extract, tcp_outa, tcp_outb }, { "tcp_ntopt", B_SPECIAL, T_TCP_NTOPT, ip_prepare, tcp_extract, tcp_outa, tcp_outb }, { "tcp_sack", B_SPECIAL, T_TCP_SACK, ip_prepare, tcp_extract, tcp_outa, tcp_outb }};static const FieldReader tcp_readers[] = { { "tcp_seq", B_4, T_TCP_SEQ, order_transp, num_ina, inb, tcp_inject }, { "tcp_ack", B_4, T_TCP_ACK, order_transp, num_ina, inb, tcp_inject }, { "tcp_off", B_1, T_TCP_OFF, order_transp - 1, num_ina, inb, tcp_inject }, { "tcp_flags", B_1, T_TCP_FLAGS, order_transp, tcp_ina, inb, tcp_inject }, { "tcp_window", B_2, T_TCP_WINDOW, order_transp, num_ina, inb, tcp_inject }, { "tcp_urp", B_2, T_TCP_URP, order_transp, num_ina, inb, tcp_inject }, { "tcp_opt", B_SPECIAL, T_TCP_OPT, order_transp + 3, tcp_opt_ina, tcp_inb, tcp_inject }, { "tcp_ntopt", B_SPECIAL, T_TCP_NTOPT, order_transp + 2, tcp_opt_ina, tcp_inb, tcp_inject }, { "tcp_sack", B_SPECIAL, T_TCP_SACK, order_transp + 1, tcp_opt_ina, tcp_inb, tcp_inject }};static const FieldSynonym tcp_synonyms[] = { { "tcp_seqno", "tcp_seq" }, { "tcp_ackno", "tcp_ack" }, { "tcp_win", "tcp_window" }};}void IPSummaryDump_TCP::static_initialize(){ using namespace IPSummaryDump; for (size_t i = 0; i < sizeof(tcp_writers) / sizeof(tcp_writers[0]); ++i) FieldWriter::add(&tcp_writers[i]); for (size_t i = 0; i < sizeof(tcp_readers) / sizeof(tcp_readers[0]); ++i) FieldReader::add(&tcp_readers[i]); for (size_t i = 0; i < sizeof(tcp_synonyms) / sizeof(tcp_synonyms[0]); ++i) FieldSynonym::add(&tcp_synonyms[i]);}void IPSummaryDump_TCP::static_cleanup(){ using namespace IPSummaryDump; for (size_t i = 0; i < sizeof(tcp_writers) / sizeof(tcp_writers[0]); ++i) FieldWriter::remove(&tcp_writers[i]); for (size_t i = 0; i < sizeof(tcp_readers) / sizeof(tcp_readers[0]); ++i) FieldReader::remove(&tcp_readers[i]); for (size_t i = 0; i < sizeof(tcp_synonyms) / sizeof(tcp_synonyms[0]); ++i) FieldSynonym::remove(&tcp_synonyms[i]);}ELEMENT_REQUIRES(userlevel IPSummaryDump)ELEMENT_PROVIDES(IPSummaryDump_TCP)CLICK_ENDDECLS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -