#include #include #include "ipv6_utils.h" #include "packet_priv.h" struct options { char *file; int print_proto; int print_summary; }; static uint64_t number = 0; static int ipv6_proto_to_str(const struct packet_layer *ipv6_layer, char *buff, int size) { int used = snprintf(buff, size, "ipv6"); uint8_t next_hdr = ipv6_hdr_get_next_header((const struct ip6_hdr *)ipv6_layer->hdr_ptr); switch (next_hdr) { case IPPROTO_HOPOPTS: used += snprintf(buff + used, size - used, ":ipv6.hopopt"); break; case IPPROTO_ROUTING: used += snprintf(buff + used, size - used, ":ipv6.routing"); break; case IPPROTO_AH: used += snprintf(buff + used, size - used, ":ipv6.ah"); break; case IPPROTO_DSTOPTS: used += snprintf(buff + used, size - used, ":ipv6.dstopts"); break; default: break; } return used; } static int packet_proto_to_str(const struct packet *pkt, char *buff, int size) { int used = 0; int8_t num = packet_get_layers_number(pkt); for (int8_t i = 0; i < num; i++) { const struct packet_layer *layer = packet_get_layer(pkt, i); switch (layer->type) { case LAYER_TYPE_ETHER: used += snprintf(buff + used, size - used, "eth:ethertype"); break; case LAYER_TYPE_PPP: used += snprintf(buff + used, size - used, "ppp"); break; case LAYER_TYPE_HDLC: used += snprintf(buff + used, size - used, "hdlc"); break; case LAYER_TYPE_L2TP: used += snprintf(buff + used, size - used, "l2tp"); break; case LAYER_TYPE_VLAN: used += snprintf(buff + used, size - used, "vlan:ethertype"); break; case LAYER_TYPE_PPPOE: used += snprintf(buff + used, size - used, "pppoes:ppp"); break; case LAYER_TYPE_MPLS: used += snprintf(buff + used, size - used, "mpls"); break; case LAYER_TYPE_IPV4: used += snprintf(buff + used, size - used, "ip"); break; case LAYER_TYPE_IPV6: used += ipv6_proto_to_str(layer, buff + used, size - used); break; case LAYER_TYPE_GRE: used += snprintf(buff + used, size - used, "gre"); break; case LAYER_TYPE_UDP: used += snprintf(buff + used, size - used, "udp"); break; case LAYER_TYPE_TCP: used += snprintf(buff + used, size - used, "tcp"); break; case LAYER_TYPE_ICMP: used += snprintf(buff + used, size - used, "icmp"); break; case LAYER_TYPE_ICMP6: used += snprintf(buff + used, size - used, "icmpv6"); break; case LAYER_TYPE_VXLAN: used += snprintf(buff + used, size - used, "vxlan"); break; case LAYER_TYPE_GTPV1_U: used += snprintf(buff + used, size - used, "gtp"); break; default: used += snprintf(buff + used, size - used, "unknown"); break; } if (i != num - 1) { used += snprintf(buff + used, size - used, ":"); } } return used; } static void packet_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) { struct options *opts = (struct options *)user; struct packet pkt; packet_parse(&pkt, (const char *)bytes, h->caplen); number++; if (opts->print_summary) { printf("\033[0;32m frame=%lu len=%u \033[0m", number, h->caplen); packet_print_str(&pkt); } if (opts->print_proto) { char buff[1024] = {0}; packet_proto_to_str(&pkt, buff, sizeof(buff)); printf("%lu %s\n", number, buff); } } static void usage(char *cmd) { printf("Usage: %s\n", cmd); printf("Options:\n"); printf(" -f pcap file\n"); printf(" -p print protocol\n"); printf(" -s print summary\n"); printf(" -h print help\n"); printf("\n"); } int main(int argc, char **argv) { int opt = 0; struct options opts = {0}; while ((opt = getopt(argc, argv, "f:psh")) != -1) { switch (opt) { case 'f': opts.file = optarg; break; case 'p': opts.print_proto = 1; break; case 's': opts.print_summary = 1; break; case 'h': default: usage(argv[0]); return 0; } } if (opts.file == NULL) { usage(argv[0]); return -1; } pcap_t *pcap = pcap_open_offline(opts.file, NULL); if (pcap == NULL) { printf("pcap_open_offline() failed\n"); return -1; } pcap_loop(pcap, -1, packet_handler, (u_char *)&opts); pcap_close(pcap); return 0; }