📄 fromtcpdump.cc
字号:
else if (s + 9 <= end && memcmp(s + 1, "[bad udp", 8) == 0 && (s2 = find(s + 9, end, ']')) + 1 < end && s2[1] == ' ') s = s2 + 2; // then check for 'udp LENGTH' if (s + 4 < end && s[0] == 'u' && s[1] == 'd' && s[2] == 'p' && s[3] == ' ' && isdigit(s[4])) { uint32_t dl; s = cp_unsigned(s + 4, end, 0, &dl); *data_len = dl; } return s;}Packet *FromTcpdump::read_packet(ErrorHandler *errh){ WritablePacket *q = Packet::make(0, (const unsigned char *)0, sizeof(click_ip) + sizeof(click_tcp), 20); if (!q) { _ff.error(errh, "out of memory!"); _dead = true; return 0; } if (_zero) memset(q->data(), 0, q->length()); q->set_ip_header((click_ip *)q->data(), sizeof(click_ip)); click_ip *iph = q->ip_header(); iph->ip_v = 4; iph->ip_hl = sizeof(click_ip) >> 2; iph->ip_off = 0; iph->ip_tos = 0; iph->ip_ttl = 2; click_udp *udph = q->udp_header(); String line; StringAccum payload; String ip_opt; String tcp_opt; while (1) { if (_ff.read_line(line, errh) <= 0) { q->kill(); _dead = true; return 0; } const char *s = line.data(); const char *end = line.end(); if (s >= end || s[0] == '#') continue; else if (!isdigit(s[0])) break; // first, read timestamp const char *s2 = find(s, end, ' '); if (!cp_time(line.substring(s, s2), &q->timestamp_anno())) break; s = s2 + 1; // then, guess protocol iph->ip_p = 0; const char *colon = find(s, end, ':'); for (colon++; colon < end && *colon == ' '; colon++) /* nada */; if (colon < end) { if (*colon == 'i') iph->ip_p = IP_PROTO_ICMP; else if (*colon == 'u' || (*colon == '[' && colon + 1 < end && colon[1] == 'u')) iph->ip_p = IP_PROTO_UDP; else if (*colon == '.' || (*colon >= 'A' && *colon <= 'Z')) iph->ip_p = IP_PROTO_TCP; } // then, read source IP address and port s2 = find(s, end, ' '); if (s2 == s || s2 + 2 >= end || s2[1] != '>' || s2[2] != ' ') break; if (iph->ip_p == IP_PROTO_TCP || iph->ip_p == IP_PROTO_UDP) { const char *sm = s2 - 1; while (sm > s && *sm != '.' && *sm != ':') sm--; if (!cp_ip_address(line.substring(s, sm), (IPAddress *) &iph->ip_src) || !cp_tcpudp_port(line.substring(sm + 1, s2), iph->ip_p, &udph->uh_sport)) break; else udph->uh_sport = htons(udph->uh_sport); } else if (!cp_ip_address(line.substring(s, s2), (IPAddress *) &iph->ip_src)) break; s = s2 + 3; // then, read destination IP address and port s2 = find(s, end, ':'); if (iph->ip_p == IP_PROTO_TCP || iph->ip_p == IP_PROTO_UDP) { const char *sm = s2 - 1; while (sm > s && *sm != '.' && *sm != ':') sm--; if (!cp_ip_address(line.substring(s, sm), (IPAddress *) &iph->ip_dst) || !cp_tcpudp_port(line.substring(sm + 1, s2), iph->ip_p, &udph->uh_dport)) break; else udph->uh_dport = htons(udph->uh_dport); } else if (!cp_ip_address(line.substring(s, s2), (IPAddress *) &iph->ip_dst)) break; // then, read protocol data int data_len = -1; if (iph->ip_p == IP_PROTO_TCP && IP_FIRSTFRAG(iph)) { s = read_tcp_line(q, colon, end, &data_len); iph = q->ip_header(); } else if (iph->ip_p == IP_PROTO_UDP && IP_FIRSTFRAG(iph)) { s = read_udp_line(q, colon, end, &data_len); q->take(sizeof(click_tcp) - sizeof(click_udp)); } else { q->take(sizeof(click_tcp)); s = colon; } // parse IP stuff at the end of the line // TTL and ID s2 = end - 1; while (s2 > s) { while (s2 > s && isspace(*s2)) s2--; if (s2 <= s || (*s2 != ')' && *s2 != ']')) break; char opener = (*s2 == ')' ? '(' : '['); const char *open = s2 - 1; while (open >= s && *open != opener) open--; const char *close = s2; s2 = open - 1; uint32_t u; if (open >= s && open < close) { const char *item = open + 1; while (item < close) { if (close - item >= 7 && memcmp(item, "tos 0x", 6) == 0) { item = cp_unsigned(item + 6, close, 16, &u); iph->ip_tos = u; } else if (close - item >= 6 && memcmp(item, "ECT(", 4) == 0 && (item[4] == '0' || item[4] == '1') && item[5] == ')') { iph->ip_tos = (iph->ip_tos & ~IP_ECNMASK) | (item[4] == '0' ? IP_ECN_ECT1 : IP_ECN_ECT2); item += 6; } else if (close - item >= 2 && item[0] == 'C' && item[1] == 'E') { iph->ip_tos = (iph->ip_tos & ~IP_ECNMASK) | IP_ECN_CE; item += 2; } else if (close - item >= 2 && item[0] == 'D' && item[1] == 'F') { iph->ip_off |= htons(IP_DF); item += 2; } else if (close - item >= 10 && memcmp(item, "frag ", 5) == 0 && isdigit(item[5])) { item = cp_unsigned(item + 5, close, 0, &u); iph->ip_id = htons(u); if (item > close - 2 || *item != ':' || !isdigit(item[1])) break; item = cp_unsigned(item + 1, close, 0, &u); data_len = u; if (item > close - 2 || *item != '@' || !isdigit(item[1])) break; item = cp_unsigned(item + 1, close, 0, &u); iph->ip_off = (iph->ip_off & htons(~IP_OFFMASK)) | htons(u); if (item < close && *item == '+') iph->ip_off |= htons(IP_MF), item++; } else if (close - item >= 5 && memcmp(item, "ttl ", 4) == 0 && isdigit(item[4])) { item = cp_unsigned(item + 4, close, 0, &u); iph->ip_ttl = u; } else if (close - item >= 4 && memcmp(item, "id ", 3) == 0 && isdigit(item[3])) { item = cp_unsigned(item + 3, close, 0, &u); iph->ip_id = htons(u); } else if (close - item >= 5 && memcmp(item, "len ", 4) == 0 && isdigit(item[4])) { item = cp_unsigned(item + 4, close, 0, &u); if (data_len < 0 || u == q->length() + data_len) data_len = u - q->length(); else if (iph->ip_p == IP_PROTO_TCP) { // the discrepancy must be due to TCP options int delta = u - (q->length() + data_len); q->change_headroom_and_length(q->headroom(), u - data_len); q->tcp_header()->th_off = (q->transport_length() >> 2); if (delta > 0) q->end_data()[-delta] = TCPOPT_EOL; } } else break; while (item < close && (*item == ',' || isspace(*item))) item++; } } } // set IP length if (data_len < 0) data_len = 0; iph->ip_len = ntohs(q->length() + data_len); SET_EXTRA_LENGTH_ANNO(q, data_len); // set UDP length (after IP length is available) if (iph->ip_p == IP_PROTO_UDP && IP_FIRSTFRAG(iph)) q->udp_header()->uh_ulen = htons(ntohs(iph->ip_len) - (iph->ip_hl << 2)); // set checksum if (_checksum) set_checksums(q, iph); return q; } // bad format if we get here if (!_format_complaint) { // don't complain if the line was all blank const char *s = line.begin(); while (s < line.end() && (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r')) s++; if (s != line.end()) { _ff.error(errh, "packet parse error"); _format_complaint = true; } } if (q) q->kill(); return 0;}boolFromTcpdump::run_task(){ if (!_active) return false; Packet *p; while (1) { p = read_packet(0); if (_dead) { if (_stop) router()->please_stop_driver(); return false; } // check sampling probability if (_sampling_prob >= (1 << SAMPLING_SHIFT) || (uint32_t)(random() & ((1 << SAMPLING_SHIFT) - 1)) < _sampling_prob) break; if (p) p->kill(); } if (p) output(0).push(p); _task.fast_reschedule(); return true;}Packet *FromTcpdump::pull(int){ if (!_active) return 0; Packet *p; while (1) { p = read_packet(0); if (_dead) { if (_stop) router()->please_stop_driver(); _notifier.set_listeners(false); return 0; } // check sampling probability if (_sampling_prob >= (1 << SAMPLING_SHIFT) || (uint32_t)(random() & ((1 << SAMPLING_SHIFT) - 1)) < _sampling_prob) break; if (p) p->kill(); } _notifier.set_listeners(true); return p;}enum { H_SAMPLING_PROB, H_ACTIVE, H_ENCAP, H_STOP };StringFromTcpdump::read_handler(Element *e, void *thunk){ FromTcpdump *fd = static_cast<FromTcpdump *>(e); switch ((intptr_t)thunk) { case H_SAMPLING_PROB: return cp_unparse_real2(fd->_sampling_prob, SAMPLING_SHIFT) + "\n"; case H_ACTIVE: return cp_unparse_bool(fd->_active) + "\n"; case H_ENCAP: return "IP\n"; default: return "<error>\n"; }}intFromTcpdump::write_handler(const String &s_in, Element *e, void *thunk, ErrorHandler *errh){ FromTcpdump *fd = static_cast<FromTcpdump *>(e); String s = cp_uncomment(s_in); switch ((intptr_t)thunk) { case H_ACTIVE: { bool active; if (cp_bool(s, &active)) { fd->_active = active; if (fd->output_is_push(0) && active && !fd->_task.scheduled()) fd->_task.reschedule(); else if (!fd->output_is_push(0)) fd->_notifier.set_listeners(active); return 0; } else return errh->error("`active' should be Boolean"); } case H_STOP: fd->_active = false; fd->router()->please_stop_driver(); return 0; default: return -EINVAL; }}voidFromTcpdump::add_handlers(){ add_read_handler("sampling_prob", read_handler, (void *)H_SAMPLING_PROB); add_read_handler("active", read_handler, (void *)H_ACTIVE); add_write_handler("active", write_handler, (void *)H_ACTIVE); add_read_handler("encap", read_handler, (void *)H_ENCAP); add_write_handler("stop", write_handler, (void *)H_STOP); _ff.add_handlers(this); if (output_is_push(0)) add_task_handlers(&_task);}ELEMENT_REQUIRES(userlevel FromFile IPSummaryDump)EXPORT_ELEMENT(FromTcpdump)#include <click/bighashmap.cc>CLICK_ENDDECLS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -