16ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org/*
26ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * rtpw.c
36ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
46ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * rtp word sender/receiver
56ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
66ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * David A. McGrew
76ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * Cisco Systems, Inc.
86ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
96ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * This app is a simple RTP application intended only for testing
106ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * libsrtp.  It reads one word at a time from /usr/dict/words (or
116ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * whatever file is specified as DICT_FILE), and sends one word out
126ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * each USEC_RATE microseconds.  Secure RTP protections can be
136ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * applied.  See the usage() function for more details.
146ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
156ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org */
166ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
176ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org/*
186ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
196ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * Copyright (c) 2001-2006, Cisco Systems, Inc.
206ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * All rights reserved.
216ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
226ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * Redistribution and use in source and binary forms, with or without
236ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * modification, are permitted provided that the following conditions
246ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * are met:
256ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
266ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   Redistributions of source code must retain the above copyright
276ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   notice, this list of conditions and the following disclaimer.
286ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
296ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   Redistributions in binary form must reproduce the above
306ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   copyright notice, this list of conditions and the following
316ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   disclaimer in the documentation and/or other materials provided
326ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   with the distribution.
336ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
346ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   Neither the name of the Cisco Systems, Inc. nor the names of its
356ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   contributors may be used to endorse or promote products derived
366ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *   from this software without specific prior written permission.
376ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
386ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
396ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
406ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
416ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
426ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
436ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
446ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
456ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
466ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
476ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
486ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
496ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * OF THE POSSIBILITY OF SUCH DAMAGE.
506ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org *
516ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org */
526ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
536ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
546ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#include "datatypes.h"
556ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#include "getopt_s.h"       /* for local getopt()  */
566ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
576ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#include <stdio.h>          /* for printf, fprintf */
586ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#include <stdlib.h>         /* for atoi()          */
596ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#include <errno.h>
606ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#include <signal.h>         /* for signal()        */
616ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
626ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#include <string.h>         /* for strncpy()       */
636ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#include <time.h>	    /* for usleep()        */
646ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
656ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#ifdef HAVE_UNISTD_H
666ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#include <unistd.h>         /* for close()         */
676ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#endif
686ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#ifdef HAVE_SYS_SOCKET_H
696ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org# include <sys/socket.h>
706ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#endif
716ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#ifdef HAVE_NETINET_IN_H
726ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org# include <netinet/in.h>
736ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#elif defined HAVE_WINSOCK2_H
746ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org# include <winsock2.h>
756ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org# include <ws2tcpip.h>
766ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org# define RTPW_USE_WINSOCK2	1
776ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#endif
786ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#ifdef HAVE_ARPA_INET_H
796ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org# include <arpa/inet.h>
806ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#endif
816ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
826ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#include "srtp.h"
836ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#include "rtp.h"
846ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
856ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#ifdef RTPW_USE_WINSOCK2
866ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org# define DICT_FILE        "words.txt"
876ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#else
886ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org# define DICT_FILE        "/usr/share/dict/words"
896ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#endif
906ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#define USEC_RATE        (5e5)
916ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#define MAX_WORD_LEN     128
926ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#define ADDR_IS_MULTICAST(a) IN_MULTICAST(htonl(a))
936ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#define MAX_KEY_LEN      64
946ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#define MASTER_KEY_LEN   30
956ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
966ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
976ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#ifndef HAVE_USLEEP
986ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org# ifdef HAVE_WINDOWS_H
996ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#  define usleep(us)	Sleep((us)/1000)
1006ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org# else
1016ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#  define usleep(us)	sleep((us)/1000000)
1026ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org# endif
1036ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#endif
1046ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1056ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1066ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org/*
1076ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * the function usage() prints an error message describing how this
1086ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * program should be called, then calls exit()
1096ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org */
1106ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1116ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgvoid
1126ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgusage(char *prog_name);
1136ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1146ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org/*
1156ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * leave_group(...) de-registers from a multicast group
1166ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org */
1176ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1186ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgvoid
1196ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgleave_group(int sock, struct ip_mreq mreq, char *name);
1206ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1216ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1226ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org/*
1236ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * setup_signal_handler() sets up a signal handler to trigger
1246ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * cleanups after an interrupt
1256ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org */
1266ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgint setup_signal_handler(char* name);
1276ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1286ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org/*
1296ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * handle_signal(...) handles interrupt signal to trigger cleanups
1306ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org */
1316ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1326ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgvolatile int interrupted = 0;
1336ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1346ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org/*
1356ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org * program_type distinguishes the [s]rtp sender and receiver cases
1366ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org */
1376ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1386ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgtypedef enum { sender, receiver, unknown } program_type;
1396ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1406ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgint
1416ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgmain (int argc, char *argv[]) {
1426ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  char *dictfile = DICT_FILE;
1436ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  FILE *dict;
1446ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  char word[MAX_WORD_LEN];
1456ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  int sock, ret;
1466ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  struct in_addr rcvr_addr;
1476ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  struct sockaddr_in name;
1486ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  struct ip_mreq mreq;
1496ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#if BEW
1506ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  struct sockaddr_in local;
1516ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#endif
1526ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  program_type prog_type = unknown;
1536ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  sec_serv_t sec_servs = sec_serv_none;
1546ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  unsigned char ttl = 5;
1556ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  int c;
1566ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  char *input_key = NULL;
1576ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  char *address = NULL;
1586ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  char key[MAX_KEY_LEN];
1596ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  unsigned short port = 0;
1606ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  rtp_sender_t snd;
1616ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  srtp_policy_t policy;
1626ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  err_status_t status;
1636ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  int len;
1646ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  int do_list_mods = 0;
1656ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  uint32_t ssrc = 0xdeadbeef; /* ssrc value hardcoded for now */
1666ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#ifdef RTPW_USE_WINSOCK2
1676ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  WORD wVersionRequested = MAKEWORD(2, 0);
1686ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  WSADATA wsaData;
1696ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1706ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  ret = WSAStartup(wVersionRequested, &wsaData);
1716ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (ret != 0) {
1726ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    fprintf(stderr, "error: WSAStartup() failed: %d\n", ret);
1736ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    exit(1);
1746ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
1756ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#endif
1766ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1776ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (setup_signal_handler(argv[0]) != 0) {
1786ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    exit(1);
1796ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
1806ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1816ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* initialize srtp library */
1826ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  status = srtp_init();
1836ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (status) {
1846ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    printf("error: srtp initialization failed with error code %d\n", status);
1856ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    exit(1);
1866ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
1876ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
1886ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* check args */
1896ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  while (1) {
1906ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    c = getopt_s(argc, argv, "k:rsaeld:");
1916ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (c == -1) {
1926ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      break;
1936ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
1946ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    switch (c) {
1956ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    case 'k':
1966ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      input_key = optarg_s;
1976ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      break;
1986ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    case 'e':
1996ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      sec_servs |= sec_serv_conf;
2006ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      break;
2016ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    case 'a':
2026ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      sec_servs |= sec_serv_auth;
2036ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      break;
2046ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    case 'r':
2056ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      prog_type = receiver;
2066ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      break;
2076ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    case 's':
2086ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      prog_type = sender;
2096ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      break;
2106ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    case 'd':
2116ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      status = crypto_kernel_set_debug_module(optarg_s, 1);
2126ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      if (status) {
2136ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org        printf("error: set debug module (%s) failed\n", optarg_s);
2146ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org        exit(1);
2156ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      }
2166ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      break;
2176ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    case 'l':
2186ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      do_list_mods = 1;
2196ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      break;
2206ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    default:
2216ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      usage(argv[0]);
2226ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
2236ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
2246ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2256ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (prog_type == unknown) {
2266ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (do_list_mods) {
2276ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      status = crypto_kernel_list_debug_modules();
2286ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      if (status) {
2296ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	printf("error: list of debug modules failed\n");
2306ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	exit(1);
2316ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      }
2326ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      return 0;
2336ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    } else {
2346ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      printf("error: neither sender [-s] nor receiver [-r] specified\n");
2356ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      usage(argv[0]);
2366ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
2376ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
2386ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2396ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if ((sec_servs && !input_key) || (!sec_servs && input_key)) {
2406ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    /*
2416ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     * a key must be provided if and only if security services have
2426ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     * been requested
2436ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     */
2446ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    usage(argv[0]);
2456ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
2466ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2476ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (argc != optind_s + 2) {
2486ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    /* wrong number of arguments */
2496ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    usage(argv[0]);
2506ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
2516ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2526ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* get address from arg */
2536ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  address = argv[optind_s++];
2546ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2556ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* get port from arg */
2566ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  port = atoi(argv[optind_s++]);
2576ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2586ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* set address */
2596ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#ifdef HAVE_INET_ATON
2606ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (0 == inet_aton(address, &rcvr_addr)) {
2616ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    fprintf(stderr, "%s: cannot parse IP v4 address %s\n", argv[0], address);
2626ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    exit(1);
2636ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
2646ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (rcvr_addr.s_addr == INADDR_NONE) {
2656ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    fprintf(stderr, "%s: address error", argv[0]);
2666ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    exit(1);
2676ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
2686ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#else
2696ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  rcvr_addr.s_addr = inet_addr(address);
2706ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (0xffffffff == rcvr_addr.s_addr) {
2716ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    fprintf(stderr, "%s: cannot parse IP v4 address %s\n", argv[0], address);
2726ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    exit(1);
2736ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
2746ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#endif
2756ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2766ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* open socket */
2776ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
2786ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (sock < 0) {
2796ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    int err;
2806ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#ifdef RTPW_USE_WINSOCK2
2816ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    err = WSAGetLastError();
2826ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#else
2836ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    err = errno;
2846ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#endif
2856ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    fprintf(stderr, "%s: couldn't open socket: %d\n", argv[0], err);
2866ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org   exit(1);
2876ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
2886ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2896ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  name.sin_addr   = rcvr_addr;
2906ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  name.sin_family = PF_INET;
2916ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  name.sin_port   = htons(port);
2926ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
2936ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
2946ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (prog_type == sender) {
2956ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      ret = setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
2966ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  	               sizeof(ttl));
2976ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      if (ret < 0) {
2986ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	fprintf(stderr, "%s: Failed to set TTL for multicast group", argv[0]);
2996ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	perror("");
3006ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	exit(1);
3016ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      }
3026ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
3036ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3046ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    mreq.imr_multiaddr.s_addr = rcvr_addr.s_addr;
3056ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    mreq.imr_interface.s_addr = htonl(INADDR_ANY);
3066ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void*)&mreq,
3076ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org		     sizeof(mreq));
3086ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (ret < 0) {
3096ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      fprintf(stderr, "%s: Failed to join multicast group", argv[0]);
3106ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      perror("");
3116ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      exit(1);
3126ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
3136ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
3146ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3156ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* report security services selected on the command line */
3166ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  printf("security services: ");
3176ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (sec_servs & sec_serv_conf)
3186ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    printf("confidentiality ");
3196ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (sec_servs & sec_serv_auth)
3206ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    printf("message authentication");
3216ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (sec_servs == sec_serv_none)
3226ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    printf("none");
3236ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  printf("\n");
3246ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3256ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* set up the srtp policy and master key */
3266ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (sec_servs) {
3276ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    /*
3286ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     * create policy structure, using the default mechanisms but
3296ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     * with only the security services requested on the command line,
3306ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     * using the right SSRC value
3316ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     */
3326ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    switch (sec_servs) {
3336ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    case sec_serv_conf_and_auth:
3346ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      crypto_policy_set_rtp_default(&policy.rtp);
3356ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      crypto_policy_set_rtcp_default(&policy.rtcp);
3366ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      break;
3376ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    case sec_serv_conf:
3386ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      crypto_policy_set_aes_cm_128_null_auth(&policy.rtp);
3396ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      crypto_policy_set_rtcp_default(&policy.rtcp);
3406ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      break;
3416ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    case sec_serv_auth:
3426ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp);
3436ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      crypto_policy_set_rtcp_default(&policy.rtcp);
3446ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      break;
3456ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    default:
3466ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      printf("error: unknown security service requested\n");
3476ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      return -1;
3486ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
3496ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.ssrc.type  = ssrc_specific;
3506ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.ssrc.value = ssrc;
3516ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.key  = (uint8_t *) key;
3526ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.ekt  = NULL;
3536ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.next = NULL;
3546ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.window_size = 128;
3556ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.allow_repeat_tx = 0;
3566ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.rtp.sec_serv = sec_servs;
3576ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.rtcp.sec_serv = sec_serv_none;  /* we don't do RTCP anyway */
3586ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3596ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    /*
3606ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     * read key from hexadecimal on command line into an octet string
3616ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     */
3626ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    len = hex_string_to_octet_string(key, input_key, MASTER_KEY_LEN*2);
3636ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3646ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    /* check that hex string is the right length */
3656ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (len < MASTER_KEY_LEN*2) {
3666ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      fprintf(stderr,
3676ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	      "error: too few digits in key/salt "
3686ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	      "(should be %d hexadecimal digits, found %d)\n",
3696ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	      MASTER_KEY_LEN*2, len);
3706ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      exit(1);
3716ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
3726ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (strlen(input_key) > MASTER_KEY_LEN*2) {
3736ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      fprintf(stderr,
3746ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	      "error: too many digits in key/salt "
3756ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	      "(should be %d hexadecimal digits, found %u)\n",
3766ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	      MASTER_KEY_LEN*2, (unsigned)strlen(input_key));
3776ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      exit(1);
3786ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
3796ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3806ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    printf("set master key/salt to %s/", octet_string_hex_string(key, 16));
3816ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    printf("%s\n", octet_string_hex_string(key+16, 14));
3826ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
3836ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  } else {
3846ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    /*
3856ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     * we're not providing security services, so set the policy to the
3866ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     * null policy
3876ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     *
3886ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     * Note that this policy does not conform to the SRTP
3896ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     * specification, since RTCP authentication is required.  However,
3906ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     * the effect of this policy is to turn off SRTP, so that this
3916ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     * application is now a vanilla-flavored RTP application.
3926ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     */
3936ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.key                 = (uint8_t *)key;
3946ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.ssrc.type           = ssrc_specific;
3956ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.ssrc.value          = ssrc;
3966ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.rtp.cipher_type     = NULL_CIPHER;
3976ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.rtp.cipher_key_len  = 0;
3986ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.rtp.auth_type       = NULL_AUTH;
3996ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.rtp.auth_key_len    = 0;
4006ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.rtp.auth_tag_len    = 0;
4016ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.rtp.sec_serv        = sec_serv_none;
4026ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.rtcp.cipher_type    = NULL_CIPHER;
4036ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.rtcp.cipher_key_len = 0;
4046ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.rtcp.auth_type      = NULL_AUTH;
4056ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.rtcp.auth_key_len   = 0;
4066ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.rtcp.auth_tag_len   = 0;
4076ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.rtcp.sec_serv       = sec_serv_none;
4086ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.window_size         = 0;
4096ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.allow_repeat_tx     = 0;
4106ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.ekt                 = NULL;
4116ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    policy.next                = NULL;
4126ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
4136ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4146ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (prog_type == sender) {
4156ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4166ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#if BEW
4176ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    /* bind to local socket (to match crypto policy, if need be) */
4186ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    memset(&local, 0, sizeof(struct sockaddr_in));
4196ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    local.sin_addr.s_addr = htonl(INADDR_ANY);
4206ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    local.sin_port = htons(port);
4216ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    ret = bind(sock, (struct sockaddr *) &local, sizeof(struct sockaddr_in));
4226ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (ret < 0) {
4236ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      fprintf(stderr, "%s: bind failed\n", argv[0]);
4246ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      perror("");
4256ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      exit(1);
4266ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
4276ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#endif /* BEW */
4286ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4296ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    /* initialize sender's rtp and srtp contexts */
4306ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    snd = rtp_sender_alloc();
4316ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (snd == NULL) {
4326ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      fprintf(stderr, "error: malloc() failed\n");
4336ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      exit(1);
4346ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
4356ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    rtp_sender_init(snd, sock, name, ssrc);
4366ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    status = rtp_sender_init_srtp(snd, &policy);
4376ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (status) {
4386ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      fprintf(stderr,
4396ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	      "error: srtp_create() failed with code %d\n",
4406ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	      status);
4416ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      exit(1);
4426ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
4436ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4446ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    /* open dictionary */
4456ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    dict = fopen (dictfile, "r");
4466ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (dict == NULL) {
4476ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      fprintf(stderr, "%s: couldn't open file %s\n", argv[0], dictfile);
4486ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
4496ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  	leave_group(sock, mreq, argv[0]);
4506ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      }
4516ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      exit(1);
4526ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
4536ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4546ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    /* read words from dictionary, then send them off */
4556ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    while (!interrupted && fgets(word, MAX_WORD_LEN, dict) != NULL) {
4566ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      len = strlen(word) + 1;  /* plus one for null */
4576ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4586ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      if (len > MAX_WORD_LEN)
4596ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	printf("error: word %s too large to send\n", word);
4606ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      else {
4616ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	rtp_sendto(snd, word, len);
4626ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org        printf("sending word: %s", word);
4636ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      }
4646ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      usleep(USEC_RATE);
4656ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
4666ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4676ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    rtp_sender_deinit_srtp(snd);
4686ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    rtp_sender_dealloc(snd);
4696ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4706ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    fclose(dict);
4716ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  } else  { /* prog_type == receiver */
4726ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    rtp_receiver_t rcvr;
4736ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4746ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (bind(sock, (struct sockaddr *)&name, sizeof(name)) < 0) {
4756ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      close(sock);
4766ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      fprintf(stderr, "%s: socket bind error\n", argv[0]);
4776ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      perror(NULL);
4786ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
4796ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    	leave_group(sock, mreq, argv[0]);
4806ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      }
4816ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      exit(1);
4826ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
4836ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4846ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    rcvr = rtp_receiver_alloc();
4856ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (rcvr == NULL) {
4866ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      fprintf(stderr, "error: malloc() failed\n");
4876ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      exit(1);
4886ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
4896ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    rtp_receiver_init(rcvr, sock, name, ssrc);
4906ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    status = rtp_receiver_init_srtp(rcvr, &policy);
4916ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    if (status) {
4926ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      fprintf(stderr,
4936ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	      "error: srtp_create() failed with code %d\n",
4946ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	      status);
4956ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      exit(1);
4966ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
4976ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
4986ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    /* get next word and loop */
4996ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    while (!interrupted) {
5006ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      len = MAX_WORD_LEN;
5016ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org      if (rtp_recvfrom(rcvr, word, &len) > -1)
5026ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	printf("\tword: %s\n", word);
5036ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    }
5046ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5056ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    rtp_receiver_deinit_srtp(rcvr);
5066ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    rtp_receiver_dealloc(rcvr);
5076ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
5086ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5096ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
5106ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    leave_group(sock, mreq, argv[0]);
5116ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
5126ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5136ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#ifdef RTPW_USE_WINSOCK2
5146ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  ret = closesocket(sock);
5156ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#else
5166ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  ret = close(sock);
5176ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#endif
5186ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (ret < 0) {
5196ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    fprintf(stderr, "%s: Failed to close socket", argv[0]);
5206ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    perror("");
5216ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
5226ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5236ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  status = srtp_shutdown();
5246ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (status) {
5256ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    printf("error: srtp shutdown failed with error code %d\n", status);
5266ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    exit(1);
5276ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
5286ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5296ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#ifdef RTPW_USE_WINSOCK2
5306ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  WSACleanup();
5316ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#endif
5326ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5336ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  return 0;
5346ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
5356ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5366ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5376ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgvoid
5386ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgusage(char *string) {
5396ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5406ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  printf("usage: %s [-d <debug>]* [-k <key> [-a][-e]] "
5416ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	 "[-s | -r] dest_ip dest_port\n"
5426ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	 "or     %s -l\n"
5436ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	 "where  -a use message authentication\n"
5446ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	 "       -e use encryption\n"
5456ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	 "       -k <key>  sets the srtp master key\n"
5466ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	 "       -s act as rtp sender\n"
5476ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	 "       -r act as rtp receiver\n"
5486ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	 "       -l list debug modules\n"
5496ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	 "       -d <debug> turn on debugging for module <debug>\n",
5506ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	 string, string);
5516ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  exit(1);
5526ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5536ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
5546ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5556ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5566ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgvoid
5576ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgleave_group(int sock, struct ip_mreq mreq, char *name) {
5586ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  int ret;
5596ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5606ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  ret = setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, (void*)&mreq,
5616ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org		   sizeof(mreq));
5626ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (ret < 0) {
5636ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	fprintf(stderr, "%s: Failed to leave multicast group", name);
5646ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org	perror("");
5656ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
5666ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
5676ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5686ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgvoid handle_signal(int signum)
5696ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org{
5706ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  interrupted = 1;
5716ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* Reset handler explicitly, in case we don't have sigaction() (and signal()
5726ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org     has BSD semantics), or we don't have SA_RESETHAND */
5736ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  signal(signum, SIG_DFL);
5746ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
5756ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5766ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.orgint setup_signal_handler(char* name)
5776ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org{
5786ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#if HAVE_SIGACTION
5796ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  struct sigaction act;
5806ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  memset(&act, 0, sizeof(act));
5816ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5826ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  act.sa_handler = handle_signal;
5836ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  sigemptyset(&act.sa_mask);
5846ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#if defined(SA_RESETHAND)
5856ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  act.sa_flags = SA_RESETHAND;
5866ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#else
5876ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  act.sa_flags = 0;
5886ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#endif
5896ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  /* Note that we're not setting SA_RESTART; we want recvfrom to return
5906ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org   * EINTR when we signal the receiver. */
5916ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org
5926ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (sigaction(SIGTERM, &act, NULL) != 0) {
5936ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    fprintf(stderr, "%s: error setting up signal handler", name);
5946ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    perror("");
5956ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return -1;
5966ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
5976ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#else
5986ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  if (signal(SIGTERM, handle_signal) == SIG_ERR) {
5996ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    fprintf(stderr, "%s: error setting up signal handler", name);
6006ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    perror("");
6016ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org    return -1;
6026ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  }
6036ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org#endif
6046ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org  return 0;
6056ed0ee98e1c3d29a0ef79996f7d1abf174f39besergeyu@chromium.org}
606