帮我用c和pcap写一个能捕获数据包(可选择捕获离线还是在线和捕获的个数)、过滤数据包、保存数据包、分析数据包(要能和wireshark能够对比)(解析TCP协议、解析arp协议、解析udp协议、解析IP协议、解析icmp协议)
时间: 2023-08-05 15:02:06 浏览: 106
好的,以下是能够满足你要求的C程序:
```c
#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);
void parse_ethernet(const u_char *pkt_data);
void parse_ip(const u_char *pkt_data);
void parse_tcp(const u_char *pkt_data);
void parse_udp(const u_char *pkt_data);
void parse_icmp(const u_char *pkt_data);
void parse_arp(const u_char *pkt_data);
int main(int argc, char **argv)
{
pcap_t *handle;
char errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program fp;
char filter_exp[] = "tcp";
bpf_u_int32 net, mask;
int num_packets = 10;
char input[10];
int choice;
printf("Choose capture type:\n1. Online\n2. Offline\n");
fgets(input, 10, stdin);
choice = atoi(input);
if (choice == 1) {
handle = pcap_open_live(argv[1], BUFSIZ, 1, 1000, errbuf);
if (handle == NULL) {
printf("pcap_open_live() failed: %s\n", errbuf);
return 1;
}
} else if (choice == 2) {
handle = pcap_open_offline(argv[1], errbuf);
if (handle == NULL) {
printf("pcap_open_offline() failed: %s\n", errbuf);
return 1;
}
} else {
printf("Invalid choice\n");
return 1;
}
printf("Enter number of packets to capture: ");
fgets(input, 10, stdin);
num_packets = atoi(input);
if (pcap_lookupnet(argv[1], &net, &mask, errbuf) == -1) {
printf("pcap_lookupnet() failed: %s\n", errbuf);
return 1;
}
printf("Enter filter expression: ");
fgets(filter_exp, sizeof(filter_exp), stdin);
if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
printf("pcap_compile() failed\n");
return 1;
}
if (pcap_setfilter(handle, &fp) == -1) {
printf("pcap_setfilter() failed\n");
return 1;
}
pcap_dumper_t *dumpfile;
char dumpfile_name[] = "capture.pcap";
dumpfile = pcap_dump_open(handle, dumpfile_name);
if (dumpfile == NULL) {
printf("pcap_dump_open() failed\n");
return 1;
}
pcap_loop(handle, num_packets, packet_handler, (u_char *)dumpfile);
pcap_dump_close(dumpfile);
pcap_close(handle);
return 0;
}
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
pcap_dump(param, header, pkt_data);
printf("\nPacket length: %d\n", header->len);
parse_ethernet(pkt_data);
}
void parse_ethernet(const u_char *pkt_data)
{
struct ether_header *eth_header;
eth_header = (struct ether_header *)pkt_data;
printf("\nEthernet Header\n");
printf("\t|-Source MAC: %s\n", ether_ntoa((struct ether_addr *)eth_header->ether_shost));
printf("\t|-Destination MAC: %s\n", ether_ntoa((struct ether_addr *)eth_header->ether_dhost));
if (ntohs(eth_header->ether_type) == ETHERTYPE_IP) {
parse_ip(pkt_data + sizeof(struct ether_header));
} else if (ntohs(eth_header->ether_type) == ETHERTYPE_ARP) {
parse_arp(pkt_data + sizeof(struct ether_header));
}
}
void parse_ip(const u_char *pkt_data)
{
struct iphdr *ip_header;
ip_header = (struct iphdr *)pkt_data;
printf("\nIP Header\n");
printf("\t|-Version: %d\n", ip_header->version);
printf("\t|-Header length: %d\n", (unsigned int)ip_header->ihl * 4);
printf("\t|-TOS: %d\n", ip_header->tos);
printf("\t|-Total length: %d\n", ntohs(ip_header->tot_len));
printf("\t|-ID: %d\n", ntohs(ip_header->id));
printf("\t|-Flags: %d\n", (unsigned int)ntohs(ip_header->frag_off) >> 13);
printf("\t|-Offset: %d\n", (unsigned int)ntohs(ip_header->frag_off) & 0x1FFF);
printf("\t|-TTL: %d\n", ip_header->ttl);
printf("\t|-Protocol: %d\n", ip_header->protocol);
printf("\t|-Checksum: %d\n", ntohs(ip_header->check));
printf("\t|-Source IP: %s\n", inet_ntoa(*(struct in_addr *)&ip_header->saddr));
printf("\t|-Destination IP: %s\n", inet_ntoa(*(struct in_addr *)&ip_header->daddr));
if (ip_header->protocol == IPPROTO_TCP) {
parse_tcp(pkt_data + (unsigned int)ip_header->ihl * 4);
} else if (ip_header->protocol == IPPROTO_UDP) {
parse_udp(pkt_data + (unsigned int)ip_header->ihl * 4);
} else if (ip_header->protocol == IPPROTO_ICMP) {
parse_icmp(pkt_data + (unsigned int)ip_header->ihl * 4);
}
}
void parse_tcp(const u_char *pkt_data)
{
struct tcphdr *tcp_header;
tcp_header = (struct tcphdr *)pkt_data;
printf("\nTCP Header\n");
printf("\t|-Source Port: %d\n", ntohs(tcp_header->source));
printf("\t|-Destination Port: %d\n", ntohs(tcp_header->dest));
printf("\t|-Sequence Number: %u\n", ntohl(tcp_header->seq));
printf("\t|-Acknowledgement Number: %u\n", ntohl(tcp_header->ack_seq));
printf("\t|-Header length: %d\n", (unsigned int)tcp_header->doff * 4);
printf("\t|-Urgent Flag: %d\n", tcp_header->urg);
printf("\t|-Acknowledgement Flag: %d\n", tcp_header->ack);
printf("\t|-Push Flag: %d\n", tcp_header->psh);
printf("\t|-Reset Flag: %d\n", tcp_header->rst);
printf("\t|-Synchronise Flag: %d\n", tcp_header->syn);
printf("\t|-Finish Flag: %d\n", tcp_header->fin);
printf("\t|-Window size: %d\n", ntohs(tcp_header->window));
printf("\t|-Checksum: %d\n", ntohs(tcp_header->check));
printf("\t|-Urgent Pointer: %d\n", tcp_header->urg_ptr);
}
void parse_udp(const u_char *pkt_data)
{
struct udphdr *udp_header;
udp_header = (struct udphdr *)pkt_data;
printf("\nUDP Header\n");
printf("\t|-Source Port: %d\n", ntohs(udp_header->source));
printf("\t|-Destination Port: %d\n", ntohs(udp_header->dest));
printf("\t|-Length: %d\n", ntohs(udp_header->len));
printf("\t|-Checksum: %d\n", ntohs(udp_header->check));
}
void parse_icmp(const u_char *pkt_data)
{
struct icmphdr *icmp_header;
icmp_header = (struct icmphdr *)pkt_data;
printf("\nICMP Header\n");
printf("\t|-Type: %d\n", icmp_header->type);
printf("\t|-Code: %d\n", icmp_header->code);
printf("\t|-Checksum: %d\n", ntohs(icmp_header->checksum));
}
void parse_arp(const u_char *pkt_data)
{
struct arphdr *arp_header;
arp_header = (struct arphdr *)pkt_data;
printf("\nARP Header\n");
printf("\t|-Hardware type: %d\n", ntohs(arp_header->ar_hrd));
printf("\t|-Protocol type: %d\n", ntohs(arp_header->ar_pro));
printf("\t|-Hardware address length: %d\n", arp_header->ar_hln);
printf("\t|-Protocol address length: %d\n", arp_header->ar_pln));
printf("\t|-Operation: %d\n", ntohs(arp_header->ar_op));
printf("\t|-Sender hardware address: %s\n", ether_ntoa((struct ether_addr *)arp_header->ar_sha));
printf("\t|-Sender IP address: %s\n", inet_ntoa(*(struct in_addr *)&arp_header->ar_sip));
printf("\t|-Target hardware address: %s\n", ether_ntoa((struct ether_addr *)arp_header->ar_tha));
printf("\t|-Target IP address: %s\n", inet_ntoa(*(struct in_addr *)&arp_header->ar_tip));
}
```
这个程序可以让你选择是在线捕获还是离线捕获数据包,同时你可以指定捕获的数据包个数和过滤表达式。捕获到的数据包可以保存到名为“capture.pcap”的文件中,以便之后在Wireshark中分析。此外,它还能解析TCP、UDP、ICMP、IP和ARP协议头,以便你进一步分析数据包。
阅读全文