Browse code

sipdump: move use of spd fields after safety check

Daniel-Constantin Mierla authored on 08/09/2020 10:52:53
Showing 1 changed files
... ...
@@ -125,8 +125,8 @@ void sipdump_write_pcap(FILE *fs, sipdump_data_t *spd)
125 125
 	char *p = NULL;
126 126
 
127 127
 	struct pcap_record_header v_pcap_record_header = {
128
-		.ts_sec = spd->tv.tv_sec,
129
-		.ts_usec = spd->tv.tv_usec,
128
+		.ts_sec = 0,
129
+		.ts_usec = 0,
130 130
 	};
131 131
 	struct pcap_ethernet_header v_pcap_ethernet_header = {
132 132
 		.type = 0,
... ...
@@ -148,6 +148,9 @@ void sipdump_write_pcap(FILE *fs, sipdump_data_t *spd)
148 148
 		return;
149 149
 	}
150 150
 
151
+	v_pcap_record_header.ts_sec = spd->tv.tv_sec;
152
+	v_pcap_record_header.ts_usec = spd->tv.tv_usec;
153
+
151 154
 	data = spd->data;
152 155
 	if((sipdump_mode & SIPDUMP_MODE_WPCAPEX) && (spd->data.len < BUF_SIZE - 256)) {
153 156
 		if(_sipdump_pcap_data_buf == NULL) {
Browse code

sipdump: init checksum filed

- silent analyzer

Daniel-Constantin Mierla authored on 08/09/2020 10:48:15
Showing 1 changed files
... ...
@@ -182,6 +182,7 @@ void sipdump_write_pcap(FILE *fs, sipdump_data_t *spd)
182 182
 	v_pcap_udp_header.src = ntohs(spd->src_port);
183 183
 	v_pcap_udp_header.dst = ntohs(spd->dst_port);
184 184
 	v_pcap_udp_header.length = ntohs(sizeof(struct pcap_udp_header) + data.len);
185
+	v_pcap_udp_header.checksum = 0;
185 186
 
186 187
 	/* IP header */
187 188
 	if (spd->afid == AF_INET6) {
... ...
@@ -243,4 +244,4 @@ void sipdump_write_pcap(FILE *fs, sipdump_data_t *spd)
243 244
 		LM_ERR("writing UDP payload to pcap failed: %s\n", strerror(errno));
244 245
 	}
245 246
 	fflush(fs);
246
-}
247 247
\ No newline at end of file
248
+}
Browse code

sipdump: insert P-KSR-SIPDump header if SIPDUMP_MODE_WPCAPEX flag is set

- inserted header contains sip message specific meta data (transport,
pid, proc no)

Daniel-Constantin Mierla authored on 16/07/2020 12:00:09
Showing 1 changed files
... ...
@@ -28,6 +28,8 @@
28 28
 
29 29
 #include "sipdump_write.h"
30 30
 
31
+extern int sipdump_mode;
32
+
31 33
 /* structures related to PCAP headers imported from open source Asterisk project
32 34
  * fuction to write to PCAP file adapted for internal structures
33 35
  * source: res_pjsip_logger.c - License GPLv2 -  Copyright (C) Digium, Inc.*/
... ...
@@ -113,8 +115,15 @@ void sipdump_init_pcap(FILE *fs)
113 115
 	}
114 116
 }
115 117
 
118
+static char *_sipdump_pcap_data_buf = NULL;
119
+
116 120
 void sipdump_write_pcap(FILE *fs, sipdump_data_t *spd)
117 121
 {
122
+	str data = str_init("");
123
+	str mval = str_init("");
124
+	str sproto = str_init("none");
125
+	char *p = NULL;
126
+
118 127
 	struct pcap_record_header v_pcap_record_header = {
119 128
 		.ts_sec = spd->tv.tv_sec,
120 129
 		.ts_usec = spd->tv.tv_usec,
... ...
@@ -139,10 +148,40 @@ void sipdump_write_pcap(FILE *fs, sipdump_data_t *spd)
139 148
 		return;
140 149
 	}
141 150
 
151
+	data = spd->data;
152
+	if((sipdump_mode & SIPDUMP_MODE_WPCAPEX) && (spd->data.len < BUF_SIZE - 256)) {
153
+		if(_sipdump_pcap_data_buf == NULL) {
154
+			_sipdump_pcap_data_buf = (char*)malloc(BUF_SIZE);
155
+		}
156
+		if(_sipdump_pcap_data_buf != NULL) {
157
+			data.s = _sipdump_pcap_data_buf;
158
+			data.len = 0;
159
+			mval.s = q_memchr(spd->data.s, '\n', spd->data.len);
160
+			p = data.s;
161
+			if(mval.s != NULL) {
162
+				data.len = mval.s - spd->data.s + 1;
163
+				memcpy(p, spd->data.s, data.len);
164
+				p += data.len;
165
+				get_valid_proto_string(spd->protoid, 0, 0, &sproto);
166
+				mval.len = snprintf(p, BUF_SIZE - (data.len + 1),
167
+						"P-KSR-SIPDump: %.*s pid=%d pno=%d\r\n",
168
+						sproto.len, sproto.s, spd->pid, spd->procno);
169
+				if(mval.len < 0 || mval.len >= BUF_SIZE - (data.len + 1)) {
170
+					data = spd->data;
171
+				} else {
172
+					data.len += mval.len;
173
+					p += mval.len;
174
+					mval.s += 1;
175
+					memcpy(p, mval.s, spd->data.s + spd->data.len - mval.s);
176
+					data.len += spd->data.s + spd->data.len - mval.s;
177
+				}
178
+			}
179
+		}
180
+	}
142 181
 	/* always store UDP */
143 182
 	v_pcap_udp_header.src = ntohs(spd->src_port);
144 183
 	v_pcap_udp_header.dst = ntohs(spd->dst_port);
145
-	v_pcap_udp_header.length = ntohs(sizeof(struct pcap_udp_header) + spd->data.len);
184
+	v_pcap_udp_header.length = ntohs(sizeof(struct pcap_udp_header) + data.len);
146 185
 
147 186
 	/* IP header */
148 187
 	if (spd->afid == AF_INET6) {
... ...
@@ -161,7 +200,7 @@ void sipdump_write_pcap(FILE *fs, sipdump_data_t *spd)
161 200
 		}
162 201
 		memcpy(&v_pcap_ipv6_header.ip6_dst, &ip6addr, sizeof(struct in6_addr));
163 202
 		v_pcap_ipv6_header.ip6_ctlun.ip6_un1.ip6_un1_plen = htons(sizeof(struct pcap_udp_header)
164
-					+ spd->data.len);
203
+					+ data.len);
165 204
 		v_pcap_ipv6_header.ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_UDP;
166 205
 	} else {
167 206
 		LM_DBG("ipv4 = %s -> %s\n", spd->src_ip.s, spd->dst_ip.s);
... ...
@@ -179,13 +218,13 @@ void sipdump_write_pcap(FILE *fs, sipdump_data_t *spd)
179 218
 		}
180 219
 		memcpy(&v_pcap_ipv4_header.ip_dst, &ip4addr, sizeof(uint32_t));
181 220
 		v_pcap_ipv4_header.ip_len = htons(sizeof(struct pcap_udp_header)
182
-					+ sizeof(struct pcap_ipv4_header) + spd->data.len);
221
+					+ sizeof(struct pcap_ipv4_header) + data.len);
183 222
 		v_pcap_ipv4_header.ip_protocol = IPPROTO_UDP; /* UDP */
184 223
 	}
185 224
 
186 225
 	/* add up all the sizes for this record */
187 226
 	v_pcap_record_header.orig_len = sizeof(struct pcap_ethernet_header) + pcap_ip_header_len
188
-			+ sizeof(struct pcap_udp_header) + spd->data.len;
227
+			+ sizeof(struct pcap_udp_header) + data.len;
189 228
 	v_pcap_record_header.incl_len = v_pcap_record_header.orig_len;
190 229
 
191 230
 	if (fwrite(&v_pcap_record_header, sizeof(struct pcap_record_header), 1, fs) != 1) {
... ...
@@ -200,7 +239,7 @@ void sipdump_write_pcap(FILE *fs, sipdump_data_t *spd)
200 239
 	if (fwrite(&v_pcap_udp_header, sizeof(struct pcap_udp_header), 1, fs) != 1) {
201 240
 		LM_ERR("writing UDP header to pcap failed: %s\n", strerror(errno));
202 241
 	}
203
-	if (fwrite(spd->data.s, spd->data.len, 1, fs) != 1) {
242
+	if (fwrite(data.s, data.len, 1, fs) != 1) {
204 243
 		LM_ERR("writing UDP payload to pcap failed: %s\n", strerror(errno));
205 244
 	}
206 245
 	fflush(fs);
Browse code

sipdump: use fflush() to get data stored more realtime

- use inet_pton() for generating the data for pcap file

Daniel-Constantin Mierla authored on 15/07/2020 09:22:09
Showing 1 changed files
... ...
@@ -20,6 +20,9 @@
20 20
  *
21 21
  */
22 22
 
23
+#include <stdio.h>
24
+#include <arpa/inet.h>
25
+
23 26
 #include "../../core/ip_addr.h"
24 27
 #include "../../core/resolve.h"
25 28
 
... ...
@@ -105,6 +108,8 @@ void sipdump_init_pcap(FILE *fs)
105 108
 	LM_DBG("writing the pcap file header\n");
106 109
 	if(fwrite(&v_pcap_header, sizeof(struct pcap_header), 1, fs) != 1) {
107 110
 		LM_ERR("failed to write the pcap file header\n");
111
+	} else {
112
+		fflush(fs);
108 113
 	}
109 114
 }
110 115
 
... ...
@@ -119,7 +124,7 @@ void sipdump_write_pcap(FILE *fs, sipdump_data_t *spd)
119 124
 	};
120 125
 	struct pcap_ipv4_header v_pcap_ipv4_header = {
121 126
 		.ver_ihl = 0x45, /* IPv4 + 20 bytes of header */
122
-		.ip_ttl = 128, /* We always put a TTL of 128 to keep Wireshark less blue */
127
+		.ip_ttl = 128, /* put a TTL of 128 to keep Wireshark less blue */
123 128
 	};
124 129
 	struct pcap_ipv6_header v_pcap_ipv6_header = {
125 130
 		.ip6_ctlun.ip6_un2_vfc = 0x60,
... ...
@@ -127,8 +132,8 @@ void sipdump_write_pcap(FILE *fs, sipdump_data_t *spd)
127 132
 	void *pcap_ip_header;
128 133
 	size_t pcap_ip_header_len;
129 134
 	struct pcap_udp_header v_pcap_udp_header;
130
-	ip_addr_t src_ip;
131
-	ip_addr_t dst_ip;
135
+	struct in_addr ip4addr;
136
+	struct in6_addr ip6addr;
132 137
 
133 138
 	if(fs == NULL || spd == NULL) {
134 139
 		return;
... ...
@@ -141,24 +146,38 @@ void sipdump_write_pcap(FILE *fs, sipdump_data_t *spd)
141 146
 
142 147
 	/* IP header */
143 148
 	if (spd->afid == AF_INET6) {
149
+		LM_DBG("ipv6 = %s -> %s\n", spd->src_ip.s, spd->dst_ip.s);
144 150
 		v_pcap_ethernet_header.type = htons(0x86DD); /* IPv6 packet */
145 151
 		pcap_ip_header = &v_pcap_ipv6_header;
146 152
 		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);
153
+		if (inet_pton(AF_INET6, spd->src_ip.s, &ip6addr) != 1) {
154
+			LM_ERR("failed to parse IPv6 address %s\n", spd->src_ip.s);
155
+			return;
156
+		}
157
+		memcpy(&v_pcap_ipv6_header.ip6_src, &ip6addr, sizeof(struct in6_addr));
158
+		if (inet_pton(AF_INET, spd->dst_ip.s, &ip6addr) != 1) {
159
+			LM_ERR("failed to parse IPv4 address %s\n", spd->dst_ip.s);
160
+			return;
161
+		}
162
+		memcpy(&v_pcap_ipv6_header.ip6_dst, &ip6addr, sizeof(struct in6_addr));
151 163
 		v_pcap_ipv6_header.ip6_ctlun.ip6_un1.ip6_un1_plen = htons(sizeof(struct pcap_udp_header)
152 164
 					+ spd->data.len);
153 165
 		v_pcap_ipv6_header.ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_UDP;
154 166
 	} else {
167
+		LM_DBG("ipv4 = %s -> %s\n", spd->src_ip.s, spd->dst_ip.s);
155 168
 		v_pcap_ethernet_header.type = htons(0x0800); /* IPv4 packet */
156 169
 		pcap_ip_header = &v_pcap_ipv4_header;
157 170
 		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);
171
+		if (inet_pton(AF_INET, spd->src_ip.s, &ip4addr) != 1) {
172
+			LM_ERR("failed to parse IPv4 address %s\n", spd->src_ip.s);
173
+			return;
174
+		}
175
+		memcpy(&v_pcap_ipv4_header.ip_src, &ip4addr, sizeof(uint32_t));
176
+		if (inet_pton(AF_INET, spd->dst_ip.s, &ip4addr) != 1) {
177
+			LM_ERR("failed to parse IPv4 address %s\n", spd->dst_ip.s);
178
+			return;
179
+		}
180
+		memcpy(&v_pcap_ipv4_header.ip_dst, &ip4addr, sizeof(uint32_t));
162 181
 		v_pcap_ipv4_header.ip_len = htons(sizeof(struct pcap_udp_header)
163 182
 					+ sizeof(struct pcap_ipv4_header) + spd->data.len);
164 183
 		v_pcap_ipv4_header.ip_protocol = IPPROTO_UDP; /* UDP */
... ...
@@ -184,4 +203,5 @@ void sipdump_write_pcap(FILE *fs, sipdump_data_t *spd)
184 203
 	if (fwrite(spd->data.s, spd->data.len, 1, fs) != 1) {
185 204
 		LM_ERR("writing UDP payload to pcap failed: %s\n", strerror(errno));
186 205
 	}
206
+	fflush(fs);
187 207
 }
188 208
\ No newline at end of file
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 1 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