📄 tcpip.cc
字号:
} if(len > 0) { *result = '\0'; return; } Snprintf(p, bufsize, ">");}/* Returns a buffer of ASCII information about a packet that may look like "TCP 127.0.0.1:50923 > 127.0.0.1:3 S ttl=61 id=39516 iplen=40 seq=625950769" or "ICMP PING (0/1) ttl=61 id=39516 iplen=40". Since this is a static buffer, don't use threads or call twice within (say) printf(). And certainly don't try to free() it! The returned buffer is NUL-terminated */static const char *ippackethdrinfo(const u8 *packet, u32 len) { static char protoinfo[512]; struct ip *ip = (struct ip *) packet; struct tcp_hdr *tcp; struct udp_hdr *udp; char ipinfo[512]; char srchost[INET6_ADDRSTRLEN], dsthost[INET6_ADDRSTRLEN]; char *p; struct in_addr saddr, daddr; int frag_off = 0, more_fragments = 0; char fragnfo[64] = ""; if (ip->ip_v != 4) return "BOGUS! IP Version in packet is not 4"; if (len < sizeof(struct ip)) return "BOGUS! Packet too short."; saddr.s_addr = ip->ip_src.s_addr; daddr.s_addr = ip->ip_dst.s_addr; inet_ntop(AF_INET, &saddr, srchost, sizeof(srchost)); inet_ntop(AF_INET, &daddr, dsthost, sizeof(dsthost)); frag_off = 8 * (ntohs(ip->ip_off) & 8191) /* 2^13 - 1 */; more_fragments = ntohs(ip->ip_off) & IP_MF; if (frag_off || more_fragments) { Snprintf(fragnfo, sizeof(fragnfo), " frag offset=%d%s", frag_off, more_fragments ? "+" : ""); } Snprintf(ipinfo, sizeof(ipinfo), "ttl=%d id=%d iplen=%d%s %s%s%s", ip->ip_ttl, ntohs(ip->ip_id), ntohs(ip->ip_len), fragnfo, ip->ip_hl==5?"":"ipopts={", ip->ip_hl==5?"":print_ip_options((u8*)ip + sizeof(struct ip), MIN((ip->ip_hl-5)*4,len-sizeof(struct ip))), ip->ip_hl==5?"":"}"); if (ip->ip_p == IPPROTO_TCP) { char tflags[10]; char tcpinfo[64] = ""; char buf[32]; char tcpoptinfo[256] = ""; tcp = (struct tcp_hdr *) (packet + ip->ip_hl * 4); if (frag_off > 8 || len < (u32) ip->ip_hl * 4 + 8) Snprintf(protoinfo, sizeof(protoinfo), "TCP %s:?? > %s:?? ?? %s (incomplete)", srchost, dsthost, ipinfo); else if (frag_off == 8) {// at least we can get TCP flags and ACKn tcp = (struct tcp_hdr *)((u8 *) tcp - frag_off); // ugly? p = tflags; /* These are basically in tcpdump order */ if (tcp->th_flags & TH_SYN) *p++ = 'S'; if (tcp->th_flags & TH_FIN) *p++ = 'F'; if (tcp->th_flags & TH_RST) *p++ = 'R'; if (tcp->th_flags & TH_PUSH) *p++ = 'P'; if (tcp->th_flags & TH_ACK) { *p++ = 'A'; Snprintf(tcpinfo, sizeof(tcpinfo), " ack=%lu", (unsigned long) ntohl(tcp->th_ack)); } if (tcp->th_flags & TH_URG) *p++ = 'U'; if (tcp->th_flags & TH_ECE) *p++ = 'E'; /* rfc 2481/3168 */ if (tcp->th_flags & TH_CWR) *p++ = 'C'; /* rfc 2481/3168 */ *p++ = '\0'; if((u32) tcp->th_off * 4 > sizeof(struct tcp_hdr)) { // tcp options if(len < (u32) ip->ip_hl * 4 + (u32) tcp->th_off * 4 - frag_off) { Snprintf(tcpoptinfo, sizeof(tcpoptinfo), "option incomplete"); } else { tcppacketoptinfo((u8*) tcp + sizeof(struct tcp_hdr), tcp->th_off*4 - sizeof(struct tcp_hdr), tcpoptinfo, sizeof(tcpoptinfo)); } } Snprintf(protoinfo, sizeof(protoinfo), "TCP %s:?? > %s:?? %s %s %s %s", srchost, dsthost, tflags, ipinfo, tcpinfo, tcpoptinfo); } else if (len < (u32) ip->ip_hl * 4 + 16) { // we can get ports and seq Snprintf(tcpinfo, sizeof(tcpinfo), "seq=%lu (incomplete)", (unsigned long) ntohl(tcp->th_seq)); Snprintf(protoinfo, sizeof(protoinfo), "TCP %s:%d > %s:%d ?? %s %s", srchost, ntohs(tcp->th_sport), dsthost, ntohs(tcp->th_dport), ipinfo, tcpinfo); } else { // at least first 16 bytes of TCP header are there Snprintf(tcpinfo, sizeof(tcpinfo), "seq=%lu win=%hu", (unsigned long) ntohl(tcp->th_seq), ntohs(tcp->th_win)); p = tflags; /* These are basically in tcpdump order */ if (tcp->th_flags & TH_SYN) *p++ = 'S'; if (tcp->th_flags & TH_FIN) *p++ = 'F'; if (tcp->th_flags & TH_RST) *p++ = 'R'; if (tcp->th_flags & TH_PUSH) *p++ = 'P'; if (tcp->th_flags & TH_ACK) { *p++ = 'A'; Snprintf(buf, sizeof(buf), " ack=%lu", (unsigned long) ntohl(tcp->th_ack)); strncat(tcpinfo, buf, sizeof(tcpinfo) - strlen(tcpinfo) - 1); } if (tcp->th_flags & TH_URG) *p++ = 'U'; if (tcp->th_flags & TH_ECE) *p++ = 'E'; /* rfc 2481/3168 */ if (tcp->th_flags & TH_CWR) *p++ = 'C'; /* rfc 2481/3168 */ *p++ = '\0'; if((u32) tcp->th_off * 4 > sizeof(struct tcp_hdr)) { // tcp options if(len < (u32) ip->ip_hl * 4 + (u32) tcp->th_off * 4) { Snprintf(tcpoptinfo, sizeof(tcpoptinfo), "option incomplete"); } else { tcppacketoptinfo((u8*) tcp + sizeof(struct tcp_hdr), tcp->th_off*4 - sizeof(struct tcp_hdr), tcpoptinfo, sizeof(tcpoptinfo)); } } Snprintf(protoinfo, sizeof(protoinfo), "TCP %s:%d > %s:%d %s %s %s %s", srchost, ntohs(tcp->th_sport), dsthost, ntohs(tcp->th_dport), tflags, ipinfo, tcpinfo, tcpoptinfo); } } else if (ip->ip_p == IPPROTO_UDP && frag_off) { Snprintf(protoinfo, sizeof(protoinfo), "UDP %s:?? > %s:?? fragment %s (incomplete)", srchost, dsthost, ipinfo); } else if (ip->ip_p == IPPROTO_UDP) { udp = (struct udp_hdr *) (packet + sizeof(struct ip)); Snprintf(protoinfo, sizeof(protoinfo), "UDP %s:%d > %s:%d %s", srchost, ntohs(udp->uh_sport), dsthost, ntohs(udp->uh_dport), ipinfo); } else if (ip->ip_p == IPPROTO_ICMP && frag_off) { Snprintf(protoinfo, sizeof(protoinfo), "ICMP %s > %s fragment %s (incomplete)", srchost, dsthost, ipinfo); } else if (ip->ip_p == IPPROTO_ICMP) { char icmptype[128]; char *ip2dst; struct ip *ip2; struct ppkt { unsigned char type; unsigned char code; unsigned short checksum; unsigned short id; unsigned short seq; } *ping; ping = (struct ppkt *) ((ip->ip_hl * 4) + (char *) ip); switch(ping->type) { case 0: strcpy(icmptype, "echo reply"); break; case 3: ip2 = (struct ip *) ((char *) ip + (ip->ip_hl * 4) + 8); tcp = (struct tcp_hdr *) ((char *) ip2 + (ip2->ip_hl * 4)); udp = (struct udp_hdr *) ((char *) ip2 + (ip2->ip_hl * 4)); ip2dst = inet_ntoa(ip2->ip_dst); switch (ping->code) { case 0: Snprintf(icmptype, sizeof icmptype, "network %s unreachable", ip2dst); break; case 1: Snprintf(icmptype, sizeof icmptype, "host %s unreachable", ip2dst); break; case 2: Snprintf(icmptype, sizeof icmptype, "protocol %u unreachable", ip2->ip_p); break; case 3: if (ip2->ip_p == IPPROTO_UDP) Snprintf(icmptype, sizeof icmptype, "port %u unreachable", ntohs(udp->uh_dport)); else if (ip2->ip_p == IPPROTO_TCP) Snprintf(icmptype, sizeof icmptype, "port %u unreachable", ntohs(tcp->th_dport)); else strcpy(icmptype, "port unreachable"); break; case 4: strcpy(icmptype, "fragmentation required"); break; case 5: strcpy(icmptype, "source route failed"); break; case 6: Snprintf(icmptype, sizeof icmptype, "destination network %s unknown", ip2dst); break; case 7: Snprintf(icmptype, sizeof icmptype, "destination host %s unknown", ip2dst); break; case 8: strcpy(icmptype, "source host isolated"); break; case 9: Snprintf(icmptype, sizeof icmptype, "destination network %s administratively prohibited", ip2dst); break; case 10: Snprintf(icmptype, sizeof icmptype, "destination host %s administratively prohibited", ip2dst); break; case 11: Snprintf(icmptype, sizeof icmptype, "network %s unreachable for TOS", ip2dst); break; case 12: Snprintf(icmptype, sizeof icmptype, "host %s unreachable for TOS", ip2dst); break; case 13: strcpy(icmptype, "communication administratively prohibited by filtering"); break; case 14: strcpy(icmptype, "host precedence violation"); break; case 15: strcpy(icmptype, "precedence cutoff in effect"); break; default: strcpy(icmptype, "unknown unreachable code"); break; } break; case 4: strcpy(icmptype, "source quench"); break; case 5: if (ping->code == 0) strcpy(icmptype, "network redirect"); else if (ping->code == 1) strcpy(icmptype, "host redirect"); else strcpy(icmptype, "unknown redirect"); break; case 8: strcpy(icmptype, "echo request"); break; case 11: if (ping->code == 0) strcpy(icmptype, "TTL=0 during transit"); else if (ping->code == 1) strcpy(icmptype, "TTL=0 during reassembly"); else strcpy(icmptype, "TTL exceeded (unknown code)"); break; case 12: if (ping->code == 0) strcpy(icmptype, "IP header bad"); else strcpy(icmptype, "Misc. parameter problem"); break; case 13: strcpy(icmptype, "Timestamp request"); break; case 14: strcpy(icmptype, "Timestamp reply"); break; case 15: strcpy(icmptype, "Information request"); break; case 16: strcpy(icmptype, "Information reply"); break; case 17: strcpy(icmptype, "Address mask request"); break; case 18: strcpy(icmptype, "Address mask reply"); break; case 30: strcpy(icmptype, "Traceroute"); break; case 37: strcpy(icmptype, "Domain name request"); break; case 38: strcpy(icmptype, "Domain name reply"); break; case 40: strcpy(icmptype, "Security failures"); /* rfc 2521 */ break; default: strcpy(icmptype, "Unknown type"); break; break; } Snprintf(protoinfo, sizeof(protoinfo), "ICMP %s > %s %s (type=%d/code=%d) %s", srchost, dsthost, icmptype, ping->type, ping->code, ipinfo); } else { Snprintf(protoinfo, sizeof(protoinfo), "Unknown protocol (%d) %s > %s: %s", ip->ip_p, srchost, dsthost, ipinfo); } return protoinfo;} /* Takes an IP PACKET and prints it if packet tracing is enabled. 'packet' must point to the IPv4 header. The direction must be PacketTrace::SENT or PacketTrace::RCVD . Optional 'now' argument makes this function slightly more efficient by avoiding a gettimeofday() call. */void PacketTrace::trace(pdirection pdir, const u8 *packet, u32 len, struct timeval *now) { struct timeval tv; if (pdir == SENT) { PktCt.sendPackets++; PktCt.sendBytes += len; } else { PktCt.recvPackets++; PktCt.recvBytes += len; } if (!o.packetTrace()) return; if (now) tv = *now; else gettimeofday(&tv, NULL); if (len < 20) { error("Packet tracer: tiny packet encountered"); return; } log_write(LOG_STDOUT|LOG_NORMAL, "%s (%.4fs) %s\n", (pdir == SENT)? "SENT" : "RCVD", o.TimeSinceStartMS(&tv) / 1000.0, ippackethdrinfo(packet, len)); return;}/* Adds a trace entry when a connect() is attempted if packet tracing is enabled. Pass IPPROTO_TCP or IPPROTO_UDP as the protocol. The sock may be a sockaddr_in or sockaddr_in6. The return code of connect is passed in connectrc. If the return code is -1, get the errno and pass that as connect_errno. */void PacketTrace::traceConnect(u8 proto, const struct sockaddr *sock, int socklen, int connectrc, int connect_errno, const struct timeval *now) { struct sockaddr_in *sin = (struct sockaddr_in *) sock;#if HAVE_IPV6 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sock;#endif struct timeval tv; char errbuf[64] = ""; char targetipstr[INET6_ADDRSTRLEN] = ""; u16 targetport = 0; if (!o.packetTrace()) return; if (now) tv = *now; else gettimeofday(&tv, NULL); assert(proto == IPPROTO_TCP || proto == IPPROTO_UDP); if (connectrc == 0) Strncpy(errbuf, "Connected", sizeof(errbuf)); else { Snprintf(errbuf, sizeof(errbuf), "%s", strerror(connect_errno)); } if (sin->sin_family == AF_INET) { if (inet_ntop(sin->sin_family, (char *) &sin->sin_addr, targetipstr, sizeof(targetipstr)) == NULL) fatal("Failed to convert target IPv4 address to presentation format!?!"); targetport = ntohs(sin->sin_port); } else {#if HAVE_IPV6 assert(sin->sin_family == AF_INET6); if (inet_ntop(sin->sin_family, (char *) &sin6->sin6_addr, targetipstr, sizeof(targetipstr)) == NULL) fatal("Failed to convert target IPv6 address to presentation format!?!"); targetport = ntohs(sin6->sin6_port);#else assert(0);#endif } log_write(LOG_STDOUT|LOG_NORMAL, "CONN (%.4fs) %s localhost > %s:%d => %s\n", o.TimeSinceStartMS(&tv) / 1000.0, (proto == IPPROTO_TCP)? "TCP" : "UDP", targetipstr, targetport, errbuf);}/* Converts an IP address given in a sockaddr_storage to an IPv4 or IPv6 IP address string. Since a static buffer is returned, this is not thread-safe and can only be used once in calls like printf() */const char *inet_socktop(struct sockaddr_storage *ss) { static char buf[INET6_ADDRSTRLEN]; struct sockaddr_in *sin = (struct sockaddr_in *) ss;#if HAVE_IPV6 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) ss;#endif if (inet_ntop(sin->sin_family, (sin->sin_family == AF_INET)? (char *) &sin->sin_addr : #if HAVE_IPV6 (char *) &sin6->sin6_addr, #else (char *) NULL,#endif /* HAVE_IPV6 */ buf, sizeof(buf)) == NULL) { fatal("Failed to convert target address to presentation format in %s!?! Error: %s", __func__, strerror(socket_errno())); } return buf;}/* Tries to resolve the given name (or literal IP) into a sockaddr structure. The af should be PF_INET (for IPv4) or PF_INET6. Returns 0 if hostname cannot be resolved. It is OK to pass in a sockaddr_in or sockaddr_in6 casted to a sockaddr_storage as long as you use the matching
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -