waitpacket.c
来自「网络流量生成工具,开源软件,也可以作为网络流量检测软件使用」· C语言 代码 · 共 622 行
C
622 行
/* * $smu-mark$ * $name: waitpacket.c$ * $author: Salvatore Sanfilippo <antirez@invece.org>$ * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ * $license: This software is under GPL version 2 of license$ * $date: Fri Nov 5 11:55:50 MET 1999$ * $rev: 8$ */ #include <stdio.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <errno.h>#include <time.h>#include <ctype.h>#include <unistd.h>#include "hping2.h"#include "globals.h"static int icmp_unreach_rtt(void *quoted_ip, int size, int *seqp, float *ms_delay);static void print_tcp_timestamp(void *tcp, int tcpsize);/* FIXME: wait_packet don't support ip and tcp options, it waits for 20 bytes IP hdr + 20 bytes TCP hdr. --> ip options fixed 31/08/99 (MK)*/void wait_packet(void){ char packet [LINK_PACKETSIZE], recvflags[1024], src_addr[1024], dst_addr[1024], *p; int recv_sport, recv_dport, size, rstseq, sequence, winsize, status, match = FALSE, ip_id, rel_id; float ms_delay; struct in_addr src, dst; struct myiphdr ip; struct mytcphdr tcp; struct myudphdr udp; struct myicmphdr icmp; struct myiphdr icmp_iph; struct icmp_tstamp_data icmp_tstamp; char hlen;#if (!defined OSTYPE_LINUX) || (defined FORCE_LIBPCAP) size = pcap_recv(packet, LINK_PACKETSIZE); if (size == -1) { perror("[wait_packet] pcap_recv()"); return; }#else size = recv(sockpacket, packet, LINK_PACKETSIZE, 0); if (size == -1) { if (errno != EINTR) { perror("[wait_packet] recv"); print_statistics(-1); } else return; }#endif if (size < linkhdr_size+IPHDR_SIZE) return; memcpy(&ip, packet+ABS_OFFSETIP, sizeof(ip)); hlen = ip.ihl << 2; memcpy(&tcp, packet+ABS_OFFSETIP+hlen, sizeof(tcp)); memcpy(&udp, packet+ABS_OFFSETIP+hlen, sizeof(udp)); memcpy(&icmp, packet+ABS_OFFSETIP+hlen, sizeof(icmp)); memcpy(&icmp_iph, packet+ABS_OFFSETIP+hlen+8, sizeof(icmp_iph)); memcpy(&icmp_tstamp, packet+ABS_OFFSETIP+hlen+8, sizeof(icmp_tstamp)); /* --------- HCMP --------- */ if (opt_sign && (p = memstr(packet, rsign, size))) { struct hcmphdr *hcmph; __u16 seqnum; __u32 usec; if (opt_debug) fprintf(stderr, "HCMP received\n"); p+=strlen(rsign); if ((size-(packet-p)) < sizeof(struct hcmphdr)) { if (opt_verbose || opt_debug) fprintf(stderr, "bad HCMP len received\n"); goto hcmp_exit; } hcmph = (struct hcmphdr*) p; switch(hcmph->type) { case HCMP_RESTART: seqnum = ntohs(hcmph->typedep.seqnum); break; case HCMP_SOURCE_QUENCH: case HCMP_SOURCE_STIRUP: usec = ntohl(hcmph->typedep.usec); default: if (opt_verbose || opt_debug) fprintf(stderr, "bad HCMP type received\n"); goto hcmp_exit; } switch(hcmph->type) { case HCMP_RESTART: src_id = seqnum; /* set id */ datafiller(NULL, seqnum); /* data seek */ goto hcmp_exit; case HCMP_SOURCE_QUENCH: case HCMP_SOURCE_STIRUP: printf("Source quench / stirpu" " still not implemented!\n"); goto hcmp_exit; /* default handled in the first switch */ } }hcmp_exit: /* get source and target address */ memcpy(&src, &(ip.saddr), sizeof(struct in_addr)); memcpy(&dst, &(ip.daddr), sizeof(struct in_addr)); strncpy(src_addr, inet_ntoa(src), 1024); strncpy(dst_addr, inet_ntoa(dst), 1024); /* get ip->id */ if (opt_winid_order) ip_id = ip.id; else ip_id = htons(ip.id); /* get source and target port */ if (opt_udpmode) /* UDP */ { recv_sport = ntohs(udp.uh_sport); recv_dport = ntohs(udp.uh_dport); } else /* TCP */ { recv_sport = ntohs(tcp.th_sport); recv_dport = ntohs(tcp.th_dport); } /* --------- TCP --------- */ if ( ip.protocol == IPPROTO_TCP && !memcmp(&ip.saddr, &remote.sin_addr, sizeof(ip.saddr)) && !memcmp(&ip.daddr, &local.sin_addr, sizeof(ip.daddr)) && (recv_sport == dst_port || opt_force_incdport) ) { match = TRUE; winsize = ntohs(tcp.th_win); tcp_exitcode = tcp.th_flags; recvflags[0] = '\0'; if (tcp.th_flags & TH_RST) strcat(recvflags, "R"); if (tcp.th_flags & TH_SYN) strcat(recvflags, "S"); if (tcp.th_flags & TH_ACK) strcat(recvflags, "A"); if (tcp.th_flags & TH_FIN) strcat(recvflags, "F"); if (tcp.th_flags & TH_PUSH) strcat(recvflags, "P"); if (tcp.th_flags & TH_URG) strcat(recvflags, "U"); if (tcp.th_flags & TH_X) strcat(recvflags, "X"); if (tcp.th_flags & TH_Y) strcat(recvflags, "Y"); if (recvflags[0] == '\0') strcat(recvflags, "none"); /* obtain round trip time */ sequence = 0; status = rtt(&sequence, recv_dport, &ms_delay); /* relativize packets ip->id */ if (opt_relid) rel_id = relativize_id(sequence, &ip_id); else rel_id = FALSE; if (opt_seqnum) { static __u32 old_th_seq = 0; __u32 seq_diff, tmp; tmp = ntohl(tcp.th_seq); if (tmp >= old_th_seq) seq_diff = tmp - old_th_seq; else seq_diff = (4294967295U - old_th_seq) + tmp; old_th_seq = tmp; printf("%10lu +%lu\n", (unsigned long) tmp, (unsigned long) seq_diff); } if (!opt_quiet && !opt_seqnum) { if (status == S_RECV) printf("DUP! "); if (!opt_incdport) printf("len=%d ip=%s ", size - linkhdr_size, src_addr); else printf("len=%d ip=%s sport=%d ", size - linkhdr_size, src_addr, recv_sport); printf("flags=%s ", recvflags); if (ntohs(ip.frag_off) & DF) printf("DF "); printf("seq=%d ", sequence); printf("ttl=%d ", ip.ttl); printf("id"); if (rel_id == TRUE) printf("=+"); else putchar('='); printf("%d ", ip_id); printf("win=%d ", winsize); printf("rtt=%.1f ms", ms_delay); putchar('\n'); } if (opt_verbose && !opt_quiet) { printf("tos=%x ", ip.tos); printf("iplen=%u ", htons(ip.tot_len)); printf("seq=%lu ", (unsigned long) ntohl(tcp.th_seq)); printf("ack=%lu ", (unsigned long) ntohl(tcp.th_ack)); printf("sum=%x ", tcp.th_sum); printf("urp=%u ", tcp.th_urp); putchar('\n'); putchar('\n'); } if (opt_tcp_timestamp) print_tcp_timestamp(packet+ABS_OFFSETIP+hlen, size - linkhdr_size - hlen); fflush(stdout); recv_pkt++; if (opt_incdport && !opt_force_incdport) dst_port++; } /* --------- ICMP --------- */ if ( ip.protocol == IPPROTO_ICMP ) { match = TRUE; /* Echo reply */ if ((icmp.type == 0 || icmp.type == ICMP_TIMESTAMPREPLY || icmp.type == ICMP_ADDRESSREPLY) && icmp.un.echo.id == (getpid() & 0xffff)) { recv_pkt++; if (!opt_quiet) { rstseq = icmp.un.echo.sequence; /* obtain round trip time */ status = rtt(&rstseq, 0, &ms_delay); /* relativize packets ip->id */ if (opt_relid) rel_id = relativize_id(rstseq, &ip_id); else rel_id = FALSE; printf("%d bytes from %s: ", size - linkhdr_size, src_addr); printf("icmp_seq=%d ", rstseq); printf("ttl=%d ", ip.ttl); printf("id"); if (rel_id == TRUE) printf("=+"); else putchar('='); printf("%d ", ip_id); printf("rtt=%.1f ms", ms_delay); putchar('\n'); if (icmp.type == ICMP_TIMESTAMPREPLY) { printf("ICMP timestamp: " "Originate=%u " "Receive=%u " "Transmit=%u\n", (unsigned int) ntohl(icmp_tstamp.orig), (unsigned int) ntohl(icmp_tstamp.recv), (unsigned int) ntohl(icmp_tstamp.tran)); printf("ICMP timestamp RTT tsrtt=%lu\n", (get_midnight_ut_ms() - ntohl(icmp_tstamp.orig))); } if (icmp.type == ICMP_ADDRESSREPLY) { unsigned char *addr = (unsigned char*) packet+ ABS_OFFSETIP+hlen+8; /* XXX: doesn't check the len */ printf("ICMP address mask: " "icmpam=%u.%u.%u.%u\n", addr[0], addr[1], addr[2], addr[3]); } } } else if ( icmp.type == 3 && /* Dest. Unreachable */ !memcmp(&icmp_iph.daddr, &remote.sin_addr, sizeof(ip.daddr)) && !memcmp(&ip.daddr, &local.sin_addr, sizeof(ip.daddr)) ) { if (!opt_quiet) log_icmp_unreach(src_addr, icmp.code); } else if (icmp.type == 11 && /* Time exceeded */ !memcmp(&icmp_iph.daddr, &remote.sin_addr, sizeof(ip.daddr)) && !memcmp(&ip.daddr, &local.sin_addr, sizeof(ip.daddr)) ) { /* traceroute mode */ static unsigned char old_src_addr[4]={0,0,0,0}; if (opt_traceroute) { if (opt_tr_keep_ttl || memcmp(&ip.saddr, old_src_addr, 4)) { int sequence = 0, retval; float rtt; retval = icmp_unreach_rtt( packet+ABS_OFFSETIP+hlen+8, size - linkhdr_size - hlen - 8, &sequence, &rtt); memcpy(old_src_addr, &ip.saddr, 4); printf("hop=%d ", src_ttl); fflush(stdout); log_icmp_timeexc(src_addr, icmp.code); if (retval != -1) printf("hop=%d " "hoprtt=%.1f ms\n", src_ttl, rtt); if (!opt_tr_keep_ttl) src_ttl++; } } else { if (!opt_quiet) log_icmp_timeexc(src_addr, icmp.code); } } else match = FALSE; } /* --------- UDP --------- */ if ( ip.protocol == IPPROTO_UDP && !memcmp(&ip.saddr, &remote.sin_addr, sizeof(ip.saddr)) && !memcmp(&ip.daddr, &local.sin_addr, sizeof(ip.daddr)) && recv_sport == dst_port ) { match = TRUE; /* obtain round trip time */ sequence = 0; status = rtt(&sequence, recv_dport, &ms_delay); /* relativize ip->id */ if (opt_relid) rel_id = relativize_id(sequence, &ip_id); else rel_id = FALSE; if (!opt_quiet) { if (status == S_RECV) printf("DUP! "); if (!opt_incdport) printf("len=%d ip=%s ", size - linkhdr_size, src_addr); else printf("len=%d ip=%s sport=%d: ", size - linkhdr_size, src_addr, recv_sport); printf("seq=%d ", sequence); printf("ttl=%d ", ip.ttl); printf("id"); if (rel_id == TRUE) printf("=+"); else putchar('='); printf("%d ", ip_id); printf("rtt=%.1f ms", ms_delay); putchar('\n'); } fflush(stdout); recv_pkt++; if (opt_incdport && !opt_force_incdport) dst_port++; } /* ---------------- COMMON ---------------- */ /* dump the received packet in hex */ if (opt_hexdump && match && !opt_quiet) { unsigned char *byte; int count = 0; printf("\t\t"); for (byte = (unsigned char*) packet; byte < (unsigned char*) (packet+size); byte++) { count++; printf("%02x", *byte); if (count % 2 == 0) printf(" "); if (count % 16 == 0) printf("\n\t\t"); } printf("\n\n"); } /* dump the received packet printable characters */ if (opt_contdump && match && !opt_quiet) { unsigned char *byte; int count = 0; printf("\t\t"); for (byte = (unsigned char*) packet; byte < (unsigned char*) (packet+size); byte++) { count ++; if (isprint(*byte)) printf("%c", *byte); else printf("."); if (count % 32 == 0) printf("\n\t\t"); } printf("\n\n"); } /* display IP options */ if (opt_rroute && match && !opt_quiet) { display_ipopt(packet+ABS_OFFSETIP); } /* --stop-tr stops hping in traceroute mode when the * first not ICMP time exceeded packet is received */ if (opt_traceroute && opt_tr_stop && match) { if (ip.protocol != IPPROTO_ICMP || icmp.type != 11) print_statistics(0); } /* exit if 'count' is reached */ if (count != -1 && count == recv_pkt) print_statistics(0);}/* Try to extract information about the original packet from the * ICMP error to obtain the round time trip * * Note that size is the the packet size starting from the * IP packet quoted in the ICMP error, it may be negative * if the ICMP is broken */static int icmp_unreach_rtt(void *quoted_ip, int size, int *seqp, float *ms_delay){ int src_port; int sequence = 0; int quoted_iphdr_size; struct myudphdr udp; struct myicmphdr icmp; struct myiphdr qip; /* The user specified --no-rtt */ if (opt_tr_no_rtt) return -1; if (size < sizeof(struct myiphdr)) return -1; memcpy(&qip, quoted_ip, sizeof(struct myiphdr)); quoted_iphdr_size = qip.ihl << 2; /* Ok, enough room, try to get the rtt, * but check if the original packet was an UDP/TCP one */ if (qip.protocol == IPPROTO_TCP || qip.protocol == IPPROTO_UDP) { /* We need at least 2 bytes of the quoted UDP/TCP header * for the source port */ if ((size - quoted_iphdr_size) < 2) return -1; /* Use the UDP header for both UDP and TCP, they are * the same in the 4 first bytes (source and dest port) */ memcpy(&udp, quoted_ip+quoted_iphdr_size, sizeof(udp)); src_port = htons(udp.uh_sport); return rtt(&sequence, src_port, ms_delay); } else if (qip.protocol == IPPROTO_ICMP) { int s; /* We need the whole 8 byte ICMP header to get * the sequence field, also the type must be * ICMP_ECHO */ memcpy(&icmp, quoted_ip+quoted_iphdr_size, sizeof(icmp)); if ((size - quoted_iphdr_size) < 8 || icmp.type != ICMP_ECHO) return -1; s = icmp.un.echo.sequence; return rtt(&s, 0, ms_delay); } return -1; /* no way */}static void print_tcp_timestamp(void *tcp, int tcpsize){ int optlen; unsigned char *opt; __u32 tstamp, echo; static __u32 last_tstamp = 0; struct mytcphdr tmptcphdr; unsigned int tcphdrlen; if (tcpsize < TCPHDR_SIZE) return; memcpy(&tmptcphdr, tcp, sizeof(struct mytcphdr)); tcphdrlen = tmptcphdr.th_off * 4; /* bad len or no options in the TCP header */ if (tcphdrlen <= 20 || tcphdrlen < tcpsize) return; optlen = tcphdrlen - TCPHDR_SIZE; opt = (unsigned char*)tcp + TCPHDR_SIZE; /* skips the TCP fix header */ while(optlen) { switch(*opt) { case 0: /* end of option */ return; case 1: /* noop */ opt++; optlen--; continue; default: if (optlen < 2) return; if (opt[1] > optlen) return; if (opt[0] != 8) { /* not timestamp */ optlen -= opt[1]; opt += opt[1]; continue; } /* timestamp found */ if (opt[1] != 10) /* bad len */ return; memcpy(&tstamp, opt+2, 4); memcpy(&echo, opt+6, 4); tstamp = ntohl(tstamp); echo = ntohl(echo); goto found; } }found: printf(" TCP timestamp: tcpts=%u\n", tstamp); if (last_tstamp && !opt_waitinusec) { int tsdiff = (tstamp - last_tstamp) / sending_wait; int hz_set[] = { 2, 10, 100, 1000, 0 }; int hzdiff = -1; int hz = 0, sec; int days, hours, minutes; if (tsdiff > 0) { int i = 0; while(hz_set[i]) { if (hzdiff == -1) { hzdiff = ABS(tsdiff-hz_set[i]); hz = hz_set[i]; } else if (hzdiff > ABS(tsdiff-hz_set[i])) { hzdiff = ABS(tsdiff-hz_set[i]); hz = hz_set[i]; } i++; } printf(" HZ seems hz=%d\n", hz); sec = tstamp/hz; /* Get the uptime in seconds */ days = sec / (3600*24); sec %= 3600*24; hours = sec / 3600; sec %= 3600; minutes = sec / 60; sec %= 60; printf(" System uptime seems: %d days, %d hours, " "%d minutes, %d seconds\n", days, hours, minutes, sec); } } printf("\n"); last_tstamp = tstamp;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?