~ubuntu-branches/ubuntu/trusty/sflphone/trusty

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/third_party/srtp/test/rtpw.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (4.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20140128182336-jrsv0k9u6cawc068
Tags: 1.3.0-1
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * rtpw.c
3
 
 *
4
 
 * rtp word sender/receiver
5
 
 *
6
 
 * David A. McGrew
7
 
 * Cisco Systems, Inc.
8
 
 *
9
 
 * This app is a simple RTP application intended only for testing
10
 
 * libsrtp.  It reads one word at a time from /usr/dict/words (or
11
 
 * whatever file is specified as DICT_FILE), and sends one word out
12
 
 * each USEC_RATE microseconds.  Secure RTP protections can be
13
 
 * applied.  See the usage() function for more details.
14
 
 *
15
 
 */
16
 
 
17
 
/*
18
 
 *
19
 
 * Copyright (c) 2001-2006, Cisco Systems, Inc.
20
 
 * All rights reserved.
21
 
 *
22
 
 * Redistribution and use in source and binary forms, with or without
23
 
 * modification, are permitted provided that the following conditions
24
 
 * are met:
25
 
 *
26
 
 *   Redistributions of source code must retain the above copyright
27
 
 *   notice, this list of conditions and the following disclaimer.
28
 
 *
29
 
 *   Redistributions in binary form must reproduce the above
30
 
 *   copyright notice, this list of conditions and the following
31
 
 *   disclaimer in the documentation and/or other materials provided
32
 
 *   with the distribution.
33
 
 *
34
 
 *   Neither the name of the Cisco Systems, Inc. nor the names of its
35
 
 *   contributors may be used to endorse or promote products derived
36
 
 *   from this software without specific prior written permission.
37
 
 *
38
 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
39
 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
40
 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
41
 
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
42
 
 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
43
 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
44
 
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
45
 
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46
 
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47
 
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48
 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49
 
 * OF THE POSSIBILITY OF SUCH DAMAGE.
50
 
 *
51
 
 */
52
 
 
53
 
 
54
 
#include "datatypes.h"
55
 
#include "getopt_s.h"       /* for local getopt()  */
56
 
 
57
 
#include <stdio.h>          /* for printf, fprintf */
58
 
#include <stdlib.h>         /* for atoi()          */
59
 
#include <errno.h>
60
 
#include <unistd.h>         /* for close()         */
61
 
 
62
 
#include <string.h>         /* for strncpy()       */
63
 
#include <time.h>           /* for usleep()        */
64
 
#ifdef HAVE_SYS_SOCKET_H
65
 
# include <sys/socket.h>
66
 
#endif
67
 
#ifdef HAVE_NETINET_IN_H
68
 
# include <netinet/in.h>
69
 
#elif defined HAVE_WINSOCK2_H
70
 
# include <winsock2.h>
71
 
# include <ws2tcpip.h>
72
 
# define RTPW_USE_WINSOCK2      1
73
 
#endif
74
 
#ifdef HAVE_ARPA_INET_H
75
 
# include <arpa/inet.h>
76
 
#endif
77
 
 
78
 
#include "srtp.h"
79
 
#include "rtp.h"
80
 
 
81
 
#ifdef RTPW_USE_WINSOCK2
82
 
# define DICT_FILE        "words.txt"
83
 
#else
84
 
# define DICT_FILE        "/usr/share/dict/words"
85
 
#endif
86
 
#define USEC_RATE        (5e5)
87
 
#define MAX_WORD_LEN     128
88
 
#define ADDR_IS_MULTICAST(a) IN_MULTICAST(htonl(a))
89
 
#define MAX_KEY_LEN      64
90
 
#define MASTER_KEY_LEN   30
91
 
 
92
 
 
93
 
#ifndef HAVE_USLEEP
94
 
# ifdef HAVE_WINDOWS_H
95
 
#  define usleep(us)    Sleep((us)/1000)
96
 
# else
97
 
#  define usleep(us)    sleep((us)/1000000)
98
 
# endif
99
 
#endif
100
 
 
101
 
 
102
 
/*
103
 
 * the function usage() prints an error message describing how this
104
 
 * program should be called, then calls exit()
105
 
 */
106
 
 
107
 
void
108
 
usage(char *prog_name);
109
 
 
110
 
/*
111
 
 * leave_group(...) de-registers from a multicast group
112
 
 */
113
 
 
114
 
void
115
 
leave_group(int sock, struct ip_mreq mreq, char *name);
116
 
 
117
 
 
118
 
/*
119
 
 * program_type distinguishes the [s]rtp sender and receiver cases
120
 
 */
121
 
 
122
 
typedef enum { sender, receiver, unknown } program_type;
123
 
 
124
 
int
125
 
main (int argc, char *argv[]) {
126
 
  char *dictfile = DICT_FILE;
127
 
  FILE *dict;
128
 
  char word[MAX_WORD_LEN];
129
 
  int sock, ret;
130
 
  struct in_addr rcvr_addr;
131
 
  struct sockaddr_in name;
132
 
  struct ip_mreq mreq;
133
 
#if BEW
134
 
  struct sockaddr_in local;
135
 
#endif
136
 
  program_type prog_type = unknown;
137
 
  sec_serv_t sec_servs = sec_serv_none;
138
 
  unsigned char ttl = 5;
139
 
  int c;
140
 
  char *input_key = NULL;
141
 
  char *address = NULL;
142
 
  char key[MAX_KEY_LEN];
143
 
  unsigned short port = 0;
144
 
  rtp_sender_t snd;
145
 
  srtp_policy_t policy;
146
 
  err_status_t status;
147
 
  int len;
148
 
  int do_list_mods = 0;
149
 
  uint32_t ssrc = 0xdeadbeef; /* ssrc value hardcoded for now */
150
 
#ifdef RTPW_USE_WINSOCK2
151
 
  WORD wVersionRequested = MAKEWORD(2, 0);
152
 
  WSADATA wsaData;
153
 
 
154
 
  ret = WSAStartup(wVersionRequested, &wsaData);
155
 
  if (ret != 0) {
156
 
    fprintf(stderr, "error: WSAStartup() failed: %d\n", ret);
157
 
    exit(1);
158
 
  }
159
 
#endif
160
 
 
161
 
  /* initialize srtp library */
162
 
  status = srtp_init();
163
 
  if (status) {
164
 
    printf("error: srtp initialization failed with error code %d\n", status);
165
 
    exit(1);
166
 
  }
167
 
 
168
 
  /* check args */
169
 
  while (1) {
170
 
    c = getopt_s(argc, argv, "k:rsaeld:");
171
 
    if (c == -1) {
172
 
      break;
173
 
    }
174
 
    switch (c) {
175
 
    case 'k':
176
 
      input_key = optarg_s;
177
 
      break;
178
 
    case 'e':
179
 
      sec_servs |= sec_serv_conf;
180
 
      break;
181
 
    case 'a':
182
 
      sec_servs |= sec_serv_auth;
183
 
      break;
184
 
    case 'r':
185
 
      prog_type = receiver;
186
 
      break;
187
 
    case 's':
188
 
      prog_type = sender;
189
 
      break;
190
 
    case 'd':
191
 
      status = crypto_kernel_set_debug_module(optarg_s, 1);
192
 
      if (status) {
193
 
        printf("error: set debug module (%s) failed\n", optarg_s);
194
 
        exit(1);
195
 
      }
196
 
      break;
197
 
    case 'l':
198
 
      do_list_mods = 1;
199
 
      break;
200
 
    default:
201
 
      usage(argv[0]);
202
 
    }
203
 
  }
204
 
 
205
 
  if (prog_type == unknown) {
206
 
    if (do_list_mods) {
207
 
      status = crypto_kernel_list_debug_modules();
208
 
      if (status) {
209
 
        printf("error: list of debug modules failed\n");
210
 
        exit(1);
211
 
      }
212
 
      return 0;
213
 
    } else {
214
 
      printf("error: neither sender [-s] nor receiver [-r] specified\n");
215
 
      usage(argv[0]);
216
 
    }
217
 
  }
218
 
 
219
 
  if ((sec_servs && !input_key) || (!sec_servs && input_key)) {
220
 
    /*
221
 
     * a key must be provided if and only if security services have
222
 
     * been requested
223
 
     */
224
 
    usage(argv[0]);
225
 
  }
226
 
 
227
 
  if (argc != optind_s + 2) {
228
 
    /* wrong number of arguments */
229
 
    usage(argv[0]);
230
 
  }
231
 
 
232
 
  /* get address from arg */
233
 
  address = argv[optind_s++];
234
 
 
235
 
  /* get port from arg */
236
 
  port = atoi(argv[optind_s++]);
237
 
 
238
 
  /* set address */
239
 
#ifdef HAVE_INET_ATON
240
 
  if (0 == inet_aton(address, &rcvr_addr)) {
241
 
    fprintf(stderr, "%s: cannot parse IP v4 address %s\n", argv[0], address);
242
 
    exit(1);
243
 
  }
244
 
  if (rcvr_addr.s_addr == INADDR_NONE) {
245
 
    fprintf(stderr, "%s: address error", argv[0]);
246
 
    exit(1);
247
 
  }
248
 
#else
249
 
  rcvr_addr.s_addr = inet_addr(address);
250
 
  if (0xffffffff == rcvr_addr.s_addr) {
251
 
    fprintf(stderr, "%s: cannot parse IP v4 address %s\n", argv[0], address);
252
 
    exit(1);
253
 
  }
254
 
#endif
255
 
 
256
 
  /* open socket */
257
 
  sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
258
 
  if (sock < 0) {
259
 
    int err;
260
 
#ifdef RTPW_USE_WINSOCK2
261
 
    err = WSAGetLastError();
262
 
#else
263
 
    err = errno;
264
 
#endif
265
 
    fprintf(stderr, "%s: couldn't open socket: %d\n", argv[0], err);
266
 
    exit(1);
267
 
  }
268
 
 
269
 
  name.sin_addr   = rcvr_addr;
270
 
  name.sin_family = PF_INET;
271
 
  name.sin_port   = htons(port);
272
 
 
273
 
  if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
274
 
    if (prog_type == sender) {
275
 
      ret = setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
276
 
                       sizeof(ttl));
277
 
      if (ret < 0) {
278
 
        fprintf(stderr, "%s: Failed to set TTL for multicast group", argv[0]);
279
 
        perror("");
280
 
        exit(1);
281
 
      }
282
 
    }
283
 
 
284
 
    mreq.imr_multiaddr.s_addr = rcvr_addr.s_addr;
285
 
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);
286
 
    ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void*)&mreq,
287
 
                     sizeof(mreq));
288
 
    if (ret < 0) {
289
 
      fprintf(stderr, "%s: Failed to join multicast group", argv[0]);
290
 
      perror("");
291
 
      exit(1);
292
 
    }
293
 
  }
294
 
 
295
 
  /* report security services selected on the command line */
296
 
  printf("security services: ");
297
 
  if (sec_servs & sec_serv_conf)
298
 
    printf("confidentiality ");
299
 
  if (sec_servs & sec_serv_auth)
300
 
    printf("message authentication");
301
 
  if (sec_servs == sec_serv_none)
302
 
    printf("none");
303
 
  printf("\n");
304
 
 
305
 
  /* set up the srtp policy and master key */
306
 
  if (sec_servs) {
307
 
    /*
308
 
     * create policy structure, using the default mechanisms but
309
 
     * with only the security services requested on the command line,
310
 
     * using the right SSRC value
311
 
     */
312
 
    switch (sec_servs) {
313
 
    case sec_serv_conf_and_auth:
314
 
      crypto_policy_set_rtp_default(&policy.rtp);
315
 
      crypto_policy_set_rtcp_default(&policy.rtcp);
316
 
      break;
317
 
    case sec_serv_conf:
318
 
      crypto_policy_set_aes_cm_128_null_auth(&policy.rtp);
319
 
      crypto_policy_set_rtcp_default(&policy.rtcp);
320
 
      break;
321
 
    case sec_serv_auth:
322
 
      crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp);
323
 
      crypto_policy_set_rtcp_default(&policy.rtcp);
324
 
      break;
325
 
    default:
326
 
      printf("error: unknown security service requested\n");
327
 
      return -1;
328
 
    }
329
 
    policy.ssrc.type  = ssrc_specific;
330
 
    policy.ssrc.value = ssrc;
331
 
    policy.key  = (uint8_t *) key;
332
 
    policy.next = NULL;
333
 
    policy.rtp.sec_serv = sec_servs;
334
 
    policy.rtcp.sec_serv = sec_serv_none;  /* we don't do RTCP anyway */
335
 
 
336
 
    /*
337
 
     * read key from hexadecimal on command line into an octet string
338
 
     */
339
 
    len = hex_string_to_octet_string(key, input_key, MASTER_KEY_LEN*2);
340
 
 
341
 
    /* check that hex string is the right length */
342
 
    if (len < MASTER_KEY_LEN*2) {
343
 
      fprintf(stderr,
344
 
              "error: too few digits in key/salt "
345
 
              "(should be %d hexadecimal digits, found %d)\n",
346
 
              MASTER_KEY_LEN*2, len);
347
 
      exit(1);
348
 
    }
349
 
    if (strlen(input_key) > MASTER_KEY_LEN*2) {
350
 
      fprintf(stderr,
351
 
              "error: too many digits in key/salt "
352
 
              "(should be %d hexadecimal digits, found %u)\n",
353
 
              MASTER_KEY_LEN*2, (unsigned)strlen(input_key));
354
 
      exit(1);
355
 
    }
356
 
 
357
 
    printf("set master key/salt to %s/", octet_string_hex_string(key, 16));
358
 
    printf("%s\n", octet_string_hex_string(key+16, 14));
359
 
 
360
 
  } else {
361
 
    /*
362
 
     * we're not providing security services, so set the policy to the
363
 
     * null policy
364
 
     *
365
 
     * Note that this policy does not conform to the SRTP
366
 
     * specification, since RTCP authentication is required.  However,
367
 
     * the effect of this policy is to turn off SRTP, so that this
368
 
     * application is now a vanilla-flavored RTP application.
369
 
     */
370
 
    policy.key                 = (uint8_t *)key;
371
 
    policy.ssrc.type           = ssrc_specific;
372
 
    policy.ssrc.value          = ssrc;
373
 
    policy.rtp.cipher_type     = NULL_CIPHER;
374
 
    policy.rtp.cipher_key_len  = 0;
375
 
    policy.rtp.auth_type       = NULL_AUTH;
376
 
    policy.rtp.auth_key_len    = 0;
377
 
    policy.rtp.auth_tag_len    = 0;
378
 
    policy.rtp.sec_serv        = sec_serv_none;
379
 
    policy.rtcp.cipher_type    = NULL_CIPHER;
380
 
    policy.rtcp.cipher_key_len = 0;
381
 
    policy.rtcp.auth_type      = NULL_AUTH;
382
 
    policy.rtcp.auth_key_len   = 0;
383
 
    policy.rtcp.auth_tag_len   = 0;
384
 
    policy.rtcp.sec_serv       = sec_serv_none;
385
 
    policy.next                = NULL;
386
 
  }
387
 
 
388
 
  if (prog_type == sender) {
389
 
 
390
 
#if BEW
391
 
    /* bind to local socket (to match crypto policy, if need be) */
392
 
    memset(&local, 0, sizeof(struct sockaddr_in));
393
 
    local.sin_addr.s_addr = htonl(INADDR_ANY);
394
 
    local.sin_port = htons(port);
395
 
    ret = bind(sock, (struct sockaddr *) &local, sizeof(struct sockaddr_in));
396
 
    if (ret < 0) {
397
 
      fprintf(stderr, "%s: bind failed\n", argv[0]);
398
 
      perror("");
399
 
      exit(1);
400
 
    }
401
 
#endif /* BEW */
402
 
 
403
 
    /* initialize sender's rtp and srtp contexts */
404
 
    snd = rtp_sender_alloc();
405
 
    if (snd == NULL) {
406
 
      fprintf(stderr, "error: malloc() failed\n");
407
 
      exit(1);
408
 
    }
409
 
    rtp_sender_init(snd, sock, name, ssrc);
410
 
    status = rtp_sender_init_srtp(snd, &policy);
411
 
    if (status) {
412
 
      fprintf(stderr,
413
 
              "error: srtp_create() failed with code %d\n",
414
 
              status);
415
 
      exit(1);
416
 
    }
417
 
 
418
 
    /* open dictionary */
419
 
    dict = fopen (dictfile, "r");
420
 
    if (dict == NULL) {
421
 
      fprintf(stderr, "%s: couldn't open file %s\n", argv[0], dictfile);
422
 
      if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
423
 
        leave_group(sock, mreq, argv[0]);
424
 
      }
425
 
      exit(1);
426
 
    }
427
 
 
428
 
    /* read words from dictionary, then send them off */
429
 
    while (fgets(word, MAX_WORD_LEN, dict) != NULL) {
430
 
      len = strlen(word) + 1;  /* plus one for null */
431
 
 
432
 
      if (len > MAX_WORD_LEN)
433
 
        printf("error: word %s too large to send\n", word);
434
 
      else {
435
 
        rtp_sendto(snd, word, len);
436
 
        printf("sending word: %s", word);
437
 
      }
438
 
      usleep(USEC_RATE);
439
 
    }
440
 
 
441
 
  } else  { /* prog_type == receiver */
442
 
    rtp_receiver_t rcvr;
443
 
 
444
 
    if (bind(sock, (struct sockaddr *)&name, sizeof(name)) < 0) {
445
 
      close(sock);
446
 
      fprintf(stderr, "%s: socket bind error\n", argv[0]);
447
 
      perror(NULL);
448
 
      if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
449
 
        leave_group(sock, mreq, argv[0]);
450
 
      }
451
 
      exit(1);
452
 
    }
453
 
 
454
 
    rcvr = rtp_receiver_alloc();
455
 
    if (rcvr == NULL) {
456
 
      fprintf(stderr, "error: malloc() failed\n");
457
 
      exit(1);
458
 
    }
459
 
    rtp_receiver_init(rcvr, sock, name, ssrc);
460
 
    status = rtp_receiver_init_srtp(rcvr, &policy);
461
 
    if (status) {
462
 
      fprintf(stderr,
463
 
              "error: srtp_create() failed with code %d\n",
464
 
              status);
465
 
      exit(1);
466
 
    }
467
 
 
468
 
    /* get next word and loop */
469
 
    while (1) {
470
 
      len = MAX_WORD_LEN;
471
 
      if (rtp_recvfrom(rcvr, word, &len) > -1)
472
 
        printf("\tword: %s", word);
473
 
    }
474
 
 
475
 
  }
476
 
 
477
 
  if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
478
 
    leave_group(sock, mreq, argv[0]);
479
 
  }
480
 
 
481
 
#ifdef RTPW_USE_WINSOCK2
482
 
  WSACleanup();
483
 
#endif
484
 
 
485
 
  return 0;
486
 
}
487
 
 
488
 
 
489
 
void
490
 
usage(char *string) {
491
 
 
492
 
  printf("usage: %s [-d <debug>]* [-k <key> [-a][-e]] "
493
 
         "[-s | -r] dest_ip dest_port\n"
494
 
         "or     %s -l\n"
495
 
         "where  -a use message authentication\n"
496
 
         "       -e use encryption\n"
497
 
         "       -k <key>  sets the srtp master key\n"
498
 
         "       -s act as rtp sender\n"
499
 
         "       -r act as rtp receiver\n"
500
 
         "       -l list debug modules\n"
501
 
         "       -d <debug> turn on debugging for module <debug>\n",
502
 
         string, string);
503
 
  exit(1);
504
 
 
505
 
}
506
 
 
507
 
 
508
 
void
509
 
leave_group(int sock, struct ip_mreq mreq, char *name) {
510
 
  int ret;
511
 
 
512
 
  ret = setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, (void*)&mreq,
513
 
                   sizeof(mreq));
514
 
  if (ret < 0) {
515
 
        fprintf(stderr, "%s: Failed to leave multicast group", name);
516
 
        perror("");
517
 
  }
518
 
}