Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No need to be root for pcapplay. #57

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/send_packets.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ typedef struct {
/* Used in send_packets thread */
struct sockaddr_storage to;
struct sockaddr_storage from;
int sock;
} play_args_t;

#ifdef __cplusplus
Expand Down
32 changes: 19 additions & 13 deletions src/call.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,26 +244,26 @@ uint16_t get_remote_port_media(const char *msg, int pattype)
*/
void call::get_remote_media_addr(char *msg)
{
uint16_t video_port, audio_port;
uint16_t audio_port = get_remote_port_media(msg, PAT_AUDIO);
uint16_t video_port = get_remote_port_media(msg, PAT_VIDEO);

if (media_ip_is_ipv6) {
struct in6_addr ip_media;
if (get_remote_ipv6_media(msg, &ip_media)) {
audio_port = get_remote_port_media(msg, PAT_AUDIO);
if (audio_port) {
/* We have audio in the SDP: set the to_audio addr */
(_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_flowinfo = 0;
(_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_scope_id = 0;
(_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_family = AF_INET6;
(_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_port = audio_port;
(_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_port = htons(audio_port);
(_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_addr = ip_media;
}
video_port = get_remote_port_media(msg, PAT_VIDEO);
if (video_port) {
/* We have video in the SDP: set the to_video addr */
(_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_flowinfo = 0;
(_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_scope_id = 0;
(_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_family = AF_INET6;
(_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_port = video_port;
(_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_port = htons(video_port);
(_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_addr = ip_media;
}
hasMediaInformation = 1;
Expand All @@ -272,23 +272,28 @@ void call::get_remote_media_addr(char *msg)
uint32_t ip_media;
ip_media = get_remote_ip_media(msg);
if (ip_media != INADDR_NONE) {
audio_port = get_remote_port_media(msg, PAT_AUDIO);
if (audio_port) {
/* We have audio in the SDP: set the to_audio addr */
(_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_family = AF_INET;
(_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_port = audio_port;
(_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_port = htons(audio_port);
(_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_addr.s_addr = ip_media;
}
video_port = get_remote_port_media(msg, PAT_VIDEO);
if (video_port) {
/* We have video in the SDP: set the to_video addr */
(_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_family = AF_INET;
(_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_port = video_port;
(_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_port = htons(video_port);
(_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_addr.s_addr = ip_media;
}
hasMediaInformation = 1;
}
}

if (audio_port) {
play_args_a.sock = media_socket;
}
if (video_port) {
play_args_v.sock = media_socket_video;
}
}

#endif
Expand Down Expand Up @@ -616,6 +621,7 @@ void call::init(scenario * call_scenario, struct sipp_socket *socket, struct soc
memset(&(play_args_v.to), 0, sizeof(struct sockaddr_storage));
memset(&(play_args_a.from), 0, sizeof(struct sockaddr_storage));
memset(&(play_args_v.from), 0, sizeof(struct sockaddr_storage));
play_args_a.sock = play_args_v.sock = -1;
hasMediaInformation = 0;
media_thread = 0;
#endif
Expand Down Expand Up @@ -2135,15 +2141,15 @@ char* call::createSendingMessage(SendingMessage *src, int P_index, char *msg_buf
}
if (strstr(begin, "audio")) {
if (media_ip_is_ipv6) {
(_RCAST(struct sockaddr_in6 *, &(play_args_a.from)))->sin6_port = port;
(_RCAST(struct sockaddr_in6 *, &(play_args_a.from)))->sin6_port = htons(port);
} else {
(_RCAST(struct sockaddr_in *, &(play_args_a.from)))->sin_port = port;
(_RCAST(struct sockaddr_in *, &(play_args_a.from)))->sin_port = htons(port);
}
} else if (strstr(begin, "video")) {
if (media_ip_is_ipv6) {
(_RCAST(struct sockaddr_in6 *, &(play_args_v.from)))->sin6_port = port;
(_RCAST(struct sockaddr_in6 *, &(play_args_v.from)))->sin6_port = htons(port);
} else {
(_RCAST(struct sockaddr_in *, &(play_args_v.from)))->sin_port = port;
(_RCAST(struct sockaddr_in *, &(play_args_v.from)))->sin_port = htons(port);
}
} else {
ERROR("media_port keyword with no audio or video on the current line (%s)", begin);
Expand Down
48 changes: 38 additions & 10 deletions src/prepare_pcap.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,9 @@
* made available by the platform, as we had no problems to get them on all supported platforms.
*/

typedef struct _ether_hdr {
char ether_dst[6];
char ether_src[6];
typedef struct _ether_type_hdr {
u_int16_t ether_type; /* we only need the type, so we can determine, if the next header is IPv4 or IPv6 */
} ether_hdr;
} ether_type_hdr;

typedef struct _ipv6_hdr {
char dontcare[6];
Expand Down Expand Up @@ -95,7 +93,8 @@ int prepare_pkts(char *file, pcap_pkts *pkts)
u_int16_t base = 0xffff;
u_long pktlen;
pcap_pkt *pkt_index;
ether_hdr *ethhdr;
size_t ether_type_offset;
ether_type_hdr *ethhdr;
struct iphdr *iphdr;
ipv6_hdr *ip6hdr;
struct udphdr *udphdr;
Expand All @@ -106,6 +105,19 @@ int prepare_pkts(char *file, pcap_pkts *pkts)
if (!pcap)
ERROR("Can't open PCAP file '%s'", file);

switch (pcap_datalink(pcap)) {
case DLT_EN10MB:
/* srcmac[6], dstmac[6], ethertype[2] */
ether_type_offset = 12;
break;
case DLT_LINUX_SLL:
/* some_stuff[14], ethertype[2] */
ether_type_offset = 14;
break;
default:
ERROR("Unsupported link-type %d", pcap_datalink(pcap));
}

#if HAVE_PCAP_NEXT_EX
while (pcap_next_ex (pcap, &pkthdr, (const u_char **) &pktdata) == 1) {
#else
Expand All @@ -118,10 +130,12 @@ int prepare_pkts(char *file, pcap_pkts *pkts)
ERROR("Can't allocate memory for pcap pkthdr");
while ((pktdata = (u_char *) pcap_next (pcap, pkthdr)) != NULL) {
#endif
ethhdr = (ether_hdr *)pktdata;
if (pkthdr->len != pkthdr->caplen)
ERROR("You've got truncated packets. Re-do dump with -s0");
ethhdr = (ether_type_hdr *)(pktdata + ether_type_offset);
if (ntohs(ethhdr->ether_type) != 0x0800 /* IPv4 */
&& ntohs(ethhdr->ether_type) != 0x86dd) { /* IPv6 */
fprintf(stderr, "Ignoring non IP{4,6} packet!\n");
WARNING("Ignoring non IP{4,6} packet!");
continue;
}
iphdr = (struct iphdr *)((char *)ethhdr + sizeof(*ethhdr));
Expand All @@ -130,14 +144,14 @@ int prepare_pkts(char *file, pcap_pkts *pkts)
pktlen = (u_long) pkthdr->len - sizeof(*ethhdr) - sizeof(*ip6hdr);
ip6hdr = (ipv6_hdr *)(void *) iphdr;
if (ip6hdr->nxt_header != IPPROTO_UDP) {
fprintf(stderr, "prepare_pcap.c: Ignoring non UDP packet!\n");
WARNING("prepare_pcap.c: Ignoring non UDP packet!");
continue;
}
udphdr = (struct udphdr *)((char *)ip6hdr + sizeof(*ip6hdr));
} else {
//ipv4
if (iphdr->protocol != IPPROTO_UDP) {
fprintf(stderr, "prepare_pcap.c: Ignoring non UDP packet!\n");
WARNING("prepare_pcap.c: Ignoring non UDP packet!");
continue;
}
#if defined(__DARWIN) || defined(__CYGWIN) || defined(__FreeBSD__)
Expand Down Expand Up @@ -193,9 +207,23 @@ int prepare_pkts(char *file, pcap_pkts *pkts)
pkts->max = pkts->pkts + n_pkts;
pkts->max_length = max_length;
pkts->base = base;
fprintf(stderr, "In pcap %s, npkts %d\nmax pkt length %ld\nbase port %d\n", file, n_pkts, max_length, base);
//fprintf(stderr, "In pcap %s, npkts %d\nmax pkt length %ld\nbase port %d\n", file, n_pkts, max_length, base);
pcap_close(pcap);

return 0;
}

/* TODO: right now we leak pkts when shutting down.
* But, we can't clean this up after send_packets, because it may get reused.
* Furthermore, there is a nasty memcpy that copies the pcap_pkts buffer for
* further use. That means that (a) this memory should stay alive until the
* end of the app and (b) it should not be freed multiple times. */
void free_pkts(pcap_pkts *pkts)
{
pcap_pkt *pkt_index = pkts->pkts;
while (pkt_index < pkts->max) {
free(pkt_index->data);
pkt_index++;
}
free(pkts->pkts);
}
34 changes: 15 additions & 19 deletions src/rtpstream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -727,11 +727,9 @@ int rtpstream_get_localport (int *rtpsocket, int *rtcpsocket)
}

if (media_ip_is_ipv6) {
(_RCAST(struct sockaddr_in6 *,&address))->sin6_port =
htons((short)port_number);
(_RCAST(struct sockaddr_in6 *,&address))->sin6_port = htons((unsigned short)port_number);
} else {
(_RCAST(struct sockaddr_in *,&address))->sin_port=
htons((short)port_number);
(_RCAST(struct sockaddr_in *,&address))->sin_port = htons((unsigned short)port_number);
}
if (bind(*rtpsocket,(sockaddr *)(void *)&address,
SOCK_ADDR_SIZE(&address)) == 0) {
Expand All @@ -758,11 +756,9 @@ int rtpstream_get_localport (int *rtpsocket, int *rtcpsocket)
if (*rtcpsocket!=-1) {
/* try to bind it to our preferred address */
if (media_ip_is_ipv6) {
(_RCAST(struct sockaddr_in6 *,&address))->sin6_port =
htons((short)port_number+1);
(_RCAST(struct sockaddr_in6 *,&address))->sin6_port = htons((unsigned short)port_number + 1);
} else {
(_RCAST(struct sockaddr_in *,&address))->sin_port=
htons((short)port_number+1);
(_RCAST(struct sockaddr_in *,&address))->sin_port = htons((unsigned short)port_number + 1);
}
if (bind(*rtcpsocket,(sockaddr *)(void *)&address,
SOCK_ADDR_SIZE(&address))) {
Expand Down Expand Up @@ -925,45 +921,45 @@ void rtpstream_set_remote (rtpstream_callinfo_t *callinfo, int ip_ver, char *ip_
/* Audio */
if (audio_port) {
if (media_ip_is_ipv6) {
(_RCAST(struct sockaddr_in6 *,&address))->sin6_port= htons((short)audio_port);
(_RCAST(struct sockaddr_in6 *,&address))->sin6_port = htons((unsigned short)audio_port);
} else {
(_RCAST(struct sockaddr_in *,&address))->sin_port= htons((short)audio_port);
(_RCAST(struct sockaddr_in *,&address))->sin_port = htons((unsigned short)audio_port);
}
memcpy (&(taskinfo->remote_audio_rtp_addr),&address,sizeof(address));

if (media_ip_is_ipv6) {
(_RCAST(struct sockaddr_in6 *,&address))->sin6_port= htons((short)audio_port+1);
(_RCAST(struct sockaddr_in6 *,&address))->sin6_port = htons((unsigned short)audio_port + 1);
} else {
(_RCAST(struct sockaddr_in *,&address))->sin_port= htons((short)audio_port+1);
(_RCAST(struct sockaddr_in *,&address))->sin_port = htons((unsigned short)audio_port + 1);
}
memcpy (&(taskinfo->remote_audio_rtcp_addr),&address,sizeof(address));

taskinfo->flags&= ~TI_NULL_AUDIOIP;
taskinfo->flags &= ~TI_NULL_AUDIOIP;
}

/* Video */
if (video_port) {
if (media_ip_is_ipv6) {
(_RCAST(struct sockaddr_in6 *,&address))->sin6_port= htons((short)video_port);
(_RCAST(struct sockaddr_in6 *,&address))->sin6_port = htons((unsigned short)video_port);
} else {
(_RCAST(struct sockaddr_in *,&address))->sin_port= htons((short)video_port);
(_RCAST(struct sockaddr_in *,&address))->sin_port = htons((unsigned short)video_port);
}
memcpy (&(taskinfo->remote_video_rtp_addr),&address,sizeof(address));

if (media_ip_is_ipv6) {
(_RCAST(struct sockaddr_in6 *,&address))->sin6_port= htons((short)video_port+1);
(_RCAST(struct sockaddr_in6 *,&address))->sin6_port = htons((unsigned short)video_port + 1);
} else {
(_RCAST(struct sockaddr_in *,&address))->sin_port= htons((short)video_port+1);
(_RCAST(struct sockaddr_in *,&address))->sin_port = htons((unsigned short)video_port + 1);
}
memcpy (&(taskinfo->remote_video_rtcp_addr),&address,sizeof(address));

taskinfo->flags&= ~TI_NULL_VIDEOIP;
taskinfo->flags &= ~TI_NULL_VIDEOIP;
}

/* ok, we are done with the shared memory objects. let go mutex */
pthread_mutex_unlock (&(taskinfo->mutex));

taskinfo->flags|= TI_RECONNECTSOCKET;
taskinfo->flags |= TI_RECONNECTSOCKET;

/* may want to start a playback (listen) task here if no task running? */
/* only makes sense if we decide to send 0-filled packets on idle */
Expand Down
Loading