comparison pcap-study/rtp-stream-dump.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-stream-dump.c@709aa9ad72d1
children d59dbdfe1778
comparison
equal deleted inserted replaced
9:c00510e1ae8b 10:e686bc92c7d8
1 /*
2 * This program is an aid for analyzing arbitrary RTP streams:
3 * it reads a pcap file, extracts packets belonging to a particular
4 * RTP stream as identified by a source or destination IP:port,
5 * and displays a one-line summary of every RTP packet.
6 * Discontinuities are treated as non-fatal errors: an error message
7 * is printed, but analysis continues.
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 int stream_init_flag;
26 static unsigned last_seq, last_tstamp, stream_ssrc;
27
28 static void
29 check_dl_type()
30 {
31 int dltype;
32
33 dltype = pcap_datalink(pcap);
34 switch (dltype) {
35 case DLT_EN10MB:
36 link_hdr_len = 14;
37 ethertype_offset = 12;
38 break;
39 case DLT_RAW:
40 link_hdr_len = 0;
41 break;
42 case DLT_LINUX_SLL:
43 link_hdr_len = 16;
44 ethertype_offset = 14;
45 break;
46 default:
47 fprintf(stderr, "error: unsupported data link type %d\n",
48 dltype);
49 exit(1);
50 }
51 }
52
53 static void
54 rtp_stream_logic(rtp_hdr, pkt_idx)
55 u_char *rtp_hdr;
56 unsigned pkt_idx;
57 {
58 unsigned cur_seq, cur_tstamp, cur_ssrc;
59
60 cur_seq = (rtp_hdr[2] << 8) | rtp_hdr[3];
61 cur_tstamp = (rtp_hdr[4] << 24) | (rtp_hdr[5] << 16) |
62 (rtp_hdr[6] << 8) | rtp_hdr[7];
63 cur_ssrc = (rtp_hdr[8] << 24) | (rtp_hdr[9] << 16) |
64 (rtp_hdr[10] << 8) | rtp_hdr[11];
65 if (stream_init_flag) {
66 if (cur_ssrc != stream_ssrc) {
67 printf(
68 "error in packet #%u: SSRC change from 0x%08X to 0x%08X\n",
69 pkt_idx, stream_ssrc, cur_ssrc);
70 } else if (cur_seq != last_seq + 1 &&
71 (cur_seq != 0 || last_seq != 0xFFFF)) {
72 printf(
73 "error in packet #%u: seq break from 0x%04X to 0x%04X\n",
74 pkt_idx, last_seq, cur_seq);
75 } else if (cur_tstamp != last_tstamp + 160) {
76 printf(
77 "error in packet #%u: timestamp break from 0x%08X to 0x%08X\n",
78 pkt_idx, last_tstamp, cur_tstamp);
79 }
80 } else
81 stream_init_flag = 1;
82 last_seq = cur_seq;
83 last_tstamp = cur_tstamp;
84 stream_ssrc = cur_ssrc;
85 }
86
87 static void
88 process_packet(pkt, caplen, pkt_idx)
89 u_char *pkt;
90 unsigned caplen, pkt_idx;
91 {
92 unsigned udplen, payload_len;
93
94 if (caplen < link_hdr_len + 28)
95 return;
96 if (link_hdr_len) {
97 if (pkt[ethertype_offset] != 0x08)
98 return;
99 if (pkt[ethertype_offset+1] != 0x00)
100 return;
101 pkt += link_hdr_len;
102 caplen -= link_hdr_len;
103 }
104 /* check IP header */
105 if (pkt[0] != 0x45)
106 return;
107 if (pkt[9] != 17) /* UDP */
108 return;
109 if (bcmp(pkt + iphdr_addr_offset, &match_ip_addr, 4))
110 return;
111 /* check UDP header */
112 if (bcmp(pkt + 20 + udphdr_port_offset, &match_udp_port, 2))
113 return;
114 /* it is our target - now scrutinize it */
115 udplen = (pkt[24] << 8) | pkt[25];
116 if (caplen < udplen + 20) {
117 fprintf(stderr,
118 "error: packet #%u is truncated in the capture\n",
119 pkt_idx);
120 exit(1);
121 }
122 if (udplen < 20) {
123 fprintf(stderr,
124 "error in packet #%u: UDP length is too short for RTP header\n",
125 pkt_idx);
126 exit(1);
127 }
128 if (pkt[28] != 0x80) {
129 fprintf(stderr,
130 "error in packet #%u: unsupported RTP header structure\n",
131 pkt_idx);
132 exit(1);
133 }
134 rtp_stream_logic(pkt + 28, pkt_idx);
135 printf("pkt #%u seq 0x%04X ts 0x%08X: pt=%u M=%u len=%u\n", pkt_idx,
136 last_seq, last_tstamp, pkt[29] & 0x7F, pkt[29] >> 7,
137 udplen - 20);
138 }
139
140 main(argc, argv)
141 char **argv;
142 {
143 char errbuf[PCAP_ERRBUF_SIZE];
144 u_char *pkt;
145 struct pcap_pkthdr pkthdr;
146 unsigned pkt_idx;
147
148 if (argc != 5) {
149 fprintf(stderr,
150 "usage: %s pcap-file src|dest ip-addr udp-port\n",
151 argv[0]);
152 exit(1);
153 }
154 pcap = pcap_open_offline(argv[1], errbuf);
155 if (!pcap) {
156 fprintf(stderr, "%s: %s\n", argv[1], errbuf);
157 exit(1);
158 }
159 check_dl_type();
160 if (!strcmp(argv[2], "src")) {
161 iphdr_addr_offset = 12;
162 udphdr_port_offset = 0;
163 } else if (!strcmp(argv[2], "dest")) {
164 iphdr_addr_offset = 16;
165 udphdr_port_offset = 2;
166 } else {
167 fprintf(stderr,
168 "error: direction argument must be \"src\" or \"dest\"\n");
169 exit(1);
170 }
171 match_ip_addr = inet_addr(argv[3]);
172 if (match_ip_addr == INADDR_NONE) {
173 fprintf(stderr, "error: IP address argument is invalid\n");
174 exit(1);
175 }
176 match_udp_port = htons(strtoul(argv[4], 0, 0));
177 for (pkt_idx = 0; ; pkt_idx++) {
178 pkt = pcap_next(pcap, &pkthdr);
179 if (!pkt)
180 break;
181 process_packet(pkt, (unsigned) pkthdr.caplen, pkt_idx);
182 }
183 if (!stream_init_flag) {
184 fprintf(stderr, "error: specified RTP stream not found\n");
185 exit(1);
186 }
187 exit(0);
188 }