comparison pcap-study/rtp-gsmfr-extr.c @ 10:e686bc92c7d8

revamp for new subdir structure and configure script
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 15 May 2024 01:44:46 +0000
parents rtp-gsmfr-extr.c@210dfa39f573
children
comparison
equal deleted inserted replaced
9:c00510e1ae8b 10:e686bc92c7d8
1 /*
2 * This program reads a pcap file, extracts packets belonging to a
3 * particular RTP stream as identified by a source or destination
4 * IP:port, verifies that an unbroken RTP stream is present, in
5 * GSM FR or EFR codec, and writes the FR/EFR frame stream to our
6 * extended-libgsm format binary file, to be fed to decoding test
7 * programs.
8 */
9
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <netinet/in.h>
13 #include <arpa/inet.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <strings.h>
18 #include <pcap/pcap.h>
19
20 static pcap_t *pcap;
21 static in_addr_t match_ip_addr;
22 static u_short match_udp_port;
23 static unsigned iphdr_addr_offset, udphdr_port_offset;
24 static unsigned link_hdr_len, ethertype_offset;
25 static FILE *outfile;
26 static int stream_init_flag;
27 static unsigned last_seq, last_tstamp, stream_ssrc;
28
29 static void
30 check_dl_type()
31 {
32 int dltype;
33
34 dltype = pcap_datalink(pcap);
35 switch (dltype) {
36 case DLT_EN10MB:
37 link_hdr_len = 14;
38 ethertype_offset = 12;
39 break;
40 case DLT_RAW:
41 link_hdr_len = 0;
42 break;
43 case DLT_LINUX_SLL:
44 link_hdr_len = 16;
45 ethertype_offset = 14;
46 break;
47 default:
48 fprintf(stderr, "error: unsupported data link type %d\n",
49 dltype);
50 exit(1);
51 }
52 }
53
54 static void
55 rtp_stream_logic(rtp_hdr, pkt_idx)
56 u_char *rtp_hdr;
57 unsigned pkt_idx;
58 {
59 unsigned cur_seq, cur_tstamp, cur_ssrc;
60
61 cur_seq = (rtp_hdr[2] << 8) | rtp_hdr[3];
62 cur_tstamp = (rtp_hdr[4] << 24) | (rtp_hdr[5] << 16) |
63 (rtp_hdr[6] << 8) | rtp_hdr[7];
64 cur_ssrc = (rtp_hdr[8] << 24) | (rtp_hdr[9] << 16) |
65 (rtp_hdr[10] << 8) | rtp_hdr[11];
66 if (stream_init_flag) {
67 if (cur_ssrc != stream_ssrc) {
68 fprintf(stderr,
69 "error in packet #%u: SSRC change from 0x%08X to 0x%08X\n",
70 pkt_idx, stream_ssrc, cur_ssrc);
71 exit(1);
72 }
73 if (cur_seq != last_seq + 1 &&
74 (cur_seq != 0 || last_seq != 0xFFFF)) {
75 fprintf(stderr,
76 "error in packet #%u: seq break from 0x%04X to 0x%04X\n",
77 pkt_idx, last_seq, cur_seq);
78 exit(1);
79 }
80 if (cur_tstamp != last_tstamp + 160) {
81 fprintf(stderr,
82 "error in packet #%u: timestamp break from 0x%08X to 0x%08X\n",
83 pkt_idx, last_tstamp, cur_tstamp);
84 exit(1);
85 }
86 } else {
87 stream_init_flag = 1;
88 stream_ssrc = cur_ssrc;
89 }
90 last_seq = cur_seq;
91 last_tstamp = cur_tstamp;
92 }
93
94 static void
95 process_packet(pkt, caplen, pkt_idx)
96 u_char *pkt;
97 unsigned caplen, pkt_idx;
98 {
99 unsigned udplen, payload_len;
100 u_char synth_bfi[2];
101
102 if (caplen < link_hdr_len + 28)
103 return;
104 if (link_hdr_len) {
105 if (pkt[ethertype_offset] != 0x08)
106 return;
107 if (pkt[ethertype_offset+1] != 0x00)
108 return;
109 pkt += link_hdr_len;
110 caplen -= link_hdr_len;
111 }
112 /* check IP header */
113 if (pkt[0] != 0x45)
114 return;
115 if (pkt[9] != 17) /* UDP */
116 return;
117 if (bcmp(pkt + iphdr_addr_offset, &match_ip_addr, 4))
118 return;
119 /* check UDP header */
120 if (bcmp(pkt + 20 + udphdr_port_offset, &match_udp_port, 2))
121 return;
122 /* it is our target - now scrutinize it */
123 udplen = (pkt[24] << 8) | pkt[25];
124 if (caplen < udplen + 20) {
125 fprintf(stderr,
126 "error: packet #%u is truncated in the capture\n",
127 pkt_idx);
128 exit(1);
129 }
130 if (udplen < 20) {
131 fprintf(stderr,
132 "error in packet #%u: UDP length is too short for RTP header\n",
133 pkt_idx);
134 exit(1);
135 }
136 if (pkt[28] != 0x80) {
137 fprintf(stderr,
138 "error in packet #%u: unsupported RTP header structure\n",
139 pkt_idx);
140 exit(1);
141 }
142 rtp_stream_logic(pkt + 28, pkt_idx);
143 payload_len = udplen - 20;
144 switch (payload_len) {
145 case 0:
146 synth_bfi[0] = 0xBF;
147 synth_bfi[1] = 0;
148 emit_synth_bfi:
149 fwrite(synth_bfi, 1, 2, outfile);
150 return;
151 case 1:
152 if ((pkt[40] & 0xF6) != 0xE6)
153 break;
154 traulike_bfi:
155 synth_bfi[0] = 0xBF;
156 synth_bfi[1] = pkt[40] & 1;
157 goto emit_synth_bfi;
158 case 2:
159 if (pkt[40] != 0xBF)
160 break;
161 emit_payload:
162 fwrite(pkt + 40, 1, payload_len, outfile);
163 return;
164 case 31:
165 if ((pkt[40] & 0xF0) != 0xC0)
166 break;
167 goto emit_payload;
168 case 32:
169 if ((pkt[40] & 0xF4) != 0xE0)
170 break;
171 if ((pkt[41] & 0xF0) != 0xC0)
172 break;
173 if (pkt[40] & 2)
174 goto traulike_bfi;
175 fwrite(pkt + 41, 1, 31, outfile);
176 return;
177 case 33:
178 if ((pkt[40] & 0xF0) != 0xD0)
179 break;
180 goto emit_payload;
181 case 34:
182 if ((pkt[40] & 0xF4) != 0xE0)
183 break;
184 if ((pkt[41] & 0xF0) != 0xD0)
185 break;
186 if (pkt[40] & 2)
187 goto traulike_bfi;
188 fwrite(pkt + 41, 1, 33, outfile);
189 return;
190 }
191 fprintf(stderr, "error in packet #%u: unsupported payload\n", pkt_idx);
192 exit(1);
193 }
194
195 main(argc, argv)
196 char **argv;
197 {
198 char errbuf[PCAP_ERRBUF_SIZE];
199 u_char *pkt;
200 struct pcap_pkthdr pkthdr;
201 unsigned pkt_idx;
202
203 if (argc != 6) {
204 fprintf(stderr,
205 "usage: %s pcap-file src|dest ip-addr udp-port outfile\n",
206 argv[0]);
207 exit(1);
208 }
209 pcap = pcap_open_offline(argv[1], errbuf);
210 if (!pcap) {
211 fprintf(stderr, "%s: %s\n", argv[1], errbuf);
212 exit(1);
213 }
214 check_dl_type();
215 if (!strcmp(argv[2], "src")) {
216 iphdr_addr_offset = 12;
217 udphdr_port_offset = 0;
218 } else if (!strcmp(argv[2], "dest")) {
219 iphdr_addr_offset = 16;
220 udphdr_port_offset = 2;
221 } else {
222 fprintf(stderr,
223 "error: direction argument must be \"src\" or \"dest\"\n");
224 exit(1);
225 }
226 match_ip_addr = inet_addr(argv[3]);
227 if (match_ip_addr == INADDR_NONE) {
228 fprintf(stderr, "error: IP address argument is invalid\n");
229 exit(1);
230 }
231 match_udp_port = htons(strtoul(argv[4], 0, 0));
232 outfile = fopen(argv[5], "w");
233 if (!outfile) {
234 perror(argv[5]);
235 exit(1);
236 }
237 for (pkt_idx = 0; ; pkt_idx++) {
238 pkt = pcap_next(pcap, &pkthdr);
239 if (!pkt)
240 break;
241 process_packet(pkt, (unsigned) pkthdr.caplen, pkt_idx);
242 }
243 if (!stream_init_flag) {
244 fprintf(stderr, "error: specified RTP stream not found\n");
245 exit(1);
246 }
247 fclose(outfile);
248 exit(0);
249 }