xref: /aosp_15_r20/external/libsrtp2/test/rtpw.c (revision 90e502c7aef8d77d0622bb67d75435c6190cfc1a)
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