1*90e502c7SAndroid Build Coastguard Worker /*
2*90e502c7SAndroid Build Coastguard Worker * rtpw.c
3*90e502c7SAndroid Build Coastguard Worker *
4*90e502c7SAndroid Build Coastguard Worker * rtp word sender/receiver
5*90e502c7SAndroid Build Coastguard Worker *
6*90e502c7SAndroid Build Coastguard Worker * David A. McGrew
7*90e502c7SAndroid Build Coastguard Worker * Cisco Systems, Inc.
8*90e502c7SAndroid Build Coastguard Worker *
9*90e502c7SAndroid Build Coastguard Worker * This app is a simple RTP application intended only for testing
10*90e502c7SAndroid Build Coastguard Worker * libsrtp. It reads one word at a time from words.txt (or
11*90e502c7SAndroid Build Coastguard Worker * whatever file is specified as DICT_FILE or with -w), and sends one word out
12*90e502c7SAndroid Build Coastguard Worker * each USEC_RATE microseconds. Secure RTP protections can be
13*90e502c7SAndroid Build Coastguard Worker * applied. See the usage() function for more details.
14*90e502c7SAndroid Build Coastguard Worker *
15*90e502c7SAndroid Build Coastguard Worker */
16*90e502c7SAndroid Build Coastguard Worker
17*90e502c7SAndroid Build Coastguard Worker /*
18*90e502c7SAndroid Build Coastguard Worker *
19*90e502c7SAndroid Build Coastguard Worker * Copyright (c) 2001-2017, Cisco Systems, Inc.
20*90e502c7SAndroid Build Coastguard Worker * All rights reserved.
21*90e502c7SAndroid Build Coastguard Worker *
22*90e502c7SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
23*90e502c7SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions
24*90e502c7SAndroid Build Coastguard Worker * are met:
25*90e502c7SAndroid Build Coastguard Worker *
26*90e502c7SAndroid Build Coastguard Worker * Redistributions of source code must retain the above copyright
27*90e502c7SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
28*90e502c7SAndroid Build Coastguard Worker *
29*90e502c7SAndroid Build Coastguard Worker * Redistributions in binary form must reproduce the above
30*90e502c7SAndroid Build Coastguard Worker * copyright notice, this list of conditions and the following
31*90e502c7SAndroid Build Coastguard Worker * disclaimer in the documentation and/or other materials provided
32*90e502c7SAndroid Build Coastguard Worker * with the distribution.
33*90e502c7SAndroid Build Coastguard Worker *
34*90e502c7SAndroid Build Coastguard Worker * Neither the name of the Cisco Systems, Inc. nor the names of its
35*90e502c7SAndroid Build Coastguard Worker * contributors may be used to endorse or promote products derived
36*90e502c7SAndroid Build Coastguard Worker * from this software without specific prior written permission.
37*90e502c7SAndroid Build Coastguard Worker *
38*90e502c7SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
39*90e502c7SAndroid Build Coastguard Worker * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
40*90e502c7SAndroid Build Coastguard Worker * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
41*90e502c7SAndroid Build Coastguard Worker * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
42*90e502c7SAndroid Build Coastguard Worker * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
43*90e502c7SAndroid Build Coastguard Worker * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
44*90e502c7SAndroid Build Coastguard Worker * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
45*90e502c7SAndroid Build Coastguard Worker * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46*90e502c7SAndroid Build Coastguard Worker * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47*90e502c7SAndroid Build Coastguard Worker * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48*90e502c7SAndroid Build Coastguard Worker * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49*90e502c7SAndroid Build Coastguard Worker * OF THE POSSIBILITY OF SUCH DAMAGE.
50*90e502c7SAndroid Build Coastguard Worker *
51*90e502c7SAndroid Build Coastguard Worker */
52*90e502c7SAndroid Build Coastguard Worker
53*90e502c7SAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
54*90e502c7SAndroid Build Coastguard Worker #include <config.h>
55*90e502c7SAndroid Build Coastguard Worker #endif
56*90e502c7SAndroid Build Coastguard Worker
57*90e502c7SAndroid Build Coastguard Worker #include "getopt_s.h" /* for local getopt() */
58*90e502c7SAndroid Build Coastguard Worker
59*90e502c7SAndroid Build Coastguard Worker #include <stdio.h> /* for printf, fprintf */
60*90e502c7SAndroid Build Coastguard Worker #include <stdlib.h> /* for atoi() */
61*90e502c7SAndroid Build Coastguard Worker #include <errno.h>
62*90e502c7SAndroid Build Coastguard Worker #include <signal.h> /* for signal() */
63*90e502c7SAndroid Build Coastguard Worker
64*90e502c7SAndroid Build Coastguard Worker #include <string.h> /* for strncpy() */
65*90e502c7SAndroid Build Coastguard Worker #include <time.h> /* for usleep() */
66*90e502c7SAndroid Build Coastguard Worker
67*90e502c7SAndroid Build Coastguard Worker #ifdef HAVE_UNISTD_H
68*90e502c7SAndroid Build Coastguard Worker #include <unistd.h> /* for close() */
69*90e502c7SAndroid Build Coastguard Worker #elif defined(_MSC_VER)
70*90e502c7SAndroid Build Coastguard Worker #include <io.h> /* for _close() */
71*90e502c7SAndroid Build Coastguard Worker #define close _close
72*90e502c7SAndroid Build Coastguard Worker #endif
73*90e502c7SAndroid Build Coastguard Worker #ifdef HAVE_SYS_SOCKET_H
74*90e502c7SAndroid Build Coastguard Worker #include <sys/socket.h>
75*90e502c7SAndroid Build Coastguard Worker #endif
76*90e502c7SAndroid Build Coastguard Worker #ifdef HAVE_NETINET_IN_H
77*90e502c7SAndroid Build Coastguard Worker #include <netinet/in.h>
78*90e502c7SAndroid Build Coastguard Worker #elif defined HAVE_WINSOCK2_H
79*90e502c7SAndroid Build Coastguard Worker #include <winsock2.h>
80*90e502c7SAndroid Build Coastguard Worker #include <ws2tcpip.h>
81*90e502c7SAndroid Build Coastguard Worker #define RTPW_USE_WINSOCK2 1
82*90e502c7SAndroid Build Coastguard Worker #endif
83*90e502c7SAndroid Build Coastguard Worker #ifdef HAVE_ARPA_INET_H
84*90e502c7SAndroid Build Coastguard Worker #include <arpa/inet.h>
85*90e502c7SAndroid Build Coastguard Worker #endif
86*90e502c7SAndroid Build Coastguard Worker
87*90e502c7SAndroid Build Coastguard Worker #include "srtp.h"
88*90e502c7SAndroid Build Coastguard Worker #include "rtp.h"
89*90e502c7SAndroid Build Coastguard Worker #include "util.h"
90*90e502c7SAndroid Build Coastguard Worker
91*90e502c7SAndroid Build Coastguard Worker #define DICT_FILE "words.txt"
92*90e502c7SAndroid Build Coastguard Worker #define USEC_RATE (5e5)
93*90e502c7SAndroid Build Coastguard Worker #define MAX_WORD_LEN 128
94*90e502c7SAndroid Build Coastguard Worker #define ADDR_IS_MULTICAST(a) IN_MULTICAST(htonl(a))
95*90e502c7SAndroid Build Coastguard Worker #define MAX_KEY_LEN 96
96*90e502c7SAndroid Build Coastguard Worker
97*90e502c7SAndroid Build Coastguard Worker #ifndef HAVE_USLEEP
98*90e502c7SAndroid Build Coastguard Worker #ifdef HAVE_WINDOWS_H
99*90e502c7SAndroid Build Coastguard Worker #define usleep(us) Sleep((us) / 1000)
100*90e502c7SAndroid Build Coastguard Worker #else
101*90e502c7SAndroid Build Coastguard Worker #define usleep(us) sleep((us) / 1000000)
102*90e502c7SAndroid Build Coastguard Worker #endif
103*90e502c7SAndroid Build Coastguard Worker #endif
104*90e502c7SAndroid Build Coastguard Worker
105*90e502c7SAndroid Build Coastguard Worker /*
106*90e502c7SAndroid Build Coastguard Worker * the function usage() prints an error message describing how this
107*90e502c7SAndroid Build Coastguard Worker * program should be called, then calls exit()
108*90e502c7SAndroid Build Coastguard Worker */
109*90e502c7SAndroid Build Coastguard Worker
110*90e502c7SAndroid Build Coastguard Worker void usage(char *prog_name);
111*90e502c7SAndroid Build Coastguard Worker
112*90e502c7SAndroid Build Coastguard Worker /*
113*90e502c7SAndroid Build Coastguard Worker * leave_group(...) de-registers from a multicast group
114*90e502c7SAndroid Build Coastguard Worker */
115*90e502c7SAndroid Build Coastguard Worker
116*90e502c7SAndroid Build Coastguard Worker void leave_group(int sock, struct ip_mreq mreq, char *name);
117*90e502c7SAndroid Build Coastguard Worker
118*90e502c7SAndroid Build Coastguard Worker /*
119*90e502c7SAndroid Build Coastguard Worker * setup_signal_handler() sets up a signal handler to trigger
120*90e502c7SAndroid Build Coastguard Worker * cleanups after an interrupt
121*90e502c7SAndroid Build Coastguard Worker */
122*90e502c7SAndroid Build Coastguard Worker int setup_signal_handler(char *name);
123*90e502c7SAndroid Build Coastguard Worker
124*90e502c7SAndroid Build Coastguard Worker /*
125*90e502c7SAndroid Build Coastguard Worker * handle_signal(...) handles interrupt signal to trigger cleanups
126*90e502c7SAndroid Build Coastguard Worker */
127*90e502c7SAndroid Build Coastguard Worker
128*90e502c7SAndroid Build Coastguard Worker volatile int interrupted = 0;
129*90e502c7SAndroid Build Coastguard Worker
130*90e502c7SAndroid Build Coastguard Worker /*
131*90e502c7SAndroid Build Coastguard Worker * program_type distinguishes the [s]rtp sender and receiver cases
132*90e502c7SAndroid Build Coastguard Worker */
133*90e502c7SAndroid Build Coastguard Worker
134*90e502c7SAndroid Build Coastguard Worker typedef enum { sender, receiver, unknown } program_type;
135*90e502c7SAndroid Build Coastguard Worker
main(int argc,char * argv[])136*90e502c7SAndroid Build Coastguard Worker int main(int argc, char *argv[])
137*90e502c7SAndroid Build Coastguard Worker {
138*90e502c7SAndroid Build Coastguard Worker char *dictfile = DICT_FILE;
139*90e502c7SAndroid Build Coastguard Worker FILE *dict;
140*90e502c7SAndroid Build Coastguard Worker char word[MAX_WORD_LEN];
141*90e502c7SAndroid Build Coastguard Worker int sock, ret;
142*90e502c7SAndroid Build Coastguard Worker struct in_addr rcvr_addr;
143*90e502c7SAndroid Build Coastguard Worker struct sockaddr_in name;
144*90e502c7SAndroid Build Coastguard Worker struct ip_mreq mreq;
145*90e502c7SAndroid Build Coastguard Worker #if BEW
146*90e502c7SAndroid Build Coastguard Worker struct sockaddr_in local;
147*90e502c7SAndroid Build Coastguard Worker #endif
148*90e502c7SAndroid Build Coastguard Worker program_type prog_type = unknown;
149*90e502c7SAndroid Build Coastguard Worker srtp_sec_serv_t sec_servs = sec_serv_none;
150*90e502c7SAndroid Build Coastguard Worker unsigned char ttl = 5;
151*90e502c7SAndroid Build Coastguard Worker int c;
152*90e502c7SAndroid Build Coastguard Worker int key_size = 128;
153*90e502c7SAndroid Build Coastguard Worker int tag_size = 8;
154*90e502c7SAndroid Build Coastguard Worker int gcm_on = 0;
155*90e502c7SAndroid Build Coastguard Worker char *input_key = NULL;
156*90e502c7SAndroid Build Coastguard Worker int b64_input = 0;
157*90e502c7SAndroid Build Coastguard Worker char *address = NULL;
158*90e502c7SAndroid Build Coastguard Worker char key[MAX_KEY_LEN];
159*90e502c7SAndroid Build Coastguard Worker unsigned short port = 0;
160*90e502c7SAndroid Build Coastguard Worker rtp_sender_t snd;
161*90e502c7SAndroid Build Coastguard Worker srtp_policy_t policy;
162*90e502c7SAndroid Build Coastguard Worker srtp_err_status_t status;
163*90e502c7SAndroid Build Coastguard Worker int len;
164*90e502c7SAndroid Build Coastguard Worker int expected_len;
165*90e502c7SAndroid Build Coastguard Worker int do_list_mods = 0;
166*90e502c7SAndroid Build Coastguard Worker uint32_t ssrc = 0xdeadbeef; /* ssrc value hardcoded for now */
167*90e502c7SAndroid Build Coastguard Worker #ifdef RTPW_USE_WINSOCK2
168*90e502c7SAndroid Build Coastguard Worker WORD wVersionRequested = MAKEWORD(2, 0);
169*90e502c7SAndroid Build Coastguard Worker WSADATA wsaData;
170*90e502c7SAndroid Build Coastguard Worker
171*90e502c7SAndroid Build Coastguard Worker ret = WSAStartup(wVersionRequested, &wsaData);
172*90e502c7SAndroid Build Coastguard Worker if (ret != 0) {
173*90e502c7SAndroid Build Coastguard Worker fprintf(stderr, "error: WSAStartup() failed: %d\n", ret);
174*90e502c7SAndroid Build Coastguard Worker exit(1);
175*90e502c7SAndroid Build Coastguard Worker }
176*90e502c7SAndroid Build Coastguard Worker #endif
177*90e502c7SAndroid Build Coastguard Worker
178*90e502c7SAndroid Build Coastguard Worker memset(&policy, 0x0, sizeof(srtp_policy_t));
179*90e502c7SAndroid Build Coastguard Worker
180*90e502c7SAndroid Build Coastguard Worker printf("Using %s [0x%x]\n", srtp_get_version_string(), srtp_get_version());
181*90e502c7SAndroid Build Coastguard Worker
182*90e502c7SAndroid Build Coastguard Worker if (setup_signal_handler(argv[0]) != 0) {
183*90e502c7SAndroid Build Coastguard Worker exit(1);
184*90e502c7SAndroid Build Coastguard Worker }
185*90e502c7SAndroid Build Coastguard Worker
186*90e502c7SAndroid Build Coastguard Worker /* initialize srtp library */
187*90e502c7SAndroid Build Coastguard Worker status = srtp_init();
188*90e502c7SAndroid Build Coastguard Worker if (status) {
189*90e502c7SAndroid Build Coastguard Worker printf("error: srtp initialization failed with error code %d\n",
190*90e502c7SAndroid Build Coastguard Worker status);
191*90e502c7SAndroid Build Coastguard Worker exit(1);
192*90e502c7SAndroid Build Coastguard Worker }
193*90e502c7SAndroid Build Coastguard Worker
194*90e502c7SAndroid Build Coastguard Worker /* check args */
195*90e502c7SAndroid Build Coastguard Worker while (1) {
196*90e502c7SAndroid Build Coastguard Worker c = getopt_s(argc, argv, "b:k:rsgt:ae:ld:w:");
197*90e502c7SAndroid Build Coastguard Worker if (c == -1) {
198*90e502c7SAndroid Build Coastguard Worker break;
199*90e502c7SAndroid Build Coastguard Worker }
200*90e502c7SAndroid Build Coastguard Worker switch (c) {
201*90e502c7SAndroid Build Coastguard Worker case 'b':
202*90e502c7SAndroid Build Coastguard Worker b64_input = 1;
203*90e502c7SAndroid Build Coastguard Worker /* fall thru */
204*90e502c7SAndroid Build Coastguard Worker case 'k':
205*90e502c7SAndroid Build Coastguard Worker input_key = optarg_s;
206*90e502c7SAndroid Build Coastguard Worker break;
207*90e502c7SAndroid Build Coastguard Worker case 'e':
208*90e502c7SAndroid Build Coastguard Worker key_size = atoi(optarg_s);
209*90e502c7SAndroid Build Coastguard Worker if (key_size != 128 && key_size != 256) {
210*90e502c7SAndroid Build Coastguard Worker printf("error: encryption key size must be 128 or 256 (%d)\n",
211*90e502c7SAndroid Build Coastguard Worker key_size);
212*90e502c7SAndroid Build Coastguard Worker exit(1);
213*90e502c7SAndroid Build Coastguard Worker }
214*90e502c7SAndroid Build Coastguard Worker sec_servs |= sec_serv_conf;
215*90e502c7SAndroid Build Coastguard Worker break;
216*90e502c7SAndroid Build Coastguard Worker case 't':
217*90e502c7SAndroid Build Coastguard Worker tag_size = atoi(optarg_s);
218*90e502c7SAndroid Build Coastguard Worker if (tag_size != 8 && tag_size != 16) {
219*90e502c7SAndroid Build Coastguard Worker printf("error: GCM tag size must be 8 or 16 (%d)\n", tag_size);
220*90e502c7SAndroid Build Coastguard Worker exit(1);
221*90e502c7SAndroid Build Coastguard Worker }
222*90e502c7SAndroid Build Coastguard Worker break;
223*90e502c7SAndroid Build Coastguard Worker case 'a':
224*90e502c7SAndroid Build Coastguard Worker sec_servs |= sec_serv_auth;
225*90e502c7SAndroid Build Coastguard Worker break;
226*90e502c7SAndroid Build Coastguard Worker case 'g':
227*90e502c7SAndroid Build Coastguard Worker gcm_on = 1;
228*90e502c7SAndroid Build Coastguard Worker sec_servs |= sec_serv_auth;
229*90e502c7SAndroid Build Coastguard Worker break;
230*90e502c7SAndroid Build Coastguard Worker case 'r':
231*90e502c7SAndroid Build Coastguard Worker prog_type = receiver;
232*90e502c7SAndroid Build Coastguard Worker break;
233*90e502c7SAndroid Build Coastguard Worker case 's':
234*90e502c7SAndroid Build Coastguard Worker prog_type = sender;
235*90e502c7SAndroid Build Coastguard Worker break;
236*90e502c7SAndroid Build Coastguard Worker case 'd':
237*90e502c7SAndroid Build Coastguard Worker status = srtp_set_debug_module(optarg_s, 1);
238*90e502c7SAndroid Build Coastguard Worker if (status) {
239*90e502c7SAndroid Build Coastguard Worker printf("error: set debug module (%s) failed\n", optarg_s);
240*90e502c7SAndroid Build Coastguard Worker exit(1);
241*90e502c7SAndroid Build Coastguard Worker }
242*90e502c7SAndroid Build Coastguard Worker break;
243*90e502c7SAndroid Build Coastguard Worker case 'l':
244*90e502c7SAndroid Build Coastguard Worker do_list_mods = 1;
245*90e502c7SAndroid Build Coastguard Worker break;
246*90e502c7SAndroid Build Coastguard Worker case 'w':
247*90e502c7SAndroid Build Coastguard Worker dictfile = optarg_s;
248*90e502c7SAndroid Build Coastguard Worker break;
249*90e502c7SAndroid Build Coastguard Worker default:
250*90e502c7SAndroid Build Coastguard Worker usage(argv[0]);
251*90e502c7SAndroid Build Coastguard Worker }
252*90e502c7SAndroid Build Coastguard Worker }
253*90e502c7SAndroid Build Coastguard Worker
254*90e502c7SAndroid Build Coastguard Worker if (prog_type == unknown) {
255*90e502c7SAndroid Build Coastguard Worker if (do_list_mods) {
256*90e502c7SAndroid Build Coastguard Worker status = srtp_list_debug_modules();
257*90e502c7SAndroid Build Coastguard Worker if (status) {
258*90e502c7SAndroid Build Coastguard Worker printf("error: list of debug modules failed\n");
259*90e502c7SAndroid Build Coastguard Worker exit(1);
260*90e502c7SAndroid Build Coastguard Worker }
261*90e502c7SAndroid Build Coastguard Worker return 0;
262*90e502c7SAndroid Build Coastguard Worker } else {
263*90e502c7SAndroid Build Coastguard Worker printf("error: neither sender [-s] nor receiver [-r] specified\n");
264*90e502c7SAndroid Build Coastguard Worker usage(argv[0]);
265*90e502c7SAndroid Build Coastguard Worker }
266*90e502c7SAndroid Build Coastguard Worker }
267*90e502c7SAndroid Build Coastguard Worker
268*90e502c7SAndroid Build Coastguard Worker if ((sec_servs && !input_key) || (!sec_servs && input_key)) {
269*90e502c7SAndroid Build Coastguard Worker /*
270*90e502c7SAndroid Build Coastguard Worker * a key must be provided if and only if security services have
271*90e502c7SAndroid Build Coastguard Worker * been requested
272*90e502c7SAndroid Build Coastguard Worker */
273*90e502c7SAndroid Build Coastguard Worker usage(argv[0]);
274*90e502c7SAndroid Build Coastguard Worker }
275*90e502c7SAndroid Build Coastguard Worker
276*90e502c7SAndroid Build Coastguard Worker if (argc != optind_s + 2) {
277*90e502c7SAndroid Build Coastguard Worker /* wrong number of arguments */
278*90e502c7SAndroid Build Coastguard Worker usage(argv[0]);
279*90e502c7SAndroid Build Coastguard Worker }
280*90e502c7SAndroid Build Coastguard Worker
281*90e502c7SAndroid Build Coastguard Worker /* get address from arg */
282*90e502c7SAndroid Build Coastguard Worker address = argv[optind_s++];
283*90e502c7SAndroid Build Coastguard Worker
284*90e502c7SAndroid Build Coastguard Worker /* get port from arg */
285*90e502c7SAndroid Build Coastguard Worker port = atoi(argv[optind_s++]);
286*90e502c7SAndroid Build Coastguard Worker
287*90e502c7SAndroid Build Coastguard Worker /* set address */
288*90e502c7SAndroid Build Coastguard Worker #ifdef HAVE_INET_ATON
289*90e502c7SAndroid Build Coastguard Worker if (0 == inet_aton(address, &rcvr_addr)) {
290*90e502c7SAndroid Build Coastguard Worker fprintf(stderr, "%s: cannot parse IP v4 address %s\n", argv[0],
291*90e502c7SAndroid Build Coastguard Worker address);
292*90e502c7SAndroid Build Coastguard Worker exit(1);
293*90e502c7SAndroid Build Coastguard Worker }
294*90e502c7SAndroid Build Coastguard Worker if (rcvr_addr.s_addr == INADDR_NONE) {
295*90e502c7SAndroid Build Coastguard Worker fprintf(stderr, "%s: address error", argv[0]);
296*90e502c7SAndroid Build Coastguard Worker exit(1);
297*90e502c7SAndroid Build Coastguard Worker }
298*90e502c7SAndroid Build Coastguard Worker #else
299*90e502c7SAndroid Build Coastguard Worker rcvr_addr.s_addr = inet_addr(address);
300*90e502c7SAndroid Build Coastguard Worker if (0xffffffff == rcvr_addr.s_addr) {
301*90e502c7SAndroid Build Coastguard Worker fprintf(stderr, "%s: cannot parse IP v4 address %s\n", argv[0],
302*90e502c7SAndroid Build Coastguard Worker address);
303*90e502c7SAndroid Build Coastguard Worker exit(1);
304*90e502c7SAndroid Build Coastguard Worker }
305*90e502c7SAndroid Build Coastguard Worker #endif
306*90e502c7SAndroid Build Coastguard Worker
307*90e502c7SAndroid Build Coastguard Worker /* open socket */
308*90e502c7SAndroid Build Coastguard Worker sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
309*90e502c7SAndroid Build Coastguard Worker if (sock < 0) {
310*90e502c7SAndroid Build Coastguard Worker int err;
311*90e502c7SAndroid Build Coastguard Worker #ifdef RTPW_USE_WINSOCK2
312*90e502c7SAndroid Build Coastguard Worker err = WSAGetLastError();
313*90e502c7SAndroid Build Coastguard Worker #else
314*90e502c7SAndroid Build Coastguard Worker err = errno;
315*90e502c7SAndroid Build Coastguard Worker #endif
316*90e502c7SAndroid Build Coastguard Worker fprintf(stderr, "%s: couldn't open socket: %d\n", argv[0], err);
317*90e502c7SAndroid Build Coastguard Worker exit(1);
318*90e502c7SAndroid Build Coastguard Worker }
319*90e502c7SAndroid Build Coastguard Worker
320*90e502c7SAndroid Build Coastguard Worker memset(&name, 0, sizeof(struct sockaddr_in));
321*90e502c7SAndroid Build Coastguard Worker name.sin_addr = rcvr_addr;
322*90e502c7SAndroid Build Coastguard Worker name.sin_family = PF_INET;
323*90e502c7SAndroid Build Coastguard Worker name.sin_port = htons(port);
324*90e502c7SAndroid Build Coastguard Worker
325*90e502c7SAndroid Build Coastguard Worker if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
326*90e502c7SAndroid Build Coastguard Worker if (prog_type == sender) {
327*90e502c7SAndroid Build Coastguard Worker ret = setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
328*90e502c7SAndroid Build Coastguard Worker sizeof(ttl));
329*90e502c7SAndroid Build Coastguard Worker if (ret < 0) {
330*90e502c7SAndroid Build Coastguard Worker fprintf(stderr, "%s: Failed to set TTL for multicast group",
331*90e502c7SAndroid Build Coastguard Worker argv[0]);
332*90e502c7SAndroid Build Coastguard Worker perror("");
333*90e502c7SAndroid Build Coastguard Worker exit(1);
334*90e502c7SAndroid Build Coastguard Worker }
335*90e502c7SAndroid Build Coastguard Worker }
336*90e502c7SAndroid Build Coastguard Worker
337*90e502c7SAndroid Build Coastguard Worker mreq.imr_multiaddr.s_addr = rcvr_addr.s_addr;
338*90e502c7SAndroid Build Coastguard Worker mreq.imr_interface.s_addr = htonl(INADDR_ANY);
339*90e502c7SAndroid Build Coastguard Worker ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq,
340*90e502c7SAndroid Build Coastguard Worker sizeof(mreq));
341*90e502c7SAndroid Build Coastguard Worker if (ret < 0) {
342*90e502c7SAndroid Build Coastguard Worker fprintf(stderr, "%s: Failed to join multicast group", argv[0]);
343*90e502c7SAndroid Build Coastguard Worker perror("");
344*90e502c7SAndroid Build Coastguard Worker exit(1);
345*90e502c7SAndroid Build Coastguard Worker }
346*90e502c7SAndroid Build Coastguard Worker }
347*90e502c7SAndroid Build Coastguard Worker
348*90e502c7SAndroid Build Coastguard Worker /* report security services selected on the command line */
349*90e502c7SAndroid Build Coastguard Worker printf("security services: ");
350*90e502c7SAndroid Build Coastguard Worker if (sec_servs & sec_serv_conf)
351*90e502c7SAndroid Build Coastguard Worker printf("confidentiality ");
352*90e502c7SAndroid Build Coastguard Worker if (sec_servs & sec_serv_auth)
353*90e502c7SAndroid Build Coastguard Worker printf("message authentication");
354*90e502c7SAndroid Build Coastguard Worker if (sec_servs == sec_serv_none)
355*90e502c7SAndroid Build Coastguard Worker printf("none");
356*90e502c7SAndroid Build Coastguard Worker printf("\n");
357*90e502c7SAndroid Build Coastguard Worker
358*90e502c7SAndroid Build Coastguard Worker /* set up the srtp policy and master key */
359*90e502c7SAndroid Build Coastguard Worker if (sec_servs) {
360*90e502c7SAndroid Build Coastguard Worker /*
361*90e502c7SAndroid Build Coastguard Worker * create policy structure, using the default mechanisms but
362*90e502c7SAndroid Build Coastguard Worker * with only the security services requested on the command line,
363*90e502c7SAndroid Build Coastguard Worker * using the right SSRC value
364*90e502c7SAndroid Build Coastguard Worker */
365*90e502c7SAndroid Build Coastguard Worker switch (sec_servs) {
366*90e502c7SAndroid Build Coastguard Worker case sec_serv_conf_and_auth:
367*90e502c7SAndroid Build Coastguard Worker if (gcm_on) {
368*90e502c7SAndroid Build Coastguard Worker #ifdef GCM
369*90e502c7SAndroid Build Coastguard Worker switch (key_size) {
370*90e502c7SAndroid Build Coastguard Worker case 128:
371*90e502c7SAndroid Build Coastguard Worker srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp);
372*90e502c7SAndroid Build Coastguard Worker srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp);
373*90e502c7SAndroid Build Coastguard Worker break;
374*90e502c7SAndroid Build Coastguard Worker case 256:
375*90e502c7SAndroid Build Coastguard Worker srtp_crypto_policy_set_aes_gcm_256_8_auth(&policy.rtp);
376*90e502c7SAndroid Build Coastguard Worker srtp_crypto_policy_set_aes_gcm_256_8_auth(&policy.rtcp);
377*90e502c7SAndroid Build Coastguard Worker break;
378*90e502c7SAndroid Build Coastguard Worker }
379*90e502c7SAndroid Build Coastguard Worker #else
380*90e502c7SAndroid Build Coastguard Worker printf("error: GCM mode only supported when using the OpenSSL "
381*90e502c7SAndroid Build Coastguard Worker "or NSS crypto engine.\n");
382*90e502c7SAndroid Build Coastguard Worker return 0;
383*90e502c7SAndroid Build Coastguard Worker #endif
384*90e502c7SAndroid Build Coastguard Worker } else {
385*90e502c7SAndroid Build Coastguard Worker switch (key_size) {
386*90e502c7SAndroid Build Coastguard Worker case 128:
387*90e502c7SAndroid Build Coastguard Worker srtp_crypto_policy_set_rtp_default(&policy.rtp);
388*90e502c7SAndroid Build Coastguard Worker srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
389*90e502c7SAndroid Build Coastguard Worker break;
390*90e502c7SAndroid Build Coastguard Worker case 256:
391*90e502c7SAndroid Build Coastguard Worker srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtp);
392*90e502c7SAndroid Build Coastguard Worker srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
393*90e502c7SAndroid Build Coastguard Worker break;
394*90e502c7SAndroid Build Coastguard Worker }
395*90e502c7SAndroid Build Coastguard Worker }
396*90e502c7SAndroid Build Coastguard Worker break;
397*90e502c7SAndroid Build Coastguard Worker case sec_serv_conf:
398*90e502c7SAndroid Build Coastguard Worker if (gcm_on) {
399*90e502c7SAndroid Build Coastguard Worker printf(
400*90e502c7SAndroid Build Coastguard Worker "error: GCM mode must always be used with auth enabled\n");
401*90e502c7SAndroid Build Coastguard Worker return -1;
402*90e502c7SAndroid Build Coastguard Worker } else {
403*90e502c7SAndroid Build Coastguard Worker switch (key_size) {
404*90e502c7SAndroid Build Coastguard Worker case 128:
405*90e502c7SAndroid Build Coastguard Worker srtp_crypto_policy_set_aes_cm_128_null_auth(&policy.rtp);
406*90e502c7SAndroid Build Coastguard Worker srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
407*90e502c7SAndroid Build Coastguard Worker break;
408*90e502c7SAndroid Build Coastguard Worker case 256:
409*90e502c7SAndroid Build Coastguard Worker srtp_crypto_policy_set_aes_cm_256_null_auth(&policy.rtp);
410*90e502c7SAndroid Build Coastguard Worker srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
411*90e502c7SAndroid Build Coastguard Worker break;
412*90e502c7SAndroid Build Coastguard Worker }
413*90e502c7SAndroid Build Coastguard Worker }
414*90e502c7SAndroid Build Coastguard Worker break;
415*90e502c7SAndroid Build Coastguard Worker case sec_serv_auth:
416*90e502c7SAndroid Build Coastguard Worker if (gcm_on) {
417*90e502c7SAndroid Build Coastguard Worker #ifdef GCM
418*90e502c7SAndroid Build Coastguard Worker switch (key_size) {
419*90e502c7SAndroid Build Coastguard Worker case 128:
420*90e502c7SAndroid Build Coastguard Worker srtp_crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtp);
421*90e502c7SAndroid Build Coastguard Worker srtp_crypto_policy_set_aes_gcm_128_8_only_auth(
422*90e502c7SAndroid Build Coastguard Worker &policy.rtcp);
423*90e502c7SAndroid Build Coastguard Worker break;
424*90e502c7SAndroid Build Coastguard Worker case 256:
425*90e502c7SAndroid Build Coastguard Worker srtp_crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtp);
426*90e502c7SAndroid Build Coastguard Worker srtp_crypto_policy_set_aes_gcm_256_8_only_auth(
427*90e502c7SAndroid Build Coastguard Worker &policy.rtcp);
428*90e502c7SAndroid Build Coastguard Worker break;
429*90e502c7SAndroid Build Coastguard Worker }
430*90e502c7SAndroid Build Coastguard Worker #else
431*90e502c7SAndroid Build Coastguard Worker printf("error: GCM mode only supported when using the OpenSSL "
432*90e502c7SAndroid Build Coastguard Worker "crypto engine.\n");
433*90e502c7SAndroid Build Coastguard Worker return 0;
434*90e502c7SAndroid Build Coastguard Worker #endif
435*90e502c7SAndroid Build Coastguard Worker } else {
436*90e502c7SAndroid Build Coastguard Worker srtp_crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp);
437*90e502c7SAndroid Build Coastguard Worker srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
438*90e502c7SAndroid Build Coastguard Worker }
439*90e502c7SAndroid Build Coastguard Worker break;
440*90e502c7SAndroid Build Coastguard Worker default:
441*90e502c7SAndroid Build Coastguard Worker printf("error: unknown security service requested\n");
442*90e502c7SAndroid Build Coastguard Worker return -1;
443*90e502c7SAndroid Build Coastguard Worker }
444*90e502c7SAndroid Build Coastguard Worker policy.ssrc.type = ssrc_specific;
445*90e502c7SAndroid Build Coastguard Worker policy.ssrc.value = ssrc;
446*90e502c7SAndroid Build Coastguard Worker policy.key = (uint8_t *)key;
447*90e502c7SAndroid Build Coastguard Worker policy.ekt = NULL;
448*90e502c7SAndroid Build Coastguard Worker policy.next = NULL;
449*90e502c7SAndroid Build Coastguard Worker policy.window_size = 128;
450*90e502c7SAndroid Build Coastguard Worker policy.allow_repeat_tx = 0;
451*90e502c7SAndroid Build Coastguard Worker policy.rtp.sec_serv = sec_servs;
452*90e502c7SAndroid Build Coastguard Worker policy.rtcp.sec_serv = sec_serv_none; /* we don't do RTCP anyway */
453*90e502c7SAndroid Build Coastguard Worker
454*90e502c7SAndroid Build Coastguard Worker if (gcm_on && tag_size != 8) {
455*90e502c7SAndroid Build Coastguard Worker policy.rtp.auth_tag_len = tag_size;
456*90e502c7SAndroid Build Coastguard Worker }
457*90e502c7SAndroid Build Coastguard Worker
458*90e502c7SAndroid Build Coastguard Worker /*
459*90e502c7SAndroid Build Coastguard Worker * read key from hexadecimal or base64 on command line into an octet
460*90e502c7SAndroid Build Coastguard Worker * string
461*90e502c7SAndroid Build Coastguard Worker */
462*90e502c7SAndroid Build Coastguard Worker if (b64_input) {
463*90e502c7SAndroid Build Coastguard Worker int pad;
464*90e502c7SAndroid Build Coastguard Worker expected_len = (policy.rtp.cipher_key_len * 4) / 3;
465*90e502c7SAndroid Build Coastguard Worker len = base64_string_to_octet_string(key, &pad, input_key,
466*90e502c7SAndroid Build Coastguard Worker expected_len);
467*90e502c7SAndroid Build Coastguard Worker if (pad != 0) {
468*90e502c7SAndroid Build Coastguard Worker fprintf(stderr, "error: padding in base64 unexpected\n");
469*90e502c7SAndroid Build Coastguard Worker exit(1);
470*90e502c7SAndroid Build Coastguard Worker }
471*90e502c7SAndroid Build Coastguard Worker } else {
472*90e502c7SAndroid Build Coastguard Worker expected_len = policy.rtp.cipher_key_len * 2;
473*90e502c7SAndroid Build Coastguard Worker len = hex_string_to_octet_string(key, input_key, expected_len);
474*90e502c7SAndroid Build Coastguard Worker }
475*90e502c7SAndroid Build Coastguard Worker /* check that hex string is the right length */
476*90e502c7SAndroid Build Coastguard Worker if (len < expected_len) {
477*90e502c7SAndroid Build Coastguard Worker fprintf(stderr, "error: too few digits in key/salt "
478*90e502c7SAndroid Build Coastguard Worker "(should be %d digits, found %d)\n",
479*90e502c7SAndroid Build Coastguard Worker expected_len, len);
480*90e502c7SAndroid Build Coastguard Worker exit(1);
481*90e502c7SAndroid Build Coastguard Worker }
482*90e502c7SAndroid Build Coastguard Worker if ((int)strlen(input_key) > policy.rtp.cipher_key_len * 2) {
483*90e502c7SAndroid Build Coastguard Worker fprintf(stderr, "error: too many digits in key/salt "
484*90e502c7SAndroid Build Coastguard Worker "(should be %d hexadecimal digits, found %u)\n",
485*90e502c7SAndroid Build Coastguard Worker policy.rtp.cipher_key_len * 2, (unsigned)strlen(input_key));
486*90e502c7SAndroid Build Coastguard Worker exit(1);
487*90e502c7SAndroid Build Coastguard Worker }
488*90e502c7SAndroid Build Coastguard Worker
489*90e502c7SAndroid Build Coastguard Worker printf("set master key/salt to %s/", octet_string_hex_string(key, 16));
490*90e502c7SAndroid Build Coastguard Worker printf("%s\n", octet_string_hex_string(key + 16, 14));
491*90e502c7SAndroid Build Coastguard Worker
492*90e502c7SAndroid Build Coastguard Worker } else {
493*90e502c7SAndroid Build Coastguard Worker /*
494*90e502c7SAndroid Build Coastguard Worker * we're not providing security services, so set the policy to the
495*90e502c7SAndroid Build Coastguard Worker * null policy
496*90e502c7SAndroid Build Coastguard Worker *
497*90e502c7SAndroid Build Coastguard Worker * Note that this policy does not conform to the SRTP
498*90e502c7SAndroid Build Coastguard Worker * specification, since RTCP authentication is required. However,
499*90e502c7SAndroid Build Coastguard Worker * the effect of this policy is to turn off SRTP, so that this
500*90e502c7SAndroid Build Coastguard Worker * application is now a vanilla-flavored RTP application.
501*90e502c7SAndroid Build Coastguard Worker */
502*90e502c7SAndroid Build Coastguard Worker srtp_crypto_policy_set_null_cipher_hmac_null(&policy.rtp);
503*90e502c7SAndroid Build Coastguard Worker srtp_crypto_policy_set_null_cipher_hmac_null(&policy.rtcp);
504*90e502c7SAndroid Build Coastguard Worker policy.key = (uint8_t *)key;
505*90e502c7SAndroid Build Coastguard Worker policy.ssrc.type = ssrc_specific;
506*90e502c7SAndroid Build Coastguard Worker policy.ssrc.value = ssrc;
507*90e502c7SAndroid Build Coastguard Worker policy.window_size = 0;
508*90e502c7SAndroid Build Coastguard Worker policy.allow_repeat_tx = 0;
509*90e502c7SAndroid Build Coastguard Worker policy.ekt = NULL;
510*90e502c7SAndroid Build Coastguard Worker policy.next = NULL;
511*90e502c7SAndroid Build Coastguard Worker }
512*90e502c7SAndroid Build Coastguard Worker
513*90e502c7SAndroid Build Coastguard Worker if (prog_type == sender) {
514*90e502c7SAndroid Build Coastguard Worker #if BEW
515*90e502c7SAndroid Build Coastguard Worker /* bind to local socket (to match crypto policy, if need be) */
516*90e502c7SAndroid Build Coastguard Worker memset(&local, 0, sizeof(struct sockaddr_in));
517*90e502c7SAndroid Build Coastguard Worker local.sin_addr.s_addr = htonl(INADDR_ANY);
518*90e502c7SAndroid Build Coastguard Worker local.sin_port = htons(port);
519*90e502c7SAndroid Build Coastguard Worker ret = bind(sock, (struct sockaddr *)&local, sizeof(struct sockaddr_in));
520*90e502c7SAndroid Build Coastguard Worker if (ret < 0) {
521*90e502c7SAndroid Build Coastguard Worker fprintf(stderr, "%s: bind failed\n", argv[0]);
522*90e502c7SAndroid Build Coastguard Worker perror("");
523*90e502c7SAndroid Build Coastguard Worker exit(1);
524*90e502c7SAndroid Build Coastguard Worker }
525*90e502c7SAndroid Build Coastguard Worker #endif /* BEW */
526*90e502c7SAndroid Build Coastguard Worker
527*90e502c7SAndroid Build Coastguard Worker /* initialize sender's rtp and srtp contexts */
528*90e502c7SAndroid Build Coastguard Worker snd = rtp_sender_alloc();
529*90e502c7SAndroid Build Coastguard Worker if (snd == NULL) {
530*90e502c7SAndroid Build Coastguard Worker fprintf(stderr, "error: malloc() failed\n");
531*90e502c7SAndroid Build Coastguard Worker exit(1);
532*90e502c7SAndroid Build Coastguard Worker }
533*90e502c7SAndroid Build Coastguard Worker rtp_sender_init(snd, sock, name, ssrc);
534*90e502c7SAndroid Build Coastguard Worker status = rtp_sender_init_srtp(snd, &policy);
535*90e502c7SAndroid Build Coastguard Worker if (status) {
536*90e502c7SAndroid Build Coastguard Worker fprintf(stderr, "error: srtp_create() failed with code %d\n",
537*90e502c7SAndroid Build Coastguard Worker status);
538*90e502c7SAndroid Build Coastguard Worker exit(1);
539*90e502c7SAndroid Build Coastguard Worker }
540*90e502c7SAndroid Build Coastguard Worker
541*90e502c7SAndroid Build Coastguard Worker /* open dictionary */
542*90e502c7SAndroid Build Coastguard Worker dict = fopen(dictfile, "r");
543*90e502c7SAndroid Build Coastguard Worker if (dict == NULL) {
544*90e502c7SAndroid Build Coastguard Worker fprintf(stderr, "%s: couldn't open file %s\n", argv[0], dictfile);
545*90e502c7SAndroid Build Coastguard Worker if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
546*90e502c7SAndroid Build Coastguard Worker leave_group(sock, mreq, argv[0]);
547*90e502c7SAndroid Build Coastguard Worker }
548*90e502c7SAndroid Build Coastguard Worker exit(1);
549*90e502c7SAndroid Build Coastguard Worker }
550*90e502c7SAndroid Build Coastguard Worker
551*90e502c7SAndroid Build Coastguard Worker /* read words from dictionary, then send them off */
552*90e502c7SAndroid Build Coastguard Worker while (!interrupted && fgets(word, MAX_WORD_LEN, dict) != NULL) {
553*90e502c7SAndroid Build Coastguard Worker len = strlen(word) + 1; /* plus one for null */
554*90e502c7SAndroid Build Coastguard Worker
555*90e502c7SAndroid Build Coastguard Worker if (len > MAX_WORD_LEN)
556*90e502c7SAndroid Build Coastguard Worker printf("error: word %s too large to send\n", word);
557*90e502c7SAndroid Build Coastguard Worker else {
558*90e502c7SAndroid Build Coastguard Worker rtp_sendto(snd, word, len);
559*90e502c7SAndroid Build Coastguard Worker printf("sending word: %s", word);
560*90e502c7SAndroid Build Coastguard Worker }
561*90e502c7SAndroid Build Coastguard Worker usleep(USEC_RATE);
562*90e502c7SAndroid Build Coastguard Worker }
563*90e502c7SAndroid Build Coastguard Worker
564*90e502c7SAndroid Build Coastguard Worker rtp_sender_deinit_srtp(snd);
565*90e502c7SAndroid Build Coastguard Worker rtp_sender_dealloc(snd);
566*90e502c7SAndroid Build Coastguard Worker
567*90e502c7SAndroid Build Coastguard Worker fclose(dict);
568*90e502c7SAndroid Build Coastguard Worker } else { /* prog_type == receiver */
569*90e502c7SAndroid Build Coastguard Worker rtp_receiver_t rcvr;
570*90e502c7SAndroid Build Coastguard Worker
571*90e502c7SAndroid Build Coastguard Worker if (bind(sock, (struct sockaddr *)&name, sizeof(name)) < 0) {
572*90e502c7SAndroid Build Coastguard Worker close(sock);
573*90e502c7SAndroid Build Coastguard Worker fprintf(stderr, "%s: socket bind error\n", argv[0]);
574*90e502c7SAndroid Build Coastguard Worker perror(NULL);
575*90e502c7SAndroid Build Coastguard Worker if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
576*90e502c7SAndroid Build Coastguard Worker leave_group(sock, mreq, argv[0]);
577*90e502c7SAndroid Build Coastguard Worker }
578*90e502c7SAndroid Build Coastguard Worker exit(1);
579*90e502c7SAndroid Build Coastguard Worker }
580*90e502c7SAndroid Build Coastguard Worker
581*90e502c7SAndroid Build Coastguard Worker rcvr = rtp_receiver_alloc();
582*90e502c7SAndroid Build Coastguard Worker if (rcvr == NULL) {
583*90e502c7SAndroid Build Coastguard Worker fprintf(stderr, "error: malloc() failed\n");
584*90e502c7SAndroid Build Coastguard Worker exit(1);
585*90e502c7SAndroid Build Coastguard Worker }
586*90e502c7SAndroid Build Coastguard Worker rtp_receiver_init(rcvr, sock, name, ssrc);
587*90e502c7SAndroid Build Coastguard Worker status = rtp_receiver_init_srtp(rcvr, &policy);
588*90e502c7SAndroid Build Coastguard Worker if (status) {
589*90e502c7SAndroid Build Coastguard Worker fprintf(stderr, "error: srtp_create() failed with code %d\n",
590*90e502c7SAndroid Build Coastguard Worker status);
591*90e502c7SAndroid Build Coastguard Worker exit(1);
592*90e502c7SAndroid Build Coastguard Worker }
593*90e502c7SAndroid Build Coastguard Worker
594*90e502c7SAndroid Build Coastguard Worker /* get next word and loop */
595*90e502c7SAndroid Build Coastguard Worker while (!interrupted) {
596*90e502c7SAndroid Build Coastguard Worker len = MAX_WORD_LEN;
597*90e502c7SAndroid Build Coastguard Worker if (rtp_recvfrom(rcvr, word, &len) > -1)
598*90e502c7SAndroid Build Coastguard Worker printf("\tword: %s\n", word);
599*90e502c7SAndroid Build Coastguard Worker }
600*90e502c7SAndroid Build Coastguard Worker
601*90e502c7SAndroid Build Coastguard Worker rtp_receiver_deinit_srtp(rcvr);
602*90e502c7SAndroid Build Coastguard Worker rtp_receiver_dealloc(rcvr);
603*90e502c7SAndroid Build Coastguard Worker }
604*90e502c7SAndroid Build Coastguard Worker
605*90e502c7SAndroid Build Coastguard Worker if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
606*90e502c7SAndroid Build Coastguard Worker leave_group(sock, mreq, argv[0]);
607*90e502c7SAndroid Build Coastguard Worker }
608*90e502c7SAndroid Build Coastguard Worker
609*90e502c7SAndroid Build Coastguard Worker #ifdef RTPW_USE_WINSOCK2
610*90e502c7SAndroid Build Coastguard Worker ret = closesocket(sock);
611*90e502c7SAndroid Build Coastguard Worker #else
612*90e502c7SAndroid Build Coastguard Worker ret = close(sock);
613*90e502c7SAndroid Build Coastguard Worker #endif
614*90e502c7SAndroid Build Coastguard Worker if (ret < 0) {
615*90e502c7SAndroid Build Coastguard Worker fprintf(stderr, "%s: Failed to close socket", argv[0]);
616*90e502c7SAndroid Build Coastguard Worker perror("");
617*90e502c7SAndroid Build Coastguard Worker }
618*90e502c7SAndroid Build Coastguard Worker
619*90e502c7SAndroid Build Coastguard Worker status = srtp_shutdown();
620*90e502c7SAndroid Build Coastguard Worker if (status) {
621*90e502c7SAndroid Build Coastguard Worker printf("error: srtp shutdown failed with error code %d\n", status);
622*90e502c7SAndroid Build Coastguard Worker exit(1);
623*90e502c7SAndroid Build Coastguard Worker }
624*90e502c7SAndroid Build Coastguard Worker
625*90e502c7SAndroid Build Coastguard Worker #ifdef RTPW_USE_WINSOCK2
626*90e502c7SAndroid Build Coastguard Worker WSACleanup();
627*90e502c7SAndroid Build Coastguard Worker #endif
628*90e502c7SAndroid Build Coastguard Worker
629*90e502c7SAndroid Build Coastguard Worker return 0;
630*90e502c7SAndroid Build Coastguard Worker }
631*90e502c7SAndroid Build Coastguard Worker
usage(char * string)632*90e502c7SAndroid Build Coastguard Worker void usage(char *string)
633*90e502c7SAndroid Build Coastguard Worker {
634*90e502c7SAndroid Build Coastguard Worker printf("usage: %s [-d <debug>]* [-k <key> [-a][-e]] "
635*90e502c7SAndroid Build Coastguard Worker "[-s | -r] dest_ip dest_port\n"
636*90e502c7SAndroid Build Coastguard Worker "or %s -l\n"
637*90e502c7SAndroid Build Coastguard Worker "where -a use message authentication\n"
638*90e502c7SAndroid Build Coastguard Worker " -e <key size> use encryption (use 128 or 256 for key size)\n"
639*90e502c7SAndroid Build Coastguard Worker " -g Use AES-GCM mode (must be used with -e)\n"
640*90e502c7SAndroid Build Coastguard Worker " -t <tag size> Tag size to use in GCM mode (use 8 or 16)\n"
641*90e502c7SAndroid Build Coastguard Worker " -k <key> sets the srtp master key given in hexadecimal\n"
642*90e502c7SAndroid Build Coastguard Worker " -b <key> sets the srtp master key given in base64\n"
643*90e502c7SAndroid Build Coastguard Worker " -s act as rtp sender\n"
644*90e502c7SAndroid Build Coastguard Worker " -r act as rtp receiver\n"
645*90e502c7SAndroid Build Coastguard Worker " -l list debug modules\n"
646*90e502c7SAndroid Build Coastguard Worker " -d <debug> turn on debugging for module <debug>\n"
647*90e502c7SAndroid Build Coastguard Worker " -w <wordsfile> use <wordsfile> for input, rather than %s\n",
648*90e502c7SAndroid Build Coastguard Worker string, string, DICT_FILE);
649*90e502c7SAndroid Build Coastguard Worker exit(1);
650*90e502c7SAndroid Build Coastguard Worker }
651*90e502c7SAndroid Build Coastguard Worker
leave_group(int sock,struct ip_mreq mreq,char * name)652*90e502c7SAndroid Build Coastguard Worker void leave_group(int sock, struct ip_mreq mreq, char *name)
653*90e502c7SAndroid Build Coastguard Worker {
654*90e502c7SAndroid Build Coastguard Worker int ret;
655*90e502c7SAndroid Build Coastguard Worker
656*90e502c7SAndroid Build Coastguard Worker ret = setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, (void *)&mreq,
657*90e502c7SAndroid Build Coastguard Worker sizeof(mreq));
658*90e502c7SAndroid Build Coastguard Worker if (ret < 0) {
659*90e502c7SAndroid Build Coastguard Worker fprintf(stderr, "%s: Failed to leave multicast group", name);
660*90e502c7SAndroid Build Coastguard Worker perror("");
661*90e502c7SAndroid Build Coastguard Worker }
662*90e502c7SAndroid Build Coastguard Worker }
663*90e502c7SAndroid Build Coastguard Worker
handle_signal(int signum)664*90e502c7SAndroid Build Coastguard Worker void handle_signal(int signum)
665*90e502c7SAndroid Build Coastguard Worker {
666*90e502c7SAndroid Build Coastguard Worker interrupted = 1;
667*90e502c7SAndroid Build Coastguard Worker /* Reset handler explicitly, in case we don't have sigaction() (and signal()
668*90e502c7SAndroid Build Coastguard Worker has BSD semantics), or we don't have SA_RESETHAND */
669*90e502c7SAndroid Build Coastguard Worker signal(signum, SIG_DFL);
670*90e502c7SAndroid Build Coastguard Worker }
671*90e502c7SAndroid Build Coastguard Worker
setup_signal_handler(char * name)672*90e502c7SAndroid Build Coastguard Worker int setup_signal_handler(char *name)
673*90e502c7SAndroid Build Coastguard Worker {
674*90e502c7SAndroid Build Coastguard Worker #if HAVE_SIGACTION
675*90e502c7SAndroid Build Coastguard Worker struct sigaction act;
676*90e502c7SAndroid Build Coastguard Worker memset(&act, 0, sizeof(act));
677*90e502c7SAndroid Build Coastguard Worker
678*90e502c7SAndroid Build Coastguard Worker act.sa_handler = handle_signal;
679*90e502c7SAndroid Build Coastguard Worker sigemptyset(&act.sa_mask);
680*90e502c7SAndroid Build Coastguard Worker #if defined(SA_RESETHAND)
681*90e502c7SAndroid Build Coastguard Worker act.sa_flags = SA_RESETHAND;
682*90e502c7SAndroid Build Coastguard Worker #else
683*90e502c7SAndroid Build Coastguard Worker act.sa_flags = 0;
684*90e502c7SAndroid Build Coastguard Worker #endif
685*90e502c7SAndroid Build Coastguard Worker /* Note that we're not setting SA_RESTART; we want recvfrom to return
686*90e502c7SAndroid Build Coastguard Worker * EINTR when we signal the receiver. */
687*90e502c7SAndroid Build Coastguard Worker
688*90e502c7SAndroid Build Coastguard Worker if (sigaction(SIGTERM, &act, NULL) != 0) {
689*90e502c7SAndroid Build Coastguard Worker fprintf(stderr, "%s: error setting up signal handler", name);
690*90e502c7SAndroid Build Coastguard Worker perror("");
691*90e502c7SAndroid Build Coastguard Worker return -1;
692*90e502c7SAndroid Build Coastguard Worker }
693*90e502c7SAndroid Build Coastguard Worker #else
694*90e502c7SAndroid Build Coastguard Worker if (signal(SIGTERM, handle_signal) == SIG_ERR) {
695*90e502c7SAndroid Build Coastguard Worker fprintf(stderr, "%s: error setting up signal handler", name);
696*90e502c7SAndroid Build Coastguard Worker perror("");
697*90e502c7SAndroid Build Coastguard Worker return -1;
698*90e502c7SAndroid Build Coastguard Worker }
699*90e502c7SAndroid Build Coastguard Worker #endif
700*90e502c7SAndroid Build Coastguard Worker return 0;
701*90e502c7SAndroid Build Coastguard Worker }
702