PCAP文件 IP隧道 转换 带MAC头报文

VPN 隧道抓的报文, 没有带上 完整的 MAC 头部信息.
不便于 某些专用程序的处理.
写了一个小方法, 实现转换功能. MAC数据为自己造的.

ip_p2p.pcap

padding_ETH_MAC.pcap

pcap_ip_to_eth.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>

#define DLT_NULL 0 /* BSD loopback encapsulation */
#define DLT_EN10MB 1 /* Ethernet (10Mb) */
#define DLT_PPP 9 /* Point-to-point Protocol */
#define PCAP_VERSION_MAJOR 2
#define PCAP_VERSION_MINOR 4

const char *ETH_SMAC = "\x00\x21\x45\x00\x01\x13";
const char *ETH_DMAC = "\x7c\x69\xf6\x71\x8b\x10";
const char *ETH_PROTO = "\x08\00";

struct pcap_file_header {
uint32_t magic;
uint16_t version_major;
uint16_t version_minor;
uint32_t thiszone; /* gmt to local correction */
uint32_t sigfigs; /* accuracy of timestamps */
uint32_t snaplen; /* max length saved portion of each pkt */
uint32_t linktype; /* data link type (LINKTYPE_*) */
};

struct pcap_pkthdr {
uint32_t sec; /* time stamp */
uint32_t usec; /* time stamp */
uint32_t caplen; /* length of portion present */
uint32_t len; /* length this packet (off wire) */
};

int copy_header(FILE *src, FILE*dst)
{
uint64_t rc;
struct pcap_file_header fh;

fread(&fh, 1, sizeof(struct pcap_file_header), stdin);
if(0xA1B2C3D4 != (uint64_t)fh.magic)
{
fprintf(stderr, "Bad file Magic %08X\n", fh.magic);
abort();
}

fh.version_major = PCAP_VERSION_MAJOR;
fh.version_minor = PCAP_VERSION_MINOR;
fh.snaplen = ntohl(1024);
fh.linktype = DLT_EN10MB;

rc = fwrite(&fh, 1, sizeof(struct pcap_file_header), dst);
if(sizeof(struct pcap_file_header) != rc)
{
perror("write");
abort();
}

return 0;
}


int main(int argc, char**args)
{
int rc;
int len;
struct pcap_pkthdr *pkt;
char buff[1024*1024];

pkt = (struct pcap_pkthdr*)buff;

copy_header(stdin, stdout);

while(1)
{
rc = fread (buff, 1, sizeof(struct pcap_pkthdr), stdin);
if(rc != sizeof(struct pcap_pkthdr))
{
fprintf(stderr,"END OF FILE\n");
break;
}

len = pkt->len;
pkt->caplen += 14;
pkt->len += 14;

rc = fwrite(buff, 1, sizeof(struct pcap_pkthdr), stdout);
if(rc != sizeof(struct pcap_pkthdr))
{
fprintf(stderr, "ERROR write pkt_hdr\n");
abort();
}

rc = fwrite(ETH_DMAC, 1, 6, stdout);
if(rc != 6)
{
fprintf(stderr, "ERROR write DMAC\n");
abort();
}

rc = fwrite(ETH_SMAC, 1, 6, stdout);
if(rc != 6)
{
fprintf(stderr, "ERROR write SMAC\n");
abort();
}

rc = fwrite(ETH_PROTO, 1, 2, stdout);
if(rc != 2)
{
fprintf(stderr, "ERROR write Proto\n");
abort();
}

rc = fread (buff, 1, len, stdin);
if(rc != len)
{
fprintf(stderr, "ERROR fread rc=%d\n", rc);
abort();
}

fwrite(buff, 1, len, stdout);
}
return 0;
}

使用方法:

gcc pcap_ip_to_eth.c
cat ip_p2p.pcap | ./a.out > padding_ETH_MAC.pcap