Browse code

sipdump: write udp pcap with sip messages if mode param flag 4 is set

- udp is always used for packets writen in pcap no matter the transport
layer used for sip messages

Daniel-Constantin Mierla authored on 15/07/2020 07:26:49
Showing 2 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,187 @@
1
+/**
2
+ * Copyright (C) 2020 Daniel-Constantin Mierla (asipto.com)
3
+ *
4
+ * This file is part of Kamailio, a free SIP server.
5
+ *
6
+ * This file is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation; either version 2 of the License, or
9
+ * (at your option) any later version
10
+ *
11
+ *
12
+ * This file is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program; if not, write to the Free Software
19
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20
+ *
21
+ */
22
+
23
+#include "../../core/ip_addr.h"
24
+#include "../../core/resolve.h"
25
+
26
+#include "sipdump_write.h"
27
+
28
+/* structures related to PCAP headers imported from open source Asterisk project
29
+ * fuction to write to PCAP file adapted for internal structures
30
+ * source: res_pjsip_logger.c - License GPLv2 -  Copyright (C) Digium, Inc.*/
31
+
32
+/* PCAP Header */
33
+struct pcap_header {
34
+	uint32_t magic_number; 	/* PCAP file format magic number */
35
+	uint16_t version_major;	/* Major version number of the file format */
36
+	uint16_t version_minor;	/* Minor version number of the file format */
37
+	int32_t thiszone;	/* GMT to local correction */
38
+	uint32_t sigfigs;	/* Accuracy of timestamps */
39
+	uint32_t snaplen;	/* The maximum size that can be recorded in the file */
40
+	uint32_t network;	/* Type of packets held within the file */
41
+};
42
+
43
+/* PCAP Packet Record Header */
44
+struct pcap_record_header {
45
+	uint32_t ts_sec;	/* When the record was created */
46
+	uint32_t ts_usec;	/* When the record was created */
47
+	uint32_t incl_len;	/* Length of packet as saved in the file */
48
+	uint32_t orig_len;	/* Length of packet as sent over network */
49
+};
50
+
51
+/* PCAP Ethernet Header */
52
+struct pcap_ethernet_header {
53
+	uint8_t dst[6];	/* Destination MAC address */
54
+	uint8_t src[6];	/* Source MAC address */
55
+	uint16_t type;	/*!The type of packet contained within */
56
+} __attribute__((__packed__));
57
+
58
+/*! PCAP IPv4 Header */
59
+struct pcap_ipv4_header {
60
+	uint8_t ver_ihl;	/* IP header version and other bits */
61
+	uint8_t ip_tos;		/*  Type of service details */
62
+	uint16_t ip_len;	/* Total length of the packet (including IPv4 header) */
63
+	uint16_t ip_id;		/* Identification value */
64
+	uint16_t ip_off;	/* Fragment offset */
65
+	uint8_t ip_ttl;		/* Time to live for the packet */
66
+	uint8_t ip_protocol;	/* Protocol of the data held within the packet (always UDP) */
67
+	uint16_t ip_sum;	/* Checksum (not calculated for our purposes */
68
+	uint32_t ip_src;	/* Source IP address */
69
+	uint32_t ip_dst;	/* Destination IP address */
70
+};
71
+
72
+/* PCAP IPv6 Header */
73
+struct pcap_ipv6_header {
74
+   union {
75
+      struct ip6_hdrctl {
76
+         uint32_t ip6_un1_flow; /* Version, traffic class, flow label */
77
+         uint16_t ip6_un1_plen; /* Length of the packet (not including IPv6 header) */
78
+         uint8_t ip6_un1_nxt; 	/* Next header field */
79
+         uint8_t ip6_un1_hlim;	/* Hop Limit */
80
+      } ip6_un1;
81
+      uint8_t ip6_un2_vfc;	/* Version, traffic class */
82
+   } ip6_ctlun;
83
+   struct in6_addr ip6_src; /* Source IP address */
84
+   struct in6_addr ip6_dst; /* Destination IP address */
85
+};
86
+
87
+/* PCAP UDP Header */
88
+struct pcap_udp_header {
89
+	uint16_t src;		/* Source IP port */
90
+	uint16_t dst;		/* Destination IP port */
91
+	uint16_t length;	/* Length of the UDP header plus UDP packet */
92
+	uint16_t checksum;	/* Packet checksum, left uncalculated for our purposes */
93
+};
94
+
95
+void sipdump_init_pcap(FILE *fs)
96
+{
97
+	struct pcap_header v_pcap_header = {
98
+		.magic_number = 0xa1b2c3d4,
99
+		.version_major = 2,
100
+		.version_minor = 4,
101
+		.snaplen = 65535,
102
+		.network = 1, /* use ethernet to combine IPv4 and IPv6 in same pcap */
103
+	};
104
+
105
+	LM_DBG("writing the pcap file header\n");
106
+	if(fwrite(&v_pcap_header, sizeof(struct pcap_header), 1, fs) != 1) {
107
+		LM_ERR("failed to write the pcap file header\n");
108
+	}
109
+}
110
+
111
+void sipdump_write_pcap(FILE *fs, sipdump_data_t *spd)
112
+{
113
+	struct pcap_record_header v_pcap_record_header = {
114
+		.ts_sec = spd->tv.tv_sec,
115
+		.ts_usec = spd->tv.tv_usec,
116
+	};
117
+	struct pcap_ethernet_header v_pcap_ethernet_header = {
118
+		.type = 0,
119
+	};
120
+	struct pcap_ipv4_header v_pcap_ipv4_header = {
121
+		.ver_ihl = 0x45, /* IPv4 + 20 bytes of header */
122
+		.ip_ttl = 128, /* We always put a TTL of 128 to keep Wireshark less blue */
123
+	};
124
+	struct pcap_ipv6_header v_pcap_ipv6_header = {
125
+		.ip6_ctlun.ip6_un2_vfc = 0x60,
126
+	};
127
+	void *pcap_ip_header;
128
+	size_t pcap_ip_header_len;
129
+	struct pcap_udp_header v_pcap_udp_header;
130
+	ip_addr_t src_ip;
131
+	ip_addr_t dst_ip;
132
+
133
+	if(fs == NULL || spd == NULL) {
134
+		return;
135
+	}
136
+
137
+	/* always store UDP */
138
+	v_pcap_udp_header.src = ntohs(spd->src_port);
139
+	v_pcap_udp_header.dst = ntohs(spd->dst_port);
140
+	v_pcap_udp_header.length = ntohs(sizeof(struct pcap_udp_header) + spd->data.len);
141
+
142
+	/* IP header */
143
+	if (spd->afid == AF_INET6) {
144
+		v_pcap_ethernet_header.type = htons(0x86DD); /* IPv6 packet */
145
+		pcap_ip_header = &v_pcap_ipv6_header;
146
+		pcap_ip_header_len = sizeof(struct pcap_ipv6_header);
147
+		str2ip6buf(&spd->src_ip, &src_ip);
148
+		memcpy(&v_pcap_ipv6_header.ip6_src, src_ip.u.addr16, src_ip.len);
149
+		str2ip6buf(&spd->dst_ip, &dst_ip);
150
+		memcpy(&v_pcap_ipv6_header.ip6_dst, dst_ip.u.addr16, dst_ip.len);
151
+		v_pcap_ipv6_header.ip6_ctlun.ip6_un1.ip6_un1_plen = htons(sizeof(struct pcap_udp_header)
152
+					+ spd->data.len);
153
+		v_pcap_ipv6_header.ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_UDP;
154
+	} else {
155
+		v_pcap_ethernet_header.type = htons(0x0800); /* IPv4 packet */
156
+		pcap_ip_header = &v_pcap_ipv4_header;
157
+		pcap_ip_header_len = sizeof(struct pcap_ipv4_header);
158
+		str2ipbuf(&spd->src_ip, &src_ip);
159
+		memcpy(&v_pcap_ipv6_header.ip6_src, src_ip.u.addr, src_ip.len);
160
+		str2ipbuf(&spd->dst_ip, &dst_ip);
161
+		memcpy(&v_pcap_ipv6_header.ip6_dst, dst_ip.u.addr, dst_ip.len);
162
+		v_pcap_ipv4_header.ip_len = htons(sizeof(struct pcap_udp_header)
163
+					+ sizeof(struct pcap_ipv4_header) + spd->data.len);
164
+		v_pcap_ipv4_header.ip_protocol = IPPROTO_UDP; /* UDP */
165
+	}
166
+
167
+	/* add up all the sizes for this record */
168
+	v_pcap_record_header.orig_len = sizeof(struct pcap_ethernet_header) + pcap_ip_header_len
169
+			+ sizeof(struct pcap_udp_header) + spd->data.len;
170
+	v_pcap_record_header.incl_len = v_pcap_record_header.orig_len;
171
+
172
+	if (fwrite(&v_pcap_record_header, sizeof(struct pcap_record_header), 1, fs) != 1) {
173
+		LM_ERR("writing PCAP header failed: %s\n", strerror(errno));
174
+	}
175
+	if (fwrite(&v_pcap_ethernet_header, sizeof(struct pcap_ethernet_header), 1, fs) != 1) {
176
+		LM_ERR("writing ethernet header to pcap failed: %s\n", strerror(errno));
177
+	}
178
+	if (fwrite(pcap_ip_header, pcap_ip_header_len, 1, fs) != 1) {
179
+		LM_ERR("writing IP header to pcap failed: %s\n", strerror(errno));
180
+	}
181
+	if (fwrite(&v_pcap_udp_header, sizeof(struct pcap_udp_header), 1, fs) != 1) {
182
+		LM_ERR("writing UDP header to pcap failed: %s\n", strerror(errno));
183
+	}
184
+	if (fwrite(spd->data.s, spd->data.len, 1, fs) != 1) {
185
+		LM_ERR("writing UDP payload to pcap failed: %s\n", strerror(errno));
186
+	}
187
+}
0 188
\ No newline at end of file
... ...
@@ -187,10 +187,10 @@ static int sipdump_write_meta(char *fpath)
187 187
 	mpath[len-2] = 't';
188 188
 	mpath[len-1] = 'a';
189 189
 
190
-	LM_DBG("writing meta to file: %s\n", mpath);
190
+	LM_DBG("writing meta to file: %s (%d)\n", mpath, len);
191 191
 	mfile = fopen( mpath , "w" );
192 192
 	if(mfile==NULL) {
193
-		LM_ERR("failed to open meta file %s\n", mpath);
193
+		LM_ERR("failed to open meta file %s (%d)\n", mpath, len);
194 194
 		return -1;
195 195
 	}
196 196
 	localtime_r(&up_since, &ti);
... ...
@@ -270,6 +270,7 @@ static int sipdump_rotate_file(void)
270 270
 			LM_ERR("failed to open file %s\n", _sipdump_fpath);
271 271
 			return -1;
272 272
 		}
273
+		sipdump_init_pcap(_sipdump_pcap_file);
273 274
 	}
274 275
 
275 276
 	sipdump_write_meta(_sipdump_fpath);
... ...
@@ -393,7 +394,7 @@ void sipdump_timer_exec(unsigned int ticks, void *param)
393 394
 			sipdump_data_print(sdd, &odata);
394 395
 			/* LM_NOTICE("writing: [[%.*s]] (%d)\n", odata.len,
395 396
 					odata.s, odata.len); */
396
-			fwrite(odata.s, 1, odata.len, _sipdump_text_file);
397
+			fwrite(odata.s, odata.len, 1, _sipdump_text_file);
397 398
 		}
398 399
 		if(sipdump_mode & SIPDUMP_MODE_WPCAP) {
399 400
 			if(_sipdump_pcap_file==NULL) {