2
* This program is free software; you can redistribute it and/or modify
3
* it under the terms of the GNU General Public License as published by
4
* the Free Software Foundation; either version 2 of the License, or
5
* (at your option) any later version.
7
* This program is distributed in the hope that it will be useful,
8
* but WITHOUT ANY WARRANTY; without even the implied warranty of
9
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
* GNU General Public License for more details.
12
* You should have received a copy of the GNU General Public License
13
* along with this program; if not, write to the Free Software
14
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
* Author : Guillaume TEISSIER from FTR&D 02/02/2006
20
#include <netinet/in.h>
21
#include <netinet/udp.h>
22
#if defined(__HPUX) || defined(__CYGWIN)
23
#include <netinet/in_systm.h>
25
#include <netinet/ip.h>
27
#include <netinet/ip6.h>
31
#include "prepare_pcap.h"
34
/* We define our own structures for Ethernet Header and IPv6 Header as they are not available on CYGWIN.
35
* We only need the fields, which are necessary to determine the type of the next header.
36
* we could also define our own structures for UDP and IPv4. We currently use the structures
37
* made available by the platform, as we had no problems to get them on all supported platforms.
40
typedef struct _ether_hdr {
43
u_int16_t ether_type; /* we only need the type, so we can determine, if the next header is IPv4 or IPv6 */
46
typedef struct _ipv6_hdr {
48
u_int8_t nxt_header; /* we only need the next header, so we can determine, if the next header is UDP or not */
54
int check(u_int16_t *buffer, int len){
56
inline int check(u_int16_t *buffer, int len){
62
for (i=0; i<(len&~1); i+= 2)
66
sum += htons( (*(const u_int8_t *)buffer) << 8);
72
u_int16_t checksum_carry(int s) {
74
inline u_int16_t checksum_carry(int s) {
76
int s_c = (s >> 16) + (s & 0xffff);
77
return (~(s_c + (s_c >> 16)) & 0xffff);
80
char errbuf[PCAP_ERRBUF_SIZE];
82
/* prepare a pcap file
84
int prepare_pkts(char *file, pcap_pkts *pkts) {
86
struct pcap_pkthdr *pkthdr = NULL;
87
u_char *pktdata = NULL;
89
u_long max_length = 0;
90
u_int16_t base = 0xffff;
96
struct udphdr *udphdr;
100
pcap = pcap_open_offline(file, errbuf);
102
ERROR_P1("Can't open PCAP file '%s'", file);
104
#if HAVE_PCAP_NEXT_EX
105
while (pcap_next_ex (pcap, &pkthdr, (const u_char **) &pktdata) == 1)
109
pkthdr = (pcap_pkthdr *) malloc (sizeof (*pkthdr));
111
pkthdr = malloc (sizeof (*pkthdr));
114
ERROR("Can't allocate memory for pcap pkthdr");
115
while ((pktdata = (u_char *) pcap_next (pcap, pkthdr)) != NULL)
118
ethhdr = (ether_hdr *)pktdata;
119
if (ntohs(ethhdr->ether_type) != 0x0800 /* IPv4 */
120
&& ntohs(ethhdr->ether_type) != 0x86dd) /* IPv6 */ {
121
fprintf(stderr, "Ignoring non IP{4,6} packet!\n");
124
iphdr = (struct iphdr *)((char *)ethhdr + sizeof(*ethhdr));
125
if (iphdr && iphdr->version == 6) {
127
pktlen = (u_long) pkthdr->len - sizeof(*ethhdr) - sizeof(*ip6hdr);
128
ip6hdr = (ipv6_hdr *)(void *) iphdr;
129
if (ip6hdr->nxt_header != IPPROTO_UDP) {
130
fprintf(stderr, "prepare_pcap.c: Ignoring non UDP packet!\n");
133
udphdr = (struct udphdr *)((char *)ip6hdr + sizeof(*ip6hdr));
136
if (iphdr->protocol != IPPROTO_UDP) {
137
fprintf(stderr, "prepare_pcap.c: Ignoring non UDP packet!\n");
140
#if defined(__DARWIN) || defined(__CYGWIN)
141
udphdr = (struct udphdr *)((char *)iphdr + (iphdr->ihl << 2) + 4);
142
pktlen = (u_long)(ntohs(udphdr->uh_ulen));
143
#elif defined ( __HPUX)
144
udphdr = (struct udphdr *)((char *)iphdr + (iphdr->ihl << 2));
145
pktlen = (u_long) pkthdr->len - sizeof(*ethhdr) - sizeof(*iphdr);
147
udphdr = (struct udphdr *)((char *)iphdr + (iphdr->ihl << 2));
148
pktlen = (u_long)(ntohs(udphdr->len));
151
if (pktlen > PCAP_MAXPACKET) {
152
ERROR("Packet size is too big! Recompile with bigger PCAP_MAXPACKET in prepare_pcap.h");
154
pkts->pkts = (pcap_pkt *) realloc(pkts->pkts, sizeof(*(pkts->pkts)) * (n_pkts + 1));
156
ERROR("Can't re-allocate memory for pcap pkt");
157
pkt_index = pkts->pkts + n_pkts;
158
pkt_index->pktlen = pktlen;
159
pkt_index->ts = pkthdr->ts;
160
pkt_index->data = (unsigned char *) malloc(pktlen);
161
if (!pkt_index->data)
162
ERROR("Can't allocate memory for pcap pkt data");
163
memcpy(pkt_index->data, udphdr, pktlen);
165
#if defined(__HPUX) || defined(__DARWIN) || (defined __CYGWIN)
171
// compute a partial udp checksum
172
// not including port that will be changed
174
#if defined(__HPUX) || defined(__DARWIN) || (defined __CYGWIN)
175
pkt_index->partial_check = check((u_int16_t *) &udphdr->uh_ulen, pktlen - 4) + ntohs(IPPROTO_UDP + pktlen);
177
pkt_index->partial_check = check((u_int16_t *) &udphdr->len, pktlen - 4) + ntohs(IPPROTO_UDP + pktlen);
179
if (max_length < pktlen)
181
#if defined(__HPUX) || defined(__DARWIN) || (defined __CYGWIN)
182
if (base > ntohs(udphdr->uh_dport))
183
base = ntohs(udphdr->uh_dport);
185
if (base > ntohs(udphdr->dest))
186
base = ntohs(udphdr->dest);
190
pkts->max = pkts->pkts + n_pkts;
191
pkts->max_length = max_length;
193
fprintf(stderr, "In pcap %s, npkts %d\nmax pkt length %ld\nbase port %d\n", file, n_pkts, max_length, base);
199
void free_pkts(pcap_pkts *pkts) {
201
while (pkt_index < pkts->max) {
202
free(pkt_index->data);